1 /*
2  * Copyright (C) 2022 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.safetycenter.resources
18 
19 import android.content.Context
20 import android.content.pm.PackageManager
21 import android.content.res.Resources
22 import androidx.test.core.app.ApplicationProvider.getApplicationContext
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import com.google.common.truth.Truth.assertThat
25 import java.lang.IllegalStateException
26 import kotlin.test.assertFailsWith
27 import org.junit.Test
28 import org.junit.runner.RunWith
29 
30 @RunWith(AndroidJUnit4::class)
31 class SafetyCenterResourcesApkTest {
32     private val context: Context = getApplicationContext()
33 
34     @Test
init_withValidInputs_returnsTruenull35     fun init_withValidInputs_returnsTrue() {
36         val resourcesApk = newSafetyCenterResourcesApk()
37 
38         val initialized = resourcesApk.init()
39 
40         assertThat(initialized).isTrue()
41     }
42 
43     @Test
init_withWrongAction_returnsFalsenull44     fun init_withWrongAction_returnsFalse() {
45         val resourcesApk = newSafetyCenterResourcesApk(resourcesApkAction = "wrong")
46 
47         val initialized = resourcesApk.init()
48 
49         assertThat(initialized).isFalse()
50     }
51 
52     @Test
init_withWrongPath_returnsFalsenull53     fun init_withWrongPath_returnsFalse() {
54         val resourcesApk =
55             newSafetyCenterResourcesApk(resourcesApkPath = "/apex/com.android.permission")
56 
57         val initialized = resourcesApk.init()
58 
59         assertThat(initialized).isFalse()
60     }
61 
62     @Test
init_withWrongFlags_returnsFalsenull63     fun init_withWrongFlags_returnsFalse() {
64         val resourcesApk = newSafetyCenterResourcesApk(flags = PackageManager.MATCH_SYSTEM_ONLY)
65 
66         val initialized = resourcesApk.init()
67 
68         assertThat(initialized).isFalse()
69     }
70 
71     @Test
getContext_withValidInputs_returnsResourcesApkContextnull72     fun getContext_withValidInputs_returnsResourcesApkContext() {
73         val resourcesApk = newSafetyCenterResourcesApk()
74 
75         val resourcesApkContext = resourcesApk.context
76 
77         assertThat(resourcesApkContext.packageName).isEqualTo(RESOURCES_APK_PKG_NAME)
78     }
79 
80     @Test
getContext_withWrongAction_throwsnull81     fun getContext_withWrongAction_throws() {
82         val resourcesApk = newSafetyCenterResourcesApk(resourcesApkAction = "wrong")
83 
84         assertFailsWith(IllegalStateException::class) { resourcesApk.context }
85     }
86 
87     @Test
getContext_withWrongPath_throwsnull88     fun getContext_withWrongPath_throws() {
89         val resourcesApk =
90             newSafetyCenterResourcesApk(resourcesApkPath = "/apex/com.android.permission")
91 
92         assertFailsWith(IllegalStateException::class) { resourcesApk.context }
93     }
94 
95     @Test
getContext_withWrongFlags_throwsnull96     fun getContext_withWrongFlags_throws() {
97         val resourcesApk = newSafetyCenterResourcesApk(flags = PackageManager.MATCH_SYSTEM_ONLY)
98 
99         assertFailsWith(IllegalStateException::class) { resourcesApk.context }
100     }
101 
102     @Test
getResources_withValidInputs_returnsResourcesApkContextResourcesnull103     fun getResources_withValidInputs_returnsResourcesApkContextResources() {
104         val resourcesApk = newSafetyCenterResourcesApk()
105 
106         val resources = resourcesApk.resources
107 
108         assertThat(resources).isEqualTo(resourcesApk.context.resources)
109     }
110 
111     @Test
getResources_nullContext_throwsRegardlessOfFallbacknull112     fun getResources_nullContext_throwsRegardlessOfFallback() {
113         val resourcesApk =
114             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
115 
116         assertFailsWith(IllegalStateException::class) { resourcesApk.resources }
117     }
118 
119     @Test
getSafetyCenterConfig_withValidInputs_returnsConfigContentnull120     fun getSafetyCenterConfig_withValidInputs_returnsConfigContent() {
121         val resourcesApk = newSafetyCenterResourcesApk()
122 
123         val config = resourcesApk.safetyCenterConfig
124         val configContent = config?.bufferedReader().use { it?.readText() }
125 
126         assertThat(config).isNotNull()
127         assertThat(configContent).isEqualTo(CONFIG_CONTENT)
128     }
129 
130     @Test
getSafetyCenterConfig_anotherValidConfigName_returnsConfigContentnull131     fun getSafetyCenterConfig_anotherValidConfigName_returnsConfigContent() {
132         val resourcesApk = newSafetyCenterResourcesApk()
133 
134         val config = resourcesApk.getSafetyCenterConfig(CONFIG_NAME)
135         val configContent = config?.bufferedReader().use { it?.readText() }
136 
137         assertThat(config).isNotNull()
138         assertThat(configContent).isEqualTo(CONFIG_CONTENT)
139     }
140 
141     @Test
getSafetyCenterConfig_invalidConfigNameWithFallback_returnsNullnull142     fun getSafetyCenterConfig_invalidConfigNameWithFallback_returnsNull() {
143         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
144 
145         assertThat(resourcesApk.getSafetyCenterConfig("wrong")).isNull()
146     }
147 
148     @Test
getSafetyCenterConfig_invalidConfigNameWithoutFallback_throwsnull149     fun getSafetyCenterConfig_invalidConfigNameWithoutFallback_throws() {
150         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
151 
152         assertFailsWith(Resources.NotFoundException::class) {
153             resourcesApk.getSafetyCenterConfig("wrong")
154         }
155     }
156 
157     @Test
getSafetyCenterConfig_nullContext_throwsRegardlessOfFallbacknull158     fun getSafetyCenterConfig_nullContext_throwsRegardlessOfFallback() {
159         val resourcesApk =
160             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
161 
162         assertFailsWith(IllegalStateException::class) { resourcesApk.safetyCenterConfig }
163     }
164 
165     @Test
getString_validString_returnsStringnull166     fun getString_validString_returnsString() {
167         val resourcesApk = newSafetyCenterResourcesApk()
168 
169         val ok = resourcesApk.getString(android.R.string.ok)
170 
171         assertThat(ok).isEqualTo("OK")
172     }
173 
174     @Test
getString_nullContext_throwsRegardlessOfFallbacknull175     fun getString_nullContext_throwsRegardlessOfFallback() {
176         val resourcesApk =
177             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
178 
179         assertFailsWith(IllegalStateException::class) {
180             resourcesApk.getString(android.R.string.ok)
181         }
182     }
183 
184     @Test
getStringWithFormatArgs_validString_returnsStringnull185     fun getStringWithFormatArgs_validString_returnsString() {
186         val resourcesApk = newSafetyCenterResourcesApk()
187 
188         val ok = resourcesApk.getString(android.R.string.ok, "")
189 
190         assertThat(ok).isEqualTo("OK")
191     }
192 
193     @Test
getStringWithFormatArgs_nullContext_throwsRegardlessOfFallbacknull194     fun getStringWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
195         val resourcesApk =
196             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
197 
198         assertFailsWith(IllegalStateException::class) {
199             resourcesApk.getString(android.R.string.ok, "")
200         }
201     }
202 
203     @Test
getStringByName_validString_returnsStringnull204     fun getStringByName_validString_returnsString() {
205         val resourcesApk = newSafetyCenterResourcesApk()
206 
207         assertThat(resourcesApk.getStringByName("valid_string")).isEqualTo("I exist!")
208     }
209 
210     @Test
getStringByName_invalidStringWithFallback_returnsEmptyStringnull211     fun getStringByName_invalidStringWithFallback_returnsEmptyString() {
212         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
213 
214         assertThat(resourcesApk.getStringByName("invalid_string")).isEqualTo("")
215     }
216 
217     @Test
getStringByName_invalidStringWithoutFallback_throwsnull218     fun getStringByName_invalidStringWithoutFallback_throws() {
219         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
220 
221         assertFailsWith(Resources.NotFoundException::class) {
222             resourcesApk.getStringByName("invalid_string")
223         }
224     }
225 
226     @Test
getStringByName_nullContext_throwsRegardlessOfFallbacknull227     fun getStringByName_nullContext_throwsRegardlessOfFallback() {
228         val resourcesApk =
229             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
230 
231         assertFailsWith(IllegalStateException::class) {
232             resourcesApk.getStringByName("valid_string")
233         }
234     }
235 
236     @Test
getStringByNameWithFormatArgs_validString_returnsStringnull237     fun getStringByNameWithFormatArgs_validString_returnsString() {
238         val resourcesApk = newSafetyCenterResourcesApk()
239 
240         assertThat(resourcesApk.getStringByName("valid_string", "")).isEqualTo("I exist!")
241     }
242 
243     @Test
getStringByNameWithFormatArgs_invalidStringWithFallback_returnsEmptyStringnull244     fun getStringByNameWithFormatArgs_invalidStringWithFallback_returnsEmptyString() {
245         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
246 
247         assertThat(resourcesApk.getStringByName("invalid_string", "")).isEqualTo("")
248     }
249 
250     @Test
getStringByNameWithFormatArgs_invalidStringWithoutFallback_throwsnull251     fun getStringByNameWithFormatArgs_invalidStringWithoutFallback_throws() {
252         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
253 
254         assertFailsWith(Resources.NotFoundException::class) {
255             resourcesApk.getStringByName("invalid_string", "")
256         }
257     }
258 
259     @Test
getStringByNameWithFormatArgs_nullContext_throwsRegardlessOfFallbacknull260     fun getStringByNameWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
261         val resourcesApk =
262             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
263 
264         assertFailsWith(IllegalStateException::class) {
265             resourcesApk.getStringByName("valid_string", "")
266         }
267     }
268 
269     @Test
getOptionalString_validString_returnsStringnull270     fun getOptionalString_validString_returnsString() {
271         val resourcesApk = newSafetyCenterResourcesApk()
272 
273         val ok = resourcesApk.getOptionalString(android.R.string.ok)
274 
275         assertThat(ok).isEqualTo("OK")
276     }
277 
278     @Test
getOptionalString_resourceIdNull_returnsNullnull279     fun getOptionalString_resourceIdNull_returnsNull() {
280         val resourcesApk = newSafetyCenterResourcesApk()
281 
282         val string = resourcesApk.getOptionalString(Resources.ID_NULL)
283 
284         assertThat(string).isNull()
285     }
286 
287     @Test
getOptionalString_nullContext_throwsRegardlessOfFallbacknull288     fun getOptionalString_nullContext_throwsRegardlessOfFallback() {
289         val resourcesApk =
290             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
291 
292         assertFailsWith(IllegalStateException::class) {
293             resourcesApk.getOptionalString(android.R.string.ok)
294         }
295     }
296 
297     @Test
getOptionalStringByName_validString_returnsStringnull298     fun getOptionalStringByName_validString_returnsString() {
299         val resourcesApk = newSafetyCenterResourcesApk()
300 
301         assertThat(resourcesApk.getOptionalStringByName("valid_string")).isEqualTo("I exist!")
302     }
303 
304     @Test
getOptionalStringByName_invalidStringWithFallback_returnsNullnull305     fun getOptionalStringByName_invalidStringWithFallback_returnsNull() {
306         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
307 
308         assertThat(resourcesApk.getOptionalStringByName("invalid_string")).isNull()
309     }
310 
311     @Test
getOptionalStringByName_invalidStringWithoutFallback_returnsNullnull312     fun getOptionalStringByName_invalidStringWithoutFallback_returnsNull() {
313         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
314 
315         assertThat(resourcesApk.getOptionalStringByName("invalid_string")).isNull()
316     }
317 
318     @Test
getOptionalStringByName_nullContext_throwsRegardlessOfFallbacknull319     fun getOptionalStringByName_nullContext_throwsRegardlessOfFallback() {
320         val resourcesApk =
321             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
322 
323         assertFailsWith(IllegalStateException::class) {
324             resourcesApk.getOptionalStringByName("valid_string")
325         }
326     }
327 
328     @Test
getDrawableByName_validDrawable_returnsDrawablenull329     fun getDrawableByName_validDrawable_returnsDrawable() {
330         val resourcesApk = newSafetyCenterResourcesApk()
331 
332         assertThat(resourcesApk.getDrawableByName("valid_drawable", context.theme)).isNotNull()
333     }
334 
335     @Test
getDrawableByName_invalidDrawableWithFallback_returnsNullnull336     fun getDrawableByName_invalidDrawableWithFallback_returnsNull() {
337         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
338 
339         assertThat(resourcesApk.getDrawableByName("invalid_drawable", context.theme)).isNull()
340     }
341 
342     @Test
getDrawableByName_invalidDrawableWithoutFallback_throwsnull343     fun getDrawableByName_invalidDrawableWithoutFallback_throws() {
344         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
345 
346         assertFailsWith(Resources.NotFoundException::class) {
347             resourcesApk.getDrawableByName("invalid_drawable", context.theme)
348         }
349     }
350 
351     @Test
getDrawableByName_nullContext_throwsRegardlessOfFallbacknull352     fun getDrawableByName_nullContext_throwsRegardlessOfFallback() {
353         val resourcesApk =
354             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
355 
356         assertFailsWith(IllegalStateException::class) {
357             resourcesApk.getDrawableByName("valid_drawable", context.theme)
358         }
359     }
360 
361     @Test
getIconByDrawableName_validDrawable_returnsIconnull362     fun getIconByDrawableName_validDrawable_returnsIcon() {
363         val resourcesApk = newSafetyCenterResourcesApk()
364 
365         assertThat(resourcesApk.getIconByDrawableName("valid_drawable")).isNotNull()
366     }
367 
368     @Test
getIconByDrawableName_invalidDrawableWithFallback_returnsNullnull369     fun getIconByDrawableName_invalidDrawableWithFallback_returnsNull() {
370         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
371 
372         assertThat(resourcesApk.getIconByDrawableName("invalid_drawable")).isNull()
373     }
374 
375     @Test
getIconByDrawableName_invalidDrawableWithoutFallback_throwsnull376     fun getIconByDrawableName_invalidDrawableWithoutFallback_throws() {
377         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
378 
379         assertFailsWith(Resources.NotFoundException::class) {
380             resourcesApk.getIconByDrawableName("invalid_drawable")
381         }
382     }
383 
384     @Test
getIconByDrawableByName_nullContext_throwsRegardlessOfFallbacknull385     fun getIconByDrawableByName_nullContext_throwsRegardlessOfFallback() {
386         val resourcesApk =
387             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
388 
389         assertFailsWith(IllegalStateException::class) {
390             resourcesApk.getIconByDrawableName("valid_drawable")
391         }
392     }
393 
394     @Test
getColorByName_validColor_returnsColornull395     fun getColorByName_validColor_returnsColor() {
396         val resourcesApk = newSafetyCenterResourcesApk()
397 
398         assertThat(resourcesApk.getColorByName("valid_color")).isNotNull()
399     }
400 
401     @Test
getColorByName_invalidColorWithFallback_returnsNullnull402     fun getColorByName_invalidColorWithFallback_returnsNull() {
403         val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
404 
405         assertThat(resourcesApk.getColorByName("invalid_color")).isNull()
406     }
407 
408     @Test
getColorByName_invalidColorWithoutFallback_throwsnull409     fun getColorByName_invalidColorWithoutFallback_throws() {
410         val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
411 
412         assertFailsWith(Resources.NotFoundException::class) {
413             resourcesApk.getColorByName("invalid_color")
414         }
415     }
416 
417     @Test
getColorByName_nullContext_throwsRegardlessOfFallbacknull418     fun getColorByName_nullContext_throwsRegardlessOfFallback() {
419         val resourcesApk =
420             newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
421 
422         assertFailsWith(IllegalStateException::class) { resourcesApk.getColorByName("valid_color") }
423     }
424 
newSafetyCenterResourcesApknull425     private fun newSafetyCenterResourcesApk(
426         resourcesApkAction: String = RESOURCES_APK_ACTION,
427         resourcesApkPath: String = "",
428         flags: Int = 0,
429         fallback: Boolean = false
430     ) = SafetyCenterResourcesApk(context, resourcesApkAction, resourcesApkPath, flags, fallback)
431 
432     companion object {
433         const val RESOURCES_APK_ACTION =
434             "com.android.safetycenter.tests.intent.action.SAFETY_CENTER_TEST_RESOURCES_APK"
435         const val RESOURCES_APK_PKG_NAME =
436             "com.android.safetycenter.tests.config.safetycenterresourceslibtestresources"
437         const val CONFIG_NAME = "test"
438         const val CONFIG_CONTENT = "TEST"
439     }
440 }
441