Chromium Code Reviews| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |