diff options
Diffstat (limited to 'src/test/java/com/android/volley/RequestQueueTest.java')
-rw-r--r-- | src/test/java/com/android/volley/RequestQueueTest.java | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/test/java/com/android/volley/RequestQueueTest.java b/src/test/java/com/android/volley/RequestQueueTest.java new file mode 100644 index 0000000..cc88d3b --- /dev/null +++ b/src/test/java/com/android/volley/RequestQueueTest.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import com.android.volley.Request.Priority; +import com.android.volley.mock.MockNetwork; +import com.android.volley.mock.MockRequest; +import com.android.volley.toolbox.NoCache; +import com.android.volley.utils.CacheTestUtils; +import com.android.volley.utils.ImmediateResponseDelivery; + +import android.os.SystemClock; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implements; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.*; + +// TODO: Resurrect these tests when we have something like a finish() observer. +// They are really gross as-is and depend on a bunch of sleeping and whatnot. +@Ignore +@RunWith(RobolectricTestRunner.class) +public class RequestQueueTest { + private ResponseDelivery mDelivery; + + @Before public void setUp() throws Exception { + mDelivery = new ImmediateResponseDelivery(); + } + + /** + * Make a list of requests with random priorities. + * @param count Number of requests to make + */ + private List<MockRequest> makeRequests(int count) { + Request.Priority[] allPriorities = Request.Priority.values(); + Random random = new Random(); + + List<MockRequest> requests = new ArrayList<MockRequest>(); + for (int i = 0; i < count; i++) { + MockRequest request = new MockRequest(); + Request.Priority priority = allPriorities[random.nextInt(allPriorities.length)]; + request.setCacheKey(String.valueOf(i)); + request.setPriority(priority); + requests.add(request); + } + return requests; + } + + @Test public void add_requestProcessedInCorrectOrder() throws Exception { + int requestsToMake = 100; + + OrderCheckingNetwork network = new OrderCheckingNetwork(); + RequestQueue queue = new RequestQueue(new NoCache(), network, 1, mDelivery); + + for (Request<?> request : makeRequests(requestsToMake)) { + queue.add(request); + } + + network.setExpectedRequests(requestsToMake); + queue.start(); + network.waitUntilExpectedDone(2000); // 2 seconds + queue.stop(); + } + + @Test public void add_dedupeByCacheKey() throws Exception { + OrderCheckingNetwork network = new OrderCheckingNetwork(); + final AtomicInteger parsed = new AtomicInteger(); + final AtomicInteger delivered = new AtomicInteger(); + // Enqueue 2 requests with the same cache key. The first request takes 1.5s. Assert that the + // second request is only handled after the first one has been parsed and delivered. + DelayedRequest req1 = new DelayedRequest(1500, parsed, delivered); + DelayedRequest req2 = new DelayedRequest(0, parsed, delivered) { + @Override + protected Response<Object> parseNetworkResponse(NetworkResponse response) { + assertEquals(1, parsed.get()); // req1 must have been parsed. + assertEquals(1, delivered.get()); // req1 must have been parsed. + return super.parseNetworkResponse(response); + } + }; + network.setExpectedRequests(2); + RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery); + queue.add(req1); + queue.add(req2); + queue.start(); + network.waitUntilExpectedDone(2000); + queue.stop(); + } + + @Test public void cancelAll_onlyCorrectTag() throws Exception { + MockNetwork network = new MockNetwork(); + RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery); + Object tagA = new Object(); + Object tagB = new Object(); + MockRequest req1 = new MockRequest(); + req1.setTag(tagA); + MockRequest req2 = new MockRequest(); + req2.setTag(tagB); + MockRequest req3 = new MockRequest(); + req3.setTag(tagA); + MockRequest req4 = new MockRequest(); + req4.setTag(tagA); + + queue.add(req1); // A + queue.add(req2); // B + queue.add(req3); // A + queue.cancelAll(tagA); + queue.add(req4); // A + + assertTrue(req1.cancel_called); // A cancelled + assertFalse(req2.cancel_called); // B not cancelled + assertTrue(req3.cancel_called); // A cancelled + assertFalse(req4.cancel_called); // A added after cancel not cancelled + } + + private class OrderCheckingNetwork implements Network { + private Priority mLastPriority = Priority.IMMEDIATE; + private int mLastSequence = -1; + private Semaphore mSemaphore; + + public void setExpectedRequests(int expectedRequests) { + // Leave one permit available so the waiter can find it. + expectedRequests--; + mSemaphore = new Semaphore(-expectedRequests); + } + + public void waitUntilExpectedDone(long timeout) + throws InterruptedException, TimeoutError { + if (mSemaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS) == false) { + throw new TimeoutError(); + } + } + + @Override + public NetworkResponse performRequest(Request<?> request) { + Priority thisPriority = request.getPriority(); + int thisSequence = request.getSequence(); + + int priorityDiff = thisPriority.compareTo(mLastPriority); + + // Should never experience a higher priority after a lower priority + assertFalse(priorityDiff > 0); + + // If we're not transitioning to a new priority block, check sequence numbers + if (priorityDiff == 0) { + assertTrue(thisSequence > mLastSequence); + } + mLastSequence = thisSequence; + mLastPriority = thisPriority; + + mSemaphore.release(); + return new NetworkResponse(new byte[16]); + } + } + + private class DelayedRequest extends Request<Object> { + private final long mDelayMillis; + private final AtomicInteger mParsedCount; + private final AtomicInteger mDeliveredCount; + + public DelayedRequest(long delayMillis, AtomicInteger parsed, AtomicInteger delivered) { + super(Request.Method.GET, "http://buganizer/", null); + mDelayMillis = delayMillis; + mParsedCount = parsed; + mDeliveredCount = delivered; + } + + @Override + protected Response<Object> parseNetworkResponse(NetworkResponse response) { + mParsedCount.incrementAndGet(); + SystemClock.sleep(mDelayMillis); + return Response.success(new Object(), CacheTestUtils.makeRandomCacheEntry(null)); + } + + @Override + protected void deliverResponse(Object response) { + mDeliveredCount.incrementAndGet(); + } + } + +} |