blob: 0cc56d721651cf14c55984108f9ab845bc7db888 [file] [log] [blame]
Winson9947f1e2019-08-16 10:20:39 -07001/*
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
17package android.content.res.loader.test
18
Ryan Mitchell61158582020-01-14 12:35:08 -080019import android.app.Activity
20import android.content.Context
21import android.content.Intent
22import android.content.res.Configuration
23import android.content.res.Resources
24import android.content.res.loader.ResourcesLoader
Winson9947f1e2019-08-16 10:20:39 -070025import android.graphics.Color
26import android.graphics.drawable.BitmapDrawable
27import android.graphics.drawable.ColorDrawable
Ryan Mitchell61158582020-01-14 12:35:08 -080028import android.os.IBinder
29import androidx.test.rule.ActivityTestRule
Winson9947f1e2019-08-16 10:20:39 -070030import org.junit.Assert.assertEquals
31import org.junit.Assert.assertNotEquals
Ryan Mitchell61158582020-01-14 12:35:08 -080032import org.junit.Rule
Winson9947f1e2019-08-16 10:20:39 -070033import org.junit.Test
34import org.junit.runner.RunWith
35import org.junit.runners.Parameterized
Ryan Mitchell61158582020-01-14 12:35:08 -080036import java.util.Collections
Winson9947f1e2019-08-16 10:20:39 -070037
38/**
39 * Tests generic ResourceLoader behavior. Intentionally abstract in its test methodology because
40 * the behavior being verified isn't specific to any resource type. As long as it can pass an
41 * equals check.
42 *
43 * Currently tests strings and dimens since String and any Number seemed most relevant to verify.
44 */
45@RunWith(Parameterized::class)
46class ResourceLoaderValuesTest : ResourceLoaderTestBase() {
47
Ryan Mitchell61158582020-01-14 12:35:08 -080048 @get:Rule
49 private val mTestActivityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
50
Winson9947f1e2019-08-16 10:20:39 -070051 companion object {
52 @Parameterized.Parameters(name = "{1} {0}")
53 @JvmStatic
54 fun parameters(): Array<Any> {
55 val parameters = mutableListOf<Parameter>()
56
57 // R.string
58 parameters += Parameter(
59 { getString(android.R.string.cancel) },
60 "stringOne", { "SomeRidiculouslyUnlikelyStringOne" },
61 "stringTwo", { "SomeRidiculouslyUnlikelyStringTwo" },
Ryan Mitchell61158582020-01-14 12:35:08 -080062 "stringThree", { "SomeRidiculouslyUnlikelyStringThree" },
63 "stringFour", { "SomeRidiculouslyUnlikelyStringFour" },
Winson9947f1e2019-08-16 10:20:39 -070064 listOf(DataType.APK, DataType.ARSC)
65 )
66
67 // R.dimen
68 parameters += Parameter(
Ryan Mitchell61158582020-01-14 12:35:08 -080069 { getDimensionPixelSize(android.R.dimen.app_icon_size) },
70 "dimenOne", { 100.dpToPx(resources) },
71 "dimenTwo", { 200.dpToPx(resources) },
72 "dimenThree", { 300.dpToPx(resources) },
73 "dimenFour", { 400.dpToPx(resources) },
Winson9947f1e2019-08-16 10:20:39 -070074 listOf(DataType.APK, DataType.ARSC)
75 )
76
77 // File in the assets directory
78 parameters += Parameter(
79 { assets.open("Asset.txt").reader().readText() },
80 "assetOne", { "assetOne" },
81 "assetTwo", { "assetTwo" },
Ryan Mitchell61158582020-01-14 12:35:08 -080082 "assetFour", { "assetFour" },
83 "assetThree", { "assetThree" },
Winson9947f1e2019-08-16 10:20:39 -070084 listOf(DataType.ASSET)
85 )
86
87 // From assets directory returning file descriptor
88 parameters += Parameter(
89 { assets.openFd("Asset.txt").readText() },
90 "assetOne", { "assetOne" },
91 "assetTwo", { "assetTwo" },
Ryan Mitchell61158582020-01-14 12:35:08 -080092 "assetFour", { "assetFour" },
93 "assetThree", { "assetThree" },
Winson9947f1e2019-08-16 10:20:39 -070094 listOf(DataType.ASSET_FD)
95 )
96
97 // From root directory returning file descriptor
98 parameters += Parameter(
99 { assets.openNonAssetFd("NonAsset.txt").readText() },
100 "NonAssetOne", { "NonAssetOne" },
101 "NonAssetTwo", { "NonAssetTwo" },
Ryan Mitchell61158582020-01-14 12:35:08 -0800102 "NonAssetThree", { "NonAssetThree" },
103 "NonAssetFour", { "NonAssetFour" },
Winson9947f1e2019-08-16 10:20:39 -0700104 listOf(DataType.NON_ASSET)
105 )
106
107 // Asset as compiled XML drawable
108 parameters += Parameter(
109 { (getDrawable(R.drawable.non_asset_drawable) as ColorDrawable).color },
Ryan Mitchell61158582020-01-14 12:35:08 -0800110 "nonAssetDrawableOne", { Color.parseColor("#000001") },
111 "nonAssetDrawableTwo", { Color.parseColor("#000002") },
112 "nonAssetDrawableThree", { Color.parseColor("#000003") },
113 "nonAssetDrawableFour", { Color.parseColor("#000004") },
Winson9947f1e2019-08-16 10:20:39 -0700114 listOf(DataType.NON_ASSET_DRAWABLE)
115 )
116
117 // Asset as compiled bitmap drawable
118 parameters += Parameter(
119 {
120 (getDrawable(R.drawable.non_asset_bitmap) as BitmapDrawable)
121 .bitmap.getColor(0, 0).toArgb()
122 },
Ryan Mitchell61158582020-01-14 12:35:08 -0800123 "nonAssetBitmapRed", { Color.RED },
Winson9947f1e2019-08-16 10:20:39 -0700124 "nonAssetBitmapGreen", { Color.GREEN },
125 "nonAssetBitmapBlue", { Color.BLUE },
Ryan Mitchell61158582020-01-14 12:35:08 -0800126 "nonAssetBitmapWhite", { Color.WHITE },
Winson9947f1e2019-08-16 10:20:39 -0700127 listOf(DataType.NON_ASSET_BITMAP)
128 )
129
130 // Asset as compiled XML layout
131 parameters += Parameter(
132 { getLayout(R.layout.layout).advanceToRoot().name },
133 "layoutOne", { "RelativeLayout" },
134 "layoutTwo", { "LinearLayout" },
Ryan Mitchell61158582020-01-14 12:35:08 -0800135 "layoutThree", { "FrameLayout" },
136 "layoutFour", { "TableLayout" },
Winson9947f1e2019-08-16 10:20:39 -0700137 listOf(DataType.NON_ASSET_LAYOUT)
138 )
139
140 // Isolated resource split
141 parameters += Parameter(
142 { getString(R.string.split_overlaid) },
143 "split_one", { "Split ONE Overlaid" },
144 "split_two", { "Split TWO Overlaid" },
Ryan Mitchell61158582020-01-14 12:35:08 -0800145 "split_three", { "Split THREE Overlaid" },
146 "split_four", { "Split FOUR Overlaid" },
Winson9947f1e2019-08-16 10:20:39 -0700147 listOf(DataType.SPLIT)
148 )
149
150 return parameters.flatMap { parameter ->
151 parameter.dataTypes.map { dataType ->
152 arrayOf(dataType, parameter)
153 }
154 }.toTypedArray()
155 }
156 }
157
158 @Suppress("LateinitVarOverridesLateinitVar")
159 @field:Parameterized.Parameter(0)
160 override lateinit var dataType: DataType
161
162 @field:Parameterized.Parameter(1)
163 lateinit var parameter: Parameter
164
165 private val valueOne by lazy { parameter.valueOne(this) }
166 private val valueTwo by lazy { parameter.valueTwo(this) }
Ryan Mitchell61158582020-01-14 12:35:08 -0800167 private val valueThree by lazy { parameter.valueThree(this) }
168 private val valueFour by lazy { parameter.valueFour(this) }
Winson9947f1e2019-08-16 10:20:39 -0700169
Ryan Mitchell61158582020-01-14 12:35:08 -0800170 private fun openOne() = parameter.providerOne.openProvider()
171 private fun openTwo() = parameter.providerTwo.openProvider()
172 private fun openThree() = parameter.providerThree.openProvider()
173 private fun openFour() = parameter.providerFour.openProvider()
Winson9947f1e2019-08-16 10:20:39 -0700174
175 // Class method for syntax highlighting purposes
Ryan Mitchell61158582020-01-14 12:35:08 -0800176 private fun getValue(c: Context = context) = parameter.getValue(c.resources)
Winson9947f1e2019-08-16 10:20:39 -0700177
178 @Test
Ryan Mitchell61158582020-01-14 12:35:08 -0800179 fun assertValueUniqueness() {
Winson9947f1e2019-08-16 10:20:39 -0700180 // Ensure the parameters are valid in case of coding errors
Ryan Mitchell61158582020-01-14 12:35:08 -0800181 val original = getValue()
182 assertNotEquals(valueOne, original)
183 assertNotEquals(valueTwo, original)
184 assertNotEquals(valueThree, original)
185 assertNotEquals(valueFour, original)
186 assertNotEquals(valueTwo, valueOne)
187 assertNotEquals(valueThree, valueOne)
188 assertNotEquals(valueFour, valueOne)
189 assertNotEquals(valueThree, valueTwo)
190 assertNotEquals(valueFour, valueTwo)
191 assertNotEquals(valueFour, valueThree)
192 }
193
194 @Test
195 fun addMultipleProviders() {
196 val originalValue = getValue()
197 val testOne = openOne()
198 val testTwo = openTwo()
199 val loader = ResourcesLoader()
200
201 resources.addLoader(loader)
202 loader.addProvider(testOne)
203 assertEquals(valueOne, getValue())
204
205 loader.addProvider(testTwo)
206 assertEquals(valueTwo, getValue())
207
208 loader.removeProvider(testOne)
209 assertEquals(valueTwo, getValue())
210
211 loader.removeProvider(testTwo)
212 assertEquals(originalValue, getValue())
Winson9947f1e2019-08-16 10:20:39 -0700213 }
214
215 @Test
216 fun addMultipleLoaders() {
217 val originalValue = getValue()
218 val testOne = openOne()
219 val testTwo = openTwo()
Ryan Mitchell61158582020-01-14 12:35:08 -0800220 val loader1 = ResourcesLoader()
221 val loader2 = ResourcesLoader()
Winson9947f1e2019-08-16 10:20:39 -0700222
Ryan Mitchell61158582020-01-14 12:35:08 -0800223 resources.addLoader(loader1)
224 loader1.addProvider(testOne)
Winson9947f1e2019-08-16 10:20:39 -0700225 assertEquals(valueOne, getValue())
226
Ryan Mitchell61158582020-01-14 12:35:08 -0800227 resources.addLoader(loader2)
228 loader2.addProvider(testTwo)
229 assertEquals(valueTwo, getValue())
Winson9947f1e2019-08-16 10:20:39 -0700230
Ryan Mitchell61158582020-01-14 12:35:08 -0800231 resources.removeLoader(loader1)
232 assertEquals(valueTwo, getValue())
233
234 resources.removeLoader(loader2)
235 assertEquals(originalValue, getValue())
236 }
237
238 @Test
239 fun setMultipleProviders() {
240 val originalValue = getValue()
241 val testOne = openOne()
242 val testTwo = openTwo()
243 val loader = ResourcesLoader()
244
245 resources.addLoader(loader)
246 loader.providers = listOf(testOne, testTwo)
247 assertEquals(valueTwo, getValue())
248
249 loader.removeProvider(testTwo)
250 assertEquals(valueOne, getValue())
251
252 loader.providers = Collections.emptyList()
Winson9947f1e2019-08-16 10:20:39 -0700253 assertEquals(originalValue, getValue())
254 }
255
256 @Test
257 fun setMultipleLoaders() {
258 val originalValue = getValue()
Ryan Mitchell61158582020-01-14 12:35:08 -0800259 val loader1 = ResourcesLoader()
260 loader1.addProvider(openOne())
261 val loader2 = ResourcesLoader()
262 loader2.addProvider(openTwo())
Winson9947f1e2019-08-16 10:20:39 -0700263
Ryan Mitchell61158582020-01-14 12:35:08 -0800264 resources.loaders = listOf(loader1, loader2)
Winson9947f1e2019-08-16 10:20:39 -0700265 assertEquals(valueTwo, getValue())
266
Ryan Mitchell61158582020-01-14 12:35:08 -0800267 resources.removeLoader(loader2)
Winson9947f1e2019-08-16 10:20:39 -0700268 assertEquals(valueOne, getValue())
269
Ryan Mitchell61158582020-01-14 12:35:08 -0800270 resources.loaders = Collections.emptyList()
Winson9947f1e2019-08-16 10:20:39 -0700271 assertEquals(originalValue, getValue())
272 }
273
Ryan Mitchell61158582020-01-14 12:35:08 -0800274 @Test(expected = UnsupportedOperationException::class)
275 fun getProvidersDoesNotLeakMutability() {
Winson9947f1e2019-08-16 10:20:39 -0700276 val testOne = openOne()
Ryan Mitchell61158582020-01-14 12:35:08 -0800277 val loader = ResourcesLoader()
278 val providers = loader.providers
279 providers += testOne
Winson9947f1e2019-08-16 10:20:39 -0700280 }
281
Ryan Mitchell61158582020-01-14 12:35:08 -0800282 @Test(expected = UnsupportedOperationException::class)
Winson9947f1e2019-08-16 10:20:39 -0700283 fun getLoadersDoesNotLeakMutability() {
Ryan Mitchell61158582020-01-14 12:35:08 -0800284 val loaders = resources.loaders
285 loaders += ResourcesLoader()
286 }
287
288 @Test
289 fun alreadyAddedProviderNoOps() {
290 val testOne = openOne()
291 val testTwo = openTwo()
292 val loader = ResourcesLoader()
293
294 resources.addLoader(loader)
295 loader.addProvider(testOne)
296 loader.addProvider(testTwo)
297 loader.addProvider(testOne)
298
299 assertEquals(2, loader.providers.size)
300 assertEquals(loader.providers[0], testOne)
301 assertEquals(loader.providers[1], testTwo)
302 }
303
304 @Test
305 fun alreadyAddedLoaderNoOps() {
306 val loader1 = ResourcesLoader()
307 loader1.addProvider(openOne())
308 val loader2 = ResourcesLoader()
309 loader2.addProvider(openTwo())
310
311 resources.addLoader(loader1)
312 resources.addLoader(loader2)
313 resources.addLoader(loader1)
314
315 assertEquals(2, resources.loaders.size)
316 assertEquals(resources.loaders[0], loader1)
317 assertEquals(resources.loaders[1], loader2)
318 }
319
320 @Test
321 fun repeatedRemoveProviderNoOps() {
322 val testOne = openOne()
323 val testTwo = openTwo()
324 val loader = ResourcesLoader()
325
326 resources.addLoader(loader)
327 loader.addProvider(testOne)
328 loader.addProvider(testTwo)
329
330 loader.removeProvider(testOne)
331 loader.removeProvider(testOne)
332
333 assertEquals(1, loader.providers.size)
334 assertEquals(loader.providers[0], testTwo)
335 }
336
337 @Test
338 fun repeatedRemoveLoaderNoOps() {
339 val loader1 = ResourcesLoader()
340 loader1.addProvider(openOne())
341 val loader2 = ResourcesLoader()
342 loader2.addProvider(openTwo())
343
344 resources.loaders = listOf(loader1, loader2)
345 resources.removeLoader(loader1)
346 resources.removeLoader(loader1)
347
348 assertEquals(1, resources.loaders.size)
349 assertEquals(resources.loaders[0], loader2)
350 }
351
352 @Test
353 fun repeatedSetProvider() {
354 val testOne = openOne()
355 val testTwo = openTwo()
356 val loader = ResourcesLoader()
357
358 resources.addLoader(loader)
359 loader.providers = listOf(testOne, testTwo)
360 loader.providers = listOf(testOne, testTwo)
361
362 assertEquals(2, loader.providers.size)
363 assertEquals(loader.providers[0], testOne)
364 assertEquals(loader.providers[1], testTwo)
365 }
366
367 @Test
368 fun repeatedSetLoaders() {
369 val loader1 = ResourcesLoader()
370 loader1.addProvider(openOne())
371 val loader2 = ResourcesLoader()
372 loader2.addProvider(openTwo())
373
374 resources.loaders = listOf(loader1, loader2)
375 resources.loaders = listOf(loader1, loader2)
376
377 assertEquals(2, resources.loaders.size)
378 assertEquals(resources.loaders[0], loader1)
379 assertEquals(resources.loaders[1], loader2)
380 }
381
382 @Test
383 fun reorderProviders() {
Winson9947f1e2019-08-16 10:20:39 -0700384 val originalValue = getValue()
385 val testOne = openOne()
386 val testTwo = openTwo()
Ryan Mitchell61158582020-01-14 12:35:08 -0800387 val loader = ResourcesLoader()
Winson9947f1e2019-08-16 10:20:39 -0700388
Ryan Mitchell61158582020-01-14 12:35:08 -0800389 resources.addLoader(loader)
390 loader.addProvider(testOne)
391 loader.addProvider(testTwo)
Winson9947f1e2019-08-16 10:20:39 -0700392 assertEquals(valueTwo, getValue())
Winson9947f1e2019-08-16 10:20:39 -0700393
Ryan Mitchell61158582020-01-14 12:35:08 -0800394 loader.removeProvider(testOne)
Winson9947f1e2019-08-16 10:20:39 -0700395 assertEquals(valueTwo, getValue())
Winson9947f1e2019-08-16 10:20:39 -0700396
Ryan Mitchell61158582020-01-14 12:35:08 -0800397 loader.addProvider(testOne)
Winson9947f1e2019-08-16 10:20:39 -0700398 assertEquals(valueOne, getValue())
399
Ryan Mitchell61158582020-01-14 12:35:08 -0800400 loader.removeProvider(testTwo)
Winson9947f1e2019-08-16 10:20:39 -0700401 assertEquals(valueOne, getValue())
402
Ryan Mitchell61158582020-01-14 12:35:08 -0800403 loader.removeProvider(testOne)
404 assertEquals(originalValue, getValue())
Winson9947f1e2019-08-16 10:20:39 -0700405 }
406
407 @Test
Ryan Mitchell61158582020-01-14 12:35:08 -0800408 fun reorderLoaders() {
Winson9947f1e2019-08-16 10:20:39 -0700409 val originalValue = getValue()
410 val testOne = openOne()
411 val testTwo = openTwo()
Ryan Mitchell61158582020-01-14 12:35:08 -0800412 val loader1 = ResourcesLoader()
413 loader1.addProvider(testOne)
414 val loader2 = ResourcesLoader()
415 loader2.addProvider(testTwo)
Winson9947f1e2019-08-16 10:20:39 -0700416
Ryan Mitchell61158582020-01-14 12:35:08 -0800417 resources.addLoader(loader1)
418 resources.addLoader(loader2)
Winson9947f1e2019-08-16 10:20:39 -0700419 assertEquals(valueTwo, getValue())
420
Ryan Mitchell61158582020-01-14 12:35:08 -0800421 resources.removeLoader(loader1)
Winson9947f1e2019-08-16 10:20:39 -0700422 assertEquals(valueTwo, getValue())
423
Ryan Mitchell61158582020-01-14 12:35:08 -0800424 resources.addLoader(loader1)
Winson9947f1e2019-08-16 10:20:39 -0700425 assertEquals(valueOne, getValue())
426
Ryan Mitchell61158582020-01-14 12:35:08 -0800427 resources.removeLoader(loader2)
Winson9947f1e2019-08-16 10:20:39 -0700428 assertEquals(valueOne, getValue())
429
Ryan Mitchell61158582020-01-14 12:35:08 -0800430 resources.removeLoader(loader1)
Winson9947f1e2019-08-16 10:20:39 -0700431 assertEquals(originalValue, getValue())
432 }
433
Ryan Mitchell61158582020-01-14 12:35:08 -0800434 @Test
435 fun reorderMultipleLoadersAndProviders() {
436 val testOne = openOne()
437 val testTwo = openTwo()
438 val testThree = openThree()
439 val testFour = openFour()
440
441 val loader1 = ResourcesLoader()
442 loader1.providers = listOf(testOne, testTwo)
443
444 val loader2 = ResourcesLoader()
445 loader2.providers = listOf(testThree, testFour)
446
447 resources.loaders = listOf(loader1, loader2)
448 assertEquals(valueFour, getValue())
449
450 resources.loaders = listOf(loader2, loader1)
451 assertEquals(valueTwo, getValue())
452
453 loader1.removeProvider(testTwo)
454 assertEquals(valueOne, getValue())
455
456 loader1.removeProvider(testOne)
457 assertEquals(valueFour, getValue())
458 }
459
460 private fun createContext(context: Context, id: Int): Context {
461 val overrideConfig = Configuration()
462 overrideConfig.orientation = Int.MAX_VALUE - id
463 return context.createConfigurationContext(overrideConfig)
464 }
465
466 @Test
467 fun copyContextLoaders() {
468 val originalValue = getValue()
469 val loader1 = ResourcesLoader()
470 loader1.addProvider(openOne())
471 val loader2 = ResourcesLoader()
472 loader2.addProvider(openTwo())
473
474 resources.loaders = listOf(loader1)
475 assertEquals(valueOne, getValue())
476
477 // The child context should include the loaders of the original context.
478 val childContext = createContext(context, 0)
479 assertEquals(valueOne, getValue(childContext))
480
481 // Changing the loaders of the child context should not affect the original context.
482 childContext.resources.loaders = listOf(loader1, loader2)
483 assertEquals(valueOne, getValue())
484 assertEquals(valueTwo, getValue(childContext))
485
486 // Changing the loaders of the original context should not affect the child context.
487 resources.removeLoader(loader1)
488 assertEquals(originalValue, getValue())
489 assertEquals(valueTwo, getValue(childContext))
490
491 // A new context created from the original after an update to the original's loaders should
492 // have the updated loaders.
493 val originalPrime = createContext(context, 2)
494 assertEquals(originalValue, getValue(originalPrime))
495
496 // A new context created from the child context after an update to the child's loaders
497 // should have the updated loaders.
498 val childPrime = createContext(childContext, 1)
499 assertEquals(valueTwo, getValue(childPrime))
500 }
501
502 @Test
503 fun loaderUpdatesAffectContexts() {
504 val originalValue = getValue()
505 val testOne = openOne()
506 val testTwo = openTwo()
507 val loader = ResourcesLoader()
508
509 resources.addLoader(loader)
510 loader.addProvider(testOne)
511 assertEquals(valueOne, getValue())
512
513 val childContext = createContext(context, 0)
514 assertEquals(valueOne, getValue(childContext))
515
516 // Adding a provider to a loader affects all contexts that use the loader.
517 loader.addProvider(testTwo)
518 assertEquals(valueTwo, getValue())
519 assertEquals(valueTwo, getValue(childContext))
520
521 // Changes to the loaders for a context do not affect providers.
522 resources.clearLoaders()
523 assertEquals(originalValue, getValue())
524 assertEquals(valueTwo, getValue(childContext))
525
526 val childContext2 = createContext(context, 1)
527 assertEquals(originalValue, getValue())
528 assertEquals(originalValue, getValue(childContext2))
529
530 childContext2.resources.addLoader(loader)
531 assertEquals(originalValue, getValue())
532 assertEquals(valueTwo, getValue(childContext))
533 assertEquals(valueTwo, getValue(childContext2))
534 }
535
536 @Test
537 fun appLoadersIncludedInActivityContexts() {
538 val loader = ResourcesLoader()
539 loader.addProvider(openOne())
540
541 val applicationContext = context.applicationContext
542 applicationContext.resources.addLoader(loader)
543 assertEquals(valueOne, getValue(applicationContext))
544
545 val activity = mTestActivityRule.launchActivity(Intent())
546 assertEquals(valueOne, getValue(activity))
547
548 applicationContext.resources.clearLoaders()
549 }
550
551 @Test
552 fun loadersApplicationInfoChanged() {
553 val loader1 = ResourcesLoader()
554 loader1.addProvider(openOne())
555 val loader2 = ResourcesLoader()
556 loader2.addProvider(openTwo())
557
558 val applicationContext = context.applicationContext
559 applicationContext.resources.addLoader(loader1)
560 assertEquals(valueOne, getValue(applicationContext))
561
562 var token: IBinder? = null
563 val activity = mTestActivityRule.launchActivity(Intent())
564 mTestActivityRule.runOnUiThread(Runnable {
565 token = activity.activityToken
566 val at = activity.activityThread
567
568 // The activity should have the loaders from the application.
569 assertEquals(valueOne, getValue(applicationContext))
570 assertEquals(valueOne, getValue(activity))
571
572 activity.resources.addLoader(loader2)
573 assertEquals(valueOne, getValue(applicationContext))
574 assertEquals(valueTwo, getValue(activity))
575
576 // Relaunches the activity.
577 at.handleApplicationInfoChanged(activity.applicationInfo)
578 })
579
580 mTestActivityRule.runOnUiThread(Runnable {
581 val activityThread = activity.activityThread
582 val newActivity = activityThread.getActivity(token)
583
584 // The loader added to the activity loaders should not be persisted.
585 assertEquals(valueOne, getValue(applicationContext))
586 assertEquals(valueOne, getValue(newActivity))
587 })
588
589 applicationContext.resources.clearLoaders()
590 }
591
592 @Test
593 fun multipleLoadersHaveSameProviders() {
594 val provider1 = openOne()
595 val loader1 = ResourcesLoader()
596 loader1.addProvider(provider1)
597 val loader2 = ResourcesLoader()
598 loader2.addProvider(provider1)
599 loader2.addProvider(openTwo())
600
601 resources.loaders = listOf(loader1, loader2)
602 assertEquals(valueTwo, getValue())
603
604 resources.loaders = listOf(loader2, loader1)
605 assertEquals(valueOne, getValue())
606
607 assertEquals(2, resources.assets.apkAssets.count { apkAssets -> apkAssets.isForLoader })
608 }
609
610 @Test(expected = IllegalStateException::class)
611 fun cannotUseClosedProvider() {
612 val provider = openOne()
613 provider.close()
614 val loader = ResourcesLoader()
615 loader.addProvider(provider)
616 }
617
618 @Test(expected = IllegalStateException::class)
619 fun cannotCloseUsedProvider() {
620 val provider = openOne()
621 val loader = ResourcesLoader()
622 loader.addProvider(provider)
623 provider.close()
624 }
625
Winson9947f1e2019-08-16 10:20:39 -0700626 data class Parameter(
Ryan Mitchell61158582020-01-14 12:35:08 -0800627 val getValue: Resources.() -> Any,
628 val providerOne: String,
Winson9947f1e2019-08-16 10:20:39 -0700629 val valueOne: ResourceLoaderValuesTest.() -> Any,
Ryan Mitchell61158582020-01-14 12:35:08 -0800630 val providerTwo: String,
Winson9947f1e2019-08-16 10:20:39 -0700631 val valueTwo: ResourceLoaderValuesTest.() -> Any,
Ryan Mitchell61158582020-01-14 12:35:08 -0800632 val providerThree: String,
633 val valueThree: ResourceLoaderValuesTest.() -> Any,
634 val providerFour: String,
635 val valueFour: ResourceLoaderValuesTest.() -> Any,
Winson9947f1e2019-08-16 10:20:39 -0700636 val dataTypes: List<DataType>
637 ) {
638 override fun toString(): String {
Ryan Mitchell61158582020-01-14 12:35:08 -0800639 val prefix = providerOne.commonPrefixWith(providerTwo)
640 return "$prefix${providerOne.removePrefix(prefix)}|${providerTwo.removePrefix(prefix)}"
Winson9947f1e2019-08-16 10:20:39 -0700641 }
642 }
643}
Ryan Mitchell61158582020-01-14 12:35:08 -0800644
645class TestActivity : Activity()