1   /* ====================================================================
2    * Copyright (c) 2006 J.T. Beetstra
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining 
5    * a copy of this software and associated documentation files (the 
6    * "Software"), to deal in the Software without restriction, including 
7    * without limitation the rights to use, copy, modify, merge, publish, 
8    * distribute, sublicense, and/or sell copies of the Software, and to 
9    * permit persons to whom the Software is furnished to do so, subject to 
10   * the following conditions:
11   *
12   * The above copyright notice and this permission notice shall be 
13   * included in all copies or substantial portions of the Software.
14   *
15   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
16   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
17   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
18   * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
19   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
20   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
21   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22   * ====================================================================
23   */
24  package com.beetstra.jutf7;
25  
26  import java.io.UnsupportedEncodingException;
27  import java.nio.ByteBuffer;
28  import java.nio.CharBuffer;
29  import java.nio.charset.Charset;
30  import java.nio.charset.CharsetDecoder;
31  import java.nio.charset.CharsetEncoder;
32  import java.nio.charset.CoderResult;
33  
34  public class ModifiedUTF7Test extends CharsetTest {
35  	protected void setUp() throws Exception {
36  		tested = new ModifiedUTF7Charset("X-MODIFIED-UTF-7", new String[] {});
37  	}
38  
39  	public void testContains() {
40  		assertTrue(tested.contains(Charset.forName("US-ASCII")));
41  		assertTrue(tested.contains(Charset.forName("ISO-8859-1")));
42  		assertTrue(tested.contains(Charset.forName("UTF-8")));
43  		assertTrue(tested.contains(Charset.forName("UTF-16")));
44  		assertTrue(tested.contains(Charset.forName("UTF-16LE")));
45  		assertTrue(tested.contains(Charset.forName("UTF-16BE")));
46  	}
47  
48  	public void testEmpty() throws Exception {
49  		String string = "";
50  		assertEquals(string, decode(string));
51  		assertEquals(string, encode(string));
52  	}
53  
54  	public void testDecodeSimple() throws Exception {
55  		assertEquals("abcdefghijklmnopqrstuvwxyz", decode("abcdefghijklmnopqrstuvwxyz"));
56  		String directly = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?\r\n";
57  		assertEquals(directly, decode(directly));
58  		String optional = "!\"#$%*;<=>@[]^_'{|}";
59  		assertEquals(optional, decode(optional));
60  		String nonUTF7 = "+\\~";
61  		assertEquals(nonUTF7, decode(nonUTF7));
62  	}
63  
64  	public void testDecodeComplex() throws Exception {
65  		assertEquals("A\u2262\u0391.", decode("A&ImIDkQ-."));
66  	}
67  
68  	public void testDecodeLong() throws Exception {
69  		assertEquals("€áéúíóýäëïöüÿ", decode("&IKwA4QDpAPoA7QDzAP0A5ADrAO8A9gD8AP8-"));
70  	}
71  
72  	public void testDecodeLimitedOutput() throws Exception {
73  		CharsetDecoder decoder = tested.newDecoder();
74  		ByteBuffer in = CharsetTestUtil.wrap("A&ImIDkQ-.");
75  		CharBuffer out = CharBuffer.allocate(4);
76  		assertEquals(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
77  		out.flip();
78  		assertEquals("A\u2262\u0391.", out.toString());
79  	}
80  
81  	public void testDecodePerfectSized() throws Exception {
82  		assertEquals("€áé", decode("&IKwA4QDp-"));
83  	}
84  
85  	public void testDecodeShiftSequence() throws Exception {
86  		assertEquals("&", decode("&-"));
87  		assertEquals("&-", decode("&--"));
88  		assertEquals("&&", decode("&-&-"));
89  	}
90  
91  	public void testDecodeNoClosing() throws Exception {
92  		ByteBuffer in = CharsetTestUtil.wrap("&");
93  		CharBuffer out = CharBuffer.allocate(1024);
94  		final CharsetDecoder decoder = tested.newDecoder();
95  		CoderResult result = decoder.decode(in, out, true);
96  		assertEquals(CoderResult.UNDERFLOW, result);
97  		result = decoder.flush(out);
98  		assertEquals(CoderResult.malformedForLength(1), result);
99  		assertEquals(1, in.position());
100 		assertEquals(0, out.position());
101 		in = CharsetTestUtil.wrap("&AO");
102 		out = CharBuffer.allocate(1024);
103 		decoder.reset();
104 		result = decoder.decode(in, out, true);
105 		assertEquals(CoderResult.UNDERFLOW, result);
106 		result = decoder.flush(out);
107 		assertEquals(CoderResult.malformedForLength(1), result);
108 		assertEquals(3, in.position());
109 		assertEquals(0, out.position());
110 	}
111 
112 	public void testDecodeInvalidLength() throws Exception {
113 		assertMalformed("&a-", "");
114 		assertMalformed("ab&IKwD-", "ab€");
115 	}
116 
117 	public void testDecodeUnshiftShiftSequence() throws Exception {
118 		assertMalformed("&ImIDkQ-&ImIDkQ-", "\u2262\u0391");
119 		assertEquals("\u2262\u0391a\u2262\u0391", decode("&ImIDkQ-a&ImIDkQ-"));
120 	}
121 
122 	public void testDecodeIllegalBase64char() throws Exception {
123 		assertMalformed("&[-", "");
124 		assertMalformed("&&ImIDkQ-", "");
125 	}
126 
127 	public void testLongBadDecode() throws Exception {
128 		assertMalformed("&IKwA4QDpA-", "€áé");
129 		assertMalformed("&IKwA4QDpA", "€áé");
130 		assertMalformed("&IKwA4QDp", "€áé");
131 		assertMalformed("&IKwA4QDpAP", "€áé");
132 		assertMalformed("&IKwA4QDpAPoA7QDzAP0A5ADrAO8A9gD8AP-", "€áéúíóýäëïöü");
133 	}
134 
135 	public void testEncodeSimple() throws Exception {
136 		String directly = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?";
137 		assertEquals(directly, encode(directly));
138 		String optional = "!\"#$%*;<=>@[]^_'{|}";
139 		assertEquals(optional, encode(optional));
140 		String nonUTF7 = "+\\~";
141 		assertEquals(nonUTF7, encode(nonUTF7));
142 	}
143 
144 	public void testEncodeComplex() throws Exception {
145 		assertEquals("A&ImIDkQ-.", encode("A\u2262\u0391."));
146 		assertEquals("&AO0A4Q-", encode("íá"));
147 	}
148 
149 	public void testEncodeLong() throws Exception {
150 		assertEquals("&IKwA4QDpAPoA7QDzAP0A5ADrAO8A9gD8AP8-", encode("€áéúíóýäëïöüÿ"));
151 	}
152 
153 	public void testEncodeAlphabet() throws Exception {
154 		assertEquals("&AL4AvgC+-", encode("¾¾¾"));
155 		assertEquals("&AL8AvwC,-", encode("¿¿¿"));
156 	}
157 
158 	public void testGetBytes() throws Exception {
159 		// simulate what is done in String.getBytes 
160 		// (cannot be used directly since Charset is not installed while testing)
161 		String string = "café";
162 		CharsetEncoder encoder = tested.newEncoder();
163 		ByteBuffer bb = ByteBuffer.allocate((int) (encoder.maxBytesPerChar() * string.length()));
164 		CharBuffer cb = CharBuffer.wrap(string);
165 		encoder.reset();
166 		CoderResult cr = encoder.encode(cb, bb, true);
167 		if (!cr.isUnderflow())
168 			cr.throwException();
169 		cr = encoder.flush(bb);
170 		if (!cr.isUnderflow())
171 			cr.throwException();
172 		bb.flip();
173 		assertEquals("caf&AOk-", CharsetTestUtil.asString(bb));
174 	}
175 
176 	protected void assertMalformed(String s, String stringOut) throws UnsupportedEncodingException {
177 		ByteBuffer in = CharsetTestUtil.wrap(s);
178 		CharsetDecoder testedDecoder = tested.newDecoder();
179 		CharBuffer out = CharBuffer.allocate(1024);
180 		CoderResult result = testedDecoder.decode(in, out, true);
181 		if (result.isUnderflow())
182 			result = testedDecoder.flush(out);
183 		out.flip();
184 		assertEquals(stringOut, out.toString());
185 		assertTrue(result.isMalformed());
186 	}
187 }