blob: c5c2ce61538960afebc3385e643e04298d6e3a5d [file] [log] [blame]
/*
* Copyright (C) 2017 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.tradefed.testtype.junit4;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.command.remote.DeviceDescriptor;
import com.android.tradefed.config.ConfigurationDef;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.StubDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.targetprep.suite.SuiteApkInstaller;
import com.android.tradefed.testtype.Abi;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.HostTest;
import com.android.tradefed.util.FileUtil;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.AssumptionViolatedException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/** Unit tests for {@link BaseHostJUnit4Test}. */
@RunWith(JUnit4.class)
public class BaseHostJUnit4TestTest {
/** An implementation of the base class for testing purpose. */
@RunWith(DeviceJUnit4ClassRunner.class)
public static class TestableHostJUnit4Test extends BaseHostJUnit4Test {
@Test
public void testPass() {
Assert.assertNotNull(getDevice());
Assert.assertNotNull(getBuild());
}
@Override
CollectingTestListener createListener() {
CollectingTestListener listener = new CollectingTestListener();
listener.testRunStarted("testRun", 1);
TestDescription tid = new TestDescription("class", "test1");
listener.testStarted(tid);
listener.testEnded(tid, new HashMap<String, Metric>());
listener.testRunEnded(500l, new HashMap<String, Metric>());
return listener;
}
}
/**
* An implementation of the base class that simulate a crashed instrumentation from an host test
* run.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public static class FailureHostJUnit4Test extends BaseHostJUnit4Test {
@Test
public void testOne() {
Assert.assertNotNull(getDevice());
Assert.assertNotNull(getBuild());
}
@Override
CollectingTestListener createListener() {
CollectingTestListener listener = new CollectingTestListener();
listener.testRunStarted("testRun", 1);
listener.testRunFailed("instrumentation crashed");
listener.testRunEnded(50L, new HashMap<String, Metric>());
return listener;
}
}
private static final String CLASSNAME =
"com.android.tradefed.testtype.junit4.BaseHostJUnit4TestTest$TestableHostJUnit4Test";
private ITestInvocationListener mMockListener;
private IBuildInfo mMockBuild;
private ITestDevice mMockDevice;
private IInvocationContext mMockContext;
private HostTest mHostTest;
@Before
public void setUp() throws Exception {
mMockListener = EasyMock.createMock(ITestInvocationListener.class);
mMockBuild = EasyMock.createMock(IBuildInfo.class);
mMockDevice = EasyMock.createMock(ITestDevice.class);
mMockContext = new InvocationContext();
mMockContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
mMockContext.addDeviceBuildInfo(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockBuild);
mHostTest = new HostTest();
mHostTest.setBuild(mMockBuild);
mHostTest.setDevice(mMockDevice);
mHostTest.setInvocationContext(mMockContext);
OptionSetter setter = new OptionSetter(mHostTest);
// Disable pretty logging for testing
setter.setOptionValue("enable-pretty-logs", "false");
}
/** Test that we are able to run the test as a JUnit4. */
@Test
public void testSimpleRun() throws Exception {
OptionSetter setter = new OptionSetter(mHostTest);
setter.setOptionValue("class", CLASSNAME);
mMockListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(1));
TestDescription tid = new TestDescription(CLASSNAME, "testPass");
mMockListener.testStarted(tid);
mMockListener.testEnded(tid, new HashMap<String, Metric>());
mMockListener.testRunEnded(
EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
EasyMock.replay(mMockListener, mMockBuild, mMockDevice);
mHostTest.run(mMockListener);
EasyMock.verify(mMockListener, mMockBuild, mMockDevice);
}
/**
* Test that {@link BaseHostJUnit4Test#runDeviceTests(String, String)} properly trigger an
* instrumentation run.
*/
@Test
public void testRunDeviceTests() throws Exception {
TestableHostJUnit4Test test = new TestableHostJUnit4Test();
test.setDevice(mMockDevice);
test.setBuild(mMockBuild);
test.setInvocationContext(mMockContext);
EasyMock.expect(mMockDevice.getIDevice()).andReturn(new StubDevice("serial"));
EasyMock.expect(
mMockDevice.runInstrumentationTests(
(IRemoteAndroidTestRunner) EasyMock.anyObject(),
(ITestInvocationListener) EasyMock.anyObject()))
.andReturn(true);
EasyMock.replay(mMockBuild, mMockDevice);
try {
test.runDeviceTests("com.package", "testClass");
} catch (AssumptionViolatedException e) {
// Ensure that the Assume logic in the test does not make a false pass for the unit test
fail("Should not have thrown an Assume exception.");
}
EasyMock.verify(mMockBuild, mMockDevice);
}
/** Test that when running an instrumentation, the abi is properly passed. */
@Test
public void testRunDeviceTests_abi() throws Exception {
RemoteAndroidTestRunner runner = Mockito.mock(RemoteAndroidTestRunner.class);
TestableHostJUnit4Test test =
new TestableHostJUnit4Test() {
@Override
RemoteAndroidTestRunner createTestRunner(
String packageName, String runnerName, IDevice device) {
return runner;
}
};
test.setDevice(mMockDevice);
test.setBuild(mMockBuild);
test.setInvocationContext(mMockContext);
test.setAbi(new Abi("arm", "32"));
EasyMock.expect(mMockDevice.getIDevice()).andReturn(new StubDevice("serial"));
EasyMock.expect(
mMockDevice.runInstrumentationTests(
(IRemoteAndroidTestRunner) EasyMock.anyObject(),
(ITestInvocationListener) EasyMock.anyObject()))
.andReturn(true);
EasyMock.replay(mMockBuild, mMockDevice);
try {
test.runDeviceTests("com.package", "testClass");
} catch (AssumptionViolatedException e) {
// Ensure that the Assume logic in the test does not make a false pass for the unit test
fail("Should not have thrown an Assume exception.");
}
EasyMock.verify(mMockBuild, mMockDevice);
// Verify that the runner options were properly set.
Mockito.verify(runner).setRunOptions("--abi arm");
}
/**
* Test that {@link BaseHostJUnit4Test#runDeviceTests(String, String)} properly trigger an
* instrumentation run as a user.
*/
@Test
public void testRunDeviceTests_asUser() throws Exception {
TestableHostJUnit4Test test = new TestableHostJUnit4Test();
test.setDevice(mMockDevice);
test.setBuild(mMockBuild);
test.setInvocationContext(mMockContext);
EasyMock.expect(mMockDevice.getIDevice()).andReturn(new StubDevice("serial"));
EasyMock.expect(
mMockDevice.runInstrumentationTestsAsUser(
(IRemoteAndroidTestRunner) EasyMock.anyObject(),
EasyMock.eq(0),
(ITestInvocationListener) EasyMock.anyObject()))
.andReturn(true);
EasyMock.replay(mMockBuild, mMockDevice);
try {
test.runDeviceTests("package", "class", 0, null);
} catch (AssumptionViolatedException e) {
// Ensure that the Assume logic in the test does not make a false pass for the unit test
fail("Should not have thrown an Assume exception.");
}
EasyMock.verify(mMockBuild, mMockDevice);
}
/**
* Test that {@link BaseHostJUnit4Test#runDeviceTests(DeviceTestRunOptions)} properly trigger an
* instrumentation run.
*/
@Test
public void testRunDeviceTestsWithOptions() throws Exception {
TestableHostJUnit4Test test = new TestableHostJUnit4Test();
test.setDevice(mMockDevice);
test.setBuild(mMockBuild);
test.setInvocationContext(mMockContext);
EasyMock.expect(mMockDevice.getIDevice()).andReturn(new StubDevice("serial"));
EasyMock.expect(
mMockDevice.runInstrumentationTests(
(IRemoteAndroidTestRunner) EasyMock.anyObject(),
(ITestInvocationListener) EasyMock.anyObject()))
.andReturn(true);
EasyMock.replay(mMockBuild, mMockDevice);
try {
test.runDeviceTests(
new DeviceTestRunOptions("com.package").setTestClassName("testClass"));
} catch (AssumptionViolatedException e) {
// Ensure that the Assume logic in the test does not make a false pass for the unit test
fail("Should not have thrown an Assume exception.");
}
EasyMock.verify(mMockBuild, mMockDevice);
}
/**
* Test that if the instrumentation crash directly we report it as a failure and not an
* AssumptionFailure (which would improperly categorize the failure).
*/
@Test
public void testRunDeviceTests_crashedInstrumentation() throws Exception {
FailureHostJUnit4Test test = new FailureHostJUnit4Test();
test.setDevice(mMockDevice);
test.setBuild(mMockBuild);
test.setInvocationContext(mMockContext);
EasyMock.expect(mMockDevice.getIDevice()).andReturn(new StubDevice("serial"));
EasyMock.expect(
mMockDevice.runInstrumentationTests(
(IRemoteAndroidTestRunner) EasyMock.anyObject(),
(ITestInvocationListener) EasyMock.anyObject()))
.andReturn(true);
EasyMock.replay(mMockBuild, mMockDevice);
try {
test.runDeviceTests("com.package", "testClass");
} catch (AssumptionViolatedException e) {
// Ensure that the Assume logic in the test does not make a false pass for the unit test
fail("Should not have thrown an Assume exception.");
} catch (AssertionError expected) {
assertTrue(expected.getMessage().contains("instrumentation crashed"));
}
EasyMock.verify(mMockBuild, mMockDevice);
}
/** An implementation of the base class for testing purpose of installation of apk. */
@RunWith(DeviceJUnit4ClassRunner.class)
public static class InstallApkHostJUnit4Test extends BaseHostJUnit4Test {
@Test
public void testInstall() throws Exception {
installPackage("apkFileName");
}
@Override
SuiteApkInstaller createSuiteApkInstaller() {
return new SuiteApkInstaller() {
@Override
protected String parsePackageName(
File testAppFile, DeviceDescriptor deviceDescriptor)
throws TargetSetupError {
return "fakepackage";
}
};
}
}
/**
* Test that when running a test that use the {@link BaseHostJUnit4Test#installPackage(String,
* String...)} the package is properly auto uninstalled.
*/
@Test
public void testInstallUninstall() throws Exception {
File fakeTestsDir = FileUtil.createTempDir("fake-base-host-dir");
try {
File apk = new File(fakeTestsDir, "apkFileName");
apk.createNewFile();
HostTest test = new HostTest();
test.setBuild(mMockBuild);
test.setDevice(mMockDevice);
test.setInvocationContext(mMockContext);
OptionSetter setter = new OptionSetter(test);
// Disable pretty logging for testing
setter.setOptionValue("enable-pretty-logs", "false");
setter.setOptionValue("class", InstallApkHostJUnit4Test.class.getName());
mMockListener.testRunStarted(InstallApkHostJUnit4Test.class.getName(), 1);
TestDescription description =
new TestDescription(InstallApkHostJUnit4Test.class.getName(), "testInstall");
mMockListener.testStarted(description);
Map<String, String> properties = new HashMap<>();
properties.put("ROOT_DIR", fakeTestsDir.getAbsolutePath());
EasyMock.expect(mMockBuild.getBuildAttributes()).andReturn(properties).times(2);
EasyMock.expect(mMockDevice.getDeviceDescriptor()).andReturn(null);
EasyMock.expect(mMockDevice.installPackage(apk, true)).andReturn(null);
// Ensure that the auto-uninstall is triggered
EasyMock.expect(mMockDevice.uninstallPackage("fakepackage")).andReturn(null);
mMockListener.testEnded(description, new HashMap<String, Metric>());
mMockListener.testRunEnded(
EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
EasyMock.replay(mMockBuild, mMockDevice, mMockListener);
test.run(mMockListener);
EasyMock.verify(mMockBuild, mMockDevice, mMockListener);
} finally {
FileUtil.recursiveDelete(fakeTestsDir);
}
}
}