diff options
author | Anonymous <no-reply@google.com> | 2021-07-09 17:40:10 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-07-09 17:40:10 +0000 |
commit | fd5d34f4fc6ffdf0b9c31381ffee78cf73f007d3 (patch) | |
tree | cf5d56ccdb862fd9676c855f919408ef940bc019 /core/src/test/java/com/android/volley/CacheDispatcherTest.java | |
parent | 904ab87ee280c7545a908a8ea10a833385a7cf3f (diff) | |
parent | ba6983e134f8f64ced7921f506862a7fcee59d19 (diff) | |
download | volley-fd5d34f4fc6ffdf0b9c31381ffee78cf73f007d3.tar.gz |
Import of Volley from GitHub to AOSP. am: 212e7004ac am: f77c53c3a3 am: f33c2e45dc am: ba6983e134t_frc_odp_330442040t_frc_odp_330442000t_frc_con_330443020t_frc_cbr_330443000t_frc_ase_330444010t_frc_art_330443060t_frc_adb_330444000frc_340821000frc_340819280frc_340819220frc_340819190frc_340819030frc_340819020frc_340819010frc_340818170frc_340818110android-vts-14.0_r4android-vts-14.0_r3android-vts-14.0_r2android-vts-14.0_r1android-u-beta-1-gplandroid-security-14.0.0_r9android-security-14.0.0_r8android-security-14.0.0_r7android-security-14.0.0_r6android-security-14.0.0_r5android-security-14.0.0_r4android-security-14.0.0_r3android-security-14.0.0_r2android-security-14.0.0_r10android-security-14.0.0_r1android-platform-14.0.0_r9android-platform-14.0.0_r8android-platform-14.0.0_r7android-platform-14.0.0_r6android-platform-14.0.0_r5android-platform-14.0.0_r4android-platform-14.0.0_r3android-platform-14.0.0_r2android-platform-14.0.0_r1android-cts-14.0_r4android-cts-14.0_r3android-cts-14.0_r2android-cts-14.0_r1android-14.0.0_r9android-14.0.0_r8android-14.0.0_r7android-14.0.0_r6android-14.0.0_r54android-14.0.0_r53android-14.0.0_r52android-14.0.0_r51android-14.0.0_r50android-14.0.0_r5android-14.0.0_r45android-14.0.0_r44android-14.0.0_r43android-14.0.0_r42android-14.0.0_r41android-14.0.0_r40android-14.0.0_r4android-14.0.0_r39android-14.0.0_r38android-14.0.0_r37android-14.0.0_r36android-14.0.0_r35android-14.0.0_r34android-14.0.0_r33android-14.0.0_r32android-14.0.0_r31android-14.0.0_r30android-14.0.0_r3android-14.0.0_r29android-14.0.0_r28android-14.0.0_r27android-14.0.0_r26android-14.0.0_r25android-14.0.0_r24android-14.0.0_r23android-14.0.0_r22android-14.0.0_r21android-14.0.0_r20android-14.0.0_r2android-14.0.0_r19android-14.0.0_r18android-14.0.0_r17android-14.0.0_r16android-14.0.0_r15android-14.0.0_r14android-14.0.0_r13android-14.0.0_r12android-14.0.0_r11android-14.0.0_r10android-14.0.0_r1android-13.0.0_r83android-13.0.0_r82android-13.0.0_r81android-13.0.0_r80android-13.0.0_r79android-13.0.0_r78android-13.0.0_r77android-13.0.0_r76android-13.0.0_r75android-13.0.0_r74android-13.0.0_r73android-13.0.0_r72android-13.0.0_r71android-13.0.0_r70android-13.0.0_r69android-13.0.0_r68android-13.0.0_r67android-13.0.0_r66android-13.0.0_r65android-13.0.0_r64android-13.0.0_r63android-13.0.0_r62android-13.0.0_r61android-13.0.0_r60android-13.0.0_r59android-13.0.0_r58android-13.0.0_r57android-13.0.0_r56android-13.0.0_r55android-13.0.0_r54android-13.0.0_r53android-13.0.0_r52android-13.0.0_r51android-13.0.0_r50android-13.0.0_r49android-13.0.0_r48android-13.0.0_r47android-13.0.0_r46android-13.0.0_r45android-13.0.0_r44android-13.0.0_r43android-13.0.0_r42android-13.0.0_r41android-13.0.0_r40android-13.0.0_r39android-13.0.0_r38android-13.0.0_r37android-13.0.0_r36android-13.0.0_r35android-13.0.0_r34android-13.0.0_r33android-13.0.0_r32android-13.0.0_r30android-13.0.0_r29android-13.0.0_r28android-13.0.0_r27android-13.0.0_r24android-13.0.0_r23android-13.0.0_r22android-13.0.0_r21android-13.0.0_r20android-13.0.0_r19android-13.0.0_r18android-13.0.0_r17android-13.0.0_r16aml_uwb_341710010aml_uwb_341513070aml_uwb_341511050aml_uwb_341310300aml_uwb_341310030aml_uwb_341111010aml_uwb_341011000aml_uwb_331910010aml_uwb_331820070aml_uwb_331613010aml_uwb_331611010aml_uwb_331410010aml_uwb_331310030aml_uwb_331115000aml_uwb_331015040aml_uwb_330810010aml_tz5_341510070aml_tz5_341510050aml_tz5_341510010aml_tz4_332714070aml_tz4_332714050aml_tz4_332714010aml_tz4_331910000aml_tz4_331314030aml_tz4_331314020aml_tz4_331314010aml_tz4_331012050aml_tz4_331012040aml_tz4_331012000aml_rkp_341510000aml_rkp_341311000aml_rkp_341114000aml_rkp_341015010aml_rkp_341012000aml_odp_341717000aml_odp_341610000aml_hef_341717050aml_hef_341613000aml_hef_341512030aml_hef_341415040aml_hef_341311010aml_hef_341114030aml_go_wif_330911000aml_go_uwb_330912000aml_go_tz4_330912000aml_go_tet_330914010aml_go_swc_330913000aml_go_sta_330911000aml_go_sdk_330810000aml_go_sch_330911000aml_go_res_330912000aml_go_per_330912000aml_go_odp_330913000aml_go_odp_330912000aml_go_neu_330912000aml_go_net_330913000aml_go_mpr_330912000aml_go_ase_330913000aml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000aml_go_adb_330913000aml_cfg_341510000aml_ase_341510000aml_ase_341410000aml_ase_341310010aml_ase_341113000aml_ase_340913000aml_ase_331311020aml_ase_331112000aml_ase_331011020aml_ads_341720000aml_ads_341615050aml_ads_341517040aml_ads_341413000aml_ads_341316030aml_ads_341131050aml_ads_341027030aml_ads_340915050aml_ads_331920180aml_ads_331814200aml_ads_331710270aml_ads_331611190aml_ads_331511020aml_ads_331418080aml_ads_331131000main-16k-with-phonesmain-16kandroid14-tests-releaseandroid14-security-releaseandroid14-s2-releaseandroid14-s1-releaseandroid14-releaseandroid14-qpr3-s2-releaseandroid14-qpr3-releaseandroid14-qpr2-s5-releaseandroid14-qpr2-s4-releaseandroid14-qpr2-s3-releaseandroid14-qpr2-s2-releaseandroid14-qpr2-s1-releaseandroid14-qpr2-releaseandroid14-qpr1-s2-releaseandroid14-qpr1-releaseandroid14-platform-releaseandroid14-mainline-uwb-releaseandroid14-mainline-healthfitness-releaseandroid14-mainline-appsearch-releaseandroid14-mainline-adservices-releaseandroid14-gsiandroid14-devandroid14-d2-s5-releaseandroid14-d2-s4-releaseandroid14-d2-s3-releaseandroid14-d2-s2-releaseandroid14-d2-s1-releaseandroid14-d2-releaseandroid14-d1-s7-releaseandroid14-d1-s6-releaseandroid14-d1-s5-releaseandroid14-d1-s4-releaseandroid14-d1-s3-releaseandroid14-d1-s2-releaseandroid14-d1-s1-releaseandroid14-d1-releaseandroid13-qpr3-s9-releaseandroid13-qpr3-s8-releaseandroid13-qpr3-s7-releaseandroid13-qpr3-s6-releaseandroid13-qpr3-s5-releaseandroid13-qpr3-s4-releaseandroid13-qpr3-s3-releaseandroid13-qpr3-s2-releaseandroid13-qpr3-s14-releaseandroid13-qpr3-s13-releaseandroid13-qpr3-s12-releaseandroid13-qpr3-s11-releaseandroid13-qpr3-s10-releaseandroid13-qpr3-s1-releaseandroid13-qpr3-releaseandroid13-qpr3-c-s8-releaseandroid13-qpr3-c-s7-releaseandroid13-qpr3-c-s6-releaseandroid13-qpr3-c-s5-releaseandroid13-qpr3-c-s4-releaseandroid13-qpr3-c-s3-releaseandroid13-qpr3-c-s2-releaseandroid13-qpr3-c-s12-releaseandroid13-qpr3-c-s11-releaseandroid13-qpr3-c-s10-releaseandroid13-qpr3-c-s1-releaseandroid13-qpr2-s9-releaseandroid13-qpr2-s8-releaseandroid13-qpr2-s7-releaseandroid13-qpr2-s6-releaseandroid13-qpr2-s5-releaseandroid13-qpr2-s3-releaseandroid13-qpr2-s2-releaseandroid13-qpr2-s12-releaseandroid13-qpr2-s11-releaseandroid13-qpr2-s10-releaseandroid13-qpr2-s1-releaseandroid13-qpr2-releaseandroid13-qpr2-b-s1-releaseandroid13-qpr1-s8-releaseandroid13-qpr1-s7-releaseandroid13-qpr1-s6-releaseandroid13-qpr1-s5-releaseandroid13-qpr1-s4-releaseandroid13-qpr1-s3-releaseandroid13-qpr1-s2-releaseandroid13-qpr1-s1-releaseandroid13-qpr1-releaseandroid13-mainline-uwb-releaseandroid13-mainline-tzdata4-releaseandroid13-mainline-go-wifi-releaseandroid13-mainline-go-uwb-releaseandroid13-mainline-go-tzdata4-releaseandroid13-mainline-go-tethering-releaseandroid13-mainline-go-sdkext-releaseandroid13-mainline-go-scheduling-releaseandroid13-mainline-go-resolv-releaseandroid13-mainline-go-permission-releaseandroid13-mainline-go-os-statsd-releaseandroid13-mainline-go-odp-releaseandroid13-mainline-go-neuralnetworks-releaseandroid13-mainline-go-networking-releaseandroid13-mainline-go-mediaprovider-releaseandroid13-mainline-go-media-swcodec-releaseandroid13-mainline-go-appsearch-releaseandroid13-mainline-go-adservices-releaseandroid13-mainline-go-adbd-releaseandroid13-mainline-appsearch-releaseandroid13-mainline-adservices-releaseandroid13-frc-odp-releaseandroid13-frc-conscrypt-releaseandroid13-frc-cellbroadcast-releaseandroid13-frc-art-releaseandroid13-frc-adbd-releaseandroid13-devandroid13-d4-s2-releaseandroid13-d4-s1-releaseandroid13-d4-releaseandroid13-d3-s1-releaseandroid13-d2-releaseaml_tz5_341510010aml_tz4_332714010
Original change: https://android-review.googlesource.com/c/platform/external/volley/+/1758419
Change-Id: I7191d1e2ebb6c416909593386dbbd3481241bf8c
Diffstat (limited to 'core/src/test/java/com/android/volley/CacheDispatcherTest.java')
-rw-r--r-- | core/src/test/java/com/android/volley/CacheDispatcherTest.java | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/core/src/test/java/com/android/volley/CacheDispatcherTest.java b/core/src/test/java/com/android/volley/CacheDispatcherTest.java new file mode 100644 index 0000000..aef6785 --- /dev/null +++ b/core/src/test/java/com/android/volley/CacheDispatcherTest.java @@ -0,0 +1,276 @@ +/* + * 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 static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.android.volley.toolbox.StringRequest; +import com.android.volley.utils.CacheTestUtils; +import java.util.concurrent.BlockingQueue; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +@SuppressWarnings("rawtypes") +public class CacheDispatcherTest { + private CacheDispatcher mDispatcher; + private @Mock BlockingQueue<Request<?>> mCacheQueue; + private @Mock BlockingQueue<Request<?>> mNetworkQueue; + private @Mock Cache mCache; + private @Mock ResponseDelivery mDelivery; + private @Mock Network mNetwork; + private StringRequest mRequest; + + @Before + public void setUp() throws Exception { + initMocks(this); + + mRequest = new StringRequest(Request.Method.GET, "http://foo", null, null); + mDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); + } + + private static class WaitForever implements Answer { + @Override + public Object answer(InvocationOnMock invocationOnMock) throws Throwable { + Thread.sleep(Long.MAX_VALUE); + return null; + } + } + + @Test + public void runStopsOnQuit() throws Exception { + when(mCacheQueue.take()).then(new WaitForever()); + mDispatcher.start(); + mDispatcher.quit(); + mDispatcher.join(1000); + } + + private static void verifyNoResponse(ResponseDelivery delivery) { + verify(delivery, never()).postResponse(any(Request.class), any(Response.class)); + verify(delivery, never()) + .postResponse(any(Request.class), any(Response.class), any(Runnable.class)); + verify(delivery, never()).postError(any(Request.class), any(VolleyError.class)); + } + + // A cancelled request should not be processed at all. + @Test + public void cancelledRequest() throws Exception { + mRequest.cancel(); + mDispatcher.processRequest(mRequest); + verify(mCache, never()).get(anyString()); + verifyNoResponse(mDelivery); + } + + // A cache miss does not post a response and puts the request on the network queue. + @Test + public void cacheMiss() throws Exception { + mDispatcher.processRequest(mRequest); + verifyNoResponse(mDelivery); + verify(mNetworkQueue).put(mRequest); + assertNull(mRequest.getCacheEntry()); + } + + // A non-expired cache hit posts a response and does not queue to the network. + @Test + public void nonExpiredCacheHit() throws Exception { + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, false); + when(mCache.get(anyString())).thenReturn(entry); + mDispatcher.processRequest(mRequest); + verify(mDelivery).postResponse(any(Request.class), any(Response.class)); + verify(mDelivery, never()).postError(any(Request.class), any(VolleyError.class)); + } + + // A soft-expired cache hit posts a response and queues to the network. + @Test + public void softExpiredCacheHit() throws Exception { + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true); + when(mCache.get(anyString())).thenReturn(entry); + mDispatcher.processRequest(mRequest); + + // Soft expiration needs to use the deferred Runnable variant of postResponse, + // so make sure it gets to run. + ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class); + verify(mDelivery).postResponse(any(Request.class), any(Response.class), runnable.capture()); + runnable.getValue().run(); + // This way we can verify the behavior of the Runnable as well. + verify(mNetworkQueue).put(mRequest); + assertSame(entry, mRequest.getCacheEntry()); + + verify(mDelivery, never()).postError(any(Request.class), any(VolleyError.class)); + } + + // An expired cache hit does not post a response and queues to the network. + @Test + public void expiredCacheHit() throws Exception { + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, true, true); + when(mCache.get(anyString())).thenReturn(entry); + mDispatcher.processRequest(mRequest); + verifyNoResponse(mDelivery); + verify(mNetworkQueue).put(mRequest); + assertSame(entry, mRequest.getCacheEntry()); + } + + // An fresh cache hit with parse error, does not post a response and queues to the network. + @Test + public void freshCacheHit_parseError() throws Exception { + Request request = mock(Request.class); + when(request.parseNetworkResponse(any(NetworkResponse.class))) + .thenReturn(Response.error(new ParseError())); + when(request.getCacheKey()).thenReturn("cache/key"); + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, false); + when(mCache.get(anyString())).thenReturn(entry); + + mDispatcher.processRequest(request); + + verifyNoResponse(mDelivery); + verify(mNetworkQueue).put(request); + assertNull(request.getCacheEntry()); + verify(mCache).invalidate("cache/key", true); + verify(request).addMarker("cache-parsing-failed"); + } + + @Test + public void duplicateCacheMiss() throws Exception { + StringRequest secondRequest = + new StringRequest(Request.Method.GET, "http://foo", null, null); + mRequest.setSequence(1); + secondRequest.setSequence(2); + mDispatcher.processRequest(mRequest); + mDispatcher.processRequest(secondRequest); + verify(mNetworkQueue).put(mRequest); + verifyNoResponse(mDelivery); + } + + @Test + public void tripleCacheMiss_networkErrorOnFirst() throws Exception { + StringRequest secondRequest = + new StringRequest(Request.Method.GET, "http://foo", null, null); + StringRequest thirdRequest = + new StringRequest(Request.Method.GET, "http://foo", null, null); + mRequest.setSequence(1); + secondRequest.setSequence(2); + thirdRequest.setSequence(3); + mDispatcher.processRequest(mRequest); + mDispatcher.processRequest(secondRequest); + mDispatcher.processRequest(thirdRequest); + + verify(mNetworkQueue).put(mRequest); + verifyNoResponse(mDelivery); + + ((Request<?>) mRequest).notifyListenerResponseNotUsable(); + // Second request should now be in network queue. + verify(mNetworkQueue).put(secondRequest); + // Another unusable response, third request should now be added. + ((Request<?>) secondRequest).notifyListenerResponseNotUsable(); + verify(mNetworkQueue).put(thirdRequest); + } + + @Test + public void duplicateSoftExpiredCacheHit_failedRequest() throws Exception { + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true); + when(mCache.get(anyString())).thenReturn(entry); + + StringRequest secondRequest = + new StringRequest(Request.Method.GET, "http://foo", null, null); + mRequest.setSequence(1); + secondRequest.setSequence(2); + + mDispatcher.processRequest(mRequest); + mDispatcher.processRequest(secondRequest); + + // Soft expiration needs to use the deferred Runnable variant of postResponse, + // so make sure it gets to run. + ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class); + verify(mDelivery).postResponse(any(Request.class), any(Response.class), runnable.capture()); + runnable.getValue().run(); + // This way we can verify the behavior of the Runnable as well. + + verify(mNetworkQueue).put(mRequest); + verify(mDelivery) + .postResponse(any(Request.class), any(Response.class), any(Runnable.class)); + + ((Request<?>) mRequest).notifyListenerResponseNotUsable(); + // Second request should now be in network queue. + verify(mNetworkQueue).put(secondRequest); + } + + @Test + public void duplicateSoftExpiredCacheHit_successfulRequest() throws Exception { + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true); + when(mCache.get(anyString())).thenReturn(entry); + + StringRequest secondRequest = + new StringRequest(Request.Method.GET, "http://foo", null, null); + mRequest.setSequence(1); + secondRequest.setSequence(2); + + mDispatcher.processRequest(mRequest); + mDispatcher.processRequest(secondRequest); + + // Soft expiration needs to use the deferred Runnable variant of postResponse, + // so make sure it gets to run. + ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class); + verify(mDelivery).postResponse(any(Request.class), any(Response.class), runnable.capture()); + runnable.getValue().run(); + // This way we can verify the behavior of the Runnable as well. + + verify(mNetworkQueue).put(mRequest); + verify(mDelivery) + .postResponse(any(Request.class), any(Response.class), any(Runnable.class)); + + ((Request<?>) mRequest).notifyListenerResponseReceived(Response.success(null, entry)); + // Second request should have delivered response. + verify(mNetworkQueue, never()).put(secondRequest); + verify(mDelivery) + .postResponse(any(Request.class), any(Response.class), any(Runnable.class)); + } + + @Test + public void processRequestNotifiesListener() throws Exception { + RequestQueue.RequestEventListener listener = mock(RequestQueue.RequestEventListener.class); + RequestQueue queue = new RequestQueue(mCache, mNetwork, 0, mDelivery); + queue.addRequestEventListener(listener); + mRequest.setRequestQueue(queue); + + Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, false); + when(mCache.get(anyString())).thenReturn(entry); + mDispatcher.processRequest(mRequest); + + InOrder inOrder = inOrder(listener); + inOrder.verify(listener) + .onRequestEvent(mRequest, RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_STARTED); + inOrder.verify(listener) + .onRequestEvent(mRequest, RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_FINISHED); + inOrder.verifyNoMoreInteractions(); + } +} |