Merge "Make VTS run on Windows."
diff --git a/harnesses/tradefed/src/com/android/tradefed/targetprep/VtsPythonVirtualenvPreparer.java b/harnesses/tradefed/src/com/android/tradefed/targetprep/VtsPythonVirtualenvPreparer.java
index 47099a8..253e887 100644
--- a/harnesses/tradefed/src/com/android/tradefed/targetprep/VtsPythonVirtualenvPreparer.java
+++ b/harnesses/tradefed/src/com/android/tradefed/targetprep/VtsPythonVirtualenvPreparer.java
@@ -47,6 +47,8 @@
private static final String PIP = "pip";
private static final String PATH = "PATH";
+ private static final String OS_NAME = "os.name";
+ private static final String WINDOWS = "Windows";
protected static final String PYTHONPATH = "PYTHONPATH";
private static final int BASE_TIMEOUT = 1000 * 60;
private static final String[] DEFAULT_DEP_MODULES = {
@@ -163,11 +165,18 @@
mRequirementsFile = f;
}
+ /**
+ * This method returns whether the OS is Windows.
+ */
+ private static boolean isOnWindows() {
+ return System.getProperty(OS_NAME).contains(WINDOWS);
+ }
+
private void activate() {
- File binDir = new File(mVenvDir, "bin");
+ File binDir = new File(mVenvDir, isOnWindows() ? "Scripts" : "bin");
mRunUtil.setWorkingDir(binDir);
String path = System.getenv(PATH);
- mRunUtil.setEnvVariable(PATH, binDir + ":" + path);
+ mRunUtil.setEnvVariable(PATH, binDir + File.pathSeparator + path);
File pipFile = new File(binDir, PIP);
pipFile.setExecutable(true);
mPip = pipFile.getAbsolutePath();
diff --git a/harnesses/tradefed/src/com/android/tradefed/testtype/VtsMultiDeviceTest.java b/harnesses/tradefed/src/com/android/tradefed/testtype/VtsMultiDeviceTest.java
index ae0f779..36452a0 100644
--- a/harnesses/tradefed/src/com/android/tradefed/testtype/VtsMultiDeviceTest.java
+++ b/harnesses/tradefed/src/com/android/tradefed/testtype/VtsMultiDeviceTest.java
@@ -68,6 +68,8 @@
static final String DATA_FILE_PATH = "data_file_path";
static final String LOG_PATH = "log_path";
static final String NAME = "name";
+ static final String OS_NAME = "os.name";
+ static final String WINDOWS = "Windows";
static final String PYTHONPATH = "PYTHONPATH";
static final String SERIAL = "serial";
static final String TEST_SUITE = "test_suite";
@@ -578,7 +580,7 @@
mPythonBin = getPythonBinary();
}
String[] baseOpts = {mPythonBin, "-m"};
- String[] testModule = {mTestCasePath, jsonFilePath};
+ String[] testModule = {mTestCasePath.replace("/", "."), jsonFilePath};
String[] cmd;
cmd = ArrayUtil.buildArray(baseOpts, testModule);
@@ -698,12 +700,23 @@
}
/**
- * This method sets the python path. It's based on the based on the
+ * This method returns whether the OS is Windows.
+ */
+ private static boolean isOnWindows() {
+ return System.getProperty(OS_NAME).contains(WINDOWS);
+ }
+
+ /**
+ * This method sets the python path. It's based on the
* assumption that the environment variable $ANDROID_BUILD_TOP is set.
*/
private void setPythonPath() {
StringBuilder sb = new StringBuilder();
- sb.append(System.getenv(PYTHONPATH));
+ String separator = File.pathSeparator;
+ if (System.getenv(PYTHONPATH) != null) {
+ sb.append(separator);
+ sb.append(System.getenv(PYTHONPATH));
+ }
// to get the path for android-vts/testcases/ which keeps the VTS python code under vts.
if (mBuildInfo != null) {
@@ -716,37 +729,44 @@
/* pass */
}
if (testDir != null) {
- sb.append(":");
+ sb.append(separator);
mTestCaseDataDir = testDir.getAbsolutePath();
sb.append(mTestCaseDataDir);
} else if (mBuildInfo.getFile(VTS) != null) {
- sb.append(":");
+ sb.append(separator);
sb.append(mBuildInfo.getFile(VTS).getAbsolutePath()).append("/..");
}
}
// for when one uses PythonVirtualenvPreparer.
if (mBuildInfo.getFile(PYTHONPATH) != null) {
- sb.append(":");
+ sb.append(separator);
sb.append(mBuildInfo.getFile(PYTHONPATH).getAbsolutePath());
}
if (System.getenv("ANDROID_BUILD_TOP") != null) {
- sb.append(":");
+ sb.append(separator);
sb.append(System.getenv("ANDROID_BUILD_TOP")).append("/test");
}
- mPythonPath = sb.toString();
+ if (sb.length() == 0) {
+ throw new RuntimeException("Could not find python path on host machine");
+ }
+ mPythonPath = sb.substring(1);
CLog.i("mPythonPath: %s", mPythonPath);
}
/**
- * This method gets the python binary
+ * This method gets the python binary.
*/
private String getPythonBinary() {
+ boolean isWindows = isOnWindows();
+ String python = (isWindows ? "python.exe" : "python");
try {
File venvDir = FileUtil.createNamedTempDir(
mBuildInfo.getTestTag() + "-virtualenv-" +
mBuildInfo.getDeviceSerial().replaceAll(":", "_"));
- File pythonBinaryFile = new File(venvDir.getAbsolutePath(), "bin/python");
+ String binDir = (isWindows ? "Script" : "bin");
+ File pythonBinaryFile = new File(venvDir.getAbsolutePath(),
+ binDir + File.separator + python);
if (pythonBinaryFile.exists()) {
return pythonBinaryFile.getAbsolutePath();
}
@@ -754,11 +774,12 @@
/* pass */
}
- IRunUtil runUtil = RunUtil.getDefault();
- CommandResult c = runUtil.runTimedCmd(1000, "which", "python");
+ IRunUtil runUtil = (mRunUtil == null ? RunUtil.getDefault() : mRunUtil);
+ CommandResult c = runUtil.runTimedCmd(1000,
+ (isWindows ? "where" : "which"), python);
String pythonBin = c.getStdout().trim();
if (pythonBin.length() == 0) {
- throw new RuntimeException("Could not find python binary on host "
+ throw new RuntimeException("Could not find " + python + " on host "
+ "machine");
}
return pythonBin;
diff --git a/harnesses/tradefed/tests/src/com/android/tradefed/testtype/VtsMultiDeviceTestTest.java b/harnesses/tradefed/tests/src/com/android/tradefed/testtype/VtsMultiDeviceTestTest.java
index 10b45e6..9e9616a 100644
--- a/harnesses/tradefed/tests/src/com/android/tradefed/testtype/VtsMultiDeviceTestTest.java
+++ b/harnesses/tradefed/tests/src/com/android/tradefed/testtype/VtsMultiDeviceTestTest.java
@@ -15,32 +15,40 @@
*/
package com.android.tradefed.testtype;
+import com.android.tradefed.build.FolderBuildInfo;
+import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.IRunUtil;
-
+import com.android.tradefed.util.StreamUtil;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
import junit.framework.TestCase;
import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.json.JSONObject;
/**
* Unit tests for {@link VtsMultiDeviceTest}.
+ * This class requires testcase config files.
+ * The working directory is assumed to be
+ * test/
+ * which contains the same config as the build output
+ * out/host/linux-x86/vts/android-vts/testcases/
*/
public class VtsMultiDeviceTestTest extends TestCase {
private ITestInvocationListener mMockInvocationListener = null;
- private ITestDevice mMockITestDevice = null;
- private IRunUtil mRunUtil = null;
+ private IBuildInfo mBuildInfo = null;
private VtsMultiDeviceTest mTest = null;
private static final String TEST_CASE_PATH =
- "test/vts/testcases/host/sample/SampleLightTest";
+ "vts/testcases/host/sample/SampleLightTest";
private static final String TEST_CONFIG_PATH =
- "test/vts/testcases/host/sample/SampleLightTest.config";
- private static final long TEST_TIMEOUT = 1000 * 60 * 5;
- private String[] mCommand = null;
+ "vts/testcases/host/camera/conventional/3_4/SampleCameraV3Test.config";
/**
* Helper to initialize the various EasyMocks we'll need.
@@ -48,30 +56,98 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mTest = new VtsMultiDeviceTest();
- mRunUtil = EasyMock.createMock(IRunUtil.class);
+ mBuildInfo = new FolderBuildInfo("MOCK_ID", "MOCK_NAME");
+ mBuildInfo.addBuildAttribute("ROOT_DIR", "DIR_NOT_EXIST");
+ mBuildInfo.addBuildAttribute("ROOT_DIR2", "DIR_NOT_EXIST");
+ mBuildInfo.addBuildAttribute("SUITE_NAME", "JUNIT_TEST_SUITE");
+ mBuildInfo.setDeviceSerial("1234567890");
mMockInvocationListener = EasyMock.createMock(ITestInvocationListener.class);
- mMockITestDevice = EasyMock.createMock(ITestDevice.class);
- mTest.setRunUtil(mRunUtil);
- //build the command
- String[] baseOpts = {"/usr/bin/python", "-m"};
- String[] testModule = {TEST_CASE_PATH, TEST_CONFIG_PATH};
- mCommand = ArrayUtil.buildArray(baseOpts, testModule);
+ mTest = new VtsMultiDeviceTest();
+ mTest.setBuild(mBuildInfo);
+ mTest.setTestCasePath(TEST_CASE_PATH);
+ mTest.setTestConfigPath(TEST_CONFIG_PATH);
+ }
+
+ /**
+ * Create a mock IRunUtil which
+ * 1. finds Python binary file and returns a mock path
+ * 2. executes the found Python binary,
+ * creates empty log file and returns expectedStatus
+ */
+ private static IRunUtil createMockRunUtil(
+ String findFileCommand, String pythonBin,
+ CommandStatus expectedStatus) {
+ IRunUtil runUtil = EasyMock.createMock(IRunUtil.class);
+ CommandResult findResult = new CommandResult();
+ findResult.setStatus(CommandStatus.SUCCESS);
+ findResult.setStdout("mock/" + pythonBin);
+ EasyMock.expect(runUtil.runTimedCmd(EasyMock.anyLong(),
+ EasyMock.eq(findFileCommand), EasyMock.eq(pythonBin))).
+ andReturn(findResult);
+
+ IAnswer<CommandResult> answer = new IAnswer<CommandResult>() {
+ @Override
+ public CommandResult answer() throws Throwable {
+ // find log path
+ String logPath = null;
+ try (FileInputStream fi = new FileInputStream(
+ (String) EasyMock.getCurrentArguments()[4])) {
+ JSONObject configJson = new JSONObject(
+ StreamUtil.getStringFromStream(fi));
+ logPath = (String) configJson.get(VtsMultiDeviceTest.LOG_PATH);
+ }
+ // create a test result on log path
+ try (FileWriter fw = new FileWriter(
+ logPath + File.separator + "test_run_summary.json")) {
+ JSONObject outJson = new JSONObject();
+ fw.write(outJson.toString());
+ }
+ CommandResult commandResult = new CommandResult();
+ commandResult.setStatus(expectedStatus);
+ return commandResult;
+ }
+ };
+ EasyMock.expect(runUtil.runTimedCmd(EasyMock.anyLong(),
+ EasyMock.eq("mock/" + pythonBin), EasyMock.eq("-m"),
+ EasyMock.eq(TEST_CASE_PATH.replace("/", ".")),
+ EasyMock.endsWith(".json"))).
+ andAnswer(answer).times(0, 1);
+ EasyMock.replay(runUtil);
+ return runUtil;
+ }
+
+ /**
+ * Create a Mock ITestDevice with necessary getter methods.
+ */
+ private static ITestDevice createMockDevice() {
+ // TestDevice
+ ITestDevice device = EasyMock.createMock(ITestDevice.class);
+ try {
+ EasyMock.expect(device.getSerialNumber()).
+ andReturn("1234567890").atLeastOnce();
+ EasyMock.expect(device.getBuildAlias()).
+ andReturn("BUILD_ALIAS");
+ EasyMock.expect(device.getBuildFlavor()).
+ andReturn("BUILD_FLAVOR");
+ EasyMock.expect(device.getBuildId()).
+ andReturn("BUILD_ID");
+ EasyMock.expect(device.getProductType()).
+ andReturn("PRODUCT_TYPE");
+ EasyMock.expect(device.getProductVariant()).
+ andReturn("PRODUCT_VARIANT");
+ } catch (DeviceNotAvailableException e) {
+ fail();
+ }
+ EasyMock.replay(device);
+ return device;
}
/**
* Test the run method with a normal input.
*/
- public void testRunNormalInput(){
- mTest.setDevice(mMockITestDevice);
- mTest.setTestCasePath(TEST_CASE_PATH);
- mTest.setTestConfigPath(TEST_CONFIG_PATH);
-
- CommandResult commandResult = new CommandResult();
- commandResult.setStatus(CommandStatus.SUCCESS);
- EasyMock.expect(mRunUtil.runTimedCmd(TEST_TIMEOUT, mCommand)).
- andReturn(commandResult);
- EasyMock.replay(mRunUtil);
+ public void testRunNormalInput() {
+ mTest.setDevice(createMockDevice());
+ mTest.setRunUtil(createMockRunUtil("which", "python", CommandStatus.SUCCESS));
try {
mTest.run(mMockInvocationListener);
} catch (IllegalArgumentException e) {
@@ -86,9 +162,25 @@
}
/**
+ * Test the run method with a normal input and Windows environment variable.
+ */
+ public void testRunNormalInputOnWindows()
+ throws IllegalArgumentException, DeviceNotAvailableException {
+ String originalName = System.getProperty(VtsMultiDeviceTest.OS_NAME);
+ System.setProperty(VtsMultiDeviceTest.OS_NAME, VtsMultiDeviceTest.WINDOWS);
+ mTest.setDevice(createMockDevice());
+ mTest.setRunUtil(createMockRunUtil("where", "python.exe", CommandStatus.SUCCESS));
+ try {
+ mTest.run(mMockInvocationListener);
+ } finally {
+ System.setProperty(VtsMultiDeviceTest.OS_NAME, originalName);
+ }
+ }
+
+ /**
* Test the run method when the device is set null.
*/
- public void testRunDevice(){
+ public void testRunDeviceNotAvailable() {
mTest.setDevice(null);
try {
mTest.run(mMockInvocationListener);
@@ -105,21 +197,20 @@
* Test the run method with abnormal input data.
*/
public void testRunNormalInputCommandFailed() {
- mTest.setDevice(mMockITestDevice);
- CommandResult commandResult = new CommandResult();
- commandResult.setStatus(CommandStatus.FAILED);
- EasyMock.expect(mRunUtil.runTimedCmd(TEST_TIMEOUT, mCommand)).
- andReturn(commandResult);
- EasyMock.replay(mRunUtil);
+ mTest.setDevice(createMockDevice());
+ mTest.setRunUtil(createMockRunUtil("which", "python", CommandStatus.FAILED));
try {
mTest.run(mMockInvocationListener);
fail();
- } catch (RuntimeException e) {
- // expected
- } catch (DeviceNotAvailableException e) {
- // not expected
- fail();
- e.printStackTrace();
- }
+ } catch (RuntimeException e) {
+ if (!"Failed to run VTS test".equals(e.getMessage())) {
+ fail();
+ }
+ // expected
+ } catch (DeviceNotAvailableException e) {
+ // not expected
+ fail();
+ e.printStackTrace();
+ }
}
}