• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base.shared_preferences;
6 
7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertFalse;
9 import static org.junit.Assert.assertNull;
10 import static org.junit.Assert.assertTrue;
11 import static org.mockito.ArgumentMatchers.eq;
12 import static org.mockito.Mockito.times;
13 import static org.mockito.Mockito.verify;
14 
15 import androidx.test.filters.SmallTest;
16 
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.junit.runner.RunWith;
20 import org.mockito.Mock;
21 import org.mockito.MockitoAnnotations;
22 
23 import org.chromium.base.test.BaseRobolectricTestRunner;
24 
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /** Unit tests for {@link SharedPreferencesManager}. */
32 @RunWith(BaseRobolectricTestRunner.class)
33 public class SharedPreferencesManagerTest {
34     @Mock private PreferenceKeyChecker mChecker;
35 
36     private static final KeyPrefix TEST_PREFIX = new KeyPrefix("TestPrefix.*");
37     private static final String PREFIXED_KEY_1 = TEST_PREFIX.createKey("stemA");
38     private static final String PREFIXED_KEY_2 = TEST_PREFIX.createKey("stemB");
39     private static final String PREFIXED_KEY_3 = TEST_PREFIX.createKey(33);
40 
41     private SharedPreferencesManager mSubject;
42 
43     @Before
setUp()44     public void setUp() {
45         MockitoAnnotations.initMocks(this);
46         mSubject = new SharedPreferencesManager(mChecker);
47     }
48 
49     @Test
50     @SmallTest
testWriteReadInt()51     public void testWriteReadInt() {
52         // Verify default return values when no value is written.
53         assertEquals(0, mSubject.readInt("int_key"));
54         assertEquals(987, mSubject.readInt("int_key", 987));
55         assertFalse(mSubject.contains("int_key"));
56 
57         // Write a value.
58         mSubject.writeInt("int_key", 123);
59 
60         // Verify value written can be read.
61         assertEquals(123, mSubject.readInt("int_key"));
62         assertEquals(123, mSubject.readInt("int_key", 987));
63         assertTrue(mSubject.contains("int_key"));
64 
65         // Remove the value.
66         mSubject.removeKey("int_key");
67 
68         // Verify the removed value is not returned anymore.
69         assertEquals(0, mSubject.readInt("int_key"));
70         assertFalse(mSubject.contains("int_key"));
71     }
72 
73     @Test
74     @SmallTest
testIncrementInt()75     public void testIncrementInt() {
76         mSubject.writeInt("int_key", 100);
77         int result = mSubject.incrementInt("int_key");
78 
79         assertEquals(101, result);
80         assertEquals(101, mSubject.readInt("int_key"));
81     }
82 
83     @Test
84     @SmallTest
testIncrementIntDefault()85     public void testIncrementIntDefault() {
86         int result = mSubject.incrementInt("int_key");
87 
88         assertEquals(1, result);
89         assertEquals(1, mSubject.readInt("int_key"));
90     }
91 
92     @Test
93     @SmallTest
testWriteReadBoolean()94     public void testWriteReadBoolean() {
95         // Verify default return values when no value is written.
96         assertEquals(false, mSubject.readBoolean("bool_key", false));
97         assertEquals(true, mSubject.readBoolean("bool_key", true));
98         assertFalse(mSubject.contains("bool_key"));
99 
100         // Write a value.
101         mSubject.writeBoolean("bool_key", true);
102 
103         // Verify value written can be read.
104         assertEquals(true, mSubject.readBoolean("bool_key", false));
105         assertEquals(true, mSubject.readBoolean("bool_key", true));
106         assertTrue(mSubject.contains("bool_key"));
107 
108         // Remove the value.
109         mSubject.removeKey("bool_key");
110 
111         // Verify the removed value is not returned anymore.
112         assertEquals(false, mSubject.readBoolean("bool_key", false));
113         assertEquals(true, mSubject.readBoolean("bool_key", true));
114         assertFalse(mSubject.contains("bool_key"));
115     }
116 
117     @Test
118     @SmallTest
testWriteReadString()119     public void testWriteReadString() {
120         // Verify default return values when no value is written.
121         assertEquals("default", mSubject.readString("string_key", "default"));
122         assertFalse(mSubject.contains("string_key"));
123 
124         // Write a value.
125         mSubject.writeString("string_key", "foo");
126 
127         // Verify value written can be read.
128         assertEquals("foo", mSubject.readString("string_key", "default"));
129         assertTrue(mSubject.contains("string_key"));
130 
131         // Remove the value.
132         mSubject.removeKey("string_key");
133 
134         // Verify the removed value is not returned anymore.
135         assertEquals("default", mSubject.readString("string_key", "default"));
136         assertFalse(mSubject.contains("string_key"));
137     }
138 
139     @Test
140     @SmallTest
testWriteReadLong()141     public void testWriteReadLong() {
142         // Verify default return values when no value is written.
143         assertEquals(0, mSubject.readLong("long_key"));
144         assertEquals(9876543210L, mSubject.readLong("long_key", 9876543210L));
145         assertFalse(mSubject.contains("long_key"));
146 
147         // Write a value.
148         mSubject.writeLong("long_key", 9999999999L);
149 
150         // Verify value written can be read.
151         assertEquals(9999999999L, mSubject.readLong("long_key"));
152         assertEquals(9999999999L, mSubject.readLong("long_key", 9876543210L));
153         assertTrue(mSubject.contains("long_key"));
154 
155         // Remove the value.
156         mSubject.removeKey("long_key");
157 
158         // Verify the removed value is not returned anymore.
159         assertEquals(0, mSubject.readLong("long_key"));
160         assertFalse(mSubject.contains("long_key"));
161     }
162 
163     @Test
164     @SmallTest
testWriteReadFloat()165     public void testWriteReadFloat() {
166         // Verify default return values when no value is written.
167         assertEquals(1.5f, mSubject.readFloat("float_key", 1.5f), 0.001f);
168         assertFalse(mSubject.contains("float_key"));
169 
170         // Write a value.
171         mSubject.writeFloat("float_key", 42.42f);
172 
173         // Verify value written can be read.
174         assertEquals(42.42f, mSubject.readFloat("float_key", 1.5f), 0.001f);
175         assertTrue(mSubject.contains("float_key"));
176 
177         // Remove the value.
178         mSubject.removeKey("float_key");
179 
180         // Verify the removed value is not returned anymore.
181         assertEquals(1.5f, mSubject.readFloat("float_key", 1.5f), 0.001f);
182         assertFalse(mSubject.contains("float_key"));
183     }
184 
185     @Test
186     @SmallTest
testWriteReadDouble()187     public void testWriteReadDouble() {
188         // Verify default return values when no value is written.
189         assertEquals(1.5d, mSubject.readDouble("double_key", 1.5d), 0.001f);
190         assertFalse(mSubject.contains("double_key"));
191 
192         // Write a value.
193         mSubject.writeDouble("double_key", 42.42f);
194 
195         // Verify value written can be read.
196         assertEquals(42.42d, mSubject.readDouble("double_key", 1.5d), 0.001f);
197         assertTrue(mSubject.contains("double_key"));
198 
199         // Remove the value.
200         mSubject.removeKey("double_key");
201 
202         // Verify the removed value is not returned anymore.
203         assertEquals(1.5d, mSubject.readDouble("double_key", 1.5d), 0.001f);
204         assertFalse(mSubject.contains("double_key"));
205     }
206 
207     @Test
208     @SmallTest
testWriteReadStringSet()209     public void testWriteReadStringSet() {
210         Set<String> defaultStringSet = new HashSet<>(Arrays.asList("a", "b", "c"));
211         Set<String> exampleStringSet = new HashSet<>(Arrays.asList("d", "e"));
212 
213         // Verify default return values when no value is written.
214         assertEquals(Collections.emptySet(), mSubject.readStringSet("string_set_key"));
215         assertEquals(defaultStringSet, mSubject.readStringSet("string_set_key", defaultStringSet));
216         assertNull(mSubject.readStringSet("string_set_key", null));
217         assertFalse(mSubject.contains("string_set_key"));
218 
219         // Write a value.
220         mSubject.writeStringSet("string_set_key", exampleStringSet);
221 
222         // Verify value written can be read.
223         assertEquals(exampleStringSet, mSubject.readStringSet("string_set_key"));
224         assertEquals(exampleStringSet, mSubject.readStringSet("string_set_key", defaultStringSet));
225         assertEquals(exampleStringSet, mSubject.readStringSet("string_set_key", null));
226         assertTrue(mSubject.contains("string_set_key"));
227 
228         // Remove the value.
229         mSubject.removeKey("string_set_key");
230 
231         // Verify the removed value is not returned anymore.
232         assertEquals(Collections.emptySet(), mSubject.readStringSet("string_set_key"));
233         assertFalse(mSubject.contains("string_set_key"));
234     }
235 
236     @Test
237     @SmallTest
testAddToStringSet()238     public void testAddToStringSet() {
239         mSubject.writeStringSet("string_set_key", new HashSet<>(Collections.singletonList("bar")));
240         mSubject.addToStringSet("string_set_key", "foo");
241 
242         assertEquals(
243                 new HashSet<>(Arrays.asList("foo", "bar")),
244                 mSubject.readStringSet("string_set_key"));
245     }
246 
247     @Test
248     @SmallTest
testAddToStringSetDefault()249     public void testAddToStringSetDefault() {
250         mSubject.addToStringSet("string_set_key", "foo");
251 
252         assertEquals(
253                 new HashSet<>(Collections.singletonList("foo")),
254                 mSubject.readStringSet("string_set_key"));
255     }
256 
257     @Test
258     @SmallTest
testRemoveFromStringSet()259     public void testRemoveFromStringSet() {
260         mSubject.writeStringSet("string_set_key", new HashSet<>(Arrays.asList("foo", "bar")));
261         mSubject.removeFromStringSet("string_set_key", "foo");
262 
263         assertEquals(
264                 new HashSet<>(Collections.singletonList("bar")),
265                 mSubject.readStringSet("string_set_key"));
266     }
267 
268     @Test
269     @SmallTest
testRemoveFromStringSetDefault()270     public void testRemoveFromStringSetDefault() {
271         mSubject.removeFromStringSet("string_set_key", "foo");
272 
273         assertEquals(Collections.emptySet(), mSubject.readStringSet("string_set_key"));
274     }
275 
276     @Test(expected = UnsupportedOperationException.class)
277     @SmallTest
testReadStringSet_nonEmpty_returnsUnmodifiable()278     public void testReadStringSet_nonEmpty_returnsUnmodifiable() {
279         Set<String> exampleStringSet = new HashSet<>(Arrays.asList("d", "e"));
280         mSubject.writeStringSet("string_set_key", exampleStringSet);
281 
282         Set<String> unmodifiableSet = mSubject.readStringSet("string_set_key");
283 
284         // Should throw an exception
285         unmodifiableSet.add("f");
286     }
287 
288     @Test
289     @SmallTest
testWriteIntSync()290     public void testWriteIntSync() throws InterruptedException {
291         // Verify default return values when no value is written.
292         assertEquals(0, mSubject.readInt("int_key"));
293 
294         // Write a value on a background thread.
295         Thread t = new Thread(() -> mSubject.writeIntSync("int_key", 123));
296         t.start();
297         t.join();
298 
299         // Verify value written can be read.
300         assertEquals(123, mSubject.readInt("int_key"));
301     }
302 
303     @Test
304     @SmallTest
testWriteBooleanSync()305     public void testWriteBooleanSync() throws InterruptedException {
306         // Verify default return values when no value is written.
307         assertEquals(false, mSubject.readBoolean("bool_key", false));
308 
309         // Write a value on a background thread.
310         Thread t = new Thread(() -> mSubject.writeBooleanSync("bool_key", true));
311         t.start();
312         t.join();
313 
314         // Verify value written can be read.
315         assertEquals(true, mSubject.readBoolean("bool_key", false));
316     }
317 
318     @Test
319     @SmallTest
testWriteStringSync()320     public void testWriteStringSync() throws InterruptedException {
321         // Verify default return values when no value is written.
322         assertEquals("default", mSubject.readString("string_key", "default"));
323 
324         // Write a value on a background thread.
325         Thread t = new Thread(() -> mSubject.writeStringSync("string_key", "foo"));
326         t.start();
327         t.join();
328 
329         // Verify value written can be read.
330         assertEquals("foo", mSubject.readString("string_key", "default"));
331     }
332 
333     @Test
334     @SmallTest
testWriteLongSync()335     public void testWriteLongSync() throws InterruptedException {
336         // Verify default return values when no value is written.
337         assertEquals(0, mSubject.readLong("long_key"));
338 
339         // Write a value on a background thread.
340         Thread t = new Thread(() -> mSubject.writeLongSync("long_key", 9999999999L));
341         t.start();
342         t.join();
343 
344         // Verify value written can be read.
345         assertEquals(9999999999L, mSubject.readLong("long_key"));
346     }
347 
348     @Test
349     @SmallTest
testWriteFloatSync()350     public void testWriteFloatSync() throws InterruptedException {
351         // Verify default return values when no value is written.
352         assertEquals(0f, mSubject.readFloat("float_key", 0f), 0f);
353 
354         // Write a value on a background thread.
355         Thread t = new Thread(() -> mSubject.writeFloatSync("float_key", 42.42f));
356         t.start();
357         t.join();
358 
359         // Verify value written can be read.
360         assertEquals(42.42f, mSubject.readFloat("float_key", 1.5f), 0.001f);
361     }
362 
363     @Test
364     @SmallTest
testRemoveKeySync()365     public void testRemoveKeySync() throws InterruptedException {
366         // Write a value.
367         mSubject.writeInt("int_key", 123);
368         assertEquals(123, mSubject.readInt("int_key", 999));
369 
370         // Write the value on a background thread.
371         Thread t = new Thread(() -> mSubject.removeKeySync("int_key"));
372         t.start();
373         t.join();
374 
375         // Verify value was removed.
376         assertEquals(999, mSubject.readInt("int_key", 999));
377     }
378 
379     @Test
380     @SmallTest
testRemoveKeys()381     public void testRemoveKeys() {
382         KeyPrefix otherPrefix = new KeyPrefix("OtherPrefix.*");
383 
384         // Write some values, both prefixes and not prefixed.
385         mSubject.writeInt(PREFIXED_KEY_1, 111);
386         mSubject.writeInt(PREFIXED_KEY_2, 222);
387         mSubject.writeInt(PREFIXED_KEY_3, 333);
388         mSubject.writeInt(otherPrefix.createKey("stemA"), 444);
389         mSubject.writeInt("OtherKey", 555);
390 
391         // Remove them
392         mSubject.removeKeysWithPrefix(TEST_PREFIX);
393 
394         // Verify only values for the given prefix were removed.
395         assertEquals(0, mSubject.readInt(PREFIXED_KEY_1, 0));
396         assertEquals(0, mSubject.readInt(PREFIXED_KEY_2, 0));
397         assertEquals(0, mSubject.readInt(PREFIXED_KEY_3, 0));
398         assertEquals(444, mSubject.readInt(otherPrefix.createKey("stemA"), 0));
399         assertEquals(555, mSubject.readInt("OtherKey", 0));
400     }
401 
402     @Test
403     @SmallTest
testReadStringsWithPrefix()404     public void testReadStringsWithPrefix() {
405         // Write some values.
406         mSubject.writeString(PREFIXED_KEY_1, "first");
407         mSubject.writeString(PREFIXED_KEY_2, "second");
408         mSubject.writeString(PREFIXED_KEY_3, "third");
409         mSubject.writeString("OtherKey", "fourth");
410 
411         // Verify values written are read with readStringsWithPrefix().
412         Map<String, String> result = mSubject.readStringsWithPrefix(TEST_PREFIX);
413         assertEquals(3, result.size());
414 
415         assertEquals("first", result.get(PREFIXED_KEY_1));
416         assertEquals("second", result.get(PREFIXED_KEY_2));
417         assertEquals("third", result.get(PREFIXED_KEY_3));
418     }
419 
420     @Test
421     @SmallTest
testReadIntsWithPrefix()422     public void testReadIntsWithPrefix() {
423         // Write some values.
424         mSubject.writeInt(PREFIXED_KEY_1, 1);
425         mSubject.writeInt(PREFIXED_KEY_2, 2);
426         mSubject.writeInt(PREFIXED_KEY_3, 3);
427         mSubject.writeInt("OtherKey", 4);
428 
429         // Verify values written are read with readIntsWithPrefix().
430         Map<String, Integer> result = mSubject.readIntsWithPrefix(TEST_PREFIX);
431         assertEquals(3, result.size());
432         assertEquals(1, result.get(PREFIXED_KEY_1).intValue());
433         assertEquals(2, result.get(PREFIXED_KEY_2).intValue());
434         assertEquals(3, result.get(PREFIXED_KEY_3).intValue());
435     }
436 
437     @Test
438     @SmallTest
testReadLongsWithPrefix()439     public void testReadLongsWithPrefix() {
440         // Write some values.
441         mSubject.writeLong(PREFIXED_KEY_1, 21474836470001L);
442         mSubject.writeLong(PREFIXED_KEY_2, 21474836470002L);
443         mSubject.writeLong(PREFIXED_KEY_3, 21474836470003L);
444         mSubject.writeLong("OtherKey", 21474836470004L);
445 
446         // Verify values written are read with readLongsWithPrefix().
447         Map<String, Long> result = mSubject.readLongsWithPrefix(TEST_PREFIX);
448         assertEquals(3, result.size());
449         assertEquals(21474836470001L, result.get(PREFIXED_KEY_1).longValue());
450         assertEquals(21474836470002L, result.get(PREFIXED_KEY_2).longValue());
451         assertEquals(21474836470003L, result.get(PREFIXED_KEY_3).longValue());
452     }
453 
454     @Test
455     @SmallTest
testReadFloatsWithPrefix()456     public void testReadFloatsWithPrefix() {
457         // Write some values.
458         mSubject.writeFloat(PREFIXED_KEY_1, 1.0f);
459         mSubject.writeFloat(PREFIXED_KEY_2, 2.5f);
460         mSubject.writeFloat(PREFIXED_KEY_3, 3.5f);
461         mSubject.writeFloat("OtherKey", 4.0f);
462 
463         // Verify values written are read with readFloatsWithPrefix().
464         Map<String, Float> result = mSubject.readFloatsWithPrefix(TEST_PREFIX);
465         assertEquals(3, result.size());
466         assertEquals(1.0f, result.get(PREFIXED_KEY_1), 1e-10);
467         assertEquals(2.5f, result.get(PREFIXED_KEY_2), 1e-10);
468         assertEquals(3.5f, result.get(PREFIXED_KEY_3), 1e-10);
469     }
470 
471     @Test
472     @SmallTest
testReadDoublesWithPrefix()473     public void testReadDoublesWithPrefix() {
474         // Write some values.
475         mSubject.writeDouble(PREFIXED_KEY_1, 1.0);
476         mSubject.writeDouble(PREFIXED_KEY_2, 2.5);
477         mSubject.writeDouble(PREFIXED_KEY_3, 3.5);
478         mSubject.writeDouble("OtherKey", 4.0);
479 
480         // Verify values written are read with readDoublesWithPrefix().
481         Map<String, Double> result = mSubject.readDoublesWithPrefix(TEST_PREFIX);
482         assertEquals(3, result.size());
483         assertEquals(1.0, result.get(PREFIXED_KEY_1), 1e-10);
484         assertEquals(2.5, result.get(PREFIXED_KEY_2), 1e-10);
485         assertEquals(3.5, result.get(PREFIXED_KEY_3).doubleValue(), 1e-10);
486     }
487 
488     @Test
489     @SmallTest
testReadBooleansWithPrefix()490     public void testReadBooleansWithPrefix() {
491         // Write some values.
492         mSubject.writeBoolean(PREFIXED_KEY_1, true);
493         mSubject.writeBoolean(PREFIXED_KEY_2, false);
494         mSubject.writeBoolean(PREFIXED_KEY_3, true);
495         mSubject.writeBoolean("OtherKey", true);
496 
497         // Verify values written are read with readBooleansWithPrefix().
498         Map<String, Boolean> result = mSubject.readBooleansWithPrefix(TEST_PREFIX);
499         assertEquals(3, result.size());
500         assertTrue(result.get(PREFIXED_KEY_1));
501         assertFalse(result.get(PREFIXED_KEY_2));
502         assertTrue(result.get(PREFIXED_KEY_3));
503     }
504 
505     @Test
506     @SmallTest
testCheckerIsCalled()507     public void testCheckerIsCalled() {
508         mSubject.writeInt("int_key", 123);
509         verify(mChecker, times(1)).checkIsKeyInUse(eq("int_key"));
510         mSubject.readInt("int_key");
511         verify(mChecker, times(2)).checkIsKeyInUse(eq("int_key"));
512         mSubject.incrementInt("int_key");
513         verify(mChecker, times(3)).checkIsKeyInUse(eq("int_key"));
514 
515         mSubject.writeBoolean("bool_key", true);
516         verify(mChecker, times(1)).checkIsKeyInUse(eq("bool_key"));
517         mSubject.readBoolean("bool_key", false);
518         verify(mChecker, times(2)).checkIsKeyInUse(eq("bool_key"));
519 
520         mSubject.writeString("string_key", "foo");
521         verify(mChecker, times(1)).checkIsKeyInUse(eq("string_key"));
522         mSubject.readString("string_key", "");
523         verify(mChecker, times(2)).checkIsKeyInUse(eq("string_key"));
524 
525         mSubject.writeLong("long_key", 999L);
526         verify(mChecker, times(1)).checkIsKeyInUse(eq("long_key"));
527         mSubject.readLong("long_key");
528         verify(mChecker, times(2)).checkIsKeyInUse(eq("long_key"));
529 
530         mSubject.writeFloat("float_key", 2.5f);
531         verify(mChecker, times(1)).checkIsKeyInUse(eq("float_key"));
532         mSubject.readFloat("float_key", 0f);
533         verify(mChecker, times(2)).checkIsKeyInUse(eq("float_key"));
534 
535         mSubject.writeDouble("double_key", 2.5d);
536         verify(mChecker, times(1)).checkIsKeyInUse(eq("double_key"));
537         mSubject.readDouble("double_key", 0d);
538         verify(mChecker, times(2)).checkIsKeyInUse(eq("double_key"));
539 
540         mSubject.writeStringSet("string_set_key", new HashSet<>());
541         verify(mChecker, times(1)).checkIsKeyInUse(eq("string_set_key"));
542         mSubject.readStringSet("string_set_key");
543         verify(mChecker, times(2)).checkIsKeyInUse(eq("string_set_key"));
544         mSubject.addToStringSet("string_set_key", "bar");
545         verify(mChecker, times(3)).checkIsKeyInUse(eq("string_set_key"));
546         mSubject.removeFromStringSet("string_set_key", "bar");
547         verify(mChecker, times(4)).checkIsKeyInUse(eq("string_set_key"));
548 
549         mSubject.removeKey("some_key");
550         verify(mChecker, times(1)).checkIsKeyInUse(eq("some_key"));
551         mSubject.contains("some_key");
552         verify(mChecker, times(2)).checkIsKeyInUse(eq("some_key"));
553 
554         mSubject.readBooleansWithPrefix(TEST_PREFIX);
555         verify(mChecker, times(1)).checkIsPrefixInUse(eq(TEST_PREFIX));
556         mSubject.readIntsWithPrefix(TEST_PREFIX);
557         verify(mChecker, times(2)).checkIsPrefixInUse(eq(TEST_PREFIX));
558         mSubject.readLongsWithPrefix(TEST_PREFIX);
559         verify(mChecker, times(3)).checkIsPrefixInUse(eq(TEST_PREFIX));
560         mSubject.readFloatsWithPrefix(TEST_PREFIX);
561         verify(mChecker, times(4)).checkIsPrefixInUse(eq(TEST_PREFIX));
562         mSubject.readDoublesWithPrefix(TEST_PREFIX);
563         verify(mChecker, times(5)).checkIsPrefixInUse(eq(TEST_PREFIX));
564         mSubject.readStringsWithPrefix(TEST_PREFIX);
565         verify(mChecker, times(6)).checkIsPrefixInUse(eq(TEST_PREFIX));
566         mSubject.removeKeysWithPrefix(TEST_PREFIX);
567         verify(mChecker, times(7)).checkIsPrefixInUse(eq(TEST_PREFIX));
568     }
569 }
570