blob: 4c62955e41a5df9dd31a14f42ff3a44ea1d33bc5 [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.content.Context
20import android.content.res.AssetManager
Winson9947f1e2019-08-16 10:20:39 -070021import android.content.res.Resources
Ryan Mitchell61158582020-01-14 12:35:08 -080022import android.content.res.loader.AssetsProvider
Winson9947f1e2019-08-16 10:20:39 -070023import android.content.res.loader.ResourcesProvider
24import android.os.ParcelFileDescriptor
Winson9947f1e2019-08-16 10:20:39 -070025import androidx.test.InstrumentationRegistry
26import org.junit.After
27import org.junit.Before
Winson9947f1e2019-08-16 10:20:39 -070028import org.mockito.ArgumentMatchers.anyInt
Winson9947f1e2019-08-16 10:20:39 -070029import org.mockito.ArgumentMatchers.eq
30import org.mockito.Mockito.doAnswer
Winson9947f1e2019-08-16 10:20:39 -070031import org.mockito.Mockito.mock
32import java.io.Closeable
33
34abstract class ResourceLoaderTestBase {
35
36 open lateinit var dataType: DataType
37
38 protected lateinit var context: Context
39 protected open val resources: Resources
40 get() = context.resources
41 protected open val assets: AssetManager
42 get() = resources.assets
43
44 // Track opened streams and ResourcesProviders to close them after testing
45 private val openedObjects = mutableListOf<Closeable>()
46
47 @Before
48 fun setUpBase() {
49 context = InstrumentationRegistry.getTargetContext()
50 }
51
52 @After
53 fun removeAllLoaders() {
Ryan Mitchell61158582020-01-14 12:35:08 -080054 resources.clearLoaders()
55 context.applicationContext.resources.clearLoaders()
Winson9947f1e2019-08-16 10:20:39 -070056 openedObjects.forEach {
57 try {
58 it.close()
59 } catch (ignored: Exception) {
60 }
61 }
62 }
63
Ryan Mitchell61158582020-01-14 12:35:08 -080064 protected fun String.openProvider(
Winson9947f1e2019-08-16 10:20:39 -070065 dataType: DataType = this@ResourceLoaderTestBase.dataType
Ryan Mitchell61158582020-01-14 12:35:08 -080066 ): ResourcesProvider = when (dataType) {
Winson9947f1e2019-08-16 10:20:39 -070067 DataType.APK -> {
Ryan Mitchell61158582020-01-14 12:35:08 -080068 context.copiedRawFile("${this}Apk").use {
69 ResourcesProvider.loadFromApk(it, mock(AssetsProvider::class.java))
Winson9947f1e2019-08-16 10:20:39 -070070 }.also { openedObjects += it }
71 }
72 DataType.ARSC -> {
Ryan Mitchell61158582020-01-14 12:35:08 -080073 openArsc(this, mock(AssetsProvider::class.java))
Winson9947f1e2019-08-16 10:20:39 -070074 }
75 DataType.SPLIT -> {
Ryan Mitchell61158582020-01-14 12:35:08 -080076 ResourcesProvider.loadFromSplit(context, this)
Winson9947f1e2019-08-16 10:20:39 -070077 }
Ryan Mitchell61158582020-01-14 12:35:08 -080078 DataType.ASSET -> {
79 val assetsProvider = mock(AssetsProvider::class.java)
80 doAnswer { byteInputStream() }.`when`(assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -070081 .loadAsset(eq("assets/Asset.txt"), anyInt())
Ryan Mitchell61158582020-01-14 12:35:08 -080082 ResourcesProvider.empty(assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -070083 }
Ryan Mitchell61158582020-01-14 12:35:08 -080084 DataType.ASSET_FD -> {
85 val assetsProvider = mock(AssetsProvider::class.java)
Winson9947f1e2019-08-16 10:20:39 -070086 doAnswer {
87 val file = context.filesDir.resolve("Asset.txt")
88 file.writeText(this)
89 ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
Ryan Mitchell61158582020-01-14 12:35:08 -080090 }.`when`(assetsProvider).loadAssetParcelFd("assets/Asset.txt")
91 ResourcesProvider.empty(assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -070092 }
Ryan Mitchell61158582020-01-14 12:35:08 -080093 DataType.NON_ASSET -> {
94 val assetsProvider = mock(AssetsProvider::class.java)
Winson9947f1e2019-08-16 10:20:39 -070095 doAnswer {
96 val file = context.filesDir.resolve("NonAsset.txt")
97 file.writeText(this)
98 ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
Ryan Mitchell61158582020-01-14 12:35:08 -080099 }.`when`(assetsProvider).loadAssetParcelFd("NonAsset.txt")
100 ResourcesProvider.empty(assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -0700101 }
Ryan Mitchell61158582020-01-14 12:35:08 -0800102 DataType.NON_ASSET_DRAWABLE -> {
103 val assetsProvider = mock(AssetsProvider::class.java)
104 doAnswer { context.copiedRawFile(this) }.`when`(assetsProvider)
105 .loadAssetParcelFd("res/drawable-nodpi-v4/non_asset_drawable.xml")
106 openArsc(this, assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -0700107 }
Ryan Mitchell61158582020-01-14 12:35:08 -0800108 DataType.NON_ASSET_BITMAP -> {
109 val assetsProvider = mock(AssetsProvider::class.java)
110 doAnswer { resources.openRawResource(rawFile(this)) }
111 .`when`(assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -0700112 .loadAsset(eq("res/drawable-nodpi-v4/non_asset_bitmap.png"), anyInt())
Ryan Mitchell61158582020-01-14 12:35:08 -0800113 openArsc(this, assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -0700114 }
Ryan Mitchell61158582020-01-14 12:35:08 -0800115 DataType.NON_ASSET_LAYOUT -> {
116 val assetsProvider = mock(AssetsProvider::class.java)
117 doAnswer { resources.openRawResource(rawFile(this)) }.`when`(assetsProvider)
118 .loadAsset(eq("res/layout/layout.xml"), anyInt())
119 doAnswer { context.copiedRawFile(this) }.`when`(assetsProvider)
120 .loadAssetParcelFd("res/layout/layout.xml")
121 openArsc(this, assetsProvider)
Winson9947f1e2019-08-16 10:20:39 -0700122 }
123 }
124
Ryan Mitchell61158582020-01-14 12:35:08 -0800125 protected fun openArsc(rawName: String, assetsProvider: AssetsProvider): ResourcesProvider {
Winson9947f1e2019-08-16 10:20:39 -0700126 return context.copiedRawFile("${rawName}Arsc")
Ryan Mitchell61158582020-01-14 12:35:08 -0800127 .use { ResourcesProvider.loadFromTable(it, assetsProvider) }
Winson9947f1e2019-08-16 10:20:39 -0700128 .also { openedObjects += it }
129 }
130
Winson9947f1e2019-08-16 10:20:39 -0700131 enum class DataType {
132 APK,
133 ARSC,
134 SPLIT,
135 ASSET,
136 ASSET_FD,
137 NON_ASSET,
138 NON_ASSET_DRAWABLE,
139 NON_ASSET_BITMAP,
140 NON_ASSET_LAYOUT,
141 }
142}