13713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick/*
23713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Copyright (C) 2011 The Android Open Source Project
33713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick *
43713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Licensed under the Apache License, Version 2.0 (the "License");
53713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * you may not use this file except in compliance with the License.
63713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * You may obtain a copy of the License at
73713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick *
83713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick *      http://www.apache.org/licenses/LICENSE-2.0
93713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick *
103713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Unless required by applicable law or agreed to in writing, software
113713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * distributed under the License is distributed on an "AS IS" BASIS,
123713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * See the License for the specific language governing permissions and
143713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * limitations under the License.
153713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick */
163713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
173713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickpackage com.android.volley;
183713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
193713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.Request.Priority;
203713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.mock.MockNetwork;
213713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.mock.MockRequest;
223713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.toolbox.NoCache;
233713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.utils.CacheTestUtils;
243713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.utils.ImmediateResponseDelivery;
253713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
263713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport android.os.SystemClock;
273713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport android.test.InstrumentationTestCase;
283713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport android.test.UiThreadTest;
29cebf98c8edef6b3506258ddb68266febadd0db1aJeff Sharkeyimport android.test.suitebuilder.annotation.LargeTest;
303713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
313713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.ArrayList;
323713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.List;
333713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.Random;
343713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.concurrent.Semaphore;
353713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.concurrent.TimeUnit;
363713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.concurrent.atomic.AtomicInteger;
373713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
38cebf98c8edef6b3506258ddb68266febadd0db1aJeff Sharkey@LargeTest
393713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickpublic class RequestQueueTest extends InstrumentationTestCase {
403713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    private ResponseDelivery mDelivery;
413713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
423713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    @Override
433713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    protected void setUp() throws Exception {
443713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        super.setUp();
453713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
463713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        mDelivery = new ImmediateResponseDelivery();
473713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
483713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
493713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    /**
503713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick     * Make a list of requests with random priorities.
513713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick     * @param count Number of requests to make
523713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick     */
533713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    private List<MockRequest> makeRequests(int count) {
543713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        Request.Priority[] allPriorities = Request.Priority.values();
553713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        Random random = new Random();
563713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
573713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        List<MockRequest> requests = new ArrayList<MockRequest>();
583713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (int i = 0; i < count; i++) {
593713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            MockRequest request = new MockRequest();
603713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            Request.Priority priority = allPriorities[random.nextInt(allPriorities.length)];
613713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            request.setCacheKey(String.valueOf(i));
623713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            request.setPriority(priority);
633713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            requests.add(request);
643713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
653713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        return requests;
663713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
673713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
683713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    @UiThreadTest
693713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    public void testAdd_requestProcessedInCorrectOrder() throws Exception {
703713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        int requestsToMake = 100;
713713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
723713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        OrderCheckingNetwork network = new OrderCheckingNetwork();
733713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        RequestQueue queue = new RequestQueue(new NoCache(), network, 1, mDelivery);
743713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
753713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (Request<?> request : makeRequests(requestsToMake)) {
763713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.add(request);
773713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
783713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
793713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.setExpectedRequests(requestsToMake);
803713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.start();
813713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.waitUntilExpectedDone(2000); // 2 seconds
823713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.stop();
833713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
843713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
853713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    public void testAdd_dedupeByCacheKey() throws Exception {
863713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        OrderCheckingNetwork network = new OrderCheckingNetwork();
873713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        final AtomicInteger parsed = new AtomicInteger();
883713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        final AtomicInteger delivered = new AtomicInteger();
893713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Enqueue 2 requests with the same cache key. The first request takes 1.5s. Assert that the
903713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // second request is only handled after the first one has been parsed and delivered.
913713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        DelayedRequest req1 = new DelayedRequest(1500, parsed, delivered);
923713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        DelayedRequest req2 = new DelayedRequest(0, parsed, delivered) {
933713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            @Override
943713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            protected Response<Object> parseNetworkResponse(NetworkResponse response) {
953713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                assertEquals(1, parsed.get());  // req1 must have been parsed.
963713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                assertEquals(1, delivered.get());  // req1 must have been parsed.
973713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                return super.parseNetworkResponse(response);
983713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            }
993713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        };
1003713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.setExpectedRequests(2);
1013713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery);
1023713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.add(req1);
1033713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.add(req2);
1043713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.start();
1053713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.waitUntilExpectedDone(2000);
1063713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.stop();
1073713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
1083713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
10919a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick    public void testCancelAll_onlyCorrectTag() throws Exception {
11019a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        MockNetwork network = new MockNetwork();
11119a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery);
11219a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        Object tagA = new Object();
11319a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        Object tagB = new Object();
11419a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        MockRequest req1 = new MockRequest();
11519a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        req1.setTag(tagA);
11619a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        MockRequest req2 = new MockRequest();
11719a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        req2.setTag(tagB);
11819a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        MockRequest req3 = new MockRequest();
11919a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        req3.setTag(tagA);
12019a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        MockRequest req4 = new MockRequest();
12119a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        req4.setTag(tagA);
12219a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick
12319a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        queue.add(req1); // A
12419a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        queue.add(req2); // B
12519a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        queue.add(req3); // A
12619a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        queue.cancelAll(tagA);
12719a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        queue.add(req4); // A
12819a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick
12919a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        assertTrue(req1.cancel_called); // A cancelled
13019a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        assertFalse(req2.cancel_called); // B not cancelled
13119a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        assertTrue(req3.cancel_called); // A cancelled
13219a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick        assertFalse(req4.cancel_called); // A added after cancel not cancelled
13319a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick    }
13419a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick
1353713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    private class OrderCheckingNetwork implements Network {
1363713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private Priority mLastPriority = Priority.IMMEDIATE;
1373713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private int mLastSequence = -1;
1383713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private Semaphore mSemaphore;
1393713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1403713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        public void setExpectedRequests(int expectedRequests) {
1413713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // Leave one permit available so the waiter can find it.
1423713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            expectedRequests--;
1433713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mSemaphore = new Semaphore(-expectedRequests);
1443713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
1453713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1463713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        public void waitUntilExpectedDone(long timeout)
1473713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                throws InterruptedException, TimeoutError {
1483713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            if (mSemaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS) == false) {
1493713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                throw new TimeoutError();
1503713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            }
1513713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
1523713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1533713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        @Override
1543713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        public NetworkResponse performRequest(Request<?> request) {
1553713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            Priority thisPriority = request.getPriority();
1563713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            int thisSequence = request.getSequence();
1573713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1583713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            int priorityDiff = thisPriority.compareTo(mLastPriority);
1593713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1603713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // Should never experience a higher priority after a lower priority
1613713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            assertFalse(priorityDiff > 0);
1623713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1633713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // If we're not transitioning to a new priority block, check sequence numbers
1643713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            if (priorityDiff == 0) {
1653713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                assertTrue(thisSequence > mLastSequence);
1663713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            }
1673713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mLastSequence = thisSequence;
1683713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mLastPriority = thisPriority;
1693713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1703713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mSemaphore.release();
1713713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            return new NetworkResponse(new byte[16]);
1723713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
1733713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
1743713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1753713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    @UiThreadTest
17619a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick    @SuppressWarnings("deprecation")
1773713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    public void testDrain_suppressesEarlierResponses() {
1783713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        MockNetwork network = new MockNetwork();
1793713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.setDataToReturn(new byte[128]);
1803713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        RequestQueue queue = new RequestQueue(new NoCache(), network, 4, mDelivery);
1813713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1823713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        int requestsBefore = 40;
1833713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        AtomicInteger parsedBefore = new AtomicInteger();
1843713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        AtomicInteger deliveredBefore = new AtomicInteger();
1853713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1863713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Start the queue and add a bunch of requests to it.
1873713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.start();
1883713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (int i = 0; i < requestsBefore; i++) {
1893713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // Make each request take 50 ms.
1903713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            DelayedRequest request = new DelayedRequest(50, parsedBefore, deliveredBefore);
1913713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.add(request);
1923713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
1933713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Sleep for a jiffy to let some of the slow requests be scheduled.
1943713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        SystemClock.sleep(5);
1953713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
1963713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Drain the queue.  None of the original requests should be delivered
1973713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // because they are still waiting to parse.
1983713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.drain();
1993713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2003713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Add some requests afterward to make sure not only that the ones before
2013713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // the drain were not delivered, but that ones afterward are.
2023713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        int requestsAfter = 10;
2033713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        AtomicInteger parsedAfter = new AtomicInteger();
2043713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        AtomicInteger deliveredAfter = new AtomicInteger();
2053713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (int i = 0; i < requestsAfter; i++) {
2063713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // These ones are much faster...
2073713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            DelayedRequest request = new DelayedRequest(1, parsedAfter, deliveredAfter);
2083713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.add(request);
2093713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2103713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2113713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Wait up to 1 second to finish
2123713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (int i = 0; i < 10; i++) {
2133713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            if (deliveredAfter.get() != requestsAfter) {
2143713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                SystemClock.sleep(100);
2153713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                continue;
2163713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            }
2173713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2183713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            assertEquals(deliveredAfter.get(), requestsAfter);
2193713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // Make sure that all "after" requests were parsed
2203713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            assertEquals(parsedAfter.get(), requestsAfter);
2213713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2223713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // Make sure that at least one of the "before" requests was parsed
2233713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            assertTrue(parsedBefore.get() > 0);
2243713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // And that none of them are delivered
2253713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            assertEquals(0, deliveredBefore.get());
2263713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.stop();
2273713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            return;
2283713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2293713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2303713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        fail("Timed out waiting for requests to complete");
2313713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
2323713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2333713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    @UiThreadTest
23419a56e8495477bfd89e4c4913860fdbcb7beb504Ficus Kirkpatrick    @SuppressWarnings("deprecation")
2353713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    public void testDrain_preservesUndrainable() {
2363713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        MockNetwork network = new MockNetwork();
2373713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        network.setDataToReturn(new byte[128]);
2383713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        RequestQueue queue = new RequestQueue(new NoCache(), network, 4, mDelivery);
2393713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2403713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Make a bunch of requests
2413713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        List<MockRequest> requests = makeRequests(50);
2423713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2433713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Pick one to be invincible.
2443713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        MockRequest invincible = requests.get(new Random().nextInt(requests.size()));
2453713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        invincible.setDrainable(false);
2463713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2473713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Add them all to the queue.
2483713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (MockRequest request : requests) {
2493713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.add(request);
2503713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2513713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2523713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Drain the queue.
2533713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.drain();
2543713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2553713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Start the queue.
2563713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        queue.start();
2573713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2583713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        // Wait up to 1 second to finish
2593713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        for (int i = 0; i < 10; i++) {
2603713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            if (!invincible.parseResponse_called) {
2613713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                SystemClock.sleep(100);
2623713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick                continue;
2633713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            }
2643713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            // If parseResponse got called, that's good enough
2653713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            queue.stop();
2663713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            return;
2673713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2683713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2693713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        fail("Undrainable request should have been parsed");
2703713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
2713713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2723713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    private class DelayedRequest extends Request<Object> {
2733713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private final long mDelayMillis;
2743713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private final AtomicInteger mParsedCount;
2753713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        private final AtomicInteger mDeliveredCount;
2763713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2773713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        public DelayedRequest(long delayMillis, AtomicInteger parsed, AtomicInteger delivered) {
2783713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            super("http://buganizer/", null);
2793713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mDelayMillis = delayMillis;
2803713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mParsedCount = parsed;
2813713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mDeliveredCount = delivered;
2823713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2833713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2843713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        @Override
2853713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        protected Response<Object> parseNetworkResponse(NetworkResponse response) {
2863713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mParsedCount.incrementAndGet();
2873713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            SystemClock.sleep(mDelayMillis);
2883713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            return Response.success(new Object(), CacheTestUtils.makeRandomCacheEntry(null));
2893713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2903713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2913713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        @Override
2923713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        protected void deliverResponse(Object response) {
2933713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick            mDeliveredCount.incrementAndGet();
2943713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick        }
2953713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick    }
2963713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick
2973713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick}
298