Test CompOS more directly.
Rather than using "vm --daemonize ..." to test, which is a slightly
unrealistic environment and doesn't exercise much of our client-side
code, use composd where we can.
A side-effect of this is that we no longer need to disable selinux for
the tests.
This is a partial revert of commit
6aff4f827839325647a43d3a884e6e3d97075d54, and thus a partial re-submit
of commit a00d792a8f7f4bca3d4deae34abbbc0dcca02f2b, changing only
ComposTestCase. This doesn't address the remanining changes to
ComposKeyTestCase, fixed, since they are higher risk and less urgent.
More significantly I've restricted the check for exact binary match to
vdex files only. The other artifacts currently differ because the fd
numbers used in the two runs are baked into them and differ.
Additionally I've tried to handle adb disconnection. In the old tests
the VM kept running until after we did our checks when we killed
it. In the new tests it gets killed by the service manager at some
indeterminate time after composd_cmd exits, and when it does the adb
connection drops, causing various weird failures. To try to avoid that
I'm deliberately killing it when we're done with it, trying to guard
against it exiting spontaneously in the meantime by doing the ADB
reconnection incantation slightly obsessively.
Bug: 200924405
Test: atest ComposTestCase (locally, on acloud, in presubmit)
Change-Id: Ia56ce4b7305d14d6b759ede0d612eb3095559576
diff --git a/compos/tests/AndroidTest.xml b/compos/tests/AndroidTest.xml
index 61b6d47..940531b 100644
--- a/compos/tests/AndroidTest.xml
+++ b/compos/tests/AndroidTest.xml
@@ -18,10 +18,6 @@
<option name="force-root" value="true" />
</target_preparer>
- <!-- 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"/>
-
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="ComposHostTestCases.jar" />
</test>
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index 40f95c3..01d8ff1 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -22,8 +22,6 @@
import android.virt.test.CommandRunner;
import android.virt.test.VirtualizationTestCaseBase;
-import com.android.compatibility.common.util.PollingCheck;
-import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.util.CommandResult;
@@ -37,11 +35,10 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public final class ComposTestCase extends VirtualizationTestCaseBase {
- /** Path to odrefresh on Microdroid */
+ // Binaries used in test. (These paths are valid both in host and Microdroid.)
private static final String ODREFRESH_BIN = "/apex/com.android.art/bin/odrefresh";
-
- /** Path to compos_key_cmd on Microdroid */
private static final String COMPOS_KEY_CMD_BIN = "/apex/com.android.compos/bin/compos_key_cmd";
+ private static final String COMPOSD_CMD_BIN = "/apex/com.android.compos/bin/composd_cmd";
/** Output directory of odrefresh */
private static final String ODREFRESH_OUTPUT_DIR =
@@ -50,38 +47,29 @@
/** Timeout of odrefresh to finish */
private static final int ODREFRESH_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
- /** Wait time for compsvc to be ready on boot */
- private static final int COMPSVC_READY_LATENCY_MS = 10 * 1000; // 10 seconds
-
// ExitCode expanded from art/odrefresh/include/odrefresh/odrefresh.h.
private static final int OKAY = 0;
private static final int COMPILATION_SUCCESS = 80;
- private String mCid;
+ // Files that define the "current" instance of CompOS
+ private static final String COMPOS_CURRENT_ROOT =
+ "/data/misc/apexdata/com.android.compos/current/";
+ private static final String INSTANCE_IMAGE = COMPOS_CURRENT_ROOT + "instance.img";
+ private static final String PUBLIC_KEY = COMPOS_CURRENT_ROOT + "key.pubkey";
+ private static final String PRIVATE_KEY_BLOB = COMPOS_CURRENT_ROOT + "key.blob";
@Before
public void setUp() throws Exception {
testIfDeviceIsCapable(getDevice());
-
- prepareVirtualizationTestSetup(getDevice());
-
- startComposVm();
}
@After
public void tearDown() throws Exception {
- if (mCid != null) {
- shutdownMicrodroid(getDevice(), mCid);
- mCid = null;
- }
-
- cleanUpVirtualizationTestSetup(getDevice());
+ killVmAndReconnectAdb();
}
@Test
public void testOdrefresh() throws Exception {
- waitForServiceRunning();
-
CommandRunner android = new CommandRunner(getDevice());
// Prepare the groundtruth. The compilation on Android should finish successfully.
@@ -103,28 +91,18 @@
android.runForResultWithTimeout(ODREFRESH_TIMEOUT_MS, ODREFRESH_BIN, "--check");
assertThat(result.getExitCode()).isEqualTo(OKAY);
- // Initialize the service with the generated key. Should succeed.
- android.run(
- COMPOS_KEY_CMD_BIN,
- "--cid " + mCid,
- "generate",
- TEST_ROOT + "test_key.blob",
- TEST_ROOT + "test_key.pubkey");
- android.run(COMPOS_KEY_CMD_BIN, "--cid " + mCid, "init-key", TEST_ROOT + "test_key.blob");
+ // Make sure we generate a fresh instance
+ android.tryRun("rm", "-rf", COMPOS_CURRENT_ROOT);
// Expect the compilation in Compilation OS to finish successfully.
{
long start = System.currentTimeMillis();
- result =
- android.runForResultWithTimeout(
- ODREFRESH_TIMEOUT_MS,
- ODREFRESH_BIN,
- "--use-compilation-os=" + mCid,
- "--force-compile");
+ result = android.runForResultWithTimeout(ODREFRESH_TIMEOUT_MS, COMPOSD_CMD_BIN);
long elapsed = System.currentTimeMillis() - start;
- assertThat(result.getExitCode()).isEqualTo(COMPILATION_SUCCESS);
+ assertThat(result.getExitCode()).isEqualTo(0);
CLog.i("Comp OS compilation took " + elapsed + "ms");
}
+ killVmAndReconnectAdb();
// Save the actual checksum for the output directory.
String actualChecksumSnapshot = checksumDirectoryContent(android, ODREFRESH_OUTPUT_DIR);
@@ -140,35 +118,27 @@
assertThat(actualChecksumSnapshot).isEqualTo(expectedChecksumSnapshot);
}
- private void startComposVm() throws DeviceNotAvailableException {
- final String apkName = "CompOSPayloadApp.apk";
- final String packageName = "com.android.compos.payload";
- mCid =
- startMicrodroid(
- getDevice(),
- getBuild(),
- apkName,
- packageName,
- "assets/vm_test_config.json",
- /* debug */ false,
- /* Use default memory */ 0);
- adbConnectToMicrodroid(getDevice(), mCid);
+ private void killVmAndReconnectAdb() throws Exception {
+ CommandRunner android = new CommandRunner(getDevice());
+
+ // When a VM exits, we tend to see adb disconnecting. So we attempt to reconnect
+ // when we kill it to avoid problems. Of course VirtualizationService may exit anyway
+ // (it's an on-demand service and all its clients have gone), taking the VM with it,
+ // which makes this a bit unpredictable.
+ reconnectHostAdb(getDevice());
+ android.tryRun("killall", "crosvm");
+ reconnectHostAdb(getDevice());
+ android.tryRun("stop", "virtualizationservice");
+ reconnectHostAdb(getDevice());
+
+ // Delete stale data
+ android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
}
- private void waitForServiceRunning() {
- try {
- PollingCheck.waitFor(COMPSVC_READY_LATENCY_MS, this::isServiceRunning);
- } catch (Exception e) {
- throw new RuntimeException("Service unavailable", e);
- }
- }
-
- private boolean isServiceRunning() {
- return tryRunOnMicrodroid("pidof compsvc") != null;
- }
-
- private String checksumDirectoryContent(CommandRunner runner, String path)
- throws DeviceNotAvailableException {
- return runner.run("find " + path + " -type f -exec sha256sum {} \\; | sort");
+ private String checksumDirectoryContent(CommandRunner runner, String path) throws Exception {
+ // Sort by filename (second column) to make comparison easier.
+ // TODO(b/192690283): Figure out how to make this work for files odex/oat/art files.
+ return runner.run(
+ "find " + path + " -type f -exec sha256sum {} \\; | grep vdex | sort -k2");
}
}
diff --git a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
index 24a955b..d62892c 100644
--- a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
+++ b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
@@ -73,18 +73,26 @@
// disconnect from microdroid
tryRunOnHost("adb", "disconnect", MICRODROID_SERIAL);
- // Make sure we're connected to the host adb again (b/194219111)
+ reconnectHostAdb(androidDevice);
+
+ // kill stale VMs and directories
+ android.tryRun("killall", "crosvm");
+ android.tryRun("stop", "virtualizationservice");
+ android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
+ }
+
+ public static void reconnectHostAdb(ITestDevice androidDevice)
+ throws DeviceNotAvailableException {
+ CommandRunner android = new CommandRunner(androidDevice);
+
+ // Make sure we're connected to the host adb; this connection seems to get dropped when a VM
+ // exits.
for (int retry = 0; retry < 3; ++retry) {
if (android.tryRun("true") != null) {
break;
}
androidDevice.waitForDeviceOnline(1000);
}
-
- // kill stale VMs and directories
- android.tryRun("killall", "crosvm");
- android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
- android.tryRun("stop", "virtualizationservice");
}
public static void testIfDeviceIsCapable(ITestDevice androidDevice)