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  */
16 
17 package libcore.java.util.prefs;
18 
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.util.Arrays;
23 import java.util.prefs.BackingStoreException;
24 import java.util.prefs.NodeChangeEvent;
25 import java.util.prefs.NodeChangeListener;
26 import java.util.prefs.PreferenceChangeEvent;
27 import java.util.prefs.PreferenceChangeListener;
28 import java.util.prefs.Preferences;
29 import java.util.prefs.PreferencesFactory;
30 import junit.framework.TestCase;
31 
32 import libcore.testing.io.TestIoUtils;
33 
34 public final class OldPreferencesTest extends TestCase {
35 
36     private static final boolean ENCOURAGE_RACES = false;
37 
38     private static final String longKey;
39     private static final String longValue;
40 
41     static {
42         StringBuilder key = new StringBuilder(Preferences.MAX_KEY_LENGTH);
43         for (int i = 0; i < Preferences.MAX_KEY_LENGTH; i++) {
44             key.append('a');
45         }
46         longKey = key.toString();
47 
48         StringBuilder value = new StringBuilder(Preferences.MAX_VALUE_LENGTH);
49         for (int i = 0; i < Preferences.MAX_VALUE_LENGTH; i++) {
50             value.append('a');
51         }
52         longValue = value.toString();
53     }
54 
55     private PreferencesFactory defaultFactory;
56 
57     @Override
setUp()58     protected void setUp() throws Exception {
59         super.setUp();
60         final File tmpDir = TestIoUtils.createTemporaryDirectory("OldPreferenceTest");
61         defaultFactory = Preferences.setPreferencesFactory(
62                 new PreferencesTest.TestPreferencesFactory(tmpDir.getAbsolutePath()));
63 
64         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
65         for (String child : pref.childrenNames()) {
66             pref.node(child).removeNode();
67         }
68         pref.clear();
69     }
70 
71     @Override
tearDown()72     protected void tearDown() throws Exception {
73         Preferences.setPreferencesFactory(defaultFactory);
74     }
75 
testAbstractMethods()76     public void testAbstractMethods() throws IOException, BackingStoreException {
77         Preferences p = new MockPreferences();
78         p.absolutePath();
79         p.childrenNames();
80         p.clear();
81         p.exportNode(null);
82         p.exportSubtree(null);
83         p.flush();
84         p.get(null, null);
85         p.getBoolean(null, false);
86         p.getByteArray(null, null);
87         p.getFloat(null, 0.1f);
88         p.getDouble(null, 0.1);
89         p.getInt(null, 1);
90         p.getLong(null, 1l);
91         p.isUserNode();
92         p.keys();
93         p.name();
94         p.node(null);
95         p.nodeExists(null);
96         p.parent();
97         p.put(null, null);
98         p.putBoolean(null, false);
99         p.putByteArray(null, null);
100         p.putDouble(null, 1);
101         p.putFloat(null, 1f);
102         p.putInt(null, 1);
103         p.putLong(null, 1l);
104         p.remove(null);
105         p.removeNode();
106         p.addNodeChangeListener(null);
107         p.addPreferenceChangeListener(null);
108         p.removeNodeChangeListener(null);
109         p.removePreferenceChangeListener(null);
110         p.sync();
111         p.toString();
112     }
113 
testConstructor()114     public void testConstructor() {
115         MockPreferences mp = new MockPreferences();
116         assertEquals(mp.getClass(), MockPreferences.class);
117     }
118 
testToString()119     public void testToString() {
120         Preferences p1 = Preferences.userNodeForPackage(Preferences.class);
121         assertNotNull(p1.toString());
122 
123         Preferences p2 = Preferences.systemRoot();
124         assertNotNull(p2.toString());
125 
126         Preferences p3 = Preferences.userRoot();
127         assertNotNull(p3.toString());
128     }
129 
testAbsolutePath()130     public void testAbsolutePath() {
131         Preferences p = Preferences.userNodeForPackage(Preferences.class);
132         assertEquals("/java/util/prefs", p.absolutePath());
133 
134     }
135 
testChildrenNames()136     public void testChildrenNames() throws BackingStoreException {
137         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
138 
139         Preferences child1 = pref.node("child1");
140 
141         pref.node("child2");
142         pref.node("child3");
143         child1.node("subchild1");
144 
145         assertSame(pref, child1.parent());
146         assertEquals(3, pref.childrenNames().length);
147         assertEquals("child1", pref.childrenNames()[0]);
148         assertEquals(1, child1.childrenNames().length);
149         assertEquals("subchild1", child1.childrenNames()[0]);
150     }
151 
testClear()152     public void testClear() throws BackingStoreException {
153         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
154         pref.put("testClearKey", "testClearValue");
155         pref.put("testClearKey1", "testClearValue1");
156         assertEquals("testClearValue", pref.get("testClearKey", null));
157         assertEquals("testClearValue1", pref.get("testClearKey1", null));
158         pref.clear();
159         assertNull(pref.get("testClearKey", null));
160         assertNull(pref.get("testClearKey1", null));
161     }
162 
testGet()163     public void testGet() throws BackingStoreException {
164         Preferences root = Preferences.userNodeForPackage(Preferences.class);
165         Preferences pref = root.node("mock");
166         assertNull(pref.get("", null));
167         assertEquals("default", pref.get("key", "default"));
168         assertNull(pref.get("key", null));
169         pref.put("testGetkey", "value");
170         assertNull(pref.get("testGetKey", null));
171         assertEquals("value", pref.get("testGetkey", null));
172 
173         try {
174             pref.get(null, "abc");
175             fail();
176         } catch (NullPointerException expected) {
177         }
178         pref.get("", "abc");
179         pref.get("key", null);
180         pref.get("key", "");
181         pref.putFloat("floatKey", 1.0f);
182         assertEquals("1.0", pref.get("floatKey", null));
183 
184         pref.removeNode();
185         try {
186             pref.get("key", "abc");
187             fail();
188         } catch (IllegalStateException expected) {
189         }
190         try {
191             pref.get(null, "abc");
192             fail();
193         } catch (NullPointerException expected) {
194         }
195     }
196 
testGetBoolean()197     public void testGetBoolean() {
198         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
199         try {
200             pref.getBoolean(null, false);
201             fail();
202         } catch (NullPointerException expected) {
203         }
204 
205         pref.put("testGetBooleanKey", "false");
206         pref.put("testGetBooleanKey2", "value");
207         assertFalse(pref.getBoolean("testGetBooleanKey", true));
208         assertTrue(pref.getBoolean("testGetBooleanKey2", true));
209     }
210 
testGetByteArray()211     public void testGetByteArray() {
212         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
213         try {
214             pref.getByteArray(null, new byte[0]);
215             fail();
216         } catch (NullPointerException expected) {
217         }
218         byte[] b64Array = new byte[] { 0x59, 0x57, 0x4a, 0x6a };// BASE64
219 
220         pref.put("testGetByteArrayKey", "abc=");
221         pref.put("testGetByteArrayKey2", new String(b64Array));
222         pref.put("invalidKey", "<>?");
223         assertTrue(Arrays.equals(new byte[] { 105, -73 }, pref.getByteArray(
224                 "testGetByteArrayKey", new byte[0])));
225         assertTrue(Arrays.equals(new byte[] { 'a', 'b', 'c' }, pref
226                 .getByteArray("testGetByteArrayKey2", new byte[0])));
227         assertTrue(Arrays.equals(new byte[0], pref.getByteArray("invalidKey",
228                 new byte[0])));
229 
230         pref.putByteArray("testGetByteArrayKey3", b64Array);
231         pref.putByteArray("testGetByteArrayKey4", "abc".getBytes());
232         assertTrue(Arrays.equals(b64Array, pref.getByteArray(
233                 "testGetByteArrayKey3", new byte[0])));
234         assertTrue(Arrays.equals("abc".getBytes(), pref.getByteArray(
235                 "testGetByteArrayKey4", new byte[0])));
236     }
237 
testGetDouble()238     public void testGetDouble() {
239         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
240         try {
241             pref.getDouble(null, 0);
242             fail();
243         } catch (NullPointerException expected) {
244         }
245 
246         pref.put("testGetDoubleKey", "1");
247         pref.put("testGetDoubleKey2", "value");
248         pref.putDouble("testGetDoubleKey3", 1);
249         pref.putInt("testGetDoubleKey4", 1);
250         assertEquals(1.0, pref.getDouble("testGetDoubleKey", 0.0), 0);
251         assertEquals(0.0, pref.getDouble("testGetDoubleKey2", 0.0), 0);
252         assertEquals(1.0, pref.getDouble("testGetDoubleKey3", 0.0), 0);
253         assertEquals(1.0, pref.getDouble("testGetDoubleKey4", 0.0), 0);
254     }
255 
testGetFloat()256     public void testGetFloat() {
257         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
258         try {
259             pref.getFloat(null, 0f);
260             fail();
261         } catch (NullPointerException expected) {
262         }
263         pref.put("testGetFloatKey", "1");
264         pref.put("testGetFloatKey2", "value");
265         assertEquals(1f, pref.getFloat("testGetFloatKey", 0f), 0);
266         assertEquals(0f, pref.getFloat("testGetFloatKey2", 0f), 0);
267     }
268 
testGetInt()269     public void testGetInt() {
270         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
271         try {
272             pref.getInt(null, 0);
273             fail();
274         } catch (NullPointerException expected) {
275         }
276 
277         pref.put("testGetIntKey", "1");
278         pref.put("testGetIntKey2", "value");
279         assertEquals(1, pref.getInt("testGetIntKey", 0));
280         assertEquals(0, pref.getInt("testGetIntKey2", 0));
281     }
282 
testGetLong()283     public void testGetLong() {
284         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
285         try {
286             pref.getLong(null, 0);
287             fail();
288         } catch (NullPointerException expected) {
289         }
290 
291         pref.put("testGetLongKey", "1");
292         pref.put("testGetLongKey2", "value");
293         assertEquals(1, pref.getInt("testGetLongKey", 0));
294         assertEquals(0, pref.getInt("testGetLongKey2", 0));
295     }
296 
testIsUserNode()297     public void testIsUserNode() {
298         Preferences pref1 = Preferences.userNodeForPackage(Preferences.class);
299         assertTrue(pref1.isUserNode());
300 
301         Preferences pref2 = Preferences.systemNodeForPackage(Preferences.class);
302         assertFalse(pref2.isUserNode());
303     }
304 
testKeys()305     public void testKeys() throws BackingStoreException {
306         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
307         pref.clear();
308 
309         pref.put("key0", "value");
310         pref.put("key1", "value1");
311         pref.put("key2", "value2");
312         pref.put("key3", "value3");
313 
314         String[] keys = pref.keys();
315         assertEquals(4, keys.length);
316         for (String key : keys) {
317             assertEquals(0, key.indexOf("key"));
318             assertEquals(4, key.length());
319         }
320     }
321 
testName()322     public void testName() {
323         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
324         Preferences child = pref.node("mock");
325         assertEquals("mock", child.name());
326     }
327 
testNode()328     public void testNode() throws BackingStoreException {
329         StringBuilder name = new StringBuilder(Preferences.MAX_NAME_LENGTH);
330         for (int i = 0; i < Preferences.MAX_NAME_LENGTH; i++) {
331             name.append('a');
332         }
333         String longName = name.toString();
334 
335         Preferences root = Preferences.userRoot();
336         Preferences parent = Preferences.userNodeForPackage(Preferences.class);
337         Preferences pref = parent.node("mock");
338 
339         try {
340             pref.node(null);
341             fail();
342         } catch (NullPointerException expected) {
343         }
344         try {
345             pref.node("/java/util/prefs/");
346             fail();
347         } catch (IllegalArgumentException expected) {
348         }
349         try {
350             pref.node("/java//util/prefs");
351             fail();
352         } catch (IllegalArgumentException expected) {
353         }
354         try {
355             pref.node(longName + "a");
356             fail();
357         } catch (IllegalArgumentException expected) {
358         }
359         assertNotNull(pref.node(longName));
360 
361         assertSame(root, pref.node("/"));
362 
363         Preferences prefs = pref.node("/java/util/prefs");
364         assertSame(prefs, parent);
365 
366         assertSame(pref, pref.node(""));
367     }
368 
testNodeExists()369     public void testNodeExists() throws BackingStoreException {
370 
371         Preferences parent = Preferences.userNodeForPackage(Preferences.class);
372         Preferences pref = parent.node("mock");
373 
374         try {
375             pref.nodeExists(null);
376             fail();
377         } catch (NullPointerException expected) {
378         }
379         try {
380             pref.nodeExists("/java/util/prefs/");
381             fail();
382         } catch (IllegalArgumentException expected) {
383         }
384         try {
385             pref.nodeExists("/java//util/prefs");
386             fail();
387         } catch (IllegalArgumentException expected) {
388         }
389 
390         assertTrue(pref.nodeExists("/"));
391 
392         assertTrue(pref.nodeExists("/java/util/prefs"));
393 
394         assertTrue(pref.nodeExists(""));
395 
396         assertFalse(pref.nodeExists("child"));
397         Preferences grandchild = pref.node("child/grandchild");
398         assertTrue(pref.nodeExists("child"));
399         assertTrue(pref.nodeExists("child/grandchild"));
400         grandchild.removeNode();
401         assertTrue(pref.nodeExists("child"));
402         assertFalse(pref.nodeExists("child/grandchild"));
403         assertFalse(grandchild.nodeExists(""));
404 
405         assertFalse(pref.nodeExists("child2/grandchild"));
406         pref.node("child2/grandchild");
407         assertTrue(pref.nodeExists("child2/grandchild"));
408     }
409 
testParent()410     public void testParent() {
411         Preferences parent = Preferences.userNodeForPackage(Preferences.class);
412         Preferences pref = parent.node("mock");
413 
414         assertSame(parent, pref.parent());
415     }
416 
testPut()417     public void testPut() throws BackingStoreException {
418         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
419         pref.put("", "emptyvalue");
420         assertEquals("emptyvalue", pref.get("", null));
421         pref.put("testPutkey", "value1");
422         assertEquals("value1", pref.get("testPutkey", null));
423         pref.put("testPutkey", "value2");
424         assertEquals("value2", pref.get("testPutkey", null));
425 
426         pref.put("", "emptyvalue");
427         assertEquals("emptyvalue", pref.get("", null));
428 
429         try {
430             pref.put(null, "value");
431             fail();
432         } catch (NullPointerException expected) {
433         }
434         try {
435             pref.put("key", null);
436             fail();
437         } catch (NullPointerException expected) {
438         }
439         pref.put(longKey, longValue);
440         try {
441             pref.put(longKey + 1, longValue);
442             fail();
443         } catch (IllegalArgumentException expected) {
444         }
445         try {
446             pref.put(longKey, longValue + 1);
447             fail();
448         } catch (IllegalArgumentException expected) {
449         }
450 
451         pref.removeNode();
452         try {
453             pref.put(longKey, longValue + 1);
454             fail();
455         } catch (IllegalArgumentException expected) {
456         }
457 
458         try {
459             pref.put(longKey, longValue);
460             fail();
461         } catch (IllegalStateException expected) {
462         }
463     }
464 
testPutBoolean()465     public void testPutBoolean() {
466         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
467         try {
468             pref.putBoolean(null, false);
469             fail();
470         } catch (NullPointerException expected) {
471         }
472         pref.putBoolean(longKey, false);
473         try {
474             pref.putBoolean(longKey + "a", false);
475             fail();
476         } catch (IllegalArgumentException expected) {
477         }
478         pref.putBoolean("testPutBooleanKey", false);
479         assertEquals("false", pref.get("testPutBooleanKey", null));
480         assertFalse(pref.getBoolean("testPutBooleanKey", true));
481     }
482 
testPutDouble()483     public void testPutDouble() {
484         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
485         try {
486             pref.putDouble(null, 3);
487             fail();
488         } catch (NullPointerException expected) {
489         }
490         pref.putDouble(longKey, 3);
491         try {
492             pref.putDouble(longKey + "a", 3);
493             fail();
494         } catch (IllegalArgumentException expected) {
495         }
496         pref.putDouble("testPutDoubleKey", 3);
497         assertEquals("3.0", pref.get("testPutDoubleKey", null));
498         assertEquals(3, pref.getDouble("testPutDoubleKey", 0), 0);
499     }
500 
testPutFloat()501     public void testPutFloat() {
502         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
503         try {
504             pref.putFloat(null, 3f);
505             fail();
506         } catch (NullPointerException expected) {
507         }
508         pref.putFloat(longKey, 3f);
509         try {
510             pref.putFloat(longKey + "a", 3f);
511             fail();
512         } catch (IllegalArgumentException expected) {
513         }
514         pref.putFloat("testPutFloatKey", 3f);
515         assertEquals("3.0", pref.get("testPutFloatKey", null));
516         assertEquals(3f, pref.getFloat("testPutFloatKey", 0), 0);
517     }
518 
testPutInt()519     public void testPutInt() {
520         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
521         try {
522             pref.putInt(null, 3);
523             fail();
524         } catch (NullPointerException expected) {
525         }
526         pref.putInt(longKey, 3);
527         try {
528             pref.putInt(longKey + "a", 3);
529             fail();
530         } catch (IllegalArgumentException expected) {
531         }
532         pref.putInt("testPutIntKey", 3);
533         assertEquals("3", pref.get("testPutIntKey", null));
534         assertEquals(3, pref.getInt("testPutIntKey", 0));
535     }
536 
testPutLong()537     public void testPutLong() {
538         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
539         try {
540             pref.putLong(null, 3L);
541             fail();
542         } catch (NullPointerException expected) {
543         }
544         pref.putLong(longKey, 3L);
545         try {
546             pref.putLong(longKey + "a", 3L);
547             fail();
548         } catch (IllegalArgumentException expected) {
549         }
550         pref.putLong("testPutLongKey", 3L);
551         assertEquals("3", pref.get("testPutLongKey", null));
552         assertEquals(3L, pref.getLong("testPutLongKey", 0));
553     }
554 
testPutByteArray()555     public void testPutByteArray() {
556         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
557         try {
558             pref.putByteArray(null, new byte[0]);
559             fail();
560         } catch (NullPointerException expected) {
561         }
562         try {
563             pref.putByteArray("testPutByteArrayKey4", null);
564             fail();
565         } catch (NullPointerException expected) {
566         }
567 
568         pref.putByteArray(longKey, new byte[0]);
569         try {
570             pref.putByteArray(longKey + "a", new byte[0]);
571             fail();
572         } catch (IllegalArgumentException expected) {
573         }
574         byte[] longArray = new byte[(int) (Preferences.MAX_VALUE_LENGTH * 0.74)];
575         byte[] longerArray = new byte[(int) (Preferences.MAX_VALUE_LENGTH * 0.75) + 1];
576         pref.putByteArray(longKey, longArray);
577         try {
578             pref.putByteArray(longKey, longerArray);
579             fail();
580         } catch (IllegalArgumentException expected) {
581         }
582 
583         pref.putByteArray("testPutByteArrayKey", new byte[0]);
584         assertEquals("", pref.get("testPutByteArrayKey", null));
585         assertTrue(Arrays.equals(new byte[0], pref.getByteArray(
586                 "testPutByteArrayKey", null)));
587 
588         pref.putByteArray("testPutByteArrayKey3", new byte[] { 'a', 'b', 'c' });
589         assertEquals("YWJj", pref.get("testPutByteArrayKey3", null));
590         assertTrue(Arrays.equals(new byte[] { 'a', 'b', 'c' }, pref
591                 .getByteArray("testPutByteArrayKey3", null)));
592     }
593 
testRemove()594     public void testRemove() throws BackingStoreException {
595         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
596         pref.remove("key");
597 
598         pref.put("key", "value");
599         assertEquals("value", pref.get("key", null));
600         pref.remove("key");
601         assertNull(pref.get("key", null));
602 
603         pref.remove("key");
604 
605         try {
606             pref.remove(null);
607             fail();
608         } catch (NullPointerException expected) {
609         }
610 
611         pref.removeNode();
612         try {
613             pref.remove("key");
614             fail();
615         } catch (IllegalStateException expected) {
616         }
617     }
618 
testRemoveNode()619     public void testRemoveNode() throws BackingStoreException {
620         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
621         Preferences child = pref.node("child");
622         Preferences child1 = pref.node("child1");
623         Preferences grandchild = child.node("grandchild");
624 
625         pref.removeNode();
626 
627         assertFalse(child.nodeExists(""));
628         assertFalse(child1.nodeExists(""));
629         assertFalse(grandchild.nodeExists(""));
630         assertFalse(pref.nodeExists(""));
631     }
632 
testAddNodeChangeListener()633     public void testAddNodeChangeListener() throws BackingStoreException {
634         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
635         try {
636             pref.addNodeChangeListener(null);
637             fail();
638         } catch (NullPointerException expected) {
639         }
640 
641         Preferences child1 = null;
642 
643         MockNodeChangeListener nl = null;
644         // To get existed node doesn't create the change event
645         try {
646             nl = new MockNodeChangeListener();
647             pref.addNodeChangeListener(nl);
648             child1 = pref.node("mock1");
649             nl.waitForEvent(1);
650             assertEquals(1, nl.getAdded());
651             nl.reset();
652             pref.node("mock1");
653             // There shouldn't be an event, but wait in case one arrives...
654             try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
655             assertEquals(0, nl.getAdded());
656             nl.reset();
657         } finally {
658             pref.removeNodeChangeListener(nl);
659             child1.removeNode();
660         }
661         // same listener can be added twice, and must be removed twice
662         try {
663             nl = new MockNodeChangeListener();
664             pref.addNodeChangeListener(nl);
665             pref.addNodeChangeListener(nl);
666             child1 = pref.node("mock2");
667             nl.waitForEvent(2);
668             assertEquals(2, nl.getAdded());
669             nl.reset();
670         } finally {
671             pref.removeNodeChangeListener(nl);
672             pref.removeNodeChangeListener(nl);
673             child1.removeNode();
674         }
675         // test remove event
676         try {
677             nl = new MockNodeChangeListener();
678             pref.addNodeChangeListener(nl);
679             child1 = pref.node("mock3");
680             child1.removeNode();
681             nl.waitForEvent(2);
682             assertEquals(1, nl.getRemoved());
683             nl.reset();
684         } finally {
685             pref.removeNodeChangeListener(nl);
686         }
687         // test remove event with two listeners
688         try {
689             nl = new MockNodeChangeListener();
690             pref.addNodeChangeListener(nl);
691             pref.addNodeChangeListener(nl);
692             child1 = pref.node("mock6");
693             child1.removeNode();
694             nl.waitForEvent(4);
695             assertEquals(2, nl.getRemoved());
696             nl.reset();
697         } finally {
698             pref.removeNodeChangeListener(nl);
699             pref.removeNodeChangeListener(nl);
700         }
701         // test add/remove indirect children, or remove several children at the
702         // same time
703         Preferences child3;
704         try {
705             nl = new MockNodeChangeListener();
706             child1 = pref.node("mock4");
707             child1.addNodeChangeListener(nl);
708             pref.node("mock4/mock5");
709             nl.waitForEvent(1);
710             assertEquals(1, nl.getAdded());
711             nl.reset();
712             child3 = pref.node("mock4/mock5/mock6");
713             // There shouldn't be an event, but wait in case one arrives...
714             try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
715             assertEquals(0, nl.getAdded());
716             nl.reset();
717 
718             child3.removeNode();
719             // There shouldn't be an event, but wait in case one arrives...
720             try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
721             assertEquals(0, nl.getRemoved());
722             nl.reset();
723 
724             pref.node("mock4/mock7");
725             nl.waitForEvent(1);
726             assertEquals(1, nl.getAdded());
727             nl.reset();
728 
729             child1.removeNode();
730             nl.waitForEvent(2);
731             assertEquals(2, nl.getRemoved());
732             nl.reset();
733         } finally {
734             try {
735                 child1.removeNode();
736             } catch (Exception ignored) {
737             }
738         }
739     }
740 
testAddPreferenceChangeListener()741     public void testAddPreferenceChangeListener() throws Exception {
742         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
743         MockPreferenceChangeListener pl = null;
744 
745         try {
746             pref.addPreferenceChangeListener(null);
747             fail();
748         } catch (NullPointerException expected) {
749         }
750 
751         // To get existed node doesn't create the change event
752         try {
753             pl = new MockPreferenceChangeListener();
754             pref.addPreferenceChangeListener(pl);
755             pref.putInt("mock1", 123);
756             pl.waitForEvent(1);
757             assertEquals(1, pl.getChanged());
758             pref.putLong("long_key", Long.MAX_VALUE);
759             pl.waitForEvent(2);
760             assertEquals(2, pl.getChanged());
761             pl.reset();
762             try {
763                 pref.clear();
764                 pl.waitForEvent(2);
765                 assertEquals(2, pl.getChanged());
766             } catch(BackingStoreException bse) {
767                 pl.reset();
768                 fail("BackingStoreException is thrown");
769             }
770             pl.reset();
771         } finally {
772             pref.removePreferenceChangeListener(pl);
773             //child1.removeNode();
774         }
775 
776         // same listener can be added twice, and must be removed twice
777         try {
778             pl = new MockPreferenceChangeListener();
779             pref.addPreferenceChangeListener(pl);
780             pref.addPreferenceChangeListener(pl);
781             pref.putFloat("float_key", Float.MIN_VALUE);
782             pl.waitForEvent(2);
783             assertEquals(2, pl.getChanged());
784             pl.reset();
785         } finally {
786             pref.removePreferenceChangeListener(pl);
787             pref.removePreferenceChangeListener(pl);
788 
789         }
790         // test remove event
791         try {
792             pl = new MockPreferenceChangeListener();
793             pref.addPreferenceChangeListener(pl);
794             pref.putDouble("double_key", Double.MAX_VALUE);
795             pl.waitForEvent(1);
796             assertEquals(1, pl.getChanged());
797             try {
798                 pref.clear();
799                 pl.waitForEvent(3);
800                 assertEquals(3, pl.getChanged());
801             } catch(BackingStoreException bse) {
802                 fail("BackingStoreException is thrown");
803             }
804             pl.reset();
805         } finally {
806             pref.removePreferenceChangeListener(pl);
807         }
808         // test remove event with two listeners
809         try {
810             pl = new MockPreferenceChangeListener();
811             pref.addPreferenceChangeListener(pl);
812             pref.addPreferenceChangeListener(pl);
813             pref.putByteArray("byte_array_key", new byte [] {1 ,2 , 3});
814             try {
815                 pref.clear();
816                 pl.waitForEvent(4);
817                 assertEquals(4, pl.getChanged());
818             } catch(BackingStoreException bse) {
819                 fail("BackingStoreException is thrown");
820             }
821             pl.reset();
822         } finally {
823             pref.removePreferenceChangeListener(pl);
824             pref.removePreferenceChangeListener(pl);
825         }
826 
827     }
828 
testRemoveNodeChangeListener()829     public void testRemoveNodeChangeListener() {
830         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
831         try {
832             pref.removeNodeChangeListener(null);
833             fail();
834         } catch (IllegalArgumentException expected) {
835         }
836         MockNodeChangeListener l1 = new MockNodeChangeListener();
837         MockNodeChangeListener l2 = new MockNodeChangeListener();
838         pref.addNodeChangeListener(l1);
839         pref.addNodeChangeListener(l1);
840 
841         pref.removeNodeChangeListener(l1);
842         pref.removeNodeChangeListener(l1);
843         try {
844             pref.removeNodeChangeListener(l1);
845             fail();
846         } catch (IllegalArgumentException expected) {
847         }
848         try {
849             pref.removeNodeChangeListener(l2);
850             fail();
851         } catch (IllegalArgumentException expected) {
852         }
853     }
854 
testRemovePreferenceChangeListener()855     public void testRemovePreferenceChangeListener() {
856         Preferences pref = Preferences.userNodeForPackage(Preferences.class);
857         try {
858             pref.removePreferenceChangeListener(null);
859             fail();
860         } catch (IllegalArgumentException expected) {
861         }
862         MockPreferenceChangeListener l1 = new MockPreferenceChangeListener();
863         MockPreferenceChangeListener l2 = new MockPreferenceChangeListener();
864         pref.addPreferenceChangeListener(l1);
865         pref.addPreferenceChangeListener(l1);
866         try {
867             pref.removePreferenceChangeListener(l2);
868             fail();
869         } catch (IllegalArgumentException expected) {
870         }
871         pref.removePreferenceChangeListener(l1);
872         pref.removePreferenceChangeListener(l1);
873         try {
874             pref.removePreferenceChangeListener(l1);
875             fail();
876         } catch (IllegalArgumentException expected) {
877         }
878 
879     }
880 
881     static class MockNodeChangeListener implements NodeChangeListener {
882         private int added = 0;
883         private int removed = 0;
884         private int eventCount = 0;
885 
waitForEvent(int count)886         public void waitForEvent(int count) {
887             synchronized (this) {
888                 while (eventCount < count) {
889                     try {
890                         wait();
891                     } catch (InterruptedException ignored) {
892                     }
893                 }
894             }
895         }
896 
childAdded(NodeChangeEvent e)897         public void childAdded(NodeChangeEvent e) {
898             if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
899             synchronized (this) {
900                 ++eventCount;
901                 ++added;
902                 notifyAll();
903             }
904         }
905 
childRemoved(NodeChangeEvent e)906         public void childRemoved(NodeChangeEvent e) {
907             if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
908             synchronized (this) {
909                 ++eventCount;
910                 ++removed;
911                 notifyAll();
912             }
913         }
914 
getAdded()915         public synchronized int getAdded() {
916             return added;
917         }
918 
getRemoved()919         public synchronized int getRemoved() {
920             return removed;
921         }
922 
reset()923         public synchronized void reset() {
924             eventCount = 0;
925             added = 0;
926             removed = 0;
927         }
928     }
929 
930     private static class MockPreferenceChangeListener implements PreferenceChangeListener {
931         private int changed = 0;
932         private int eventCount = 0;
933 
waitForEvent(int count)934         public void waitForEvent(int count) {
935             synchronized (this) {
936                 while (eventCount < count) {
937                     try {
938                         wait();
939                     } catch (InterruptedException ignored) {
940                     }
941                 }
942             }
943         }
944 
preferenceChange(PreferenceChangeEvent pce)945         public void preferenceChange(PreferenceChangeEvent pce) {
946             if (ENCOURAGE_RACES) try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
947             synchronized (this) {
948                 ++eventCount;
949                 ++changed;
950                 notifyAll();
951             }
952         }
953 
getChanged()954         public synchronized int getChanged() {
955             return changed;
956         }
957 
reset()958         public synchronized void reset() {
959             eventCount = 0;
960             changed = 0;
961         }
962     }
963 
964     @SuppressWarnings("unused")
965     static class MockPreferences extends Preferences {
966 
967         @Override
absolutePath()968         public String absolutePath() {
969             return null;
970         }
971 
972         @Override
childrenNames()973         public String[] childrenNames() throws BackingStoreException {
974             return null;
975         }
976 
977         @Override
clear()978         public void clear() throws BackingStoreException {
979         }
980 
981         @Override
exportNode(OutputStream ostream)982         public void exportNode(OutputStream ostream) throws IOException, BackingStoreException {
983         }
984 
985         @Override
exportSubtree(OutputStream ostream)986         public void exportSubtree(OutputStream ostream) throws IOException, BackingStoreException {
987         }
988 
989         @Override
flush()990         public void flush() throws BackingStoreException {
991         }
992 
993         @Override
get(String key, String deflt)994         public String get(String key, String deflt) {
995             return null;
996         }
997 
998         @Override
getBoolean(String key, boolean deflt)999         public boolean getBoolean(String key, boolean deflt) {
1000             return false;
1001         }
1002 
1003         @Override
getByteArray(String key, byte[] deflt)1004         public byte[] getByteArray(String key, byte[] deflt) {
1005             return null;
1006         }
1007 
1008         @Override
getDouble(String key, double deflt)1009         public double getDouble(String key, double deflt) {
1010             return 0;
1011         }
1012 
1013         @Override
getFloat(String key, float deflt)1014         public float getFloat(String key, float deflt) {
1015             return 0;
1016         }
1017 
1018         @Override
getInt(String key, int deflt)1019         public int getInt(String key, int deflt) {
1020             return 0;
1021         }
1022 
1023         @Override
getLong(String key, long deflt)1024         public long getLong(String key, long deflt) {
1025             return 0;
1026         }
1027 
1028         @Override
isUserNode()1029         public boolean isUserNode() {
1030             return false;
1031         }
1032 
1033         @Override
keys()1034         public String[] keys() throws BackingStoreException {
1035             return null;
1036         }
1037 
1038         @Override
name()1039         public String name() {
1040             return null;
1041         }
1042 
1043         @Override
node(String name)1044         public Preferences node(String name) {
1045             return null;
1046         }
1047 
1048         @Override
nodeExists(String name)1049         public boolean nodeExists(String name) throws BackingStoreException {
1050             return false;
1051         }
1052 
1053         @Override
parent()1054         public Preferences parent() {
1055             return null;
1056         }
1057 
1058         @Override
put(String key, String value)1059         public void put(String key, String value) {
1060         }
1061 
1062         @Override
putBoolean(String key, boolean value)1063         public void putBoolean(String key, boolean value) {
1064         }
1065 
1066         @Override
putByteArray(String key, byte[] value)1067         public void putByteArray(String key, byte[] value) {
1068         }
1069 
1070         @Override
putDouble(String key, double value)1071         public void putDouble(String key, double value) {
1072         }
1073 
1074         @Override
putFloat(String key, float value)1075         public void putFloat(String key, float value) {
1076         }
1077 
1078         @Override
putInt(String key, int value)1079         public void putInt(String key, int value) {
1080         }
1081 
1082         @Override
putLong(String key, long value)1083         public void putLong(String key, long value) {
1084         }
1085 
1086         @Override
remove(String key)1087         public void remove(String key) {
1088         }
1089 
1090         @Override
removeNode()1091         public void removeNode() throws BackingStoreException {
1092         }
1093 
1094         @Override
addNodeChangeListener(NodeChangeListener ncl)1095         public void addNodeChangeListener(NodeChangeListener ncl) {
1096         }
1097 
1098         @Override
addPreferenceChangeListener(PreferenceChangeListener pcl)1099         public void addPreferenceChangeListener(PreferenceChangeListener pcl) {
1100         }
1101 
1102         @Override
removeNodeChangeListener(NodeChangeListener ncl)1103         public void removeNodeChangeListener(NodeChangeListener ncl) {
1104         }
1105 
1106         @Override
removePreferenceChangeListener(PreferenceChangeListener pcl)1107         public void removePreferenceChangeListener(PreferenceChangeListener pcl) {
1108         }
1109 
1110         @Override
sync()1111         public void sync() throws BackingStoreException {
1112         }
1113 
1114         @Override
toString()1115         public String toString() {
1116             return null;
1117         }
1118     }
1119 }
1120