OLD | NEW |
---|---|
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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 UrlRequest urlRequest = builder.build(); | 120 UrlRequest urlRequest = builder.build(); |
120 urlRequest.start(); | 121 urlRequest.start(); |
121 callback.blockForDone(); | 122 callback.blockForDone(); |
122 networkQualityExecutor.runAllTasks(); | 123 networkQualityExecutor.runAllTasks(); |
123 assertEquals(0, rttListener.rttObservationCount()); | 124 assertEquals(0, rttListener.rttObservationCount()); |
124 cronetEngine.shutdown(); | 125 cronetEngine.shutdown(); |
125 } | 126 } |
126 | 127 |
127 // Returns whether a file contains a particular string. | 128 // Returns whether a file contains a particular string. |
128 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") | 129 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") |
129 private boolean fileContainsString(String filename, String content) throws I OException { | 130 private boolean prefsFileContainsString(String content) throws IOException { |
130 File file = new File(getTestStorage(getContext()) + "/prefs/" + filename ); | 131 File file = new File(getTestStorage(getContext()) + "/prefs/local_prefs. json"); |
131 FileInputStream fileInputStream = new FileInputStream(file); | 132 FileInputStream fileInputStream = new FileInputStream(file); |
132 byte[] data = new byte[(int) file.length()]; | 133 byte[] data = new byte[(int) file.length()]; |
133 fileInputStream.read(data); | 134 fileInputStream.read(data); |
134 fileInputStream.close(); | 135 fileInputStream.close(); |
135 return new String(data, "UTF-8").contains(content); | 136 return new String(data, "UTF-8").contains(content); |
136 } | 137 } |
137 | 138 |
139 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") | |
140 private boolean deletePrefsFile() throws Exception { | |
141 File file = new File(getTestStorage(getContext()) + "/prefs/local_prefs. json"); | |
142 if (file.exists()) { | |
143 return file.delete(); | |
144 } | |
145 return true; | |
146 } | |
147 | |
138 @SmallTest | 148 @SmallTest |
139 @Feature({"Cronet"}) | 149 @Feature({"Cronet"}) |
140 @DisabledTest(message = "Disabled due to flaky assert. See crbug.com/710626" ) | |
141 public void testQuicDisabled() throws Exception { | 150 public void testQuicDisabled() throws Exception { |
142 ExperimentalCronetEngine.Builder cronetEngineBuilder = | 151 ExperimentalCronetEngine.Builder cronetEngineBuilder = |
143 new ExperimentalCronetEngine.Builder(getContext()); | 152 new ExperimentalCronetEngine.Builder(getContext()); |
144 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; | 153 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; |
145 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory()); | 154 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory()); |
146 TestNetworkQualityRttListener rttListener = | 155 TestNetworkQualityRttListener rttListener = |
147 new TestNetworkQualityRttListener(listenersExecutor); | 156 new TestNetworkQualityRttListener(listenersExecutor); |
148 TestNetworkQualityThroughputListener throughputListener = | 157 TestNetworkQualityThroughputListener throughputListener = |
149 new TestNetworkQualityThroughputListener(listenersExecutor); | 158 new TestNetworkQualityThroughputListener(listenersExecutor); |
150 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false); | 159 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 // estimates are available. | 216 // estimates are available. |
208 assertTrue(cronetEngine.getHttpRttMs() >= 0); | 217 assertTrue(cronetEngine.getHttpRttMs() >= 0); |
209 assertTrue(cronetEngine.getTransportRttMs() >= 0); | 218 assertTrue(cronetEngine.getTransportRttMs() >= 0); |
210 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0); | 219 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0); |
211 | 220 |
212 // Verify that the cached estimates were written to the prefs. | 221 // Verify that the cached estimates were written to the prefs. |
213 while (true) { | 222 while (true) { |
214 Log.i(TAG, "Still waiting for pref file update....."); | 223 Log.i(TAG, "Still waiting for pref file update....."); |
215 Thread.sleep(12000); | 224 Thread.sleep(12000); |
216 try { | 225 try { |
217 if (fileContainsString("local_prefs.json", "network_qualities")) { | 226 if (prefsFileContainsString("network_qualities")) { |
218 break; | 227 break; |
219 } | 228 } |
220 } catch (FileNotFoundException e) { | 229 } catch (FileNotFoundException e) { |
221 // Ignored this exception since the file will only be created wh en updates are | 230 // Ignored this exception since the file will only be created wh en updates are |
222 // flushed to the disk. | 231 // flushed to the disk. |
223 } | 232 } |
224 } | 233 } |
225 assertTrue(fileContainsString("local_prefs.json", "network_qualities")); | 234 assertTrue(prefsFileContainsString("network_qualities")); |
226 | 235 |
227 cronetEngine.shutdown(); | 236 cronetEngine.shutdown(); |
228 assertTrue(writeCountHistogram.getDelta() > 0); | 237 assertTrue(writeCountHistogram.getDelta() > 0); |
229 } | 238 } |
239 | |
240 @SmallTest | |
241 @Feature({"Cronet"}) | |
242 public void testPrefsWriteRead() throws Exception { | |
243 // Clear the prefs file when the test is ran again. See | |
244 // https://bugs.chromium.org/p/chromium/issues/detail?id=569589 for deta ils. | |
245 deletePrefsFile(); | |
246 | |
247 // When the loop is run for the first time, network quality is written t o the disk. The | |
248 // test verifies that in the next loop, the network quality is read back . | |
249 for (int i = 0; i <= 1; ++i) { | |
250 ExperimentalCronetEngine.Builder cronetEngineBuilder = | |
251 new ExperimentalCronetEngine.Builder(getContext()); | |
252 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; | |
253 Executor listenersExecutor = | |
254 Executors.newSingleThreadExecutor(new ExecutorThreadFactory( )); | |
255 TestNetworkQualityRttListener rttListener = | |
256 new TestNetworkQualityRttListener(listenersExecutor); | |
257 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2( true).enableQuic( | |
258 false); | |
259 cronetEngineBuilder.setStoragePath(getTestStorage(getContext())); | |
260 | |
261 JSONObject nqeOptions = new JSONObject().put("persistent_cache_readi ng_enabled", true); | |
262 JSONObject experimentalOptions = | |
263 new JSONObject().put("NetworkQualityEstimator", nqeOptions); | |
264 | |
265 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toStr ing()); | |
266 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.bu ild(); | |
267 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, true); | |
268 cronetEngine.addRttListener(rttListener); | |
269 | |
270 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.W riteCount", 1); | |
271 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check. | |
272 | |
273 HistogramDelta readCountHistogram = new HistogramDelta("NQE.Prefs.Re adCount", 1); | |
274 assertEquals(0, readCountHistogram.getDelta()); // Sanity check. | |
275 | |
276 HistogramDelta readPrefsSizeHistogram = new HistogramDelta("NQE.Pref s.ReadSize", 1); | |
277 assertEquals(0, readPrefsSizeHistogram.getDelta()); // Sanity check. | |
278 | |
279 // NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE: 3 | |
280 HistogramDelta cachedRttHistogram = new HistogramDelta("NQE.RTT.Obse rvationSource", 3); | |
281 assertEquals(0, cachedRttHistogram.getDelta()); // Sanity check. | |
282 | |
283 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | |
284 UrlRequest.Builder builder = | |
285 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.g etExecutor()); | |
286 UrlRequest urlRequest = builder.build(); | |
287 urlRequest.start(); | |
288 callback.blockForDone(); | |
289 | |
290 // Wait for RTT observation (at the URL request layer) to be posted. | |
291 rttListener.waitUntilFirstUrlRequestRTTReceived(); | |
292 | |
293 // Prefs must be read at startup. | |
294 assertTrue(readCountHistogram.getDelta() > 0); | |
295 | |
296 // Check RTT observation count after throughput observation has been received. This | |
297 // ensures | |
298 // that executor has finished posting the RTT observation to the RTT listeners. | |
299 assertTrue(rttListener.rttObservationCount() > 0); | |
300 | |
301 // Verify that effective connection type callback is received and | |
302 // effective connection type is correctly set. | |
303 assertTrue(cronetEngine.getEffectiveConnectionType() | |
304 != EffectiveConnectionType.TYPE_UNKNOWN); | |
305 | |
306 cronetEngine.shutdown(); | |
307 | |
308 if (i == 0) { | |
309 // Verify that the cached estimates were written to the prefs. | |
310 while (true) { | |
mgersh
2017/06/29 19:02:32
What shutdown() does is destroy the native CronetU
tbansal1
2017/06/29 22:45:05
Done.
| |
311 Log.i(TAG, "Still waiting for pref file update....."); | |
312 try { | |
313 if (prefsFileContainsString("network_qualities")) { | |
314 break; | |
315 } | |
316 } catch (FileNotFoundException e) { | |
mgersh
2017/06/29 19:02:32
This try/catch can be removed if you wait for a pr
tbansal1
2017/06/29 22:45:05
Done.
| |
317 // Ignored this exception since the file will only be cr eated when updates | |
318 // are flushed to the disk. | |
319 } | |
320 Thread.sleep(2000); | |
mgersh
2017/06/29 19:02:32
In order to be useful, this sleep should happen be
tbansal1
2017/06/29 22:45:05
Done.
| |
321 } | |
322 assertTrue(prefsFileContainsString("network_qualities")); | |
323 } | |
324 | |
325 // Stored network quality in the pref should be read in the second i teration. | |
326 assertEquals(readPrefsSizeHistogram.getDelta() > 0, i > 0); | |
327 assertEquals(cachedRttHistogram.getDelta() > 0, i > 0); | |
328 } | |
329 } | |
330 | |
331 @SmallTest | |
332 @Feature({"Cronet"}) | |
333 public void testQuicDisabledWithParams() throws Exception { | |
334 ExperimentalCronetEngine.Builder cronetEngineBuilder = | |
335 new ExperimentalCronetEngine.Builder(getContext()); | |
336 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu torThreadFactory()); | |
337 TestNetworkQualityRttListener rttListener = | |
338 new TestNetworkQualityRttListener(listenersExecutor); | |
339 TestNetworkQualityThroughputListener throughputListener = | |
340 new TestNetworkQualityThroughputListener(listenersExecutor); | |
341 | |
342 // Force the effective connection type to "2G". | |
343 JSONObject nqeOptions = new JSONObject().put("force_effective_connection _type", "Slow-2G"); | |
344 // Add one more extra param two times to ensure robustness. | |
345 nqeOptions.put("some_other_param_1", "value1"); | |
346 nqeOptions.put("some_other_param_2", "value2"); | |
347 JSONObject experimentalOptions = | |
348 new JSONObject().put("NetworkQualityEstimator", nqeOptions); | |
349 experimentalOptions.put("SomeOtherFieldTrialName", new JSONObject()); | |
350 | |
351 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true ).enableQuic(false); | |
352 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString( )); | |
353 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build( ); | |
354 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, fals e); | |
355 | |
356 cronetEngine.addRttListener(rttListener); | |
357 cronetEngine.addThroughputListener(throughputListener); | |
358 | |
359 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | |
360 UrlRequest.Builder builder = | |
361 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getEx ecutor()); | |
362 UrlRequest urlRequest = builder.build(); | |
363 urlRequest.start(); | |
364 callback.blockForDone(); | |
365 | |
366 // Throughput observation is posted to the network quality estimator on the network thread | |
367 // after the UrlRequest is completed. The observations are then eventual ly posted to | |
368 // throughput listeners on the executor provided to network quality. | |
369 throughputListener.waitUntilFirstThroughputObservationReceived(); | |
370 | |
371 // Wait for RTT observation (at the URL request layer) to be posted. | |
372 rttListener.waitUntilFirstUrlRequestRTTReceived(); | |
373 | |
374 assertTrue(throughputListener.throughputObservationCount() > 0); | |
375 | |
376 // Check RTT observation count after throughput observation has been rec eived. This ensures | |
377 // that executor has finished posting the RTT observation to the RTT lis teners. | |
378 assertTrue(rttListener.rttObservationCount() > 0); | |
379 | |
380 // NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST | |
381 assertTrue(rttListener.rttObservationCount(0) > 0); | |
382 | |
383 // NETWORK_QUALITY_OBSERVATION_SOURCE_TCP | |
384 assertTrue(rttListener.rttObservationCount(1) > 0); | |
385 | |
386 // NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC | |
387 assertEquals(0, rttListener.rttObservationCount(2)); | |
388 | |
389 // Verify that the listeners were notified on the expected thread. | |
390 assertEquals(mNetworkQualityThread, rttListener.getThread()); | |
391 assertEquals(mNetworkQualityThread, throughputListener.getThread()); | |
392 | |
393 // Verify that effective connection type callback is received and effect ive connection type | |
394 // is correctly set to the forced value. This also verifies that the con figuration params | |
395 // from Cronet embedders were correctly read by NetworkQualityEstimator. | |
396 assertEquals( | |
397 EffectiveConnectionType.TYPE_SLOW_2G, cronetEngine.getEffectiveC onnectionType()); | |
398 | |
399 cronetEngine.shutdown(); | |
400 } | |
230 } | 401 } |
OLD | NEW |