OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.download.items; |
| 6 |
| 7 import static org.mockito.ArgumentMatchers.argThat; |
| 8 import static org.mockito.Mockito.inOrder; |
| 9 import static org.mockito.Mockito.never; |
| 10 import static org.mockito.Mockito.times; |
| 11 import static org.mockito.Mockito.verify; |
| 12 |
| 13 import android.graphics.Bitmap; |
| 14 |
| 15 import org.junit.Assert; |
| 16 import org.junit.Rule; |
| 17 import org.junit.Test; |
| 18 import org.junit.runner.RunWith; |
| 19 import org.mockito.ArgumentCaptor; |
| 20 import org.mockito.ArgumentMatcher; |
| 21 import org.mockito.ArgumentMatchers; |
| 22 import org.mockito.InOrder; |
| 23 import org.mockito.Mock; |
| 24 import org.mockito.junit.MockitoJUnit; |
| 25 import org.mockito.junit.MockitoRule; |
| 26 import org.robolectric.annotation.Config; |
| 27 |
| 28 import org.chromium.chrome.browser.download.DownloadInfo; |
| 29 import org.chromium.chrome.browser.download.DownloadNotifier; |
| 30 import org.chromium.components.offline_items_collection.ContentId; |
| 31 import org.chromium.components.offline_items_collection.OfflineContentProvider; |
| 32 import org.chromium.components.offline_items_collection.OfflineItem; |
| 33 import org.chromium.components.offline_items_collection.OfflineItemState; |
| 34 import org.chromium.components.offline_items_collection.OfflineItemVisuals; |
| 35 import org.chromium.testing.local.LocalRobolectricTestRunner; |
| 36 |
| 37 import java.util.ArrayList; |
| 38 import java.util.List; |
| 39 |
| 40 /** |
| 41 * Unit tests for {@link OfflineContentAggregatorNotifierBridgeUi}. Validate th
at it interacts with |
| 42 * both the {@link DownloadNotifier} and the {@link OfflineContentProvider} in e
xpected ways. |
| 43 */ |
| 44 @RunWith(LocalRobolectricTestRunner.class) |
| 45 @Config(manifest = Config.NONE) |
| 46 public class OfflineContentAggregatorNotificationBridgeUiTest { |
| 47 /** Helper class to validate that a DownloadInfo has the right ContentId. */ |
| 48 static class DownloadInfoIdMatcher implements ArgumentMatcher<DownloadInfo>
{ |
| 49 private final ContentId mExpectedId; |
| 50 |
| 51 public DownloadInfoIdMatcher(ContentId expected) { |
| 52 mExpectedId = expected; |
| 53 } |
| 54 |
| 55 @Override |
| 56 public boolean matches(DownloadInfo argument) { |
| 57 return ((DownloadInfo) argument).getContentId().equals(mExpectedId); |
| 58 } |
| 59 |
| 60 @Override |
| 61 public String toString() { |
| 62 return mExpectedId == null ? null : mExpectedId.toString(); |
| 63 } |
| 64 } |
| 65 |
| 66 @Mock |
| 67 private OfflineContentProvider mProvider; |
| 68 |
| 69 @Mock |
| 70 private DownloadNotifier mNotifier; |
| 71 |
| 72 @Rule |
| 73 public MockitoRule mMockitoRule = MockitoJUnit.rule(); |
| 74 |
| 75 private static OfflineItem buildOfflineItem(ContentId id, @OfflineItemState
int state) { |
| 76 OfflineItem item = new OfflineItem(); |
| 77 item.id = id; |
| 78 item.state = state; |
| 79 return item; |
| 80 } |
| 81 |
| 82 @Test |
| 83 public void testOnlyInterestingNewItemsGetSentToTheUi() { |
| 84 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 85 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 86 verify(mProvider, times(1)).addObserver(bridge); |
| 87 |
| 88 ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() { |
| 89 { |
| 90 add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.I
N_PROGRESS)); |
| 91 add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.P
ENDING)); |
| 92 add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.C
OMPLETE)); |
| 93 add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.C
ANCELLED)); |
| 94 add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.I
NTERRUPTED)); |
| 95 add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.F
AILED)); |
| 96 add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.P
AUSED)); |
| 97 } |
| 98 }; |
| 99 |
| 100 bridge.onItemsAvailable(); |
| 101 bridge.onItemsAdded(items); |
| 102 |
| 103 InOrder order = inOrder(mProvider); |
| 104 order.verify(mProvider, times(1)) |
| 105 .getVisualsForItem(items.get(0).id /* OfflineItemState.IN_PROGRE
SS */, bridge); |
| 106 order.verify(mProvider, never()) |
| 107 .getVisualsForItem(ArgumentMatchers.any(), ArgumentMatchers.any(
)); |
| 108 |
| 109 bridge.onVisualsAvailable(items.get(0).id, new OfflineItemVisuals()); |
| 110 |
| 111 verify(mNotifier, times(1)) |
| 112 .notifyDownloadProgress(argThat(new DownloadInfoIdMatcher(items.
get(0).id)), |
| 113 ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean(
)); |
| 114 |
| 115 bridge.destroy(); |
| 116 verify(mProvider, times(1)).removeObserver(bridge); |
| 117 } |
| 118 |
| 119 @Test |
| 120 public void testItemUpdatesGetSentToTheUi() { |
| 121 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 122 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 123 verify(mProvider, times(1)).addObserver(bridge); |
| 124 |
| 125 ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() { |
| 126 { |
| 127 add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.I
N_PROGRESS)); |
| 128 add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.P
ENDING)); |
| 129 add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.C
OMPLETE)); |
| 130 add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.C
ANCELLED)); |
| 131 add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.I
NTERRUPTED)); |
| 132 add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.F
AILED)); |
| 133 add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.P
AUSED)); |
| 134 } |
| 135 }; |
| 136 |
| 137 bridge.onItemsAvailable(); |
| 138 for (int i = 0; i < items.size(); i++) bridge.onItemUpdated(items.get(i)
); |
| 139 |
| 140 verify(mProvider, times(1)).getVisualsForItem(items.get(0).id, bridge); |
| 141 verify(mProvider, times(1)).getVisualsForItem(items.get(1).id, bridge); |
| 142 verify(mProvider, times(1)).getVisualsForItem(items.get(2).id, bridge); |
| 143 verify(mProvider, never()).getVisualsForItem(items.get(3).id, bridge); |
| 144 verify(mProvider, times(1)).getVisualsForItem(items.get(4).id, bridge); |
| 145 verify(mProvider, times(1)).getVisualsForItem(items.get(5).id, bridge); |
| 146 verify(mProvider, times(1)).getVisualsForItem(items.get(6).id, bridge); |
| 147 |
| 148 for (int i = 0; i < items.size(); i++) { |
| 149 bridge.onVisualsAvailable(items.get(i).id, new OfflineItemVisuals())
; |
| 150 } |
| 151 |
| 152 verify(mNotifier, times(1)) |
| 153 .notifyDownloadProgress(argThat(new DownloadInfoIdMatcher(items.
get(0).id)), |
| 154 ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean(
)); |
| 155 verify(mNotifier, times(1)) |
| 156 .notifyDownloadSuccessful(argThat(new DownloadInfoIdMatcher(item
s.get(2).id)), |
| 157 ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean(
), |
| 158 ArgumentMatchers.anyBoolean()); |
| 159 verify(mNotifier, times(1)) |
| 160 .notifyDownloadCanceled(items.get(3).id /* OfflineItemState.CANC
ELLED */); |
| 161 verify(mNotifier, times(1)) |
| 162 .notifyDownloadInterrupted(argThat(new DownloadInfoIdMatcher(ite
ms.get(4).id)), |
| 163 ArgumentMatchers.anyBoolean()); |
| 164 verify(mNotifier, times(1)) |
| 165 .notifyDownloadFailed(argThat(new DownloadInfoIdMatcher(items.ge
t(5).id))); |
| 166 verify(mNotifier, times(1)) |
| 167 .notifyDownloadPaused(argThat(new DownloadInfoIdMatcher(items.ge
t(6).id))); |
| 168 |
| 169 bridge.destroy(); |
| 170 verify(mProvider, times(1)).removeObserver(bridge); |
| 171 } |
| 172 |
| 173 @Test |
| 174 public void testNullVisuals() { |
| 175 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 176 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 177 verify(mProvider, times(1)).addObserver(bridge); |
| 178 |
| 179 OfflineItem item1 = buildOfflineItem(new ContentId("1", "A"), OfflineIte
mState.IN_PROGRESS); |
| 180 OfflineItem item2 = buildOfflineItem(new ContentId("2", "B"), OfflineIte
mState.IN_PROGRESS); |
| 181 |
| 182 OfflineItemVisuals visuals1 = new OfflineItemVisuals(); |
| 183 visuals1.icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); |
| 184 |
| 185 bridge.onItemsAvailable(); |
| 186 bridge.onItemUpdated(item1); |
| 187 bridge.onItemUpdated(item2); |
| 188 |
| 189 verify(mProvider, times(1)).getVisualsForItem(item1.id, bridge); |
| 190 verify(mProvider, times(1)).getVisualsForItem(item2.id, bridge); |
| 191 |
| 192 ArgumentCaptor<DownloadInfo> captor = ArgumentCaptor.forClass(DownloadIn
fo.class); |
| 193 |
| 194 bridge.onVisualsAvailable(item1.id, visuals1); |
| 195 bridge.onVisualsAvailable(item2.id, null); |
| 196 verify(mNotifier, times(2)) |
| 197 .notifyDownloadProgress(captor.capture(), ArgumentMatchers.anyLo
ng(), |
| 198 ArgumentMatchers.anyBoolean()); |
| 199 |
| 200 List<DownloadInfo> capturedInfo = captor.getAllValues(); |
| 201 Assert.assertEquals(item1.id, capturedInfo.get(0).getContentId()); |
| 202 Assert.assertEquals(visuals1.icon, capturedInfo.get(0).getIcon()); |
| 203 Assert.assertEquals(item2.id, capturedInfo.get(1).getContentId()); |
| 204 Assert.assertEquals(null, capturedInfo.get(1).getIcon()); |
| 205 |
| 206 bridge.destroy(); |
| 207 verify(mProvider, times(1)).removeObserver(bridge); |
| 208 } |
| 209 |
| 210 @Test |
| 211 public void testRemovedItemsGetRemovedFromTheUi() { |
| 212 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 213 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 214 verify(mProvider, times(1)).addObserver(bridge); |
| 215 |
| 216 ContentId id = new ContentId("1", "A"); |
| 217 |
| 218 bridge.onItemsAvailable(); |
| 219 bridge.onItemRemoved(id); |
| 220 verify(mNotifier, times(1)).notifyDownloadCanceled(id); |
| 221 |
| 222 bridge.destroy(); |
| 223 verify(mProvider, times(1)).removeObserver(bridge); |
| 224 } |
| 225 |
| 226 @Test |
| 227 public void testRemovedItemsIgnoreVisualsCallback() { |
| 228 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 229 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 230 verify(mProvider, times(1)).addObserver(bridge); |
| 231 |
| 232 OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItem
State.IN_PROGRESS); |
| 233 |
| 234 bridge.onItemsAvailable(); |
| 235 bridge.onItemUpdated(item); |
| 236 verify(mProvider, times(1)).getVisualsForItem(item.id, bridge); |
| 237 |
| 238 bridge.onItemRemoved(item.id); |
| 239 bridge.onVisualsAvailable(item.id, new OfflineItemVisuals()); |
| 240 InOrder order = inOrder(mNotifier); |
| 241 order.verify(mNotifier, times(1)).notifyDownloadCanceled(item.id); |
| 242 order.verifyNoMoreInteractions(); |
| 243 |
| 244 bridge.destroy(); |
| 245 verify(mProvider, times(1)).removeObserver(bridge); |
| 246 } |
| 247 |
| 248 @Test |
| 249 public void testOnlyRequestsVisualsOnceForMultipleUpdates() { |
| 250 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 251 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 252 verify(mProvider, times(1)).addObserver(bridge); |
| 253 |
| 254 OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItem
State.IN_PROGRESS); |
| 255 |
| 256 bridge.onItemsAvailable(); |
| 257 bridge.onItemUpdated(item); |
| 258 bridge.onItemUpdated(item); |
| 259 verify(mProvider, times(1)).getVisualsForItem(item.id, bridge); |
| 260 |
| 261 bridge.destroy(); |
| 262 verify(mProvider, times(1)).removeObserver(bridge); |
| 263 } |
| 264 |
| 265 @Test |
| 266 public void testVisualsAreCachedForInterestingItems() { |
| 267 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 268 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 269 verify(mProvider, times(1)).addObserver(bridge); |
| 270 |
| 271 ArrayList<OfflineItem> interestingItems = new ArrayList<OfflineItem>() { |
| 272 { |
| 273 add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.I
N_PROGRESS)); |
| 274 add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.P
ENDING)); |
| 275 add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.I
NTERRUPTED)); |
| 276 add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.P
AUSED)); |
| 277 } |
| 278 }; |
| 279 |
| 280 ArrayList<OfflineItem> uninterestingItems = new ArrayList<OfflineItem>()
{ |
| 281 { |
| 282 add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.C
OMPLETE)); |
| 283 add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.F
AILED)); |
| 284 } |
| 285 }; |
| 286 |
| 287 bridge.onItemsAvailable(); |
| 288 |
| 289 for (int i = 0; i < interestingItems.size(); i++) { |
| 290 OfflineItem item = interestingItems.get(i); |
| 291 bridge.onItemUpdated(item); |
| 292 bridge.onVisualsAvailable(item.id, null); |
| 293 bridge.onItemUpdated(item); |
| 294 verify(mProvider, times(1)).getVisualsForItem(item.id, bridge); |
| 295 verify(mNotifier, times(2)) |
| 296 .notifyDownloadProgress(ArgumentMatchers.any(), ArgumentMatc
hers.anyLong(), |
| 297 ArgumentMatchers.anyBoolean()); |
| 298 } |
| 299 |
| 300 for (int i = 0; i < uninterestingItems.size(); i++) { |
| 301 OfflineItem item = uninterestingItems.get(i); |
| 302 bridge.onItemUpdated(item); |
| 303 bridge.onVisualsAvailable(item.id, null); |
| 304 bridge.onItemUpdated(item); |
| 305 verify(mProvider, times(2)).getVisualsForItem(item.id, bridge); |
| 306 } |
| 307 |
| 308 bridge.destroy(); |
| 309 verify(mProvider, times(1)).removeObserver(bridge); |
| 310 } |
| 311 |
| 312 @Test |
| 313 public void testVisualsGetClearedForUninterestingItems() { |
| 314 OfflineContentAggregatorNotificationBridgeUi bridge = |
| 315 new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNot
ifier); |
| 316 verify(mProvider, times(1)).addObserver(bridge); |
| 317 |
| 318 ContentId id = new ContentId("1", "A"); |
| 319 OfflineItem item1 = buildOfflineItem(id, OfflineItemState.IN_PROGRESS); |
| 320 OfflineItem item2 = buildOfflineItem(id, OfflineItemState.FAILED); |
| 321 OfflineItem item3 = buildOfflineItem(id, OfflineItemState.IN_PROGRESS); |
| 322 |
| 323 bridge.onItemsAvailable(); |
| 324 bridge.onItemUpdated(item1); |
| 325 bridge.onVisualsAvailable(item1.id, new OfflineItemVisuals()); |
| 326 bridge.onItemUpdated(item2); |
| 327 bridge.onItemUpdated(item3); |
| 328 bridge.onVisualsAvailable(item1.id, new OfflineItemVisuals()); |
| 329 verify(mProvider, times(2)).getVisualsForItem(id, bridge); |
| 330 |
| 331 bridge.destroy(); |
| 332 verify(mProvider, times(1)).removeObserver(bridge); |
| 333 } |
| 334 } |
OLD | NEW |