1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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 */
16
17package libcore.java.util.prefs;
18
19import java.io.ByteArrayInputStream;
20import java.io.ByteArrayOutputStream;
21import java.io.File;
22import java.io.IOException;
23import java.util.prefs.AbstractPreferences;
24import java.util.prefs.BackingStoreException;
25import java.util.prefs.InvalidPreferencesFormatException;
26import java.util.prefs.NodeChangeEvent;
27import java.util.prefs.NodeChangeListener;
28import java.util.prefs.PreferenceChangeEvent;
29import java.util.prefs.PreferenceChangeListener;
30import java.util.prefs.Preferences;
31import java.util.prefs.PreferencesFactory;
32
33import junit.framework.TestCase;
34import libcore.io.IoUtils;
35
36public final class OldAbstractPreferencesTest extends TestCase {
37
38    static final String nodeName = "mock";
39
40    /** Timeout used for Object.wait when no action is expected. */
41    static final long NO_ACTION_EXPECTED_TIMEOUT = 200;
42
43    /** Timeout used for Object.wait when an action is expected. */
44    static final long ACTION_EXPECTED_TIMEOUT = 0; // Wait indefinitely
45
46    private PreferencesFactory defaultFactory;
47
48    AbstractPreferences pref;
49    AbstractPreferences root;
50    AbstractPreferences parent = null;
51
52    protected void setUp() throws Exception {
53        super.setUp();
54
55        File tmpDir = IoUtils.createTemporaryDirectory("OldAbstractPreferencesTest");
56        defaultFactory = Preferences.setPreferencesFactory(
57                new PreferencesTest.TestPreferencesFactory(tmpDir.getAbsolutePath()));
58
59        root = (AbstractPreferences) Preferences.userRoot();
60        assertEquals(0, root.childrenNames().length);
61        assertEquals(0, root.keys().length);
62
63        parent = (AbstractPreferences) Preferences.userNodeForPackage(getClass());
64        pref = (AbstractPreferences) parent.node(nodeName);
65    }
66
67    @Override
68    public void tearDown() throws Exception {
69        Preferences.setPreferencesFactory(defaultFactory);
70        super.tearDown();
71    }
72
73    public void testToString() {
74        assertTrue(pref.toString().contains(nodeName));
75    }
76
77    public void testPut() throws BackingStoreException {
78        pref.put("Value", "String");
79        pref.flush();
80
81        assertEquals("String", pref.get("Value", ":"));
82
83        try {
84            pref.put(null, "Exception");
85            fail("NullPointerException expected");
86        } catch (NullPointerException e) {
87            //expected
88        }
89
90        int i;
91        StringBuffer sb = new StringBuffer();
92
93        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
94            sb.append('c');
95        }
96
97        try {
98            pref.put(new String(sb), "Exception");
99            fail("IllegalArgumentException expected");
100        } catch (IllegalArgumentException e) {
101            //expected
102        }
103
104        sb = new StringBuffer();
105
106        for (i = 0; i < Preferences.MAX_VALUE_LENGTH + 1; i++) {
107            sb.append('c');
108        }
109
110        try {
111            pref.put("DoubleValue", new String(sb));
112            fail("IllegalArgumentException expected");
113        } catch (IllegalArgumentException e) {
114            //expected
115        }
116
117        pref.removeNode();
118
119        try {
120            pref.put("DoubleValue", "Exception");
121            fail("IllegalStateException expected");
122        } catch (IllegalStateException e) {
123            //expected
124        }
125    }
126
127    public void testGet() throws BackingStoreException {
128        pref.put("Value", "String");
129        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
130        pref.putBoolean("BoolValue", true);
131        pref.flush();
132
133        assertEquals("String", pref.get("Value", ":"));
134        assertEquals("true", pref.get("BoolValue", ":"));
135        assertEquals("9.10938188E-31", pref.get("DoubleValue", null));
136
137        try {
138            pref.get(null, "Exception");
139            fail("NullPointerException expected");
140        } catch (NullPointerException e) {
141            //expected
142        }
143
144        pref.removeNode();
145
146        try {
147            pref.get("DoubleValue", "Exception");
148            fail("IllegalStateException expected");
149        } catch (IllegalStateException e) {
150            //expected
151        }
152    }
153
154    public void testRemove() throws BackingStoreException {
155        String[] keyArray = new String[]{"Value", "DoubleValue", "LongValue", "IntValue"};
156        pref.put(keyArray[0], "String");
157        pref.putDouble(keyArray[1], new Double(9.10938188e-31));
158        pref.putLong(keyArray[2], new Long(Long.MIN_VALUE));
159        pref.putInt(keyArray[3], 299792458);
160        pref.node("New node");
161        pref.flush();
162
163        String[] str = pref.keys();
164        assertEquals(keyArray.length, str.length);
165        for(int i = 0; i < keyArray.length; i++) {
166            pref.remove(keyArray[i]);
167            str = pref.keys();
168            assertEquals(keyArray.length - i - 1, str.length);
169        }
170        assertEquals(1, pref.childrenNames().length);
171        pref.remove("New node");
172        assertEquals(1, pref.childrenNames().length);
173
174        pref.removeNode();
175
176        try {
177            pref.remove("New node");
178            fail("IllegalStateException expected");
179        } catch (IllegalStateException e) {
180            //expected
181        }
182    }
183
184    public void testClear() throws BackingStoreException {
185        AbstractPreferences ap = (AbstractPreferences) pref.node("New node");
186        pref.putInt("IntValue", 33);
187        pref.putBoolean("BoolValue", true);
188        pref.flush();
189        assertTrue(pref.getBoolean("BoolValue", false));
190        assertEquals(33, pref.getInt("IntValue", 22));
191        assertEquals(1, pref.childrenNames().length);
192        pref.clear();
193        assertFalse(pref.getBoolean("BoolValue", false));
194        assertEquals(22, pref.getInt("IntValue", 22));
195        assertEquals(1, pref.childrenNames().length);
196
197        pref.removeNode();
198
199        try {
200            pref.clear();
201            fail("IllegalStateException expected");
202        } catch (IllegalStateException e) {
203            //expected
204        }
205
206        try {
207            ap.clear();
208            fail("IllegalStateException expected");
209        } catch (IllegalStateException e) {
210            //expected
211        }
212    }
213
214    public void testPutInt() throws BackingStoreException {
215        pref.putInt("IntValue", 299792458);
216        pref.flush();
217
218        assertEquals(299792458, pref.getInt("IntValue", new Integer(1)));
219
220        try {
221            pref.putInt(null, new Integer(1));
222            fail("NullPointerException expected");
223        } catch (NullPointerException e) {
224            //expected
225        }
226
227        int i;
228        StringBuffer sb = new StringBuffer();
229
230        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
231            sb.append('c');
232        }
233
234        try {
235            pref.putInt(new String(sb), new Integer(1));
236            fail("IllegalArgumentException expected");
237        } catch (IllegalArgumentException e) {
238            //expected
239        }
240
241        pref.removeNode();
242
243        try {
244            pref.putInt("IntValue", new Integer(1));
245            fail("IllegalStateException expected");
246        } catch (IllegalStateException e) {
247            //expected
248        }
249    }
250
251    public void testGetInt() throws BackingStoreException {
252        pref.put("Value", "String");
253        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
254        pref.putLong("LongValue", new Long(Long.MIN_VALUE));
255        pref.putInt("IntValue", 299792458);
256        pref.flush();
257
258        assertEquals(1, pref.getInt("Value", new Integer(1)));
259        assertEquals(1, pref.getInt("LongValue", new Integer(1)));
260        assertEquals(1, pref.getInt("DoubleValue", new Integer(1)));
261        assertEquals(299792458, pref.getInt("IntValue", new Integer(1)));
262
263        try {
264            pref.getInt(null, new Integer(1));
265            fail("NullPointerException expected");
266        } catch (NullPointerException e) {
267            //expected
268        }
269
270        pref.removeNode();
271
272        try {
273            pref.getInt("IntValue", new Integer(1));
274            fail("IllegalStateException expected");
275        } catch (IllegalStateException e) {
276            //expected
277        }
278    }
279
280    public void testPutLong() throws BackingStoreException {
281        pref.putLong("LongValue", new Long(299792458));
282        pref.flush();
283
284        assertEquals(299792458L, pref.getLong("LongValue", new Long(1)));
285
286        try {
287            pref.putLong(null, new Long(1));
288            fail("NullPointerException expected");
289        } catch (NullPointerException e) {
290            //expected
291        }
292
293        int i;
294        StringBuffer sb = new StringBuffer();
295
296        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
297            sb.append('c');
298        }
299
300        try {
301            pref.putLong(new String(sb), new Long(1));
302            fail("IllegalArgumentException expected");
303        } catch (IllegalArgumentException e) {
304            //expected
305        }
306
307        pref.removeNode();
308
309        try {
310            pref.putLong("LongValue", new Long(1));
311            fail("IllegalStateException expected");
312        } catch (IllegalStateException e) {
313            //expected
314        }
315    }
316
317    public void testGetLong() throws BackingStoreException {
318        pref.put("Value", "String");
319        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
320        pref.putLong("LongValue", new Long(Long.MIN_VALUE));
321        pref.putInt("IntValue", 299792458);
322        pref.flush();
323
324        assertEquals(1L, pref.getLong("Value", new Long(1)));
325        assertEquals(Long.MIN_VALUE, pref.getLong("LongValue", new Long(1)));
326        assertEquals(1L, pref.getLong("DoubleValue", new Long(1)));
327        assertEquals(299792458L, pref.getLong("IntValue", new Long(1)));
328
329        try {
330            pref.getLong(null, new Long(1));
331            fail("NullPointerException expected");
332        } catch (NullPointerException e) {
333            //expected
334        }
335
336        pref.removeNode();
337
338        try {
339            pref.getLong("LongValue", new Long(1));
340            fail("IllegalStateException expected");
341        } catch (IllegalStateException e) {
342            //expected
343        }
344    }
345
346    public void testPutBoolean() throws BackingStoreException {
347        pref.putBoolean("BoolValue", true);
348        pref.flush();
349
350        assertTrue(pref.getBoolean("BoolValue", false));
351
352        try {
353            pref.putBoolean(null, true);
354            fail("NullPointerException expected");
355        } catch (NullPointerException e) {
356            //expected
357        }
358
359        int i;
360        StringBuffer sb = new StringBuffer();
361
362        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
363            sb.append('c');
364        }
365
366        try {
367            pref.putBoolean(new String(sb), true);
368            fail("IllegalArgumentException expected");
369        } catch (IllegalArgumentException e) {
370            //expected
371        }
372
373        pref.removeNode();
374
375        try {
376            pref.putBoolean("DoubleValue", true);
377            fail("IllegalStateException expected");
378        } catch (IllegalStateException e) {
379            //expected
380        }
381    }
382
383    public void testGetBoolean() throws BackingStoreException {
384        pref.put("Value", "String");
385        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
386        pref.putBoolean("BoolValue", true);
387        pref.flush();
388
389        assertFalse(pref.getBoolean("Value", false));
390        assertTrue(pref.getBoolean("BoolValue", false));
391        assertFalse(pref.getBoolean("DoubleValue", false));
392
393        try {
394            pref.getBoolean(null, true);
395            fail("NullPointerException expected");
396        } catch (NullPointerException e) {
397            //expected
398        }
399
400        pref.removeNode();
401
402        try {
403            pref.getBoolean("DoubleValue", true);
404            fail("IllegalStateException expected");
405        } catch (IllegalStateException e) {
406            //expected
407        }
408    }
409
410    public void testPutFloat() throws BackingStoreException {
411        pref.putFloat("FloatValue", new Float(1.602e-19));
412        pref.flush();
413
414        assertEquals(new Float(1.602e-19), pref.getFloat("FloatValue", new Float(0.2)));
415
416        try {
417            pref.putFloat(null, new Float(0.1));
418            fail("NullPointerException expected");
419        } catch (NullPointerException e) {
420            //expected
421        }
422
423        int i;
424        StringBuffer sb = new StringBuffer();
425
426        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
427            sb.append('c');
428        }
429
430        try {
431            pref.putFloat(new String(sb), new Float(0.1));
432            fail("IllegalArgumentException expected");
433        } catch (IllegalArgumentException e) {
434            //expected
435        }
436
437        pref.removeNode();
438
439        try {
440            pref.putFloat("FloatValue", new Float(0.1));
441            fail("IllegalStateException expected");
442        } catch (IllegalStateException e) {
443            //expected
444        }
445    }
446
447    public void testGetFloat() throws BackingStoreException {
448        pref.put("Value", "String");
449        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
450        pref.putFloat("FloatValue", new Float(-0.123));
451        pref.putInt("IntValue", 299792458);
452        pref.flush();
453
454        assertEquals(new Float(0.1), pref.getFloat("Value", new Float(0.1)));
455        assertEquals(new Float(-0.123), pref.getFloat("FloatValue", new Float(0.2)));
456        assertEquals(new Float(9.109382e-31), pref.getFloat("DoubleValue", new Float(2.14)));
457        assertEquals(new Float(2.99792448e8), pref.getFloat("IntValue", new Float(5)));
458
459        try {
460            pref.getFloat(null, new Float(0.1));
461            fail("NullPointerException expected");
462        } catch (NullPointerException e) {
463            //expected
464        }
465
466        pref.removeNode();
467
468        try {
469            pref.getFloat("FloatValue", new Float(0.1));
470            fail("IllegalStateException expected");
471        } catch (IllegalStateException e) {
472            //expected
473        }
474    }
475
476    public void testPutDouble() throws BackingStoreException {
477        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
478        pref.flush();
479
480        assertEquals(new Double(9.10938188e-31), pref.getDouble("DoubleValue", new Double(2.14)));
481
482        try {
483            pref.putDouble(null, new Double(0.1));
484            fail("NullPointerException expected");
485        } catch (NullPointerException e) {
486            //expected
487        }
488
489        int i;
490        StringBuffer sb = new StringBuffer();
491
492        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
493            sb.append('c');
494        }
495
496        try {
497            pref.putDouble(new String(sb), new Double(0.1));
498            fail("IllegalArgumentException expected");
499        } catch (IllegalArgumentException e) {
500            //expected
501        }
502
503        pref.removeNode();
504
505        try {
506            pref.putDouble("DoubleValue", new Double(0.1));
507            fail("IllegalStateException expected");
508        } catch (IllegalStateException e) {
509            //expected
510        }
511    }
512
513    public void testGetDouble() throws BackingStoreException {
514        pref.put("Value", "String");
515        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
516        pref.putBoolean("BoolValue", true);
517        pref.putInt("IntValue", 299792458);
518        pref.flush();
519
520        assertEquals(new Double(0.1), pref.getDouble("Value", new Double(0.1)));
521        assertEquals(new Double(0.2), pref.getDouble("BoolValue", new Double(0.2)));
522        assertEquals(new Double(9.10938188e-31), pref.getDouble("DoubleValue", new Double(2.14)));
523        assertEquals(new Double(2.99792458e8), pref.getDouble("IntValue", new Double(5)));
524
525        try {
526            pref.getDouble(null, new Double(0.1));
527            fail("NullPointerException expected");
528        } catch (NullPointerException e) {
529            //expected
530        }
531
532        pref.removeNode();
533
534        try {
535            pref.getDouble("DoubleValue", new Double(0.1));
536            fail("IllegalStateException expected");
537        } catch (IllegalStateException e) {
538            //expected
539        }
540    }
541
542    public void testPutByteArray() throws BackingStoreException {
543        byte[] bArray = new byte[]{1, 2, 3, 4, 5};
544        byte[] array  = null;
545        int i;
546        pref.putByteArray("Array", bArray);
547        pref.flush();
548
549        array = pref.getByteArray("Array", null);
550        assertEquals(bArray.length, array.length);
551        for(i = 0; i < bArray.length; i++) {
552            assertEquals(bArray[i], array[i]);
553        }
554
555        try {
556            pref.putByteArray(null, bArray);
557            fail("NullPointerException expected");
558        } catch (NullPointerException e) {
559            //expected
560        }
561
562        StringBuffer sb = new StringBuffer();
563
564        for (i = 0; i < Preferences.MAX_KEY_LENGTH + 1; i++) {
565            sb.append('c');
566        }
567
568        try {
569            pref.putByteArray(new String(sb), bArray);
570            fail("IllegalArgumentException expected");
571        } catch (IllegalArgumentException e) {
572            //expected
573        }
574
575        bArray = new byte[Preferences.MAX_VALUE_LENGTH * 3 / 4 + 1];
576
577        try {
578            pref.putByteArray("Big array", bArray);
579            fail("IllegalArgumentException expected");
580        } catch (IllegalArgumentException e) {
581            //expected
582        }
583
584        pref.removeNode();
585
586        try {
587            pref.putByteArray("Array", new byte[10]);
588            fail("IllegalStateException expected");
589        } catch (IllegalStateException e) {
590            //expected
591        }
592    }
593
594    public void testGetByteArray() throws BackingStoreException {
595        byte[] bArray = new byte[]{1, 2, 3, 4, 5};
596        byte[] tmp    = new byte[]{5};
597        byte[] array  = null;
598        int i;
599        pref.put("Value", "String");
600        pref.putDouble("DoubleValue", new Double(9.10938188e-31));
601        pref.putByteArray("Array", bArray);
602        pref.flush();
603
604        array = pref.getByteArray("Value", tmp);
605        assertEquals(tmp.length, array.length);
606        for(i = 0; i < tmp.length; i++) {
607            assertEquals(tmp[i], array[i]);
608        }
609
610        array = pref.getByteArray("DoubleValue", tmp);
611        assertEquals(tmp.length, array.length);
612        for(i = 0; i < tmp.length; i++) {
613            assertEquals(tmp[i], array[i]);
614        }
615
616        array = pref.getByteArray("Array", tmp);
617        assertEquals(bArray.length, array.length);
618        for(i = 0; i < bArray.length; i++) {
619            assertEquals(bArray[i], array[i]);
620        }
621
622        try {
623            pref.getByteArray(null, tmp);
624            fail("NullPointerException expected");
625        } catch (NullPointerException e) {
626            //expected
627        }
628
629        pref.removeNode();
630
631        try {
632            pref.getByteArray("Array", tmp);
633            fail("IllegalStateException expected");
634        } catch (IllegalStateException e) {
635            //expected
636        }
637    }
638
639    public void testKeys() throws BackingStoreException {
640        String[] keyArray = new String[]{"Value", "DoubleValue", "BoolValue", "IntValue"};
641        String nodeStr = "New node";
642        pref.node(nodeStr);
643        pref.put(keyArray[0], "String");
644        pref.putDouble(keyArray[1], new Double(9.10938188e-31));
645        pref.putBoolean(keyArray[2], true);
646        pref.putInt(keyArray[3], 299792458);
647        pref.flush();
648
649        String[] str = pref.keys();
650        assertEquals(keyArray.length, str.length);
651        for(int i = 0; i < str.length; i++) {
652            boolean flag = false;
653            for(int j = 0; j < keyArray.length; j++) {
654                if (str[i].compareTo(keyArray[j]) == 0) {
655                    flag = true;
656                    break;
657                }
658            }
659            assertTrue(str[i].compareTo(nodeStr) != 0);
660            assertTrue(flag);
661        }
662
663        pref.removeNode();
664
665        try {
666            pref.keys();
667            fail("IllegalStateException expected");
668        } catch(IllegalStateException e) {
669            //expected
670        }
671    }
672
673    public void testChildrenNames() throws BackingStoreException {
674        AbstractPreferences first = (AbstractPreferences) pref.node("First node");
675        AbstractPreferences second = (AbstractPreferences) pref.node("Second node");
676
677        assertEquals(2, pref.childrenNames().length);
678        assertEquals(0, first.childrenNames().length);
679        assertEquals(0, second.childrenNames().length);
680
681        second.removeNode();
682
683        try {
684            second.childrenNames();
685            fail("IllegalStateException expected");
686        } catch (IllegalStateException e) {
687            //expected
688        }
689
690        pref.removeNode();
691
692        try {
693            first.childrenNames();
694            fail("IllegalStateException expected");
695        } catch (IllegalStateException e) {
696            //expected
697        }
698    }
699
700    public void test_nodeExists() throws BackingStoreException {
701        AbstractPreferences test = (AbstractPreferences) Preferences.userRoot()
702                .node("test");
703        try {
704            test.nodeExists(null);
705            fail("should throw NullPointerException");
706        } catch (NullPointerException e) {
707            // Expected
708        }
709
710        test.removeNode();
711        try {
712            test.nodeExists(null);
713            fail("should throw NullPointerException");
714        } catch (NullPointerException e) {
715            // Expected
716        }
717    }
718
719    public void testParent() throws BackingStoreException {
720        AbstractPreferences node = (AbstractPreferences) pref.node("First node/sub node");
721
722        assertTrue(node.parent().name().compareTo("First node") == 0);
723
724        pref.removeNode();
725
726        try {
727            node.parent();
728            fail("IllegalStateException expected");
729        } catch (IllegalStateException e) {
730            //expected
731        }
732    }
733
734    public void testNode() throws BackingStoreException {
735        AbstractPreferences first = (AbstractPreferences) pref.node("First node");
736        AbstractPreferences second = (AbstractPreferences) pref.node("Second node");
737
738        try {
739            first.node("blabla/");
740            fail("IllegalArgumentException expected");
741        } catch (IllegalArgumentException e) {
742            //expected
743        }
744
745        try {
746            first.node("///invalid");
747            fail("IllegalArgumentException expected");
748        } catch (IllegalArgumentException e) {
749            //expected
750        }
751
752        StringBuffer sb = new StringBuffer();
753
754        for (int i = 0; i < Preferences.MAX_NAME_LENGTH; i++) {
755            sb.append('c');
756        }
757        first.node(new String(sb));
758        sb.append('c');
759
760        try {
761            first.node(new String(sb));
762            fail("IllegalArgumentException expected");
763        } catch (IllegalArgumentException e) {
764            //expected
765        }
766
767        second.removeNode();
768
769        try {
770            second.node("");
771            fail("IllegalStateException expected");
772        } catch (IllegalStateException e) {
773            //expected
774        }
775        pref.removeNode();
776        try {
777            first.node("");
778            fail("IllegalStateException expected");
779        } catch (IllegalStateException e) {
780            //expected
781        }
782    }
783
784    public void testNodeExists() throws BackingStoreException {
785        AbstractPreferences ap1 = (AbstractPreferences) pref.node("First node");
786        AbstractPreferences ap2 = (AbstractPreferences) pref.node("Second node");
787        pref.putInt("IntegerValue", 33);
788        pref.putBoolean("BoolValue", true);
789        pref.flush();
790
791        assertTrue(pref.nodeExists("First node"));
792        assertTrue(pref.nodeExists("Second node"));
793        assertFalse(pref.nodeExists("IntegerValue"));
794        assertFalse(pref.nodeExists("BoolValue"));
795        assertFalse(pref.nodeExists("Value"));
796        assertFalse(pref.nodeExists(nodeName));
797
798        try {
799            pref.nodeExists("///invalid");
800            fail("IllegalArgumentException expected");
801        } catch (IllegalArgumentException e) {
802            //expected
803        }
804
805        pref.removeNode();
806
807        try {
808            pref.nodeExists("Exception");
809            fail("IllegalStateException expected");
810        } catch (IllegalStateException e) {
811            //expected
812        }
813    }
814
815    public void testRemoveNode() throws BackingStoreException {
816        String[] nodeArray = new String[]{"First node", "Second node", "Last node"};
817        int i;
818        pref.put("Key", "String");
819        for (i = 0; i < nodeArray.length; i++) {
820            pref.node(nodeArray[i]);
821        }
822        pref.flush();
823
824        String[] str = pref.childrenNames();
825        assertEquals(nodeArray.length, str.length);
826        for(i = 0; i < nodeArray.length; i++) {
827            pref.node(nodeArray[i]).removeNode();
828            str = pref.childrenNames();
829            assertEquals(nodeArray.length - i - 1, str.length);
830        }
831        assertEquals(1, pref.keys().length);
832        pref.node("Key").removeNode();
833        assertEquals(1, pref.keys().length);
834
835        pref.removeNode();
836
837        try {
838            pref.removeNode();
839            fail("IllegalStateException expected");
840        } catch (IllegalStateException e) {
841            //expected
842        }
843
844        try {
845            root.removeNode();
846            fail("UnsupportedOperationException expected");
847        } catch (UnsupportedOperationException e) {
848            //expected
849        }
850    }
851
852    public void testName() {
853        AbstractPreferences first = (AbstractPreferences) pref.node("First node");
854        AbstractPreferences second = (AbstractPreferences) pref.node("Second node/sub node");
855
856        assertTrue(first.name().compareTo("First node") == 0);
857        assertFalse(first.name().compareTo("Second node") == 0);
858        assertTrue(second.name().compareTo("sub node") == 0);
859    }
860
861    public void testAbsolutePath() {
862        assertEquals(parent.absolutePath() + "/" + nodeName, pref.absolutePath());
863        assertEquals(parent.absolutePath() + "/" + "new node", parent.node("new node").absolutePath());
864    }
865
866    public void testIsUserNode() {
867        assertTrue(parent.isUserNode());
868        assertFalse(Preferences.systemRoot().isUserNode());
869    }
870
871    public void testSync() throws BackingStoreException {
872        pref.node("new node/sub node");
873        pref.sync();
874
875        pref.removeNode();
876
877        try {
878            pref.sync();
879            fail("IllegalStateException expected");
880        } catch (IllegalStateException e) {
881            //expected
882        }
883    }
884
885    class MockPreferenceChangeListener implements PreferenceChangeListener {
886        private boolean flagChange = false;
887
888        public synchronized void preferenceChange(PreferenceChangeEvent arg0) {
889            flagChange = true;
890            notifyAll();
891        }
892
893        public synchronized void assertChanged(boolean expected) throws InterruptedException {
894            if (!flagChange) {
895              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
896            }
897            assertEquals(expected, flagChange);
898            flagChange = false;
899        }
900    }
901
902    public void testAddPreferenceChangeListener() throws Exception {
903        MockPreferenceChangeListener mpcl = new MockPreferenceChangeListener();
904        parent.addPreferenceChangeListener(mpcl);
905        mpcl.assertChanged(false);
906        pref.node("new node");
907        mpcl.assertChanged(false);
908        parent.node("new node");
909        mpcl.assertChanged(false);
910        parent.putInt("IntValue", 33);
911        mpcl.assertChanged(true);
912        assertEquals(33, parent.getInt("IntValue", 22));
913        mpcl.assertChanged(false);
914        assertEquals(22, parent.getInt("Missed Value", 22));
915        mpcl.assertChanged(false);
916    }
917
918    public void testRemovePreferenceChangeListener() throws Exception {
919        MockPreferenceChangeListener mpcl = new MockPreferenceChangeListener();
920        parent.addPreferenceChangeListener(mpcl);
921        mpcl.assertChanged(false);
922        parent.putInt("IntValue", 33);
923        mpcl.assertChanged(true);
924        parent.removePreferenceChangeListener(mpcl);
925        parent.putInt("IntValue", 33);
926        mpcl.assertChanged(false);
927    }
928
929    class MockNodeChangeListener implements NodeChangeListener {
930        private boolean flagAdded = false;
931        private boolean flagRemoved = false;
932
933        public synchronized void childAdded(NodeChangeEvent arg0) {
934            flagAdded = true;
935            notifyAll();
936        }
937
938        public synchronized void childRemoved(NodeChangeEvent arg0) {
939            flagRemoved = true;
940            notifyAll();
941        }
942
943        public synchronized void assertAdded(boolean expected) throws InterruptedException {
944            if (!flagAdded) {
945              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
946            }
947            assertEquals(expected, flagAdded);
948        }
949
950        public synchronized void assertRemoved(boolean expected) throws InterruptedException {
951            if (!flagRemoved) {
952              wait(expected ? ACTION_EXPECTED_TIMEOUT : NO_ACTION_EXPECTED_TIMEOUT);
953            }
954            assertEquals(expected, flagRemoved);
955        }
956    }
957
958    public void testAddNodeChangeListener() throws Exception {
959        MockNodeChangeListener mncl = new MockNodeChangeListener();
960        parent.addNodeChangeListener(mncl);
961        pref.node("test");
962        mncl.assertAdded(false);
963        mncl.assertRemoved(false);
964        pref.removeNode();
965        mncl.assertAdded(false);
966        mncl.assertRemoved(true);
967        parent.node("new node");
968        mncl.assertAdded(true);
969        mncl.assertRemoved(true);
970    }
971
972    public void testRemoveNodeChangeListener() throws BackingStoreException, InterruptedException {
973        MockNodeChangeListener mncl = new MockNodeChangeListener();
974        parent.addNodeChangeListener(mncl);
975        pref.node("test");
976        mncl.assertAdded(false);
977        mncl.assertRemoved(false);
978        parent.removeNodeChangeListener(mncl);
979        pref.removeNode();
980        mncl.assertAdded(false);
981        mncl.assertRemoved(false);
982        parent.node("new node");
983        mncl.assertAdded(false);
984        mncl.assertRemoved(false);
985    }
986
987    public void testExportNode() throws BackingStoreException, IOException, InvalidPreferencesFormatException {
988        AbstractPreferences ap = (AbstractPreferences) pref.node("New node");
989        pref.putInt("IntValue", 33);
990        pref.putBoolean("BoolValue", true);
991        pref.flush();
992
993        ByteArrayOutputStream baos = new ByteArrayOutputStream();
994
995        pref.exportNode(baos);
996        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
997
998        assertTrue(pref.getBoolean("BoolValue", false));
999        assertEquals(33, pref.getInt("IntValue", 22));
1000        assertEquals(1, pref.childrenNames().length);
1001
1002        String xmlData = new String(baos.toByteArray());
1003
1004        assertTrue(xmlData.contains("IntValue"));
1005        assertTrue(xmlData.contains("BoolValue"));
1006        assertTrue(xmlData.contains("33"));
1007        assertTrue(xmlData.contains("true"));
1008
1009        pref.removeNode();
1010
1011        try {
1012            pref.exportNode(new ByteArrayOutputStream());
1013            fail("IllegalStateException expected");
1014        } catch (IllegalStateException e) {
1015            //expected
1016        }
1017
1018        try {
1019            pref.getBoolean("BoolValue", false);
1020            fail("IllegalStateException expected");
1021        } catch (IllegalStateException e) {
1022            //expected
1023        }
1024        pref = (AbstractPreferences) parent.node(nodeName);
1025
1026        pref.importPreferences(bais);
1027
1028        assertTrue(pref.getBoolean("BoolValue", false));
1029        assertEquals(33, pref.getInt("IntValue", 22));
1030        assertEquals(0, pref.childrenNames().length);
1031    }
1032
1033    public void testExportSubtree() throws BackingStoreException, IOException, InvalidPreferencesFormatException {
1034        AbstractPreferences ap1 = (AbstractPreferences) pref.node("First node");
1035        AbstractPreferences ap2 = (AbstractPreferences) pref.node("Second node");
1036        pref.putInt("IntegerValue", 33);
1037        pref.putBoolean("BoolValue", true);
1038        pref.flush();
1039
1040        ap1.putInt("FirstIntValue", 11);
1041        ap2.putDouble("DoubleValue", new Double(6.626e-34));
1042
1043        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1044
1045        pref.exportSubtree(baos);
1046        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
1047
1048        assertTrue(pref.getBoolean("BoolValue", false));
1049        assertEquals(33, pref.getInt("IntegerValue", 22));
1050        assertEquals(2, pref.childrenNames().length);
1051        assertEquals(11, ap1.getInt("FirstIntValue", 22));
1052        assertEquals(new Double(6.626e-34), ap2.getDouble("DoubleValue", new Double (3.14)));
1053
1054        String xmlData = new String(baos.toByteArray());
1055
1056        assertTrue(xmlData.contains("IntegerValue"));
1057        assertTrue(xmlData.contains("BoolValue"));
1058        assertTrue(xmlData.contains("FirstIntValue"));
1059        assertTrue(xmlData.contains("DoubleValue"));
1060        assertTrue(xmlData.contains("33"));
1061        assertTrue(xmlData.contains("true"));
1062        assertTrue(xmlData.contains("11"));
1063        assertTrue(xmlData.contains("6.626E-34"));
1064
1065        pref.removeNode();
1066
1067        try {
1068            pref.exportSubtree(new ByteArrayOutputStream());
1069            fail("IllegalStateException expected");
1070        } catch (IllegalStateException e) {
1071            //expected
1072        }
1073
1074        try {
1075            pref.getBoolean("BoolValue", false);
1076            fail("IllegalStateException expected");
1077        } catch (IllegalStateException e) {
1078            //expected
1079        }
1080        pref = (AbstractPreferences) parent.node(nodeName);
1081        pref.importPreferences(bais);
1082
1083        ap1 = (AbstractPreferences) pref.node("First node");
1084        ap2 = (AbstractPreferences) pref.node("Second node");
1085
1086        assertTrue(pref.getBoolean("BoolValue", false));
1087        assertEquals(33, pref.getInt("IntegerValue", 22));
1088        assertEquals(2, pref.childrenNames().length);
1089        assertEquals(11, ap1.getInt("FirstIntValue", 22));
1090        assertEquals(new Double(6.626e-34), ap2.getDouble("DoubleValue", new Double (3.14)));
1091    }
1092
1093    class MockAbstractPreferences extends AbstractPreferences {
1094        protected MockAbstractPreferences(AbstractPreferences parent, String name) {
1095            super(parent, name);
1096        }
1097
1098        @Override
1099        protected AbstractPreferences childSpi(String name) {
1100            return null;
1101        }
1102
1103        @Override
1104        protected String[] childrenNamesSpi() throws BackingStoreException {
1105            return null;
1106        }
1107
1108        @Override
1109        protected void flushSpi() throws BackingStoreException {
1110        }
1111
1112        @Override
1113        protected String getSpi(String key) {
1114            return null;
1115        }
1116
1117        @Override
1118        protected String[] keysSpi() throws BackingStoreException {
1119            return null;
1120        }
1121
1122        @Override
1123        protected void putSpi(String key, String value) {
1124        }
1125
1126        @Override
1127        protected void removeNodeSpi() throws BackingStoreException {
1128        }
1129
1130        @Override
1131        protected void removeSpi(String key) {
1132        }
1133
1134        @Override
1135        protected void syncSpi() throws BackingStoreException {
1136        }
1137    }
1138
1139    public void testAbstractPreferences() {
1140        assertNotNull(new MockAbstractPreferences(pref, "node name"));
1141        try {
1142            new MockAbstractPreferences(pref, "node/name");
1143            fail("IllegalArgumentException expected");
1144        } catch (IllegalArgumentException e) {
1145            //expected
1146        }
1147
1148        try {
1149            new MockAbstractPreferences(null, "node");
1150            fail("IllegalArgumentException expected");
1151        } catch (IllegalArgumentException e) {
1152            //expected
1153        }
1154    }
1155
1156    public void testCachedChildren() throws BackingStoreException {
1157        pref.node("First node");
1158        pref.node("Second node");
1159
1160        assertEquals(2, pref.childrenNames().length);
1161    }
1162}
1163