| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.content.Context; | 7 import android.content.Context; |
| 8 import android.content.ContextWrapper; | 8 import android.content.ContextWrapper; |
| 9 import android.os.ConditionVariable; | 9 import android.os.ConditionVariable; |
| 10 import android.os.Handler; | 10 import android.os.Handler; |
| 11 import android.os.Looper; | 11 import android.os.Looper; |
| 12 import android.os.StrictMode; | |
| 13 import android.support.test.filters.SmallTest; | 12 import android.support.test.filters.SmallTest; |
| 14 | 13 |
| 15 import org.json.JSONObject; | 14 import org.json.JSONObject; |
| 16 | 15 |
| 17 import static org.chromium.net.CronetEngine.Builder.HTTP_CACHE_IN_MEMORY; | 16 import static org.chromium.net.CronetEngine.Builder.HTTP_CACHE_IN_MEMORY; |
| 18 | 17 |
| 19 import org.chromium.base.FileUtils; | 18 import org.chromium.base.FileUtils; |
| 20 import org.chromium.base.Log; | |
| 21 import org.chromium.base.PathUtils; | 19 import org.chromium.base.PathUtils; |
| 22 import org.chromium.base.annotations.JNINamespace; | 20 import org.chromium.base.annotations.JNINamespace; |
| 23 import org.chromium.base.annotations.SuppressFBWarnings; | |
| 24 import org.chromium.base.test.util.DisabledTest; | |
| 25 import org.chromium.base.test.util.Feature; | 21 import org.chromium.base.test.util.Feature; |
| 26 import org.chromium.base.test.util.MetricsUtils.HistogramDelta; | |
| 27 import org.chromium.net.MetricsTestUtil.TestExecutor; | |
| 28 import org.chromium.net.TestUrlRequestCallback.ResponseStep; | 22 import org.chromium.net.TestUrlRequestCallback.ResponseStep; |
| 29 import org.chromium.net.impl.CronetEngineBase; | 23 import org.chromium.net.impl.CronetEngineBase; |
| 30 import org.chromium.net.impl.CronetEngineBuilderImpl; | 24 import org.chromium.net.impl.CronetEngineBuilderImpl; |
| 31 import org.chromium.net.impl.CronetLibraryLoader; | 25 import org.chromium.net.impl.CronetLibraryLoader; |
| 32 import org.chromium.net.impl.CronetUrlRequestContext; | 26 import org.chromium.net.impl.CronetUrlRequestContext; |
| 33 import org.chromium.net.test.EmbeddedTestServer; | 27 import org.chromium.net.test.EmbeddedTestServer; |
| 34 | 28 |
| 35 import java.io.BufferedReader; | 29 import java.io.BufferedReader; |
| 36 import java.io.File; | 30 import java.io.File; |
| 37 import java.io.FileInputStream; | |
| 38 import java.io.FileNotFoundException; | |
| 39 import java.io.FileReader; | 31 import java.io.FileReader; |
| 40 import java.io.IOException; | |
| 41 import java.net.URL; | 32 import java.net.URL; |
| 42 import java.util.Arrays; | 33 import java.util.Arrays; |
| 43 import java.util.concurrent.Executor; | 34 import java.util.concurrent.Executor; |
| 44 import java.util.concurrent.Executors; | |
| 45 import java.util.concurrent.ThreadFactory; | |
| 46 import java.util.concurrent.atomic.AtomicReference; | 35 import java.util.concurrent.atomic.AtomicReference; |
| 47 | 36 |
| 48 /** | 37 /** |
| 49 * Test CronetEngine. | 38 * Test CronetEngine. |
| 50 */ | 39 */ |
| 51 @JNINamespace("cronet") | 40 @JNINamespace("cronet") |
| 52 public class CronetUrlRequestContextTest extends CronetTestBase { | 41 public class CronetUrlRequestContextTest extends CronetTestBase { |
| 53 private static final String TAG = CronetUrlRequestContextTest.class.getSimpl
eName(); | 42 private static final String TAG = CronetUrlRequestContextTest.class.getSimpl
eName(); |
| 54 | 43 |
| 55 // URLs used for tests. | 44 // URLs used for tests. |
| 56 private static final String MOCK_CRONET_TEST_FAILED_URL = | 45 private static final String MOCK_CRONET_TEST_FAILED_URL = |
| 57 "http://mock.failed.request/-2"; | 46 "http://mock.failed.request/-2"; |
| 58 private static final String MOCK_CRONET_TEST_SUCCESS_URL = | 47 private static final String MOCK_CRONET_TEST_SUCCESS_URL = |
| 59 "http://mock.http/success.txt"; | 48 "http://mock.http/success.txt"; |
| 60 private static final int MAX_FILE_SIZE = 1000000000; | 49 private static final int MAX_FILE_SIZE = 1000000000; |
| 61 private static final int NUM_EVENT_FILES = 10; | 50 private static final int NUM_EVENT_FILES = 10; |
| 62 | 51 |
| 63 private EmbeddedTestServer mTestServer; | 52 private EmbeddedTestServer mTestServer; |
| 64 private String mUrl; | 53 private String mUrl; |
| 65 private String mUrl404; | 54 private String mUrl404; |
| 66 private String mUrl500; | 55 private String mUrl500; |
| 67 | 56 |
| 68 // Thread on which network quality listeners should be notified. | |
| 69 private Thread mNetworkQualityThread; | |
| 70 | |
| 71 @Override | 57 @Override |
| 72 protected void setUp() throws Exception { | 58 protected void setUp() throws Exception { |
| 73 super.setUp(); | 59 super.setUp(); |
| 74 mTestServer = EmbeddedTestServer.createAndStartServer(getContext()); | 60 mTestServer = EmbeddedTestServer.createAndStartServer(getContext()); |
| 75 mUrl = mTestServer.getURL("/echo?status=200"); | 61 mUrl = mTestServer.getURL("/echo?status=200"); |
| 76 mUrl404 = mTestServer.getURL("/echo?status=404"); | 62 mUrl404 = mTestServer.getURL("/echo?status=404"); |
| 77 mUrl500 = mTestServer.getURL("/echo?status=500"); | 63 mUrl500 = mTestServer.getURL("/echo?status=500"); |
| 78 } | 64 } |
| 79 | 65 |
| 80 @Override | 66 @Override |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 mCronetEngine.shutdown(); | 120 mCronetEngine.shutdown(); |
| 135 mCallbackCompletionBlock.open(); | 121 mCallbackCompletionBlock.open(); |
| 136 } | 122 } |
| 137 | 123 |
| 138 // Wait for request completion callback. | 124 // Wait for request completion callback. |
| 139 void blockForCallbackToComplete() { | 125 void blockForCallbackToComplete() { |
| 140 mCallbackCompletionBlock.block(); | 126 mCallbackCompletionBlock.block(); |
| 141 } | 127 } |
| 142 } | 128 } |
| 143 | 129 |
| 144 private class ExecutorThreadFactory implements ThreadFactory { | |
| 145 public Thread newThread(final Runnable r) { | |
| 146 mNetworkQualityThread = new Thread(new Runnable() { | |
| 147 @Override | |
| 148 public void run() { | |
| 149 StrictMode.ThreadPolicy threadPolicy = StrictMode.getThreadP
olicy(); | |
| 150 try { | |
| 151 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.B
uilder() | |
| 152 .detectNetwork() | |
| 153 .penaltyLog() | |
| 154 .penaltyDeath() | |
| 155 .build()); | |
| 156 r.run(); | |
| 157 } finally { | |
| 158 StrictMode.setThreadPolicy(threadPolicy); | |
| 159 } | |
| 160 } | |
| 161 }); | |
| 162 return mNetworkQualityThread; | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 @SmallTest | 130 @SmallTest |
| 167 @Feature({"Cronet"}) | 131 @Feature({"Cronet"}) |
| 168 @SuppressWarnings("deprecation") | 132 @SuppressWarnings("deprecation") |
| 169 public void testConfigUserAgent() throws Exception { | 133 public void testConfigUserAgent() throws Exception { |
| 170 String userAgentName = "User-Agent"; | 134 String userAgentName = "User-Agent"; |
| 171 String userAgentValue = "User-Agent-Value"; | 135 String userAgentValue = "User-Agent-Value"; |
| 172 ExperimentalCronetEngine.Builder cronetEngineBuilder = | 136 ExperimentalCronetEngine.Builder cronetEngineBuilder = |
| 173 new ExperimentalCronetEngine.Builder(getContext()); | 137 new ExperimentalCronetEngine.Builder(getContext()); |
| 174 if (testingJavaImpl()) { | 138 if (testingJavaImpl()) { |
| 175 cronetEngineBuilder = createJavaEngineBuilder(); | 139 cronetEngineBuilder = createJavaEngineBuilder(); |
| 176 } | 140 } |
| 177 cronetEngineBuilder.setUserAgent(userAgentValue); | 141 cronetEngineBuilder.setUserAgent(userAgentValue); |
| 178 final CronetTestFramework testFramework = | 142 final CronetTestFramework testFramework = |
| 179 startCronetTestFrameworkWithUrlAndCronetEngineBuilder(mUrl, cron
etEngineBuilder); | 143 startCronetTestFrameworkWithUrlAndCronetEngineBuilder(mUrl, cron
etEngineBuilder); |
| 180 NativeTestServer.shutdownNativeTestServer(); // startNativeTestServer re
turns false if it's | 144 NativeTestServer.shutdownNativeTestServer(); // startNativeTestServer re
turns false if it's |
| 181 // already running | 145 // already running |
| 182 assertTrue(NativeTestServer.startNativeTestServer(getContext())); | 146 assertTrue(NativeTestServer.startNativeTestServer(getContext())); |
| 183 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | 147 TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
| 184 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( | 148 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( |
| 185 NativeTestServer.getEchoHeaderURL(userAgentName), callback, call
back.getExecutor()); | 149 NativeTestServer.getEchoHeaderURL(userAgentName), callback, call
back.getExecutor()); |
| 186 urlRequestBuilder.build().start(); | 150 urlRequestBuilder.build().start(); |
| 187 callback.blockForDone(); | 151 callback.blockForDone(); |
| 188 assertEquals(userAgentValue, callback.mResponseAsString); | 152 assertEquals(userAgentValue, callback.mResponseAsString); |
| 189 } | 153 } |
| 190 | 154 |
| 191 @SmallTest | 155 @SmallTest |
| 192 @Feature({"Cronet"}) | 156 @Feature({"Cronet"}) |
| 193 @DisabledTest(message = "Disabled due to flaky assert. See crbug.com/710626"
) | |
| 194 public void testRealTimeNetworkQualityObservationsNotEnabled() throws Except
ion { | |
| 195 ExperimentalCronetEngine.Builder mCronetEngineBuilder = | |
| 196 new ExperimentalCronetEngine.Builder(getContext()); | |
| 197 final CronetTestFramework testFramework = | |
| 198 startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCro
netEngineBuilder); | |
| 199 Executor networkQualityExecutor = Executors.newSingleThreadExecutor(); | |
| 200 TestNetworkQualityRttListener rttListener = | |
| 201 new TestNetworkQualityRttListener(networkQualityExecutor); | |
| 202 TestNetworkQualityThroughputListener throughputListener = | |
| 203 new TestNetworkQualityThroughputListener(networkQualityExecutor,
null); | |
| 204 try { | |
| 205 testFramework.mCronetEngine.addRttListener(rttListener); | |
| 206 fail("Should throw an exception."); | |
| 207 } catch (IllegalStateException e) { | |
| 208 } | |
| 209 try { | |
| 210 testFramework.mCronetEngine.addThroughputListener(throughputListener
); | |
| 211 fail("Should throw an exception."); | |
| 212 } catch (IllegalStateException e) { | |
| 213 } | |
| 214 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | |
| 215 UrlRequest.Builder builder = testFramework.mCronetEngine.newUrlRequestBu
ilder( | |
| 216 mUrl, callback, callback.getExecutor()); | |
| 217 UrlRequest urlRequest = builder.build(); | |
| 218 | |
| 219 urlRequest.start(); | |
| 220 callback.blockForDone(); | |
| 221 assertEquals(0, rttListener.rttObservationCount()); | |
| 222 assertEquals(0, throughputListener.throughputObservationCount()); | |
| 223 testFramework.mCronetEngine.shutdown(); | |
| 224 } | |
| 225 | |
| 226 @SmallTest | |
| 227 @Feature({"Cronet"}) | |
| 228 public void testRealTimeNetworkQualityObservationsListenerRemoved() throws E
xception { | |
| 229 ExperimentalCronetEngine.Builder mCronetEngineBuilder = | |
| 230 new ExperimentalCronetEngine.Builder(getContext()); | |
| 231 TestExecutor networkQualityExecutor = new TestExecutor(); | |
| 232 TestNetworkQualityRttListener rttListener = | |
| 233 new TestNetworkQualityRttListener(networkQualityExecutor); | |
| 234 mCronetEngineBuilder.enableNetworkQualityEstimator(true); | |
| 235 final CronetTestFramework testFramework = | |
| 236 startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCro
netEngineBuilder); | |
| 237 testFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(t
rue, true, false); | |
| 238 | |
| 239 testFramework.mCronetEngine.addRttListener(rttListener); | |
| 240 testFramework.mCronetEngine.removeRttListener(rttListener); | |
| 241 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | |
| 242 UrlRequest.Builder builder = testFramework.mCronetEngine.newUrlRequestBu
ilder( | |
| 243 mUrl, callback, callback.getExecutor()); | |
| 244 UrlRequest urlRequest = builder.build(); | |
| 245 urlRequest.start(); | |
| 246 callback.blockForDone(); | |
| 247 networkQualityExecutor.runAllTasks(); | |
| 248 assertEquals(0, rttListener.rttObservationCount()); | |
| 249 testFramework.mCronetEngine.shutdown(); | |
| 250 } | |
| 251 | |
| 252 // Returns whether a file contains a particular string. | |
| 253 @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") | |
| 254 private boolean fileContainsString(String filename, String content) throws I
OException { | |
| 255 File file = | |
| 256 new File(CronetTestFramework.getTestStorage(getContext()) + "/pr
efs/" + filename); | |
| 257 FileInputStream fileInputStream = new FileInputStream(file); | |
| 258 byte[] data = new byte[(int) file.length()]; | |
| 259 fileInputStream.read(data); | |
| 260 fileInputStream.close(); | |
| 261 return new String(data, "UTF-8").contains(content); | |
| 262 } | |
| 263 | |
| 264 @SmallTest | |
| 265 @Feature({"Cronet"}) | |
| 266 public void testRealTimeNetworkQualityObservationsQuicDisabled() throws Exce
ption { | |
| 267 ExperimentalCronetEngine.Builder mCronetEngineBuilder = | |
| 268 new ExperimentalCronetEngine.Builder(getContext()); | |
| 269 assert RttThroughputValues.INVALID_RTT_THROUGHPUT < 0; | |
| 270 Executor listenersExecutor = Executors.newSingleThreadExecutor(new Execu
torThreadFactory()); | |
| 271 ConditionVariable waitForThroughput = new ConditionVariable(); | |
| 272 TestNetworkQualityRttListener rttListener = | |
| 273 new TestNetworkQualityRttListener(listenersExecutor); | |
| 274 TestNetworkQualityThroughputListener throughputListener = | |
| 275 new TestNetworkQualityThroughputListener(listenersExecutor, wait
ForThroughput); | |
| 276 mCronetEngineBuilder.enableNetworkQualityEstimator(true).enableHttp2(tru
e).enableQuic( | |
| 277 false); | |
| 278 mCronetEngineBuilder.setStoragePath(CronetTestFramework.getTestStorage(g
etContext())); | |
| 279 final CronetTestFramework testFramework = | |
| 280 startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCro
netEngineBuilder); | |
| 281 testFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(t
rue, true, true); | |
| 282 | |
| 283 testFramework.mCronetEngine.addRttListener(rttListener); | |
| 284 testFramework.mCronetEngine.addThroughputListener(throughputListener); | |
| 285 | |
| 286 HistogramDelta writeCountHistogram = new HistogramDelta("NQE.Prefs.Write
Count", 1); | |
| 287 assertEquals(0, writeCountHistogram.getDelta()); // Sanity check. | |
| 288 | |
| 289 HistogramDelta readCountHistogram = new HistogramDelta("NQE.Prefs.ReadCo
unt", 1); | |
| 290 assertEquals(0, readCountHistogram.getDelta()); // Sanity check. | |
| 291 | |
| 292 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | |
| 293 UrlRequest.Builder builder = testFramework.mCronetEngine.newUrlRequestBu
ilder( | |
| 294 mUrl, callback, callback.getExecutor()); | |
| 295 UrlRequest urlRequest = builder.build(); | |
| 296 urlRequest.start(); | |
| 297 callback.blockForDone(); | |
| 298 | |
| 299 // Throughput observation is posted to the network quality estimator on
the network thread | |
| 300 // after the UrlRequest is completed. The observations are then eventual
ly posted to | |
| 301 // throughput listeners on the executor provided to network quality. | |
| 302 waitForThroughput.block(); | |
| 303 assertTrue(throughputListener.throughputObservationCount() > 0); | |
| 304 | |
| 305 // Prefs must be read at startup. | |
| 306 assertTrue(readCountHistogram.getDelta() > 0); | |
| 307 | |
| 308 // Check RTT observation count after throughput observation has been rec
eived. This ensures | |
| 309 // that executor has finished posting the RTT observation to the RTT lis
teners. | |
| 310 assertTrue(rttListener.rttObservationCount() > 0); | |
| 311 | |
| 312 // NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST | |
| 313 assertTrue(rttListener.rttObservationCount(0) > 0); | |
| 314 | |
| 315 // NETWORK_QUALITY_OBSERVATION_SOURCE_TCP | |
| 316 assertTrue(rttListener.rttObservationCount(1) > 0); | |
| 317 | |
| 318 // NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC | |
| 319 assertEquals(0, rttListener.rttObservationCount(2)); | |
| 320 | |
| 321 // Verify that the listeners were notified on the expected thread. | |
| 322 assertEquals(mNetworkQualityThread, rttListener.getThread()); | |
| 323 assertEquals(mNetworkQualityThread, throughputListener.getThread()); | |
| 324 | |
| 325 // Verify that effective connection type callback is received and | |
| 326 // effective connection type is correctly set. | |
| 327 assertTrue(testFramework.mCronetEngine.getEffectiveConnectionType() | |
| 328 != EffectiveConnectionType.TYPE_UNKNOWN); | |
| 329 | |
| 330 // Verify that the HTTP RTT, transport RTT and downstream throughput | |
| 331 // estimates are available. | |
| 332 assertTrue(testFramework.mCronetEngine.getHttpRttMs() >= 0); | |
| 333 assertTrue(testFramework.mCronetEngine.getTransportRttMs() >= 0); | |
| 334 assertTrue(testFramework.mCronetEngine.getDownstreamThroughputKbps() >=
0); | |
| 335 | |
| 336 // Verify that the cached estimates were written to the prefs. | |
| 337 while (true) { | |
| 338 Log.i(TAG, "Still waiting for pref file update....."); | |
| 339 Thread.sleep(12000); | |
| 340 try { | |
| 341 if (fileContainsString("local_prefs.json", "network_qualities"))
{ | |
| 342 break; | |
| 343 } | |
| 344 } catch (FileNotFoundException e) { | |
| 345 // Ignored this exception since the file will only be created wh
en updates are | |
| 346 // flushed to the disk. | |
| 347 } | |
| 348 } | |
| 349 assertTrue(fileContainsString("local_prefs.json", "network_qualities")); | |
| 350 | |
| 351 testFramework.mCronetEngine.shutdown(); | |
| 352 assertTrue(writeCountHistogram.getDelta() > 0); | |
| 353 } | |
| 354 | |
| 355 @SmallTest | |
| 356 @Feature({"Cronet"}) | |
| 357 // TODO: Remove the annotation after fixing http://crbug.com/637979 & http:/
/crbug.com/637972 | 157 // TODO: Remove the annotation after fixing http://crbug.com/637979 & http:/
/crbug.com/637972 |
| 358 @OnlyRunNativeCronet | 158 @OnlyRunNativeCronet |
| 359 public void testShutdown() throws Exception { | 159 public void testShutdown() throws Exception { |
| 360 final CronetTestFramework testFramework = startCronetTestFramework(); | 160 final CronetTestFramework testFramework = startCronetTestFramework(); |
| 361 ShutdownTestUrlRequestCallback callback = | 161 ShutdownTestUrlRequestCallback callback = |
| 362 new ShutdownTestUrlRequestCallback(testFramework.mCronetEngine); | 162 new ShutdownTestUrlRequestCallback(testFramework.mCronetEngine); |
| 363 // Block callback when response starts to verify that shutdown fails | 163 // Block callback when response starts to verify that shutdown fails |
| 364 // if there are active requests. | 164 // if there are active requests. |
| 365 callback.setAutoAdvance(false); | 165 callback.setAutoAdvance(false); |
| 366 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( | 166 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( |
| (...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 TestUrlRequestCallback callback = new TestUrlRequestCallback(); | 1260 TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
| 1461 URL requestUrl = | 1261 URL requestUrl = |
| 1462 new URL("http", resolverTestHostname, testUrl.getPort(), testUrl
.getFile()); | 1262 new URL("http", resolverTestHostname, testUrl.getPort(), testUrl
.getFile()); |
| 1463 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( | 1263 UrlRequest.Builder urlRequestBuilder = testFramework.mCronetEngine.newUr
lRequestBuilder( |
| 1464 requestUrl.toString(), callback, callback.getExecutor()); | 1264 requestUrl.toString(), callback, callback.getExecutor()); |
| 1465 urlRequestBuilder.build().start(); | 1265 urlRequestBuilder.build().start(); |
| 1466 callback.blockForDone(); | 1266 callback.blockForDone(); |
| 1467 assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); | 1267 assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); |
| 1468 } | 1268 } |
| 1469 } | 1269 } |
| OLD | NEW |