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

Side by Side Diff: components/cronet/android/test/javatests/src/org/chromium/net/NQETest.java

Issue 2416473004: Add functionality for embedders to configure NQE (Closed)
Patch Set: ps Created 3 years, 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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.net; 5 package org.chromium.net;
6 6
7 import android.os.StrictMode; 7 import android.os.StrictMode;
8 import android.support.test.filters.SmallTest; 8 import android.support.test.filters.SmallTest;
9 9
10 import org.json.JSONObject;
11
10 import org.chromium.base.Log; 12 import org.chromium.base.Log;
11 import org.chromium.base.annotations.JNINamespace; 13 import org.chromium.base.annotations.JNINamespace;
12 import org.chromium.base.annotations.SuppressFBWarnings; 14 import org.chromium.base.annotations.SuppressFBWarnings;
13 import org.chromium.base.test.util.DisabledTest;
14 import org.chromium.base.test.util.Feature; 15 import org.chromium.base.test.util.Feature;
15 import org.chromium.base.test.util.MetricsUtils.HistogramDelta; 16 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
16 import org.chromium.net.MetricsTestUtil.TestExecutor; 17 import org.chromium.net.MetricsTestUtil.TestExecutor;
17 import org.chromium.net.test.EmbeddedTestServer; 18 import org.chromium.net.test.EmbeddedTestServer;
18 19
19 import java.io.File; 20 import java.io.File;
20 import java.io.FileInputStream; 21 import java.io.FileInputStream;
21 import java.io.FileNotFoundException; 22 import java.io.FileNotFoundException;
22 import java.io.IOException; 23 import java.io.IOException;
23 import java.util.concurrent.Executor; 24 import java.util.concurrent.Executor;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 102
102 @SmallTest 103 @SmallTest
103 @Feature({"Cronet"}) 104 @Feature({"Cronet"})
104 public void testListenerRemoved() throws Exception { 105 public void testListenerRemoved() throws Exception {
105 ExperimentalCronetEngine.Builder cronetEngineBuilder = 106 ExperimentalCronetEngine.Builder cronetEngineBuilder =
106 new ExperimentalCronetEngine.Builder(getContext()); 107 new ExperimentalCronetEngine.Builder(getContext());
107 TestExecutor networkQualityExecutor = new TestExecutor(); 108 TestExecutor networkQualityExecutor = new TestExecutor();
108 TestNetworkQualityRttListener rttListener = 109 TestNetworkQualityRttListener rttListener =
109 new TestNetworkQualityRttListener(networkQualityExecutor); 110 new TestNetworkQualityRttListener(networkQualityExecutor);
110 cronetEngineBuilder.enableNetworkQualityEstimator(true); 111 cronetEngineBuilder.enableNetworkQualityEstimator(true);
112
113 JSONObject experimentalOptions = new JSONObject();
mgersh 2017/06/28 18:26:50 These two lines shouldn't be necessary.
tbansal1 2017/06/29 01:17:58 Done.
114 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString( ));
111 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( ); 115 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( );
112 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, fals e); 116 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, fals e);
113 117
114 cronetEngine.addRttListener(rttListener); 118 cronetEngine.addRttListener(rttListener);
115 cronetEngine.removeRttListener(rttListener); 119 cronetEngine.removeRttListener(rttListener);
116 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 120 TestUrlRequestCallback callback = new TestUrlRequestCallback();
117 UrlRequest.Builder builder = 121 UrlRequest.Builder builder =
118 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getEx ecutor()); 122 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getEx ecutor());
119 UrlRequest urlRequest = builder.build(); 123 UrlRequest urlRequest = builder.build();
120 urlRequest.start(); 124 urlRequest.start();
121 callback.blockForDone(); 125 callback.blockForDone();
122 networkQualityExecutor.runAllTasks(); 126 networkQualityExecutor.runAllTasks();
123 assertEquals(0, rttListener.rttObservationCount()); 127 assertEquals(0, rttListener.rttObservationCount());
124 cronetEngine.shutdown(); 128 cronetEngine.shutdown();
125 } 129 }
126 130
127 // Returns whether a file contains a particular string. 131 // Returns whether a file contains a particular string.
128 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") 132 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE")
129 private boolean fileContainsString(String filename, String content) throws I OException { 133 private boolean prefsFileContainsString(String content) throws IOException {
130 File file = new File(getTestStorage(getContext()) + "/prefs/" + filename ); 134 File file = new File(getTestStorage(getContext()) + "/prefs/local_prefs. json");
131 FileInputStream fileInputStream = new FileInputStream(file); 135 FileInputStream fileInputStream = new FileInputStream(file);
132 byte[] data = new byte[(int) file.length()]; 136 byte[] data = new byte[(int) file.length()];
133 fileInputStream.read(data); 137 fileInputStream.read(data);
134 fileInputStream.close(); 138 fileInputStream.close();
135 return new String(data, "UTF-8").contains(content); 139 return new String(data, "UTF-8").contains(content);
136 } 140 }
137 141
142 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE")
143 private boolean deletePrefsFile() throws Exception {
144 File file = new File(getTestStorage(getContext()) + "/prefs/local_prefs. json");
145 if (file.exists()) {
146 return file.delete();
147 }
148 return true;
149 }
150
138 @SmallTest 151 @SmallTest
139 @Feature({"Cronet"}) 152 @Feature({"Cronet"})
140 @DisabledTest(message = "Disabled due to flaky assert. See crbug.com/710626" )
141 public void testQuicDisabled() throws Exception { 153 public void testQuicDisabled() throws Exception {
142 ExperimentalCronetEngine.Builder cronetEngineBuilder = 154 ExperimentalCronetEngine.Builder cronetEngineBuilder =
143 new ExperimentalCronetEngine.Builder(getContext()); 155 new ExperimentalCronetEngine.Builder(getContext());
144 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; 156 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0;
145 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory()); 157 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory());
146 TestNetworkQualityRttListener rttListener = 158 TestNetworkQualityRttListener rttListener =
147 new TestNetworkQualityRttListener(listenersExecutor); 159 new TestNetworkQualityRttListener(listenersExecutor);
148 TestNetworkQualityThroughputListener throughputListener = 160 TestNetworkQualityThroughputListener throughputListener =
149 new TestNetworkQualityThroughputListener(listenersExecutor); 161 new TestNetworkQualityThroughputListener(listenersExecutor);
162
163 JSONObject experimentalOptions = new JSONObject();
mgersh 2017/06/28 18:26:50 Also shouldn't be necessary.
tbansal1 2017/06/29 01:17:58 Done.
164 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString( ));
165
150 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false); 166 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false);
151 cronetEngineBuilder.setStoragePath(getTestStorage(getContext())); 167 cronetEngineBuilder.setStoragePath(getTestStorage(getContext()));
152 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( ); 168 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( );
153 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, true ); 169 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, true );
154 170
155 cronetEngine.addRttListener(rttListener); 171 cronetEngine.addRttListener(rttListener);
156 cronetEngine.addThroughputListener(throughputListener); 172 cronetEngine.addThroughputListener(throughputListener);
157 173
158 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.Write Count", 1); 174 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.Write Count", 1);
159 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check. 175 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // estimates are available. 223 // estimates are available.
208 assertTrue(cronetEngine.getHttpRttMs() >= 0); 224 assertTrue(cronetEngine.getHttpRttMs() >= 0);
209 assertTrue(cronetEngine.getTransportRttMs() >= 0); 225 assertTrue(cronetEngine.getTransportRttMs() >= 0);
210 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0); 226 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0);
211 227
212 // Verify that the cached estimates were written to the prefs. 228 // Verify that the cached estimates were written to the prefs.
213 while (true) { 229 while (true) {
214 Log.i(TAG, "Still waiting for pref file update....."); 230 Log.i(TAG, "Still waiting for pref file update.....");
215 Thread.sleep(12000); 231 Thread.sleep(12000);
216 try { 232 try {
217 if (fileContainsString("local_prefs.json", "network_qualities")) { 233 if (prefsFileContainsString("network_qualities")) {
218 break; 234 break;
219 } 235 }
220 } catch (FileNotFoundException e) { 236 } catch (FileNotFoundException e) {
221 // Ignored this exception since the file will only be created wh en updates are 237 // Ignored this exception since the file will only be created wh en updates are
222 // flushed to the disk. 238 // flushed to the disk.
223 } 239 }
224 } 240 }
225 assertTrue(fileContainsString("local_prefs.json", "network_qualities")); 241 assertTrue(prefsFileContainsString("network_qualities"));
226 242
227 cronetEngine.shutdown(); 243 cronetEngine.shutdown();
228 assertTrue(writeCountHistogram.getDelta() > 0); 244 assertTrue(writeCountHistogram.getDelta() > 0);
229 } 245 }
246
247 @SmallTest
248 @Feature({"Cronet"})
249 public void testPrefsWriteRead() throws Exception {
250 deletePrefsFile();
mgersh 2017/06/28 18:26:50 CronetTestBase() does this for you, so no need for
tbansal1 2017/06/29 01:17:58 Added comment.
mgersh 2017/06/29 19:02:31 Oh, I see what's going on. You're running into crb
tbansal1 2017/06/29 22:45:05 Done.
251
252 // When the loop is run for the first time, network quality is written t o the disk. The
253 // test verifies that in the next loop, the network quality is read back .
254 for (int i = 0; i <= 1; ++i) {
255 ExperimentalCronetEngine.Builder cronetEngineBuilder =
256 new ExperimentalCronetEngine.Builder(getContext());
257 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0;
258 Executor listenersExecutor =
259 Executors.newSingleThreadExecutor(new ExecutorThreadFactory( ));
260 TestNetworkQualityRttListener rttListener =
261 new TestNetworkQualityRttListener(listenersExecutor);
262 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2( true).enableQuic(
263 false);
264 cronetEngineBuilder.setStoragePath(getTestStorage(getContext()));
265
266 JSONObject nqeOptions =
267 new JSONObject().put("persistent_cache_reading_enabled", "tr ue");
268 JSONObject experimentalOptions =
269 new JSONObject().put("NetworkQualityEstimator", nqeOptions);
270
271 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toStr ing());
272 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.bu ild();
273 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, true);
274 cronetEngine.addRttListener(rttListener);
275
276 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.W riteCount", 1);
277 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check.
278
279 HistogramDelta readCountHistogram = new HistogramDelta("NQE.Prefs.Re adCount", 1);
280 assertEquals(0, readCountHistogram.getDelta()); // Sanity check.
281
282 HistogramDelta readPrefsSizeHistogram = new HistogramDelta("NQE.Pref s.ReadSize", 1);
283 assertEquals(0, readPrefsSizeHistogram.getDelta()); // Sanity check.
284
285 // NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE: 3
286 HistogramDelta cachedRttHistogram = new HistogramDelta("NQE.RTT.Obse rvationSource", 3);
287 assertEquals(0, cachedRttHistogram.getDelta()); // Sanity check.
288
289 TestUrlRequestCallback callback = new TestUrlRequestCallback();
290 UrlRequest.Builder builder =
291 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.g etExecutor());
292 UrlRequest urlRequest = builder.build();
293 urlRequest.start();
294 callback.blockForDone();
295
296 // Wait for RTT observation (at the URL request layer) to be posted.
297 rttListener.waitUntilFirstUrlRequestRTTReceived();
298
299 // Prefs must be read at startup.
300 assertTrue(readCountHistogram.getDelta() > 0);
301
302 // Check RTT observation count after throughput observation has been received. This
303 // ensures
304 // that executor has finished posting the RTT observation to the RTT listeners.
305 assertTrue(rttListener.rttObservationCount() > 0);
306
307 // Verify that effective connection type callback is received and
308 // effective connection type is correctly set.
309 assertTrue(cronetEngine.getEffectiveConnectionType()
310 != EffectiveConnectionType.TYPE_UNKNOWN);
311
312 if (i == 0) {
313 // Verify that the cached estimates were written to the prefs.
314 while (true) {
mgersh 2017/06/28 18:26:50 If you do this after cronetEngine.shutdown(), you
tbansal1 2017/06/29 01:17:58 Cool. Done.
315 Log.i(TAG, "Still waiting for pref file update.....");
316 Thread.sleep(12000);
317 try {
318 if (prefsFileContainsString("network_qualities")) {
319 break;
320 }
321 } catch (FileNotFoundException e) {
322 // Ignored this exception since the file will only be cr eated when updates
323 // are flushed to the disk.
324 }
325 }
326 assertTrue(prefsFileContainsString("network_qualities"));
327 }
328
329 cronetEngine.shutdown();
330 // Stored network quality in the pref should be read in the second i teration.
331 assertEquals(readPrefsSizeHistogram.getDelta() > 0, i > 0);
332 assertEquals(cachedRttHistogram.getDelta() > 0, i > 0);
333 }
334 }
335
336 @SmallTest
337 @Feature({"Cronet"})
338 public void testQuicDisabledWithParams() throws Exception {
339 ExperimentalCronetEngine.Builder cronetEngineBuilder =
340 new ExperimentalCronetEngine.Builder(getContext());
341 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory());
342 TestNetworkQualityRttListener rttListener =
343 new TestNetworkQualityRttListener(listenersExecutor);
344 TestNetworkQualityThroughputListener throughputListener =
345 new TestNetworkQualityThroughputListener(listenersExecutor);
346
347 // Force the effective connection type to "2G".
348 JSONObject nqeOptions = new JSONObject().put("force_effective_connection _type", "Slow-2G");
349 // Add one more extra param two times to ensure robustness.
350 nqeOptions.put("some_other_param_1", "value1");
351 nqeOptions.put("some_other_param_2", "value2");
352 JSONObject experimentalOptions =
353 new JSONObject().put("NetworkQualityEstimator", nqeOptions);
354 experimentalOptions.put("SomeOtherFieldTrialName", new JSONObject());
355
356 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false);
357 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString( ));
358 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( );
359 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, fals e);
360
361 cronetEngine.addRttListener(rttListener);
362 cronetEngine.addThroughputListener(throughputListener);
363
364 TestUrlRequestCallback callback = new TestUrlRequestCallback();
365 UrlRequest.Builder builder =
366 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getEx ecutor());
367 UrlRequest urlRequest = builder.build();
368 urlRequest.start();
369 callback.blockForDone();
370
371 // Throughput observation is posted to the network quality estimator on the network thread
372 // after the UrlRequest is completed. The observations are then eventual ly posted to
373 // throughput listeners on the executor provided to network quality.
374 throughputListener.waitUntilFirstThroughputObservationReceived();
375
376 // Wait for RTT observation (at the URL request layer) to be posted.
377 rttListener.waitUntilFirstUrlRequestRTTReceived();
378
379 assertTrue(throughputListener.throughputObservationCount() > 0);
380
381 // Check RTT observation count after throughput observation has been rec eived. This ensures
382 // that executor has finished posting the RTT observation to the RTT lis teners.
383 assertTrue(rttListener.rttObservationCount() > 0);
384
385 // NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST
386 assertTrue(rttListener.rttObservationCount(0) > 0);
387
388 // NETWORK_QUALITY_OBSERVATION_SOURCE_TCP
389 assertTrue(rttListener.rttObservationCount(1) > 0);
390
391 // NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC
392 assertEquals(0, rttListener.rttObservationCount(2));
393
394 // Verify that the listeners were notified on the expected thread.
395 assertEquals(mNetworkQualityThread, rttListener.getThread());
396 assertEquals(mNetworkQualityThread, throughputListener.getThread());
397
398 // Verify that effective connection type callback is received and effect ive connection type
399 // is correctly set to the forced value. This also verifies that the con figuration params
400 // from Cronet embedders were correctly read by NetworkQualityEstimator.
401 assertEquals(
402 EffectiveConnectionType.TYPE_SLOW_2G, cronetEngine.getEffectiveC onnectionType());
403
404 cronetEngine.shutdown();
405 }
230 } 406 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698