Make backup CTS tests more resilient for failing logcat --clear
Test: cts-tradefed run cts -m CtsBackupTestCases
Change-Id: I3202367fff7436da23b50ab09ab00b671fd635fe
diff --git a/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java b/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
index 4a70a67..9c42cc6 100644
--- a/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
+++ b/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
@@ -26,9 +26,8 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
+import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* Base class for backup instrumentation tests.
@@ -36,7 +35,7 @@
* Ensures that backup is enabled and local transport selected, and provides some utility methods.
*/
public class BaseBackupCtsTest extends InstrumentationTestCase {
- protected static final String APP_LOG_TAG = "BackupCTSApp";
+ private static final String APP_LOG_TAG = "BackupCTSApp";
private static final String LOCAL_TRANSPORT =
"android/com.android.internal.backup.LocalTransport";
@@ -55,6 +54,7 @@
if (isBackupSupported) {
assertTrue("Backup not enabled", isBackupEnabled());
assertTrue("LocalTransport not selected", isLocalTransportSelected());
+ exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
}
}
@@ -72,16 +72,44 @@
return output.contains("* " + LOCAL_TRANSPORT);
}
- protected boolean waitForLogcat(String logcatString, int maxTimeoutInSeconds) throws Exception {
+ /**
+ * Attempts to clear logcat.
+ *
+ * Clearing logcat is known to be unreliable, so this methods also output a unique separator
+ * that can be used to find this point in the log even if clearing failed.
+ * @return a unique separator string
+ * @throws Exception
+ */
+ protected String clearLogcat() throws Exception {
+ exec("logcat -c");
+ String uniqueString = ":::" + UUID.randomUUID().toString();
+ exec("log -t " + APP_LOG_TAG + " " + uniqueString);
+ return uniqueString;
+ }
+
+ /**
+ * Wait for up to maxTimeoutInSeconds for the given strings to appear in the logcat in the given order.
+ * By passing the separator returned by {@link #clearLogcat} as the first string you can ensure that only
+ * logs emitted after that call to clearLogcat are found.
+ *
+ * @throws AssertionError if the strings are not found in the given time.
+ */
+ protected void waitForLogcat(int maxTimeoutInSeconds, String... logcatStrings)
+ throws Exception {
long timeout = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(maxTimeoutInSeconds);
+ int stringIndex = 0;
while (timeout >= System.currentTimeMillis()) {
FileInputStream fis = executeStreamedShellCommand(getInstrumentation(),
"logcat -v brief -d " + APP_LOG_TAG + ":* *:S");
BufferedReader log = new BufferedReader(new InputStreamReader(fis));
String line;
+ stringIndex = 0;
while ((line = log.readLine()) != null) {
- if (line.contains(logcatString)) {
- return true;
+ if (line.contains(logcatStrings[stringIndex])) {
+ stringIndex++;
+ if (stringIndex >= logcatStrings.length) {
+ return;
+ }
}
}
closeQuietly(log);
@@ -89,7 +117,9 @@
// performing the next search.
Thread.sleep(SMALL_LOGCAT_DELAY);
}
- return false;
+ fail("Couldn't find " + logcatStrings[stringIndex] +
+ (stringIndex > 0 ? " after " + logcatStrings[stringIndex - 1] : "") +
+ " within " + maxTimeoutInSeconds + " seconds ");
}
protected void createTestFileOfSize(String packageName, int size) throws Exception {
@@ -97,14 +127,14 @@
"-c android.intent.category.LAUNCHER " +
"-n " + packageName + "/android.backup.app.MainActivity " +
"-e file_size " + size);
- assertTrue("File was not created", waitForLogcat("File created!", 30));
+ waitForLogcat(30, "File created!");
}
protected String exec(String command) throws Exception {
- BufferedReader br = null;
try (InputStream in = executeStreamedShellCommand(getInstrumentation(), command)) {
- br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
- String str = null;
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(in, StandardCharsets.UTF_8));
+ String str;
StringBuilder out = new StringBuilder();
while ((str = br.readLine()) != null) {
out.append(str);
diff --git a/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java b/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
index 16ecb79..90dc5e8 100644
--- a/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
+++ b/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
@@ -25,50 +25,37 @@
private static final int LOCAL_TRANSPORT_CONFORMING_FILE_SIZE = 5 * 1024;
+ private static final int TIMEOUT_SECONDS = 10;
+
public void testExpectedMethodsCalledInOrder() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
- exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
+ String backupSeparator = clearLogcat();
// Make sure there's something to backup
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_CONFORMING_FILE_SIZE);
// Request backup and wait for it to complete
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Backup agent not destroyed", waitForLogcat("onDestroy", 10));
- verifyContainsInOrder(execLogcat(),
+ waitForLogcat(TIMEOUT_SECONDS,
+ backupSeparator,
"onCreate",
"Full backup requested",
"onDestroy");
- exec("logcat --clear");
+ String restoreSeparator = clearLogcat();
// Now request restore and wait for it to complete
exec("bmgr restore " + BACKUP_APP_NAME);
- assertTrue("Backup agent not destroyed", waitForLogcat("onDestroy", 10));
- verifyContainsInOrder(execLogcat(),
+ waitForLogcat(TIMEOUT_SECONDS,
+ restoreSeparator,
"onCreate",
"onRestoreFile",
"onRestoreFinished",
"onDestroy");
}
- private void verifyContainsInOrder(String message, String... substrings) {
- int currentIndex = 0;
- for (String substring : substrings) {
- int substringIndex = message.indexOf(substring, currentIndex);
- if (substringIndex < 0) {
- fail("Didn't find '" + substring + "' in expected order");
- }
- currentIndex = substringIndex + substring.length();
- }
- };
-
- private String execLogcat() throws Exception {
- return exec("logcat -v brief -d " + APP_LOG_TAG + ":* *:S");
- }
}
diff --git a/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java b/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
index cfe007c..7315097 100644
--- a/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
@@ -30,28 +30,30 @@
private static final int LOCAL_TRANSPORT_BACKUP_QUOTA = 25 * 1024 * 1024;
private static final int LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE = 30 * 1024 * 1024;
+ private static final int TIMEOUT_SECONDS = 10;
+
public void testQuotaExceeded() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
- exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
+ String separator = clearLogcat();
// Launch test app and create file exceeding limit for local transport
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE);
// Request backup and wait for quota exceeded event in logcat
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Quota exceeded event is not received", waitForLogcat("Quota exceeded!", 10));
+ waitForLogcat(TIMEOUT_SECONDS,separator,
+ "Quota exceeded!");
}
public void testQuotaReported() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
+ String separator = clearLogcat();
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Quota not reported correctly",
- waitForLogcat("quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA, 10));
+ waitForLogcat(TIMEOUT_SECONDS,separator,
+ "quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA);
}
}
diff --git a/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java b/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
index 420c723..2802f81 100644
--- a/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
+++ b/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
@@ -25,50 +25,35 @@
private static final int LOCAL_TRANSPORT_CONFORMING_FILE_SIZE = 5 * 1024;
+ private static final int TIMEOUT_SECONDS = 10;
+
public void testExpectedMethodsCalledInOrder() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
- exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
+ String backupSeparator = clearLogcat();
// Make sure there's something to backup
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_CONFORMING_FILE_SIZE);
// Request backup and wait for it to complete
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Backup agent not destroyed", waitForLogcat("onDestroy", 10));
- verifyContainsInOrder(execLogcat(),
+ waitForLogcat(TIMEOUT_SECONDS,backupSeparator,
"onCreate",
"Backup requested",
"onDestroy");
- exec("logcat --clear");
+ String restoreSeparator = clearLogcat();
// Now request restore and wait for it to complete
exec("bmgr restore " + BACKUP_APP_NAME);
- assertTrue("Backup agent not destroyed", waitForLogcat("onDestroy", 10));
- verifyContainsInOrder(execLogcat(),
+ waitForLogcat(TIMEOUT_SECONDS, restoreSeparator,
"onCreate",
"Restore requested",
"onRestoreFinished",
"onDestroy");
}
- private void verifyContainsInOrder(String message, String... substrings) {
- int currentIndex = 0;
- for (String substring : substrings) {
- int substringIndex = message.indexOf(substring, currentIndex);
- if (substringIndex < 0) {
- fail("Didn't find '" + substring + "' in expected order");
- }
- currentIndex = substringIndex + substring.length();
- }
- };
-
- private String execLogcat() throws Exception {
- return exec("logcat -v brief -d " + APP_LOG_TAG + ":* *:S");
- }
}
diff --git a/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java b/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
index 9647d07..6f78b09 100644
--- a/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
@@ -30,28 +30,30 @@
private static final int LOCAL_TRANSPORT_BACKUP_QUOTA = 5 * 1024 * 1024;
private static final int LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE = 6 * 1024 * 1024;
+ private static final int TIMEOUT_SECONDS = 10;
+
public void testQuotaExceeded() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
- exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
+ String separator = clearLogcat();
// Launch test app and create file exceeding limit for local transport
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE);
// Request backup and wait for quota exceeded event in logcat
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Quota exceeded event is not received", waitForLogcat("Quota exceeded!", 10));
+ waitForLogcat(TIMEOUT_SECONDS, separator,
+ "Quota exceeded!");
}
public void testQuotaReported() throws Exception {
if (!isBackupSupported()) {
return;
}
- exec("logcat --clear");
+ String separator = clearLogcat();
exec("bmgr backupnow " + BACKUP_APP_NAME);
- assertTrue("Quota not reported correctly",
- waitForLogcat("quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA, 10));
+ waitForLogcat(TIMEOUT_SECONDS, separator,
+ "quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA);
}
}