Chromium Code Reviews| Index: components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUploadTest.java |
| diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUploadTest.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUploadTest.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c5c34561d3b7307f27d7aa8defb2c43961be6be5 |
| --- /dev/null |
| +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUploadTest.java |
| @@ -0,0 +1,232 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.cronet_test_apk; |
| + |
| +import android.test.suitebuilder.annotation.SmallTest; |
| + |
| +import org.chromium.base.test.util.Feature; |
| +import org.chromium.net.CronetUploadDataStream; |
| + |
| +import java.util.Arrays; |
| +import java.util.List; |
| +import java.util.concurrent.ExecutorService; |
| +import java.util.concurrent.Executors; |
| + |
| +/** |
| + * Tests that directly drive {@code CronetUploadDataStream} and |
| + * {@code UploadDataProvider} to simulate different ordering of reset, init, |
| + * read, and rewind calls. |
| + */ |
| +public class CronetUploadTest extends CronetTestBase { |
| + private TestDrivenDataProvider mDataProvider; |
| + private CronetUploadDataStream mUploadDataStream; |
| + private UploadDataStreamHandler mHandler; |
| + |
| + @Override |
| + protected void setUp() throws Exception { |
| + super.setUp(); |
| + launchCronetTestApp(); |
| + ExecutorService executor = Executors.newSingleThreadExecutor(); |
| + List<byte[]> reads = Arrays.asList("hello".getBytes()); |
| + mDataProvider = new TestDrivenDataProvider(executor, reads); |
| + mUploadDataStream = new CronetUploadDataStream(mDataProvider, executor); |
| + mHandler = new UploadDataStreamHandler( |
| + mUploadDataStream.createAdapter()); |
| + } |
| + |
| + @Override |
| + protected void tearDown() throws Exception { |
| + // Destroy handler's native objects. |
| + mHandler.destroyNativeObjects(); |
| + super.tearDown(); |
| + } |
| + |
| + /** |
| + * Tests that after some data is read, init triggers a rewind, and that |
| + * before the rewind completes, init blocks. |
| + */ |
| + @SmallTest |
| + @Feature({"Cronet"}) |
| + public void testInitTriggersRewindAndInitBeforeRewindCompletes() |
| + throws Exception { |
| + // Init completes synchronously and read succeeds. |
| + assertTrue(mHandler.init()); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mHandler.waitForReadComplete(); |
| + mDataProvider.assertReadNotPending(); |
| + assertEquals(0, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("hello", mHandler.getData()); |
| + |
| + // Reset and then init, which should trigger a rewind. |
| + mHandler.reset(); |
| + assertEquals("", mHandler.getData()); |
| + assertFalse(mHandler.init()); |
| + mDataProvider.waitForRewindRequest(); |
| + mHandler.checkInitCallbackNotInvoked(); |
| + |
| + // Before rewind completes, reset and init should block. |
| + mHandler.reset(); |
| + assertFalse(mHandler.init()); |
| + |
| + // Signal rewind completes, and wait for init to complete. |
| + mHandler.resetWaitForInitComplete(); |
| + mDataProvider.onRewindSucceeded(mUploadDataStream); |
| + mHandler.waitForInitComplete(); |
| + mDataProvider.assertRewindNotPending(); |
| + |
| + // Read should complete successfully since init has completed. |
| + mDataProvider.resetWaitForReadRequest(); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mHandler.resetWaitForReadComplete(); |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mHandler.waitForReadComplete(); |
| + mDataProvider.assertReadNotPending(); |
| + assertEquals(1, mDataProvider.getNumRewindCalls()); |
| + assertEquals(2, mDataProvider.getNumReadCalls()); |
| + assertEquals("hello", mHandler.getData()); |
| + } |
| + |
| + /** |
| + * Tests that after some data is read, init triggers a rewind, and that |
| + * after the rewind completes, init does not block. |
| + */ |
| + @SmallTest |
| + @Feature({"Cronet"}) |
| + public void testInitTriggersRewindAndInitAfterRewindCompletes() |
| + throws Exception { |
| + // Init completes synchronously and read succeeds. |
| + assertTrue(mHandler.init()); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mHandler.waitForReadComplete(); |
| + mDataProvider.assertReadNotPending(); |
| + assertEquals(0, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("hello", mHandler.getData()); |
| + |
| + // Reset and then init, which should trigger a rewind. |
| + mHandler.reset(); |
| + assertEquals("", mHandler.getData()); |
| + assertFalse(mHandler.init()); |
| + mDataProvider.waitForRewindRequest(); |
| + mHandler.checkInitCallbackNotInvoked(); |
| + |
| + // Signal rewind completes, and wait for init to complete. |
| + mHandler.resetWaitForInitComplete(); |
| + mDataProvider.onRewindSucceeded(mUploadDataStream); |
| + mHandler.waitForInitComplete(); |
| + mDataProvider.assertRewindNotPending(); |
| + |
| + // Reset and init should not block, since rewind has completed. |
| + mHandler.reset(); |
| + assertTrue(mHandler.init()); |
| + |
| + // Read should complete successfully since init has completed. |
| + mDataProvider.resetWaitForReadRequest(); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mHandler.resetWaitForReadComplete(); |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mHandler.waitForReadComplete(); |
| + mDataProvider.assertReadNotPending(); |
| + assertEquals(1, mDataProvider.getNumRewindCalls()); |
| + assertEquals(2, mDataProvider.getNumReadCalls()); |
| + assertEquals("hello", mHandler.getData()); |
| + } |
| + |
| + /** |
| + * Tests that if init before read completes, a rewind is triggered when |
| + * read completes. |
| + */ |
| + @SmallTest |
| + @Feature({"Cronet"}) |
| + public void testReadCompleteTriggerRewind() throws Exception { |
| + // Reset and init before read completes. |
| + assertTrue(mHandler.init()); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mHandler.reset(); |
| + // Init should return asynchronously, since there is a pending read. |
| + assertFalse(mHandler.init()); |
| + mDataProvider.assertRewindNotPending(); |
| + mHandler.checkInitCallbackNotInvoked(); |
| + assertEquals(0, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("", mHandler.getData()); |
| + |
| + // Read completes should trigger a rewind. |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mDataProvider.waitForRewindRequest(); |
| + mHandler.resetWaitForInitComplete(); |
| + mDataProvider.onRewindSucceeded(mUploadDataStream); |
| + mHandler.waitForInitComplete(); |
| + mDataProvider.assertRewindNotPending(); |
| + assertEquals(1, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("", mHandler.getData()); |
| + } |
| + |
| + /** |
| + * Tests that when init again after rewind completes, no additional rewind |
| + * is triggered. This test is the same as testReadCompleteTriggerRewind |
| + * except that this test invokes reset and init again in the end. |
| + */ |
| + @SmallTest |
| + @Feature({"Cronet"}) |
| + public void testReadCompleteTriggerRewindOnlyOneRewind() throws Exception { |
| + testReadCompleteTriggerRewind(); |
| + // Reset and Init again, no rewind should happen. |
| + mHandler.reset(); |
| + assertTrue(mHandler.init()); |
| + mDataProvider.assertRewindNotPending(); |
| + assertEquals(1, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("", mHandler.getData()); |
| + } |
| + |
| + /** |
| + * Tests that if reset before read completes, no rewind is triggered, and |
| + * that a following init triggers rewind. |
| + */ |
| + @SmallTest |
| + @Feature({"Cronet"}) |
| + public void testResetBeforeReadCompleteAndInitTriggerRewind() |
| + throws Exception { |
| + // Reset before read completes. Rewind is not triggered. |
| + assertTrue(mHandler.init()); |
| + mHandler.read(); |
| + mDataProvider.waitForReadRequest(); |
| + mHandler.checkReadCallbackNotInvoked(); |
| + mHandler.reset(); |
| + mDataProvider.onReadSucceeded(mUploadDataStream); |
| + mDataProvider.assertReadNotPending(); |
|
xunjieli
2015/02/02 17:06:01
There is a race condition here. assertReadNotPendi
xunjieli
2015/02/02 18:25:42
Done.
mmenke
2015/02/02 18:26:12
Right, that's why we had the asserts jumping over
|
| + mDataProvider.assertRewindNotPending(); |
| + assertEquals(0, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("", mHandler.getData()); |
| + |
| + // Init should trigger a rewind. |
| + assertFalse(mHandler.init()); |
| + mDataProvider.waitForRewindRequest(); |
| + mHandler.checkInitCallbackNotInvoked(); |
| + mHandler.resetWaitForInitComplete(); |
| + mDataProvider.onRewindSucceeded(mUploadDataStream); |
| + mHandler.waitForInitComplete(); |
| + mDataProvider.assertRewindNotPending(); |
| + assertEquals(1, mDataProvider.getNumRewindCalls()); |
| + assertEquals(1, mDataProvider.getNumReadCalls()); |
| + assertEquals("", mHandler.getData()); |
| + } |
| +} |