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.prefs.tests.java.util.prefs;
19
20import java.io.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.UnsupportedEncodingException;
25import java.lang.reflect.InvocationTargetException;
26import java.lang.reflect.Method;
27import java.util.Arrays;
28import java.util.prefs.AbstractPreferences;
29import java.util.prefs.BackingStoreException;
30import java.util.prefs.NodeChangeEvent;
31import java.util.prefs.NodeChangeListener;
32import java.util.prefs.PreferenceChangeEvent;
33import java.util.prefs.PreferenceChangeListener;
34import java.util.prefs.Preferences;
35
36import javax.xml.parsers.DocumentBuilder;
37import javax.xml.parsers.DocumentBuilderFactory;
38import javax.xml.parsers.ParserConfigurationException;
39
40import junit.framework.TestCase;
41
42//import org.apache.xpath.XPathAPI;
43import org.w3c.dom.Document;
44import org.w3c.dom.Node;
45import org.xml.sax.SAXException;
46
47/**
48 * TODO: refine this test to adapt all implementations
49 *
50 */
51public class AbstractPreferencesTest extends TestCase {
52
53    AbstractPreferences pref;
54
55    static AbstractPreferences root = null;
56
57    static AbstractPreferences parent = null;
58
59    final static String longKey;
60
61    final static String longValue;
62
63    final static String longName;
64
65    MockNodeChangeListener nl;
66
67    MockPreferenceChangeListener pl;
68
69    static {
70        StringBuffer key = new StringBuffer(Preferences.MAX_KEY_LENGTH);
71        for (int i = 0; i < Preferences.MAX_KEY_LENGTH; i++) {
72            key.append('a');
73        }
74        longKey = key.toString();
75        StringBuffer value = new StringBuffer(Preferences.MAX_VALUE_LENGTH);
76        for (int i = 0; i < Preferences.MAX_VALUE_LENGTH; i++) {
77            value.append('a');
78        }
79        longValue = value.toString();
80
81        StringBuffer name = new StringBuffer(Preferences.MAX_NAME_LENGTH);
82        for (int i = 0; i < Preferences.MAX_NAME_LENGTH; i++) {
83            name.append('a');
84        }
85        longName = name.toString();
86    }
87
88    @Override
89    protected void setUp() throws Exception {
90        super.setUp();
91        root = (AbstractPreferences) Preferences.userRoot();
92        parent = (AbstractPreferences) Preferences
93        .userNodeForPackage(Preferences.class);
94        // FIXME: change here is dangerous
95        // pref = new MockAbstractPreferences((AbstractPreferences) parent,
96        // "mock");
97
98        pref = (AbstractPreferences) parent.node("mock");
99    }
100
101    @Override
102    protected void tearDown() throws Exception {
103        try {
104            if (pref instanceof MockAbstractPreferences) {
105                ((MockAbstractPreferences) pref)
106                .setResult(MockAbstractPreferences.NORMAL);
107            }
108            // make sure remove it successfully
109            parent.node("mock").removeNode();
110
111        } catch (Exception e) {
112        }
113        super.tearDown();
114    }
115
116    public void testConstructor() throws BackingStoreException {
117        try {
118            pref = new MockAbstractPreferences(
119                    (AbstractPreferences) Preferences.userRoot(), "mo/ck");
120            fail("should throw IllegalArgumentException");
121        } catch (IllegalArgumentException e) {
122            // Expected
123        }
124        try {
125            pref = new MockAbstractPreferences(null, "mock");
126            fail("should throw IllegalArgumentException");
127        } catch (IllegalArgumentException e) {
128            // Expected
129        }
130        try {
131            new MockAbstractPreferences(null, " ");
132            fail("should throw IllegalArgumentException");
133        } catch (IllegalArgumentException e) {
134            // Expected
135        }
136        try {
137            new MockAbstractPreferences(pref, "");
138            fail("should throw IllegalArgumentException");
139        } catch (IllegalArgumentException e) {
140            // Expected
141        }
142        try {
143            new MockAbstractPreferences(pref, null);
144            fail("should throw NullPointerException");
145        } catch (NullPointerException e) {
146            // Expected
147        }
148        if (!(pref instanceof MockAbstractPreferences)) {
149            return;
150        }
151        new MockAbstractPreferences(pref, " ");
152
153        Preferences p2 = new MockAbstractPreferences(null, "");
154        assertNotSame(p2, Preferences.systemRoot());
155        assertNotSame(p2, Preferences.userRoot());
156        assertFalse(p2.isUserNode());
157
158        p2 = new MockAbstractPreferences((AbstractPreferences) Preferences
159                .userRoot(), "mock");
160        assertNotSame(p2, pref);
161        p2.removeNode();
162    }
163
164    public void testProtectedFields() throws BackingStoreException {
165        if (!(pref instanceof MockAbstractPreferences)) {
166            return;
167        }
168        MockAbstractPreferences p = new MockAbstractPreferences(pref, "newNode");
169        assertFalse(p.getNewNode());
170        assertSame(p.getLock().getClass(), Object.class);
171
172        p = (MockAbstractPreferences) pref.node("child");
173        assertTrue(p.getNewNode());
174
175        p = (MockAbstractPreferences) ((MockAbstractPreferences) pref)
176        .publicChildSpi("child2");
177        assertTrue(p.getNewNode());
178    }
179
180    public void testToString() {
181        assertEquals("User Preference Node: " + pref.absolutePath(), pref
182                .toString());
183
184        pref = new MockAbstractPreferences((AbstractPreferences) Preferences
185                .systemRoot(), "mock");
186        assertEquals("System Preference Node: " + pref.absolutePath(), pref
187                .toString());
188    }
189
190    public void testAbsolutePath() {
191        assertEquals("/java/util/prefs/mock", pref.absolutePath());
192
193        pref = new MockAbstractPreferences(pref, " ");
194        assertEquals("/java/util/prefs/mock/ ", pref.absolutePath());
195    }
196
197    public void testChildrenNames() throws BackingStoreException {
198        assertEquals(0, pref.childrenNames().length);
199
200        // MockAbstractPreferences child1 = new MockAbstractPreferences(pref,
201        // "child1");
202        // MockAbstractPreferences child2 = new MockAbstractPreferences(pref,
203        // "child2");
204        // MockAbstractPreferences child3 = new MockAbstractPreferences(pref,
205        // "child3");
206        // MockAbstractPreferences subchild1 = new
207        // MockAbstractPreferences(child1,
208        // "subchild1");
209        Preferences child1 = pref.node("child1");
210
211        pref.node("child2");
212        pref.node("child3");
213        child1.node("subchild1");
214
215        assertSame(pref, child1.parent());
216        assertEquals(3, pref.childrenNames().length);
217    }
218
219    public void testClear() throws BackingStoreException {
220        pref.put("testClearKey", "testClearValue");
221        pref.put("testClearKey1", "testClearValue1");
222        assertEquals("testClearValue", pref.get("testClearKey", null));
223        assertEquals("testClearValue1", pref.get("testClearKey1", null));
224        pref.clear();
225        assertNull(pref.get("testClearKey", null));
226        assertNull(pref.get("testClearKey1", null));
227    }
228
229    public void testGet() throws BackingStoreException {
230        assertNull(pref.get("", null));
231        assertEquals("default", pref.get("key", "default"));
232        assertNull(pref.get("key", null));
233        pref.put("testGetkey", "value");
234        assertNull(pref.get("testGetKey", null));
235        assertEquals("value", pref.get("testGetkey", null));
236
237        try {
238            pref.get(null, "abc");
239            fail("should throw NullPointerException");
240        } catch (NullPointerException e) {
241            // Expected
242        }
243        pref.get("", "abc");
244        pref.get("key", null);
245        pref.get("key", "");
246        pref.putFloat("floatKey", 1.0f);
247        assertEquals("1.0", pref.get("floatKey", null));
248
249        pref.removeNode();
250        try {
251            pref.get("key", "abc");
252            fail("should throw IllegalStateException");
253        } catch (IllegalStateException e) {
254            // Expected
255        }
256        try {
257            pref.get(null, "abc");
258            fail("should throw NullPointerException");
259        } catch (NullPointerException e) {
260            // Expected
261        }
262    }
263
264    public void testGetBoolean() {
265        try {
266            pref.getBoolean(null, false);
267            fail("should throw NullPointerException");
268        } catch (NullPointerException e) {
269            // Expected
270        }
271
272        pref.put("testGetBooleanKey", "false");
273        pref.put("testGetBooleanKey2", "value");
274        assertFalse(pref.getBoolean("testGetBooleanKey", true));
275        assertTrue(pref.getBoolean("testGetBooleanKey2", true));
276    }
277
278    public void testPutByteArray() {
279        try {
280            pref.putByteArray(null, new byte[0]);
281            fail("should throw NullPointerException");
282        } catch (NullPointerException e) {
283            // Expected
284        }
285        try {
286            pref.putByteArray("testPutByteArrayKey4", null);
287            fail("should throw NullPointerException");
288        } catch (NullPointerException e) {
289            // Expected
290        }
291
292        pref.putByteArray(longKey, new byte[0]);
293        try {
294            pref.putByteArray(longKey + "a", new byte[0]);
295            fail("should throw IllegalArgumentException");
296        } catch (IllegalArgumentException e) {
297            // Expected
298        }
299        byte[] longArray = new byte[(int) (Preferences.MAX_VALUE_LENGTH * 0.74)];
300        byte[] longerArray = new byte[(int) (Preferences.MAX_VALUE_LENGTH * 0.75) + 1];
301        pref.putByteArray(longKey, longArray);
302        try {
303            pref.putByteArray(longKey, longerArray);
304            fail("should throw IllegalArgumentException");
305        } catch (IllegalArgumentException e) {
306            // Expected
307        }
308
309        pref.putByteArray("testPutByteArrayKey", new byte[0]);
310        assertEquals("", pref.get("testPutByteArrayKey", null));
311        assertTrue(Arrays.equals(new byte[0], pref.getByteArray(
312                "testPutByteArrayKey", null)));
313
314        pref.putByteArray("testPutByteArrayKey3", new byte[] { 'a', 'b', 'c' });
315        assertEquals("YWJj", pref.get("testPutByteArrayKey3", null));
316        assertTrue(Arrays.equals(new byte[] { 'a', 'b', 'c' }, pref
317                .getByteArray("testPutByteArrayKey3", null)));
318    }
319
320    public void testGetByteArray() throws UnsupportedEncodingException {
321        try {
322            pref.getByteArray(null, new byte[0]);
323            fail("should throw NullPointerException");
324        } catch (NullPointerException e) {
325            // Expected
326        }
327        byte[] b64Array = new byte[] { 0x59, 0x57, 0x4a, 0x6a };// BASE64
328        // encoding for
329        // "abc"
330
331        pref.put("testGetByteArrayKey", "abc=");
332        pref.put("testGetByteArrayKey2", new String(b64Array, "UTF-8"));
333        pref.put("invalidKey", "<>?");
334        // assertTrue(Arrays.equals(new byte[0], p.getByteArray(
335        // "testGetByteArrayKey", new byte[0])));
336        assertTrue(Arrays.equals(new byte[] { 105, -73 }, pref.getByteArray(
337                "testGetByteArrayKey", new byte[0])));
338        assertTrue(Arrays.equals(new byte[] { 'a', 'b', 'c' }, pref
339                .getByteArray("testGetByteArrayKey2", new byte[0])));
340        assertTrue(Arrays.equals(new byte[0], pref.getByteArray("invalidKey",
341                new byte[0])));
342
343        pref.putByteArray("testGetByteArrayKey3", b64Array);
344        pref.putByteArray("testGetByteArrayKey4", "abc".getBytes());
345        assertTrue(Arrays.equals(b64Array, pref.getByteArray(
346                "testGetByteArrayKey3", new byte[0])));
347        assertTrue(Arrays.equals("abc".getBytes(), pref.getByteArray(
348                "testGetByteArrayKey4", new byte[0])));
349    }
350
351    public void testGetDouble() {
352        try {
353            pref.getDouble(null, 0);
354            fail("should throw NullPointerException");
355        } catch (NullPointerException e) {
356            // Expected
357        }
358
359        pref.put("testGetDoubleKey", "1");
360        pref.put("testGetDoubleKey2", "value");
361        pref.putDouble("testGetDoubleKey3", 1);
362        pref.putInt("testGetDoubleKey4", 1);
363        assertEquals(1.0, pref.getDouble("testGetDoubleKey", 0.0), 0);
364        assertEquals(0.0, pref.getDouble("testGetDoubleKey2", 0.0), 0);
365        assertEquals(1.0, pref.getDouble("testGetDoubleKey3", 0.0), 0);
366        assertEquals(1.0, pref.getDouble("testGetDoubleKey4", 0.0), 0);
367    }
368
369    public void testGetFloat() {
370        try {
371            pref.getFloat(null, 0f);
372            fail("should throw NullPointerException");
373        } catch (NullPointerException e) {
374            // Expected
375        }
376        pref.put("testGetFloatKey", "1");
377        pref.put("testGetFloatKey2", "value");
378        assertEquals(1f, pref.getFloat("testGetFloatKey", 0f), 0); //$NON-NLS-1$
379        assertEquals(0f, pref.getFloat("testGetFloatKey2", 0f), 0);
380    }
381
382    public void testGetInt() {
383        try {
384            pref.getInt(null, 0);
385            fail("should throw NullPointerException");
386        } catch (NullPointerException e) {
387            // Expected
388        }
389
390        pref.put("testGetIntKey", "1");
391        pref.put("testGetIntKey2", "value");
392        assertEquals(1, pref.getInt("testGetIntKey", 0));
393        assertEquals(0, pref.getInt("testGetIntKey2", 0));
394    }
395
396    public void testGetLong() {
397        try {
398            pref.getLong(null, 0);
399            fail("should throw NullPointerException");
400        } catch (NullPointerException e) {
401            // Expected
402        }
403
404        pref.put("testGetLongKey", "1");
405        pref.put("testGetLongKey2", "value");
406        assertEquals(1, pref.getInt("testGetLongKey", 0));
407        assertEquals(0, pref.getInt("testGetLongKey2", 0));
408    }
409
410    public void testIsUserNode() {
411        assertTrue(pref.isUserNode());
412
413        pref = new MockAbstractPreferences((AbstractPreferences) Preferences
414                .systemRoot(), "mock");
415        assertFalse(pref.isUserNode());
416    }
417
418    // TODO, how to test the "stored defaults"
419    // TODO, how to test the multi-thread
420    public void testKeys() throws BackingStoreException {
421        assertEquals(0, pref.keys().length);
422
423        pref.put("key0", "value");
424        pref.put("key1", "value1");
425        pref.put("key2", "value2");
426        pref.put("key3", "value3");
427
428        String[] keys = pref.keys();
429        assertEquals(4, keys.length);
430        for (int i = 0; i < keys.length; i++) {
431            assertEquals(0, keys[i].indexOf("key"));
432            assertEquals(4, keys[i].length());
433        }
434    }
435
436    public void testName() {
437        assertEquals("mock", pref.name());
438
439        pref = new MockAbstractPreferences(pref, " ");
440        assertEquals(" ", pref.name());
441    }
442
443    public void testCharCase() throws BackingStoreException {
444        assertSame(pref.node("samechild"), pref.node("samechild"));
445        assertNotSame(pref.node("sameChild"), pref.node("samechild"));
446        assertNotSame(pref.node("child"), pref.node("Child"));
447        assertNotSame(pref.node("child"), pref.node("Child"));
448        assertNotSame(pref.node("child"), pref.node(" child"));
449        String[] names = pref.childrenNames();
450        assertEquals(5, names.length);
451        for (int i = 0; i < names.length; i++) {
452            String name = names[i];
453            assertTrue("samechild".equals(name) || "sameChild".equals(name)
454                    || "child".equals(name) || "Child".equals(name)
455                    || " child".equals(name));
456        }
457
458        Preferences mock1 = pref.node("mock1");
459        mock1.put("key", "1value");
460        mock1.put("KEY", "2value");
461        mock1.put("/K/E/Y", "7value");
462        mock1.put("/K/E\\Y\\abc~@!#$%^&*(\\", "8value");
463
464        assertEquals("8value", mock1.get("/K/E\\Y\\abc~@!#$%^&*(\\", null));
465        assertNull(mock1.get("/k/e/y", null));
466        assertEquals("7value", mock1.get("/K/E/Y", null));
467        assertEquals("1value", mock1.get("key", null));
468
469        String[] keys = mock1.keys();
470        assertEquals(4, keys.length);
471        for (int i = 0; i < keys.length; i++) {
472            String key = keys[i];
473            assertTrue("key".equals(key) || "KEY".equals(key)
474                    || "/K/E/Y".equals(key)
475                    || "/K/E\\Y\\abc~@!#$%^&*(\\".equals(key));
476        }
477    }
478
479    public void testNode() throws BackingStoreException {
480        try {
481            pref.node(null);
482            fail("should throw NullPointerException");
483        } catch (NullPointerException e) {
484            // Expected
485        }
486        try {
487            pref.node("/java/util/prefs/");
488            fail("should throw IllegalArgumentException");
489        } catch (IllegalArgumentException e) {
490            // Expected
491        }
492        try {
493            pref.node("/java//util/prefs");
494            fail("should throw IllegalArgumentException");
495        } catch (IllegalArgumentException e) {
496            // Expected
497        }
498        try {
499            pref.node(longName + "a");
500            fail("should throw IllegalArgumentException");
501        } catch (IllegalArgumentException e) {
502            // Expected
503        }
504        assertNotNull(pref.node(longName));
505
506        assertSame(root, pref.node("/"));
507
508        Preferences prefs = pref.node("/java/util/prefs");
509        assertSame(prefs, parent);
510
511        assertSame(pref, pref.node(""));
512
513        if (!(pref instanceof MockAbstractPreferences)) {
514            return;
515        }
516        MockAbstractPreferences child = (MockAbstractPreferences) ((MockAbstractPreferences) pref)
517        .publicChildSpi("child");
518        assertSame(child, pref.node("child"));
519
520        Preferences child2 = pref.node("child2");
521        assertSame(child2, ((MockAbstractPreferences) pref)
522                .publicChildSpi("child2"));
523
524        Preferences grandchild = pref.node("child/grandchild");
525        assertSame(grandchild, child.childSpi("grandchild"));
526        assertSame(grandchild, child.cachedChildrenImpl()[0]);
527        grandchild.removeNode();
528        assertNotSame(grandchild, pref.node("child/grandchild"));
529
530        grandchild = pref.node("child3/grandchild");
531        AbstractPreferences[] childs = ((MockAbstractPreferences) pref)
532        .cachedChildrenImpl();
533        Preferences child3 = child;
534        for (int i = 0; i < childs.length; i++) {
535            if (childs[i].name().equals("child3")) {
536                child3 = childs[i];
537                break;
538            }
539        }
540        assertSame(child3, grandchild.parent());
541    }
542
543    public void testNodeExists() throws BackingStoreException {
544        try {
545            pref.nodeExists(null);
546            fail("should throw NullPointerException");
547        } catch (NullPointerException e) {
548            // Expected
549        }
550        try {
551            pref.nodeExists("/java/util/prefs/");
552            fail("should throw IllegalArgumentException");
553        } catch (IllegalArgumentException e) {
554            // Expected
555        }
556        try {
557            pref.nodeExists("/java//util/prefs");
558            fail("should throw IllegalArgumentException");
559        } catch (IllegalArgumentException e) {
560            // Expected
561        }
562
563        assertTrue(pref.nodeExists("/"));
564
565        assertTrue(pref.nodeExists("/java/util/prefs"));
566
567        assertTrue(pref.nodeExists(""));
568
569        assertFalse(pref.nodeExists("child"));
570        Preferences grandchild = pref.node("child/grandchild");
571        assertTrue(pref.nodeExists("child"));
572        assertTrue(pref.nodeExists("child/grandchild"));
573        grandchild.removeNode();
574        assertTrue(pref.nodeExists("child"));
575        assertFalse(pref.nodeExists("child/grandchild"));
576        assertFalse(grandchild.nodeExists(""));
577
578        assertFalse(pref.nodeExists("child2/grandchild"));
579        pref.node("child2/grandchild");
580        assertTrue(pref.nodeExists("child2/grandchild"));
581    }
582
583    public void test_nodeExists() throws BackingStoreException {
584        AbstractPreferences test = (AbstractPreferences) Preferences.userRoot()
585                .node("test");
586        try {
587            test.nodeExists(null);
588            fail("should throw NullPointerException");
589        } catch (NullPointerException e) {
590            // Expected
591        }
592
593        test.removeNode();
594        try {
595            test.nodeExists(null);
596            fail("should throw NullPointerException");
597        } catch (NullPointerException e) {
598            // Expected
599        }
600    }
601
602    public void testParent() {
603        assertSame(parent, pref.parent());
604        AbstractPreferences child1 = new MockAbstractPreferences(pref, "child1");
605        assertSame(pref, child1.parent());
606        assertNull(root.parent());
607    }
608
609    public void testPut() throws BackingStoreException {
610        pref.put("", "emptyvalue");
611        assertEquals("emptyvalue", pref.get("", null));
612        pref.put("testPutkey", "value1");
613        assertEquals("value1", pref.get("testPutkey", null));
614        pref.put("testPutkey", "value2");
615        assertEquals("value2", pref.get("testPutkey", null));
616
617        pref.put("", "emptyvalue");
618        assertEquals("emptyvalue", pref.get("", null));
619
620        try {
621            pref.put(null, "value");
622            fail("should throw NullPointerException");
623        } catch (NullPointerException e) {
624            // Expected
625        }
626        try {
627            pref.put("key", null);
628            fail("should throw NullPointerException");
629        } catch (NullPointerException e) {
630            // Expected
631        }
632        pref.put(longKey, longValue);
633        try {
634            pref.put(longKey + 1, longValue);
635            fail("should throw IllegalArgumentException");
636        } catch (IllegalArgumentException e) {
637            // Expected
638        }
639        try {
640            pref.put(longKey, longValue + 1);
641            fail("should throw IllegalArgumentException");
642        } catch (IllegalArgumentException e) {
643            // Expected
644        }
645
646        pref.removeNode();
647        try {
648            pref.put(longKey, longValue + 1);
649            fail("should throw IllegalArgumentException");
650        } catch (IllegalArgumentException e) {
651            // Expected
652        }
653
654        try {
655            pref.put(longKey, longValue);
656            fail("should throw IllegalStateException");
657        } catch (IllegalStateException e) {
658            // Expected
659        }
660    }
661
662    public void testPutBoolean() {
663        try {
664            pref.putBoolean(null, false);
665            fail("should throw NullPointerException");
666        } catch (NullPointerException e) {
667            // Expected
668        }
669        pref.putBoolean(longKey, false);
670        try {
671            pref.putBoolean(longKey + "a", false);
672            fail("should throw IllegalArgumentException");
673        } catch (IllegalArgumentException e) {
674            // Expected
675        }
676        pref.putBoolean("testPutBooleanKey", false);
677        assertEquals("false", pref.get("testPutBooleanKey", null));
678        assertFalse(pref.getBoolean("testPutBooleanKey", true));
679    }
680
681    public void testPutDouble() {
682        try {
683            pref.putDouble(null, 3);
684            fail("should throw NullPointerException");
685        } catch (NullPointerException e) {
686            // Expected
687        }
688        pref.putDouble(longKey, 3);
689        try {
690            pref.putDouble(longKey + "a", 3);
691            fail("should throw IllegalArgumentException");
692        } catch (IllegalArgumentException e) {
693            // Expected
694        }
695        pref.putDouble("testPutDoubleKey", 3);
696        assertEquals("3.0", pref.get("testPutDoubleKey", null));
697        assertEquals(3, pref.getDouble("testPutDoubleKey", 0), 0);
698    }
699
700    public void testPutFloat() {
701        try {
702            pref.putFloat(null, 3f);
703            fail("should throw NullPointerException");
704        } catch (NullPointerException e) {
705            // Expected
706        }
707        pref.putFloat(longKey, 3f);
708        try {
709            pref.putFloat(longKey + "a", 3f);
710            fail("should throw IllegalArgumentException");
711        } catch (IllegalArgumentException e) {
712            // Expected
713        }
714        pref.putFloat("testPutFloatKey", 3f);
715        assertEquals("3.0", pref.get("testPutFloatKey", null));
716        assertEquals(3f, pref.getFloat("testPutFloatKey", 0), 0);
717    }
718
719    public void testPutInt() {
720        try {
721            pref.putInt(null, 3);
722            fail("should throw NullPointerException");
723        } catch (NullPointerException e) {
724            // Expected
725        }
726        pref.putInt(longKey, 3);
727        try {
728            pref.putInt(longKey + "a", 3);
729            fail("should throw IllegalArgumentException");
730        } catch (IllegalArgumentException e) {
731            // Expected
732        }
733        pref.putInt("testPutIntKey", 3);
734        assertEquals("3", pref.get("testPutIntKey", null));
735        assertEquals(3, pref.getInt("testPutIntKey", 0));
736    }
737
738    public void testPutLong() {
739        try {
740            pref.putLong(null, 3L);
741            fail("should throw NullPointerException");
742        } catch (NullPointerException e) {
743            // Expected
744        }
745        pref.putLong(longKey, 3L);
746        try {
747            pref.putLong(longKey + "a", 3L);
748            fail("should throw IllegalArgumentException");
749        } catch (IllegalArgumentException e) {
750            // Expected
751        }
752        pref.putLong("testPutLongKey", 3L);
753        assertEquals("3", pref.get("testPutLongKey", null));
754        assertEquals(3L, pref.getLong("testPutLongKey", 0));
755    }
756
757    public void testRemove() throws BackingStoreException {
758        pref.remove("key");
759
760        pref.put("key", "value");
761        assertEquals("value", pref.get("key", null));
762        pref.remove("key");
763        assertNull(pref.get("key", null));
764
765        pref.remove("key");
766
767        try {
768            pref.remove(null);
769            fail("should throw NullPointerException");
770        } catch (NullPointerException e) {
771            // Expected
772        }
773
774        pref.removeNode();
775        try {
776            pref.remove("key");
777            fail("should throw IllegalStateException");
778        } catch (IllegalStateException e) {
779            // Expected
780        }
781    }
782
783    public void testRemoveNode() throws BackingStoreException {
784        Preferences child = pref.node("child");
785        Preferences child1 = pref.node("child1");
786        Preferences grandchild = child.node("grandchild");
787
788        pref.removeNode();
789
790        assertFalse(child.nodeExists(""));
791        assertFalse(child1.nodeExists(""));
792        assertFalse(grandchild.nodeExists(""));
793        assertFalse(pref.nodeExists(""));
794    }
795
796    // public void testAddNodeChangeListener() throws BackingStoreException {
797    // try {
798    // pref.addNodeChangeListener(null);
799    // fail();
800    // } catch (NullPointerException e) {
801    // }
802    //
803    // Preferences child1 = null;
804    // Preferences child2 = null;
805    // Preferences child3 = null;
806    // //To get existed node doesn't create the change event
807    // try {
808    // nl = new MockNodeChangeListener();
809    // pref.addNodeChangeListener(nl);
810    // child1 = pref.node("mock1");
811    // assertEquals(1, nl.getAdded());
812    // nl.reset();
813    // child2 = pref.node("mock1");
814    // assertEquals(0, nl.getAdded());
815    // nl.reset();
816    // } finally {
817    // pref.removeNodeChangeListener(nl);
818    // child1.removeNode();
819    // }
820    // //same listener can be added twice, and must be removed twice
821    // try {
822    // nl = new MockNodeChangeListener();
823    // pref.addNodeChangeListener(nl);
824    // pref.addNodeChangeListener(nl);
825    // child1 = pref.node("mock2");
826    // assertEquals(2, nl.getAdded());
827    // nl.reset();
828    // } finally {
829    // pref.removeNodeChangeListener(nl);
830    // pref.removeNodeChangeListener(nl);
831    // child1.removeNode();
832    // }
833    // //test remove event
834    // try {
835    // nl = new MockNodeChangeListener();
836    // pref.addNodeChangeListener(nl);
837    // child1 = pref.node("mock3");
838    // child1.removeNode();
839    // assertEquals(1, nl.getRemoved());
840    // nl.reset();
841    // } finally {
842    // pref.removeNodeChangeListener(nl);
843    // }
844    // // test remove event with two listeners
845    // try {
846    // nl = new MockNodeChangeListener();
847    // pref.addNodeChangeListener(nl);
848    // pref.addNodeChangeListener(nl);
849    // child1 = pref.node("mock6");
850    // child1.removeNode();
851    // assertEquals(2, nl.getRemoved());
852    // nl.reset();
853    // } finally {
854    // pref.removeNodeChangeListener(nl);
855    // pref.removeNodeChangeListener(nl);
856    // }
857    // //test add/remove indirect children, or remove several children at the
858    // same time
859    // try {
860    // nl = new MockNodeChangeListener();
861    // child1 = pref.node("mock4");
862    // child1.addNodeChangeListener(nl);
863    // child2 = pref.node("mock4/mock5");
864    // assertEquals(1, nl.getAdded());
865    // nl.reset();
866    // child3 = pref.node("mock4/mock5/mock6");
867    // assertEquals(0, nl.getAdded());
868    // nl.reset();
869    //
870    // child3.removeNode();
871    // assertEquals(0, nl.getRemoved());
872    // nl.reset();
873    //
874    // child3 = pref.node("mock4/mock7");
875    // assertEquals(1, nl.getAdded());
876    // nl.reset();
877    //
878    // child1.removeNode();
879    // assertEquals(2, nl.getRemoved());
880    // nl.reset();
881    // } finally {
882    // try {
883    // child1.removeNode();
884    // } catch (Exception e) {
885    // }
886    // }
887    //
888    // }
889
890    public void testAddPreferenceChangeListener() {
891        // TODO: start from here
892    }
893
894    public void testRemoveNodeChangeListener() {
895        try {
896            pref.removeNodeChangeListener(null);
897            fail("should throw IllegalArgumentException");
898        } catch (IllegalArgumentException e) {
899            // Expected
900        }
901        MockNodeChangeListener l1 = new MockNodeChangeListener();
902        MockNodeChangeListener l2 = new MockNodeChangeListener();
903        pref.addNodeChangeListener(l1);
904        pref.addNodeChangeListener(l1);
905
906        pref.removeNodeChangeListener(l1);
907        pref.removeNodeChangeListener(l1);
908        try {
909            pref.removeNodeChangeListener(l1);
910            fail("should throw IllegalArgumentException");
911        } catch (IllegalArgumentException e) {
912            // Expected
913        }
914        try {
915            pref.removeNodeChangeListener(l2);
916            fail("should throw IllegalArgumentException");
917        } catch (IllegalArgumentException e) {
918            // Expected
919        }
920    }
921
922    public void testRemovePreferenceChangeListener() {
923        try {
924            pref.removePreferenceChangeListener(null);
925            fail("should throw IllegalArgumentException");
926        } catch (IllegalArgumentException e) {
927            // Expected
928        }
929        MockPreferenceChangeListener l1 = new MockPreferenceChangeListener();
930        MockPreferenceChangeListener l2 = new MockPreferenceChangeListener();
931        pref.addPreferenceChangeListener(l1);
932        pref.addPreferenceChangeListener(l1);
933        try {
934            pref.removePreferenceChangeListener(l2);
935            fail("should throw IllegalArgumentException");
936        } catch (IllegalArgumentException e) {
937            // Expected
938        }
939        pref.removePreferenceChangeListener(l1);
940        pref.removePreferenceChangeListener(l1);
941        try {
942            pref.removePreferenceChangeListener(l1);
943            fail("should throw IllegalArgumentException");
944        } catch (IllegalArgumentException e) {
945            // Expected
946        }
947
948    }
949
950    public void testSync() throws BackingStoreException {
951        pref.sync();
952        if (!(pref instanceof MockAbstractPreferences)) {
953            return;
954        }
955        MockAbstractPreferences p = (MockAbstractPreferences) pref;
956        p.resetSyncTimes();
957        p.sync();
958        assertEquals(1, p.getSyncTimes());
959
960        p.resetSyncTimes();
961        MockAbstractPreferences child = (MockAbstractPreferences) p
962        .node("child");
963        MockAbstractPreferences child2 = new MockAbstractPreferences(p,
964        "child2");
965        p.childs.put("child2", child2);
966        assertEquals(1, p.cachedChildrenImpl().length);
967        assertSame(child, p.cachedChildrenImpl()[0]);
968        p.sync();
969        assertEquals(1, p.getSyncTimes());
970        assertEquals(1, child.getSyncTimes());
971        assertEquals(0, child2.getSyncTimes());
972
973        p.resetSyncTimes();
974        child.resetSyncTimes();
975        child.sync();
976        assertEquals(0, p.getSyncTimes());
977        assertEquals(1, child.getSyncTimes());
978
979        p.resetSyncTimes();
980        child.resetSyncTimes();
981        MockAbstractPreferences grandson = (MockAbstractPreferences) child
982        .node("grandson");
983        child.sync();
984        assertEquals(0, p.getSyncTimes());
985        assertEquals(1, child.getSyncTimes());
986        assertEquals(1, grandson.getSyncTimes());
987    }
988
989    public void testFlush() throws BackingStoreException {
990        pref.flush();
991        if (!(pref instanceof MockAbstractPreferences)) {
992            return;
993        }
994        MockAbstractPreferences p = (MockAbstractPreferences) pref;
995        p.resetFlushedTimes();
996        p.flush();
997        assertEquals(1, p.getFlushedTimes());
998
999        p.resetFlushedTimes();
1000        MockAbstractPreferences child = (MockAbstractPreferences) p
1001        .node("child");
1002        MockAbstractPreferences child2 = new MockAbstractPreferences(p,
1003        "child2");
1004        p.childs.put("child2", child2);
1005        assertEquals(1, p.cachedChildrenImpl().length);
1006        assertSame(child, p.cachedChildrenImpl()[0]);
1007        p.flush();
1008        assertEquals(1, p.getFlushedTimes());
1009        assertEquals(1, child.getFlushedTimes());
1010        assertEquals(0, child2.getFlushedTimes());
1011
1012        p.resetFlushedTimes();
1013        child.resetFlushedTimes();
1014        child.flush();
1015        assertEquals(0, p.getFlushedTimes());
1016        assertEquals(1, child.getFlushedTimes());
1017
1018        p.resetFlushedTimes();
1019        child.resetFlushedTimes();
1020        MockAbstractPreferences grandson = (MockAbstractPreferences) child
1021        .node("grandson");
1022        child.flush();
1023        assertEquals(0, p.getFlushedTimes());
1024        assertEquals(1, child.getFlushedTimes());
1025        assertEquals(1, grandson.getFlushedTimes());
1026
1027        p.resetFlushedTimes();
1028        child.resetFlushedTimes();
1029        grandson.resetFlushedTimes();
1030        child.removeNode();
1031        child.flush();
1032        assertEquals(0, p.getFlushedTimes());
1033        assertEquals(1, child.getFlushedTimes());
1034        assertEquals(0, grandson.getFlushedTimes());
1035    }
1036
1037    public void testGetChild() throws BackingStoreException {
1038        if (!(pref instanceof MockAbstractPreferences)) {
1039            return;
1040        }
1041        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1042        assertNull(p.getChildImpl("child"));
1043        MockAbstractPreferences child = new MockAbstractPreferences(p, "child");
1044        p.childs.put("child", child);
1045        assertSame(child, p.getChildImpl("child"));
1046        assertNull(p.getChildImpl("child "));
1047
1048        assertNull(p.getChildImpl("child/grandson"));
1049        child.childs.put("grandson", new MockAbstractPreferences(child,
1050        "grandson"));
1051        assertNull(p.getChildImpl("child/grandson"));
1052
1053        assertNull(p.getChildImpl(null));
1054        assertNull(p.getChildImpl(""));
1055        assertNull(p.getChildImpl(" "));
1056        assertNull(p.getChildImpl("abc//abc"));
1057        assertNull(p.getChildImpl("child/"));
1058        assertNull(p.getChildImpl(longName + "a"));
1059
1060        child.removeNode();
1061        assertNull(p.getChildImpl("child"));
1062    }
1063
1064    public void testIsRemoved() throws BackingStoreException {
1065        if (!(pref instanceof MockAbstractPreferences)) {
1066            return;
1067        }
1068        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1069        assertFalse(p.isRemovedImpl());
1070        p.removeNode();
1071        assertTrue(p.isRemovedImpl());
1072    }
1073
1074    public void testExportNode() throws Exception {
1075        try {
1076            pref.exportNode(null);
1077            fail("should throw NullPointerException");
1078        } catch (NullPointerException e) {
1079            // Expected
1080        }
1081
1082        pref.putBoolean("key", false);
1083        Preferences child = pref.node("child<");
1084        child.put("key2", "value2<");
1085        Preferences grandson = child.node("grandson");
1086        grandson.put("key3", "value3");
1087        ByteArrayOutputStream out = new ByteArrayOutputStream();
1088        child.exportNode(out);
1089
1090        byte[] result = out.toByteArray();
1091        ByteArrayInputStream in = new ByteArrayInputStream(result);
1092
1093        Document doc = parseXmlStream(in, false);
1094
1095        // only output this node without parent and children
1096        /* Android doesn't have XPathAPI
1097        String rootpath = "/preferences[@EXTERNAL_XML_VERSION='1.0']/root[@type='user']/node[@name='java']/node[@name='util']/node[@name='prefs']";
1098        Node node = XPathAPI
1099        .selectSingleNode(
1100                doc,
1101                rootpath
1102                + "/node[@name='mock']/map/entry[@key='key' and @value='false']");
1103        assertNull(node);
1104        node = XPathAPI
1105        .selectSingleNode(
1106                doc,
1107                rootpath
1108                + "/node[@name='mock']/node[@name='child<']/map/entry[@key='key2' and @value='value2<']");
1109        assertNotNull(node);
1110        node = XPathAPI.selectSingleNode(doc, rootpath
1111                + "/node[@name='mock']/node[@name='child']/node");
1112        assertNull(node);
1113        */
1114    }
1115
1116    private static Document parseXmlStream(InputStream input, boolean validating)
1117    throws SAXException, IOException, ParserConfigurationException {
1118        // Create a builder factory
1119        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1120        factory.setValidating(validating);
1121        factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
1122
1123        // Create the builder and parse the file
1124        DocumentBuilder builder = factory.newDocumentBuilder();
1125        Document doc = builder.parse(input);
1126        return doc;
1127    }
1128
1129    public void testExportSubtree() throws Exception {
1130        try {
1131            pref.exportSubtree(null);
1132            fail("should throw NullPointerException");
1133        } catch (NullPointerException e) {
1134            // Expected
1135        }
1136        ByteArrayOutputStream out = new ByteArrayOutputStream();
1137        pref.putBoolean("key", false);
1138        Preferences child = pref.node("child");
1139        child.put("key2", "value2");
1140        Preferences grandson = child.node("grandson");
1141        grandson.put("key3", "value3");
1142        child.node("grandson2");
1143        Preferences grandgrandson = grandson.node("grandgrandson");
1144        grandgrandson.put("key4", "value4");
1145        child.exportSubtree(out);
1146
1147        byte[] result = out.toByteArray();
1148        // System.out.println(new String(result, "utf-8"));
1149        ByteArrayInputStream in = new ByteArrayInputStream(result);
1150        Document doc = parseXmlStream(in, false);
1151
1152        /* Android doesn't have XPathAPI
1153        // only output this node and subtree without parent
1154        String rootpath = "/preferences[@EXTERNAL_XML_VERSION='1.0']/root[@type='user']/node[@name='java']/node[@name='util']/node[@name='prefs']";
1155        Node node = XPathAPI
1156        .selectSingleNode(
1157                doc,
1158                rootpath
1159                + "/node[@name='mock']/map/entry[@key='key' and @value='false']");
1160        assertNull(node);
1161        node = XPathAPI
1162        .selectSingleNode(
1163                doc,
1164                rootpath
1165                + "/node[@name='mock']/node[@name='child']/map/entry[@key='key2' and @value='value2']");
1166        assertNotNull(node);
1167        node = XPathAPI
1168        .selectSingleNode(
1169                doc,
1170                rootpath
1171                + "/node[@name='mock']/node[@name='child']/node[@name='grandson']/map/entry[@key='key3' and @value='value3']");
1172        assertNotNull(node);
1173        node = XPathAPI
1174        .selectSingleNode(
1175                doc,
1176                rootpath
1177                + "/node[@name='mock']/node[@name='child']/node[@name='grandson']/node[@name='grandgrandson']/map/entry[@key='key4' and @value='value4']");
1178        assertNotNull(node);
1179        node = XPathAPI
1180        .selectSingleNode(
1181                doc,
1182                rootpath
1183                + "/node[@name='mock']/node[@name='child']/node[@name='grandson2']/map");
1184        assertNotNull(node);
1185        */
1186    }
1187
1188    public void testCachedChildren() throws Exception {
1189        if (!(pref instanceof MockAbstractPreferences)) {
1190            return;
1191        }
1192        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1193        assertEquals(0, p.cachedChildrenImpl().length);
1194
1195        MockAbstractPreferences child = (MockAbstractPreferences) p
1196        .getChildImpl("child");
1197        assertNull(child);
1198
1199        child = new MockAbstractPreferences(p, "child");
1200        assertSame(child, p.getChildImpl("child"));
1201
1202        assertEquals(0, p.cachedChildrenImpl().length);
1203
1204        p.node("child");
1205        assertSame(child, p.cachedChildrenImpl()[0]);
1206
1207        MockAbstractPreferences grandchild = new MockAbstractPreferences(child,
1208        "grandchild");
1209        assertSame(grandchild, child.getChildImpl("grandchild"));
1210        assertNull(p.getChildImpl("grandchild"));
1211
1212        assertEquals(1, p.cachedChildrenImpl().length);
1213        assertEquals(0, child.cachedChildrenImpl().length);
1214
1215        p.node("child/grandchild");
1216        assertSame(child, p.cachedChildrenImpl()[0]);
1217        assertSame(grandchild, child.cachedChildrenImpl()[0]);
1218        assertEquals(1, p.cachedChildrenImpl().length);
1219        assertEquals(1, child.cachedChildrenImpl().length);
1220
1221        p.childs.put("child2", new MockAbstractPreferences(p, "child2"));
1222        p.nodeExists("child2/grandchild");
1223        assertSame(child, p.cachedChildrenImpl()[0]);
1224        assertSame(grandchild, child.cachedChildrenImpl()[0]);
1225        assertEquals(1, p.cachedChildrenImpl().length);
1226        assertEquals(1, child.cachedChildrenImpl().length);
1227    }
1228
1229    public void testAbstractMethod() {
1230        if (!(pref instanceof MockAbstractPreferences)) {
1231            return;
1232        }
1233        ((MockAbstractPreferences) pref).protectedAbstractMethod();
1234    }
1235
1236    public Object invokeNonPublicMethod(AbstractPreferences obj, String name,
1237            Class<?>[] params, Object[] paramValues) throws SecurityException,
1238            NoSuchMethodException, IllegalArgumentException,
1239            IllegalAccessException, InvocationTargetException {
1240        Method method = obj.getClass().getMethod(name, params);
1241        method.setAccessible(true);
1242        return method.invoke(obj, paramValues);
1243    }
1244
1245    public void testBackingStoreException() throws IOException,
1246    BackingStoreException {
1247        if (!(pref instanceof MockAbstractPreferences)) {
1248            return;
1249        }
1250        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1251        p.setResult(MockAbstractPreferences.backingException);
1252        try {
1253            p.childrenNames();
1254            fail("should throw BackingStoreException");
1255        } catch (BackingStoreException e) {
1256            // Expected
1257        }
1258        p.put("exceptionkey", "value");
1259        p.absolutePath();
1260        p.toString();
1261        assertEquals("exception default", p.get("key", "exception default"));
1262        p.remove("key");
1263        try {
1264            p.clear();
1265            fail("should throw BackingStoreException");
1266        } catch (BackingStoreException e) {
1267            // Expected
1268        }
1269        p.putInt("key", 3);
1270        p.getInt("key", 3);
1271        p.putLong("key", 3l);
1272        p.getLong("key", 3l);
1273        p.putDouble("key", 3);
1274        p.getDouble("key", 3);
1275        p.putBoolean("key", true);
1276        p.getBoolean("key", true);
1277        p.putFloat("key", 3f);
1278        p.getFloat("key", 3f);
1279        p.putByteArray("key", new byte[0]);
1280        p.getByteArray("key", new byte[0]);
1281        try {
1282            p.keys();
1283            fail("should throw BackingStoreException");
1284        } catch (BackingStoreException e) {
1285            // Expected
1286        }
1287
1288        try {
1289            p.keys();
1290            fail("should throw BackingStoreException");
1291        } catch (BackingStoreException e) {
1292            // Expected
1293        }
1294        try {
1295            p.childrenNames();
1296            fail("should throw BackingStoreException");
1297        } catch (BackingStoreException e) {
1298            // Expected
1299        }
1300        p.parent();
1301        p.node("");
1302        p.nodeExists("");
1303        try {
1304            p.removeNode();
1305            fail("should throw BackingStoreException");
1306        } catch (BackingStoreException e) {
1307            // Expected
1308        }
1309        p.name();
1310        p.absolutePath();
1311        p.isUserNode();
1312        MockPreferenceChangeListener mockPreferenceChangeListener = new MockPreferenceChangeListener();
1313        p.addPreferenceChangeListener(mockPreferenceChangeListener);
1314        p.removePreferenceChangeListener(mockPreferenceChangeListener);
1315        MockNodeChangeListener mockNodeChangeListener = new MockNodeChangeListener();
1316        p.addNodeChangeListener(mockNodeChangeListener);
1317        p.removeNodeChangeListener(mockNodeChangeListener);
1318        p.toString();
1319        try {
1320            p.sync();
1321            fail("should throw BackingStoreException");
1322        } catch (BackingStoreException e) {
1323            // Expected
1324        }
1325        try {
1326            p.flush();
1327            fail("should throw BackingStoreException");
1328        } catch (BackingStoreException e) {
1329            // Expected
1330        }
1331        try {
1332            p.exportNode(new ByteArrayOutputStream());
1333            fail("should throw BackingStoreException");
1334        } catch (BackingStoreException e) {
1335            // Expected
1336        }
1337        try {
1338            p.exportSubtree(new ByteArrayOutputStream());
1339            fail("should throw BackingStoreException");
1340        } catch (BackingStoreException e) {
1341            // Expected
1342        }
1343        p.isRemovedImpl();
1344        try {
1345            p.getChildImpl(null);
1346            fail("should throw BackingStoreException");
1347        } catch (BackingStoreException e) {
1348            // Expected
1349        }
1350        p.cachedChildrenImpl();
1351    }
1352
1353    public void testRuntimeException() throws IOException,
1354    BackingStoreException {
1355        if (!(pref instanceof MockAbstractPreferences)) {
1356            return;
1357        }
1358        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1359        p.setResult(MockAbstractPreferences.runtimeException);
1360        try {
1361            p.childrenNames();
1362            fail("should throw MockRuntimeException");
1363        } catch (MockRuntimeException e) {
1364            // Expected
1365        }
1366        try {
1367            p.put("exceptionkey", "value");
1368            fail("should throw MockRuntimeException");
1369        } catch (MockRuntimeException e) {
1370            // Expected
1371        }
1372        p.absolutePath();
1373        p.toString();
1374        assertEquals("exception default", p.get("key", "exception default"));
1375        try {
1376            p.remove("key");
1377            fail("should throw MockRuntimeException");
1378        } catch (MockRuntimeException e) {
1379            // Expected
1380        }
1381        try {
1382            p.clear();
1383            fail("should throw MockRuntimeException");
1384        } catch (MockRuntimeException e) {
1385            // Expected
1386        }
1387        try {
1388            p.putInt("key", 3);
1389            fail("should throw MockRuntimeException");
1390        } catch (MockRuntimeException e) {
1391            // Expected
1392        }
1393        p.getInt("key", 3);
1394        try {
1395            p.putLong("key", 3l);
1396            fail("should throw MockRuntimeException");
1397        } catch (MockRuntimeException e) {
1398            // Expected
1399        }
1400        p.getLong("key", 3l);
1401        try {
1402            p.putDouble("key", 3);
1403            fail("should throw MockRuntimeException");
1404        } catch (MockRuntimeException e) {
1405            // Expected
1406        }
1407        p.getDouble("key", 3);
1408        try {
1409            p.putBoolean("key", true);
1410            fail("should throw MockRuntimeException");
1411        } catch (MockRuntimeException e) {
1412            // Expected
1413        }
1414        p.getBoolean("key", true);
1415        try {
1416            p.putFloat("key", 3f);
1417            fail("should throw MockRuntimeException");
1418        } catch (MockRuntimeException e) {
1419            // Expected
1420        }
1421        p.getFloat("key", 3f);
1422        try {
1423            p.putByteArray("key", new byte[0]);
1424            fail("should throw MockRuntimeException");
1425        } catch (MockRuntimeException e) {
1426            // Expected
1427        }
1428        p.getByteArray("key", new byte[0]);
1429        try {
1430            p.keys();
1431            fail("should throw MockRuntimeException");
1432        } catch (MockRuntimeException e) {
1433            // Expected
1434        }
1435        try {
1436            p.keys();
1437            fail("should throw MockRuntimeException");
1438        } catch (MockRuntimeException e) {
1439            // Expected
1440        }
1441        try {
1442            p.childrenNames();
1443            fail("should throw MockRuntimeException");
1444        } catch (MockRuntimeException e) {
1445            // Expected
1446        }
1447        p.parent();
1448        p.node("");
1449        p.nodeExists("");
1450        try {
1451            p.removeNode();
1452            fail("should throw MockRuntimeException");
1453        } catch (MockRuntimeException e) {
1454            // Expected
1455        }
1456        p.name();
1457        p.absolutePath();
1458        p.isUserNode();
1459        MockPreferenceChangeListener pcl = new MockPreferenceChangeListener();
1460        p.addPreferenceChangeListener(pcl);
1461        p.removePreferenceChangeListener(pcl);
1462        MockNodeChangeListener ncl = new MockNodeChangeListener();
1463        p.addNodeChangeListener(ncl);
1464        p.removeNodeChangeListener(ncl);
1465        p.toString();
1466        try {
1467            p.sync();
1468            fail("should throw MockRuntimeException");
1469        } catch (MockRuntimeException e) {
1470            // Expected
1471        }
1472        try {
1473            p.flush();
1474            fail("should throw MockRuntimeException");
1475        } catch (MockRuntimeException e) {
1476            // Expected
1477        }
1478        try {
1479            p.exportNode(new ByteArrayOutputStream());
1480            fail("should throw MockRuntimeException");
1481        } catch (MockRuntimeException e) {
1482            // Expected
1483        }
1484        try {
1485            p.exportSubtree(new ByteArrayOutputStream());
1486            fail("should throw MockRuntimeException");
1487        } catch (MockRuntimeException e) {
1488            // Expected
1489        }
1490        p.isRemovedImpl();
1491        try {
1492            p.getChildImpl(null);
1493            fail("should throw MockRuntimeException");
1494        } catch (MockRuntimeException e) {
1495            // Expected
1496        }
1497        p.cachedChildrenImpl();
1498    }
1499
1500    public void testSPIReturnNull() throws IOException, BackingStoreException {
1501        if (!(pref instanceof MockAbstractPreferences)) {
1502            return;
1503        }
1504        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1505        p.setResult(MockAbstractPreferences.returnNull);
1506        try {
1507            p.childrenNames();
1508            fail("should throw NullPointerException");
1509        } catch (NullPointerException e) {
1510            // Expected
1511        }
1512        p.absolutePath();
1513        p.toString();
1514        p.put("nullkey", "value");
1515        assertEquals("null default", p.get("key", "null default"));
1516        p.remove("key");
1517        try {
1518            p.clear();
1519            fail("should throw NullPointerException");
1520        } catch (NullPointerException e) {
1521            // Expected
1522        }
1523        p.putInt("key", 3);
1524        p.getInt("key", 3);
1525        p.putLong("key", 3l);
1526        p.getLong("key", 3l);
1527        p.putDouble("key", 3);
1528        p.getDouble("key", 3);
1529        p.putBoolean("key", true);
1530        p.getBoolean("key", true);
1531        p.putFloat("key", 3f);
1532        p.getFloat("key", 3f);
1533        p.putByteArray("key", new byte[0]);
1534        p.getByteArray("key", new byte[0]);
1535        p.keys();
1536        try {
1537            p.childrenNames();
1538            fail("should throw NullPointerException");
1539        } catch (NullPointerException e) {
1540            // Expected
1541        }
1542        p.parent();
1543        p.node("");
1544        p.nodeExists("");
1545        try {
1546            p.removeNode();
1547            fail("should throw NullPointerException");
1548        } catch (NullPointerException e) {
1549            // Expected
1550        }
1551        p.name();
1552        p.absolutePath();
1553        p.isUserNode();
1554        MockPreferenceChangeListener mockPreferenceChangeListener = new MockPreferenceChangeListener();
1555        p.addPreferenceChangeListener(mockPreferenceChangeListener);
1556        p.removePreferenceChangeListener(mockPreferenceChangeListener);
1557        MockNodeChangeListener mockNodeChangeListener = new MockNodeChangeListener();
1558        p.addNodeChangeListener(mockNodeChangeListener);
1559        p.removeNodeChangeListener(mockNodeChangeListener);
1560        p.toString();
1561        p.sync();
1562        p.flush();
1563        try {
1564            p.exportNode(System.out);
1565            fail("should throw NullPointerException");
1566        } catch (NullPointerException e) {
1567            // Expected
1568        }
1569        try {
1570            p.exportSubtree(System.out);
1571            fail("should throw NullPointerException");
1572        } catch (NullPointerException e) {
1573            // Expected
1574        }
1575        p.isRemovedImpl();
1576        try {
1577            p.getChildImpl("");
1578            fail("should throw NullPointerException");
1579        } catch (NullPointerException e) {
1580            // Expected
1581        }
1582        p.cachedChildrenImpl();
1583    }
1584
1585    public void testIllegalStateException() throws IOException,
1586    BackingStoreException {
1587        if (!(pref instanceof MockAbstractPreferences)) {
1588            return;
1589        }
1590        pref.removeNode();
1591        // after remove node, every methods, except name(), absolutePath(),
1592        // isUserNode(), flush() or nodeExists(""),
1593        // will throw illegal state exception
1594        pref.nodeExists("");
1595        pref.name();
1596        pref.absolutePath();
1597        pref.isUserNode();
1598        pref.toString();
1599        pref.flush();
1600        try {
1601            pref.nodeExists("child");
1602            fail("should throw IllegalStateException");
1603        } catch (IllegalStateException e) {
1604            // Expected
1605        }
1606        try {
1607            pref.childrenNames();
1608            fail("should throw IllegalStateException");
1609        } catch (IllegalStateException e) {
1610            // Expected
1611        }
1612        try {
1613            pref.remove(null);
1614            fail("should throw IllegalStateException");
1615        } catch (IllegalStateException e) {
1616            // Expected
1617        }
1618        try {
1619            pref.clear();
1620            fail("should throw IllegalStateException");
1621        } catch (IllegalStateException e) {
1622            // Expected
1623        }
1624        try {
1625            pref.get("key", "null default");
1626            fail("should throw IllegalStateException");
1627        } catch (IllegalStateException e) {
1628            // Expected
1629        }
1630        try {
1631            pref.put("nullkey", "value");
1632            fail("should throw IllegalStateException");
1633        } catch (IllegalStateException e) {
1634            // Expected
1635        }
1636        try {
1637            pref.putInt("key", 3);
1638            fail("should throw IllegalStateException");
1639        } catch (IllegalStateException e) {
1640            // Expected
1641        }
1642        try {
1643            pref.getInt("key", 3);
1644            fail("should throw IllegalStateException");
1645        } catch (IllegalStateException e) {
1646            // Expected
1647        }
1648        try {
1649            pref.putLong("key", 3l);
1650            fail("should throw IllegalStateException");
1651        } catch (IllegalStateException e) {
1652            // Expected
1653        }
1654        try {
1655            pref.getLong("key", 3l);
1656            fail("should throw IllegalStateException");
1657        } catch (IllegalStateException e) {
1658            // Expected
1659        }
1660        try {
1661            pref.putDouble("key", 3);
1662            fail("should throw IllegalStateException");
1663        } catch (IllegalStateException e) {
1664            // Expected
1665        }
1666        try {
1667            pref.getDouble("key", 3);
1668            fail("should throw IllegalStateException");
1669        } catch (IllegalStateException e) {
1670            // Expected
1671        }
1672        try {
1673            pref.putBoolean("key", true);
1674            fail("should throw IllegalStateException");
1675        } catch (IllegalStateException e) {
1676            // Expected
1677        }
1678        try {
1679            pref.getBoolean("key", true);
1680            fail("should throw IllegalStateException");
1681        } catch (IllegalStateException e) {
1682            // Expected
1683        }
1684        try {
1685            pref.putFloat("key", 3f);
1686            fail("should throw IllegalStateException");
1687        } catch (IllegalStateException e) {
1688            // Expected
1689        }
1690        try {
1691            pref.getFloat("key", 3f);
1692            fail("should throw IllegalStateException");
1693        } catch (IllegalStateException e) {
1694            // Expected
1695        }
1696        try {
1697            pref.putByteArray("key", new byte[0]);
1698            fail("should throw IllegalStateException");
1699        } catch (IllegalStateException e) {
1700            // Expected
1701        }
1702        try {
1703            pref.getByteArray("key", new byte[0]);
1704            fail("should throw IllegalStateException");
1705        } catch (IllegalStateException e) {
1706            // Expected
1707        }
1708        try {
1709            pref.keys();
1710            fail("should throw IllegalStateException");
1711        } catch (IllegalStateException e) {
1712            // Expected
1713        }
1714        try {
1715            pref.keys();
1716            fail("should throw IllegalStateException");
1717        } catch (IllegalStateException e) {
1718            // Expected
1719        }
1720        try {
1721            pref.childrenNames();
1722            fail("should throw IllegalStateException");
1723        } catch (IllegalStateException e) {
1724            // Expected
1725        }
1726        try {
1727            pref.parent();
1728            fail("should throw IllegalStateException");
1729        } catch (IllegalStateException e) {
1730            // Expected
1731        }
1732        try {
1733            pref.node(null);
1734            fail("should throw IllegalStateException");
1735        } catch (IllegalStateException e) {
1736            // Expected
1737        }
1738        try {
1739            pref.removeNode();
1740            fail("should throw IllegalStateException");
1741        } catch (IllegalStateException e) {
1742            // Expected
1743        }
1744        try {
1745            pref
1746                    .addPreferenceChangeListener(new MockPreferenceChangeListener());
1747            fail("should throw IllegalStateException");
1748        } catch (IllegalStateException e) {
1749            // Expected
1750        }
1751        try {
1752            pref
1753                    .removePreferenceChangeListener(new MockPreferenceChangeListener());
1754            fail("should throw IllegalStateException");
1755        } catch (IllegalStateException e) {
1756            // Expected
1757        }
1758        try {
1759            pref.addNodeChangeListener(new MockNodeChangeListener());
1760            fail("should throw IllegalStateException");
1761        } catch (IllegalStateException e) {
1762            // Expected
1763        }
1764        try {
1765            pref.removeNodeChangeListener(new MockNodeChangeListener());
1766            fail("should throw IllegalStateException");
1767        } catch (IllegalStateException e) {
1768            // Expected
1769        }
1770        try {
1771            pref.sync();
1772            fail("should throw IllegalStateException");
1773        } catch (IllegalStateException e) {
1774            // Expected
1775        }
1776        try {
1777            pref.exportNode(null);
1778            fail("should throw IllegalStateException");
1779        } catch (IllegalStateException e) {
1780            // Expected
1781        }
1782        try {
1783            pref.exportSubtree(null);
1784            fail("should throw IllegalStateException");
1785        } catch (IllegalStateException e) {
1786            // Expected
1787        }
1788        if (!(pref instanceof MockAbstractPreferences)) {
1789            return;
1790        }
1791        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1792        p.isRemovedImpl();
1793        p.cachedChildrenImpl();
1794        try {
1795            p.getChildImpl(null);
1796            fail("should throw IllegalStateException");
1797        } catch (IllegalStateException e) {
1798            // Expected
1799        }
1800    }
1801
1802    public void testNullAndIllegalStateException() throws Exception {
1803        if (!(pref instanceof MockAbstractPreferences)) {
1804            return;
1805        }
1806        MockAbstractPreferences p = (MockAbstractPreferences) pref;
1807        p.removeNode();
1808        try {
1809            p.get(null, "null default");
1810            fail("should throw NullPointerException");
1811        } catch (NullPointerException e) {
1812            // Expected
1813        }
1814        try {
1815            p.put(null, "value");
1816            fail("should throw NullPointerException");
1817        } catch (NullPointerException e) {
1818            // Expected
1819        }
1820        try {
1821            p.putInt(null, 3);
1822            fail("should throw NullPointerException");
1823        } catch (NullPointerException e) {
1824            // Expected
1825        }
1826        try {
1827            p.getInt(null, 3);
1828            fail("should throw NullPointerException");
1829        } catch (NullPointerException e) {
1830            // Expected
1831        }
1832        try {
1833            p.putLong(null, 3l);
1834            fail("should throw NullPointerException");
1835        } catch (NullPointerException e) {
1836            // Expected
1837        }
1838        try {
1839            p.getLong(null, 3l);
1840            fail("should throw NullPointerException");
1841        } catch (NullPointerException e) {
1842            // Expected
1843        }
1844        try {
1845            p.putDouble(null, 3);
1846            fail("should throw NullPointerException");
1847        } catch (NullPointerException e) {
1848            // Expected
1849        }
1850        try {
1851            p.getDouble(null, 3);
1852            fail("should throw NullPointerException");
1853        } catch (NullPointerException e) {
1854            // Expected
1855        }
1856        try {
1857            p.putBoolean(null, true);
1858            fail("should throw NullPointerException");
1859        } catch (NullPointerException e) {
1860            // Expected
1861        }
1862        try {
1863            p.getBoolean(null, true);
1864            fail("should throw NullPointerException");
1865        } catch (NullPointerException e) {
1866            // Expected
1867        }
1868        try {
1869            p.putFloat(null, 3f);
1870            fail("should throw NullPointerException");
1871        } catch (NullPointerException e) {
1872            // Expected
1873        }
1874        try {
1875            p.getFloat(null, 3f);
1876            fail("should throw NullPointerException");
1877        } catch (NullPointerException e) {
1878            // Expected
1879        }
1880        try {
1881            p.putByteArray(null, new byte[0]);
1882            fail("should throw NullPointerException");
1883        } catch (NullPointerException e) {
1884            // Expected
1885        }
1886        try {
1887            p.getByteArray(null, new byte[0]);
1888            fail("should throw NullPointerException");
1889        } catch (NullPointerException e) {
1890            // Expected
1891        }
1892        try {
1893            p.addPreferenceChangeListener(null);
1894            fail("should throw NullPointerException");
1895        } catch (NullPointerException e) {
1896            // Expected
1897        }
1898        try {
1899            p.removePreferenceChangeListener(null);
1900            fail("should throw IllegalStateException");
1901        } catch (IllegalStateException e) {
1902            // Expected
1903        }
1904        try {
1905            p.addNodeChangeListener(null);
1906            fail("should throw NullPointerException");
1907        } catch (NullPointerException e) {
1908            // Expected
1909        }
1910        try {
1911            p.removeNodeChangeListener(null);
1912            fail("should throw IllegalStateException");
1913        } catch (IllegalStateException e) {
1914            // Expected
1915        }
1916    }
1917
1918    /**
1919     * Regression for HARMONY-828
1920     */
1921    public void testLongPath() throws Exception {
1922        assertFalse(pref.nodeExists("ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"));
1923    }
1924
1925    public static class MockPreferenceChangeListener implements
1926    PreferenceChangeListener {
1927        private int changed = 0;
1928
1929        // private Object lock = new Object();
1930
1931        public void preferenceChange(PreferenceChangeEvent pce) {
1932            // synchronized(lock){
1933            changed++;
1934            // }
1935        }
1936
1937        public int getChanged() {
1938            // synchronized(lock){
1939            int result = changed;
1940            changed = 0;
1941            return result;
1942            // }
1943        }
1944    }
1945
1946    public static class MockNodeChangeListener implements NodeChangeListener {
1947        private boolean addDispatched = false;
1948
1949        private boolean removeDispatched = false;
1950
1951        private Object addLock = new Object();
1952
1953        private Object removeLock = new Object();
1954
1955        private int added = 0;
1956
1957        private int removed = 0;
1958
1959        public void childAdded(NodeChangeEvent e) {
1960            synchronized (addLock) {
1961                ++added;
1962                addDispatched = true;
1963                addLock.notifyAll();
1964            }
1965        }
1966
1967        public void childRemoved(NodeChangeEvent e) {
1968            synchronized (removeLock) {
1969                removed++;
1970                removeDispatched = true;
1971                removeLock.notifyAll();
1972            }
1973        }
1974
1975        public int getAdded() {
1976            synchronized (addLock) {
1977                if (!addDispatched) {
1978                    try {
1979                        // TODO: don't know why must add limitation
1980                        addLock.wait(100);
1981                    } catch (InterruptedException e) {
1982                        e.printStackTrace();
1983                    }
1984                }
1985                addDispatched = false;
1986            }
1987            return added;
1988        }
1989
1990        public int getRemoved() {
1991            synchronized (removeLock) {
1992                if (!removeDispatched) {
1993                    try {
1994                        removeLock.wait(100);
1995                    } catch (InterruptedException e) {
1996                        e.printStackTrace();
1997                    }
1998                }
1999                removeDispatched = false;
2000            }
2001            return removed;
2002
2003        }
2004
2005        public void reset() {
2006            added = 0;
2007            removed = 0;
2008        }
2009    }
2010
2011}
2012