OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.offlinepages; | 5 package org.chromium.chrome.browser.offlinepages; |
6 | 6 |
7 import android.app.NotificationManager; | 7 import android.app.NotificationManager; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.os.Environment; | 9 import android.os.Environment; |
10 import android.text.TextUtils; | 10 import android.text.TextUtils; |
11 import android.util.LongSparseArray; | 11 import android.util.LongSparseArray; |
12 | 12 |
| 13 import org.junit.After; |
| 14 import org.junit.Assert; |
| 15 import org.junit.Before; |
| 16 import org.junit.Rule; |
| 17 import org.junit.Test; |
| 18 import org.junit.runner.RunWith; |
| 19 |
13 import org.chromium.base.Callback; | 20 import org.chromium.base.Callback; |
14 import org.chromium.base.ContextUtils; | 21 import org.chromium.base.ContextUtils; |
15 import org.chromium.base.Log; | 22 import org.chromium.base.Log; |
16 import org.chromium.base.ThreadUtils; | 23 import org.chromium.base.ThreadUtils; |
17 import org.chromium.base.test.util.CommandLineFlags; | 24 import org.chromium.base.test.util.CommandLineFlags; |
18 import org.chromium.base.test.util.Manual; | 25 import org.chromium.base.test.util.Manual; |
19 import org.chromium.base.test.util.TimeoutScale; | 26 import org.chromium.base.test.util.TimeoutScale; |
20 import org.chromium.chrome.browser.ChromeActivity; | 27 import org.chromium.chrome.browser.ChromeActivity; |
| 28 import org.chromium.chrome.browser.ChromeSwitches; |
21 import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluation
Bridge; | 29 import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluation
Bridge; |
22 import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluation
Bridge.OfflinePageEvaluationObserver; | 30 import org.chromium.chrome.browser.offlinepages.evaluation.OfflinePageEvaluation
Bridge.OfflinePageEvaluationObserver; |
23 import org.chromium.chrome.browser.profiles.Profile; | 31 import org.chromium.chrome.browser.profiles.Profile; |
24 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | 32 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 33 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
25 import org.chromium.components.offlinepages.BackgroundSavePageResult; | 34 import org.chromium.components.offlinepages.BackgroundSavePageResult; |
26 | 35 |
27 import java.io.BufferedReader; | 36 import java.io.BufferedReader; |
28 import java.io.File; | 37 import java.io.File; |
29 import java.io.FileInputStream; | 38 import java.io.FileInputStream; |
30 import java.io.FileNotFoundException; | 39 import java.io.FileNotFoundException; |
31 import java.io.FileReader; | 40 import java.io.FileReader; |
32 import java.io.FileWriter; | 41 import java.io.FileWriter; |
33 import java.io.IOException; | 42 import java.io.IOException; |
34 import java.io.InputStream; | 43 import java.io.InputStream; |
35 import java.io.OutputStreamWriter; | 44 import java.io.OutputStreamWriter; |
36 | |
37 import java.util.ArrayList; | 45 import java.util.ArrayList; |
38 import java.util.List; | 46 import java.util.List; |
39 import java.util.Properties; | 47 import java.util.Properties; |
40 import java.util.concurrent.CountDownLatch; | 48 import java.util.concurrent.CountDownLatch; |
41 import java.util.concurrent.Semaphore; | 49 import java.util.concurrent.Semaphore; |
42 import java.util.concurrent.TimeUnit; | 50 import java.util.concurrent.TimeUnit; |
43 | 51 |
44 /** | 52 /** |
45 * Tests OfflinePageBridge.SavePageLater over a batch of urls. | 53 * Tests OfflinePageBridge.SavePageLater over a batch of urls. |
46 * Tests against a list of top EM urls, try to call SavePageLater on each of the
url. It also | 54 * Tests against a list of top EM urls, try to call SavePageLater on each of the
url. It also |
47 * record metrics (failure rate, time elapsed etc.) by writing metrics to a file
on external | 55 * record metrics (failure rate, time elapsed etc.) by writing metrics to a file
on external |
48 * storage. This will always use prerenderer. | 56 * storage. This will always use prerenderer. |
49 */ | 57 */ |
50 @CommandLineFlags.Add({"disable-features=BackgroundLoader"}) | 58 @RunWith(ChromeJUnit4ClassRunner.class) |
51 public class OfflinePageSavePageLaterEvaluationTest | 59 @CommandLineFlags.Add({"disable-features=BackgroundLoader", |
52 extends ChromeActivityTestCaseBase<ChromeActivity> { | 60 ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 61 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) |
| 62 public class OfflinePageSavePageLaterEvaluationTest { |
53 /** | 63 /** |
54 * Class which is used to calculate time difference. | 64 * Class which is used to calculate time difference. |
55 */ | 65 */ |
| 66 |
| 67 @Rule |
| 68 public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = |
| 69 new ChromeActivityTestRule<>(ChromeActivity.class); |
| 70 |
56 static class TimeDelta { | 71 static class TimeDelta { |
57 public void setStartTime(Long startTime) { | 72 public void setStartTime(Long startTime) { |
58 mStartTime = startTime; | 73 mStartTime = startTime; |
59 } | 74 } |
60 public void setEndTime(Long endTime) { | 75 public void setEndTime(Long endTime) { |
61 mEndTime = endTime; | 76 mEndTime = endTime; |
62 } | 77 } |
63 // Return time delta in milliseconds. | 78 // Return time delta in milliseconds. |
64 public Long getTimeDelta() { | 79 public Long getTimeDelta() { |
65 return mEndTime - mStartTime; | 80 return mEndTime - mStartTime; |
(...skipping 30 matching lines...) Expand all Loading... |
96 private CountDownLatch mCompletionLatch; | 111 private CountDownLatch mCompletionLatch; |
97 private List<String> mUrls; | 112 private List<String> mUrls; |
98 private int mCount; | 113 private int mCount; |
99 private boolean mIsUserRequested; | 114 private boolean mIsUserRequested; |
100 private boolean mUseTestScheduler; | 115 private boolean mUseTestScheduler; |
101 private int mScheduleBatchSize; | 116 private int mScheduleBatchSize; |
102 private boolean mUseBackgroundLoader; | 117 private boolean mUseBackgroundLoader; |
103 | 118 |
104 private LongSparseArray<RequestMetadata> mRequestMetadata; | 119 private LongSparseArray<RequestMetadata> mRequestMetadata; |
105 | 120 |
106 public OfflinePageSavePageLaterEvaluationTest() { | 121 @Before |
107 super(ChromeActivity.class); | 122 public void setUp() throws Exception { |
108 } | 123 mActivityTestRule.startMainActivityOnBlankPage(); |
109 | |
110 @Override | |
111 protected void setUp() throws Exception { | |
112 super.setUp(); | |
113 mRequestMetadata = new LongSparseArray<RequestMetadata>(); | 124 mRequestMetadata = new LongSparseArray<RequestMetadata>(); |
114 mCount = 0; | 125 mCount = 0; |
115 } | 126 } |
116 | 127 |
117 @Override | 128 @After |
118 protected void tearDown() throws Exception { | 129 public void tearDown() throws Exception { |
119 NotificationManager notificationManager = | 130 NotificationManager notificationManager = |
120 (NotificationManager) ContextUtils.getApplicationContext().getSy
stemService( | 131 (NotificationManager) ContextUtils.getApplicationContext().getSy
stemService( |
121 Context.NOTIFICATION_SERVICE); | 132 Context.NOTIFICATION_SERVICE); |
122 notificationManager.cancelAll(); | 133 notificationManager.cancelAll(); |
123 final Semaphore mClearingSemaphore = new Semaphore(0); | 134 final Semaphore mClearingSemaphore = new Semaphore(0); |
124 ThreadUtils.runOnUiThread(new Runnable() { | 135 ThreadUtils.runOnUiThread(new Runnable() { |
125 @Override | 136 @Override |
126 public void run() { | 137 public void run() { |
127 assert mBridge != null; | 138 assert mBridge != null; |
128 mBridge.getRequestsInQueue(new Callback<SavePageRequest[]>() { | 139 mBridge.getRequestsInQueue(new Callback<SavePageRequest[]>() { |
(...skipping 10 matching lines...) Expand all Loading... |
139 } | 150 } |
140 }); | 151 }); |
141 } | 152 } |
142 }); | 153 }); |
143 } | 154 } |
144 }); | 155 }); |
145 checkTrue(mClearingSemaphore.tryAcquire(REMOVE_REQUESTS_TIMEOUT_MS, Time
Unit.MILLISECONDS), | 156 checkTrue(mClearingSemaphore.tryAcquire(REMOVE_REQUESTS_TIMEOUT_MS, Time
Unit.MILLISECONDS), |
146 "Timed out when clearing remaining requests!"); | 157 "Timed out when clearing remaining requests!"); |
147 mBridge.closeLog(); | 158 mBridge.closeLog(); |
148 mBridge.destroy(); | 159 mBridge.destroy(); |
149 super.tearDown(); | |
150 } | |
151 | |
152 @Override | |
153 public void startMainActivity() throws InterruptedException { | |
154 startMainActivityOnBlankPage(); | |
155 } | 160 } |
156 | 161 |
157 /** | 162 /** |
158 * Get a reader for a given input file path. | 163 * Get a reader for a given input file path. |
159 */ | 164 */ |
160 private BufferedReader getInputStream(String inputFilePath) throws FileNotFo
undException { | 165 private BufferedReader getInputStream(String inputFilePath) throws FileNotFo
undException { |
161 FileReader fileReader = | 166 FileReader fileReader = |
162 new FileReader(new File(Environment.getExternalStorageDirectory(
), inputFilePath)); | 167 new FileReader(new File(Environment.getExternalStorageDirectory(
), inputFilePath)); |
163 BufferedReader bufferedReader = new BufferedReader(fileReader); | 168 BufferedReader bufferedReader = new BufferedReader(fileReader); |
164 return bufferedReader; | 169 return bufferedReader; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 private void log(String tag, String format, Object... args) { | 210 private void log(String tag, String format, Object... args) { |
206 mBridge.log(tag, String.format(format, args)); | 211 mBridge.log(tag, String.format(format, args)); |
207 } | 212 } |
208 | 213 |
209 /** | 214 /** |
210 * Assert the condition is true, otherwise abort the test and log. | 215 * Assert the condition is true, otherwise abort the test and log. |
211 */ | 216 */ |
212 private void checkTrue(boolean condition, String message) { | 217 private void checkTrue(boolean condition, String message) { |
213 if (!condition) { | 218 if (!condition) { |
214 log(TAG, message); | 219 log(TAG, message); |
215 fail(); | 220 Assert.fail(); |
216 } | 221 } |
217 } | 222 } |
218 | 223 |
219 /** | 224 /** |
220 * Initializes the evaluation bridge which will be used. | 225 * Initializes the evaluation bridge which will be used. |
221 * @param useCustomScheduler True if customized scheduler (the one with imme
diate scheduling) | 226 * @param useCustomScheduler True if customized scheduler (the one with imme
diate scheduling) |
222 * will be used. False otherwise. | 227 * will be used. False otherwise. |
223 * @param useBackgroundLoader True if use background loader. False if use pr
erenderer. | 228 * @param useBackgroundLoader True if use background loader. False if use pr
erenderer. |
224 */ | 229 */ |
225 private void initializeBridgeForProfile(final boolean useTestingScheduler, | 230 private void initializeBridgeForProfile(final boolean useTestingScheduler, |
226 final boolean useBackgroundLoader) throws InterruptedException { | 231 final boolean useBackgroundLoader) throws InterruptedException { |
227 final Semaphore semaphore = new Semaphore(0); | 232 final Semaphore semaphore = new Semaphore(0); |
228 ThreadUtils.runOnUiThread(new Runnable() { | 233 ThreadUtils.runOnUiThread(new Runnable() { |
229 @Override | 234 @Override |
230 public void run() { | 235 public void run() { |
231 Profile profile = Profile.getLastUsedProfile(); | 236 Profile profile = Profile.getLastUsedProfile(); |
232 mBridge = new OfflinePageEvaluationBridge( | 237 mBridge = new OfflinePageEvaluationBridge( |
233 profile, useTestingScheduler, useBackgroundLoader); | 238 profile, useTestingScheduler, useBackgroundLoader); |
234 if (mBridge == null) { | 239 if (mBridge == null) { |
235 fail("OfflinePageEvaluationBridge initialization failed!"); | 240 Assert.fail("OfflinePageEvaluationBridge initialization fail
ed!"); |
236 return; | 241 return; |
237 } | 242 } |
238 if (mBridge.isOfflinePageModelLoaded()) { | 243 if (mBridge.isOfflinePageModelLoaded()) { |
239 semaphore.release(); | 244 semaphore.release(); |
240 return; | 245 return; |
241 } | 246 } |
242 mBridge.addObserver(new OfflinePageEvaluationObserver() { | 247 mBridge.addObserver(new OfflinePageEvaluationObserver() { |
243 @Override | 248 @Override |
244 public void offlinePageModelLoaded() { | 249 public void offlinePageModelLoaded() { |
245 semaphore.release(); | 250 semaphore.release(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 ThreadUtils.runOnUiThread(new Runnable() { | 330 ThreadUtils.runOnUiThread(new Runnable() { |
326 @Override | 331 @Override |
327 public void run() { | 332 public void run() { |
328 mBridge.savePageLater(url, namespace, mIsUserRequested); | 333 mBridge.savePageLater(url, namespace, mIsUserRequested); |
329 } | 334 } |
330 }); | 335 }); |
331 } | 336 } |
332 | 337 |
333 private void processUrls(List<String> urls) throws InterruptedException, IOE
xception { | 338 private void processUrls(List<String> urls) throws InterruptedException, IOE
xception { |
334 if (mBridge == null) { | 339 if (mBridge == null) { |
335 fail("Test initialization error, aborting. No results would be writt
en."); | 340 Assert.fail("Test initialization error, aborting. No results would b
e written."); |
336 return; | 341 return; |
337 } | 342 } |
338 int count = 0; | 343 int count = 0; |
339 log(TAG_PROGRESS, "# of Urls in file: " + mUrls.size()); | 344 log(TAG_PROGRESS, "# of Urls in file: " + mUrls.size()); |
340 for (int i = 0; i < mUrls.size(); i++) { | 345 for (int i = 0; i < mUrls.size(); i++) { |
341 savePageLater(mUrls.get(i), NAMESPACE); | 346 savePageLater(mUrls.get(i), NAMESPACE); |
342 count++; | 347 count++; |
343 if (count == mScheduleBatchSize || i == mUrls.size() - 1) { | 348 if (count == mScheduleBatchSize || i == mUrls.size() - 1) { |
344 count = 0; | 349 count = 0; |
345 mCompletionLatch = new CountDownLatch(1); | 350 mCompletionLatch = new CountDownLatch(1); |
(...skipping 16 matching lines...) Expand all Loading... |
362 mUrls.add(url); | 367 mUrls.add(url); |
363 } | 368 } |
364 } | 369 } |
365 } finally { | 370 } finally { |
366 if (bufferedReader != null) { | 371 if (bufferedReader != null) { |
367 bufferedReader.close(); | 372 bufferedReader.close(); |
368 } | 373 } |
369 } | 374 } |
370 } catch (FileNotFoundException e) { | 375 } catch (FileNotFoundException e) { |
371 Log.e(TAG, e.getMessage(), e); | 376 Log.e(TAG, e.getMessage(), e); |
372 fail(String.format("URL file %s is not found.", inputFilePath)); | 377 Assert.fail(String.format("URL file %s is not found.", inputFilePath
)); |
373 } | 378 } |
374 } | 379 } |
375 | 380 |
376 // Translate the int value of status to BackgroundSavePageResult. | 381 // Translate the int value of status to BackgroundSavePageResult. |
377 private String statusToString(int status) { | 382 private String statusToString(int status) { |
378 switch (status) { | 383 switch (status) { |
379 case BackgroundSavePageResult.SUCCESS: | 384 case BackgroundSavePageResult.SUCCESS: |
380 return "SUCCESS"; | 385 return "SUCCESS"; |
381 case BackgroundSavePageResult.LOADING_FAILURE: | 386 case BackgroundSavePageResult.LOADING_FAILURE: |
382 return "LOADING_FAILURE"; | 387 return "LOADING_FAILURE"; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 File configFile = new File(Environment.getExternalStorageDirectory()
, CONFIG_FILE_PATH); | 495 File configFile = new File(Environment.getExternalStorageDirectory()
, CONFIG_FILE_PATH); |
491 inputStream = new FileInputStream(configFile); | 496 inputStream = new FileInputStream(configFile); |
492 properties.load(inputStream); | 497 properties.load(inputStream); |
493 mIsUserRequested = Boolean.parseBoolean(properties.getProperty("IsUs
erRequested")); | 498 mIsUserRequested = Boolean.parseBoolean(properties.getProperty("IsUs
erRequested")); |
494 mUseTestScheduler = Boolean.parseBoolean(properties.getProperty("Use
TestScheduler")); | 499 mUseTestScheduler = Boolean.parseBoolean(properties.getProperty("Use
TestScheduler")); |
495 mScheduleBatchSize = Integer.parseInt(properties.getProperty("Schedu
leBatchSize")); | 500 mScheduleBatchSize = Integer.parseInt(properties.getProperty("Schedu
leBatchSize")); |
496 mUseBackgroundLoader = | 501 mUseBackgroundLoader = |
497 Boolean.parseBoolean(properties.getProperty("UseBackgroundLo
ader")); | 502 Boolean.parseBoolean(properties.getProperty("UseBackgroundLo
ader")); |
498 } catch (FileNotFoundException e) { | 503 } catch (FileNotFoundException e) { |
499 Log.e(TAG, e.getMessage(), e); | 504 Log.e(TAG, e.getMessage(), e); |
500 fail(String.format( | 505 Assert.fail(String.format( |
501 "Config file %s is not found, aborting the test.", CONFIG_FI
LE_PATH)); | 506 "Config file %s is not found, aborting the test.", CONFIG_FI
LE_PATH)); |
502 } catch (NumberFormatException e) { | 507 } catch (NumberFormatException e) { |
503 Log.e(TAG, e.getMessage(), e); | 508 Log.e(TAG, e.getMessage(), e); |
504 fail("Error parsing config file, aborting test."); | 509 Assert.fail("Error parsing config file, aborting test."); |
505 } finally { | 510 } finally { |
506 if (inputStream != null) { | 511 if (inputStream != null) { |
507 inputStream.close(); | 512 inputStream.close(); |
508 } | 513 } |
509 } | 514 } |
510 } | 515 } |
511 | 516 |
512 /** | 517 /** |
513 * The test is the entry point for all kinds of testing of SavePageLater. | 518 * The test is the entry point for all kinds of testing of SavePageLater. |
514 * It is encouraged to use run_offline_page_evaluation_test.py to run this t
est. | 519 * It is encouraged to use run_offline_page_evaluation_test.py to run this t
est. |
515 * TimeoutScale is set to 4, in case we hit the hard limit for @Manual tests
(10 hours) | 520 * TimeoutScale is set to 4, in case we hit the hard limit for @Manual tests
(10 hours) |
516 * and gets killed. It expand the timeout to 10 * 4 hours. | 521 * and gets killed. It expand the timeout to 10 * 4 hours. |
517 * We won't be treating svelte devices differently so enable the feature whi
ch would let | 522 * We won't be treating svelte devices differently so enable the feature whi
ch would let |
518 * immediate processing also works on svelte devices. This flag will *not* a
ffect normal | 523 * immediate processing also works on svelte devices. This flag will *not* a
ffect normal |
519 * devices. | 524 * devices. |
520 */ | 525 */ |
| 526 @Test |
521 @Manual | 527 @Manual |
522 @TimeoutScale(4) | 528 @TimeoutScale(4) |
523 @CommandLineFlags | 529 @CommandLineFlags.Add({"enable-features=OfflinePagesSvelteConcurrentLoading"
}) |
524 .Add({"enable-features=OfflinePagesSvelteConcurrentLoading"}) | |
525 @CommandLineFlags.Remove({"disable-features=OfflinePagesSvelteConcurrentLoad
ing"}) | 530 @CommandLineFlags.Remove({"disable-features=OfflinePagesSvelteConcurrentLoad
ing"}) |
526 public void testFailureRate() throws IOException, InterruptedException { | 531 public void testFailureRate() throws IOException, InterruptedException { |
527 parseConfigFile(); | 532 parseConfigFile(); |
528 setUpIOAndBridge(mUseTestScheduler, mUseBackgroundLoader); | 533 setUpIOAndBridge(mUseTestScheduler, mUseBackgroundLoader); |
529 processUrls(mUrls); | 534 processUrls(mUrls); |
530 } | 535 } |
531 | 536 |
532 /** | 537 /** |
533 * Runs testFailureRate with background loader enabled. | 538 * Runs testFailureRate with background loader enabled. |
534 * We won't be treating svelte devices differently so enable the feature whi
ch would let | 539 * We won't be treating svelte devices differently so enable the feature whi
ch would let |
535 * immediate processing also works on svelte devices. This flag will *not* a
ffect normal | 540 * immediate processing also works on svelte devices. This flag will *not* a
ffect normal |
536 * devices. | 541 * devices. |
537 */ | 542 */ |
| 543 @Test |
538 @Manual | 544 @Manual |
539 @TimeoutScale(4) | 545 @TimeoutScale(4) |
540 @CommandLineFlags | 546 @CommandLineFlags.Add({"enable-features=BackgroundLoaderOfflinePagesSvelteCo
ncurrentLoading"}) |
541 .Add({"enable-features=BackgroundLoader,OfflinePagesSvelteConcurrent
Loading"}) | 547 @CommandLineFlags.Remove({ |
542 @CommandLineFlags | 548 "disable-features=BackgroundLoaderOfflinePagesSvelteConcurrentLoadin
g"}) |
543 .Remove({"disable-features=BackgroundLoader,OfflinePagesSvelteConcur
rentLoading"}) | |
544 public void testBackgroundLoaderFailureRate() throws IOException, Interrupte
dException { | 549 public void testBackgroundLoaderFailureRate() throws IOException, Interrupte
dException { |
545 testFailureRate(); | 550 testFailureRate(); |
546 } | 551 } |
547 } | 552 } |
OLD | NEW |