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