1 /*
2  * Copyright (C) 2019 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 com.android.modules.utils.testing;
18 
19 import static android.provider.DeviceConfig.OnPropertiesChangedListener;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assume.assumeTrue;
24 
25 import android.platform.test.annotations.Presubmit;
26 import android.provider.DeviceConfig;
27 import android.provider.DeviceConfig.BadConfigException;
28 import android.provider.DeviceConfig.Properties;
29 
30 import androidx.test.core.app.ApplicationProvider;
31 import androidx.test.filters.SmallTest;
32 import androidx.test.runner.AndroidJUnit4;
33 
34 import com.android.modules.utils.build.SdkLevel;
35 
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.TimeUnit;
42 
43 /** Tests that ensure appropriate settings are backed up. */
44 @Presubmit
45 @RunWith(AndroidJUnit4.class)
46 @SmallTest
47 public class TestableDeviceConfigTest {
48     private static final String sNamespace = "namespace1";
49     private static final String sKey = "key1";
50     private static final String sValue = "value1";
51     private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
52 
53     @Rule
54     public TestableDeviceConfig.TestableDeviceConfigRule
55             mTestableDeviceConfig = new TestableDeviceConfig.TestableDeviceConfigRule();
56 
57     @Test
getProperty_empty()58     public void getProperty_empty() {
59         String result = DeviceConfig.getProperty(sNamespace, sKey);
60         assertThat(result).isNull();
61     }
62 
63     @Test
setAndGetProperty_sameNamespace()64     public void setAndGetProperty_sameNamespace() {
65         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
66         String result = DeviceConfig.getProperty(sNamespace, sKey);
67         assertThat(result).isEqualTo(sValue);
68     }
69 
70     @Test
setAndGetProperty_differentNamespace()71     public void setAndGetProperty_differentNamespace() {
72         String newNamespace = "namespace2";
73         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
74         String result = DeviceConfig.getProperty(newNamespace, sKey);
75         assertThat(result).isNull();
76     }
77 
78     @Test
setAndGetProperty_multipleNamespaces()79     public void setAndGetProperty_multipleNamespaces() {
80         String newNamespace = "namespace2";
81         String newValue = "value2";
82         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
83         DeviceConfig.setProperty(newNamespace, sKey, newValue, false);
84         String result = DeviceConfig.getProperty(sNamespace, sKey);
85         assertThat(result).isEqualTo(sValue);
86         result = DeviceConfig.getProperty(newNamespace, sKey);
87         assertThat(result).isEqualTo(newValue);
88     }
89 
90     @Test
setAndGetProperty_overrideValue()91     public void setAndGetProperty_overrideValue() {
92         String newValue = "value2";
93         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
94         DeviceConfig.setProperty(sNamespace, sKey, newValue, false);
95         String result = DeviceConfig.getProperty(sNamespace, sKey);
96         assertThat(result).isEqualTo(newValue);
97     }
98 
99     @Test
setProperties()100     public void setProperties() throws BadConfigException {
101         // api only present on T
102         assumeTrue(SdkLevel.isAtLeastT());
103         String newKey = "key2";
104         String newValue = "value2";
105         DeviceConfig.setProperties(new Properties.Builder(sNamespace).setString(sKey,
106                 sValue).setString(newKey, newValue).build());
107         assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isEqualTo(sValue);
108         assertThat(DeviceConfig.getProperty(sNamespace, newKey)).isEqualTo(newValue);
109     }
110 
111     @Test
deleteProperty()112     public void deleteProperty() {
113         // api only present on T
114         assumeTrue(SdkLevel.isAtLeastT());
115 
116         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
117         assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isEqualTo(sValue);
118         DeviceConfig.deleteProperty(sNamespace, sKey);
119         assertThat(DeviceConfig.getProperty(sNamespace, sKey)).isNull();
120         String newNamespace = "namespace2";
121         String newValue = "value2";
122         DeviceConfig.setProperty(newNamespace, sKey, newValue, false);
123         assertThat(DeviceConfig.getProperty(newNamespace, sKey)).isEqualTo(newValue);
124         DeviceConfig.deleteProperty(newNamespace, sKey);
125         assertThat(DeviceConfig.getProperty(newNamespace, sKey)).isNull();
126     }
127 
128     @Test
getProperties_empty()129     public void getProperties_empty() {
130         // api only present on R+
131         assumeTrue(SdkLevel.isAtLeastR());
132         String newKey = "key2";
133         String newValue = "value2";
134         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
135         Properties properties = DeviceConfig.getProperties(sNamespace);
136         assertThat(properties.getString(sKey, null)).isEqualTo(sValue);
137         assertThat(properties.getString(newKey, null)).isNull();
138 
139         DeviceConfig.setProperty(sNamespace, newKey, newValue, false);
140         properties = DeviceConfig.getProperties(sNamespace);
141         assertThat(properties.getString(sKey, null)).isEqualTo(sValue);
142         assertThat(properties.getString(newKey, null)).isEqualTo(newValue);
143 
144     }
145 
146     @Test
getProperties()147     public void getProperties() {
148         // api only present on R+
149         assumeTrue(SdkLevel.isAtLeastR());
150         Properties properties = DeviceConfig.getProperties(sNamespace, sKey);
151         assertThat(properties.getString(sKey, null)).isNull();
152 
153         DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
154         properties = DeviceConfig.getProperties(sNamespace, sKey);
155         assertThat(properties.getString(sKey, null)).isEqualTo(sValue);
156 
157         String newKey = "key2";
158         String newValue = "value2";
159         DeviceConfig.setProperty(sNamespace, newKey, newValue, false);
160         properties = DeviceConfig.getProperties(sNamespace, sKey, newKey);
161         assertThat(properties.getString(sKey, null)).isEqualTo(sValue);
162         assertThat(properties.getString(newKey, null)).isEqualTo(newValue);
163 
164         String unsetKey = "key3";
165         properties = DeviceConfig.getProperties(sNamespace, newKey, unsetKey);
166         assertThat(properties.getKeyset()).containsExactly(newKey, unsetKey);
167         assertThat(properties.getString(newKey, null)).isEqualTo(newValue);
168         assertThat(properties.getString(unsetKey, null)).isNull();
169     }
170 
171     @Test
testListener_setProperty()172     public void testListener_setProperty() throws InterruptedException {
173         CountDownLatch countDownLatch = new CountDownLatch(1);
174 
175         OnPropertiesChangedListener changeListener = (properties) -> {
176             assertThat(properties.getNamespace()).isEqualTo(sNamespace);
177             assertThat(properties.getKeyset()).containsExactly(sKey);
178             assertThat(properties.getString(sKey, "bogus_value")).isEqualTo(sValue);
179             assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value");
180             countDownLatch.countDown();
181         };
182         try {
183             DeviceConfig.addOnPropertiesChangedListener(sNamespace,
184                     ApplicationProvider.getApplicationContext().getMainExecutor(), changeListener);
185             DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
186             assertThat(countDownLatch.await(
187                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
188         } finally {
189             DeviceConfig.removeOnPropertiesChangedListener(changeListener);
190         }
191     }
192 
193     @Test
testListener_setProperties()194     public void testListener_setProperties() throws BadConfigException, InterruptedException {
195         // api only present on T
196         assumeTrue(SdkLevel.isAtLeastT());
197         CountDownLatch countDownLatch = new CountDownLatch(1);
198         String newKey = "key2";
199         String newValue = "value2";
200 
201         OnPropertiesChangedListener changeListener = (properties) -> {
202             assertThat(properties.getNamespace()).isEqualTo(sNamespace);
203             assertThat(properties.getKeyset()).containsExactly(sKey, newKey);
204             assertThat(properties.getString(sKey, "bogus_value")).isEqualTo(sValue);
205             assertThat(properties.getString(newKey, "bogus_value")).isEqualTo(newValue);
206             assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value");
207             countDownLatch.countDown();
208         };
209         try {
210             DeviceConfig.addOnPropertiesChangedListener(sNamespace,
211                     ApplicationProvider.getApplicationContext().getMainExecutor(), changeListener);
212             DeviceConfig.setProperties(new Properties.Builder(sNamespace).setString(sKey,
213                     sValue).setString(newKey, newValue).build());
214             assertThat(countDownLatch.await(
215                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
216         } finally {
217             DeviceConfig.removeOnPropertiesChangedListener(changeListener);
218         }
219     }
220 
221     @Test
testListener_deleteProperty()222     public void testListener_deleteProperty() throws InterruptedException {
223         // api only present on T
224         assumeTrue(SdkLevel.isAtLeastT());
225         CountDownLatch countDownLatch = new CountDownLatch(1);
226 
227         OnPropertiesChangedListener changeListener = (properties) -> {
228             assertThat(properties.getNamespace()).isEqualTo(sNamespace);
229             assertThat(properties.getKeyset()).containsExactly(sKey);
230             assertThat(properties.getString(sKey, "bogus_value")).isEqualTo("bogus_value");
231             assertThat(properties.getString("bogus_key", "bogus_value")).isEqualTo("bogus_value");
232             countDownLatch.countDown();
233         };
234         try {
235             DeviceConfig.addOnPropertiesChangedListener(sNamespace,
236                     ApplicationProvider.getApplicationContext().getMainExecutor(), changeListener);
237             DeviceConfig.deleteProperty(sNamespace, sKey);
238             assertThat(countDownLatch.await(
239                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
240         } finally {
241             DeviceConfig.removeOnPropertiesChangedListener(changeListener);
242         }
243     }
244 }
245 
246 
247