001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018
019package org.apache.commons.codec.net;
020
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertFalse;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertTrue;
025import static org.junit.Assert.fail;
026
027import java.nio.charset.UnsupportedCharsetException;
028
029import org.apache.commons.codec.CharEncoding;
030import org.apache.commons.codec.DecoderException;
031import org.apache.commons.codec.EncoderException;
032import org.junit.Test;
033
034/**
035 * Quoted-printable codec test cases
036 *
037 * @version $Id: QCodecTest.html 891688 2013-12-24 20:49:46Z ggregory $
038 */
039public class QCodecTest {
040
041    static final int SWISS_GERMAN_STUFF_UNICODE [] = {
042        0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
043    };
044
045    static final int RUSSIAN_STUFF_UNICODE [] = {
046        0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
047        0x432, 0x435, 0x442
048    };
049
050    private String constructString(final int [] unicodeChars) {
051        final StringBuilder buffer = new StringBuilder();
052        if (unicodeChars != null) {
053            for (final int unicodeChar : unicodeChars) {
054                buffer.append((char)unicodeChar);
055            }
056        }
057        return buffer.toString();
058    }
059
060    @Test
061    public void testNullInput() throws Exception {
062        final QCodec qcodec = new QCodec();
063        assertNull(qcodec.doDecoding(null));
064        assertNull(qcodec.doEncoding(null));
065    }
066
067    @Test
068    public void testUTF8RoundTrip() throws Exception {
069
070        final String ru_msg = constructString(RUSSIAN_STUFF_UNICODE);
071        final String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE);
072
073        final QCodec qcodec = new QCodec(CharEncoding.UTF_8);
074
075        assertEquals(
076            "=?UTF-8?Q?=D0=92=D1=81=D0=B5=D0=BC=5F=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D1=82?=",
077        qcodec.encode(ru_msg)
078        );
079        assertEquals("=?UTF-8?Q?Gr=C3=BCezi=5Fz=C3=A4m=C3=A4?=", qcodec.encode(ch_msg));
080
081        assertEquals(ru_msg, qcodec.decode(qcodec.encode(ru_msg)));
082        assertEquals(ch_msg, qcodec.decode(qcodec.encode(ch_msg)));
083    }
084
085
086    @Test
087    public void testBasicEncodeDecode() throws Exception {
088        final QCodec qcodec = new QCodec();
089        final String plain = "= Hello there =\r\n";
090        final String encoded = qcodec.encode(plain);
091        assertEquals("Basic Q encoding test",
092            "=?UTF-8?Q?=3D Hello there =3D=0D=0A?=", encoded);
093        assertEquals("Basic Q decoding test",
094            plain, qcodec.decode(encoded));
095    }
096
097    @Test
098    public void testUnsafeEncodeDecode() throws Exception {
099        final QCodec qcodec = new QCodec();
100        final String plain = "?_=\r\n";
101        final String encoded = qcodec.encode(plain);
102        assertEquals("Unsafe chars Q encoding test",
103            "=?UTF-8?Q?=3F=5F=3D=0D=0A?=", encoded);
104        assertEquals("Unsafe chars Q decoding test",
105            plain, qcodec.decode(encoded));
106    }
107
108    @Test
109    public void testEncodeDecodeNull() throws Exception {
110        final QCodec qcodec = new QCodec();
111        assertNull("Null string Q encoding test",
112            qcodec.encode((String)null));
113        assertNull("Null string Q decoding test",
114            qcodec.decode((String)null));
115    }
116
117    @Test
118    public void testEncodeStringWithNull() throws Exception {
119        final QCodec qcodec = new QCodec();
120        final String test = null;
121        final String result = qcodec.encode( test, "charset" );
122        assertEquals("Result should be null", null, result);
123    }
124
125    @Test
126    public void testDecodeStringWithNull() throws Exception {
127        final QCodec qcodec = new QCodec();
128        final String test = null;
129        final String result = qcodec.decode( test );
130        assertEquals("Result should be null", null, result);
131    }
132
133
134    @Test
135    public void testEncodeObjects() throws Exception {
136        final QCodec qcodec = new QCodec();
137        final String plain = "1+1 = 2";
138        final String encoded = (String) qcodec.encode((Object) plain);
139        assertEquals("Basic Q encoding test",
140            "=?UTF-8?Q?1+1 =3D 2?=", encoded);
141
142        final Object result = qcodec.encode((Object) null);
143        assertEquals( "Encoding a null Object should return null", null, result);
144
145        try {
146            final Object dObj = new Double(3.0);
147            qcodec.encode( dObj );
148            fail( "Trying to url encode a Double object should cause an exception.");
149        } catch (final EncoderException ee) {
150            // Exception expected, test segment passes.
151        }
152    }
153
154
155    @Test(expected=UnsupportedCharsetException.class)
156    public void testInvalidEncoding() {
157        new QCodec("NONSENSE");
158    }
159
160    @Test
161    public void testDecodeObjects() throws Exception {
162        final QCodec qcodec = new QCodec();
163        final String decoded = "=?UTF-8?Q?1+1 =3D 2?=";
164        final String plain = (String) qcodec.decode((Object) decoded);
165        assertEquals("Basic Q decoding test",
166            "1+1 = 2", plain);
167
168        final Object result = qcodec.decode((Object) null);
169        assertEquals( "Decoding a null Object should return null", null, result);
170
171        try {
172            final Object dObj = new Double(3.0);
173            qcodec.decode( dObj );
174            fail( "Trying to url encode a Double object should cause an exception.");
175        } catch (final DecoderException ee) {
176            // Exception expected, test segment passes.
177        }
178    }
179
180
181    @Test
182    public void testEncodeDecodeBlanks() throws Exception {
183        final String plain = "Mind those pesky blanks";
184        final String encoded1 = "=?UTF-8?Q?Mind those pesky blanks?=";
185        final String encoded2 = "=?UTF-8?Q?Mind_those_pesky_blanks?=";
186        final QCodec qcodec = new QCodec();
187        qcodec.setEncodeBlanks(false);
188        String s = qcodec.encode(plain);
189        assertEquals("Blanks encoding with the Q codec test", encoded1, s);
190        qcodec.setEncodeBlanks(true);
191        s = qcodec.encode(plain);
192        assertEquals("Blanks encoding with the Q codec test", encoded2, s);
193        s = qcodec.decode(encoded1);
194        assertEquals("Blanks decoding with the Q codec test", plain, s);
195        s = qcodec.decode(encoded2);
196        assertEquals("Blanks decoding with the Q codec test", plain, s);
197    }
198
199
200    @Test
201    public void testLetUsMakeCloverHappy() throws Exception {
202        final QCodec qcodec = new QCodec();
203        qcodec.setEncodeBlanks(true);
204        assertTrue(qcodec.isEncodeBlanks());
205        qcodec.setEncodeBlanks(false);
206        assertFalse(qcodec.isEncodeBlanks());
207    }
208
209}