Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Unified Diff: chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageManualEvaluationTest.java

Issue 2432593002: [Offline Pages] Add basic evaluation tests and related changes. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageManualEvaluationTest.java
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageManualEvaluationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageManualEvaluationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9659ac0b1c9a892a42c26776b424ae0edad3fe71
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageManualEvaluationTest.java
@@ -0,0 +1,348 @@
+// 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.offlinepages;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.util.LongSparseArray;
+
+import org.chromium.base.Callback;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Manual;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluationBridge;
+import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluationBridge.OfflinePageEvaluationObserver;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.components.offlinepages.BackgroundSavePageResult;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Manual evaluation tests for OfflinePageBridge.SavePageLater.
dougarnett 2016/10/19 16:46:25 What is "manual" about this? Really more of a batc
romax 2016/10/19 19:32:42 Sure... I was thinking this test can only be teste
+ * Testing against a list of top EM urls, try to call SavePageLater on each of the url. And also
+ * record metrics (failure rate, time elapsed etc.) by writing metrics to a file on external
+ * storage.
+ * */
+public class OfflinePageManualEvaluationTest extends ChromeActivityTestCaseBase<ChromeActivity> {
dougarnett 2016/10/19 16:46:25 OfflinePageSavePageLaterEvaluationTest ?
romax 2016/10/19 19:32:42 Done.
+ class TimeDelta {
+ public void setStartTime(Long startTime) {
+ mStartTime = startTime;
+ }
+ public void setEndTime(Long endTime) {
+ mEndTime = endTime;
+ }
+ // Return time delta in milliseconds.
+ public Long getTimeDelta() {
+ return mEndTime - mStartTime;
+ }
+
+ private Long mStartTime, mEndTime;
+ }
+
+ private static final String TAG = "OPManualEvaluation";
+ private static final String NAMESPACE = "async_loading";
+ private static final String NEW_LINE = System.getProperty("line.separator");
+ private static final File INPUT_FILE =
+ new File(Environment.getExternalStorageDirectory(), "paquete/top_em_urls.txt");
+ private static final File OUTPUT_FILE =
+ new File(Environment.getExternalStorageDirectory(), "paquete/offline_eval_results.txt");
+ private static final int TIMEOUT_MS = 5000;
+ private static final String DELIMITER = ";";
+
+ private OfflinePageEvaluationBridge mBridge;
+ private OfflinePageEvaluationObserver mObserver;
+
+ private Semaphore mSem;
+ private List<String> mUrls;
+ private int mCount;
+ private boolean mIsUserRequested;
+
+ private LongSparseArray<OfflinePageItem> mPages;
+ private LongSparseArray<Integer> mRequestStatus;
+ private LongSparseArray<TimeDelta> mRequestTimeDelta;
+ private LongSparseArray<String> mRequestIdToUrl;
+ private OutputStreamWriter mOutput;
+ private Long mTimeoutPerUrlInSeconds = 0L;
+ private File mInputFile = INPUT_FILE;
+ private File mOutputFile = OUTPUT_FILE;
+
+ public OfflinePageManualEvaluationTest() {
+ super(ChromeActivity.class);
+ }
+
+ private void initializeBridgeForProfile(final boolean shortcut) throws InterruptedException {
+ final Semaphore semaphore = new Semaphore(0);
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Profile profile = Profile.getLastUsedProfile();
+ mBridge = OfflinePageEvaluationBridge.getForProfile(profile, shortcut);
+ if (mBridge == null || mBridge.isOfflinePageModelLoaded()) {
+ semaphore.release();
+ return;
+ }
+ mBridge.addObserver(new OfflinePageEvaluationObserver() {
+ @Override
+ public void offlinePageModelLoaded() {
+ semaphore.release();
+ mBridge.removeObserver(this);
+ }
+ });
+ }
+ });
+ assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPages = new LongSparseArray<OfflinePageItem>();
+ mRequestStatus = new LongSparseArray<Integer>();
+ mRequestTimeDelta = new LongSparseArray<TimeDelta>();
+ mRequestIdToUrl = new LongSparseArray<String>();
+ mCount = 0;
+ mIsUserRequested = false;
+ getUrls();
+ assertTrue("URLs weren't loaded.", mUrls != null);
+ assertFalse("No valid URLs in the input file.", mUrls.size() == 0);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ NotificationManager nm =
+ (NotificationManager) ContextUtils.getApplicationContext().getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ nm.cancelAll();
+ }
+
+ @Override
+ public void startMainActivity() throws InterruptedException {
+ startMainActivityOnBlankPage();
+ }
+
+ private BufferedReader getInputStream(File inputFile) throws FileNotFoundException {
+ FileReader fileReader = new FileReader(inputFile);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ return bufferedReader;
+ }
+
+ private OutputStreamWriter getOutputStream(File outputFile) throws IOException {
+ return new FileWriter(outputFile);
+ }
+
+ protected void setUpBridge(final boolean shortcut) throws InterruptedException {
+ initializeBridgeForProfile(shortcut);
+ mObserver = new OfflinePageEvaluationObserver() {
+ public void savePageRequestAdded(SavePageRequest request) {
+ mRequestStatus.put(request.getRequestId(), -1);
+ mRequestIdToUrl.put(request.getRequestId(), request.getUrl());
+
+ TimeDelta delta = new TimeDelta();
+ delta.setStartTime(System.currentTimeMillis());
+ mRequestTimeDelta.put(request.getRequestId(), delta);
+ }
+ public void savePageRequestCompleted(SavePageRequest request, int status) {
+ mRequestTimeDelta.get(request.getRequestId())
+ .setEndTime(System.currentTimeMillis());
+ if (mRequestStatus.get(request.getRequestId()) == -1) {
+ mCount++;
+ }
+ mRequestStatus.put(request.getRequestId(), status);
+ if (mCount == mUrls.size()) {
+ mSem.release();
+ return;
+ }
+ }
+ public void savePageRequestChanged(SavePageRequest request) {}
+ };
+ mBridge.addObserver(mObserver);
+ }
+
+ private void savePageLater(final String url, final String namespace)
+ throws InterruptedException {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBridge.savePageLater(url, namespace, mIsUserRequested);
+ }
+ });
+ }
+
+ private void pushRequestCoordinator() throws InterruptedException {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ boolean res = BackgroundSchedulerBridge.startProcessing(
+ OfflinePageUtils.getDeviceConditions(getActivity().getBaseContext()),
+ new Callback<Boolean>() {
+ @Override
+ public void onResult(Boolean result) {}
+ });
+ }
+ });
+ }
+
+ private void runThroughURLs(List<String> urls) throws InterruptedException, IOException {
+ mSem = new Semaphore(0);
+ // If no timeout value is given, set 30 seconds for each url as default.
+ if (mTimeoutPerUrlInSeconds == 0) {
+ mTimeoutPerUrlInSeconds = 30L;
+ }
+ for (String url : mUrls) {
+ savePageLater(url, NAMESPACE);
+ }
+
+ if (!mSem.tryAcquire(urls.size() * mTimeoutPerUrlInSeconds, TimeUnit.SECONDS)) {
+ writeResults(false);
+ } else {
+ packData();
+ writeResults(true);
+ }
+ }
+
+ private void getUrls() throws IOException, InterruptedException {
+ mUrls = new ArrayList<String>();
+ try {
+ BufferedReader bufferedReader = getInputStream(mInputFile);
+ try {
+ String url;
+ while ((url = bufferedReader.readLine()) != null) {
+ if (!TextUtils.isEmpty(url)) {
+ mUrls.add(url);
+ }
+ }
+ } finally {
+ if (bufferedReader != null) {
+ bufferedReader.close();
+ }
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, e.getMessage(), e);
+ fail(String.format("URL file %s is not found.", mInputFile));
+ }
+ }
+
+ // Translate the int value of status to BackgroundSavePageResult.
+ private String statusToString(int status) {
+ switch (status) {
+ case BackgroundSavePageResult.SUCCESS:
+ return "SUCCESS";
+ case BackgroundSavePageResult.PRERENDER_FAILURE:
+ return "PRERENDER_FAILURE";
+ case BackgroundSavePageResult.PRERENDER_CANCELED:
+ return "PRERENDER_CANCELED";
+ case BackgroundSavePageResult.FOREGROUND_CANCELED:
+ return "FOREGROUND_CANCELED";
+ case BackgroundSavePageResult.SAVE_FAILED:
+ return "SAVE_FAILED";
+ case BackgroundSavePageResult.EXPIRED:
+ return "EXPIRED";
+ case BackgroundSavePageResult.RETRY_COUNT_EXCEEDED:
+ return "RETRY_COUNT_EXCEEDED";
+ case BackgroundSavePageResult.START_COUNT_EXCEEDED:
+ return "START_COUNT_EXCEEDED";
+ case BackgroundSavePageResult.REMOVED:
+ return "REMOVED";
+ case -1:
+ return "NOT COMPLETED";
+ default:
+ return "UNDEFINED STATUS";
+ }
+ }
+
+ private void packData() throws InterruptedException {
+ final Semaphore semaphore = new Semaphore(0);
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBridge.getAllPages(new Callback<List<OfflinePageItem>>() {
+ @Override
+ public void onResult(List<OfflinePageItem> pages) {
+ for (OfflinePageItem page : pages) {
+ mPages.put(page.getOfflineId(), page);
+ }
+ semaphore.release();
+ }
+ });
+ }
+ });
+ assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ private void writeResults(boolean completed) throws IOException, InterruptedException {
+ mOutput = getOutputStream(mOutputFile);
+ packData();
+ try {
+ if (!completed) {
+ mOutput.write("Timed out, incompleted results!" + NEW_LINE);
+ }
+ for (int i = 0; i < mRequestStatus.size(); i++) {
+ long requestId = mRequestStatus.keyAt(i);
+ int status = mRequestStatus.valueAt(i);
+ OfflinePageItem page = mPages.get(requestId);
+ if (page == null) {
+ mOutput.write(mRequestIdToUrl.get(requestId) + DELIMITER
+ + statusToString(status) + NEW_LINE);
+ continue;
+ }
+ mOutput.write(page.getUrl() + DELIMITER + statusToString(status) + DELIMITER
+ + page.getFileSize() / 1000 + " KB" + DELIMITER
+ + mRequestTimeDelta.get(requestId).getTimeDelta() + NEW_LINE);
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, e.getMessage(), e);
+ } finally {
+ if (mOutput != null) {
+ mOutput.close();
+ }
+ }
+ }
+
+ /**
+ * The test would terminate after #urls * timeoutPerUrl even if some urls are being processed.
+ */
+ @Manual
+ public void testFailureRateWithTimeout() throws IOException, InterruptedException {
+ mTimeoutPerUrlInSeconds = (long) (90); // Timeout for a page is 90 seconds.
+ mIsUserRequested = true;
+ mOutputFile = new File(Environment.getExternalStorageDirectory(), "paquete/results1.txt");
+ setUpBridge(true);
+ runThroughURLs(mUrls);
+ }
+
+ @Manual
+ public void testFailureRate() throws IOException, InterruptedException {
+ mTimeoutPerUrlInSeconds = (long) (24 * 60 * 60); // Timeout after 1 day.
+ mOutputFile = new File(Environment.getExternalStorageDirectory(), "paquete/results2.txt");
+ setUpBridge(true);
+ runThroughURLs(mUrls);
+ }
+
+ @Manual
+ public void testFailureRateAuto() throws IOException, InterruptedException {
+ mTimeoutPerUrlInSeconds = (long) (24 * 60 * 60); // Timeout after 1 day.
+ mOutputFile =
+ new File(Environment.getExternalStorageDirectory(), "paquete/results_auto.txt");
+ setUpBridge(false);
+ runThroughURLs(mUrls);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698