blob: 09fd27e02b599add19965eb9c523bf0756cb3b4f [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.content.res.loader.test
import android.content.res.Resources
import android.content.res.loader.ResourceLoader
import android.content.res.loader.ResourcesProvider
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import com.google.common.truth.Truth.assertThat
import org.hamcrest.CoreMatchers.not
import org.junit.Assume.assumeThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
import org.mockito.Mockito.argThat
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@RunWith(Parameterized::class)
class ResourceLoaderDrawableTest : ResourceLoaderTestBase() {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
fun data() = arrayOf(DataType.APK, DataType.ARSC)
}
@field:Parameterized.Parameter(0)
override lateinit var dataType: DataType
@Test
fun matchingConfig() {
val original = getDrawable(android.R.drawable.ic_delete)
val loader = "drawableMdpiWithoutFile".openLoader()
`when`(loader.first.loadDrawable(any(), anyInt(), anyInt(), any()))
.thenReturn(ColorDrawable(Color.BLUE))
addLoader(loader)
updateConfiguration { densityDpi = 160 /* mdpi */ }
val drawable = getDrawable(android.R.drawable.ic_delete)
loader.verifyLoadDrawableCalled()
assertThat(drawable).isNotEqualTo(original)
assertThat(drawable).isInstanceOf(ColorDrawable::class.java)
assertThat((drawable as ColorDrawable).color).isEqualTo(Color.BLUE)
}
@Test
fun worseConfig() {
val loader = "drawableMdpiWithoutFile".openLoader()
addLoader(loader)
updateConfiguration { densityDpi = 480 /* xhdpi */ }
getDrawable(android.R.drawable.ic_delete)
verify(loader.first, never()).loadDrawable(any(), anyInt(), anyInt(), any())
}
@Test
fun multipleLoaders() {
val original = getDrawable(android.R.drawable.ic_delete)
val loaderOne = "drawableMdpiWithoutFile".openLoader()
val loaderTwo = "drawableMdpiWithoutFile".openLoader()
`when`(loaderTwo.first.loadDrawable(any(), anyInt(), anyInt(), any()))
.thenReturn(ColorDrawable(Color.BLUE))
addLoader(loaderOne, loaderTwo)
updateConfiguration { densityDpi = 160 /* mdpi */ }
val drawable = getDrawable(android.R.drawable.ic_delete)
loaderOne.verifyLoadDrawableNotCalled()
loaderTwo.verifyLoadDrawableCalled()
assertThat(drawable).isNotEqualTo(original)
assertThat(drawable).isInstanceOf(ColorDrawable::class.java)
assertThat((drawable as ColorDrawable).color).isEqualTo(Color.BLUE)
}
@Test(expected = Resources.NotFoundException::class)
fun multipleLoadersNoReturnWithoutFile() {
val loaderOne = "drawableMdpiWithoutFile".openLoader()
val loaderTwo = "drawableMdpiWithoutFile".openLoader()
addLoader(loaderOne, loaderTwo)
updateConfiguration { densityDpi = 160 /* mdpi */ }
try {
getDrawable(android.R.drawable.ic_delete)
} finally {
// We expect the call to fail because at least the loader won't resolve the overridden
// drawable, but we should still verify that both loaders were called before allowing
// the exception to propagate.
loaderOne.verifyLoadDrawableNotCalled()
loaderTwo.verifyLoadDrawableCalled()
}
}
@Test
fun multipleLoadersReturnWithFile() {
// Can't return a file if an ARSC
assumeThat(dataType, not(DataType.ARSC))
val original = getDrawable(android.R.drawable.ic_delete)
val loaderOne = "drawableMdpiWithFile".openLoader()
val loaderTwo = "drawableMdpiWithFile".openLoader()
addLoader(loaderOne, loaderTwo)
updateConfiguration { densityDpi = 160 /* mdpi */ }
val drawable = getDrawable(android.R.drawable.ic_delete)
loaderOne.verifyLoadDrawableNotCalled()
loaderTwo.verifyLoadDrawableCalled()
assertThat(drawable).isNotNull()
assertThat(drawable).isInstanceOf(original.javaClass)
}
@Test
fun unhandledResourceIgnoresLoaders() {
val loader = "drawableMdpiWithoutFile".openLoader()
`when`(loader.first.loadDrawable(any(), anyInt(), anyInt(), any()))
.thenReturn(ColorDrawable(Color.BLUE))
addLoader(loader)
getDrawable(android.R.drawable.ic_menu_add)
loader.verifyLoadDrawableNotCalled()
getDrawable(android.R.drawable.ic_delete)
loader.verifyLoadDrawableCalled()
}
private fun Pair<ResourceLoader, ResourcesProvider>.verifyLoadDrawableCalled() {
verify(first).loadDrawable(
argThat {
it.density == 160 &&
it.resourceId == android.R.drawable.ic_delete &&
it.string == "res/drawable-mdpi-v4/ic_delete.png"
},
eq(android.R.drawable.ic_delete),
eq(0),
any()
)
}
private fun Pair<ResourceLoader, ResourcesProvider>.verifyLoadDrawableNotCalled() {
verify(first, never()).loadDrawable(
any(),
anyInt(),
anyInt(),
any()
)
}
}