blob: a6a83789c082d8fa1054b10677403e2092c1b3fb [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.res.AssetManager
20import android.content.res.loader.DirectoryResourceLoader
21import android.content.res.loader.ResourceLoader
22import android.content.res.loader.ResourcesProvider
23import com.google.common.truth.Truth.assertThat
24import org.junit.Before
25import org.junit.Rule
26import org.junit.Test
27import org.junit.rules.TestName
28import org.junit.runner.RunWith
29import org.junit.runners.Parameterized
30import org.mockito.Mockito.anyInt
31import org.mockito.Mockito.anyString
32import org.mockito.Mockito.doAnswer
33import org.mockito.Mockito.doReturn
34import org.mockito.Mockito.eq
35import org.mockito.Mockito.inOrder
36import org.mockito.Mockito.mock
37import java.io.File
38import java.io.FileNotFoundException
39import java.io.IOException
40import java.nio.file.Paths
41
42@RunWith(Parameterized::class)
43class ResourceLoaderAssetTest : ResourceLoaderTestBase() {
44
45 companion object {
46 private const val BASE_TEST_PATH = "android/content/res/loader/test/file.txt"
47 private const val TEST_TEXT = "some text"
48
49 @JvmStatic
50 @Parameterized.Parameters(name = "{0}")
51 fun parameters(): Array<Array<out Any?>> {
52 val fromInputStream: ResourceLoader.(String) -> Any? = {
53 loadAsset(eq(it), anyInt())
54 }
55
56 val fromFileDescriptor: ResourceLoader.(String) -> Any? = {
57 loadAssetFd(eq(it))
58 }
59
60 val openAsset: AssetManager.() -> String? = {
61 open(BASE_TEST_PATH).reader().readText()
62 }
63
64 val openNonAsset: AssetManager.() -> String? = {
65 openNonAssetFd(BASE_TEST_PATH).readText()
66 }
67
68 return arrayOf(
69 arrayOf("assets", fromInputStream, openAsset),
70 arrayOf("", fromFileDescriptor, openNonAsset)
71 )
72 }
73 }
74
75 @get:Rule
76 val testName = TestName()
77
78 @JvmField
79 @field:Parameterized.Parameter(0)
80 var prefix: String? = null
81
82 @field:Parameterized.Parameter(1)
83 lateinit var loadAssetFunction: ResourceLoader.(String) -> Any?
84
85 @field:Parameterized.Parameter(2)
86 lateinit var openAssetFunction: AssetManager.() -> String?
87
88 private val testPath: String
89 get() = Paths.get(prefix.orEmpty(), BASE_TEST_PATH).toString()
90
91 private fun ResourceLoader.loadAsset() = loadAssetFunction(testPath)
92
93 private fun AssetManager.openAsset() = openAssetFunction()
94
95 private lateinit var testDir: File
96
97 @Before
98 fun setUpTestDir() {
99 testDir = context.filesDir.resolve("DirectoryResourceLoaderTest_${testName.methodName}")
100 testDir.resolve(testPath).apply { parentFile!!.mkdirs() }.writeText(TEST_TEXT)
101 }
102
103 @Test
104 fun multipleLoadersSearchesBackwards() {
105 // DirectoryResourceLoader relies on a private field and can't be spied directly, so wrap it
106 val loader = DirectoryResourceLoader(testDir)
107 val loaderWrapper = mock(ResourceLoader::class.java).apply {
108 doAnswer { loader.loadAsset(it.arguments[0] as String, it.arguments[1] as Int) }
109 .`when`(this).loadAsset(anyString(), anyInt())
110 doAnswer { loader.loadAssetFd(it.arguments[0] as String) }
111 .`when`(this).loadAssetFd(anyString())
112 }
113
114 val one = loaderWrapper to ResourcesProvider.empty()
115 val two = mockLoader {
116 doReturn(null).`when`(it).loadAsset()
117 }
118
119 addLoader(one, two)
120
121 assertOpenedAsset()
122 inOrder(two.first, one.first).apply {
123 verify(two.first).loadAsset()
124 verify(one.first).loadAsset()
125 }
126 }
127
128 @Test(expected = FileNotFoundException::class)
129 fun failToFindThrowsFileNotFound() {
130 val one = mockLoader {
131 doReturn(null).`when`(it).loadAsset()
132 }
133 val two = mockLoader {
134 doReturn(null).`when`(it).loadAsset()
135 }
136
137 addLoader(one, two)
138
139 assertOpenedAsset()
140 }
141
142 @Test
143 fun throwingIOExceptionIsSkipped() {
144 val one = DirectoryResourceLoader(testDir) to ResourcesProvider.empty()
145 val two = mockLoader {
146 doAnswer { throw IOException() }.`when`(it).loadAsset()
147 }
148
149 addLoader(one, two)
150
151 assertOpenedAsset()
152 }
153
154 @Test(expected = IllegalStateException::class)
155 fun throwingNonIOExceptionCausesFailure() {
156 val one = DirectoryResourceLoader(testDir) to ResourcesProvider.empty()
157 val two = mockLoader {
158 doAnswer { throw IllegalStateException() }.`when`(it).loadAsset()
159 }
160
161 addLoader(one, two)
162
163 assertOpenedAsset()
164 }
165
166 private fun assertOpenedAsset() {
167 assertThat(resources.assets.openAsset()).isEqualTo(TEST_TEXT)
168 }
169}