Add an assertNoCrashes function to CTS

Bug: 134613999
Test: None
Change-Id: I6c94638c76f79a60d24add0ca4371f422aff6387
Merged-In: I6c94638c76f79a60d24add0ca4371f422aff6387
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 954d1ce..0521bb6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -16,6 +16,8 @@
 
 package android.security.cts;
 
+import com.android.compatibility.common.util.Crash;
+import com.android.compatibility.common.util.CrashUtils;
 import com.android.ddmlib.NullOutputReceiver;
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -27,6 +29,7 @@
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.Scanner;
 
@@ -291,6 +294,71 @@
     }
 
     /**
+     * Runs the poc binary and asserts that there are no security crashes that match the expected
+     * process pattern.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
+     */
+    public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
+            String... processPatternStrings) throws Exception {
+        AdbUtils.runCommandLine("logcat -c", device);
+        // account for the poc timer of 5 minutes (+15 seconds for safety)
+        AdbUtils.runPocNoOutput(pocName, device, 315);
+        assertNoCrashes(device, processPatternStrings);
+    }
+
+    /**
+     * Dumps logcat and asserts that there are no security crashes that match the expected process.
+     * By default, checks min crash addresses
+     * pattern. Ensure that adb logcat -c is called beforehand.
+     * @param device device to be ran on
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
+     */
+    public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
+            throws Exception {
+        assertNoCrashes(device, true, processPatternStrings);
+    }
+
+    /**
+     * Dumps logcat and asserts that there are no security crashes that match the expected process
+     * pattern. Ensure that adb logcat -c is called beforehand.
+     * @param device device to be ran on
+     * @param checkMinAddress if the minimum fault address should be respected
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
+     */
+    public static void assertNoCrashes(ITestDevice device, boolean checkMinAddress,
+            String... processPatternStrings) throws Exception {
+        String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device);
+
+        Pattern[] processPatterns = new Pattern[processPatternStrings.length];
+        for (int i = 0; i < processPatternStrings.length; i++) {
+            processPatterns[i] = Pattern.compile(processPatternStrings[i]);
+        }
+        List<Crash> crashes = CrashUtils.getAllCrashes(logcat);
+        List<Crash> securityCrashes =
+                CrashUtils.matchSecurityCrashes(crashes, checkMinAddress, processPatterns);
+
+        if (securityCrashes.isEmpty()) {
+            return; // no security crashes detected
+        }
+
+        StringBuilder error = new StringBuilder();
+        error.append("Security crash detected:\n");
+        error.append("Process patterns:");
+        for (String pattern : processPatternStrings) {
+            error.append(String.format(" '%s'", pattern));
+        }
+        error.append("\nCrashes:\n");
+        for (Crash crash : securityCrashes) {
+            if (crash.crashString != null) {
+                error.append(String.format("%s\n", crash.crashString));
+            }
+        }
+        fail(error.toString());
+    }
+
+    /**
      * Executes a given poc within a given timeout. Returns error if the
      * given poc doesnt complete its execution within timeout. It also deletes
      * the list of files provided.