blob: e4641776c9f190fc682a582ff010297b6975535e [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.webapps;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.ContextUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.util.AdvancedMockContext;
import org.chromium.base.test.util.Feature;
import org.chromium.webapk.lib.common.WebApkConstants;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* Tests for the ActivityAssigner class.
*/
public class ActivityAssignerTest extends InstrumentationTestCase {
private static final String BASE_WEBAPP_ID = "BASE_WEBAPP_ID_";
private AdvancedMockContext mContext;
private HashMap<String, Object>[] mPreferences;
@Override
protected void setUp() throws Exception {
super.setUp();
RecordHistogram.disableForTests();
mContext = new AdvancedMockContext(ContextUtils.getApplicationContext());
mPreferences = new HashMap[ActivityAssigner.ACTIVITY_TYPE_COUNT];
for (int i = 0; i < ActivityAssigner.ACTIVITY_TYPE_COUNT; ++i) {
mPreferences[i] = new HashMap<String, Object>();
mContext.addSharedPreferences(ActivityAssigner.PREF_PACKAGE[i], mPreferences[i]);
}
ContextUtils.initApplicationContextForTests(mContext);
}
@UiThreadTest
@SmallTest
@Feature({"Webapps"})
public void testEntriesCreated() {
String webappId = BASE_WEBAPP_ID;
ActivityAssigner assigner = ActivityAssigner.instance(webappId);
// Make sure that no webapps have been assigned to any Activities for a fresh install.
checkState(assigner);
List<ActivityAssigner.ActivityEntry> entries = assigner.getEntries();
assertEquals(ActivityAssigner.NUM_WEBAPP_ACTIVITIES, entries.size());
for (ActivityAssigner.ActivityEntry entry : entries) {
assertEquals(null, entry.mWebappId);
}
}
/**
* Make sure invalid entries get culled & that we still have the correct number of unique
* Activity indices available.
*/
@UiThreadTest
@SmallTest
@Feature({"Webapps"})
public void testEntriesDownsized() {
// Store preferences indicating that more Activities existed previously than there are now.
int numSavedEntries = ActivityAssigner.NUM_WEBAPP_ACTIVITIES + 1;
String webappId = BASE_WEBAPP_ID;
int index = ActivityAssigner.getIndex(webappId);
createPreferences(numSavedEntries, index);
ActivityAssigner assigner = ActivityAssigner.instance(webappId);
assertEquals(index, assigner.getActivityTypeIndex());
checkState(assigner);
}
/**
* Make sure we recover from corrupted stored preferences.
*/
@UiThreadTest
@SmallTest
@Feature({"Webapps"})
public void testCorruptedPreferences() {
String wrongVariableType = "omgwtfbbq";
String webappId = BASE_WEBAPP_ID;
int index = ActivityAssigner.getIndex(BASE_WEBAPP_ID);
mPreferences[index].clear();
mPreferences[index].put(ActivityAssigner.PREF_NUM_SAVED_ENTRIES[index], wrongVariableType);
ActivityAssigner assigner = ActivityAssigner.instance(webappId);
assertEquals(index, assigner.getActivityTypeIndex());
checkState(assigner);
}
@UiThreadTest
@SmallTest
@Feature({"Webapps"})
public void testAssignment() {
String webappId = BASE_WEBAPP_ID;
ActivityAssigner assigner = ActivityAssigner.instance(webappId);
int index = assigner.getActivityTypeIndex();
checkState(assigner);
// Assign all of the Activities to webapps.
// Go backwards to make sure ordering doesn't matter.
Map<String, Integer> testMap = new HashMap<String, Integer>();
for (int i = ActivityAssigner.NUM_WEBAPP_ACTIVITIES - 1; i >= 0; --i) {
String currentWebappId = BASE_WEBAPP_ID + i;
int activityIndex = assigner.assign(currentWebappId);
testMap.put(currentWebappId, activityIndex);
}
assertEquals(ActivityAssigner.NUM_WEBAPP_ACTIVITIES, testMap.size());
// Make sure that passing in the same webapp ID gives back the same Activity.
for (int i = 0; i < ActivityAssigner.NUM_WEBAPP_ACTIVITIES; ++i) {
String currentWebappId = BASE_WEBAPP_ID + i;
int actualIndex = assigner.assign(currentWebappId);
int expectedIndex = testMap.get(currentWebappId);
assertEquals(expectedIndex, actualIndex);
}
// Access all but the last one to ensure that the last Activity is recycled.
for (int i = 0; i < ActivityAssigner.NUM_WEBAPP_ACTIVITIES - 1; ++i) {
String currentWebappId = BASE_WEBAPP_ID + i;
int activityIndex = testMap.get(currentWebappId);
assigner.markActivityUsed(activityIndex, currentWebappId);
}
// Make sure that the least recently used Activity is repurposed when we run out.
String overflowWebappId = "OVERFLOW_ID";
assertEquals(index, ActivityAssigner.getIndex(overflowWebappId));
int overflowActivityIndex = assigner.assign(overflowWebappId);
String lastAssignedWebappId = BASE_WEBAPP_ID + (ActivityAssigner.NUM_WEBAPP_ACTIVITIES - 1);
int lastAssignedCurrentActivityIndex = assigner.assign(lastAssignedWebappId);
int lastAssignedPreviousActivityIndex = testMap.get(lastAssignedWebappId);
assertEquals("Overflow webapp did not steal the Activity from the other webapp",
lastAssignedPreviousActivityIndex, overflowActivityIndex);
assertNotSame("Webapp did not get reassigned to a new Activity.",
lastAssignedPreviousActivityIndex, lastAssignedCurrentActivityIndex);
checkState(assigner);
}
@UiThreadTest
@SmallTest
@Feature({"WebApk"})
public void testGetIndex() {
String webappId = BASE_WEBAPP_ID;
assertEquals(ActivityAssigner.WEBAPP_ACTIVITY_INDEX, ActivityAssigner.getIndex(webappId));
String webApkId = WebApkConstants.WEBAPK_ID_PREFIX + "id";
assertEquals(ActivityAssigner.WEBAPK_ACTIVITY_INDEX, ActivityAssigner.getIndex(webApkId));
}
/** Saves state indicating that a number of WebappActivities have already been saved out. */
private void createPreferences(int numSavedEntries, int activityTypeIndex) {
mPreferences[activityTypeIndex].clear();
mPreferences[activityTypeIndex].put(
ActivityAssigner.PREF_NUM_SAVED_ENTRIES[activityTypeIndex], numSavedEntries);
for (int i = 0; i < numSavedEntries; ++i) {
String activityIndexKey =
ActivityAssigner.PREF_ACTIVITY_INDEX[activityTypeIndex] + i;
mPreferences[activityTypeIndex].put(activityIndexKey, i);
String webappIdKey = ActivityAssigner.PREF_WEBAPP_ID[activityTypeIndex] + i;
String webappIdValue = BASE_WEBAPP_ID + i;
mPreferences[activityTypeIndex].put(webappIdKey, webappIdValue);
}
}
/** Checks the saved state to make sure it makes sense. */
private void checkState(ActivityAssigner assigner) {
List<ActivityAssigner.ActivityEntry> entries = assigner.getEntries();
int activityTypeIndex = assigner.getActivityTypeIndex();
// Confirm that the right number of entries in memory and in the preferences.
assertEquals(ActivityAssigner.NUM_WEBAPP_ACTIVITIES, entries.size());
assertEquals(ActivityAssigner.NUM_WEBAPP_ACTIVITIES,
(int) (Integer) mPreferences[activityTypeIndex].get(
ActivityAssigner.PREF_NUM_SAVED_ENTRIES[activityTypeIndex]));
// Confirm that the Activity indices go from 0 to NUM_WEBAPP_ACTIVITIES - 1.
HashSet<Integer> assignedActivities = new HashSet<Integer>();
for (ActivityAssigner.ActivityEntry entry : entries) {
assignedActivities.add(entry.mActivityIndex);
}
for (int i = 0; i < ActivityAssigner.NUM_WEBAPP_ACTIVITIES; ++i) {
assertTrue(assignedActivities.contains(i));
}
}
}