1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.util;
19
20import java.io.BufferedReader;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.InputStreamReader;
26import java.io.OutputStreamWriter;
27import java.io.PrintStream;
28import java.io.PrintWriter;
29import java.io.Writer;
30import java.util.ArrayList;
31import java.util.Arrays;
32import java.util.Enumeration;
33import java.util.HashSet;
34import java.util.InvalidPropertiesFormatException;
35import java.util.Iterator;
36import java.util.List;
37import java.util.Properties;
38import java.util.Scanner;
39import java.util.Set;
40import tests.support.resource.Support_Resources;
41
42public class PropertiesTest extends junit.framework.TestCase {
43
44    Properties tProps;
45
46    byte[] propsFile;
47
48    /**
49     * java.util.Properties#Properties()
50     */
51    public void test_Constructor() {
52        // Test for method java.util.Properties()
53        Properties p = new Properties();
54        // do something to avoid getting a variable unused warning
55        p.clear();
56        assertTrue("Created incorrect Properties", true);
57    }
58
59    public void test_loadLjava_io_InputStream_NPE() throws Exception {
60        Properties p = new Properties();
61        try {
62            p.load((InputStream) null);
63            fail("should throw NullPointerException");
64        } catch (NullPointerException e) {
65            // Expected
66        }
67    }
68
69    public void test_loadsave() throws Exception {
70        Properties p = new Properties();
71        try {
72            p.load((InputStream) null);
73            fail("should throw NPE");
74        } catch (NullPointerException npe) {
75            // expected
76        }
77    }
78
79    /**
80     * java.util.Properties#Properties(java.util.Properties)
81     */
82    public void test_ConstructorLjava_util_Properties() {
83        Properties systemProperties = System.getProperties();
84        Properties properties = new Properties(systemProperties);
85        Enumeration<?> propertyNames = systemProperties.propertyNames();
86        String propertyName = null;
87        while (propertyNames.hasMoreElements()) {
88            propertyName = (String) propertyNames.nextElement();
89            assertEquals("failed to construct correct properties",
90                    systemProperties.getProperty(propertyName),
91                    properties.getProperty(propertyName));
92        }
93    }
94
95    /**
96     * java.util.Properties#getProperty(java.lang.String)
97     */
98    public void test_getPropertyLjava_lang_String() {
99        // Test for method java.lang.String
100        // java.util.Properties.getProperty(java.lang.String)
101        assertEquals("Did not retrieve property", "this is a test property",
102                ((String) tProps.getProperty("test.prop")));
103    }
104
105    /**
106     * java.util.Properties#getProperty(java.lang.String,
107     *java.lang.String)
108     */
109    public void test_getPropertyLjava_lang_StringLjava_lang_String() {
110        // Test for method java.lang.String
111        // java.util.Properties.getProperty(java.lang.String, java.lang.String)
112        assertEquals("Did not retrieve property", "this is a test property",
113                ((String) tProps.getProperty("test.prop", "Blarg")));
114        assertEquals("Did not return default value", "Gabba", ((String) tProps
115                .getProperty("notInThere.prop", "Gabba")));
116    }
117
118    /**
119     * java.util.Properties#getProperty(java.lang.String)
120     */
121    public void test_getPropertyLjava_lang_String2() {
122        // regression test for HARMONY-3518
123        MyProperties props = new MyProperties();
124        assertNull(props.getProperty("key"));
125    }
126
127    /**
128     * java.util.Properties#getProperty(java.lang.String,
129     *java.lang.String)
130     */
131    public void test_getPropertyLjava_lang_StringLjava_lang_String2() {
132        // regression test for HARMONY-3518
133        MyProperties props = new MyProperties();
134        assertEquals("defaultValue", props.getProperty("key", "defaultValue"));
135    }
136
137    // regression testing for HARMONY-3518
138    static class MyProperties extends Properties {
139        public synchronized Object get(Object key) {
140            return getProperty((String) key); // assume String
141        }
142    }
143
144    /**
145     * java.util.Properties#list(java.io.PrintStream)
146     */
147    public void test_listLjava_io_PrintStream() {
148        ByteArrayOutputStream baos = new ByteArrayOutputStream();
149        PrintStream ps = new PrintStream(baos);
150        Properties myProps = new Properties();
151        myProps.setProperty("Abba", "Cadabra");
152        myProps.setProperty("Open", "Sesame");
153        myProps.setProperty("LongProperty",
154                "a long long long long long long long property");
155        myProps.list(ps);
156        ps.flush();
157        String propList = baos.toString();
158        assertTrue("Property list innacurate",
159                propList.indexOf("Abba=Cadabra") >= 0);
160        assertTrue("Property list innacurate",
161                propList.indexOf("Open=Sesame") >= 0);
162        assertTrue("property list do not conatins \"...\"", propList
163                .indexOf("...") != -1);
164
165        ps = null;
166        try {
167            myProps.list(ps);
168            fail("should throw NullPointerException");
169        } catch (NullPointerException e) {
170            // expected
171        }
172    }
173
174    /**
175     * java.util.Properties#list(java.io.PrintWriter)
176     */
177    public void test_listLjava_io_PrintWriter() {
178        ByteArrayOutputStream baos = new ByteArrayOutputStream();
179        PrintWriter pw = new PrintWriter(baos);
180        Properties myProps = new Properties();
181        myProps.setProperty("Abba", "Cadabra");
182        myProps.setProperty("Open", "Sesame");
183        myProps.setProperty("LongProperty",
184                "a long long long long long long long property");
185        myProps.list(pw);
186        pw.flush();
187        String propList = baos.toString();
188        assertTrue("Property list innacurate",
189                propList.indexOf("Abba=Cadabra") >= 0);
190        assertTrue("Property list innacurate",
191                propList.indexOf("Open=Sesame") >= 0);
192        pw = null;
193        try {
194            myProps.list(pw);
195            fail("should throw NullPointerException");
196        } catch (NullPointerException e) {
197            // expected
198        }
199    }
200
201    /**
202     * java.util.Properties#load(java.io.InputStream)
203     */
204    public void test_loadLjava_io_InputStream() {
205        // Test for method void java.util.Properties.load(java.io.InputStream)
206        Properties prop = null;
207        try {
208            InputStream is;
209            prop = new Properties();
210            prop.load(is = new ByteArrayInputStream(writeProperties()));
211            is.close();
212        } catch (Exception e) {
213            fail("Exception during load test : " + e.getMessage());
214        }
215        assertEquals("Failed to load correct properties", "harmony.tests", prop
216                .getProperty("test.pkg"));
217        assertNull("Load failed to parse incorrectly", prop
218                .getProperty("commented.entry"));
219
220        prop = new Properties();
221        try {
222            prop.load(new ByteArrayInputStream("=".getBytes()));
223        } catch (IOException e) {
224            // expected
225        }
226        assertTrue("Failed to add empty key", prop.get("").equals(""));
227
228        prop = new Properties();
229        try {
230            prop.load(new ByteArrayInputStream(" = ".getBytes()));
231        } catch (IOException e) {
232            // expected
233        }
234        assertTrue("Failed to add empty key2", prop.get("").equals(""));
235
236        prop = new Properties();
237        try {
238            prop.load(new ByteArrayInputStream(" a= b".getBytes()));
239        } catch (IOException e) {
240            // expected
241        }
242        assertEquals("Failed to ignore whitespace", "b", prop.get("a"));
243
244        prop = new Properties();
245        try {
246            prop.load(new ByteArrayInputStream(" a b".getBytes()));
247        } catch (IOException e) {
248            // expected
249        }
250        assertEquals("Failed to interpret whitespace as =", "b", prop.get("a"));
251
252        prop = new Properties();
253        try {
254            prop.load(new ByteArrayInputStream("#\u008d\u00d2\na=\u008d\u00d3"
255                    .getBytes("ISO8859_1")));
256        } catch (IOException e) {
257            // expected
258        }
259        assertEquals("Failed to parse chars >= 0x80", "\u008d\u00d3", prop
260                .get("a"));
261
262        prop = new Properties();
263        try {
264            prop.load(new ByteArrayInputStream(
265                    "#properties file\r\nfred=1\r\n#last comment"
266                            .getBytes("ISO8859_1")));
267        } catch (IOException e) {
268            // expected
269        } catch (IndexOutOfBoundsException e) {
270            fail("IndexOutOfBoundsException when last line is a comment with no line terminator");
271        }
272        assertEquals("Failed to load when last line contains a comment", "1",
273                prop.get("fred"));
274    }
275
276    /**
277     * java.util.Properties#load(java.io.InputStream)
278     */
279    public void test_loadLjava_io_InputStream_subtest0() {
280        try {
281            InputStream is = Support_Resources
282                    .getStream("hyts_PropertiesTest.properties");
283            Properties props = new Properties();
284            props.load(is);
285            is.close();
286            assertEquals("1", "\n \t \f", props.getProperty(" \r"));
287            assertEquals("2", "a", props.getProperty("a"));
288            assertEquals("3", "bb as,dn   ", props.getProperty("b"));
289            assertEquals("4", ":: cu", props.getProperty("c\r \t\nu"));
290            assertEquals("5", "bu", props.getProperty("bu"));
291            assertEquals("6", "d\r\ne=e", props.getProperty("d"));
292            assertEquals("7", "fff", props.getProperty("f"));
293            assertEquals("8", "g", props.getProperty("g"));
294            assertEquals("9", "", props.getProperty("h h"));
295            assertEquals("10", "i=i", props.getProperty(" "));
296            assertEquals("11", "   j", props.getProperty("j"));
297            assertEquals("12", "   c", props.getProperty("space"));
298            assertEquals("13", "\\", props.getProperty("dblbackslash"));
299        } catch (IOException e) {
300            fail("Unexpected: " + e);
301        }
302    }
303
304    /**
305     * @throws IOException
306     * java.util.Properties#load(java.io.Reader)
307     * @since 1.6
308     */
309    public void test_loadLjava_io_Reader() throws IOException {
310        Properties prop = null;
311        try {
312            InputStream is;
313            prop = new Properties();
314            is = new ByteArrayInputStream(writeProperties());
315            prop.load(new InputStreamReader(is));
316            is.close();
317        } catch (Exception e) {
318            fail("Exception during load test : " + e.getMessage());
319        }
320        assertEquals("Failed to load correct properties", "harmony.tests", prop
321                .getProperty("test.pkg"));
322        assertNull("Load failed to parse incorrectly", prop
323                .getProperty("commented.entry"));
324
325        prop = new Properties();
326        prop.load(new ByteArrayInputStream("=".getBytes()));
327        assertEquals("Failed to add empty key", "", prop.get(""));
328
329        prop = new Properties();
330        prop.load(new ByteArrayInputStream(" = ".getBytes()));
331        assertEquals("Failed to add empty key2", "", prop.get(""));
332
333        prop = new Properties();
334        prop.load(new ByteArrayInputStream(" a= b".getBytes()));
335        assertEquals("Failed to ignore whitespace", "b", prop.get("a"));
336
337        prop = new Properties();
338        prop.load(new ByteArrayInputStream(" a b".getBytes()));
339        assertEquals("Failed to interpret whitespace as =", "b", prop.get("a"));
340
341        prop = new Properties();
342        prop.load(new ByteArrayInputStream("#comment\na=value"
343                .getBytes("UTF-8")));
344        assertEquals("value", prop.getProperty("a"));
345
346        prop = new Properties();
347        prop.load(new InputStreamReader(new ByteArrayInputStream(
348                "#\u008d\u00d2\na=\u008d\u00d3".getBytes("UTF-8"))));
349        try {
350            prop
351                    .load(new InputStreamReader(new ByteArrayInputStream(
352                            "#\u008d\u00d2\na=\\\\u008d\\\\\\uu00d3"
353                                    .getBytes("UTF-8"))));
354            fail("Should throw IllegalArgumentException");
355        } catch (IllegalArgumentException e) {
356            // expected
357        }
358
359        prop = new Properties();
360        try {
361            prop.load(new InputStreamReader(new ByteArrayInputStream(
362                    "#properties file\r\nfred=1\r\n#last comment"
363                            .getBytes("ISO8859_1"))));
364        } catch (IndexOutOfBoundsException e) {
365            fail("IndexOutOfBoundsException when last line is a comment with no line terminator");
366        }
367        assertEquals("Failed to load when last line contains a comment", "1",
368                prop.get("fred"));
369
370        // Regression tests for HARMONY-5414
371        prop = new Properties();
372        prop.load(new ByteArrayInputStream("a=\\u1234z".getBytes()));
373
374        prop = new Properties();
375        try {
376            prop.load(new ByteArrayInputStream("a=\\u123".getBytes()));
377            fail("should throw IllegalArgumentException");
378        } catch (IllegalArgumentException e) {
379            // Expected
380        }
381
382        prop = new Properties();
383        try {
384            prop.load(new ByteArrayInputStream("a=\\u123z".getBytes()));
385            fail("should throw IllegalArgumentException");
386        } catch (IllegalArgumentException expected) {
387            // Expected
388        }
389
390        prop = new Properties();
391        Properties expected = new Properties();
392        expected.put("a", "\u0000");
393        prop.load(new ByteArrayInputStream("a=\\".getBytes()));
394        assertEquals("Failed to read trailing slash value", expected, prop);
395
396        prop = new Properties();
397        expected = new Properties();
398        expected.put("a", "\u1234\u0000");
399        prop.load(new ByteArrayInputStream("a=\\u1234\\".getBytes()));
400        assertEquals("Failed to read trailing slash value #2", expected, prop);
401
402        prop = new Properties();
403        expected = new Properties();
404        expected.put("a", "q");
405        prop.load(new ByteArrayInputStream("a=\\q".getBytes()));
406        assertEquals("Failed to read slash value #3", expected, prop);
407    }
408
409    /**
410     * java.util.Properties#load(java.io.InputStream)
411     */
412    public void test_loadLjava_io_InputStream_Special() throws IOException {
413        // Test for method void java.util.Properties.load(java.io.InputStream)
414        Properties prop = null;
415        prop = new Properties();
416        prop.load(new ByteArrayInputStream("=".getBytes()));
417        assertTrue("Failed to add empty key", prop.get("").equals(""));
418
419        prop = new Properties();
420        prop.load(new ByteArrayInputStream("=\r\n".getBytes()));
421        assertTrue("Failed to add empty key", prop.get("").equals(""));
422
423        prop = new Properties();
424        prop.load(new ByteArrayInputStream("=\n\r".getBytes()));
425        assertTrue("Failed to add empty key", prop.get("").equals(""));
426    }
427
428    /**
429     * @throws IOException
430     * java.util.Properties#load(java.io.Reader)
431     * @since 1.6
432     */
433    public void test_loadLjava_io_Reader_subtest0() throws IOException {
434        InputStream is = Support_Resources
435                .getStream("hyts_PropertiesTest.properties");
436        Properties props = new Properties();
437        props.load(new InputStreamReader(is));
438        is.close();
439        assertEquals("1", "\n \t \f", props.getProperty(" \r"));
440        assertEquals("2", "a", props.getProperty("a"));
441        assertEquals("3", "bb as,dn   ", props.getProperty("b"));
442        assertEquals("4", ":: cu", props.getProperty("c\r \t\nu"));
443        assertEquals("5", "bu", props.getProperty("bu"));
444        assertEquals("6", "d\r\ne=e", props.getProperty("d"));
445        assertEquals("7", "fff", props.getProperty("f"));
446        assertEquals("8", "g", props.getProperty("g"));
447        assertEquals("9", "", props.getProperty("h h"));
448        assertEquals("10", "i=i", props.getProperty(" "));
449        assertEquals("11", "   j", props.getProperty("j"));
450        assertEquals("12", "   c", props.getProperty("space"));
451        assertEquals("13", "\\", props.getProperty("dblbackslash"));
452    }
453
454    /**
455     * {@link java.util.Properties#stringPropertyNames()}
456     * @since 1.6
457     */
458    public void test_stringPropertyNames() {
459        Set<String> set = tProps.stringPropertyNames();
460        assertEquals(2, set.size());
461        assertTrue(set.contains("test.prop"));
462        assertTrue(set.contains("bogus.prop"));
463        assertNotSame(set, tProps.stringPropertyNames());
464
465        set = new Properties().stringPropertyNames();
466        assertEquals(0, set.size());
467
468        set = new Properties(System.getProperties()).stringPropertyNames();
469        assertTrue(set.size() > 0);
470
471        tProps = new Properties(tProps);
472        tProps.put("test.prop", "anotherValue");
473        tProps.put("3rdKey", "3rdValue");
474        set = tProps.stringPropertyNames();
475        assertEquals(3, set.size());
476        assertTrue(set.contains("test.prop"));
477        assertTrue(set.contains("bogus.prop"));
478        assertTrue(set.contains("3rdKey"));
479
480        tProps.put(String.class, "valueOfNonStringKey");
481        set = tProps.stringPropertyNames();
482        assertEquals(3, set.size());
483        assertTrue(set.contains("test.prop"));
484        assertTrue(set.contains("bogus.prop"));
485        assertTrue(set.contains("3rdKey"));
486
487        tProps.put("4thKey", "4thValue");
488        assertEquals(4, tProps.size());
489        assertEquals(3, set.size());
490
491        try {
492            set.add("another");
493            fail("Should throw UnsupportedOperationException");
494        } catch (UnsupportedOperationException e) {
495            // expected
496        }
497    }
498
499    /**
500     * {@link java.util.Properties#stringPropertyNames()}
501     * @since 1.6
502     */
503    public void test_stringPropertyNames_scenario1() {
504        String[] keys = new String[] { "key1", "key2", "key3" };
505        String[] values = new String[] { "value1", "value2", "value3" };
506        List<String> keyList = Arrays.asList(keys);
507
508        Properties properties = new Properties();
509        for (int index = 0; index < keys.length; index++) {
510            properties.setProperty(keys[index], values[index]);
511        }
512
513        properties = new Properties(properties);
514        Set<String> nameSet = properties.stringPropertyNames();
515        assertEquals(keys.length, nameSet.size());
516        Iterator<String> iterator = nameSet.iterator();
517        while (iterator.hasNext()) {
518            assertTrue(keyList.contains(iterator.next()));
519        }
520
521        Enumeration<?> nameEnum = properties.propertyNames();
522        int count = 0;
523        while (nameEnum.hasMoreElements()) {
524            count++;
525            assertTrue(keyList.contains(nameEnum.nextElement()));
526        }
527        assertEquals(keys.length, count);
528
529        properties = new Properties(properties);
530        nameSet = properties.stringPropertyNames();
531        assertEquals(keys.length, nameSet.size());
532        iterator = nameSet.iterator();
533        while (iterator.hasNext()) {
534            assertTrue(keyList.contains(iterator.next()));
535        }
536
537        nameEnum = properties.propertyNames();
538        count = 0;
539        while (nameEnum.hasMoreElements()) {
540            count++;
541            assertTrue(keyList.contains(nameEnum.nextElement()));
542        }
543        assertEquals(keys.length, count);
544    }
545
546    /**
547     * {@link java.util.Properties#stringPropertyNames()}
548     * @since 1.6
549     */
550    public void test_stringPropertyNames_scenario2() {
551        String[] defaultKeys = new String[] { "defaultKey1", "defaultKey2",
552                "defaultKey3", "defaultKey4", "defaultKey5", "defaultKey6" };
553        String[] defaultValues = new String[] { "defaultValue1",
554                "defaultValue2", "defaultValue3", "defaultValue4",
555                "defaultValue5", "defaultValue6" };
556        List<String> keyList = new ArrayList<String>();
557        Properties defaults = new Properties();
558        for (int index = 0; index < 3; index++) {
559            defaults.setProperty(defaultKeys[index], defaultValues[index]);
560            keyList.add(defaultKeys[index]);
561        }
562
563        String[] keys = new String[] { "key1", "key2", "key3" };
564        String[] values = new String[] { "value1", "value2", "value3" };
565        Properties properties = new Properties(defaults);
566        for (int index = 0; index < keys.length; index++) {
567            properties.setProperty(keys[index], values[index]);
568            keyList.add(keys[index]);
569        }
570
571        Set<String> nameSet = properties.stringPropertyNames();
572        assertEquals(keyList.size(), nameSet.size());
573        Iterator<String> iterator = nameSet.iterator();
574        while (iterator.hasNext()) {
575            assertTrue(keyList.contains(iterator.next()));
576        }
577
578        Enumeration<?> nameEnum = properties.propertyNames();
579        int count = 0;
580        while (nameEnum.hasMoreElements()) {
581            count++;
582            assertTrue(keyList.contains(nameEnum.nextElement()));
583        }
584        assertEquals(keyList.size(), count);
585
586        for (int index = 3; index < defaultKeys.length; index++) {
587            defaults.setProperty(defaultKeys[index], defaultValues[index]);
588            keyList.add(defaultKeys[index]);
589        }
590
591        nameSet = properties.stringPropertyNames();
592        assertEquals(keyList.size(), nameSet.size());
593        iterator = nameSet.iterator();
594        while (iterator.hasNext()) {
595            assertTrue(keyList.contains(iterator.next()));
596        }
597
598        nameEnum = properties.propertyNames();
599        count = 0;
600        while (nameEnum.hasMoreElements()) {
601            count++;
602            assertTrue(keyList.contains(nameEnum.nextElement()));
603        }
604        assertEquals(keyList.size(), count);
605    }
606
607    /**
608     * java.util.Properties#save(java.io.OutputStream, java.lang.String)
609     */
610    public void test_saveLjava_io_OutputStreamLjava_lang_String() {
611        // Test for method void java.util.Properties.save(java.io.OutputStream,
612        // java.lang.String)
613        Properties myProps = new Properties();
614        Properties myProps2 = new Properties();
615
616        myProps.setProperty("Property A", "aye");
617        myProps.setProperty("Property B", "bee");
618        myProps.setProperty("Property C", "see");
619
620        try {
621            ByteArrayOutputStream out = new ByteArrayOutputStream();
622            myProps.save(out, "A Header");
623            out.close();
624            ByteArrayInputStream in = new ByteArrayInputStream(out
625                    .toByteArray());
626            myProps2.load(in);
627            in.close();
628        } catch (IOException ioe) {
629            fail("IOException occurred reading/writing file : "
630                    + ioe.getMessage());
631        }
632
633        Enumeration e = myProps.propertyNames();
634        String nextKey;
635        while (e.hasMoreElements()) {
636            nextKey = (String) e.nextElement();
637            assertEquals("Stored property list not equal to original", myProps
638                    .getProperty(nextKey), myProps2.getProperty(nextKey));
639        }
640    }
641
642    /**
643     * java.util.Properties#setProperty(java.lang.String,
644     *java.lang.String)
645     */
646    public void test_setPropertyLjava_lang_StringLjava_lang_String() {
647        // Test for method java.lang.Object
648        // java.util.Properties.setProperty(java.lang.String, java.lang.String)
649        Properties myProps = new Properties();
650        myProps.setProperty("Yoink", "Yabba");
651        assertEquals("Failed to set property", "Yabba", myProps
652                .getProperty("Yoink"));
653        myProps.setProperty("Yoink", "Gab");
654        assertEquals("Failed to reset property", "Gab", myProps
655                .getProperty("Yoink"));
656    }
657
658    /**
659     * java.util.Properties#store(java.io.OutputStream, java.lang.String)
660     */
661    public void test_storeLjava_io_OutputStreamLjava_lang_String() {
662        // Test for method void java.util.Properties.store(java.io.OutputStream,
663        // java.lang.String)
664        Properties myProps = new Properties();
665        Properties myProps2 = new Properties();
666        Enumeration e;
667        String nextKey;
668
669        myProps.put("Property A", " aye\\\f\t\n\r\b");
670        myProps.put("Property B", "b ee#!=:");
671        myProps.put("Property C", "see");
672
673        try {
674            ByteArrayOutputStream out = new ByteArrayOutputStream();
675            myProps.store(out, "A Header");
676            out.close();
677            ByteArrayInputStream in = new ByteArrayInputStream(out
678                    .toByteArray());
679            myProps2.load(in);
680            in.close();
681        } catch (IOException ioe) {
682            fail("IOException occurred reading/writing file : "
683                    + ioe.getMessage());
684        }
685
686        e = myProps.propertyNames();
687        while (e.hasMoreElements()) {
688            nextKey = (String) e.nextElement();
689            assertTrue("Stored property list not equal to original", myProps2
690                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
691        }
692
693    }
694
695    /**
696     * @throws IOException
697     * java.util.Properties#store(java.io.Writer, java.lang.String)
698     * @since 1.6
699     */
700    public void test_storeLjava_io_WriterLjava_lang_String() throws IOException {
701        Properties myProps = new Properties();
702        Properties myProps2 = new Properties();
703
704        myProps.put("Property A", " aye\\\f\t\n\r\b");
705        myProps.put("Property B", "b ee#!=:");
706        myProps.put("Property C", "see");
707
708        ByteArrayOutputStream out = new ByteArrayOutputStream();
709        myProps.store(new OutputStreamWriter(out), "A Header");
710        Scanner scanner = new Scanner(out.toString());
711        assertTrue(scanner.nextLine().startsWith("#A Header"));
712        assertTrue(scanner.nextLine().startsWith("#"));
713        out.close();
714        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
715        myProps2.load(in);
716        in.close();
717
718        Enumeration e = myProps.propertyNames();
719        String nextKey;
720        while (e.hasMoreElements()) {
721            nextKey = (String) e.nextElement();
722            assertTrue("Stored property list not equal to original", myProps2
723                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
724        }
725
726        try {
727            myProps.store((Writer) null, "some comments");
728            fail("Should throw NullPointerException");
729        } catch (NullPointerException e1) {
730            // expected
731        }
732
733        myProps.put(String.class, "wrong type");
734        try {
735            myProps.store(new OutputStreamWriter(new ByteArrayOutputStream()),
736                    "some comments");
737            fail("Should throw ClassCastException");
738        } catch (ClassCastException e1) {
739            // expected
740        }
741        myProps.remove(String.class);
742        myProps.store(new OutputStreamWriter(new ByteArrayOutputStream()),
743                "some comments");
744        // it is OK
745        myProps.put("wrong type", String.class);
746        try {
747            myProps.store(new OutputStreamWriter(new ByteArrayOutputStream()),
748                    "some comments");
749            fail("Should throw ClassCastException");
750        } catch (ClassCastException e1) {
751            // expected
752        }
753    }
754
755    /**
756     * java.util.Properties#loadFromXML(java.io.InputStream)
757     */
758    public void test_loadFromXMLLjava_io_InputStream() throws Exception {
759        // Test for method void
760        // java.util.Properties.loadFromXML(java.io.InputStream)
761        Properties prop = null;
762        try {
763            InputStream is;
764            prop = new Properties();
765            prop.loadFromXML(is = new ByteArrayInputStream(
766                    writePropertiesXMLUTF_8()));
767            is.close();
768        } catch (Exception e) {
769            fail("Exception during load test : " + e.getMessage());
770        }
771        assertEquals("Failed to load correct properties", "value3", prop
772                .getProperty("key3"));
773        assertEquals("Failed to load correct properties", "value1", prop
774                .getProperty("key1"));
775
776        try {
777            InputStream is;
778            prop = new Properties();
779            prop.loadFromXML(is = new ByteArrayInputStream(
780                    writePropertiesXMLISO_8859_1()));
781            is.close();
782        } catch (Exception e) {
783            fail("Exception during load test : " + e.getMessage());
784        }
785        assertEquals("Failed to load correct properties", "value2", prop
786                .getProperty("key2"));
787        assertEquals("Failed to load correct properties", "value1", prop
788                .getProperty("key1"));
789
790        try {
791            prop.loadFromXML(null);
792            fail("should throw NullPointerException");
793        } catch (NullPointerException e) {
794            // expected
795        }
796    }
797
798    /**
799     * java.util.Properties#storeToXML(java.io.OutputStream,
800     *java.lang.String, java.lang.String)
801     */
802    public void test_storeToXMLLjava_io_OutputStreamLjava_lang_StringLjava_lang_String()
803            throws Exception {
804        // Test for method void
805        // java.util.Properties.storeToXML(java.io.OutputStream,
806        // java.lang.String, java.lang.String)
807        Properties myProps = new Properties();
808        Properties myProps2 = new Properties();
809        Enumeration e;
810        String nextKey;
811
812        myProps.setProperty("key1", "value1");
813        myProps.setProperty("key2", "value2");
814        myProps.setProperty("key3", "value3");
815        myProps.setProperty("<a>key4</a>", "\"value4");
816        myProps.setProperty("key5   ", "<h>value5</h>");
817        myProps.setProperty("<a>key6</a>", "   <h>value6</h>   ");
818        myProps.setProperty("<comment>key7</comment>", "value7");
819        myProps.setProperty("  key8   ", "<comment>value8</comment>");
820        myProps.setProperty("&lt;key9&gt;", "\u0027value9");
821        myProps.setProperty("key10\"", "&lt;value10&gt;");
822        myProps.setProperty("&amp;key11&amp;", "value11");
823        myProps.setProperty("key12", "&amp;value12&amp;");
824        myProps.setProperty("<a>&amp;key13&lt;</a>",
825                "&amp;&value13<b>&amp;</b>");
826
827        try {
828            ByteArrayOutputStream out = new ByteArrayOutputStream();
829
830            // store in UTF-8 encoding
831            myProps.storeToXML(out, "comment");
832            out.close();
833            ByteArrayInputStream in = new ByteArrayInputStream(out
834                    .toByteArray());
835            myProps2.loadFromXML(in);
836            in.close();
837        } catch (InvalidPropertiesFormatException ipfe) {
838            fail("InvalidPropertiesFormatException occurred reading file: "
839                    + ipfe.getMessage());
840        } catch (IOException ioe) {
841            fail("IOException occurred reading/writing file : "
842                    + ioe.getMessage());
843        }
844
845        e = myProps.propertyNames();
846        while (e.hasMoreElements()) {
847            nextKey = (String) e.nextElement();
848            assertTrue("Stored property list not equal to original", myProps2
849                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
850        }
851
852        try {
853            ByteArrayOutputStream out = new ByteArrayOutputStream();
854
855            // store in ISO-8859-1 encoding
856            myProps.storeToXML(out, "comment", "ISO-8859-1");
857            out.close();
858            ByteArrayInputStream in = new ByteArrayInputStream(out
859                    .toByteArray());
860            myProps2 = new Properties();
861            myProps2.loadFromXML(in);
862            in.close();
863        } catch (InvalidPropertiesFormatException ipfe) {
864            fail("InvalidPropertiesFormatException occurred reading file: "
865                    + ipfe.getMessage());
866        } catch (IOException ioe) {
867            fail("IOException occurred reading/writing file : "
868                    + ioe.getMessage());
869        }
870
871        e = myProps.propertyNames();
872        while (e.hasMoreElements()) {
873            nextKey = (String) e.nextElement();
874            assertTrue("Stored property list not equal to original", myProps2
875                    .getProperty(nextKey).equals(myProps.getProperty(nextKey)));
876        }
877
878        try {
879            ByteArrayOutputStream out = new ByteArrayOutputStream();
880            myProps.storeToXML(out, null, null);
881            fail("should throw nullPointerException");
882        } catch (NullPointerException ne) {
883            // expected
884        }
885    }
886
887    /**
888     * if loading from single line like "hello" without "\n\r" neither "=", it
889     * should be same as loading from "hello="
890     */
891    public void testLoadSingleLine() throws Exception {
892        Properties props = new Properties();
893        InputStream sr = new ByteArrayInputStream("hello".getBytes());
894        props.load(sr);
895        assertEquals(1, props.size());
896    }
897
898    public void test_propertyNames() {
899        Properties parent = new Properties();
900        parent.setProperty("parent.a.key", "parent.a.value");
901        parent.setProperty("parent.b.key", "parent.b.value");
902
903        Enumeration<?> names = parent.propertyNames();
904        assertPropertyEnumeration(names, "parent.a.key", "parent.b.key");
905
906        Properties current = new Properties(parent);
907        current.setProperty("current.a.key", "current.a.value");
908        current.setProperty("current.b.key", "current.b.value");
909
910        names = current.propertyNames();
911        assertPropertyEnumeration(names,
912                "parent.a.key",
913                "parent.b.key",
914                "current.a.key",
915                "current.b.key");
916
917        Properties child = new Properties(current);
918        child.setProperty("child.a.key", "child.a.value");
919        child.setProperty("child.b.key", "child.b.value");
920
921        names = child.propertyNames();
922        assertPropertyEnumeration(names,
923                "parent.a.key",
924                "parent.b.key",
925                "current.a.key",
926                "current.b.key",
927                "child.a.key",
928                "child.b.key");
929    }
930
931    public void assertPropertyEnumeration(Enumeration<?> propNames,
932            String... expected) {
933        Set<String> propsSet = new HashSet<String>();
934        while (propNames.hasMoreElements()) {
935            String next = (String) propNames.nextElement();
936            assertFalse(propsSet.contains(next));
937            propsSet.add(next);
938        }
939
940        assertEquals(expected.length, propsSet.size());
941        assertTrue(propsSet.containsAll(Arrays.asList(expected)));
942    }
943
944    private String comment1 = "comment1";
945
946    private String comment2 = "comment2";
947
948    private void validateOutput(String[] expectStrings, byte[] output)
949            throws IOException {
950        ByteArrayInputStream bais = new ByteArrayInputStream(output);
951        BufferedReader br = new BufferedReader(new InputStreamReader(bais,
952                "ISO8859_1"));
953        for (String expectString : expectStrings) {
954            assertEquals(expectString, br.readLine());
955        }
956        br.readLine();
957        assertNull(br.readLine());
958        br.close();
959    }
960
961    public void testStore_scenario0() throws IOException {
962        ByteArrayOutputStream baos = new ByteArrayOutputStream();
963        Properties props = new Properties();
964        props.store(baos, comment1 + '\r' + comment2);
965        validateOutput(new String[] { "#comment1", "#comment2" },
966                baos.toByteArray());
967        baos.close();
968    }
969
970    public void testStore_scenario1() throws IOException {
971        ByteArrayOutputStream baos = new ByteArrayOutputStream();
972        Properties props = new Properties();
973        props.store(baos, comment1 + '\n' + comment2);
974        validateOutput(new String[] { "#comment1", "#comment2" },
975                baos.toByteArray());
976        baos.close();
977    }
978
979    public void testStore_scenario2() throws IOException {
980        ByteArrayOutputStream baos = new ByteArrayOutputStream();
981        Properties props = new Properties();
982        props.store(baos, comment1 + '\r' + '\n' + comment2);
983        validateOutput(new String[] { "#comment1", "#comment2" },
984                baos.toByteArray());
985        baos.close();
986    }
987
988    public void testStore_scenario3() throws IOException {
989        ByteArrayOutputStream baos = new ByteArrayOutputStream();
990        Properties props = new Properties();
991        props.store(baos, comment1 + '\n' + '\r' + comment2);
992        validateOutput(new String[] { "#comment1", "#", "#comment2" },
993                baos.toByteArray());
994        baos.close();
995    }
996
997    public void testStore_scenario4() throws IOException {
998        ByteArrayOutputStream baos = new ByteArrayOutputStream();
999        Properties props = new Properties();
1000        props.store(baos, comment1 + '\r' + '#' + comment2);
1001        validateOutput(new String[] { "#comment1", "#comment2" },
1002                baos.toByteArray());
1003        baos.close();
1004    }
1005
1006    public void testStore_scenario5() throws IOException {
1007        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1008        Properties props = new Properties();
1009        props.store(baos, comment1 + '\r' + '!' + comment2);
1010        validateOutput(new String[] { "#comment1", "!comment2" },
1011                baos.toByteArray());
1012        baos.close();
1013    }
1014
1015    public void testStore_scenario6() throws IOException {
1016        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1017        Properties props = new Properties();
1018        props.store(baos, comment1 + '\n' + '#' + comment2);
1019        validateOutput(new String[] { "#comment1", "#comment2" },
1020                baos.toByteArray());
1021        baos.close();
1022    }
1023
1024    public void testStore_scenario7() throws IOException {
1025        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1026        Properties props = new Properties();
1027        props.store(baos, comment1 + '\n' + '!' + comment2);
1028        validateOutput(new String[] { "#comment1", "!comment2" },
1029                baos.toByteArray());
1030        baos.close();
1031    }
1032
1033    public void testStore_scenario8() throws IOException {
1034        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1035        Properties props = new Properties();
1036        props.store(baos, comment1 + '\r' + '\n' + '#' + comment2);
1037        validateOutput(new String[] { "#comment1", "#comment2" },
1038                baos.toByteArray());
1039        baos.close();
1040    }
1041
1042    public void testStore_scenario9() throws IOException {
1043        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1044        Properties props = new Properties();
1045        props.store(baos, comment1 + '\n' + '\r' + '#' + comment2);
1046        validateOutput(new String[] { "#comment1", "#", "#comment2" },
1047                baos.toByteArray());
1048        baos.close();
1049    }
1050
1051    public void testStore_scenario10() throws IOException {
1052        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1053        Properties props = new Properties();
1054        props.store(baos, comment1 + '\r' + '\n' + '!' + comment2);
1055        validateOutput(new String[] { "#comment1", "!comment2" },
1056                baos.toByteArray());
1057        baos.close();
1058    }
1059
1060    public void testStore_scenario11() throws IOException {
1061        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1062        Properties props = new Properties();
1063        props.store(baos, comment1 + '\n' + '\r' + '!' + comment2);
1064        validateOutput(new String[] { "#comment1", "#", "!comment2" },
1065                baos.toByteArray());
1066        baos.close();
1067    }
1068
1069    public void testLoadReader() throws IOException {
1070        InputStream inputStream = new ByteArrayInputStream(
1071                "\u3000key=value".getBytes("UTF-8"));
1072        Properties props = new Properties();
1073        props.load(inputStream);
1074        Enumeration<Object> keyEnum = props.keys();
1075        assertFalse("\u3000key".equals(keyEnum.nextElement()));
1076        assertFalse(keyEnum.hasMoreElements());
1077        inputStream.close();
1078
1079        inputStream = new ByteArrayInputStream(
1080                "\u3000key=value".getBytes("UTF-8"));
1081        props = new Properties();
1082        props.load(new InputStreamReader(inputStream, "UTF-8"));
1083        keyEnum = props.keys();
1084        assertEquals("key", keyEnum.nextElement());
1085        assertFalse(keyEnum.hasMoreElements());
1086        inputStream.close();
1087    }
1088
1089    /**
1090     * Sets up the fixture, for example, open a network connection. This method
1091     * is called before a test is executed.
1092     */
1093    protected void setUp() {
1094
1095        tProps = new Properties();
1096        tProps.put("test.prop", "this is a test property");
1097        tProps.put("bogus.prop", "bogus");
1098    }
1099
1100    /**
1101     * Tears down the fixture, for example, close a network connection. This
1102     * method is called after a test is executed.
1103     */
1104    protected void tearDown() {
1105    }
1106
1107    /**
1108     * Tears down the fixture, for example, close a network connection. This
1109     * method is called after a test is executed.
1110     */
1111    protected byte[] writeProperties() throws IOException {
1112        PrintStream ps = null;
1113        ByteArrayOutputStream bout = new ByteArrayOutputStream();
1114        ps = new PrintStream(bout);
1115        ps.println("#commented.entry=Bogus");
1116        ps.println("test.pkg=harmony.tests");
1117        ps.println("test.proj=Automated Tests");
1118        ps.close();
1119        return bout.toByteArray();
1120    }
1121
1122    protected byte[] writePropertiesXMLUTF_8() throws IOException {
1123        PrintStream ps = null;
1124        ByteArrayOutputStream bout = new ByteArrayOutputStream();
1125        ps = new PrintStream(bout, true, "UTF-8");
1126        ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
1127        ps
1128                .println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
1129        ps.println("<properties>");
1130        ps.println("<comment>comment</comment>");
1131        ps.println("<entry key=\"key4\">value4</entry>");
1132        ps.println("<entry key=\"key3\">value3</entry>");
1133        ps.println("<entry key=\"key2\">value2</entry>");
1134        ps.println("<entry key=\"key1\"><!-- xml comment -->value1</entry>");
1135        ps.println("</properties>");
1136        ps.close();
1137        return bout.toByteArray();
1138    }
1139
1140    protected byte[] writePropertiesXMLISO_8859_1() throws IOException {
1141        PrintStream ps = null;
1142        ByteArrayOutputStream bout = new ByteArrayOutputStream();
1143        ps = new PrintStream(bout, true, "ISO-8859-1");
1144        ps.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
1145        ps
1146                .println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
1147        ps.println("<properties>");
1148        ps.println("<comment>comment</comment>");
1149        ps.println("<entry key=\"key4\">value4</entry>");
1150        ps.println("<entry key=\"key3\">value3</entry>");
1151        ps.println("<entry key=\"key2\">value2</entry>");
1152        ps.println("<entry key=\"key1\"><!-- xml comment -->value1</entry>");
1153        ps.println("</properties>");
1154        ps.close();
1155        return bout.toByteArray();
1156    }
1157}
1158