1/* 2 * Copyright (C) 2015 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 */ 16package android.support.v17.leanback.widget; 17 18import static org.junit.Assert.assertEquals; 19import static org.mockito.Matchers.anyInt; 20import static org.mockito.Mockito.mock; 21import static org.mockito.Mockito.times; 22import static org.mockito.Mockito.verify; 23 24import android.support.test.filters.SmallTest; 25import android.support.test.runner.AndroidJUnit4; 26import android.support.v7.widget.RecyclerView; 27 28import org.junit.Test; 29import org.junit.runner.RunWith; 30 31/** 32 * Testing SingleRow algorithm 33 */ 34@SmallTest 35@RunWith(AndroidJUnit4.class) 36public class SingleRowTest extends GridTest { 37 38 private SingleRow mSingleRow; 39 40 @Test 41 public void testAppendPrependRemove() { 42 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 43 44 mSingleRow = new SingleRow(); 45 mSingleRow.setSpacing(20); 46 mSingleRow.setProvider(mProvider); 47 mSingleRow.appendVisibleItems(200); 48 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 49 50 mSingleRow.appendVisibleItems(201); 51 assertEquals(dump(mSingleRow) + " Should filled 3 items", 52 2, mSingleRow.mLastVisibleIndex); 53 54 mSingleRow.appendVisibleItems(251); 55 assertEquals(dump(mSingleRow) + " Should filled 4 items", 56 3, mSingleRow.mLastVisibleIndex); 57 58 mSingleRow.appendVisibleItems(Integer.MAX_VALUE); 59 assertEquals(dump(mSingleRow) + " Should filled 6 items", 60 5, mSingleRow.mLastVisibleIndex); 61 assertEquals(mProvider.getEdge(0), 0); 62 assertEquals(mProvider.getEdge(1), 100); 63 assertEquals(mProvider.getEdge(2), 200); 64 assertEquals(mProvider.getEdge(3), 250); 65 assertEquals(mProvider.getEdge(4), 370); 66 assertEquals(mProvider.getEdge(5), 430); 67 68 mSingleRow.removeInvisibleItemsAtEnd(0, 200); 69 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 70 71 mSingleRow.appendVisibleItems(Integer.MAX_VALUE); 72 assertEquals(dump(mSingleRow) + " Should filled 6 items", 73 5, mSingleRow.mLastVisibleIndex); 74 75 mSingleRow.removeInvisibleItemsAtFront(1000, 80); 76 assertEquals(dump(mSingleRow) + " visible index should start from 1", 77 1, mSingleRow.mFirstVisibleIndex); 78 79 mSingleRow.prependVisibleItems(0); 80 assertEquals(dump(mSingleRow) + " visible index should start from 0", 81 0, mSingleRow.mFirstVisibleIndex); 82 } 83 84 @Test 85 public void testAppendPrependRemoveReversed() { 86 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 87 88 mSingleRow = new SingleRow(); 89 mSingleRow.setSpacing(20); 90 mSingleRow.setProvider(mProvider); 91 mSingleRow.setReversedFlow(true); 92 mSingleRow.appendVisibleItems(-200); 93 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 94 95 mSingleRow.appendVisibleItems(-201); 96 assertEquals(dump(mSingleRow) + " Should filled 3 items", 97 2, mSingleRow.mLastVisibleIndex); 98 99 mSingleRow.appendVisibleItems(-251); 100 assertEquals(dump(mSingleRow) + " Should filled 4 items", 101 3, mSingleRow.mLastVisibleIndex); 102 103 mSingleRow.appendVisibleItems(Integer.MIN_VALUE); 104 assertEquals(dump(mSingleRow) + " Should filled 6 items", 105 5, mSingleRow.mLastVisibleIndex); 106 assertEquals(mProvider.getEdge(0), 0); 107 assertEquals(mProvider.getEdge(1), -100); 108 assertEquals(mProvider.getEdge(2), -200); 109 assertEquals(mProvider.getEdge(3), -250); 110 assertEquals(mProvider.getEdge(4), -370); 111 assertEquals(mProvider.getEdge(5), -430); 112 113 mSingleRow.removeInvisibleItemsAtEnd(0, -200); 114 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 115 116 mSingleRow.appendVisibleItems(Integer.MIN_VALUE); 117 assertEquals(dump(mSingleRow) + " Should filled 6 items", 118 5, mSingleRow.mLastVisibleIndex); 119 120 mSingleRow.removeInvisibleItemsAtFront(1000, -80); 121 assertEquals(dump(mSingleRow) + " Should filled 6 items", 122 1, mSingleRow.mFirstVisibleIndex); 123 } 124 125 @Test 126 public void testPrependWithSpacing() { 127 128 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 129 130 mSingleRow = new SingleRow(); 131 mSingleRow.setSpacing(20); 132 mSingleRow.setProvider(mProvider); 133 mSingleRow.appendVisibleItems(200); 134 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 135 136 mProvider.scroll(90); 137 mSingleRow.removeInvisibleItemsAtFront(Integer.MAX_VALUE, 0); 138 mSingleRow.appendVisibleItems(200); 139 assertEquals(dump(mSingleRow) + " Should filled 1 ~ 3", 1, mSingleRow.mFirstVisibleIndex); 140 assertEquals(dump(mSingleRow) + " Should filled 1 ~ 3", 3, mSingleRow.mLastVisibleIndex); 141 assertEquals(mProvider.getEdge(1), 10); 142 143 mSingleRow.prependVisibleItems(0); 144 assertEquals(dump(mSingleRow) + " Should not prepend 0", 1, mSingleRow.mFirstVisibleIndex); 145 } 146 147 @Test 148 public void testPrependWithSpacingReversed() { 149 150 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 151 152 mSingleRow = new SingleRow(); 153 mSingleRow.setSpacing(20); 154 mSingleRow.setProvider(mProvider); 155 mSingleRow.setReversedFlow(true); 156 mSingleRow.appendVisibleItems(-200); 157 assertEquals(dump(mSingleRow) + " Should filled 2 items", 1, mSingleRow.mLastVisibleIndex); 158 159 mProvider.scroll(-90); 160 mSingleRow.removeInvisibleItemsAtFront(Integer.MAX_VALUE, 0); 161 mSingleRow.appendVisibleItems(-200); 162 assertEquals(dump(mSingleRow) + " Should filled 1 ~ 3", 1, mSingleRow.mFirstVisibleIndex); 163 assertEquals(dump(mSingleRow) + " Should filled 1 ~ 3", 3, mSingleRow.mLastVisibleIndex); 164 assertEquals(mProvider.getEdge(1), -10); 165 166 mSingleRow.prependVisibleItems(0); 167 assertEquals(dump(mSingleRow) + " Should not prepend 0", 1, mSingleRow.mFirstVisibleIndex); 168 } 169 170 public void validatePrefetch(int fromLimit, int delta, Integer[]... positionData) { 171 // duplicates logic in support.v7.widget.CacheUtils#verifyPositionsPrefetched 172 RecyclerView.LayoutManager.LayoutPrefetchRegistry registry 173 = mock(RecyclerView.LayoutManager.LayoutPrefetchRegistry.class); 174 mSingleRow.collectAdjacentPrefetchPositions(fromLimit, delta, registry); 175 176 verify(registry, times(positionData.length)).addPosition(anyInt(), anyInt()); 177 for (Integer[] aPositionData : positionData) { 178 verify(registry).addPosition(aPositionData[0], aPositionData[1]); 179 } 180 } 181 182 @Test 183 public void testPrefetchBounds() { 184 mProvider = new Provider(new int[]{100, 100}); 185 186 mSingleRow = new SingleRow(); 187 mSingleRow.setSpacing(20); 188 mSingleRow.setProvider(mProvider); 189 mSingleRow.appendVisibleItems(150); 190 191 validatePrefetch(0, -10); 192 validatePrefetch(-150, 10); 193 } 194 195 @Test 196 public void testPrefetchBoundsReversed() { 197 mProvider = new Provider(new int[]{100, 100}); 198 199 mSingleRow = new SingleRow(); 200 mSingleRow.setSpacing(20); 201 mSingleRow.setProvider(mProvider); 202 mSingleRow.setReversedFlow(true); 203 mSingleRow.appendVisibleItems(-150); 204 205 validatePrefetch(0, -10); 206 validatePrefetch(150, 10); 207 } 208 209 @Test 210 public void testPrefetchItems() { 211 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 212 213 mSingleRow = new SingleRow(); 214 mSingleRow.setSpacing(20); 215 mSingleRow.setProvider(mProvider); 216 mSingleRow.appendVisibleItems(200); 217 218 // next item, 2, is 0 pixels away 219 validatePrefetch(200, 10, new Integer[] {2, 0}); 220 221 // nothing above 222 validatePrefetch(0, -10); 223 224 mProvider.scroll(90); 225 mSingleRow.removeInvisibleItemsAtFront(Integer.MAX_VALUE, 0); 226 mSingleRow.appendVisibleItems(200); 227 228 // next item, 4, is 80 pixels away 229 validatePrefetch(200, 10, new Integer[] {4, 80}); 230 231 // next item, 0, is 10 pixels away 232 validatePrefetch(0, -10, new Integer[] {0, 10}); 233 } 234 235 @Test 236 public void testPrefetchItemsReversed() { 237 mProvider = new Provider(new int[]{80, 80, 30, 100, 40, 10}); 238 239 mSingleRow = new SingleRow(); 240 mSingleRow.setSpacing(20); 241 mSingleRow.setProvider(mProvider); 242 mSingleRow.setReversedFlow(true); 243 mSingleRow.appendVisibleItems(-200); 244 245 // next item, 2, is 0 pixels away 246 validatePrefetch(-200, -10, new Integer[] {2, 0}); 247 248 // nothing above 249 validatePrefetch(0, 10); 250 251 mProvider.scroll(-90); 252 mSingleRow.removeInvisibleItemsAtFront(Integer.MAX_VALUE, 0); 253 mSingleRow.appendVisibleItems(-200); 254 255 // next item, 4, is 80 pixels away 256 validatePrefetch(-200, -10, new Integer[] {4, 80}); 257 258 // one above, 0, is 10 pixels away 259 validatePrefetch(0, 10, new Integer[] {0, 10}); 260 261 } 262}