• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.provider;
18 
19 import static android.provider.DeviceConfig.Properties;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assert.assertTrue;
24 import static org.testng.Assert.assertThrows;
25 
26 import android.app.ActivityThread;
27 import android.content.ContentResolver;
28 import android.os.Bundle;
29 import android.platform.test.annotations.Presubmit;
30 
31 import androidx.test.InstrumentationRegistry;
32 import androidx.test.ext.junit.runners.AndroidJUnit4;
33 import androidx.test.filters.FlakyTest;
34 import androidx.test.filters.SmallTest;
35 
36 import org.junit.After;
37 import org.junit.Assert;
38 import org.junit.Ignore;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.util.HashMap;
43 import java.util.Map;
44 import java.util.Objects;
45 import java.util.concurrent.CompletableFuture;
46 import java.util.concurrent.ExecutionException;
47 import java.util.concurrent.TimeUnit;
48 import java.util.concurrent.TimeoutException;
49 import java.util.concurrent.atomic.AtomicReference;
50 
51 /** Tests that ensure appropriate settings are backed up. */
52 @Presubmit
53 @RunWith(AndroidJUnit4.class)
54 @SmallTest
55 public class DeviceConfigTest {
56     private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
57     private static final String DEFAULT_VALUE = "test_default_value";
58     private static final String NAMESPACE = "namespace1";
59     private static final String NAMESPACE2 = "namespace2";
60     private static final String KEY = "key1";
61     private static final String KEY2 = "key2";
62     private static final String KEY3 = "key3";
63     private static final String KEY4 = "key4";
64     private static final String VALUE = "value1";
65     private static final String VALUE2 = "value2";
66     private static final String VALUE3 = "value3";
67     private static final String NULL_VALUE = "null";
68 
69     @After
cleanUp()70     public void cleanUp() {
71         deleteViaContentProvider(NAMESPACE, KEY);
72         deleteViaContentProvider(NAMESPACE, KEY2);
73         deleteViaContentProvider(NAMESPACE, KEY3);
74         DeviceConfig.clearAllLocalOverrides();
75         DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE);
76     }
77 
78     /**
79      * Test that creating a sticky local override for a flag prevents further writes to that flag.
80      */
81     @Test
testAddStickyLocalOverridePreventsWrites()82     public void testAddStickyLocalOverridePreventsWrites() {
83         DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
84 
85         String key1Value = DeviceConfig.getProperty(NAMESPACE, KEY);
86         assertThat(key1Value).isEqualTo(VALUE);
87 
88         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, /* makeDefault= */ false);
89         key1Value = DeviceConfig.getProperty(NAMESPACE, KEY);
90         assertThat(key1Value).isEqualTo(VALUE);
91     }
92 
93     /**
94      * Test that when we locally override a flag, we can still write other flags.
95      */
96     @Test
testAddStickyLocalOverrideDoesNotAffectOtherFlags()97     public void testAddStickyLocalOverrideDoesNotAffectOtherFlags() {
98         DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
99         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, /* makeDefault= */ false);
100         String key2Value = DeviceConfig.getProperty(NAMESPACE, KEY2);
101         assertThat(key2Value).isEqualTo(VALUE2);
102     }
103 
104     /**
105      * Test that when we apply some overrides, they show up in the override list.
106      */
107     @Test
testGetStickyLocalOverrides()108     public void testGetStickyLocalOverrides() {
109         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false);
110         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE, false);
111         DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
112         DeviceConfig.setLocalOverride(NAMESPACE, KEY2, VALUE2);
113 
114         Map<String, Map<String, String>> expectedOverrides = new HashMap<>();
115         Map<String, String> expectedInnerMap = new HashMap<>();
116         expectedInnerMap.put(KEY, VALUE2);
117         expectedInnerMap.put(KEY2, VALUE);
118         expectedOverrides.put(NAMESPACE, expectedInnerMap);
119 
120         assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags())
121                 .isEqualTo(expectedOverrides);
122     }
123 
124     /**
125      * Test that when we clear all overrides, the override list is empty.
126      */
127     @Test
testClearStickyLocalOverrides()128     public void testClearStickyLocalOverrides() {
129         DeviceConfig.setLocalOverride(NAMESPACE2, KEY, VALUE);
130         DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2);
131 
132         DeviceConfig.clearAllLocalOverrides();
133 
134         Map<String, Map<String, String>> overrides =
135                 DeviceConfig.getUnderlyingValuesForOverriddenFlags();
136         assertThat(overrides).isEmpty();
137     }
138 
139     /**
140      * Test that when we clear a single override, it doesn't appear in the list.
141      */
142     @Test
testClearStickyLocalOverride()143     public void testClearStickyLocalOverride() {
144         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false);
145         DeviceConfig.setProperty(NAMESPACE2, KEY2, VALUE, false);
146         DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
147         DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2);
148 
149         DeviceConfig.clearLocalOverride(NAMESPACE, KEY);
150 
151         Map<String, Map<String, String>> expectedOverrides = new HashMap<>();
152         Map<String, String> expectedInnerMap = new HashMap<>();
153         expectedInnerMap.put(KEY2, VALUE);
154         expectedOverrides.put(NAMESPACE2, expectedInnerMap);
155 
156         assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags())
157                 .isEqualTo(expectedOverrides);
158     }
159 
160     @Test
getProperty_empty()161     public void getProperty_empty() {
162         String result = DeviceConfig.getProperty(NAMESPACE, KEY);
163         assertThat(result).isNull();
164     }
165 
166     @Test
getProperty_nullNamespace()167     public void getProperty_nullNamespace() {
168         try {
169             DeviceConfig.getProperty(null, KEY);
170             Assert.fail("Null namespace should have resulted in an NPE.");
171         } catch (NullPointerException e) {
172             // expected
173         }
174     }
175 
176     @Test
getProperty_nullName()177     public void getProperty_nullName() {
178         try {
179             DeviceConfig.getProperty(NAMESPACE, null);
180             Assert.fail("Null name should have resulted in an NPE.");
181         } catch (NullPointerException e) {
182             // expected
183         }
184     }
185 
186     @Test
getString_empty()187     public void getString_empty() {
188         final String default_value = "default_value";
189         final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
190         assertThat(result).isEqualTo(default_value);
191     }
192 
193     @Test
getString_nullDefault()194     public void getString_nullDefault() {
195         final String result = DeviceConfig.getString(NAMESPACE, KEY, null);
196         assertThat(result).isNull();
197     }
198 
199     @Test
getString_nonEmpty()200     public void getString_nonEmpty() {
201         final String value = "new_value";
202         final String default_value = "default";
203         DeviceConfig.setProperty(NAMESPACE, KEY, value, false);
204 
205         final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
206         assertThat(result).isEqualTo(value);
207     }
208 
209     @Test
getString_nullNamespace()210     public void getString_nullNamespace() {
211         try {
212             DeviceConfig.getString(null, KEY, "default_value");
213             Assert.fail("Null namespace should have resulted in an NPE.");
214         } catch (NullPointerException e) {
215             // expected
216         }
217     }
218 
219     @Test
getString_nullName()220     public void getString_nullName() {
221         try {
222             DeviceConfig.getString(NAMESPACE, null, "default_value");
223             Assert.fail("Null name should have resulted in an NPE.");
224         } catch (NullPointerException e) {
225             // expected
226         }
227     }
228 
229     @Test
getBoolean_empty()230     public void getBoolean_empty() {
231         final boolean default_value = true;
232         final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
233         assertThat(result).isEqualTo(default_value);
234     }
235 
236     @Test
getBoolean_valid()237     public void getBoolean_valid() {
238         final boolean value = true;
239         final boolean default_value = false;
240         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
241 
242         final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
243         assertThat(result).isEqualTo(value);
244     }
245 
246     @Test
getBoolean_invalid()247     public void getBoolean_invalid() {
248         final boolean default_value = true;
249         DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_boolean", false);
250 
251         final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
252         // Anything non-null other than case insensitive "true" parses to false.
253         assertThat(result).isFalse();
254     }
255 
256     @Test
getBoolean_nullNamespace()257     public void getBoolean_nullNamespace() {
258         try {
259             DeviceConfig.getBoolean(null, KEY, false);
260             Assert.fail("Null namespace should have resulted in an NPE.");
261         } catch (NullPointerException e) {
262             // expected
263         }
264     }
265 
266     @Test
getBoolean_nullName()267     public void getBoolean_nullName() {
268         try {
269             DeviceConfig.getBoolean(NAMESPACE, null, false);
270             Assert.fail("Null name should have resulted in an NPE.");
271         } catch (NullPointerException e) {
272             // expected
273         }
274     }
275 
276     @Test
getInt_empty()277     public void getInt_empty() {
278         final int default_value = 999;
279         final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
280         assertThat(result).isEqualTo(default_value);
281     }
282 
283     @Test
getInt_valid()284     public void getInt_valid() {
285         final int value = 123;
286         final int default_value = 999;
287         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
288 
289         final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
290         assertThat(result).isEqualTo(value);
291     }
292 
293     @Test
getInt_invalid()294     public void getInt_invalid() {
295         final int default_value = 999;
296         DeviceConfig.setProperty(NAMESPACE, KEY, "not_an_int", false);
297 
298         final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
299         // Failure to parse results in using the default value
300         assertThat(result).isEqualTo(default_value);
301     }
302 
303     @Test
getInt_nullNamespace()304     public void getInt_nullNamespace() {
305         try {
306             DeviceConfig.getInt(null, KEY, 0);
307             Assert.fail("Null namespace should have resulted in an NPE.");
308         } catch (NullPointerException e) {
309             // expected
310         }
311     }
312 
313     @Test
getInt_nullName()314     public void getInt_nullName() {
315         try {
316             DeviceConfig.getInt(NAMESPACE, null, 0);
317             Assert.fail("Null name should have resulted in an NPE.");
318         } catch (NullPointerException e) {
319             // expected
320         }
321     }
322 
323     @Test
getLong_empty()324     public void getLong_empty() {
325         final long default_value = 123456;
326         final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
327         assertThat(result).isEqualTo(default_value);
328     }
329 
330     @Test
getLong_valid()331     public void getLong_valid() {
332         final long value = 456789;
333         final long default_value = 123456;
334         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
335 
336         final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
337         assertThat(result).isEqualTo(value);
338     }
339 
340     @Test
getLong_invalid()341     public void getLong_invalid() {
342         final long default_value = 123456;
343         DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_long", false);
344 
345         final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
346         // Failure to parse results in using the default value
347         assertThat(result).isEqualTo(default_value);
348     }
349 
350     @Test
getLong_nullNamespace()351     public void getLong_nullNamespace() {
352         try {
353             DeviceConfig.getLong(null, KEY, 0);
354             Assert.fail("Null namespace should have resulted in an NPE.");
355         } catch (NullPointerException e) {
356             // expected
357         }
358     }
359 
360     @Test
getLong_nullName()361     public void getLong_nullName() {
362         try {
363             DeviceConfig.getLong(NAMESPACE, null, 0);
364             Assert.fail("Null name should have resulted in an NPE.");
365         } catch (NullPointerException e) {
366             // expected
367         }
368     }
369 
370     @Test
getFloat_empty()371     public void getFloat_empty() {
372         final float default_value = 123.456f;
373         final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
374         assertThat(result).isEqualTo(default_value);
375     }
376 
377     @Test
getFloat_valid()378     public void getFloat_valid() {
379         final float value = 456.789f;
380         final float default_value = 123.456f;
381         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
382 
383         final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
384         assertThat(result).isEqualTo(value);
385     }
386 
387     @Test
getFloat_invalid()388     public void getFloat_invalid() {
389         final float default_value = 123.456f;
390         DeviceConfig.setProperty(NAMESPACE, KEY, "not_a_float", false);
391 
392         final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
393         // Failure to parse results in using the default value
394         assertThat(result).isEqualTo(default_value);
395     }
396 
397     @Test
getFloat_nullNamespace()398     public void getFloat_nullNamespace() {
399         try {
400             DeviceConfig.getFloat(null, KEY, 0);
401             Assert.fail("Null namespace should have resulted in an NPE.");
402         } catch (NullPointerException e) {
403             // expected
404         }
405     }
406 
407     @Test
getFloat_nullName()408     public void getFloat_nullName() {
409         try {
410             DeviceConfig.getFloat(NAMESPACE, null, 0);
411             Assert.fail("Null name should have resulted in an NPE.");
412         } catch (NullPointerException e) {
413             // expected
414         }
415     }
416 
417     @Test
setProperty_nullNamespace()418     public void setProperty_nullNamespace() {
419         try {
420             DeviceConfig.setProperty(null, KEY, VALUE, false);
421             Assert.fail("Null namespace should have resulted in an NPE.");
422         } catch (NullPointerException e) {
423             // expected
424         }
425     }
426 
427     @Test
setProperty_nullName()428     public void setProperty_nullName() {
429         try {
430             DeviceConfig.setProperty(NAMESPACE, null, VALUE, false);
431             Assert.fail("Null name should have resulted in an NPE.");
432         } catch (NullPointerException e) {
433             // expected
434         }
435     }
436 
437     @Test
setAndGetProperty_sameNamespace()438     public void setAndGetProperty_sameNamespace() {
439         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
440         String result = DeviceConfig.getProperty(NAMESPACE, KEY);
441         assertThat(result).isEqualTo(VALUE);
442     }
443 
444     @Test
setAndGetProperty_differentNamespace()445     public void setAndGetProperty_differentNamespace() {
446         String newNamespace = "namespace2";
447         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
448         String result = DeviceConfig.getProperty(newNamespace, KEY);
449         assertThat(result).isNull();
450     }
451 
452     @Test
setAndGetProperty_multipleNamespaces()453     public void setAndGetProperty_multipleNamespaces() {
454         String newNamespace = "namespace2";
455         String newValue = "value2";
456         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
457         DeviceConfig.setProperty(newNamespace, KEY, newValue, false);
458         String result = DeviceConfig.getProperty(NAMESPACE, KEY);
459         assertThat(result).isEqualTo(VALUE);
460         result = DeviceConfig.getProperty(newNamespace, KEY);
461         assertThat(result).isEqualTo(newValue);
462 
463         // clean up
464         deleteViaContentProvider(newNamespace, KEY);
465     }
466 
467     @Test
setAndGetProperty_overrideValue()468     public void setAndGetProperty_overrideValue() {
469         String newValue = "value2";
470         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
471         DeviceConfig.setProperty(NAMESPACE, KEY, newValue, false);
472         String result = DeviceConfig.getProperty(NAMESPACE, KEY);
473         assertThat(result).isEqualTo(newValue);
474     }
475 
476     @Test
resetToDefault_makeDefault()477     public void resetToDefault_makeDefault() {
478         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, true);
479         assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE);
480 
481         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, NAMESPACE);
482         assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE);
483     }
484 
485     @Test
resetToDefault_doNotMakeDefault()486     public void resetToDefault_doNotMakeDefault() {
487         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
488         assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isEqualTo(VALUE);
489 
490         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, NAMESPACE);
491         assertThat(DeviceConfig.getProperty(NAMESPACE, KEY)).isNull();
492     }
493 
494     @Test
getProperties_fullNamespace()495     public void getProperties_fullNamespace() {
496         Properties properties = DeviceConfig.getProperties(NAMESPACE);
497         assertThat(properties.getKeyset()).isEmpty();
498 
499         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
500         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
501         properties = DeviceConfig.getProperties(NAMESPACE);
502         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
503         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
504         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
505 
506         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE3, false);
507         properties = DeviceConfig.getProperties(NAMESPACE);
508         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
509         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3);
510         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
511 
512         DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE, false);
513         properties = DeviceConfig.getProperties(NAMESPACE);
514         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
515         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3);
516         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
517         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE);
518     }
519 
520     @Test
getProperties_getString()521     public void getProperties_getString() {
522         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
523         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
524 
525         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
526         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
527         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
528         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
529     }
530 
531     @Test
getProperties_getBoolean()532     public void getProperties_getBoolean() {
533         DeviceConfig.setProperty(NAMESPACE, KEY, "true", false);
534         DeviceConfig.setProperty(NAMESPACE, KEY2, "false", false);
535         DeviceConfig.setProperty(NAMESPACE, KEY3, "not a valid boolean", false);
536 
537         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2, KEY3);
538         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
539         assertThat(properties.getBoolean(KEY, true)).isTrue();
540         assertThat(properties.getBoolean(KEY, false)).isTrue();
541         assertThat(properties.getBoolean(KEY2, true)).isFalse();
542         assertThat(properties.getBoolean(KEY2, false)).isFalse();
543         // KEY3 was set to garbage, anything nonnull but "true" will parse as false
544         assertThat(properties.getBoolean(KEY3, true)).isFalse();
545         assertThat(properties.getBoolean(KEY3, false)).isFalse();
546         // If a key was not set, it will return the default value
547         assertThat(properties.getBoolean("missing_key", true)).isTrue();
548         assertThat(properties.getBoolean("missing_key", false)).isFalse();
549     }
550 
551     @Test
getProperties_getInt()552     public void getProperties_getInt() {
553         final int value = 101;
554 
555         DeviceConfig.setProperty(NAMESPACE, KEY, Integer.toString(value), false);
556         DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid int", false);
557 
558         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
559         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
560         assertThat(properties.getInt(KEY, -1)).isEqualTo(value);
561         // KEY2 was set to garbage, the default value is returned if an int cannot be parsed
562         assertThat(properties.getInt(KEY2, -1)).isEqualTo(-1);
563     }
564 
565     @Test
getProperties_getFloat()566     public void getProperties_getFloat() {
567         final float value = 101.010f;
568 
569         DeviceConfig.setProperty(NAMESPACE, KEY, Float.toString(value), false);
570         DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid float", false);
571 
572         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
573         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
574         assertThat(properties.getFloat(KEY, -1.0f)).isEqualTo(value);
575         // KEY2 was set to garbage, the default value is returned if a float cannot be parsed
576         assertThat(properties.getFloat(KEY2, -1.0f)).isEqualTo(-1.0f);
577     }
578 
579     @Test
getProperties_getLong()580     public void getProperties_getLong() {
581         final long value = 101;
582 
583         DeviceConfig.setProperty(NAMESPACE, KEY, Long.toString(value), false);
584         DeviceConfig.setProperty(NAMESPACE, KEY2, "not a valid long", false);
585 
586         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
587         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
588         assertThat(properties.getLong(KEY, -1)).isEqualTo(value);
589         // KEY2 was set to garbage, the default value is returned if a long cannot be parsed
590         assertThat(properties.getLong(KEY2, -1)).isEqualTo(-1);
591     }
592 
593     @Test
getProperties_defaults()594     public void getProperties_defaults() {
595         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
596         DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE3, false);
597 
598         Properties properties = DeviceConfig.getProperties(NAMESPACE, KEY, KEY2);
599         assertThat(properties.getKeyset()).containsExactly(KEY);
600         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
601         // not set in DeviceConfig, but requested in getProperties
602         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
603         // set in DeviceConfig, but not requested in getProperties
604         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
605     }
606 
607     @Test
setProperties()608     public void setProperties() throws DeviceConfig.BadConfigException {
609         Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
610                 .setString(KEY2, VALUE2).build();
611 
612         DeviceConfig.setProperties(properties);
613         properties = DeviceConfig.getProperties(NAMESPACE);
614         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
615         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
616         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
617 
618         properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE2)
619                 .setString(KEY3, VALUE3).build();
620 
621         DeviceConfig.setProperties(properties);
622         properties = DeviceConfig.getProperties(NAMESPACE);
623         assertThat(properties.getKeyset()).containsExactly(KEY, KEY3);
624         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE2);
625         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE3);
626 
627         assertThat(properties.getKeyset()).doesNotContain(KEY2);
628         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
629     }
630 
631     @Test
632     @FlakyTest(bugId = 299483542)
setProperties_multipleNamespaces()633     public void setProperties_multipleNamespaces() throws DeviceConfig.BadConfigException {
634         final String namespace2 = "namespace2";
635         Properties properties1 = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
636                 .setString(KEY2, VALUE2).build();
637         Properties properties2 = new Properties.Builder(namespace2).setString(KEY2, VALUE)
638                 .setString(KEY3, VALUE2).build();
639 
640         assertTrue(DeviceConfig.setProperties(properties1));
641         assertTrue(DeviceConfig.setProperties(properties2));
642 
643         Properties properties = DeviceConfig.getProperties(NAMESPACE);
644         assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
645         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
646         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
647 
648         assertThat(properties.getKeyset()).doesNotContain(KEY3);
649         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
650 
651         properties = DeviceConfig.getProperties(namespace2);
652         assertThat(properties.getKeyset()).containsExactly(KEY2, KEY3);
653         assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE);
654         assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE2);
655 
656         assertThat(properties.getKeyset()).doesNotContain(KEY);
657         assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
658 
659         // clean up
660         deleteViaContentProvider(namespace2, KEY);
661         deleteViaContentProvider(namespace2, KEY2);
662         deleteViaContentProvider(namespace2, KEY3);
663     }
664 
665     @Test
propertiesBuilder()666     public void propertiesBuilder() {
667         boolean booleanValue = true;
668         int intValue = 123;
669         float floatValue = 4.56f;
670         long longValue = -789L;
671         String key4 = "key4";
672         String key5 = "key5";
673 
674         Properties properties = new Properties.Builder(NAMESPACE).setString(KEY, VALUE)
675                 .setBoolean(KEY2, booleanValue).setInt(KEY3, intValue).setLong(key4, longValue)
676                 .setFloat(key5, floatValue).build();
677         assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
678         assertThat(properties.getString(KEY, "defaultValue")).isEqualTo(VALUE);
679         assertThat(properties.getBoolean(KEY2, false)).isEqualTo(booleanValue);
680         assertThat(properties.getInt(KEY3, 0)).isEqualTo(intValue);
681         assertThat(properties.getLong("key4", 0L)).isEqualTo(longValue);
682         assertThat(properties.getFloat("key5", 0f)).isEqualTo(floatValue);
683     }
684 
685     @Test
banNamespaceProperties()686     public void banNamespaceProperties() throws DeviceConfig.BadConfigException {
687         // Given namespace will be permanently banned, thus it needs to be different every time
688         final String namespaceToBan = NAMESPACE + System.currentTimeMillis();
689         Properties properties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE)
690                 .setString(KEY4, NULL_VALUE).build();
691         // Set namespace properties
692         DeviceConfig.setProperties(properties);
693         // Ban namespace with related properties
694         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan);
695         // Verify given namespace properties are banned
696         assertThrows(DeviceConfig.BadConfigException.class,
697                 () -> DeviceConfig.setProperties(properties));
698         // Modify properties and verify we can set them
699         Properties modifiedProperties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE)
700                 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
701         DeviceConfig.setProperties(modifiedProperties);
702         modifiedProperties = DeviceConfig.getProperties(namespaceToBan);
703         assertThat(modifiedProperties.getKeyset()).containsExactly(KEY, KEY2, KEY4);
704         assertThat(modifiedProperties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
705         assertThat(modifiedProperties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
706         // Since value is null DEFAULT_VALUE should be returned
707         assertThat(modifiedProperties.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
708     }
709 
710     @Test
banEntireDeviceConfig()711     public void banEntireDeviceConfig() throws DeviceConfig.BadConfigException {
712         // Given namespaces will be permanently banned, thus they need to be different every time
713         final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis();
714         final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1;
715 
716         // Set namespaces properties
717         Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE)
718                 .setString(KEY4, NULL_VALUE).build();
719         DeviceConfig.setProperties(properties1);
720         Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2)
721                 .setString(KEY4, NULL_VALUE).build();
722         DeviceConfig.setProperties(properties2);
723 
724         // Ban entire DeviceConfig
725         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, null);
726 
727         // Verify given namespace properties are banned
728         assertThrows(DeviceConfig.BadConfigException.class,
729                 () -> DeviceConfig.setProperties(properties1));
730         assertThrows(DeviceConfig.BadConfigException.class,
731                 () -> DeviceConfig.setProperties(properties2));
732 
733         // Modify properties and verify we can set them
734         Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY,
735                 VALUE)
736                 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
737         DeviceConfig.setProperties(modifiedProperties1);
738         modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1);
739         assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4);
740         assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
741         assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
742         // Since value is null DEFAULT_VALUE should be returned
743         assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
744 
745         Properties modifiedProperties2 = new Properties.Builder(namespaceToBan2).setString(KEY,
746                 VALUE)
747                 .setString(KEY3, NULL_VALUE).setString(KEY4, VALUE2).build();
748         DeviceConfig.setProperties(modifiedProperties2);
749         modifiedProperties2 = DeviceConfig.getProperties(namespaceToBan2);
750         assertThat(modifiedProperties2.getKeyset()).containsExactly(KEY, KEY3, KEY4);
751         assertThat(modifiedProperties2.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
752         assertThat(modifiedProperties2.getString(KEY4, DEFAULT_VALUE)).isEqualTo(VALUE2);
753         // Since value is null DEFAULT_VALUE should be returned
754         assertThat(modifiedProperties2.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
755     }
756 
757     @Test
allConfigsUnbannedIfAnyUnbannedConfigUpdated()758     public void allConfigsUnbannedIfAnyUnbannedConfigUpdated()
759             throws DeviceConfig.BadConfigException {
760         // Given namespaces will be permanently banned, thus they need to be different every time
761         final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis();
762         final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1;
763 
764         // Set namespaces properties
765         Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE)
766                 .setString(KEY4, NULL_VALUE).build();
767         DeviceConfig.setProperties(properties1);
768         Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2)
769                 .setString(KEY4, NULL_VALUE).build();
770         DeviceConfig.setProperties(properties2);
771 
772         // Ban namespace with related properties
773         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan1);
774         DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan2);
775 
776         // Verify given namespace properties are banned
777         assertThrows(DeviceConfig.BadConfigException.class,
778                 () -> DeviceConfig.setProperties(properties1));
779         assertThrows(DeviceConfig.BadConfigException.class,
780                 () -> DeviceConfig.setProperties(properties2));
781 
782         // Modify properties and verify we can set them
783         Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY,
784                 VALUE)
785                 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
786         DeviceConfig.setProperties(modifiedProperties1);
787         modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1);
788         assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4);
789         assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
790         assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
791         // Since value is null DEFAULT_VALUE should be returned
792         assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
793 
794         // verify that other banned namespaces are unbanned now.
795         DeviceConfig.setProperties(properties2);
796         Properties result = DeviceConfig.getProperties(namespaceToBan2);
797         assertThat(result.getKeyset()).containsExactly(KEY2, KEY4);
798         assertThat(result.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
799         // Since value is null DEFAULT_VALUE should be returned
800         assertThat(result.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
801     }
802 
803     @Test
onPropertiesChangedListener_setPropertyCallback()804     public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
805         final AtomicReference<Properties> changedProperties = new AtomicReference<>();
806         final CompletableFuture<Boolean> completed = new CompletableFuture<>();
807 
808         DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
809             changedProperties.set(properties);
810             completed.complete(true);
811         };
812 
813         try {
814             DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
815                     Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(),
816                     changeListener);
817             DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
818 
819             assertThat(completed.get(
820                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
821 
822             Properties properties = changedProperties.get();
823             assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
824             assertThat(properties.getKeyset()).contains(KEY);
825             assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE);
826         } catch (ExecutionException | TimeoutException | InterruptedException e) {
827             Assert.fail(e.getMessage());
828         } finally {
829             DeviceConfig.removeOnPropertiesChangedListener(changeListener);
830         }
831     }
832 
833     @Test
834     @FlakyTest(bugId = 299483542)
onPropertiesChangedListener_setPropertiesCallback()835     public void onPropertiesChangedListener_setPropertiesCallback() {
836         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
837         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
838 
839         Map<String, String> keyValues = new HashMap<>(2);
840         keyValues.put(KEY, VALUE2);
841         keyValues.put(KEY3, VALUE3);
842         Properties setProperties = new Properties(NAMESPACE, keyValues);
843 
844         final AtomicReference<Properties> changedProperties = new AtomicReference<>();
845         final CompletableFuture<Boolean> completed = new CompletableFuture<>();
846 
847         DeviceConfig.OnPropertiesChangedListener changeListener = (properties) -> {
848             changedProperties.set(properties);
849             completed.complete(true);
850         };
851 
852         try {
853             DeviceConfig.addOnPropertiesChangedListener(NAMESPACE,
854                     Objects.requireNonNull(ActivityThread.currentApplication()).getMainExecutor(),
855                     changeListener);
856             DeviceConfig.setProperties(setProperties);
857 
858             assertThat(completed.get(
859                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
860 
861             if (changedProperties.get().getKeyset().size() != 3) {
862                 // Sometimes there are a few onChanged callback calls. Let's wait a bit more.
863                 final int oneMoreOnChangedDelayMs = 100;
864                 Thread.currentThread().sleep(oneMoreOnChangedDelayMs);
865             }
866 
867             Properties properties = changedProperties.get();
868             assertThat(properties.getNamespace()).isEqualTo(NAMESPACE);
869             assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
870             // KEY updated from VALUE to VALUE2
871             assertThat(properties.getString(KEY, "default_value")).isEqualTo(VALUE2);
872             // KEY2 deleted (returns default_value)
873             assertThat(properties.getString(KEY2, "default_value")).isEqualTo("default_value");
874             // KEY3 added with VALUE3
875             assertThat(properties.getString(KEY3, "default_value")).isEqualTo(VALUE3);
876         } catch (ExecutionException | TimeoutException | InterruptedException e) {
877             Assert.fail(e.getMessage());
878         } catch (DeviceConfig.BadConfigException e) {
879             Assert.fail(e.getMessage());
880         } finally {
881             DeviceConfig.removeOnPropertiesChangedListener(changeListener);
882         }
883     }
884 
885     @Test
886     @Ignore("b/300174188")
syncDisabling()887     public void syncDisabling() throws Exception {
888         Properties properties1 = new Properties.Builder(NAMESPACE)
889                 .setString(KEY, VALUE)
890                 .build();
891         Properties properties2 = new Properties.Builder(NAMESPACE)
892                 .setString(KEY, VALUE2)
893                 .build();
894 
895         try {
896             // Ensure the device starts in a known state.
897             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE);
898 
899             // Assert starting state.
900             assertThat(DeviceConfig.getSyncDisabledMode())
901                     .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE);
902             assertThat(DeviceConfig.setProperties(properties1)).isTrue();
903             assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
904                     .isEqualTo(VALUE);
905 
906             // Test disabled (persistent). Persistence is not actually tested, that would require
907             // a host test.
908             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_PERSISTENT);
909             assertThat(DeviceConfig.getSyncDisabledMode())
910                     .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_PERSISTENT);
911             assertThat(DeviceConfig.setProperties(properties2)).isFalse();
912             assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
913                     .isEqualTo(VALUE);
914 
915             // Return to not disabled.
916             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE);
917             assertThat(DeviceConfig.getSyncDisabledMode())
918                     .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE);
919             assertThat(DeviceConfig.setProperties(properties2)).isTrue();
920             assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
921                     .isEqualTo(VALUE2);
922 
923             // Test disabled (persistent). Absence of persistence is not actually tested, that would
924             // require a host test.
925             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_UNTIL_REBOOT);
926             assertThat(DeviceConfig.getSyncDisabledMode())
927                     .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_UNTIL_REBOOT);
928             assertThat(DeviceConfig.setProperties(properties1)).isFalse();
929             assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
930                     .isEqualTo(VALUE2);
931 
932             // Return to not disabled.
933             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE);
934             assertThat(DeviceConfig.getSyncDisabledMode())
935                     .isEqualTo(DeviceConfig.SYNC_DISABLED_MODE_NONE);
936             assertThat(DeviceConfig.setProperties(properties1)).isTrue();
937             assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
938                     .isEqualTo(VALUE);
939         } finally {
940             // Try to return to the default sync disabled state in case of failure.
941             DeviceConfig.setSyncDisabledMode(DeviceConfig.SYNC_DISABLED_MODE_NONE);
942 
943             // NAMESPACE will be cleared by cleanUp()
944         }
945     }
946 
deleteViaContentProvider(String namespace, String key)947     private static boolean deleteViaContentProvider(String namespace, String key) {
948         ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
949         String compositeName = namespace + "/" + key;
950         Bundle result = resolver.call(
951                 Settings.Config.CONTENT_URI,
952                 Settings.CALL_METHOD_DELETE_CONFIG,
953                 compositeName,
954                 null);
955         assertThat(result).isNotNull();
956         return compositeName.equals(result.getString(Settings.NameValueTable.VALUE));
957     }
958 
959     @Test
deleteProperty_nullNamespace()960     public void deleteProperty_nullNamespace() {
961         try {
962             DeviceConfig.deleteProperty(null, KEY);
963             Assert.fail("Null namespace should have resulted in an NPE.");
964         } catch (NullPointerException e) {
965             // expected
966         }
967     }
968 
969     @Test
deleteProperty_nullName()970     public void deleteProperty_nullName() {
971         try {
972             DeviceConfig.deleteProperty(NAMESPACE, null);
973             Assert.fail("Null name should have resulted in an NPE.");
974         } catch (NullPointerException e) {
975             // expected
976         }
977     }
978 
979     @Test
deletePropertyString()980     public void deletePropertyString() {
981         final String value = "new_value";
982         final String default_value = "default";
983         DeviceConfig.setProperty(NAMESPACE, KEY, value, false);
984         DeviceConfig.deleteProperty(NAMESPACE, KEY);
985         final String result = DeviceConfig.getString(NAMESPACE, KEY, default_value);
986         assertThat(result).isEqualTo(default_value);
987     }
988 
989     @Test
deletePropertyBoolean()990     public void deletePropertyBoolean() {
991         final boolean value = true;
992         final boolean default_value = false;
993         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
994         DeviceConfig.deleteProperty(NAMESPACE, KEY);
995         final boolean result = DeviceConfig.getBoolean(NAMESPACE, KEY, default_value);
996         assertThat(result).isEqualTo(default_value);
997     }
998 
999     @Test
deletePropertyInt()1000     public void deletePropertyInt() {
1001         final int value = 123;
1002         final int default_value = 999;
1003         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
1004         DeviceConfig.deleteProperty(NAMESPACE, KEY);
1005         final int result = DeviceConfig.getInt(NAMESPACE, KEY, default_value);
1006         assertThat(result).isEqualTo(default_value);
1007     }
1008 
1009     @Test
deletePropertyLong()1010     public void deletePropertyLong() {
1011         final long value = 456789;
1012         final long default_value = 123456;
1013         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
1014         DeviceConfig.deleteProperty(NAMESPACE, KEY);
1015         final long result = DeviceConfig.getLong(NAMESPACE, KEY, default_value);
1016         assertThat(result).isEqualTo(default_value);
1017     }
1018 
1019     @Test
deletePropertyFloat()1020     public void deletePropertyFloat() {
1021         final float value = 456.789f;
1022         final float default_value = 123.456f;
1023         DeviceConfig.setProperty(NAMESPACE, KEY, String.valueOf(value), false);
1024         DeviceConfig.deleteProperty(NAMESPACE, KEY);
1025         final float result = DeviceConfig.getFloat(NAMESPACE, KEY, default_value);
1026         assertThat(result).isEqualTo(default_value);
1027     }
1028 
1029     @Test
deleteProperty_empty()1030     public void deleteProperty_empty() {
1031         assertThat(DeviceConfig.deleteProperty(NAMESPACE, KEY)).isTrue();
1032         final String result = DeviceConfig.getString(NAMESPACE, KEY, null);
1033         assertThat(result).isNull();
1034     }
1035 }
1036