blob: 09fd27e02b599add19965eb9c523bf0756cb3b4f [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.Resources
20import android.content.res.loader.ResourceLoader
21import android.content.res.loader.ResourcesProvider
22import android.graphics.Color
23import android.graphics.drawable.ColorDrawable
24import com.google.common.truth.Truth.assertThat
25import org.hamcrest.CoreMatchers.not
26import org.junit.Assume.assumeThat
27import org.junit.Test
28import org.junit.runner.RunWith
29import org.junit.runners.Parameterized
30import org.mockito.ArgumentMatchers.anyInt
31import org.mockito.Mockito.`when`
32import org.mockito.Mockito.any
33import org.mockito.Mockito.argThat
34import org.mockito.Mockito.eq
35import org.mockito.Mockito.never
36import org.mockito.Mockito.verify
37
38@RunWith(Parameterized::class)
39class ResourceLoaderDrawableTest : ResourceLoaderTestBase() {
40
41 companion object {
42
43 @JvmStatic
44 @Parameterized.Parameters(name = "{0}")
45 fun data() = arrayOf(DataType.APK, DataType.ARSC)
46 }
47
48 @field:Parameterized.Parameter(0)
49 override lateinit var dataType: DataType
50
51 @Test
52 fun matchingConfig() {
53 val original = getDrawable(android.R.drawable.ic_delete)
54 val loader = "drawableMdpiWithoutFile".openLoader()
55 `when`(loader.first.loadDrawable(any(), anyInt(), anyInt(), any()))
56 .thenReturn(ColorDrawable(Color.BLUE))
57
58 addLoader(loader)
59
60 updateConfiguration { densityDpi = 160 /* mdpi */ }
61
62 val drawable = getDrawable(android.R.drawable.ic_delete)
63
64 loader.verifyLoadDrawableCalled()
65
66 assertThat(drawable).isNotEqualTo(original)
67 assertThat(drawable).isInstanceOf(ColorDrawable::class.java)
68 assertThat((drawable as ColorDrawable).color).isEqualTo(Color.BLUE)
69 }
70
71 @Test
72 fun worseConfig() {
73 val loader = "drawableMdpiWithoutFile".openLoader()
74 addLoader(loader)
75
76 updateConfiguration { densityDpi = 480 /* xhdpi */ }
77
78 getDrawable(android.R.drawable.ic_delete)
79
80 verify(loader.first, never()).loadDrawable(any(), anyInt(), anyInt(), any())
81 }
82
83 @Test
84 fun multipleLoaders() {
85 val original = getDrawable(android.R.drawable.ic_delete)
86 val loaderOne = "drawableMdpiWithoutFile".openLoader()
87 val loaderTwo = "drawableMdpiWithoutFile".openLoader()
88
89 `when`(loaderTwo.first.loadDrawable(any(), anyInt(), anyInt(), any()))
90 .thenReturn(ColorDrawable(Color.BLUE))
91
92 addLoader(loaderOne, loaderTwo)
93
94 updateConfiguration { densityDpi = 160 /* mdpi */ }
95
96 val drawable = getDrawable(android.R.drawable.ic_delete)
97 loaderOne.verifyLoadDrawableNotCalled()
98 loaderTwo.verifyLoadDrawableCalled()
99
100 assertThat(drawable).isNotEqualTo(original)
101 assertThat(drawable).isInstanceOf(ColorDrawable::class.java)
102 assertThat((drawable as ColorDrawable).color).isEqualTo(Color.BLUE)
103 }
104
105 @Test(expected = Resources.NotFoundException::class)
106 fun multipleLoadersNoReturnWithoutFile() {
107 val loaderOne = "drawableMdpiWithoutFile".openLoader()
108 val loaderTwo = "drawableMdpiWithoutFile".openLoader()
109
110 addLoader(loaderOne, loaderTwo)
111
112 updateConfiguration { densityDpi = 160 /* mdpi */ }
113
114 try {
115 getDrawable(android.R.drawable.ic_delete)
116 } finally {
117 // We expect the call to fail because at least the loader won't resolve the overridden
118 // drawable, but we should still verify that both loaders were called before allowing
119 // the exception to propagate.
120 loaderOne.verifyLoadDrawableNotCalled()
121 loaderTwo.verifyLoadDrawableCalled()
122 }
123 }
124
125 @Test
126 fun multipleLoadersReturnWithFile() {
127 // Can't return a file if an ARSC
128 assumeThat(dataType, not(DataType.ARSC))
129
130 val original = getDrawable(android.R.drawable.ic_delete)
131 val loaderOne = "drawableMdpiWithFile".openLoader()
132 val loaderTwo = "drawableMdpiWithFile".openLoader()
133
134 addLoader(loaderOne, loaderTwo)
135
136 updateConfiguration { densityDpi = 160 /* mdpi */ }
137
138 val drawable = getDrawable(android.R.drawable.ic_delete)
139 loaderOne.verifyLoadDrawableNotCalled()
140 loaderTwo.verifyLoadDrawableCalled()
141
142 assertThat(drawable).isNotNull()
143 assertThat(drawable).isInstanceOf(original.javaClass)
144 }
145
146 @Test
147 fun unhandledResourceIgnoresLoaders() {
148 val loader = "drawableMdpiWithoutFile".openLoader()
149 `when`(loader.first.loadDrawable(any(), anyInt(), anyInt(), any()))
150 .thenReturn(ColorDrawable(Color.BLUE))
151 addLoader(loader)
152
153 getDrawable(android.R.drawable.ic_menu_add)
154
155 loader.verifyLoadDrawableNotCalled()
156
157 getDrawable(android.R.drawable.ic_delete)
158
159 loader.verifyLoadDrawableCalled()
160 }
161
162 private fun Pair<ResourceLoader, ResourcesProvider>.verifyLoadDrawableCalled() {
163 verify(first).loadDrawable(
164 argThat {
165 it.density == 160 &&
166 it.resourceId == android.R.drawable.ic_delete &&
167 it.string == "res/drawable-mdpi-v4/ic_delete.png"
168 },
169 eq(android.R.drawable.ic_delete),
170 eq(0),
171 any()
172 )
173 }
174
175 private fun Pair<ResourceLoader, ResourcesProvider>.verifyLoadDrawableNotCalled() {
176 verify(first, never()).loadDrawable(
177 any(),
178 anyInt(),
179 anyInt(),
180 any()
181 )
182 }
183}