1 /* 2 * Copyright (C) 2016 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.documentsui; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertSame; 22 import static org.junit.Assert.assertTrue; 23 24 import android.content.ComponentCallbacks2; 25 import android.graphics.Bitmap; 26 import android.graphics.Point; 27 import android.net.Uri; 28 29 import androidx.test.filters.SmallTest; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.documentsui.ThumbnailCache.Result; 33 import com.android.documentsui.base.UserId; 34 import com.android.documentsui.testing.Bitmaps; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 @RunWith(AndroidJUnit4.class) 41 @SmallTest 42 public class ThumbnailCacheTest { 43 44 private static final Uri URI_0 = Uri.parse("content://authority/document/0"); 45 private static final Uri URI_1 = Uri.parse("content://authority/document/1"); 46 47 private static final UserId USER_ID_0 = UserId.of(0); 48 private static final UserId USER_ID_1 = UserId.of(1); 49 50 private static final Point SMALL_SIZE = new Point(1, 1); 51 private static final Point MID_SIZE = new Point(2, 2); 52 private static final Point LARGE_SIZE = new Point(3, 3); 53 54 private static final Bitmap SMALL_BITMAP = Bitmaps.createTestBitmap(1, 1); 55 private static final Bitmap MIDSIZE_BITMAP = Bitmaps.createTestBitmap(2, 2); 56 private static final Bitmap LARGE_BITMAP = Bitmaps.createTestBitmap(3, 3); 57 58 private static final long LAST_MODIFIED = 100; 59 60 private static final int CACHE_SIZE_LIMIT = 61 MIDSIZE_BITMAP.getByteCount() + LARGE_BITMAP.getByteCount(); 62 63 private ThumbnailCache mCache; 64 65 @Before setUp()66 public void setUp() { 67 mCache = new ThumbnailCache(CACHE_SIZE_LIMIT); 68 } 69 70 @Test testMiss()71 public void testMiss() { 72 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 73 74 Result result = mCache.getThumbnail(URI_1, USER_ID_0, MID_SIZE); 75 76 assertMiss(result); 77 } 78 79 @Test testMiss_DifferentUser()80 public void testMiss_DifferentUser() { 81 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 82 Result result = mCache.getThumbnail(URI_0, USER_ID_1, MID_SIZE); 83 assertMiss(result); 84 } 85 86 @Test testHit_Exact()87 public void testHit_Exact() { 88 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 89 90 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 91 92 assertHitExact(result); 93 assertSame(MIDSIZE_BITMAP, result.getThumbnail()); 94 } 95 96 @Test testHit_Smaller()97 public void testHit_Smaller() { 98 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 99 100 Result result = mCache.getThumbnail(URI_0, USER_ID_0, LARGE_SIZE); 101 102 assertHitSmaller(result); 103 assertSame(MIDSIZE_BITMAP, result.getThumbnail()); 104 } 105 106 @Test testHit_Larger()107 public void testHit_Larger() { 108 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 109 110 Result result = mCache.getThumbnail(URI_0, USER_ID_0, SMALL_SIZE); 111 112 assertHitLarger(result); 113 assertSame(MIDSIZE_BITMAP, result.getThumbnail()); 114 } 115 116 @Test testHit_Larger_HasBothSize()117 public void testHit_Larger_HasBothSize() { 118 mCache.putThumbnail(URI_0, USER_ID_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED); 119 mCache.putThumbnail(URI_0, USER_ID_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED); 120 121 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 122 123 assertHitLarger(result); 124 assertSame(LARGE_BITMAP, result.getThumbnail()); 125 } 126 127 @Test testHit_Exact_MultiplePut()128 public void testHit_Exact_MultiplePut() { 129 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 130 131 Bitmap localBitmap = Bitmaps.createTestBitmap(MID_SIZE.x, MID_SIZE.y); 132 long localLastModified = LAST_MODIFIED + 100; 133 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, localBitmap, localLastModified); 134 135 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 136 137 assertHitExact(result); 138 assertSame(localBitmap, result.getThumbnail()); 139 } 140 141 @Test testHit_EqualLastModified()142 public void testHit_EqualLastModified() { 143 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 144 145 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 146 147 assertEquals(LAST_MODIFIED, result.getLastModified()); 148 } 149 150 @Test testEvictOldest_SizeExceeded()151 public void testEvictOldest_SizeExceeded() { 152 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 153 mCache.putThumbnail(URI_1, USER_ID_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED); 154 mCache.putThumbnail(URI_1, USER_ID_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED); 155 156 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 157 158 assertMiss(result); 159 } 160 161 @Test testCacheShrink_OnTrimMemory_Moderate()162 public void testCacheShrink_OnTrimMemory_Moderate() { 163 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 164 mCache.putThumbnail(URI_0, USER_ID_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED); 165 mCache.putThumbnail(URI_0, USER_ID_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED); 166 167 mCache.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE); 168 169 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 170 assertMiss(result); 171 } 172 173 @Test testCacheShrink_OnTrimMemory_Background()174 public void testCacheShrink_OnTrimMemory_Background() { 175 mCache.putThumbnail(URI_0, USER_ID_0, LARGE_SIZE, LARGE_BITMAP, LAST_MODIFIED); 176 mCache.putThumbnail(URI_0, USER_ID_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED); 177 178 mCache.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND); 179 180 // Math here (size of each pixel omitted): 181 // Limit = midSize + largeSize = 2 * 2 + 3 * 3 = 13, so after all putThumbnail the cache is 182 // full. 183 // 184 // HalfLimit = Limit / 2 = 5. After evicting largeSize bitmap, cache size decreases to 4, 185 // which is smaller than 5. Then smallSize bitmap remains. 186 Result result = mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE); 187 assertHitSmaller(result); 188 assertSame(SMALL_BITMAP, result.getThumbnail()); 189 } 190 191 @Test testRemoveUri()192 public void testRemoveUri() { 193 mCache.putThumbnail(URI_0, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 194 mCache.putThumbnail(URI_0, USER_ID_0, SMALL_SIZE, SMALL_BITMAP, LAST_MODIFIED); 195 mCache.putThumbnail(URI_1, USER_ID_0, MID_SIZE, MIDSIZE_BITMAP, LAST_MODIFIED); 196 197 mCache.removeUri(URI_0, USER_ID_0); 198 199 assertMiss(mCache.getThumbnail(URI_0, USER_ID_0, MID_SIZE)); 200 assertHitExact(mCache.getThumbnail(URI_1, USER_ID_0, MID_SIZE)); 201 } 202 assertMiss(Result result)203 private static void assertMiss(Result result) { 204 assertEquals(Result.CACHE_MISS, result.getStatus()); 205 assertFalse(result.isExactHit()); 206 assertFalse(result.isHit()); 207 } 208 assertHitExact(Result result)209 private static void assertHitExact(Result result) { 210 assertEquals(Result.CACHE_HIT_EXACT, result.getStatus()); 211 assertTrue(result.isExactHit()); 212 assertTrue(result.isHit()); 213 } 214 assertHitSmaller(Result result)215 private static void assertHitSmaller(Result result) { 216 assertEquals(Result.CACHE_HIT_SMALLER, result.getStatus()); 217 assertFalse(result.isExactHit()); 218 assertTrue(result.isHit()); 219 } 220 assertHitLarger(Result result)221 private static void assertHitLarger(Result result) { 222 assertEquals(Result.CACHE_HIT_LARGER, result.getStatus()); 223 assertFalse(result.isExactHit()); 224 assertTrue(result.isHit()); 225 } 226 } 227