Merge AuthFsHostTest into MicrodroidTestCase
In the meantime, in order to reduce the amount of testing time, boot the
VM once in AuthFsTestCase. This is possible through
@BeforeClassWithInfo.
The new DeviceRunner class intends to generalize shell command execution
to ITestDevice. Later when the VM can be represented as an ITestDevice,
we can easily run a command in the same way.
Bug: 191056545
Bug: 182478337
Test: atest MicrodroidHostTestCases # succeeded in 7:50 on CF
Change-Id: I680a9ef00c345a2f4d7773412c7f0ebd767aab15
diff --git a/authfs/tests/Android.bp b/authfs/tests/Android.bp
deleted file mode 100644
index 8061c56..0000000
--- a/authfs/tests/Android.bp
+++ /dev/null
@@ -1,21 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_test_host {
- name: "AuthFsHostTest",
- srcs: ["java/**/*.java"],
- libs: [
- "tradefed",
- "compatibility-tradefed",
- "compatibility-host-util",
- ],
- static_libs: [
- "VirtualizationTestHelper",
- ],
- test_suites: ["general-tests"],
- data: [
- ":authfs_test_files",
- ":MicrodroidTestApp.signed",
- ],
-}
diff --git a/authfs/tests/AndroidTest.xml b/authfs/tests/AndroidTest.xml
deleted file mode 100644
index 8f940f6..0000000
--- a/authfs/tests/AndroidTest.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-
-<configuration description="Config for authfs tests">
- <!-- Need root to start virtualizationservice -->
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <!-- virtualizationservice doesn't have access to shell_data_file. Instead of giving it
- a test-only permission, run it without selinux -->
- <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer"/>
-
- <!-- Basic checks that the device has all the prerequisites. -->
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="throw-if-cmd-fail" value="true" />
- <!-- Make sure kernel has FUSE enabled. -->
- <option name="run-command" value="ls /dev/fuse" />
- <!-- Make sure necessary executables are installed. -->
- <option name="run-command" value="ls /apex/com.android.virt/bin/fd_server" />
- <option name="run-command" value="ls /apex/com.android.virt/bin/authfs" />
- <!-- Prepare test directory. -->
- <option name="run-command" value="mkdir -p /data/local/tmp/authfs/mnt" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/authfs" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="abort-on-push-failure" value="true" />
- <option name="push-file" key="cert.der" value="/data/local/tmp/authfs/cert.der" />
- <option name="push-file" key="input.4m" value="/data/local/tmp/authfs/input.4m" />
- <option name="push-file" key="input.4k1" value="/data/local/tmp/authfs/input.4k1" />
- <option name="push-file" key="input.4k" value="/data/local/tmp/authfs/input.4k" />
- <option name="push-file" key="input.4m.fsv_sig"
- value="/data/local/tmp/authfs/input.4m.fsv_sig" />
- <option name="push-file" key="input.4k1.fsv_sig"
- value="/data/local/tmp/authfs/input.4k1.fsv_sig" />
- <option name="push-file" key="input.4k.fsv_sig"
- value="/data/local/tmp/authfs/input.4k.fsv_sig" />
- <option name="push-file" key="input.4m.merkle_dump"
- value="/data/local/tmp/authfs/input.4m.merkle_dump" />
- <option name="push-file" key="input.4m.merkle_dump.bad"
- value="/data/local/tmp/authfs/input.4m.merkle_dump.bad" />
- <option name="push-file" key="input.4k1.merkle_dump"
- value="/data/local/tmp/authfs/input.4k1.merkle_dump" />
- <option name="push-file" key="input.4k.merkle_dump"
- value="/data/local/tmp/authfs/input.4k.merkle_dump" />
- </target_preparer>
-
- <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="jar" value="AuthFsHostTest.jar" />
- </test>
-</configuration>
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 968c991..4d70c70 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -8,9 +8,14 @@
test_suites: ["device-tests"],
libs: [
"tradefed",
+ "compatibility-tradefed",
+ "compatibility-host-util",
],
static_libs: [
"VirtualizationTestHelper",
],
- data: [":MicrodroidTestApp.signed"],
+ data: [
+ ":authfs_test_files",
+ ":MicrodroidTestApp.signed",
+ ],
}
diff --git a/tests/hostside/AndroidTest.xml b/tests/hostside/AndroidTest.xml
index eda733a..889fc4e 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/hostside/AndroidTest.xml
@@ -22,6 +22,38 @@
a test-only permission, run it without selinux -->
<target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer"/>
+ <!-- Prepare test directory for AuthFsTestCase. -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="throw-if-cmd-fail" value="true" />
+ <!-- Prepare test directory. -->
+ <option name="run-command" value="mkdir -p /data/local/tmp/authfs/mnt" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/authfs" />
+ </target_preparer>
+
+ <!-- Prepare files for AuthFsTestCase. -->
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="abort-on-push-failure" value="true" />
+ <option name="push-file" key="cert.der" value="/data/local/tmp/authfs/cert.der" />
+ <option name="push-file" key="input.4m" value="/data/local/tmp/authfs/input.4m" />
+ <option name="push-file" key="input.4k1" value="/data/local/tmp/authfs/input.4k1" />
+ <option name="push-file" key="input.4k" value="/data/local/tmp/authfs/input.4k" />
+ <option name="push-file" key="input.4m.fsv_sig"
+ value="/data/local/tmp/authfs/input.4m.fsv_sig" />
+ <option name="push-file" key="input.4k1.fsv_sig"
+ value="/data/local/tmp/authfs/input.4k1.fsv_sig" />
+ <option name="push-file" key="input.4k.fsv_sig"
+ value="/data/local/tmp/authfs/input.4k.fsv_sig" />
+ <option name="push-file" key="input.4m.merkle_dump"
+ value="/data/local/tmp/authfs/input.4m.merkle_dump" />
+ <option name="push-file" key="input.4m.merkle_dump.bad"
+ value="/data/local/tmp/authfs/input.4m.merkle_dump.bad" />
+ <option name="push-file" key="input.4k1.merkle_dump"
+ value="/data/local/tmp/authfs/input.4k1.merkle_dump" />
+ <option name="push-file" key="input.4k.merkle_dump"
+ value="/data/local/tmp/authfs/input.4k.merkle_dump" />
+ </target_preparer>
+
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="MicrodroidHostTestCases.jar" />
</test>
diff --git a/tests/hostside/helper/java/android/virt/test/CommandRunner.java b/tests/hostside/helper/java/android/virt/test/CommandRunner.java
new file mode 100644
index 0000000..696c89a
--- /dev/null
+++ b/tests/hostside/helper/java/android/virt/test/CommandRunner.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 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.virt.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+/** A helper class to provide easy way to run commands on a test device. */
+public class CommandRunner {
+
+ /** Default timeout. 30 sec because Microdroid is extremely slow on GCE-on-CF. */
+ private static final long DEFAULT_TIMEOUT = 30000;
+
+ private ITestDevice mDevice;
+
+ public CommandRunner(@Nonnull ITestDevice device) {
+ mDevice = device;
+ }
+
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ public String run(String... cmd) throws DeviceNotAvailableException {
+ CommandResult result = runForResult(cmd);
+ if (result.getStatus() != CommandStatus.SUCCESS) {
+ fail(join(cmd) + " has failed: " + result);
+ }
+ return result.getStdout().trim();
+ }
+
+ public String tryRun(String... cmd) throws DeviceNotAvailableException {
+ CommandResult result = runForResult(cmd);
+ if (result.getStatus() == CommandStatus.SUCCESS) {
+ return result.getStdout().trim();
+ } else {
+ CLog.d(join(cmd) + " has failed (but ok): " + result);
+ return null;
+ }
+ }
+
+ public String runWithTimeout(long timeoutMillis, String... cmd)
+ throws DeviceNotAvailableException {
+ CommandResult result =
+ mDevice.executeShellV2Command(
+ join(cmd), timeoutMillis, java.util.concurrent.TimeUnit.MILLISECONDS);
+ if (result.getStatus() != CommandStatus.SUCCESS) {
+ fail(join(cmd) + " has failed: " + result);
+ }
+ return result.getStdout().trim();
+ }
+
+ public CommandResult runForResult(String... cmd) throws DeviceNotAvailableException {
+ return mDevice.executeShellV2Command(join(cmd));
+ }
+
+ public void assumeSuccess(String... cmd) throws DeviceNotAvailableException {
+ assumeThat(runForResult(cmd).getStatus(), is(CommandStatus.SUCCESS));
+ }
+
+ private static String join(String... strs) {
+ return String.join(" ", Arrays.asList(strs));
+ }
+}
diff --git a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
index 451f9ba..7a17619 100644
--- a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
+++ b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
@@ -20,10 +20,11 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeThat;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.CommandResult;
@@ -50,92 +51,63 @@
private static final long MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES = 5;
- public void prepareVirtualizationTestSetup() throws DeviceNotAvailableException {
- // kill stale crosvm processes
- tryRunOnAndroid("killall", "crosvm");
+ public static void prepareVirtualizationTestSetup(ITestDevice androidDevice)
+ throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
- // Prepare the test root
- tryRunOnAndroid("rm", "-rf", TEST_ROOT);
- tryRunOnAndroid("mkdir", "-p", TEST_ROOT);
+ // kill stale crosvm processes
+ android.tryRun("killall", "crosvm");
// disconnect from microdroid
tryRunOnHost("adb", "disconnect", MICRODROID_SERIAL);
}
- public void cleanUpVirtualizationTestSetup() throws DeviceNotAvailableException {
+ public static void cleanUpVirtualizationTestSetup(ITestDevice androidDevice)
+ throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
+
// disconnect from microdroid
tryRunOnHost("adb", "disconnect", MICRODROID_SERIAL);
// kill stale VMs and directories
- tryRunOnAndroid("killall", "crosvm");
- tryRunOnAndroid("rm", "-rf", "/data/misc/virtualizationservice/*");
- tryRunOnAndroid("stop", "virtualizationservice");
+ android.tryRun("killall", "crosvm");
+ android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
+ android.tryRun("stop", "virtualizationservice");
}
- public void testIfDeviceIsCapable() throws DeviceNotAvailableException {
+ public static void testIfDeviceIsCapable(ITestDevice androidDevice)
+ throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
+
// Checks the preconditions to run microdroid. If the condition is not satisfied
// don't run the test (instead of failing)
- skipIfFail("ls /dev/kvm");
- skipIfFail("ls /dev/vhost-vsock");
- skipIfFail("ls /apex/com.android.virt/bin/crosvm");
+ android.assumeSuccess("ls /dev/kvm");
+ android.assumeSuccess("ls /dev/vhost-vsock");
+ android.assumeSuccess("ls /apex/com.android.virt/bin/crosvm");
}
// Run an arbitrary command in the host side and returns the result
- private String runOnHost(String... cmd) {
+ private static String runOnHost(String... cmd) {
return runOnHostWithTimeout(10000, cmd);
}
// Same as runOnHost, but failure is not an error
- private String tryRunOnHost(String... cmd) {
+ private static String tryRunOnHost(String... cmd) {
final long timeout = 10000;
CommandResult result = RunUtil.getDefault().runTimedCmd(timeout, cmd);
return result.getStdout().trim();
}
// Same as runOnHost, but with custom timeout
- private String runOnHostWithTimeout(long timeoutMillis, String... cmd) {
+ private static String runOnHostWithTimeout(long timeoutMillis, String... cmd) {
assertTrue(timeoutMillis >= 0);
CommandResult result = RunUtil.getDefault().runTimedCmd(timeoutMillis, cmd);
assertThat(result.getStatus(), is(CommandStatus.SUCCESS));
return result.getStdout().trim();
}
- // Run a shell command on Android. the default timeout is 2 min by tradefed
- public String runOnAndroid(String... cmd) throws DeviceNotAvailableException {
- CommandResult result = getDevice().executeShellV2Command(join(cmd));
- if (result.getStatus() != CommandStatus.SUCCESS) {
- fail(join(cmd) + " has failed: " + result);
- }
- return result.getStdout().trim();
- }
-
- // Same as runOnAndroid, but returns null on error.
- public String tryRunOnAndroid(String... cmd) throws DeviceNotAvailableException {
- CommandResult result = getDevice().executeShellV2Command(join(cmd));
- if (result.getStatus() == CommandStatus.SUCCESS) {
- return result.getStdout().trim();
- } else {
- CLog.d(join(cmd) + " has failed (but ok): " + result);
- return null;
- }
- }
-
- private String runOnAndroidWithTimeout(long timeoutMillis, String... cmd)
- throws DeviceNotAvailableException {
- CommandResult result =
- getDevice()
- .executeShellV2Command(
- join(cmd),
- timeoutMillis,
- java.util.concurrent.TimeUnit.MILLISECONDS);
- if (result.getStatus() != CommandStatus.SUCCESS) {
- fail(join(cmd) + " has failed: " + result);
- }
- return result.getStdout().trim();
- }
-
// Run a shell command on Microdroid
- public String runOnMicrodroid(String... cmd) {
+ public static String runOnMicrodroid(String... cmd) {
CommandResult result = runOnMicrodroidForResult(cmd);
if (result.getStatus() != CommandStatus.SUCCESS) {
fail(join(cmd) + " has failed: " + result);
@@ -144,7 +116,7 @@
}
// Same as runOnMicrodroid, but returns null on error.
- public String tryRunOnMicrodroid(String... cmd) {
+ public static String tryRunOnMicrodroid(String... cmd) {
CommandResult result = runOnMicrodroidForResult(cmd);
if (result.getStatus() == CommandStatus.SUCCESS) {
return result.getStdout().trim();
@@ -154,51 +126,62 @@
}
}
- public CommandResult runOnMicrodroidForResult(String... cmd) {
+ public static CommandResult runOnMicrodroidForResult(String... cmd) {
final long timeout = 30000; // 30 sec. Microdroid is extremely slow on GCE-on-CF.
return RunUtil.getDefault()
.runTimedCmd(timeout, "adb", "-s", MICRODROID_SERIAL, "shell", join(cmd));
}
- private String join(String... strs) {
+ private static String join(String... strs) {
return String.join(" ", Arrays.asList(strs));
}
public File findTestFile(String name) {
+ return findTestFile(getBuild(), name);
+ }
+
+ private static File findTestFile(IBuildInfo buildInfo, String name) {
try {
- return (new CompatibilityBuildHelper(getBuild())).getTestFile(name);
+ return (new CompatibilityBuildHelper(buildInfo)).getTestFile(name);
} catch (FileNotFoundException e) {
fail("Missing test file: " + name);
return null;
}
}
- public String startMicrodroid(
- String apkName, String packageName, String configPath, boolean debug)
+ public static String startMicrodroid(
+ ITestDevice androidDevice,
+ IBuildInfo buildInfo,
+ String apkName,
+ String packageName,
+ String configPath,
+ boolean debug)
throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
+
// Install APK
- File apkFile = findTestFile(apkName);
- getDevice().installPackage(apkFile, /* reinstall */ true);
+ File apkFile = findTestFile(buildInfo, apkName);
+ androidDevice.installPackage(apkFile, /* reinstall */ true);
// Get the path to the installed apk. Note that
// getDevice().getAppPackageInfo(...).getCodePath() doesn't work due to the incorrect
// parsing of the "=" character. (b/190975227). So we use the `pm path` command directly.
- String apkPath = runOnAndroid("pm", "path", packageName);
+ String apkPath = android.run("pm", "path", packageName);
assertTrue(apkPath.startsWith("package:"));
apkPath = apkPath.substring("package:".length());
// Push the idsig file to the device
- File idsigOnHost = findTestFile(apkName + ".idsig");
+ File idsigOnHost = findTestFile(buildInfo, apkName + ".idsig");
final String apkIdsigPath = TEST_ROOT + apkName + ".idsig";
- getDevice().pushFile(idsigOnHost, apkIdsigPath);
+ androidDevice.pushFile(idsigOnHost, apkIdsigPath);
final String logPath = TEST_ROOT + "log.txt";
final String debugFlag = debug ? "--debug " : "";
// Run the VM
- runOnAndroid("start", "virtualizationservice");
+ android.run("start", "virtualizationservice");
String ret =
- runOnAndroid(
+ android.run(
VIRT_APEX + "bin/vm",
"run-app",
"--daemonize",
@@ -214,7 +197,7 @@
() -> {
try {
// Keep redirecting sufficiently long enough
- runOnAndroidWithTimeout(
+ android.runWithTimeout(
MICRODROID_BOOT_TIMEOUT_MINUTES * 60 * 1000,
"logwrapper",
"tail",
@@ -233,17 +216,20 @@
return matcher.group(1);
}
- public void shutdownMicrodroid(String cid) throws DeviceNotAvailableException {
+ public static void shutdownMicrodroid(ITestDevice androidDevice, String cid)
+ throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
+
// Close the connection before shutting the VM down. Otherwise, b/192660485.
tryRunOnHost("adb", "disconnect", MICRODROID_SERIAL);
- final String serial = getDevice().getSerialNumber();
+ final String serial = androidDevice.getSerialNumber();
tryRunOnHost("adb", "-s", serial, "forward", "--remove", "tcp:" + TEST_VM_ADB_PORT);
// Shutdown the VM
- runOnAndroid(VIRT_APEX + "bin/vm", "stop", cid);
+ android.run(VIRT_APEX + "bin/vm", "stop", cid);
}
- public void rootMicrodroid() throws DeviceNotAvailableException {
+ public static void rootMicrodroid() throws DeviceNotAvailableException {
runOnHost("adb", "-s", MICRODROID_SERIAL, "root");
// TODO(192660959): Figure out the root cause and remove the sleep. For unknown reason,
@@ -251,6 +237,12 @@
// `adb -s $MICRODROID_SERIAL shell ...` often fails with "adb: device offline".
try {
Thread.sleep(1000);
+ runOnHostWithTimeout(
+ MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES * 60 * 1000,
+ "adb",
+ "-s",
+ MICRODROID_SERIAL,
+ "wait-for-device");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
@@ -258,12 +250,13 @@
// Establish an adb connection to microdroid by letting Android forward the connection to
// microdroid. Wait until the connection is established and microdroid is booted.
- public void adbConnectToMicrodroid(String cid) throws DeviceNotAvailableException {
+ public static void adbConnectToMicrodroid(ITestDevice androidDevice, String cid)
+ throws DeviceNotAvailableException {
long start = System.currentTimeMillis();
long timeoutMillis = MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES * 60 * 1000;
long elapsed = 0;
- final String serial = getDevice().getSerialNumber();
+ final String serial = androidDevice.getSerialNumber();
final String from = "tcp:" + TEST_VM_ADB_PORT;
final String to = "vsock:" + cid + ":5555";
runOnHost("adb", "-s", serial, "forward", from, to);
@@ -297,9 +290,4 @@
// Check if it actually booted by reading a sysprop.
assertThat(runOnMicrodroid("getprop", "ro.hardware"), is("microdroid"));
}
-
- private void skipIfFail(String command) throws DeviceNotAvailableException {
- CommandResult result = getDevice().executeShellV2Command(command);
- assumeThat(result.getStatus(), is(CommandStatus.SUCCESS));
- }
}
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/tests/hostside/java/android/virt/test/AuthFsTestCase.java
similarity index 79%
rename from authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
rename to tests/hostside/java/android/virt/test/AuthFsTestCase.java
index 426b333..ae29a09 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/tests/hostside/java/android/virt/test/AuthFsTestCase.java
@@ -14,22 +14,28 @@
* limitations under the License.
*/
-package com.android.virt.fs;
+package android.virt.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.RootPermissionTest;
-import android.virt.test.VirtualizationTestCaseBase;
import com.android.compatibility.common.util.PollingCheck;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
+import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
import com.android.tradefed.util.CommandResult;
import org.junit.After;
+import org.junit.AssumptionViolatedException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,10 +43,9 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-// TODO move to Virtualization/tests/hostside/
@RootPermissionTest
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class AuthFsHostTest extends VirtualizationTestCaseBase {
+public final class AuthFsTestCase extends VirtualizationTestCaseBase {
/** Test directory on Android where data are located */
private static final String TEST_DIR = "/data/local/tmp/authfs";
@@ -55,50 +60,87 @@
private static final String AUTHFS_BIN = "/system/bin/authfs";
/** Plenty of time for authfs to get ready */
- private static final int AUTHFS_INIT_TIMEOUT_MS = 1500;
+ private static final int AUTHFS_INIT_TIMEOUT_MS = 3000;
/** FUSE's magic from statfs(2) */
private static final String FUSE_SUPER_MAGIC_HEX = "65735546";
- private ExecutorService mThreadPool;
- private String mCid;
+ private static CommandRunner sAndroid;
+ private static String sCid;
+ private static boolean sAssumptionFailed;
- @Before
- public void setUp() throws DeviceNotAvailableException {
- testIfDeviceIsCapable();
+ private ExecutorService mThreadPool = Executors.newCachedThreadPool();
- cleanUpTestFiles();
+ @BeforeClassWithInfo
+ public static void beforeClassWithDevice(TestInformation testInfo)
+ throws DeviceNotAvailableException {
+ assertNotNull(testInfo.getDevice());
+ ITestDevice androidDevice = testInfo.getDevice();
+ sAndroid = new CommandRunner(androidDevice);
- prepareVirtualizationTestSetup();
+ try {
+ testIfDeviceIsCapable(androidDevice);
+ } catch (AssumptionViolatedException e) {
+ // NB: The assumption exception is NOT handled by the test infra when it is thrown from
+ // a class method (see b/37502066). This has not only caused the loss of log, but also
+ // prevented the test cases to be reported at all and thus confused the test infra.
+ //
+ // Since we want to avoid the big overhead to start the VM repeatedly on CF, let's catch
+ // AssumptionViolatedException and emulate it artifitially.
+ CLog.e("Assumption failed: " + e);
+ sAssumptionFailed = true;
+ return;
+ }
- mThreadPool = Executors.newCachedThreadPool();
+ prepareVirtualizationTestSetup(androidDevice);
// For each test case, boot and adb connect to a new Microdroid
+ CLog.i("Starting the shared VM");
final String apkName = "MicrodroidTestApp.apk";
final String packageName = "com.android.microdroid.test";
final String configPath = "assets/vm_config.json"; // path inside the APK
- mCid = startMicrodroid(apkName, packageName, configPath, /* debug */ false);
- adbConnectToMicrodroid(mCid);
+ sCid =
+ startMicrodroid(
+ androidDevice,
+ testInfo.getBuildInfo(),
+ apkName,
+ packageName,
+ configPath,
+ /* debug */ false);
+ adbConnectToMicrodroid(androidDevice, sCid);
// Root because authfs (started from shell in this test) currently require root to open
// /dev/fuse and mount the FUSE.
rootMicrodroid();
}
- @After
- public void tearDown() throws DeviceNotAvailableException {
- if (mCid != null) {
- shutdownMicrodroid(mCid);
- mCid = null;
+ @AfterClassWithInfo
+ public static void afterClassWithDevice(TestInformation testInfo)
+ throws DeviceNotAvailableException {
+ assertNotNull(sAndroid);
+
+ if (sCid != null) {
+ CLog.i("Shutting down shared VM");
+ shutdownMicrodroid(sAndroid.getDevice(), sCid);
+ sCid = null;
}
- tryRunOnAndroid("killall fd_server");
- cleanUpTestFiles();
- cleanUpVirtualizationTestSetup();
+ cleanUpVirtualizationTestSetup(sAndroid.getDevice());
+ sAndroid = null;
}
- private void cleanUpTestFiles() throws DeviceNotAvailableException {
- tryRunOnAndroid("rm -f " + TEST_DIR + "/output");
+ @Before
+ public void setUp() {
+ assumeFalse(sAssumptionFailed);
+ }
+
+ @After
+ public void tearDown() throws DeviceNotAvailableException {
+ sAndroid.tryRun("killall fd_server");
+ sAndroid.tryRun("rm -f " + TEST_DIR + "/output");
+
+ tryRunOnMicrodroid("killall authfs");
+ tryRunOnMicrodroid("umount " + MOUNT_DIR);
}
@Test
@@ -194,7 +236,7 @@
// Action
// Tampering with the first 2 4K block of the backing file.
- runOnAndroid("dd if=/dev/zero of=" + backendPath + " bs=1 count=8192");
+ sAndroid.run("dd if=/dev/zero of=" + backendPath + " bs=1 count=8192");
// Verify
// Write to a block partially requires a read back to calculate the new hash. It should fail
@@ -274,7 +316,7 @@
}
private String computeFileHashOnAndroid(String path) throws DeviceNotAvailableException {
- String result = runOnAndroid("sha256sum " + path);
+ String result = sAndroid.run("sha256sum " + path);
String[] tokens = result.split("\\s");
if (tokens.length > 0) {
return tokens[0];
@@ -320,7 +362,7 @@
() -> {
try {
CLog.i("Starting fd_server");
- CommandResult result = getDevice().executeShellV2Command(cmd);
+ CommandResult result = sAndroid.runForResult(cmd);
CLog.w("fd_server has stopped: " + result);
} catch (DeviceNotAvailableException e) {
CLog.e("Error running fd_server", e);
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 02fb7e5..d48028e 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -35,8 +35,15 @@
@Test
public void testMicrodroidBoots() throws Exception {
final String configPath = "assets/vm_config.json"; // path inside the APK
- final String cid = startMicrodroid(APK_NAME, PACKAGE_NAME, configPath, /* debug */ false);
- adbConnectToMicrodroid(cid);
+ final String cid =
+ startMicrodroid(
+ getDevice(),
+ getBuild(),
+ APK_NAME,
+ PACKAGE_NAME,
+ configPath,
+ /* debug */ false);
+ adbConnectToMicrodroid(getDevice(), cid);
// Test writing to /data partition
runOnMicrodroid("echo MicrodroidTest > /data/local/tmp/test.txt");
@@ -73,26 +80,27 @@
// Check that keystore was found by the payload
assertThat(runOnMicrodroid("getprop", "debug.microdroid.test.keystore"), is("PASS"));
- shutdownMicrodroid(cid);
+ shutdownMicrodroid(getDevice(), cid);
}
@Test
public void testDebugMode() throws Exception {
final String configPath = "assets/vm_config.json"; // path inside the APK
final boolean debug = true;
- final String cid = startMicrodroid(APK_NAME, PACKAGE_NAME, configPath, debug);
- adbConnectToMicrodroid(cid);
+ final String cid =
+ startMicrodroid(getDevice(), getBuild(), APK_NAME, PACKAGE_NAME, configPath, debug);
+ adbConnectToMicrodroid(getDevice(), cid);
assertThat(runOnMicrodroid("getenforce"), is("Permissive"));
- shutdownMicrodroid(cid);
+ shutdownMicrodroid(getDevice(), cid);
}
@Before
public void setUp() throws Exception {
- testIfDeviceIsCapable();
+ testIfDeviceIsCapable(getDevice());
- prepareVirtualizationTestSetup();
+ prepareVirtualizationTestSetup(getDevice());
getDevice().installPackage(findTestFile(APK_NAME), /* reinstall */ false);
@@ -102,7 +110,7 @@
@After
public void shutdown() throws Exception {
- cleanUpVirtualizationTestSetup();
+ cleanUpVirtualizationTestSetup(getDevice());
getDevice().uninstallPackage(PACKAGE_NAME);
}