diff --git a/src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java b/src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java index ba296bb24..031cf1a03 100644 --- a/src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java +++ b/src/java/com/google/devtools/mobileharness/api/model/error/AndroidErrorId.java @@ -624,6 +624,7 @@ public enum AndroidErrorId implements ErrorId { XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILD_NOT_MATCH_RETRY_PREV_SESSION( 135_521, ErrorType.CUSTOMER_ISSUE), XTS_DEVICE_COMPAT_CHECKER_CHECK_DEVICE_BUILD_ERROR(135_522, ErrorType.INFRA_ISSUE), + XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILDS_NOT_THE_SAME(135_523, ErrorType.CUSTOMER_ISSUE), /** Android Apps: 140_001 ~ 145_000 */ // Device Daemon app: 140_001 ~ 140_020 diff --git a/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/BUILD b/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/BUILD index 3d29c249c..720f5d345 100644 --- a/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/BUILD @@ -178,6 +178,7 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/ats/common:session_request_handler_util", "//src/java/com/google/devtools/mobileharness/infra/ats/common:session_request_info", "//src/java/com/google/devtools/mobileharness/infra/ats/common:session_result_handler_util", + "//src/java/com/google/devtools/mobileharness/infra/ats/common:xts_property_name", "//src/java/com/google/devtools/mobileharness/infra/ats/common/jobcreator:xts_job_creator", "//src/java/com/google/devtools/mobileharness/infra/ats/console/util/verifier:verifier_result_helper", "//src/java/com/google/devtools/mobileharness/infra/client/longrunningservice/constant:session_properties", diff --git a/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/RunCommandHandler.java b/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/RunCommandHandler.java index 13c358f4e..29a62b029 100644 --- a/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/RunCommandHandler.java +++ b/src/java/com/google/devtools/mobileharness/infra/ats/console/controller/sessionplugin/RunCommandHandler.java @@ -35,6 +35,7 @@ import com.google.devtools.mobileharness.infra.ats.common.SessionRequestHandlerUtil; import com.google.devtools.mobileharness.infra.ats.common.SessionRequestInfo; import com.google.devtools.mobileharness.infra.ats.common.SessionResultHandlerUtil; +import com.google.devtools.mobileharness.infra.ats.common.XtsPropertyName.Job; import com.google.devtools.mobileharness.infra.ats.common.jobcreator.XtsJobCreator; import com.google.devtools.mobileharness.infra.ats.console.controller.proto.SessionPluginProto.AtsSessionPluginOutput; import com.google.devtools.mobileharness.infra.ats.console.controller.proto.SessionPluginProto.AtsSessionPluginOutput.Failure; @@ -245,7 +246,11 @@ void handleResultProcessing(RunCommand command, RunCommandState runCommandState) .filter( jobInfo -> jobInfo.resultWithCause().get().type() == TestResult.SKIP - && jobInfo.properties().has(SessionHandlerHelper.XTS_MODULE_NAME_PROP)) + && jobInfo.properties().has(SessionHandlerHelper.XTS_MODULE_NAME_PROP) + && !jobInfo + .properties() + .getBoolean(Job.SKIP_COLLECTING_NON_TF_REPORTS) + .orElse(false)) .map( jobInfo -> { // Mark skipped modules done when broadcasting results to update the status of diff --git a/src/java/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityChecker.java b/src/java/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityChecker.java index 04f8d02b4..fcf9dfe2f 100644 --- a/src/java/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityChecker.java +++ b/src/java/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityChecker.java @@ -76,7 +76,7 @@ public void onTestStarted(LocalTestStartedEvent event) .log() .atInfo() .alsoTo(logger) - .log("Validating device build fingerprint for test %s", testInfo.locator().getName()); + .log("Validating device build fingerprint for retry %s", testInfo.locator().getName()); validateDeviceBuildFingerprintMatchPrevSession( getAllocatedAndroidDeviceSerials(event), testInfo, @@ -90,6 +90,17 @@ public void onTestStarted(LocalTestStartedEvent event) .getOptional(Job.PREV_SESSION_DEVICE_VENDOR_BUILD_FINGERPRINT) .orElse("")); } + + if (jobInfo.properties().getBoolean(Job.IS_XTS_NON_TF_JOB).orElse(false)) { + testInfo + .log() + .atInfo() + .alsoTo(logger) + .log( + "Validating device build fingerprint for non TF test %s", + testInfo.locator().getName()); + validateDeviceBuildFingerprintsTheSame(getAllocatedAndroidDeviceSerials(event), testInfo); + } } /** @@ -120,10 +131,7 @@ private void validateDeviceBuildFingerprintMatchPrevSession( try { for (String serial : deviceSerials) { - String deviceBuildFingerprint = - androidAdbUtil - .getProperty(serial, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName())) - .trim(); + String deviceBuildFingerprint = getDeviceBuildFingerprint(serial); if (!Ascii.equalsIgnoreCase( deviceBuildFingerprint, prevSessionDeviceBuildFingerprintToCompare)) { setSkipCollectingNonTfReports(testInfo.jobInfo()); @@ -140,11 +148,7 @@ private void validateDeviceBuildFingerprintMatchPrevSession( } if (!prevSessionDeviceVendorBuildFingerprint.isEmpty()) { - String deviceVendorBuildFingerprint = - androidAdbUtil - .getProperty( - serial, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName())) - .trim(); + String deviceVendorBuildFingerprint = getDeviceVendorBuildFingerprint(serial); if (!Ascii.equalsIgnoreCase( deviceVendorBuildFingerprint, prevSessionDeviceVendorBuildFingerprint)) { setSkipCollectingNonTfReports(testInfo.jobInfo()); @@ -173,6 +177,62 @@ private void validateDeviceBuildFingerprintMatchPrevSession( } } + private void validateDeviceBuildFingerprintsTheSame( + ImmutableList deviceSerials, TestInfo testInfo) + throws InterruptedException, SkipTestException { + if (deviceSerials.size() < 2) { + return; + } + + try { + String deviceBuildFingerprint = getDeviceBuildFingerprint(deviceSerials.get(0)); + String deviceVendorBuildFingerprint = getDeviceVendorBuildFingerprint(deviceSerials.get(0)); + for (int i = 1; i < deviceSerials.size(); i++) { + String serial = deviceSerials.get(i); + String deviceBuildFingerprintToCompare = getDeviceBuildFingerprint(serial); + if (!Ascii.equalsIgnoreCase(deviceBuildFingerprint, deviceBuildFingerprintToCompare)) { + setSkipCollectingNonTfReports(testInfo.jobInfo()); + throw SkipTestException.create( + String.format( + "Device build fingerprints should be the same for multi-device tests." + + " Found [%s: %s] and [%s: %s]. Skipping test [%s]", + deviceSerials.get(0), + deviceBuildFingerprint, + serial, + deviceBuildFingerprintToCompare, + testInfo.locator().getName()), + DesiredTestResult.SKIP, + AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILDS_NOT_THE_SAME); + } + String deviceVendorBuildFingerprintToCompare = getDeviceVendorBuildFingerprint(serial); + if (!Ascii.equalsIgnoreCase( + deviceVendorBuildFingerprint, deviceVendorBuildFingerprintToCompare)) { + setSkipCollectingNonTfReports(testInfo.jobInfo()); + throw SkipTestException.create( + String.format( + "Device vendor build fingerprints should be the same for multi-device tests." + + "Found [%s: %s] and [%s: %s]. Skipping test [%s]", + deviceSerials.get(0), + deviceVendorBuildFingerprint, + serial, + deviceVendorBuildFingerprintToCompare, + testInfo.locator().getName()), + DesiredTestResult.SKIP, + AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILDS_NOT_THE_SAME); + } + } + } catch (MobileHarnessException e) { + setSkipCollectingNonTfReports(testInfo.jobInfo()); + throw SkipTestException.create( + String.format( + "Error when checking device build fingerprint for test [%s]", + testInfo.locator().getName()), + DesiredTestResult.SKIP, + AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_CHECK_DEVICE_BUILD_ERROR, + e); + } + } + private void setSkipCollectingNonTfReports(JobInfo jobInfo) { jobInfo.properties().add(Job.SKIP_COLLECTING_NON_TF_REPORTS, "true"); } @@ -186,4 +246,18 @@ private ImmutableList getAllocatedAndroidDeviceSerials(LocalTestStartedE .filter(allAndroidDevices::contains) .collect(toImmutableList()); } + + private String getDeviceBuildFingerprint(String serial) + throws MobileHarnessException, InterruptedException { + return androidAdbUtil + .getProperty(serial, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName())) + .trim(); + } + + private String getDeviceVendorBuildFingerprint(String serial) + throws MobileHarnessException, InterruptedException { + return androidAdbUtil + .getProperty(serial, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName())) + .trim(); + } } diff --git a/src/javatests/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityCheckerTest.java b/src/javatests/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityCheckerTest.java index dff08c2ba..4846cffd0 100644 --- a/src/javatests/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityCheckerTest.java +++ b/src/javatests/com/google/devtools/mobileharness/platform/android/xts/plugin/XtsDeviceCompatibilityCheckerTest.java @@ -220,4 +220,75 @@ public void deviceBuildFingerprintUnalteredNotMatched_throwsSkipTestException() AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILD_NOT_MATCH_RETRY_PREV_SESSION); assertThat(properties.getBoolean(Job.SKIP_COLLECTING_NON_TF_REPORTS).orElse(false)).isTrue(); } + + @Test + public void deviceBuildFingerprintsTheSame() throws Exception { + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint"); + properties.add(Job.IS_XTS_NON_TF_JOB, "true"); + + xtsDeviceCompatibilityChecker.onTestStarted(event); + + assertThat(properties.getBoolean(Job.SKIP_COLLECTING_NON_TF_REPORTS).orElse(false)).isFalse(); + } + + @Test + public void deviceBuildFingerprintsDifferent() throws Exception { + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint1"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint2"); + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint"); + properties.add(Job.IS_XTS_NON_TF_JOB, "true"); + + assertThat( + assertThrows( + SkipTestException.class, + () -> xtsDeviceCompatibilityChecker.onTestStarted(event)) + .errorId()) + .isEqualTo(AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILDS_NOT_THE_SAME); + assertThat(properties.getBoolean(Job.SKIP_COLLECTING_NON_TF_REPORTS).orElse(false)).isTrue(); + } + + @Test + public void deviceVendorBuildFingerprintsDifferent() throws Exception { + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.FINGERPRINT.getPropName()))) + .thenReturn("build_fingerprint"); + when(androidAdbUtil.getProperty( + DEVICE_ID_1, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint1"); + when(androidAdbUtil.getProperty( + DEVICE_ID_2, ImmutableList.of(DeviceBuildInfo.VENDOR_FINGERPRINT.getPropName()))) + .thenReturn("vendor_build_fingerprint2"); + properties.add(Job.IS_XTS_NON_TF_JOB, "true"); + + assertThat( + assertThrows( + SkipTestException.class, + () -> xtsDeviceCompatibilityChecker.onTestStarted(event)) + .errorId()) + .isEqualTo(AndroidErrorId.XTS_DEVICE_COMPAT_CHECKER_DEVICE_BUILDS_NOT_THE_SAME); + assertThat(properties.getBoolean(Job.SKIP_COLLECTING_NON_TF_REPORTS).orElse(false)).isTrue(); + } }