| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
 |    2 // Use of this source code is governed by a BSD-style license that can be | 
 |    3 // found in the LICENSE file. | 
 |    4  | 
 |    5 package org.chromium.net; | 
 |    6  | 
 |    7 import android.test.suitebuilder.annotation.SmallTest; | 
 |    8  | 
 |    9 import org.chromium.base.test.util.Feature; | 
 |   10  | 
 |   11 import java.util.Arrays; | 
 |   12 import java.util.List; | 
 |   13 import java.util.concurrent.ExecutorService; | 
 |   14 import java.util.concurrent.Executors; | 
 |   15  | 
 |   16 /** | 
 |   17  * Tests that directly drive {@code CronetUploadDataStream} and | 
 |   18  * {@code UploadDataProvider} to simulate different ordering of reset, init, | 
 |   19  * read, and rewind calls. | 
 |   20  */ | 
 |   21 public class CronetUploadTest extends CronetTestBase { | 
 |   22     private TestDrivenDataProvider mDataProvider; | 
 |   23     private CronetUploadDataStream mUploadDataStream; | 
 |   24     private TestUploadDataStreamHandler mHandler; | 
 |   25     // Address of native CronetUploadDataStreamAdapter object. | 
 |   26     private long mAdapter = 0; | 
 |   27  | 
 |   28     @Override | 
 |   29     protected void setUp() throws Exception { | 
 |   30         super.setUp(); | 
 |   31         launchCronetTestApp(); | 
 |   32         ExecutorService executor = Executors.newSingleThreadExecutor(); | 
 |   33         List<byte[]> reads = Arrays.asList("hello".getBytes()); | 
 |   34         mDataProvider = new TestDrivenDataProvider(executor, reads); | 
 |   35         mUploadDataStream = new CronetUploadDataStream(mDataProvider, executor); | 
 |   36         mAdapter = mUploadDataStream.createAdapterForTesting(); | 
 |   37         mHandler = new TestUploadDataStreamHandler(mAdapter); | 
 |   38     } | 
 |   39  | 
 |   40     @Override | 
 |   41     protected void tearDown() throws Exception { | 
 |   42         // Destroy handler's native objects. | 
 |   43         mHandler.destroyNativeObjects(); | 
 |   44         super.tearDown(); | 
 |   45     } | 
 |   46  | 
 |   47     /** | 
 |   48      * Tests that after some data is read, init triggers a rewind, and that | 
 |   49      * before the rewind completes, init blocks. | 
 |   50      */ | 
 |   51     @SmallTest | 
 |   52     @Feature({"Cronet"}) | 
 |   53     public void testInitTriggersRewindAndInitBeforeRewindCompletes() | 
 |   54             throws Exception { | 
 |   55         // Init completes synchronously and read succeeds. | 
 |   56         assertTrue(mHandler.init()); | 
 |   57         mHandler.read(); | 
 |   58         mDataProvider.waitForReadRequest(); | 
 |   59         mHandler.checkReadCallbackNotInvoked(); | 
 |   60         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |   61         mHandler.waitForReadComplete(); | 
 |   62         mDataProvider.assertReadNotPending(); | 
 |   63         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |   64         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |   65         assertEquals("hello", mHandler.getData()); | 
 |   66  | 
 |   67         // Reset and then init, which should trigger a rewind. | 
 |   68         mHandler.reset(); | 
 |   69         assertEquals("", mHandler.getData()); | 
 |   70         assertFalse(mHandler.init()); | 
 |   71         mDataProvider.waitForRewindRequest(); | 
 |   72         mHandler.checkInitCallbackNotInvoked(); | 
 |   73  | 
 |   74         // Before rewind completes, reset and init should block. | 
 |   75         mHandler.reset(); | 
 |   76         assertFalse(mHandler.init()); | 
 |   77  | 
 |   78         // Signal rewind completes, and wait for init to complete. | 
 |   79         mHandler.checkInitCallbackNotInvoked(); | 
 |   80         mDataProvider.onRewindSucceeded(mUploadDataStream); | 
 |   81         mHandler.waitForInitComplete(); | 
 |   82         mDataProvider.assertRewindNotPending(); | 
 |   83  | 
 |   84         // Read should complete successfully since init has completed. | 
 |   85         mHandler.read(); | 
 |   86         mDataProvider.waitForReadRequest(); | 
 |   87         mHandler.checkReadCallbackNotInvoked(); | 
 |   88         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |   89         mHandler.waitForReadComplete(); | 
 |   90         mDataProvider.assertReadNotPending(); | 
 |   91         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |   92         assertEquals(2, mDataProvider.getNumReadCalls()); | 
 |   93         assertEquals("hello", mHandler.getData()); | 
 |   94     } | 
 |   95  | 
 |   96     /** | 
 |   97      * Tests that after some data is read, init triggers a rewind, and that | 
 |   98      * after the rewind completes, init does not block. | 
 |   99      */ | 
 |  100     @SmallTest | 
 |  101     @Feature({"Cronet"}) | 
 |  102     public void testInitTriggersRewindAndInitAfterRewindCompletes() | 
 |  103             throws Exception { | 
 |  104         // Init completes synchronously and read succeeds. | 
 |  105         assertTrue(mHandler.init()); | 
 |  106         mHandler.read(); | 
 |  107         mDataProvider.waitForReadRequest(); | 
 |  108         mHandler.checkReadCallbackNotInvoked(); | 
 |  109         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  110         mHandler.waitForReadComplete(); | 
 |  111         mDataProvider.assertReadNotPending(); | 
 |  112         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |  113         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  114         assertEquals("hello", mHandler.getData()); | 
 |  115  | 
 |  116         // Reset and then init, which should trigger a rewind. | 
 |  117         mHandler.reset(); | 
 |  118         assertEquals("", mHandler.getData()); | 
 |  119         assertFalse(mHandler.init()); | 
 |  120         mDataProvider.waitForRewindRequest(); | 
 |  121         mHandler.checkInitCallbackNotInvoked(); | 
 |  122  | 
 |  123         // Signal rewind completes, and wait for init to complete. | 
 |  124         mDataProvider.onRewindSucceeded(mUploadDataStream); | 
 |  125         mHandler.waitForInitComplete(); | 
 |  126         mDataProvider.assertRewindNotPending(); | 
 |  127  | 
 |  128         // Reset and init should not block, since rewind has completed. | 
 |  129         mHandler.reset(); | 
 |  130         assertTrue(mHandler.init()); | 
 |  131  | 
 |  132         // Read should complete successfully since init has completed. | 
 |  133         mHandler.read(); | 
 |  134         mDataProvider.waitForReadRequest(); | 
 |  135         mHandler.checkReadCallbackNotInvoked(); | 
 |  136         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  137         mHandler.waitForReadComplete(); | 
 |  138         mDataProvider.assertReadNotPending(); | 
 |  139         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |  140         assertEquals(2, mDataProvider.getNumReadCalls()); | 
 |  141         assertEquals("hello", mHandler.getData()); | 
 |  142     } | 
 |  143  | 
 |  144     /** | 
 |  145      * Tests that if init before read completes, a rewind is triggered when | 
 |  146      * read completes. | 
 |  147      */ | 
 |  148     @SmallTest | 
 |  149     @Feature({"Cronet"}) | 
 |  150     public void testReadCompleteTriggerRewind() throws Exception { | 
 |  151         // Reset and init before read completes. | 
 |  152         assertTrue(mHandler.init()); | 
 |  153         mHandler.read(); | 
 |  154         mDataProvider.waitForReadRequest(); | 
 |  155         mHandler.checkReadCallbackNotInvoked(); | 
 |  156         mHandler.reset(); | 
 |  157         // Init should return asynchronously, since there is a pending read. | 
 |  158         assertFalse(mHandler.init()); | 
 |  159         mDataProvider.assertRewindNotPending(); | 
 |  160         mHandler.checkInitCallbackNotInvoked(); | 
 |  161         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |  162         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  163         assertEquals("", mHandler.getData()); | 
 |  164  | 
 |  165         // Read completes should trigger a rewind. | 
 |  166         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  167         mDataProvider.waitForRewindRequest(); | 
 |  168         mHandler.checkInitCallbackNotInvoked(); | 
 |  169         mDataProvider.onRewindSucceeded(mUploadDataStream); | 
 |  170         mHandler.waitForInitComplete(); | 
 |  171         mDataProvider.assertRewindNotPending(); | 
 |  172         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |  173         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  174         assertEquals("", mHandler.getData()); | 
 |  175     } | 
 |  176  | 
 |  177     /** | 
 |  178      * Tests that when init again after rewind completes, no additional rewind | 
 |  179      * is triggered. This test is the same as testReadCompleteTriggerRewind | 
 |  180      * except that this test invokes reset and init again in the end. | 
 |  181      */ | 
 |  182     @SmallTest | 
 |  183     @Feature({"Cronet"}) | 
 |  184     public void testReadCompleteTriggerRewindOnlyOneRewind() throws Exception { | 
 |  185         testReadCompleteTriggerRewind(); | 
 |  186         // Reset and Init again, no rewind should happen. | 
 |  187         mHandler.reset(); | 
 |  188         assertTrue(mHandler.init()); | 
 |  189         mDataProvider.assertRewindNotPending(); | 
 |  190         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |  191         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  192         assertEquals("", mHandler.getData()); | 
 |  193     } | 
 |  194  | 
 |  195     /** | 
 |  196      * Tests that if reset before read completes, no rewind is triggered, and | 
 |  197      * that a following init triggers rewind. | 
 |  198      */ | 
 |  199     @SmallTest | 
 |  200     @Feature({"Cronet"}) | 
 |  201     public void testResetBeforeReadCompleteAndInitTriggerRewind() | 
 |  202             throws Exception { | 
 |  203         // Reset before read completes. Rewind is not triggered. | 
 |  204         assertTrue(mHandler.init()); | 
 |  205         mHandler.read(); | 
 |  206         mDataProvider.waitForReadRequest(); | 
 |  207         mHandler.checkReadCallbackNotInvoked(); | 
 |  208         mHandler.reset(); | 
 |  209         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  210         mDataProvider.assertRewindNotPending(); | 
 |  211         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |  212         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  213         assertEquals("", mHandler.getData()); | 
 |  214  | 
 |  215         // Init should trigger a rewind. | 
 |  216         assertFalse(mHandler.init()); | 
 |  217         mDataProvider.waitForRewindRequest(); | 
 |  218         mHandler.checkInitCallbackNotInvoked(); | 
 |  219         mDataProvider.onRewindSucceeded(mUploadDataStream); | 
 |  220         mHandler.waitForInitComplete(); | 
 |  221         mDataProvider.assertRewindNotPending(); | 
 |  222         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |  223         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  224         assertEquals("", mHandler.getData()); | 
 |  225     } | 
 |  226  | 
 |  227     /** | 
 |  228      * Tests that there is no crash when native CronetUploadDataStreamAdapter is | 
 |  229      * destroyed while read is pending. The test is racy since read could | 
 |  230      * complete either before or after onDestroyAdapter() is called in | 
 |  231      * CronetUploadDataStream. However, the test should pass either way, though | 
 |  232      * we are interested in the latter case. | 
 |  233      */ | 
 |  234     @SmallTest | 
 |  235     @Feature({"Cronet"}) | 
 |  236     public void testDestroyAdapterBeforeReadComplete() | 
 |  237             throws Exception { | 
 |  238         // Start a read and wait for it to be pending. | 
 |  239         assertTrue(mHandler.init()); | 
 |  240         mHandler.read(); | 
 |  241         mDataProvider.waitForReadRequest(); | 
 |  242         mHandler.checkReadCallbackNotInvoked(); | 
 |  243  | 
 |  244         // Destroy the C++ object, which should trigger the Java | 
 |  245         // onAdapterDestroyed() which should block until the read completes. | 
 |  246         mAdapter = 0; | 
 |  247  | 
 |  248         // Make the read complete should not encounter a crash. | 
 |  249         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  250  | 
 |  251         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |  252         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  253     } | 
 |  254  | 
 |  255     /** | 
 |  256      * Tests that there is no crash when native CronetUploadDataStreamAdapter is | 
 |  257      * destroyed while rewind is pending. The test is racy since rewind could | 
 |  258      * complete either before or after onDestroyAdapter() is called in | 
 |  259      * CronetUploadDataStream. However, the test should pass either way, though | 
 |  260      * we are interested in the latter case. | 
 |  261      */ | 
 |  262     @SmallTest | 
 |  263     @Feature({"Cronet"}) | 
 |  264     public void testDestroyAdapterBeforeRewindComplete() | 
 |  265             throws Exception { | 
 |  266         // Start a read and wait for it to complete. | 
 |  267         assertTrue(mHandler.init()); | 
 |  268         mHandler.read(); | 
 |  269         mDataProvider.waitForReadRequest(); | 
 |  270         mHandler.checkReadCallbackNotInvoked(); | 
 |  271         mDataProvider.onReadSucceeded(mUploadDataStream); | 
 |  272         mHandler.waitForReadComplete(); | 
 |  273         mDataProvider.assertReadNotPending(); | 
 |  274         assertEquals(0, mDataProvider.getNumRewindCalls()); | 
 |  275         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  276         assertEquals("hello", mHandler.getData()); | 
 |  277  | 
 |  278         // Reset and then init, which should trigger a rewind. | 
 |  279         mHandler.reset(); | 
 |  280         assertEquals("", mHandler.getData()); | 
 |  281         assertFalse(mHandler.init()); | 
 |  282         mDataProvider.waitForRewindRequest(); | 
 |  283         mHandler.checkInitCallbackNotInvoked(); | 
 |  284  | 
 |  285         // Destroy the C++ object, which should trigger the Java | 
 |  286         // onAdapterDestroyed(). | 
 |  287         mAdapter = 0; | 
 |  288  | 
 |  289         // Signal rewind completes, and wait for init to complete. | 
 |  290         mHandler.checkInitCallbackNotInvoked(); | 
 |  291         mDataProvider.onRewindSucceeded(mUploadDataStream); | 
 |  292         mHandler.waitForInitComplete(); | 
 |  293         mDataProvider.assertRewindNotPending(); | 
 |  294  | 
 |  295         assertEquals(1, mDataProvider.getNumRewindCalls()); | 
 |  296         assertEquals(1, mDataProvider.getNumReadCalls()); | 
 |  297     } | 
 |  298 } | 
| OLD | NEW |