Home | History | Annotate | Download | only in volley
      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 
     17 package com.android.volley;
     18 
     19 import com.android.volley.mock.MockCache;
     20 import com.android.volley.mock.MockRequest;
     21 import com.android.volley.mock.MockResponseDelivery;
     22 import com.android.volley.mock.WaitableQueue;
     23 import com.android.volley.utils.CacheTestUtils;
     24 
     25 import org.junit.After;
     26 import org.junit.Before;
     27 import org.junit.Test;
     28 import org.junit.runner.RunWith;
     29 import org.robolectric.RobolectricTestRunner;
     30 
     31 import static org.junit.Assert.*;
     32 
     33 @RunWith(RobolectricTestRunner.class)
     34 @SuppressWarnings("rawtypes")
     35 public class CacheDispatcherTest {
     36     private CacheDispatcher mDispatcher;
     37     private WaitableQueue mCacheQueue;
     38     private WaitableQueue mNetworkQueue;
     39     private MockCache mCache;
     40     private MockResponseDelivery mDelivery;
     41     private MockRequest mRequest;
     42 
     43     private static final long TIMEOUT_MILLIS = 5000;
     44 
     45     @Before public void setUp() throws Exception {
     46         mCacheQueue = new WaitableQueue();
     47         mNetworkQueue = new WaitableQueue();
     48         mCache = new MockCache();
     49         mDelivery = new MockResponseDelivery();
     50 
     51         mRequest = new MockRequest();
     52 
     53         mDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
     54         mDispatcher.start();
     55     }
     56 
     57     @After public void tearDown() throws Exception {
     58         mDispatcher.quit();
     59         mDispatcher.join();
     60     }
     61 
     62     // A cancelled request should not be processed at all.
     63     @Test public void cancelledRequest() throws Exception {
     64         mRequest.cancel();
     65         mCacheQueue.add(mRequest);
     66         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
     67         assertFalse(mCache.getCalled);
     68         assertFalse(mDelivery.wasEitherResponseCalled());
     69     }
     70 
     71     // A cache miss does not post a response and puts the request on the network queue.
     72     @Test public void cacheMiss() throws Exception {
     73         mCacheQueue.add(mRequest);
     74         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
     75         assertFalse(mDelivery.wasEitherResponseCalled());
     76         assertTrue(mNetworkQueue.size() > 0);
     77         Request request = mNetworkQueue.take();
     78         assertNull(request.getCacheEntry());
     79     }
     80 
     81     // A non-expired cache hit posts a response and does not queue to the network.
     82     @Test public void nonExpiredCacheHit() throws Exception {
     83         Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, false);
     84         mCache.setEntryToReturn(entry);
     85         mCacheQueue.add(mRequest);
     86         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
     87         assertTrue(mDelivery.postResponse_called);
     88         assertFalse(mDelivery.postError_called);
     89     }
     90 
     91     // A soft-expired cache hit posts a response and queues to the network.
     92     @Test public void softExpiredCacheHit() throws Exception {
     93         Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true);
     94         mCache.setEntryToReturn(entry);
     95         mCacheQueue.add(mRequest);
     96         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
     97         assertTrue(mDelivery.postResponse_called);
     98         assertFalse(mDelivery.postError_called);
     99         assertTrue(mNetworkQueue.size() > 0);
    100         Request request = mNetworkQueue.take();
    101         assertSame(entry, request.getCacheEntry());
    102     }
    103 
    104     // An expired cache hit does not post a response and queues to the network.
    105     @Test public void expiredCacheHit() throws Exception {
    106         Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, true, true);
    107         mCache.setEntryToReturn(entry);
    108         mCacheQueue.add(mRequest);
    109         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
    110         assertFalse(mDelivery.wasEitherResponseCalled());
    111         assertTrue(mNetworkQueue.size() > 0);
    112         Request request = mNetworkQueue.take();
    113         assertSame(entry, request.getCacheEntry());
    114     }
    115 
    116     @Test public void duplicateCacheMiss() throws Exception {
    117         MockRequest secondRequest = new MockRequest();
    118         mRequest.setSequence(1);
    119         secondRequest.setSequence(2);
    120         mCacheQueue.add(mRequest);
    121         mCacheQueue.add(secondRequest);
    122         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
    123         assertTrue(mNetworkQueue.size() == 1);
    124         assertFalse(mDelivery.postResponse_called);
    125     }
    126 
    127     @Test public void tripleCacheMiss_networkErrorOnFirst() throws Exception {
    128         MockRequest secondRequest = new MockRequest();
    129         MockRequest thirdRequest = new MockRequest();
    130         mRequest.setSequence(1);
    131         secondRequest.setSequence(2);
    132         thirdRequest.setSequence(3);
    133         mCacheQueue.add(mRequest);
    134         mCacheQueue.add(secondRequest);
    135         mCacheQueue.add(thirdRequest);
    136         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
    137 
    138         assertTrue(mNetworkQueue.size() == 1);
    139         assertFalse(mDelivery.postResponse_called);
    140 
    141         Request request = mNetworkQueue.take();
    142         request.notifyListenerResponseNotUsable();
    143         // Second request should now be in network queue.
    144         assertTrue(mNetworkQueue.size() == 1);
    145         request = mNetworkQueue.take();
    146         assertTrue(request.equals(secondRequest));
    147         // Another unusable response, third request should now be added.
    148         request.notifyListenerResponseNotUsable();
    149         assertTrue(mNetworkQueue.size() == 1);
    150         request = mNetworkQueue.take();
    151         assertTrue(request.equals(thirdRequest));
    152     }
    153 
    154     @Test public void duplicateSoftExpiredCacheHit_failedRequest() throws Exception {
    155         Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true);
    156         mCache.setEntryToReturn(entry);
    157 
    158         MockRequest secondRequest = new MockRequest();
    159         mRequest.setSequence(1);
    160         secondRequest.setSequence(2);
    161 
    162         mCacheQueue.add(mRequest);
    163         mCacheQueue.add(secondRequest);
    164         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
    165 
    166         assertTrue(mNetworkQueue.size() == 1);
    167         assertTrue(mDelivery.postResponse_calledNtimes == 2);
    168 
    169         Request request = mNetworkQueue.take();
    170         request.notifyListenerResponseNotUsable();
    171         // Second request should now be in network queue.
    172         assertTrue(mNetworkQueue.size() == 1);
    173         request = mNetworkQueue.take();
    174         assertTrue(request.equals(secondRequest));
    175     }
    176 
    177     @Test public void duplicateSoftExpiredCacheHit_successfulRequest() throws Exception {
    178         Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true);
    179         mCache.setEntryToReturn(entry);
    180 
    181         MockRequest secondRequest = new MockRequest();
    182         mRequest.setSequence(1);
    183         secondRequest.setSequence(2);
    184 
    185         mCacheQueue.add(mRequest);
    186         mCacheQueue.add(secondRequest);
    187         mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS);
    188 
    189         assertTrue(mNetworkQueue.size() == 1);
    190         assertTrue(mDelivery.postResponse_calledNtimes == 2);
    191 
    192         Request request = mNetworkQueue.take();
    193         request.notifyListenerResponseReceived(Response.success(null, entry));
    194         // Second request should have delivered response.
    195         assertTrue(mNetworkQueue.size() == 0);
    196         assertTrue(mDelivery.postResponse_calledNtimes == 3);
    197     }
    198 }
    199