| Index: chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java
|
| diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java
|
| index 9b48687820cf4d77767ef3ddc0d5c861cf7077a7..c31e302d72b2bcb0cec416a1f07caacd42acdd23 100644
|
| --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java
|
| +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java
|
| @@ -8,17 +8,14 @@ import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
|
|
|
| import android.accounts.Account;
|
| import android.content.Context;
|
| -import android.util.Log;
|
| import android.util.Pair;
|
|
|
| import junit.framework.Assert;
|
|
|
| -import org.chromium.base.CommandLine;
|
| import org.chromium.base.ThreadUtils;
|
| import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory;
|
| import org.chromium.chrome.browser.profiles.Profile;
|
| import org.chromium.chrome.browser.sync.ProfileSyncService;
|
| -import org.chromium.chrome.test.util.TestHttpServerClient;
|
| import org.chromium.content.browser.test.util.Criteria;
|
| import org.chromium.content.browser.test.util.CriteriaHelper;
|
| import org.chromium.sync.signin.ChromeSigninController;
|
| @@ -27,15 +24,11 @@ import org.json.JSONException;
|
| import org.json.JSONObject;
|
|
|
| import java.util.ArrayList;
|
| -import java.util.HashMap;
|
| import java.util.Iterator;
|
| import java.util.List;
|
| -import java.util.Locale;
|
| -import java.util.Map;
|
| import java.util.concurrent.Callable;
|
| import java.util.concurrent.Semaphore;
|
| import java.util.concurrent.TimeUnit;
|
| -import java.util.concurrent.atomic.AtomicLong;
|
|
|
| /**
|
| * Utility class for shared sync test functionality.
|
| @@ -43,146 +36,16 @@ import java.util.concurrent.atomic.AtomicLong;
|
| public final class SyncTestUtil {
|
| private static final String TAG = "SyncTestUtil";
|
|
|
| - public static final long UI_TIMEOUT_MS = scaleTimeout(20000);
|
| - public static final int CHECK_INTERVAL_MS = 250;
|
| + public static final long TIMEOUT_MS = scaleTimeout(20000);
|
| + public static final int INTERVAL_MS = 250;
|
|
|
| - private static final long SYNC_WAIT_TIMEOUT_MS = scaleTimeout(30 * 1000);
|
| - private static final int SYNC_CHECK_INTERVAL_MS = 250;
|
| -
|
| - public static final Pair<String, String> SYNC_SUMMARY_STATUS =
|
| - newPair("Summary", "Summary");
|
| - protected static final String UNINITIALIZED = "Uninitialized";
|
| - protected static final Pair<String, String> USERNAME_STAT =
|
| - newPair("Identity", "Username");
|
| -
|
| - // Override the default server used for profile sync.
|
| - // Native switch - chrome_switches::kSyncServiceURL
|
| - private static final String SYNC_URL = "sync-url";
|
| -
|
| - private SyncTestUtil() {
|
| - }
|
| -
|
| - /**
|
| - * Creates a Pair of lowercased and trimmed Strings. Makes it easier to avoid running afoul of
|
| - * case-sensitive comparison since getAboutInfoStats(), et al, use Pair<String, String> as map
|
| - * keys.
|
| - */
|
| - private static Pair<String, String> newPair(String first, String second) {
|
| - return Pair.create(first.toLowerCase(Locale.US).trim(),
|
| - second.toLowerCase(Locale.US).trim());
|
| - }
|
| + private SyncTestUtil() {}
|
|
|
| /**
|
| - * Parses raw JSON into a map with keys Pair<String, String>. The first string in each Pair
|
| - * corresponds to the title under which a given stat_name/stat_value is situated, and the second
|
| - * contains the name of the actual stat. For example, a stat named "Syncing" which falls under
|
| - * "Local State" would be a Pair of newPair("Local State", "Syncing").
|
| - *
|
| - * @param rawJson the JSON to parse into a map
|
| - * @return a map containing a mapping of titles and stat names to stat values
|
| - * @throws org.json.JSONException
|
| - */
|
| - public static Map<Pair<String, String>, String> getAboutInfoStats(String rawJson)
|
| - throws JSONException {
|
| -
|
| - // What we get back is what you'd get from chrome.sync.aboutInfo at chrome://sync. This is
|
| - // a JSON object, and we care about the "details" field in that object. "details" itself has
|
| - // objects with two fields: data and title. The data field itself contains an array of
|
| - // objects. These objects contains two fields: stat_name and stat_value. Ultimately these
|
| - // are the values displayed on the page and the values we care about in this method.
|
| - Map<Pair<String, String>, String> statLookup = new HashMap<Pair<String, String>, String>();
|
| - JSONObject aboutInfo = new JSONObject(rawJson);
|
| - JSONArray detailsArray = aboutInfo.getJSONArray("details");
|
| - for (int i = 0; i < detailsArray.length(); i++) {
|
| - JSONObject dataObj = detailsArray.getJSONObject(i);
|
| - String dataTitle = dataObj.getString("title");
|
| - JSONArray dataArray = dataObj.getJSONArray("data");
|
| - for (int j = 0; j < dataArray.length(); j++) {
|
| - JSONObject statObj = dataArray.getJSONObject(j);
|
| - String statName = statObj.getString("stat_name");
|
| - Pair<String, String> key = newPair(dataTitle, statName);
|
| - statLookup.put(key, statObj.getString("stat_value"));
|
| - }
|
| - }
|
| -
|
| - return statLookup;
|
| - }
|
| -
|
| - /**
|
| - * Verifies that sync is signed out and its status is "Syncing not enabled".
|
| - * TODO(mmontgomery): check whether or not this method is necessary. It queries
|
| - * syncSummaryStatus(), which is a slightly more direct route than via JSON.
|
| + * Verifies that sync is signed out.
|
| */
|
| public static void verifySyncIsSignedOut(Context context) {
|
| - Map<Pair<String, String>, String> expectedStats =
|
| - new HashMap<Pair<String, String>, String>();
|
| - expectedStats.put(SYNC_SUMMARY_STATUS, UNINITIALIZED);
|
| - expectedStats.put(USERNAME_STAT, ""); // Expect an empty username when sync is signed out.
|
| - Assert.assertTrue("Expected sync to be disabled.",
|
| - pollAboutSyncStats(context, expectedStats));
|
| - }
|
| -
|
| - /**
|
| - * Polls the stats on about:sync until timeout or all expected stats match actual stats. The
|
| - * comparison is case insensitive. *All* stats must match those passed in via expectedStats.
|
| - *
|
| - *
|
| - * @param expectedStats a map of stat names to their expected values
|
| - * @return whether the stats matched up before the timeout
|
| - */
|
| - public static boolean pollAboutSyncStats(
|
| - Context context, final Map<Pair<String, String>, String> expectedStats) {
|
| - final AboutSyncInfoGetter aboutInfoGetter =
|
| - new AboutSyncInfoGetter(context);
|
| -
|
| - Criteria statChecker = new Criteria() {
|
| - @Override
|
| - public boolean isSatisfied() {
|
| - try {
|
| - ThreadUtils.runOnUiThreadBlocking(aboutInfoGetter);
|
| - Map<Pair<String, String>, String> actualStats = aboutInfoGetter.getAboutInfo();
|
| - return areExpectedStatsAmongActual(expectedStats, actualStats);
|
| - } catch (Throwable e) {
|
| - Log.w(TAG, "Interrupted while attempting to fetch sync internals info.", e);
|
| - }
|
| - return false;
|
| - }
|
| - };
|
| -
|
| - boolean matched = false;
|
| - try {
|
| - matched = CriteriaHelper.pollForCriteria(statChecker, UI_TIMEOUT_MS, CHECK_INTERVAL_MS);
|
| - } catch (InterruptedException e) {
|
| - Log.w(TAG, "Interrupted while polling sync internals info.", e);
|
| - Assert.fail("Interrupted while polling sync internals info.");
|
| - }
|
| - return matched;
|
| - }
|
| -
|
| - /**
|
| - * Checks whether the expected map's keys and values are a subset of those in another map. Both
|
| - * keys and values are compared in a case-insensitive fashion.
|
| - *
|
| - * @param expectedStats a map which may be a subset of actualSet
|
| - * @param actualStats a map which may be a superset of expectedSet
|
| - * @return true if all key/value pairs in expectedSet are in actualSet; false otherwise
|
| - */
|
| - private static boolean areExpectedStatsAmongActual(
|
| - Map<Pair<String, String>, String> expectedStats,
|
| - Map<Pair<String, String>, String> actualStats) {
|
| - for (Map.Entry<Pair<String, String>, String> statEntry : expectedStats.entrySet()) {
|
| - // Make stuff lowercase here, at the site of comparison.
|
| - String expectedValue = statEntry.getValue().toLowerCase(Locale.US).trim();
|
| - String actualValue = actualStats.get(statEntry.getKey());
|
| - if (actualValue == null) {
|
| - return false;
|
| - }
|
| - actualValue = actualValue.toLowerCase(Locale.US).trim();
|
| - if (!expectedValue.contentEquals(actualValue)) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| + Assert.assertTrue(isSyncOff());
|
| }
|
|
|
| /**
|
| @@ -201,53 +64,38 @@ public final class SyncTestUtil {
|
| /**
|
| * Triggers a sync and waits till it is complete.
|
| */
|
| - public static void triggerSyncAndWaitForCompletion(final Context context)
|
| - throws InterruptedException {
|
| - final long oldSyncTime = getCurrentSyncTime(context);
|
| -
|
| + public static void triggerSyncAndWaitForCompletion() throws InterruptedException {
|
| + final long oldSyncTime = getCurrentSyncTime();
|
| triggerSync();
|
| -
|
| - // Wait till lastSyncedTime > oldSyncTime.
|
| - Assert.assertTrue("Timed out waiting for syncing to complete.",
|
| - CriteriaHelper.pollForCriteria(new Criteria() {
|
| - @Override
|
| - public boolean isSatisfied() {
|
| - long currentSyncTime = 0;
|
| - try {
|
| - currentSyncTime = getCurrentSyncTime(context);
|
| - } catch (InterruptedException e) {
|
| - Log.w(TAG, "Interrupted while getting sync time.", e);
|
| - }
|
| - return currentSyncTime > oldSyncTime;
|
| - }
|
| - }, SYNC_WAIT_TIMEOUT_MS, SYNC_CHECK_INTERVAL_MS));
|
| + boolean syncCompleted = CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return getCurrentSyncTime() > oldSyncTime;
|
| + }
|
| + }, TIMEOUT_MS, INTERVAL_MS);
|
| + Assert.assertTrue("Timed out waiting for sync cycle to complete.", syncCompleted);
|
| }
|
|
|
| - private static long getCurrentSyncTime(final Context context) throws InterruptedException {
|
| - final Semaphore s = new Semaphore(0);
|
| - final AtomicLong result = new AtomicLong();
|
| - ThreadUtils.runOnUiThreadBlocking(new Runnable() {
|
| + private static long getCurrentSyncTime() {
|
| + return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Long>() {
|
| @Override
|
| - public void run() {
|
| - result.set(ProfileSyncService.get().getLastSyncedTimeForTest());
|
| - s.release();
|
| + public Long call() {
|
| + return ProfileSyncService.get().getLastSyncedTimeForTest();
|
| }
|
| });
|
| - Assert.assertTrue(s.tryAcquire(SYNC_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
| - return result.get();
|
| }
|
|
|
| /**
|
| * Waits for sync to become active.
|
| */
|
| - public static void waitForSyncActive(final Context context) throws InterruptedException {
|
| + public static void waitForSyncActive() throws InterruptedException {
|
| Assert.assertTrue("Timed out waiting for sync to become active.",
|
| CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| @Override
|
| public boolean isSatisfied() {
|
| return ProfileSyncService.get().isSyncActive();
|
| }
|
| - }, SYNC_WAIT_TIMEOUT_MS, SYNC_CHECK_INTERVAL_MS));
|
| + }, TIMEOUT_MS, INTERVAL_MS));
|
| }
|
|
|
| /**
|
| @@ -255,8 +103,8 @@ public final class SyncTestUtil {
|
| */
|
| public static void verifySyncIsActiveForAccount(Context context, Account account)
|
| throws InterruptedException {
|
| - waitForSyncActive(context);
|
| - triggerSyncAndWaitForCompletion(context);
|
| + waitForSyncActive();
|
| + triggerSyncAndWaitForCompletion();
|
| verifySignedInWithAccount(context, account);
|
| }
|
|
|
| @@ -264,50 +112,28 @@ public final class SyncTestUtil {
|
| * Makes sure that sync is enabled with the correct account.
|
| */
|
| public static void verifySignedInWithAccount(Context context, Account account) {
|
| - if (account == null) return;
|
| -
|
| - Assert.assertEquals(
|
| - account.name, ChromeSigninController.get(context).getSignedInAccountName());
|
| + Assert.assertEquals(account, ChromeSigninController.get(context).getSignedInUser());
|
| }
|
|
|
| /**
|
| - * Makes sure that the Python sync server was successfully started by checking for a well known
|
| - * response to a request for the server time. The command line argument for the sync server must
|
| - * be present in order for this check to be valid.
|
| + * Verifies that the sync is off but signed in with the account.
|
| */
|
| - public static void verifySyncServerIsRunning() {
|
| - boolean hasSwitch = CommandLine.getInstance().hasSwitch(SYNC_URL);
|
| - Assert.assertTrue(SYNC_URL + " is a required parameter for the sync tests.", hasSwitch);
|
| - String syncTimeUrl = CommandLine.getInstance().getSwitchValue(SYNC_URL) + "/time";
|
| - TestHttpServerClient.checkServerIsUp(syncTimeUrl, "0123456789");
|
| + public static void verifySyncIsDisabled(Context context, Account account) {
|
| + Assert.assertTrue("Expected sync to be disabled.", isSyncOff());
|
| + verifySignedInWithAccount(context, account);
|
| }
|
|
|
| - /**
|
| - * Returns whether the sync engine has keep everything synced set to true.
|
| - */
|
| - public static boolean isSyncEverythingEnabled(final Context context) {
|
| + private static boolean isSyncOff() {
|
| return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
|
| @Override
|
| public Boolean call() {
|
| - return ProfileSyncService.get().hasKeepEverythingSynced();
|
| + ProfileSyncService syncService = ProfileSyncService.get();
|
| + return !syncService.isBackendInitialized() && !syncService.isSyncRequested();
|
| }
|
| });
|
| }
|
|
|
| /**
|
| - * Verifies that the sync status is "Syncing not enabled" and that sync is signed in with the
|
| - * account.
|
| - */
|
| - public static void verifySyncIsDisabled(Context context, Account account) {
|
| - Map<Pair<String, String>, String> expectedStats =
|
| - new HashMap<Pair<String, String>, String>();
|
| - expectedStats.put(SYNC_SUMMARY_STATUS, UNINITIALIZED);
|
| - Assert.assertTrue(
|
| - "Expected sync to be disabled.", pollAboutSyncStats(context, expectedStats));
|
| - verifySignedInWithAccount(context, account);
|
| - }
|
| -
|
| - /**
|
| * Retrieves the local Sync data as a JSONArray via ProfileSyncService.
|
| *
|
| * This method blocks until the data is available or until it times out.
|
| @@ -332,7 +158,7 @@ public final class SyncTestUtil {
|
|
|
| try {
|
| Assert.assertTrue("Semaphore should have been released.",
|
| - semaphore.tryAcquire(UI_TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
| + semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
| } catch (InterruptedException e) {
|
| throw new RuntimeException(e);
|
| }
|
| @@ -432,35 +258,4 @@ public final class SyncTestUtil {
|
| }
|
| return localDataForDatatype;
|
| }
|
| -
|
| - /**
|
| - * Retrieves the sync internals information which is the basis for chrome://sync-internals and
|
| - * makes the result available in {@link AboutSyncInfoGetter#getAboutInfo()}.
|
| - *
|
| - * This class has to be run on the main thread, as it accesses the ProfileSyncService.
|
| - */
|
| - public static class AboutSyncInfoGetter implements Runnable {
|
| - private static final String TAG = "AboutSyncInfoGetter";
|
| - final Context mContext;
|
| - Map<Pair<String, String>, String> mAboutInfo;
|
| -
|
| - public AboutSyncInfoGetter(Context context) {
|
| - mContext = context.getApplicationContext();
|
| - mAboutInfo = new HashMap<Pair<String, String>, String>();
|
| - }
|
| -
|
| - @Override
|
| - public void run() {
|
| - String info = ProfileSyncService.get().getSyncInternalsInfoForTest();
|
| - try {
|
| - mAboutInfo = getAboutInfoStats(info);
|
| - } catch (JSONException e) {
|
| - Log.w(TAG, "Unable to parse JSON message: " + info, e);
|
| - }
|
| - }
|
| -
|
| - public Map<Pair<String, String>, String> getAboutInfo() {
|
| - return mAboutInfo;
|
| - }
|
| - }
|
| }
|
|
|