RequestQueueTest.java revision b9b8dc3d98fb1a8c3f02c2c2fcc18cbd344c05cb
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.volley; 18 19import com.android.volley.Request.Priority; 20import com.android.volley.mock.MockNetwork; 21import com.android.volley.mock.MockRequest; 22import com.android.volley.toolbox.NoCache; 23import com.android.volley.utils.CacheTestUtils; 24import com.android.volley.utils.ImmediateResponseDelivery; 25 26import android.os.SystemClock; 27import org.junit.Before; 28import org.junit.Ignore; 29import org.junit.Test; 30import org.junit.runner.RunWith; 31import org.robolectric.RobolectricTestRunner; 32import org.robolectric.annotation.Config; 33import org.robolectric.annotation.Implements; 34 35import java.util.ArrayList; 36import java.util.List; 37import java.util.Random; 38import java.util.concurrent.Semaphore; 39import java.util.concurrent.TimeUnit; 40import java.util.concurrent.atomic.AtomicInteger; 41 42import static org.junit.Assert.*; 43 44// TODO: Resurrect these tests when we have something like a finish() observer. 45// They are really gross as-is and depend on a bunch of sleeping and whatnot. 46@Ignore 47@RunWith(RobolectricTestRunner.class) 48public class RequestQueueTest { 49 private ResponseDelivery mDelivery; 50 51 @Before public void setUp() throws Exception { 52 mDelivery = new ImmediateResponseDelivery(); 53 } 54 55 /** 56 * Make a list of requests with random priorities. 57 * @param count Number of requests to make 58 */ 59 private List<MockRequest> makeRequests(int count) { 60 Request.Priority[] allPriorities = Request.Priority.values(); 61 Random random = new Random(); 62 63 List<MockRequest> requests = new ArrayList<MockRequest>(); 64 for (int i = 0; i < count; i++) { 65 MockRequest request = new MockRequest(); 66 Request.Priority priority = allPriorities[random.nextInt(allPriorities.length)]; 67 request.setCacheKey(String.valueOf(i)); 68 request.setPriority(priority); 69 requests.add(request); 70 } 71 return requests; 72 } 73 74 @Test public void add_requestProcessedInCorrectOrder() throws Exception { 75 int requestsToMake = 100; 76 77 OrderCheckingNetwork network = new OrderCheckingNetwork(); 78 RequestQueue queue = new RequestQueue(new NoCache(), network, 1, mDelivery); 79 80 for (Request<?> request : makeRequests(requestsToMake)) { 81 queue.add(request); 82 } 83 84 network.setExpectedRequests(requestsToMake); 85 queue.start(); 86 network.waitUntilExpectedDone(2000); // 2 seconds 87 queue.stop(); 88 } 89 90 @Test public void add_dedupeByCacheKey() throws Exception { 91 OrderCheckingNetwork network = new OrderCheckingNetwork(); 92 final AtomicInteger parsed = new AtomicInteger(); 93 final AtomicInteger delivered = new AtomicInteger(); 94 // Enqueue 2 requests with the same cache key. The first request takes 1.5s. Assert that the 95 // second request is only handled after the first one has been parsed and delivered. 96 DelayedRequest req1 = new DelayedRequest(1500, parsed, delivered); 97 DelayedRequest req2 = new DelayedRequest(0, parsed, delivered) { 98 @Override 99 protected Response<Object> parseNetworkResponse(NetworkResponse response) { 100 assertEquals(1, parsed.get()); // req1 must have been parsed. 101 assertEquals(1, delivered.get()); // req1 must have been parsed. 102 return super.parseNetworkResponse(response); 103 } 104 }; 105 network.setExpectedRequests(2); 106 RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery); 107 queue.add(req1); 108 queue.add(req2); 109 queue.start(); 110 network.waitUntilExpectedDone(2000); 111 queue.stop(); 112 } 113 114 @Test public void cancelAll_onlyCorrectTag() throws Exception { 115 MockNetwork network = new MockNetwork(); 116 RequestQueue queue = new RequestQueue(new NoCache(), network, 3, mDelivery); 117 Object tagA = new Object(); 118 Object tagB = new Object(); 119 MockRequest req1 = new MockRequest(); 120 req1.setTag(tagA); 121 MockRequest req2 = new MockRequest(); 122 req2.setTag(tagB); 123 MockRequest req3 = new MockRequest(); 124 req3.setTag(tagA); 125 MockRequest req4 = new MockRequest(); 126 req4.setTag(tagA); 127 128 queue.add(req1); // A 129 queue.add(req2); // B 130 queue.add(req3); // A 131 queue.cancelAll(tagA); 132 queue.add(req4); // A 133 134 assertTrue(req1.cancel_called); // A cancelled 135 assertFalse(req2.cancel_called); // B not cancelled 136 assertTrue(req3.cancel_called); // A cancelled 137 assertFalse(req4.cancel_called); // A added after cancel not cancelled 138 } 139 140 private class OrderCheckingNetwork implements Network { 141 private Priority mLastPriority = Priority.IMMEDIATE; 142 private int mLastSequence = -1; 143 private Semaphore mSemaphore; 144 145 public void setExpectedRequests(int expectedRequests) { 146 // Leave one permit available so the waiter can find it. 147 expectedRequests--; 148 mSemaphore = new Semaphore(-expectedRequests); 149 } 150 151 public void waitUntilExpectedDone(long timeout) 152 throws InterruptedException, TimeoutError { 153 if (mSemaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS) == false) { 154 throw new TimeoutError(); 155 } 156 } 157 158 @Override 159 public NetworkResponse performRequest(Request<?> request) { 160 Priority thisPriority = request.getPriority(); 161 int thisSequence = request.getSequence(); 162 163 int priorityDiff = thisPriority.compareTo(mLastPriority); 164 165 // Should never experience a higher priority after a lower priority 166 assertFalse(priorityDiff > 0); 167 168 // If we're not transitioning to a new priority block, check sequence numbers 169 if (priorityDiff == 0) { 170 assertTrue(thisSequence > mLastSequence); 171 } 172 mLastSequence = thisSequence; 173 mLastPriority = thisPriority; 174 175 mSemaphore.release(); 176 return new NetworkResponse(new byte[16]); 177 } 178 } 179 180 private class DelayedRequest extends Request<Object> { 181 private final long mDelayMillis; 182 private final AtomicInteger mParsedCount; 183 private final AtomicInteger mDeliveredCount; 184 185 public DelayedRequest(long delayMillis, AtomicInteger parsed, AtomicInteger delivered) { 186 super(Request.Method.GET, "http://buganizer/", null); 187 mDelayMillis = delayMillis; 188 mParsedCount = parsed; 189 mDeliveredCount = delivered; 190 } 191 192 @Override 193 protected Response<Object> parseNetworkResponse(NetworkResponse response) { 194 mParsedCount.incrementAndGet(); 195 SystemClock.sleep(mDelayMillis); 196 return Response.success(new Object(), CacheTestUtils.makeRandomCacheEntry(null)); 197 } 198 199 @Override 200 protected void deliverResponse(Object response) { 201 mDeliveredCount.incrementAndGet(); 202 } 203 } 204 205} 206