Fix race condition
After staging an APEX, wait for the compilation job to be scheduled
before forcing it to run. The job is scheduled asynchronously to us,
so we can't assume it's already happened.
Test: atest CompOsSigningHostTest
Bug: 217851780
Change-Id: I7bf93a98007ae53dba3ce7b35ee8332946d50eb1
diff --git a/test/odsign/test-src/com/android/tests/odsign/CompOsSigningHostTest.java b/test/odsign/test-src/com/android/tests/odsign/CompOsSigningHostTest.java
index b250b9c..a04c87b 100644
--- a/test/odsign/test-src/com/android/tests/odsign/CompOsSigningHostTest.java
+++ b/test/odsign/test-src/com/android/tests/odsign/CompOsSigningHostTest.java
@@ -19,8 +19,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@@ -29,23 +27,14 @@
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
-import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import com.android.tradefed.util.CommandResult;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Arrays;
-import java.util.Optional;
-import java.util.Set;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* Test to check if CompOS works properly.
@@ -56,13 +45,15 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public class CompOsSigningHostTest extends ActivationTest {
- private static final String COMPOSD_CMD_BIN = "/apex/com.android.compos/bin/composd_cmd";
private static final String PENDING_ARTIFACTS_DIR =
"/data/misc/apexdata/com.android.art/compos-pending";
/** odrefresh is currently hard-coded to fail if it does not complete in 300 seconds. */
private static final int ODREFRESH_MAX_SECONDS = 300;
+ /** Waiting time for the job to be scheduled after staging an APEX */
+ private static final int JOB_CREATION_MAX_SECONDS = 5;
+
/** Waiting time before starting to check odrefresh progress. */
private static final int SECONDS_BEFORE_PROGRESS_CHECK = 30;
@@ -85,9 +76,10 @@
OdsignTestUtils testUtils = new OdsignTestUtils(testInfo);
testUtils.installTestApex();
- // Once the test APK is installed, a CompilationJob is scheduled to run when certain
- // criteria are met, e.g. the device is charging and idle. Since we don't want to wait in
- // the test, here we start the job by ID immediately.
+ // Once the test APK is installed, a CompilationJob is (asynchronously) scheduled to run
+ // when certain criteria are met, e.g. the device is charging and idle. Since we don't
+ // want to wait in the test, here we start the job by ID as soon as it is scheduled.
+ waitForJobToBeScheduled(device, JOB_CREATION_MAX_SECONDS);
assertCommandSucceeds(device, "cmd jobscheduler run android " + JOB_ID);
// It takes time. Just don't spam.
TimeUnit.SECONDS.sleep(SECONDS_BEFORE_PROGRESS_CHECK);
@@ -147,25 +139,36 @@
return result.getStdout();
}
+ private static void waitForJobToBeScheduled(ITestDevice device, int timeout)
+ throws Exception {
+ for (int i = 0; i < timeout; i++) {
+ CommandResult result = device.executeShellV2Command(
+ "cmd jobscheduler get-job-state android " + JOB_ID);
+ String state = result.getStdout().toString();
+ if (state.startsWith("unknown")) {
+ // The job hasn't been scheduled yet. So try again.
+ TimeUnit.SECONDS.sleep(1);
+ } else if (result.getExitCode() != 0) {
+ fail("Failing due to unexpected job state: " + result);
+ } else {
+ // The job exists, which is all we care about here
+ return;
+ }
+ }
+ fail("Timed out waiting for the job to be scheduled");
+ }
+
private static void waitForJobExit(ITestDevice device, int timeout)
throws Exception {
- boolean started = false;
for (int i = 0; i < timeout; i++) {
CommandResult result = device.executeShellV2Command(
"cmd jobscheduler get-job-state android " + JOB_ID);
String state = result.getStdout().toString();
if (state.contains("ready") || state.contains("active")) {
- started = true;
TimeUnit.SECONDS.sleep(1);
} else if (state.startsWith("unknown")) {
- if (!started) {
- // It's likely that the job hasn't been scheduled. So try again.
- TimeUnit.SECONDS.sleep(1);
- continue;
- } else {
- // Job has completed
- return;
- }
+ // Job has completed
+ return;
} else {
fail("Failing due to unexpected job state: " + result);
}