blob: 017552a021526c0d97ddf7e2fe5f1a87b9843b73 [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
19import android.graphics.Color
20import android.graphics.drawable.BitmapDrawable
21import android.graphics.drawable.ColorDrawable
22import com.google.common.truth.Truth.assertThat
23import org.junit.Assert.assertEquals
24import org.junit.Assert.assertNotEquals
25import org.junit.Test
26import org.junit.runner.RunWith
27import org.junit.runners.Parameterized
28
29/**
30 * Tests generic ResourceLoader behavior. Intentionally abstract in its test methodology because
31 * the behavior being verified isn't specific to any resource type. As long as it can pass an
32 * equals check.
33 *
34 * Currently tests strings and dimens since String and any Number seemed most relevant to verify.
35 */
36@RunWith(Parameterized::class)
37class ResourceLoaderValuesTest : ResourceLoaderTestBase() {
38
39 companion object {
40 @Parameterized.Parameters(name = "{1} {0}")
41 @JvmStatic
42 fun parameters(): Array<Any> {
43 val parameters = mutableListOf<Parameter>()
44
45 // R.string
46 parameters += Parameter(
47 { getString(android.R.string.cancel) },
48 "stringOne", { "SomeRidiculouslyUnlikelyStringOne" },
49 "stringTwo", { "SomeRidiculouslyUnlikelyStringTwo" },
50 listOf(DataType.APK, DataType.ARSC)
51 )
52
53 // R.dimen
54 parameters += Parameter(
55 { resources.getDimensionPixelSize(android.R.dimen.app_icon_size) },
56 "dimenOne", { 564716.dpToPx(resources) },
57 "dimenTwo", { 565717.dpToPx(resources) },
58 listOf(DataType.APK, DataType.ARSC)
59 )
60
61 // File in the assets directory
62 parameters += Parameter(
63 { assets.open("Asset.txt").reader().readText() },
64 "assetOne", { "assetOne" },
65 "assetTwo", { "assetTwo" },
66 listOf(DataType.ASSET)
67 )
68
69 // From assets directory returning file descriptor
70 parameters += Parameter(
71 { assets.openFd("Asset.txt").readText() },
72 "assetOne", { "assetOne" },
73 "assetTwo", { "assetTwo" },
74 listOf(DataType.ASSET_FD)
75 )
76
77 // From root directory returning file descriptor
78 parameters += Parameter(
79 { assets.openNonAssetFd("NonAsset.txt").readText() },
80 "NonAssetOne", { "NonAssetOne" },
81 "NonAssetTwo", { "NonAssetTwo" },
82 listOf(DataType.NON_ASSET)
83 )
84
85 // Asset as compiled XML drawable
86 parameters += Parameter(
87 { (getDrawable(R.drawable.non_asset_drawable) as ColorDrawable).color },
88 "nonAssetDrawableOne", { Color.parseColor("#A3C3E3") },
89 "nonAssetDrawableTwo", { Color.parseColor("#3A3C3E") },
90 listOf(DataType.NON_ASSET_DRAWABLE)
91 )
92
93 // Asset as compiled bitmap drawable
94 parameters += Parameter(
95 {
96 (getDrawable(R.drawable.non_asset_bitmap) as BitmapDrawable)
97 .bitmap.getColor(0, 0).toArgb()
98 },
99 "nonAssetBitmapGreen", { Color.GREEN },
100 "nonAssetBitmapBlue", { Color.BLUE },
101 listOf(DataType.NON_ASSET_BITMAP)
102 )
103
104 // Asset as compiled XML layout
105 parameters += Parameter(
106 { getLayout(R.layout.layout).advanceToRoot().name },
107 "layoutOne", { "RelativeLayout" },
108 "layoutTwo", { "LinearLayout" },
109 listOf(DataType.NON_ASSET_LAYOUT)
110 )
111
112 // Isolated resource split
113 parameters += Parameter(
114 { getString(R.string.split_overlaid) },
115 "split_one", { "Split ONE Overlaid" },
116 "split_two", { "Split TWO Overlaid" },
117 listOf(DataType.SPLIT)
118 )
119
120 return parameters.flatMap { parameter ->
121 parameter.dataTypes.map { dataType ->
122 arrayOf(dataType, parameter)
123 }
124 }.toTypedArray()
125 }
126 }
127
128 @Suppress("LateinitVarOverridesLateinitVar")
129 @field:Parameterized.Parameter(0)
130 override lateinit var dataType: DataType
131
132 @field:Parameterized.Parameter(1)
133 lateinit var parameter: Parameter
134
135 private val valueOne by lazy { parameter.valueOne(this) }
136 private val valueTwo by lazy { parameter.valueTwo(this) }
137
138 private fun openOne() = parameter.loaderOne.openLoader()
139 private fun openTwo() = parameter.loaderTwo.openLoader()
140
141 // Class method for syntax highlighting purposes
142 private fun getValue() = parameter.getValue(this)
143
144 @Test
145 fun verifyValueUniqueness() {
146 // Ensure the parameters are valid in case of coding errors
147 assertNotEquals(valueOne, getValue())
148 assertNotEquals(valueTwo, getValue())
149 assertNotEquals(valueOne, valueTwo)
150 }
151
152 @Test
153 fun addMultipleLoaders() {
154 val originalValue = getValue()
155 val testOne = openOne()
156 val testTwo = openTwo()
157
158 addLoader(testOne, testTwo)
159
160 assertEquals(valueTwo, getValue())
161
162 removeLoader(testTwo)
163
164 assertEquals(valueOne, getValue())
165
166 removeLoader(testOne)
167
168 assertEquals(originalValue, getValue())
169 }
170
171 @Test
172 fun setMultipleLoaders() {
173 val originalValue = getValue()
174 val testOne = openOne()
175 val testTwo = openTwo()
176
177 setLoaders(testOne, testTwo)
178
179 assertEquals(valueTwo, getValue())
180
181 removeLoader(testTwo)
182
183 assertEquals(valueOne, getValue())
184
185 setLoaders()
186
187 assertEquals(originalValue, getValue())
188 }
189
190 @Test
191 fun getLoadersContainsAll() {
192 val testOne = openOne()
193 val testTwo = openTwo()
194
195 addLoader(testOne, testTwo)
196
197 assertThat(getLoaders()).containsAllOf(testOne, testTwo)
198 }
199
200 @Test
201 fun getLoadersDoesNotLeakMutability() {
202 val originalValue = getValue()
203 val testOne = openOne()
204 val testTwo = openTwo()
205
206 addLoader(testOne)
207
208 assertEquals(valueOne, getValue())
209
210 val loaders = getLoaders()
211 loaders += testTwo
212
213 assertEquals(valueOne, getValue())
214
215 removeLoader(testOne)
216
217 assertEquals(originalValue, getValue())
218 }
219
220 @Test(expected = IllegalArgumentException::class)
221 fun alreadyAddedThrows() {
222 val testOne = openOne()
223 val testTwo = openTwo()
224
225 addLoader(testOne)
226 addLoader(testTwo)
227 addLoader(testOne)
228 }
229
230 @Test(expected = IllegalArgumentException::class)
231 fun alreadyAddedAndSetThrows() {
232 val testOne = openOne()
233 val testTwo = openTwo()
234
235 addLoader(testOne)
236 addLoader(testTwo)
237 setLoaders(testTwo)
238 }
239
240 @Test
241 fun repeatedRemoveSucceeds() {
242 val originalValue = getValue()
243 val testOne = openOne()
244
245 addLoader(testOne)
246
247 assertNotEquals(originalValue, getValue())
248
249 removeLoader(testOne)
250
251 assertEquals(originalValue, getValue())
252
253 removeLoader(testOne)
254
255 assertEquals(originalValue, getValue())
256 }
257
258 @Test
259 fun addToFront() {
260 val testOne = openOne()
261 val testTwo = openTwo()
262
263 addLoader(testOne)
264
265 assertEquals(valueOne, getValue())
266
267 addLoader(testTwo, 0)
268
269 assertEquals(valueOne, getValue())
270
271 // Remove top loader, so previously added to front should now resolve
272 removeLoader(testOne)
273 assertEquals(valueTwo, getValue())
274 }
275
276 @Test
277 fun addToEnd() {
278 val testOne = openOne()
279 val testTwo = openTwo()
280
281 addLoader(testOne)
282
283 assertEquals(valueOne, getValue())
284
285 addLoader(testTwo, 1)
286
287 assertEquals(valueTwo, getValue())
288 }
289
290 @Test(expected = IndexOutOfBoundsException::class)
291 fun addPastEnd() {
292 val testOne = openOne()
293 val testTwo = openTwo()
294
295 addLoader(testOne)
296
297 assertEquals(valueOne, getValue())
298
299 addLoader(testTwo, 2)
300 }
301
302 @Test(expected = IndexOutOfBoundsException::class)
303 fun addBeforeFront() {
304 val testOne = openOne()
305 val testTwo = openTwo()
306
307 addLoader(testOne)
308
309 assertEquals(valueOne, getValue())
310
311 addLoader(testTwo, -1)
312 }
313
314 @Test
315 fun reorder() {
316 val originalValue = getValue()
317 val testOne = openOne()
318 val testTwo = openTwo()
319
320 addLoader(testOne, testTwo)
321
322 assertEquals(valueTwo, getValue())
323
324 removeLoader(testOne)
325
326 assertEquals(valueTwo, getValue())
327
328 addLoader(testOne)
329
330 assertEquals(valueOne, getValue())
331
332 removeLoader(testTwo)
333
334 assertEquals(valueOne, getValue())
335
336 removeLoader(testOne)
337
338 assertEquals(originalValue, getValue())
339 }
340
341 data class Parameter(
342 val getValue: ResourceLoaderValuesTest.() -> Any,
343 val loaderOne: String,
344 val valueOne: ResourceLoaderValuesTest.() -> Any,
345 val loaderTwo: String,
346 val valueTwo: ResourceLoaderValuesTest.() -> Any,
347 val dataTypes: List<DataType>
348 ) {
349 override fun toString(): String {
350 val prefix = loaderOne.commonPrefixWith(loaderTwo)
351 return "$prefix${loaderOne.removePrefix(prefix)}|${loaderTwo.removePrefix(prefix)}"
352 }
353 }
354}