1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package tests.api.java.nio.charset;
17
18import java.io.File;
19import java.io.FileOutputStream;
20import java.io.OutputStreamWriter;
21import java.nio.charset.Charset;
22import java.nio.charset.UnsupportedCharsetException;
23import java.nio.charset.spi.CharsetProvider;
24import java.util.Iterator;
25import java.util.Vector;
26
27import junit.framework.TestCase;
28import tests.api.java.nio.charset.CharsetTest.MockCharset;
29
30/**
31 * Test charset providers managed by Charset.
32 */
33public class CharsetProviderTest extends TestCase {
34
35	// need to be modified, e.g., read from system property
36	static String PROP_CONFIG_FILE1 = "clear.tests.cp1";
37
38	static String CONFIG_FILE1 = null;
39
40
41	static MockCharset charset1 = new MockCharset("mockCharset00",
42			new String[] { "mockCharset01", "mockCharset02" });
43
44	static MockCharset charset2 = new MockCharset("mockCharset10",
45			new String[] { "mockCharset11", "mockCharset12" });
46
47	/**
48	 * @param arg0
49	 */
50	public CharsetProviderTest(String arg0) {
51		super(arg0);
52                CONFIG_FILE1 = System.getProperty("user.dir") + "/resources";
53
54		String sep = System.getProperty("file.separator");
55
56		if (!CONFIG_FILE1.endsWith(sep)) {
57			CONFIG_FILE1 += sep;
58		}
59		CONFIG_FILE1 += "META-INF" + sep + "services" + sep
60				+ "java.nio.charset.spi.CharsetProvider";
61	}
62
63	/*
64	 * Write the string to the config file.
65	 */
66	private void setupFile(String path, String content) throws Exception {
67		String sep = System.getProperty("file.separator");
68		int sepIndex = path.lastIndexOf(sep);
69		File f = new File(path.substring(0, sepIndex));
70		f.mkdirs();
71
72		FileOutputStream fos = new FileOutputStream(path);
73		OutputStreamWriter writer = new OutputStreamWriter(fos, "UTF-8");
74		try {
75			writer.write(content);
76		} finally {
77			writer.close();
78		}
79	}
80
81	/*
82	 * Write the string to the config file.
83	 */
84	private void cleanupFile(String path) throws Exception {
85		File f = new File(path);
86		f.delete();
87	}
88
89	/*
90	 * Test the method isSupported(String) with charset supported by some
91	 * providers (multiple).
92	 */
93	public void testIsSupported_And_ForName_NormalProvider() throws Exception {
94		try {
95			assertFalse(Charset.isSupported("mockCharset10"));
96			assertFalse(Charset.isSupported("mockCharset11"));
97			assertFalse(Charset.isSupported("mockCharset12"));
98            try {
99                Charset.forName("mockCharset10");
100                fail("Should throw UnsupportedCharsetException!");
101            } catch (UnsupportedCharsetException e) {
102                // expected
103            }
104            try {
105                Charset.forName("mockCharset11");
106                fail("Should throw UnsupportedCharsetException!");
107            } catch (UnsupportedCharsetException e) {
108                // expected
109            }
110            try {
111                Charset.forName("mockCharset12");
112                fail("Should throw UnsupportedCharsetException!");
113            } catch (UnsupportedCharsetException e) {
114                // expected
115            }
116
117			StringBuffer sb = new StringBuffer();
118			sb.append("#comment\r");
119			sb.append("\n");
120			sb.append("\r\n");
121			sb
122					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
123			sb
124					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
125			setupFile(CONFIG_FILE1, sb.toString());
126
127			sb = new StringBuffer();
128			sb.append(" #comment\r");
129			sb.append("\n");
130			sb.append("\r\n");
131			sb
132					.append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
133			setupFile(CONFIG_FILE1, sb.toString());
134
135			assertTrue(Charset.isSupported("mockCharset10"));
136			// ignore case problem in mock, intended
137			assertTrue(Charset.isSupported("MockCharset11"));
138			assertTrue(Charset.isSupported("MockCharset12"));
139			assertTrue(Charset.isSupported("MOCKCharset10"));
140			// intended case problem in mock
141			assertTrue(Charset.isSupported("MOCKCharset11"));
142			assertTrue(Charset.isSupported("MOCKCharset12"));
143
144            assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
145            assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
146            assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
147
148            assertTrue(Charset.forName("mockCharset10") == charset2);
149            // intended case problem in mock
150            Charset.forName("mockCharset11");
151            assertTrue(Charset.forName("mockCharset12") == charset2);
152		} finally {
153			cleanupFile(CONFIG_FILE1);
154		}
155	}
156
157	/*
158	 * Test the method isSupported(String) when the configuration file contains
159	 * a non-existing class name.
160	 */
161	public void testIsSupported_NonExistingClass() throws Exception {
162		try {
163			StringBuffer sb = new StringBuffer();
164			sb.append("impossible\r");
165			setupFile(CONFIG_FILE1, sb.toString());
166
167			Charset.isSupported("impossible");
168			fail("Should throw Error!");
169		} catch (Error e) {
170			// expected
171		} finally {
172			cleanupFile(CONFIG_FILE1);
173		}
174	}
175
176	/*
177	 * Test the method isSupported(String) when the configuration file contains
178	 * a non-CharsetProvider class name.
179	 */
180	public void testIsSupported_NotCharsetProviderClass() throws Exception {
181		try {
182			StringBuffer sb = new StringBuffer();
183			sb.append("java.lang.String\r");
184			setupFile(CONFIG_FILE1, sb.toString());
185
186			Charset.isSupported("impossible");
187			fail("Should throw ClassCastException!");
188		} catch (ClassCastException e) {
189			// expected
190		} finally {
191			cleanupFile(CONFIG_FILE1);
192		}
193	}
194
195	/*
196	 * Test the method forName(String) when the charset provider supports a
197	 * built-in charset.
198	 */
199	public void testForName_DuplicateWithBuiltInCharset() throws Exception {
200		try {
201			StringBuffer sb = new StringBuffer();
202			sb
203					.append("tests.api.java.nio.charset.CharsetProviderTest$MockCharsetProviderACSII\r");
204			setupFile(CONFIG_FILE1, sb.toString());
205
206			assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
207			assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
208		} finally {
209			cleanupFile(CONFIG_FILE1);
210		}
211	}
212
213	/*
214	 * Test the method forName(String) when the configuration file contains a
215	 * non-existing class name.
216	 */
217	public void testForName_NonExistingClass() throws Exception {
218		try {
219			StringBuffer sb = new StringBuffer();
220			sb.append("impossible\r");
221			setupFile(CONFIG_FILE1, sb.toString());
222
223			Charset.forName("impossible");
224			fail("Should throw Error!");
225		} catch (Error e) {
226			// expected
227		} finally {
228			cleanupFile(CONFIG_FILE1);
229		}
230	}
231
232	/*
233	 * Test the method forName(String) when the configuration file contains a
234	 * non-CharsetProvider class name.
235	 */
236	public void testForName_NotCharsetProviderClass() throws Exception {
237		try {
238			StringBuffer sb = new StringBuffer();
239			sb.append("java.lang.String\r");
240			setupFile(CONFIG_FILE1, sb.toString());
241
242			Charset.forName("impossible");
243			fail("Should throw ClassCastException!");
244		} catch (ClassCastException e) {
245			// expected
246		} finally {
247			cleanupFile(CONFIG_FILE1);
248		}
249	}
250
251	/*
252	 * Test the method availableCharsets() with charset supported by some
253	 * providers (multiple).
254	 */
255	public void testAvailableCharsets_NormalProvider() throws Exception {
256		try {
257			assertFalse(Charset.availableCharsets()
258					.containsKey("mockCharset10"));
259			assertFalse(Charset.availableCharsets()
260					.containsKey("mockCharset11"));
261			assertFalse(Charset.availableCharsets()
262					.containsKey("mockCharset12"));
263
264			StringBuffer sb = new StringBuffer();
265			sb.append("#comment\r");
266			sb.append("\n");
267			sb.append("\r\n");
268			sb
269					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
270			sb
271					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
272			setupFile(CONFIG_FILE1, sb.toString());
273
274			sb = new StringBuffer();
275			sb.append("#comment\r");
276			sb.append("\n");
277			sb.append("\r\n");
278			sb
279					.append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
280			setupFile(CONFIG_FILE1, sb.toString());
281
282			assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
283			assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
284			assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
285			assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
286			assertFalse(Charset.availableCharsets()
287					.containsKey("mockCharset01"));
288			assertFalse(Charset.availableCharsets()
289					.containsKey("mockCharset02"));
290
291			assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
292			assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
293			assertFalse(Charset.availableCharsets()
294					.containsKey("mockCharset11"));
295			assertFalse(Charset.availableCharsets()
296					.containsKey("mockCharset12"));
297
298			assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
299			assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
300			assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
301			assertFalse(Charset.availableCharsets()
302					.containsKey("mockCharset11"));
303			assertFalse(Charset.availableCharsets()
304					.containsKey("mockCharset12"));
305		} finally {
306			cleanupFile(CONFIG_FILE1);
307		}
308	}
309
310	/*
311	 * Test the method availableCharsets(String) when the configuration file
312	 * contains a non-existing class name.
313	 */
314	public void testAvailableCharsets_NonExistingClass() throws Exception {
315		try {
316			StringBuffer sb = new StringBuffer();
317			sb.append("impossible\r");
318			setupFile(CONFIG_FILE1, sb.toString());
319
320			Charset.availableCharsets();
321			fail("Should throw Error!");
322		} catch (Error e) {
323			// expected
324		} finally {
325			cleanupFile(CONFIG_FILE1);
326		}
327	}
328
329	/*
330	 * Test the method availableCharsets(String) when the configuration file
331	 * contains a non-CharsetProvider class name.
332	 */
333	public void testAvailableCharsets_NotCharsetProviderClass()
334			throws Exception {
335		try {
336			StringBuffer sb = new StringBuffer();
337			sb.append("java.lang.String\r");
338			setupFile(CONFIG_FILE1, sb.toString());
339
340			Charset.availableCharsets();
341			fail("Should throw ClassCastException!");
342		} catch (ClassCastException e) {
343			// expected
344		} finally {
345			cleanupFile(CONFIG_FILE1);
346		}
347	}
348
349	/*
350	 * Test the method availableCharsets(String) when the configuration file
351	 * contains an illegal string.
352	 */
353	public void testAvailableCharsets_IllegalString() throws Exception {
354		try {
355			StringBuffer sb = new StringBuffer();
356			sb.append("java String\r");
357			setupFile(CONFIG_FILE1, sb.toString());
358
359			Charset.availableCharsets();
360			fail("Should throw Error!");
361		} catch (Error e) {
362			// expected
363		} finally {
364			cleanupFile(CONFIG_FILE1);
365		}
366	}
367
368    /*
369     * Mock charset provider.
370     */
371    public static class MockCharsetProvider extends CharsetProvider {
372
373        public Charset charsetForName(String charsetName) {
374            if ("MockCharset10".equalsIgnoreCase(charsetName)
375                    || "MockCharset11".equalsIgnoreCase(charsetName)
376                    || "MockCharset12".equalsIgnoreCase(charsetName)) {
377                return charset2;
378            }
379            return null;
380        }
381
382        public Iterator charsets() {
383            Vector v = new Vector();
384            v.add(charset2);
385            return v.iterator();
386        }
387    }
388
389    /*
390     * Another mock charset provider providing build-in charset "ascii".
391     */
392    public static class MockCharsetProviderACSII extends CharsetProvider {
393
394        public Charset charsetForName(String charsetName) {
395            if ("US-ASCII".equalsIgnoreCase(charsetName)
396                    || "ASCII".equalsIgnoreCase(charsetName)) {
397                return new MockCharset("US-ASCII", new String[] { "ASCII" });
398            }
399            return null;
400        }
401
402        public Iterator charsets() {
403            Vector v = new Vector();
404            v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
405            return v.iterator();
406        }
407    }
408
409}
410