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 |
138 @SmallTest | 139 @SmallTest |
139 @Feature({"Cronet"}) | 140 @Feature({"Cronet"}) |
140 @DisabledTest(message = "Disabled due to flaky assert. See crbug.com/710626"
) | |
141 public void testQuicDisabled() throws Exception { | 141 public void testQuicDisabled() throws Exception { |
142 ExperimentalCronetEngine.Builder cronetEngineBuilder = | 142 ExperimentalCronetEngine.Builder cronetEngineBuilder = |
143 new ExperimentalCronetEngine.Builder(getContext()); | 143 new ExperimentalCronetEngine.Builder(getContext()); |
144 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; | 144 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; |
145 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu
torThreadFactory()); | 145 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu
torThreadFactory()); |
146 TestNetworkQualityRttListener rttListener = | 146 TestNetworkQualityRttListener rttListener = |
147 new TestNetworkQualityRttListener(listenersExecutor); | 147 new TestNetworkQualityRttListener(listenersExecutor); |
148 TestNetworkQualityThroughputListener throughputListener = | 148 TestNetworkQualityThroughputListener throughputListener = |
149 new TestNetworkQualityThroughputListener(listenersExecutor); | 149 new TestNetworkQualityThroughputListener(listenersExecutor); |
150 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true
).enableQuic(false); | 150 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true
).enableQuic(false); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 // estimates are available. | 207 // estimates are available. |
208 assertTrue(cronetEngine.getHttpRttMs() >= 0); | 208 assertTrue(cronetEngine.getHttpRttMs() >= 0); |
209 assertTrue(cronetEngine.getTransportRttMs() >= 0); | 209 assertTrue(cronetEngine.getTransportRttMs() >= 0); |
210 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0); | 210 assertTrue(cronetEngine.getDownstreamThroughputKbps() >= 0); |
211 | 211 |
212 // Verify that the cached estimates were written to the prefs. | 212 // Verify that the cached estimates were written to the prefs. |
213 while (true) { | 213 while (true) { |
214 Log.i(TAG, "Still waiting for pref file update....."); | 214 Log.i(TAG, "Still waiting for pref file update....."); |
215 Thread.sleep(12000); | 215 Thread.sleep(12000); |
216 try { | 216 try { |
217 if (fileContainsString("local_prefs.json", "network_qualities"))
{ | 217 if (prefsFileContainsString("network_qualities")) { |
218 break; | 218 break; |
219 } | 219 } |
220 } catch (FileNotFoundException e) { | 220 } catch (FileNotFoundException e) { |
221 // Ignored this exception since the file will only be created wh
en updates are | 221 // Ignored this exception since the file will only be created wh
en updates are |
222 // flushed to the disk. | 222 // flushed to the disk. |
223 } | 223 } |
224 } | 224 } |
225 assertTrue(fileContainsString("local_prefs.json", "network_qualities")); | 225 assertTrue(prefsFileContainsString("network_qualities")); |
226 | 226 |
227 cronetEngine.shutdown(); | 227 cronetEngine.shutdown(); |
228 assertTrue(writeCountHistogram.getDelta() > 0); | 228 assertTrue(writeCountHistogram.getDelta() > 0); |
229 } | 229 } |
| 230 |
| 231 @SmallTest |
| 232 @OnlyRunNativeCronet |
| 233 @Feature({"Cronet"}) |
| 234 public void testPrefsWriteRead() throws Exception { |
| 235 // When the loop is run for the first time, network quality is written t
o the disk. The |
| 236 // test verifies that in the next loop, the network quality is read back
. |
| 237 for (int i = 0; i <= 1; ++i) { |
| 238 ExperimentalCronetEngine.Builder cronetEngineBuilder = |
| 239 new ExperimentalCronetEngine.Builder(getContext()); |
| 240 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; |
| 241 Executor listenersExecutor = |
| 242 Executors.newSingleThreadExecutor(new ExecutorThreadFactory(
)); |
| 243 TestNetworkQualityRttListener rttListener = |
| 244 new TestNetworkQualityRttListener(listenersExecutor); |
| 245 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(
true).enableQuic( |
| 246 false); |
| 247 cronetEngineBuilder.setStoragePath(getTestStorage(getContext())); |
| 248 |
| 249 JSONObject nqeOptions = new JSONObject().put("persistent_cache_readi
ng_enabled", true); |
| 250 JSONObject experimentalOptions = |
| 251 new JSONObject().put("NetworkQualityEstimator", nqeOptions); |
| 252 |
| 253 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toStr
ing()); |
| 254 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.bu
ild(); |
| 255 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true,
true); |
| 256 cronetEngine.addRttListener(rttListener); |
| 257 |
| 258 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.W
riteCount", 1); |
| 259 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check. |
| 260 |
| 261 HistogramDelta readCountHistogram = new HistogramDelta("NQE.Prefs.Re
adCount", 1); |
| 262 assertEquals(0, readCountHistogram.getDelta()); // Sanity check. |
| 263 |
| 264 HistogramDelta readPrefsSizeHistogram = new HistogramDelta("NQE.Pref
s.ReadSize", 1); |
| 265 assertEquals(0, readPrefsSizeHistogram.getDelta()); // Sanity check. |
| 266 |
| 267 // NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE: 3 |
| 268 HistogramDelta cachedRttHistogram = new HistogramDelta("NQE.RTT.Obse
rvationSource", 3); |
| 269 assertEquals(0, cachedRttHistogram.getDelta()); // Sanity check. |
| 270 |
| 271 TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
| 272 UrlRequest.Builder builder = |
| 273 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.g
etExecutor()); |
| 274 UrlRequest urlRequest = builder.build(); |
| 275 urlRequest.start(); |
| 276 callback.blockForDone(); |
| 277 |
| 278 // Wait for RTT observation (at the URL request layer) to be posted. |
| 279 rttListener.waitUntilFirstUrlRequestRTTReceived(); |
| 280 |
| 281 // Prefs must be read at startup. |
| 282 assertTrue(readCountHistogram.getDelta() > 0); |
| 283 |
| 284 // Check RTT observation count after throughput observation has been
received. This |
| 285 // ensures |
| 286 // that executor has finished posting the RTT observation to the RTT
listeners. |
| 287 assertTrue(rttListener.rttObservationCount() > 0); |
| 288 |
| 289 // Verify that effective connection type callback is received and |
| 290 // effective connection type is correctly set. |
| 291 assertTrue(cronetEngine.getEffectiveConnectionType() |
| 292 != EffectiveConnectionType.TYPE_UNKNOWN); |
| 293 |
| 294 cronetEngine.shutdown(); |
| 295 |
| 296 if (i == 0) { |
| 297 // Verify that the cached estimates were written to the prefs. |
| 298 assertTrue(prefsFileContainsString("network_qualities")); |
| 299 } |
| 300 |
| 301 // Stored network quality in the pref should be read in the second i
teration. |
| 302 assertEquals(readPrefsSizeHistogram.getDelta() > 0, i > 0); |
| 303 assertEquals(cachedRttHistogram.getDelta() > 0, i > 0); |
| 304 } |
| 305 } |
| 306 |
| 307 @SmallTest |
| 308 @Feature({"Cronet"}) |
| 309 public void testQuicDisabledWithParams() throws Exception { |
| 310 ExperimentalCronetEngine.Builder cronetEngineBuilder = |
| 311 new ExperimentalCronetEngine.Builder(getContext()); |
| 312 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu
torThreadFactory()); |
| 313 TestNetworkQualityRttListener rttListener = |
| 314 new TestNetworkQualityRttListener(listenersExecutor); |
| 315 TestNetworkQualityThroughputListener throughputListener = |
| 316 new TestNetworkQualityThroughputListener(listenersExecutor); |
| 317 |
| 318 // Force the effective connection type to "2G". |
| 319 JSONObject nqeOptions = new JSONObject().put("force_effective_connection
_type", "Slow-2G"); |
| 320 // Add one more extra param two times to ensure robustness. |
| 321 nqeOptions.put("some_other_param_1", "value1"); |
| 322 nqeOptions.put("some_other_param_2", "value2"); |
| 323 JSONObject experimentalOptions = |
| 324 new JSONObject().put("NetworkQualityEstimator", nqeOptions); |
| 325 experimentalOptions.put("SomeOtherFieldTrialName", new JSONObject()); |
| 326 |
| 327 cronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(true
).enableQuic(false); |
| 328 cronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString(
)); |
| 329 final ExperimentalCronetEngine cronetEngine = cronetEngineBuilder.build(
); |
| 330 cronetEngine.configureNetworkQualityEstimatorForTesting(true, true, fals
e); |
| 331 |
| 332 cronetEngine.addRttListener(rttListener); |
| 333 cronetEngine.addThroughputListener(throughputListener); |
| 334 |
| 335 TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
| 336 UrlRequest.Builder builder = |
| 337 cronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getEx
ecutor()); |
| 338 UrlRequest urlRequest = builder.build(); |
| 339 urlRequest.start(); |
| 340 callback.blockForDone(); |
| 341 |
| 342 // Throughput observation is posted to the network quality estimator on
the network thread |
| 343 // after the UrlRequest is completed. The observations are then eventual
ly posted to |
| 344 // throughput listeners on the executor provided to network quality. |
| 345 throughputListener.waitUntilFirstThroughputObservationReceived(); |
| 346 |
| 347 // Wait for RTT observation (at the URL request layer) to be posted. |
| 348 rttListener.waitUntilFirstUrlRequestRTTReceived(); |
| 349 |
| 350 assertTrue(throughputListener.throughputObservationCount() > 0); |
| 351 |
| 352 // Check RTT observation count after throughput observation has been rec
eived. This ensures |
| 353 // that executor has finished posting the RTT observation to the RTT lis
teners. |
| 354 assertTrue(rttListener.rttObservationCount() > 0); |
| 355 |
| 356 // NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST |
| 357 assertTrue(rttListener.rttObservationCount(0) > 0); |
| 358 |
| 359 // NETWORK_QUALITY_OBSERVATION_SOURCE_TCP |
| 360 assertTrue(rttListener.rttObservationCount(1) > 0); |
| 361 |
| 362 // NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC |
| 363 assertEquals(0, rttListener.rttObservationCount(2)); |
| 364 |
| 365 // Verify that the listeners were notified on the expected thread. |
| 366 assertEquals(mNetworkQualityThread, rttListener.getThread()); |
| 367 assertEquals(mNetworkQualityThread, throughputListener.getThread()); |
| 368 |
| 369 // Verify that effective connection type callback is received and effect
ive connection type |
| 370 // is correctly set to the forced value. This also verifies that the con
figuration params |
| 371 // from Cronet embedders were correctly read by NetworkQualityEstimator. |
| 372 assertEquals( |
| 373 EffectiveConnectionType.TYPE_SLOW_2G, cronetEngine.getEffectiveC
onnectionType()); |
| 374 |
| 375 cronetEngine.shutdown(); |
| 376 } |
230 } | 377 } |
OLD | NEW |