Fix flaky RollbackTest#testBadUpdateRollback

Added wait for ACTION_ROLLBACK_COMMITTED and also
minor RollbackTestUtils refactoring.

Test: atest RollbackTest
Bug: 126497394
Change-Id: Ia31b98974733ea19cd73c2688971ea853834e195
This commit is contained in:
Zimuzo
2019-03-20 14:16:41 +00:00
parent 289cd11cc4
commit 790a3ccfa6
3 changed files with 51 additions and 30 deletions

View File

@@ -62,6 +62,13 @@ class RollbackBroadcastReceiver extends BroadcastReceiver {
return mRollbackBroadcasts.poll(timeout, unit);
}
/**
* Waits forever for the next rollback broadcast.
*/
Intent take() throws InterruptedException {
return mRollbackBroadcasts.take();
}
/**
* Unregisters this broadcast receiver.
*/

View File

@@ -27,7 +27,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import android.Manifest;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -46,8 +45,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
@@ -790,34 +787,14 @@ public class RollbackTest {
rm.getAvailableRollbacks(), TEST_APP_B);
assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
// Register rollback committed receiver
RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver();
IntentFilter crashCountFilter = new IntentFilter();
crashCountFilter.addAction("com.android.tests.rollback.CRASH");
crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
// Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback
crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5);
crashCountReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
// Sleep long enough for packagewatchdog to be notified of crash
Thread.sleep(1000);
// Kill app and close AppErrorDialog
ActivityManager am = context.getSystemService(ActivityManager.class);
am.killBackgroundProcesses(TEST_APP_A);
// Allow another package launch
crashQueue.put(intent.getIntExtra("count", 0));
} catch (InterruptedException e) {
fail("Failed to communicate with test app");
}
}
};
context.registerReceiver(crashCountReceiver, crashCountFilter);
// Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes
do {
RollbackTestUtils.launchPackage(TEST_APP_A);
} while(crashQueue.take() < 5);
// Verify we received a broadcast for the rollback.
rollbackReceiver.take();
// TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver
assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));

View File

@@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -47,6 +48,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
/**
* Utilities to facilitate testing rollbacks.
@@ -187,7 +189,7 @@ class RollbackTestUtils {
}
/** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */
static void launchPackage(String packageName)
private static void launchPackage(String packageName)
throws InterruptedException, IOException {
Context context = InstrumentationRegistry.getContext();
Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -488,4 +490,39 @@ class RollbackTestUtils {
}
return null;
}
/**
* Send broadcast to crash {@code packageName} {@code count} times. If {@code count} is at least
* {@link PackageWatchdog#TRIGGER_FAILURE_COUNT}, watchdog crash detection will be triggered.
*/
static BroadcastReceiver sendCrashBroadcast(Context context, String packageName, int count)
throws InterruptedException, IOException {
BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
IntentFilter crashCountFilter = new IntentFilter();
crashCountFilter.addAction("com.android.tests.rollback.CRASH");
crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
BroadcastReceiver crashCountReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
// Sleep long enough for packagewatchdog to be notified of crash
Thread.sleep(1000);
// Kill app and close AppErrorDialog
ActivityManager am = context.getSystemService(ActivityManager.class);
am.killBackgroundProcesses(packageName);
// Allow another package launch
crashQueue.put(intent.getIntExtra("count", 0));
} catch (InterruptedException e) {
fail("Failed to communicate with test app");
}
}
};
context.registerReceiver(crashCountReceiver, crashCountFilter);
do {
launchPackage(packageName);
} while(crashQueue.take() < count);
return crashCountReceiver;
}
}