Index: components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java |
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java |
index 95f35eed336afe712c640f82540cbb353600e2fb..3d12bb4366fde4f1b87ffff108f4b6e07e4b6f75 100644 |
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java |
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java |
@@ -11,6 +11,7 @@ import android.content.ContextWrapper; |
import android.os.ConditionVariable; |
import android.os.Handler; |
import android.os.Looper; |
+import android.os.StrictMode; |
import android.test.suitebuilder.annotation.SmallTest; |
import org.chromium.base.PathUtils; |
@@ -30,6 +31,7 @@ import java.util.LinkedList; |
import java.util.NoSuchElementException; |
import java.util.concurrent.Executor; |
import java.util.concurrent.Executors; |
+import java.util.concurrent.ThreadFactory; |
/** |
* Test CronetEngine. |
@@ -48,6 +50,9 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
private String mUrl500; |
CronetTestFramework mTestFramework; |
+ // Thread on which network quality listeners should be notified. |
+ private Thread mNetworkQualityThread; |
+ |
@Override |
protected void setUp() throws Exception { |
super.setUp(); |
@@ -125,45 +130,25 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
} |
} |
- static class TestNetworkQualityListener |
- implements NetworkQualityRttListener, NetworkQualityThroughputListener { |
- // Lock to ensure that observation counts can be updated and read by different threads. |
- private final Object mLock = new Object(); |
- private final ConditionVariable mWaitForThroughput; |
- private int mRttObservationCount; |
- private int mThroughputObservationCount; |
- |
- TestNetworkQualityListener(ConditionVariable waitForThroughput) { |
- mWaitForThroughput = waitForThroughput; |
- } |
- |
- @Override |
- public void onRttObservation(int rttMs, long when, int source) { |
- synchronized (mLock) { |
- mRttObservationCount++; |
- } |
- } |
- |
- @Override |
- public void onThroughputObservation(int throughputKbps, long when, int source) { |
- synchronized (mLock) { |
- if (mWaitForThroughput != null) { |
- mWaitForThroughput.open(); |
+ private class ExecutorThreadFactory implements ThreadFactory { |
+ public Thread newThread(final Runnable r) { |
+ mNetworkQualityThread = new Thread(new Runnable() { |
+ @Override |
+ public void run() { |
+ StrictMode.ThreadPolicy threadPolicy = StrictMode.getThreadPolicy(); |
+ try { |
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() |
+ .detectNetwork() |
+ .penaltyLog() |
+ .penaltyDeath() |
+ .build()); |
+ r.run(); |
+ } finally { |
+ StrictMode.setThreadPolicy(threadPolicy); |
+ } |
} |
- mThroughputObservationCount++; |
- } |
- } |
- |
- public int rttObservationCount() { |
- synchronized (mLock) { |
- return mRttObservationCount; |
- } |
- } |
- |
- public int throughputObservationCount() { |
- synchronized (mLock) { |
- return mThroughputObservationCount; |
- } |
+ }); |
+ return mNetworkQualityThread; |
} |
} |
@@ -240,15 +225,21 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
@SmallTest |
@Feature({"Cronet"}) |
public void testRealTimeNetworkQualityObservationsNotEnabled() throws Exception { |
- mTestFramework = startCronetTestFramework(); |
- TestNetworkQualityListener networkQualityListener = new TestNetworkQualityListener(null); |
+ CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); |
+ mTestFramework = |
+ startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCronetEngineBuilder); |
+ Executor networkQualityExecutor = Executors.newSingleThreadExecutor(); |
+ TestNetworkQualityRttListener rttListener = |
+ new TestNetworkQualityRttListener(networkQualityExecutor); |
+ TestNetworkQualityThroughputListener throughputListener = |
+ new TestNetworkQualityThroughputListener(networkQualityExecutor, null); |
try { |
- mTestFramework.mCronetEngine.addRttListener(networkQualityListener); |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
fail("Should throw an exception."); |
} catch (IllegalStateException e) { |
} |
try { |
- mTestFramework.mCronetEngine.addThroughputListener(networkQualityListener); |
+ mTestFramework.mCronetEngine.addThroughputListener(throughputListener); |
fail("Should throw an exception."); |
} catch (IllegalStateException e) { |
} |
@@ -257,45 +248,144 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
urlRequest.start(); |
callback.blockForDone(); |
- assertEquals(0, networkQualityListener.rttObservationCount()); |
- assertEquals(0, networkQualityListener.throughputObservationCount()); |
+ assertEquals(0, rttListener.rttObservationCount()); |
+ assertEquals(0, throughputListener.throughputObservationCount()); |
+ mTestFramework.mCronetEngine.shutdown(); |
+ } |
+ |
+ @SmallTest |
+ @Feature({"Cronet"}) |
+ public void testRealTimeNetworkQualityObservationsNotEnabled_LegacyAPI() throws Exception { |
+ mTestFramework = startCronetTestFramework(); |
+ TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); |
+ try { |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
+ fail("Should throw an exception."); |
+ } catch (IllegalStateException e) { |
+ } |
+ TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
+ UrlRequest urlRequest = |
+ mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
+ urlRequest.start(); |
+ callback.blockForDone(); |
+ assertEquals(0, rttListener.rttObservationCount()); |
mTestFramework.mCronetEngine.shutdown(); |
} |
@SmallTest |
@Feature({"Cronet"}) |
public void testRealTimeNetworkQualityObservationsListenerRemoved() throws Exception { |
+ CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); |
+ TestExecutor networkQualityExecutor = new TestExecutor(); |
+ TestNetworkQualityRttListener rttListener = |
+ new TestNetworkQualityRttListener(networkQualityExecutor); |
+ mCronetEngineBuilder.enableNetworkQualityEstimator(true); |
+ mTestFramework = |
+ startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCronetEngineBuilder); |
+ mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); |
+ |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
+ mTestFramework.mCronetEngine.removeRttListener(rttListener); |
+ TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
+ UrlRequest urlRequest = |
+ mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
+ urlRequest.start(); |
+ callback.blockForDone(); |
+ networkQualityExecutor.runAllTasks(); |
+ assertEquals(0, rttListener.rttObservationCount()); |
+ mTestFramework.mCronetEngine.shutdown(); |
+ } |
+ |
+ @SmallTest |
+ @Feature({"Cronet"}) |
+ public void testRealTimeNetworkQualityObservationsListenerRemoved_LegacyAPI() throws Exception { |
mTestFramework = startCronetTestFramework(); |
TestExecutor testExecutor = new TestExecutor(); |
- TestNetworkQualityListener networkQualityListener = new TestNetworkQualityListener(null); |
- mTestFramework.mCronetEngine.enableNetworkQualityEstimatorForTesting( |
- true, true, testExecutor); |
- mTestFramework.mCronetEngine.addRttListener(networkQualityListener); |
- mTestFramework.mCronetEngine.addThroughputListener(networkQualityListener); |
- mTestFramework.mCronetEngine.removeRttListener(networkQualityListener); |
- mTestFramework.mCronetEngine.removeThroughputListener(networkQualityListener); |
+ TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); |
+ mTestFramework.mCronetEngine.enableNetworkQualityEstimator(testExecutor); |
+ mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
+ mTestFramework.mCronetEngine.removeRttListener(rttListener); |
TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
UrlRequest urlRequest = |
mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
urlRequest.start(); |
callback.blockForDone(); |
testExecutor.runAllTasks(); |
- assertEquals(0, networkQualityListener.rttObservationCount()); |
- assertEquals(0, networkQualityListener.throughputObservationCount()); |
+ assertEquals(0, rttListener.rttObservationCount()); |
mTestFramework.mCronetEngine.shutdown(); |
} |
@SmallTest |
@Feature({"Cronet"}) |
- public void testRealTimeNetworkQualityObservations() throws Exception { |
+ public void testRealTimeNetworkQualityObservationsQuicDisabled() throws Exception { |
+ CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); |
+ Executor requestFinishedListenerExecutor = |
+ Executors.newSingleThreadExecutor(new ExecutorThreadFactory()); |
+ Executor listenersExecutor = Executors.newSingleThreadExecutor(new ExecutorThreadFactory()); |
+ ConditionVariable waitForThroughput = new ConditionVariable(); |
+ TestNetworkQualityRttListener rttListener = |
+ new TestNetworkQualityRttListener(listenersExecutor); |
+ TestNetworkQualityThroughputListener throughputListener = |
+ new TestNetworkQualityThroughputListener(listenersExecutor, waitForThroughput); |
+ mCronetEngineBuilder.enableHTTP2(true).enableQUIC(false).enableNetworkQualityEstimator( |
+ true); |
+ mTestFramework = |
+ startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCronetEngineBuilder); |
+ mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); |
+ // requestFinishedListenerExecutor should not be used for notifying the RTT and |
+ // throughput listeners. |
+ mTestFramework.mCronetEngine.setRequestFinishedListenerExecutor( |
+ requestFinishedListenerExecutor); |
+ |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
+ mTestFramework.mCronetEngine.addThroughputListener(throughputListener); |
+ |
+ TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
+ UrlRequest urlRequest = |
+ mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
+ urlRequest.start(); |
+ callback.blockForDone(); |
+ |
+ // Throughput observation is posted to the network quality estimator on the network thread |
+ // after the UrlRequest is completed. The observations are then eventually posted to |
+ // throughput listeners on the executor provided to network quality. |
+ waitForThroughput.block(); |
+ assertTrue(throughputListener.throughputObservationCount() > 0); |
+ |
+ // Check RTT observation count after throughput observation has been received. This ensures |
+ // that executor has finished posting the RTT observation to the RTT listeners. |
+ assertTrue(rttListener.rttObservationCount() > 0); |
+ |
+ // NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST |
+ assertTrue(rttListener.rttObservationCount(0) > 0); |
+ |
+ // NETWORK_QUALITY_OBSERVATION_SOURCE_TCP |
+ assertTrue(rttListener.rttObservationCount(1) > 0); |
+ |
+ // NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC |
+ assertEquals(0, rttListener.rttObservationCount(2)); |
+ |
+ // Verify that the listeners were notified on the expected thread. |
+ assertEquals(mNetworkQualityThread, rttListener.getThread()); |
+ assertEquals(mNetworkQualityThread, throughputListener.getThread()); |
+ |
+ mTestFramework.mCronetEngine.shutdown(); |
+ } |
+ |
+ @SmallTest |
+ @Feature({"Cronet"}) |
+ public void testRealTimeNetworkQualityObservations_LegacyAPI() throws Exception { |
mTestFramework = startCronetTestFramework(); |
Executor executor = Executors.newSingleThreadExecutor(); |
ConditionVariable waitForThroughput = new ConditionVariable(); |
- TestNetworkQualityListener networkQualityListener = |
- new TestNetworkQualityListener(waitForThroughput); |
- mTestFramework.mCronetEngine.enableNetworkQualityEstimatorForTesting(true, true, executor); |
- mTestFramework.mCronetEngine.addRttListener(networkQualityListener); |
- mTestFramework.mCronetEngine.addThroughputListener(networkQualityListener); |
+ TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); |
+ TestNetworkQualityThroughputListener throughputListener = |
+ new TestNetworkQualityThroughputListener(executor, waitForThroughput); |
+ mTestFramework.mCronetEngine.enableNetworkQualityEstimator(executor); |
+ mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); |
+ mTestFramework.mCronetEngine.addRttListener(rttListener); |
+ mTestFramework.mCronetEngine.addThroughputListener(throughputListener); |
TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
UrlRequest urlRequest = |
mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); |
@@ -306,15 +396,16 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
// after the UrlRequest is completed. The observations are then eventually posted to |
// throughput listeners on the executor provided to network quality. |
waitForThroughput.block(); |
- assertTrue(networkQualityListener.throughputObservationCount() > 0); |
+ assertTrue(throughputListener.throughputObservationCount() > 0); |
// Check RTT observation count after throughput observation has been received. This ensures |
// that executor has finished posting the RTT observation to the RTT listeners. |
- assertTrue(networkQualityListener.rttObservationCount() > 0); |
+ assertTrue(rttListener.rttObservationCount() > 0); |
mTestFramework.mCronetEngine.shutdown(); |
} |
+ // TODO(tbansal): http://crbug.com/618034 Remove this. |
private static class TestRequestFinishedListener |
implements CronetEngine.RequestFinishedListener { |
private UrlRequestInfo mRequestInfo = null; |
@@ -330,7 +421,7 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
@SmallTest |
@Feature({"Cronet"}) |
@SuppressWarnings("deprecation") |
- public void testRequestFinishedListener() throws Exception { |
+ public void testRequestFinishedListener_LegacyAPI() throws Exception { |
mTestFramework = startCronetTestFramework(); |
TestExecutor testExecutor = new TestExecutor(); |
TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); |
@@ -360,13 +451,50 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
mTestFramework.mCronetEngine.shutdown(); |
} |
+ @SmallTest |
+ @Feature({"Cronet"}) |
+ @SuppressWarnings("deprecation") |
+ public void testRequestFinishedListenerWithExecutorSetLater_LegacyAPI() throws Exception { |
+ CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); |
+ TestExecutor testExecutor = new TestExecutor(); |
+ mCronetEngineBuilder.enableHTTP2(true).enableQUIC(false).enableNetworkQualityEstimator( |
+ true); |
+ mTestFramework = |
+ startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, mCronetEngineBuilder); |
+ TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); |
+ mTestFramework.mCronetEngine.setRequestFinishedListenerExecutor(testExecutor); |
+ mTestFramework.mCronetEngine.addRequestFinishedListener(requestFinishedListener); |
+ TestUrlRequestCallback callback = new TestUrlRequestCallback(); |
+ UrlRequest.Builder urlRequestBuilder = new UrlRequest.Builder( |
+ mUrl, callback, callback.getExecutor(), mTestFramework.mCronetEngine); |
+ urlRequestBuilder.addRequestAnnotation("request annotation") |
+ .addRequestAnnotation(this) |
+ .build() |
+ .start(); |
+ callback.blockForDone(); |
+ testExecutor.runAllTasks(); |
+ |
+ CronetEngine.UrlRequestInfo requestInfo = requestFinishedListener.mRequestInfo; |
+ assertNotNull("RequestFinishedListener must be called", requestInfo); |
+ assertEquals(mUrl, requestInfo.getUrl()); |
+ assertNotNull(requestInfo.getResponseInfo()); |
+ assertEquals(newHashSet("request annotation", this), // Use sets for unordered comparison. |
+ new HashSet<Object>(requestInfo.getAnnotations())); |
+ CronetEngine.UrlRequestMetrics metrics = requestInfo.getMetrics(); |
+ assertNotNull("UrlRequestInfo.getMetrics() must not be null", metrics); |
+ assertTrue(metrics.getTotalTimeMs() > 0); |
+ assertTrue(metrics.getTotalTimeMs() >= metrics.getTtfbMs()); |
+ assertTrue(metrics.getReceivedBytesCount() > 0); |
+ mTestFramework.mCronetEngine.shutdown(); |
+ } |
+ |
/* |
@SmallTest |
@Feature({"Cronet"}) |
@SuppressWarnings("deprecation") |
*/ |
@FlakyTest(message = "https://crbug.com/592444") |
- public void testRequestFinishedListenerFailedRequest() throws Exception { |
+ public void testRequestFinishedListenerFailedRequest_LegacyAPI() throws Exception { |
String connectionRefusedUrl = "http://127.0.0.1:3"; |
mTestFramework = startCronetTestFramework(); |
TestExecutor testExecutor = new TestExecutor(); |
@@ -396,7 +524,7 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
@SmallTest |
@Feature({"Cronet"}) |
@SuppressWarnings("deprecation") |
- public void testRequestFinishedListenerRemoved() throws Exception { |
+ public void testRequestFinishedListenerRemoved_LegacyAPI() throws Exception { |
mTestFramework = startCronetTestFramework(); |
TestExecutor testExecutor = new TestExecutor(); |
TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); |
@@ -418,7 +546,7 @@ public class CronetUrlRequestContextTest extends CronetTestBase { |
@SmallTest |
@Feature({"Cronet"}) |
@SuppressWarnings("deprecation") |
- public void testRequestFinishedListenerDisabled() throws Exception { |
+ public void testRequestFinishedListenerDisabled_LegacyAPI() throws Exception { |
mTestFramework = startCronetTestFramework(); |
TestExecutor testExecutor = new TestExecutor(); |
TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); |