blob: 893145dff1d18a26a2d7618d450a8b24f72c8ffd [file] [log] [blame]
/*
* Copyright (C) 2015 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;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ITestLifeCycleReceiver;
import com.android.tradefed.util.FileUtil;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Unit tests for {@link AndroidJUnitTest}
*/
public class AndroidJUnitTestTest extends TestCase {
private static final String AJUR = "android.support.test.runner.AndroidJUnitRunner";
private static final int TEST_TIMEOUT = 0;
private static final long SHELL_TIMEOUT = 0;
private static final String TEST_PACKAGE_VALUE = "com.foo";
private static final TestIdentifier TEST1 = new TestIdentifier("Test", "test1");
private static final TestIdentifier TEST2 = new TestIdentifier("Test", "test2");
/** The {@link AndroidJUnitTest} under test, with all dependencies mocked out */
private AndroidJUnitTest mAndroidJUnitTest;
// The mock objects.
private IDevice mMockIDevice;
private ITestDevice mMockTestDevice;
private IRemoteAndroidTestRunner mMockRemoteRunner;
private ITestInvocationListener mMockListener;
@Override
protected void setUp() throws Exception {
super.setUp();
mMockIDevice = EasyMock.createMock(IDevice.class);
mMockTestDevice = EasyMock.createMock(ITestDevice.class);
EasyMock.expect(mMockTestDevice.getIDevice()).andStubReturn(mMockIDevice);
EasyMock.expect(mMockTestDevice.getSerialNumber()).andStubReturn("serial");
mMockRemoteRunner = EasyMock.createMock(IRemoteAndroidTestRunner.class);
mMockListener = EasyMock.createMock(ITestInvocationListener.class);
mAndroidJUnitTest = new AndroidJUnitTest() {
@Override
IRemoteAndroidTestRunner createRemoteAndroidTestRunner(String packageName,
String runnerName, IDevice device) {
return mMockRemoteRunner;
}
};
mAndroidJUnitTest.setRunnerName(AJUR);
mAndroidJUnitTest.setPackageName(TEST_PACKAGE_VALUE);
mAndroidJUnitTest.setDevice(mMockTestDevice);
// default to no rerun, for simplicity
mAndroidJUnitTest.setRerunMode(false);
// default to no timeout for simplicity
mAndroidJUnitTest.setTestTimeout(TEST_TIMEOUT);
mAndroidJUnitTest.setShellTimeout(SHELL_TIMEOUT);
mMockRemoteRunner.setMaxTimeToOutputResponse(SHELL_TIMEOUT, TimeUnit.MILLISECONDS);
mMockRemoteRunner.setMaxTimeout(0L, TimeUnit.MILLISECONDS);
mMockRemoteRunner.addInstrumentationArg(InstrumentationTest.TEST_TIMEOUT_INST_ARGS_KEY,
Long.toString(SHELL_TIMEOUT));
mMockRemoteRunner.addInstrumentationArg(
AndroidJUnitTest.NEW_RUN_LISTENER_ORDER_KEY, "true");
}
/**
* Test list of tests to run is filtered by include filters.
*/
public void testRun_includeFilterClass() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("class", TEST1.toString());
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addIncludeFilter(TEST1.toString());
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by exclude filters.
*/
public void testRun_excludeFilterClass() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("notClass", TEST1.toString());
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addExcludeFilter(TEST1.toString());
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by include and exclude filters.
*/
public void testRun_includeAndExcludeFilterClass() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("class", TEST1.getClassName());
mMockRemoteRunner.addInstrumentationArg("notClass", TEST2.toString());
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addIncludeFilter(TEST1.getClassName());
mAndroidJUnitTest.addExcludeFilter(TEST2.toString());
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by include filters.
*/
public void testRun_includeFilterPackage() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("package", "com.android.test");
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addIncludeFilter("com.android.test");
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by exclude filters.
*/
public void testRun_excludeFilterPackage() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("notPackage", "com.android.not");
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addExcludeFilter("com.android.not");
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by include and exclude filters.
*/
public void testRun_includeAndExcludeFilterPackage() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("package", "com.android.test");
mMockRemoteRunner.addInstrumentationArg("notPackage", "com.android.not");
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addIncludeFilter("com.android.test");
mAndroidJUnitTest.addExcludeFilter("com.android.not");
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by include and exclude filters.
*/
public void testRun_includeAndExcludeFilters() throws Exception {
// expect this call
mMockRemoteRunner.addInstrumentationArg("class", TEST1.getClassName());
mMockRemoteRunner.addInstrumentationArg("notClass", TEST2.toString());
mMockRemoteRunner.addInstrumentationArg("package", "com.android.test");
mMockRemoteRunner.addInstrumentationArg("notPackage", "com.android.not");
setRunTestExpectations();
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
mAndroidJUnitTest.addIncludeFilter(TEST1.getClassName());
mAndroidJUnitTest.addExcludeFilter(TEST2.toString());
mAndroidJUnitTest.addIncludeFilter("com.android.test");
mAndroidJUnitTest.addExcludeFilter("com.android.not");
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
}
/**
* Test list of tests to run is filtered by include file.
*/
public void testRun_includeFile() throws Exception {
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("testFile"), EasyMock.<String>anyObject());
setRunTestExpectations();
EasyMock.expect(mMockTestDevice.pushFile(
EasyMock.<File>anyObject(), EasyMock.<String>anyObject())).andReturn(Boolean.TRUE);
EasyMock.expect(mMockTestDevice.executeShellCommand(EasyMock.<String>anyObject()))
.andReturn("")
.times(2);
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
File tmpFile = FileUtil.createTempFile("testFile", ".txt");
try {
mAndroidJUnitTest.setIncludeTestFile(tmpFile);
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
} finally {
FileUtil.deleteFile(tmpFile);
}
}
/**
* Test list of tests to run is filtered by exclude file.
*/
public void testRun_excludeFile() throws Exception {
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("notTestFile"), EasyMock.<String>anyObject());
setRunTestExpectations();
EasyMock.expect(mMockTestDevice.pushFile(
EasyMock.<File>anyObject(), EasyMock.<String>anyObject())).andReturn(Boolean.TRUE);
EasyMock.expect(mMockTestDevice.executeShellCommand(EasyMock.<String>anyObject()))
.andReturn("")
.times(2);
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
File tmpFile = FileUtil.createTempFile("notTestFile", ".txt");
try {
mAndroidJUnitTest.setExcludeTestFile(tmpFile);
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
} finally {
FileUtil.deleteFile(tmpFile);
}
}
/**
* Test list of tests to run is filtered by include file, does not override existing filters.
*/
public void testRun_testFileAndFilters() throws Exception {
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("testFile"), EasyMock.<String>anyObject());
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("notTestFile"), EasyMock.<String>anyObject());
mMockRemoteRunner.addInstrumentationArg("class", TEST1.getClassName());
mMockRemoteRunner.addInstrumentationArg("notClass", TEST2.toString());
setRunTestExpectations();
EasyMock.expect(mMockTestDevice.pushFile(EasyMock.<File>anyObject(),
EasyMock.<String>anyObject())).andReturn(Boolean.TRUE).times(2);
EasyMock.expect(mMockTestDevice.executeShellCommand(EasyMock.<String>anyObject()))
.andReturn("")
.times(3);
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
File tmpFileInclude = FileUtil.createTempFile("includeFile", ".txt");
File tmpFileExclude = FileUtil.createTempFile("excludeFile", ".txt");
try {
mAndroidJUnitTest.addIncludeFilter(TEST1.getClassName());
mAndroidJUnitTest.addExcludeFilter(TEST2.toString());
mAndroidJUnitTest.setIncludeTestFile(tmpFileInclude);
mAndroidJUnitTest.setExcludeTestFile(tmpFileExclude);
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
} finally {
FileUtil.deleteFile(tmpFileInclude);
FileUtil.deleteFile(tmpFileExclude);
}
}
/**
* Test that when pushing the filters fails, we have a test run failure since we were not able
* to run anything.
*/
public void testRun_testFileAndFilters_fails() throws Exception {
mMockRemoteRunner = EasyMock.createMock(IRemoteAndroidTestRunner.class);
EasyMock.expect(
mMockTestDevice.pushFile(
EasyMock.<File>anyObject(), EasyMock.<String>anyObject()))
.andThrow(new DeviceNotAvailableException("failed to push", "device1"));
mMockListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(0));
mMockListener.testRunFailed("failed to push");
mMockListener.testRunEnded(0, new HashMap<String, Metric>());
EasyMock.replay(mMockRemoteRunner, mMockTestDevice, mMockListener);
File tmpFileInclude = FileUtil.createTempFile("includeFile", ".txt");
File tmpFileExclude = FileUtil.createTempFile("excludeFile", ".txt");
try {
mAndroidJUnitTest.addIncludeFilter(TEST1.getClassName());
mAndroidJUnitTest.addExcludeFilter(TEST2.toString());
mAndroidJUnitTest.setIncludeTestFile(tmpFileInclude);
mAndroidJUnitTest.setExcludeTestFile(tmpFileExclude);
mAndroidJUnitTest.run(mMockListener);
fail("Should have thrown an exception.");
} catch (DeviceNotAvailableException expected) {
//expected
} finally {
FileUtil.deleteFile(tmpFileInclude);
FileUtil.deleteFile(tmpFileExclude);
}
EasyMock.verify(mMockRemoteRunner, mMockTestDevice, mMockListener);
}
/**
* Test that setting option for "test-file-filter" works as intended
*/
public void testRun_setTestFileOptions() throws Exception {
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("testFile"), EasyMock.<String>anyObject());
mMockRemoteRunner.addInstrumentationArg(
EasyMock.eq("notTestFile"), EasyMock.<String>anyObject());
setRunTestExpectations();
EasyMock.expect(
mMockTestDevice.pushFile(
EasyMock.<File>anyObject(), EasyMock.<String>anyObject()))
.andReturn(Boolean.TRUE)
.times(2);
EasyMock.expect(mMockTestDevice.executeShellCommand(EasyMock.<String>anyObject()))
.andReturn("")
.times(3);
EasyMock.replay(mMockRemoteRunner, mMockTestDevice);
File tmpFileInclude = FileUtil.createTempFile("includeFile", ".txt");
File tmpFileExclude = FileUtil.createTempFile("excludeFile", ".txt");
try {
OptionSetter setter = new OptionSetter(mAndroidJUnitTest);
setter.setOptionValue("test-file-include-filter", tmpFileInclude.getAbsolutePath());
setter.setOptionValue("test-file-exclude-filter", tmpFileExclude.getAbsolutePath());
mAndroidJUnitTest.run(mMockListener);
EasyMock.verify(mMockRemoteRunner, mMockTestDevice);
} finally {
FileUtil.deleteFile(tmpFileInclude);
FileUtil.deleteFile(tmpFileExclude);
}
}
private void setRunTestExpectations() throws DeviceNotAvailableException {
EasyMock.expect(
mMockTestDevice.runInstrumentationTests(
EasyMock.eq(mMockRemoteRunner),
(ITestLifeCycleReceiver) EasyMock.anyObject()))
.andReturn(Boolean.TRUE);
}
/**
* Test isClassOrMethod returns true for <package>.<class> and <package>.<class>#<method> but
* not for <package>.
*/
public void testIsClassOrMethod() throws Exception {
assertFalse("String was just package", mAndroidJUnitTest.isClassOrMethod("android.test"));
assertTrue("String was class", mAndroidJUnitTest.isClassOrMethod("android.test.Foo"));
assertTrue("String was method", mAndroidJUnitTest.isClassOrMethod("android.test.Foo#bar"));
}
/**
* Test that {@link AndroidJUnitTest#split()} returns null if the runner is not shardable.
*/
public void testSplit_notShardable() {
mAndroidJUnitTest.setRunnerName("fake.runner.not.shardable");
assertNull(mAndroidJUnitTest.split());
}
/**
* Test that {@link AndroidJUnitTest#split()} returns null if no shards have been requested.
*/
public void testSplit_noShardRequested() {
assertEquals(AJUR, mAndroidJUnitTest.getRunnerName());
assertNull(mAndroidJUnitTest.split());
}
/** Test that {@link AndroidJUnitTest#split(int)} returns 3 shards when requested to do so. */
public void testSplit_threeShards() throws Exception {
mAndroidJUnitTest = new AndroidJUnitTest();
mAndroidJUnitTest.setRunnerName(AJUR);
assertEquals(AJUR, mAndroidJUnitTest.getRunnerName());
OptionSetter setter = new OptionSetter(mAndroidJUnitTest);
setter.setOptionValue("runtime-hint", "60s");
List<IRemoteTest> res = (List<IRemoteTest>) mAndroidJUnitTest.split(3);
assertNotNull(res);
assertEquals(3, res.size());
// Third of the execution time on each shard.
assertEquals(20000L, ((AndroidJUnitTest)res.get(0)).getRuntimeHint());
assertEquals(20000L, ((AndroidJUnitTest)res.get(1)).getRuntimeHint());
assertEquals(20000L, ((AndroidJUnitTest)res.get(2)).getRuntimeHint());
// Make sure shards cannot be re-sharded
assertNull(((AndroidJUnitTest) res.get(0)).split(2));
assertNull(((AndroidJUnitTest) res.get(0)).split());
}
/**
* Test that {@link AndroidJUnitTest#split(int)} can only split up to the ajur-max-shard option.
*/
public void testSplit_maxShard() throws Exception {
mAndroidJUnitTest = new AndroidJUnitTest();
mAndroidJUnitTest.setRunnerName(AJUR);
assertEquals(AJUR, mAndroidJUnitTest.getRunnerName());
OptionSetter setter = new OptionSetter(mAndroidJUnitTest);
setter.setOptionValue("runtime-hint", "60s");
setter.setOptionValue("ajur-max-shard", "2");
List<IRemoteTest> res = (List<IRemoteTest>) mAndroidJUnitTest.split(3);
assertNotNull(res);
assertEquals(2, res.size());
// Third of the execution time on each shard.
assertEquals(30000L, ((AndroidJUnitTest) res.get(0)).getRuntimeHint());
assertEquals(30000L, ((AndroidJUnitTest) res.get(1)).getRuntimeHint());
// Make sure shards cannot be re-sharded
assertNull(((AndroidJUnitTest) res.get(0)).split(2));
assertNull(((AndroidJUnitTest) res.get(0)).split());
}
}