blob: 35db483137296077da03795fb0b0807cacd0e8f9 [file] [log] [blame]
/*
* Copyright (C) 2020 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 com.android.build.gradle.internal.tasks
import com.android.build.api.dsl.Device
import com.android.build.api.instrumentation.manageddevice.DeviceTestRunConfigureAction
import com.android.build.api.instrumentation.manageddevice.DeviceTestRunInput
import com.android.build.api.instrumentation.manageddevice.DeviceTestRunParameters
import com.android.build.api.instrumentation.manageddevice.DeviceTestRunTaskAction
import com.android.build.gradle.internal.component.InstrumentedTestCreationConfig
import com.android.build.gradle.internal.fixtures.FakeGradleWorkExecutor
import com.android.build.gradle.internal.profile.AnalyticsService
import com.android.build.gradle.internal.test.AbstractTestDataImpl
import com.android.build.gradle.internal.utils.setDisallowChanges
import com.android.builder.model.TestOptions
import com.android.testutils.MockitoKt.any
import com.android.testutils.MockitoKt.eq
import com.android.testutils.MockitoKt.mock
import com.android.testutils.MockitoKt.same
import com.google.common.truth.Truth.assertThat
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.ArtifactCollection
import org.gradle.api.provider.Property
import org.gradle.testfixtures.ProjectBuilder
import org.gradle.workers.WorkerExecutor
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.mockito.Answers.RETURNS_DEEP_STUBS
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.Mockito.withSettings
import org.mockito.junit.MockitoJUnit
import javax.inject.Inject
/**
* Unit tests for [ManagedDeviceTestTask].
*/
class ManagedDeviceTestTaskTest {
interface TestDevice : Device
interface TestRunInput : DeviceTestRunInput
interface TestRunConfigAction : DeviceTestRunConfigureAction<TestDevice, TestRunInput>
interface TestRunTaskAction : DeviceTestRunTaskAction<TestRunInput>
@get:Rule val mockitoRule = MockitoJUnit.rule()
@get:Rule val tempFolderRule = TemporaryFolder()
@Mock(answer = RETURNS_DEEP_STUBS) lateinit var creationConfig: InstrumentedTestCreationConfig
@Mock lateinit var device: TestDevice
@Mock lateinit var testData: AbstractTestDataImpl
private lateinit var project: Project
abstract class TaskForTest @Inject constructor(testWorkerExecutor: WorkerExecutor) :
ManagedDeviceTestTask() {
override val workerExecutor = testWorkerExecutor
// Allows for setting the dependencies to the Test Task without expanding
// internal public api.
fun setDependenciesForTest(collection: ArtifactCollection) {
dependencies = collection
}
}
// Needs to be a true abstract class and not a mock, to allow for the ObjectFactory to
// decorate the class for test.
abstract class FakeTestAction @Inject constructor(): DeviceTestRunTaskAction<DeviceTestRunInput> {
override fun runTests(params: DeviceTestRunParameters<DeviceTestRunInput>): Boolean {
return shouldSucceed
}
companion object {
internal var shouldSucceed: Boolean = false
}
}
@Before
fun setupMocks() {
project = ProjectBuilder.builder().withProjectDir(tempFolderRule.root).build()
`when`(device.name).thenReturn("testDeviceName")
`when`(creationConfig.name).thenReturn("variantName")
`when`(testData.hasTests(any(), any(), any())).thenReturn(realPropertyFor(true))
`when`(testData.flavorName).thenReturn(realPropertyFor(""))
`when`(testData.getAsStaticData()).thenReturn(mock())
FakeTestAction.shouldSucceed = false
}
@Test
fun configureTask() {
val creationAction = ManagedDeviceTestTask.CreationAction(
creationConfig,
device,
TestRunConfigAction::class.java,
TestRunTaskAction::class.java,
testData,
tempFolderRule.newFolder(),
tempFolderRule.newFolder(),
tempFolderRule.newFolder(),
tempFolderRule.newFolder(),
null,
)
val mockTask = mock<ManagedDeviceTestTask>(withSettings().defaultAnswer(RETURNS_DEEP_STUBS))
val mockConfigAction = mock<TestRunConfigAction>()
`when`(mockTask.objectFactory.newInstance(eq(TestRunConfigAction::class.java)))
.thenReturn(mockConfigAction)
val mockTestRunInput = mock<TestRunInput>()
`when`(mockConfigAction.configureTaskInput(eq(device))).thenReturn(mockTestRunInput)
creationAction.configure(mockTask)
verify(mockTask.deviceInput).setDisallowChanges(same(mockTestRunInput))
}
@Test
fun runTaskWithPassingTests() {
val task = createTask(testRunTaskActionResult = true)
task.doTaskAction()
}
@Test
fun runTaskWithFailedTests() {
val task = createTask(testRunTaskActionResult = false)
val exception = assertThrows(GradleException::class.java) {
task.doTaskAction()
}
assertThat(exception).hasMessageThat().contains(
"There were failing tests for Device: myDevice.")
}
private inline fun <reified ValueClass> realPropertyFor(
providedValue: ValueClass): Property<ValueClass> {
val property = project.objects.property(ValueClass::class.java)
property.set(providedValue)
return property
}
private fun createTask(testRunTaskActionResult: Boolean): ManagedDeviceTestTask {
FakeTestAction.shouldSucceed = testRunTaskActionResult
return project.tasks.register(
"testTask",
TaskForTest::class.java,
FakeGradleWorkExecutor(project.objects, tempFolderRule.newFolder())
).get().apply {
resultsDir.set(tempFolderRule.newFolder())
getCoverageDirectory().set(tempFolderRule.newFolder())
getAdditionalTestOutputEnabled().set(true)
getAdditionalTestOutputDir().set(tempFolderRule.newFolder())
testAction.set(FakeTestAction::class.java)
analyticsService.set(mock<AnalyticsService>())
testData.set(this@ManagedDeviceTestTaskTest.testData)
setDependenciesForTest(
mock<ArtifactCollection>(withSettings().defaultAnswer(RETURNS_DEEP_STUBS)))
executionEnum.set(TestOptions.Execution.HOST)
deviceInput.set(mock<DeviceTestRunInput>())
deviceDslName.set("myDevice")
projectPath.set("project_path")
getReportsDir().set(tempFolderRule.newFolder())
}
}
}