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.Mockito.atLeastOnce; |
| 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 import static org.mockito.Mockito.when; |
| 13 |
| 14 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotifi
er.NotifierUi; |
| 15 import org.chromium.components.offline_items_collection.ContentId; |
| 16 import org.chromium.components.offline_items_collection.OfflineContentProvider; |
| 17 import org.chromium.components.offline_items_collection.OfflineItem; |
| 18 import org.chromium.components.offline_items_collection.OfflineItemState; |
| 19 import org.chromium.components.offline_items_collection.OfflineItemState.Offline
ItemStateEnum; |
| 20 import org.chromium.testing.local.LocalRobolectricTestRunner; |
| 21 import org.junit.Rule; |
| 22 import org.junit.Test; |
| 23 import org.junit.runner.RunWith; |
| 24 import org.mockito.ArgumentCaptor; |
| 25 import org.mockito.ArgumentMatchers; |
| 26 import org.mockito.Captor; |
| 27 import org.mockito.InOrder; |
| 28 import org.mockito.Mock; |
| 29 import org.mockito.junit.MockitoJUnit; |
| 30 import org.mockito.junit.MockitoRule; |
| 31 import org.robolectric.annotation.Config; |
| 32 |
| 33 import java.util.ArrayList; |
| 34 |
| 35 /** Unit tests for {@link OfflineContentAggregatorNotifier}. */ |
| 36 @RunWith(LocalRobolectricTestRunner.class) |
| 37 @Config(manifest = Config.NONE) |
| 38 public class OfflineContentAggregatorNotifierUnitTest { |
| 39 @Mock |
| 40 private OfflineContentProvider mProvider; |
| 41 @Mock |
| 42 private NotifierUi mUi; |
| 43 |
| 44 @Rule |
| 45 public MockitoRule mMockitoRule = MockitoJUnit.rule(); |
| 46 |
| 47 @Captor |
| 48 ArgumentCaptor<Runnable> mOnUiNeededCaptor; |
| 49 |
| 50 private static OfflineItem buildOfflineItem(ContentId id, @OfflineItemStateE
num int state) { |
| 51 OfflineItem item = new OfflineItem(); |
| 52 item.id = id; |
| 53 item.state = state; |
| 54 return item; |
| 55 } |
| 56 |
| 57 @Test |
| 58 public void testOnItemsAddedRunningUi() { |
| 59 OfflineContentAggregatorNotifier notifier = |
| 60 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 61 |
| 62 // Initialize NotifierUi expectations. |
| 63 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 64 |
| 65 // Initialize OfflineContentProvider expectations. |
| 66 ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() { |
| 67 { |
| 68 add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.I
N_PROGRESS)); |
| 69 add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.P
ENDING)); |
| 70 add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.C
OMPLETE)); |
| 71 add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.C
ANCELLED)); |
| 72 add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.I
NTERRUPTED)); |
| 73 add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.F
AILED)); |
| 74 add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.P
AUSED)); |
| 75 } |
| 76 }; |
| 77 |
| 78 notifier.onItemsAvailable(); |
| 79 notifier.onItemsAdded(items); |
| 80 notifier.destroy(); |
| 81 |
| 82 verify(mProvider, times(1)).addObserver(notifier); |
| 83 verify(mUi, atLeastOnce()).onUiNeeded(ArgumentMatchers.any()); |
| 84 |
| 85 InOrder order = inOrder(mUi); |
| 86 |
| 87 order.verify(mUi, times(1)).updateItem(items.get(0) /* OfflineItemState.
IN_PROGRESS */); |
| 88 order.verify(mUi, times(1)).updateItem(items.get(1) /* OfflineItemState.
PENDING */); |
| 89 order.verify(mUi, never()).updateItem(ArgumentMatchers.any()); |
| 90 |
| 91 verify(mUi, never()).onUiNotNeeded(); |
| 92 verify(mProvider, times(1)).removeObserver(notifier); |
| 93 } |
| 94 |
| 95 @Test |
| 96 public void testOnItemsRemovedRunningUi() { |
| 97 OfflineContentAggregatorNotifier notifier = |
| 98 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 99 |
| 100 // Initialize NotifierUi expectations. |
| 101 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 102 |
| 103 // Initialize OfflineContentProvider expectations. |
| 104 ContentId id = new ContentId("1", "A"); |
| 105 |
| 106 notifier.onItemsAvailable(); |
| 107 notifier.onItemRemoved(id); |
| 108 notifier.destroy(); |
| 109 |
| 110 verify(mProvider, times(1)).addObserver(notifier); |
| 111 verify(mUi, atLeastOnce()).onUiNeeded(ArgumentMatchers.any()); |
| 112 verify(mUi, times(1)).removeItem(id); |
| 113 verify(mUi, atLeastOnce()).onUiNotNeeded(); |
| 114 verify(mProvider, times(1)).removeObserver(notifier); |
| 115 } |
| 116 |
| 117 @Test |
| 118 public void testOnItemUpdatedRunningUi() { |
| 119 OfflineContentAggregatorNotifier notifier = |
| 120 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 121 |
| 122 // Initialize NotifierUi expectations. |
| 123 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 124 |
| 125 // Initialize OfflineContentProvider expectations. |
| 126 OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItem
State.IN_PROGRESS); |
| 127 |
| 128 notifier.onItemsAvailable(); |
| 129 notifier.onItemUpdated(item); |
| 130 notifier.destroy(); |
| 131 |
| 132 verify(mProvider, times(1)).addObserver(notifier); |
| 133 verify(mUi, atLeastOnce()).onUiNeeded(ArgumentMatchers.any()); |
| 134 verify(mUi, times(1)).updateItem(item); |
| 135 verify(mProvider, times(1)).removeObserver(notifier); |
| 136 } |
| 137 |
| 138 @Test |
| 139 public void testUiShutdown() { |
| 140 OfflineContentAggregatorNotifier notifier = |
| 141 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 142 |
| 143 // Initialize NotifierUi expectations. |
| 144 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 145 |
| 146 // Initialize OfflineContentProvider expectations. |
| 147 OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItem
State.IN_PROGRESS); |
| 148 OfflineItem itemUpdate = buildOfflineItem(new ContentId("1", "A"), Offli
neItemState.PAUSED); |
| 149 |
| 150 notifier.onItemsAvailable(); |
| 151 notifier.onItemUpdated(item /* OfflineItemState.IN_PROGRESS */); |
| 152 notifier.onItemUpdated(itemUpdate /* OfflineItemState.PAUSED */); |
| 153 notifier.destroy(); |
| 154 |
| 155 verify(mProvider, times(1)).addObserver(notifier); |
| 156 verify(mUi, atLeastOnce()).onUiNeeded(ArgumentMatchers.any()); |
| 157 verify(mUi, times(1)).onUiNotNeeded(); |
| 158 verify(mProvider, times(1)).removeObserver(notifier); |
| 159 } |
| 160 |
| 161 @Test |
| 162 public void testQueuesActionsWhileWaitingForUi() { |
| 163 OfflineContentAggregatorNotifier notifier = |
| 164 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 165 |
| 166 // Initialize NotifierUi expectations. |
| 167 when(mUi.onUiNeeded(mOnUiNeededCaptor.capture())).thenReturn(false); |
| 168 |
| 169 // Initialize OfflineContentProvider expectations. |
| 170 ContentId id1 = new ContentId("1", "A"); |
| 171 ContentId id2 = new ContentId("2", "B"); |
| 172 ContentId id3 = new ContentId("3", "C"); |
| 173 |
| 174 OfflineItem item1 = buildOfflineItem(id1, OfflineItemState.IN_PROGRESS); |
| 175 OfflineItem item2 = buildOfflineItem(id2, OfflineItemState.PAUSED); |
| 176 |
| 177 notifier.onItemsAvailable(); |
| 178 notifier.onItemUpdated(item1); |
| 179 notifier.onItemUpdated(item2); |
| 180 notifier.onItemRemoved(id3); |
| 181 |
| 182 // Grab the captured NotifierUi.onUiNeeded Runnable. |
| 183 final Runnable capturedOnReadyEvent = mOnUiNeededCaptor.getValue(); |
| 184 |
| 185 verify(mProvider, times(1)).addObserver(notifier); |
| 186 verify(mUi, atLeastOnce()).onUiNeeded(capturedOnReadyEvent); |
| 187 verify(mUi, never()).updateItem(ArgumentMatchers.any()); |
| 188 verify(mUi, never()).removeItem(ArgumentMatchers.any()); |
| 189 |
| 190 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 191 capturedOnReadyEvent.run(); |
| 192 notifier.destroy(); |
| 193 |
| 194 verify(mUi, times(1)).updateItem(item1); |
| 195 verify(mUi, times(1)).updateItem(item2); |
| 196 verify(mUi, times(1)).removeItem(id3); |
| 197 verify(mProvider, times(1)).removeObserver(notifier); |
| 198 } |
| 199 |
| 200 @Test |
| 201 public void testQueuesRemoveStaleEntries() { |
| 202 OfflineContentAggregatorNotifier notifier = |
| 203 new OfflineContentAggregatorNotifier(mProvider, mUi); |
| 204 |
| 205 // Initialize NotifierUi expectations. |
| 206 when(mUi.onUiNeeded(mOnUiNeededCaptor.capture())).thenReturn(false); |
| 207 |
| 208 // Initialize OfflineContentProvider expectations. |
| 209 ContentId id1 = new ContentId("1", "A"); |
| 210 ContentId id2 = new ContentId("2", "B"); |
| 211 ContentId id3 = new ContentId("3", "C"); |
| 212 |
| 213 OfflineItem item1 = buildOfflineItem(id1, OfflineItemState.IN_PROGRESS); |
| 214 OfflineItem item1Update = buildOfflineItem(id1, OfflineItemState.PAUSED)
; |
| 215 OfflineItem item2 = buildOfflineItem(id2, OfflineItemState.PAUSED); |
| 216 OfflineItem item3 = buildOfflineItem(id3, OfflineItemState.PAUSED); |
| 217 |
| 218 notifier.onItemsAvailable(); |
| 219 // 1. Overwrite an item1 "update" with item1Update. |
| 220 notifier.onItemUpdated(item1); |
| 221 notifier.onItemUpdated(item1Update); |
| 222 |
| 223 // 2. Overwrite an item2 "update" with a "removal." |
| 224 notifier.onItemUpdated(item2); |
| 225 notifier.onItemRemoved(id2); |
| 226 |
| 227 // 3. Overwrite an item3 "removal" with an "update." |
| 228 notifier.onItemRemoved(id3); |
| 229 notifier.onItemUpdated(item3); |
| 230 |
| 231 // Grab the captured NotifierUi.onUiNeeded Runnable. |
| 232 final Runnable capturedOnReadyEvent = mOnUiNeededCaptor.getValue(); |
| 233 |
| 234 verify(mProvider, times(1)).addObserver(notifier); |
| 235 verify(mUi, atLeastOnce()).onUiNeeded(capturedOnReadyEvent); |
| 236 verify(mUi, never()).updateItem(ArgumentMatchers.any()); |
| 237 verify(mUi, never()).removeItem(ArgumentMatchers.any()); |
| 238 |
| 239 when(mUi.onUiNeeded(ArgumentMatchers.any())).thenReturn(true); |
| 240 capturedOnReadyEvent.run(); |
| 241 notifier.destroy(); |
| 242 |
| 243 // 1. Verify only the latest update gets called. |
| 244 verify(mUi, never()).updateItem(item1); |
| 245 verify(mUi, times(1)).updateItem(item1Update); |
| 246 |
| 247 // 2. Verify only the removal gets called. |
| 248 verify(mUi, never()).updateItem(item2); |
| 249 verify(mUi, times(1)).removeItem(id2); |
| 250 |
| 251 // 3. Verify only the update gets called. |
| 252 verify(mUi, never()).removeItem(id3); |
| 253 verify(mUi, times(1)).updateItem(item3); |
| 254 |
| 255 verify(mProvider, times(1)).removeObserver(notifier); |
| 256 } |
| 257 } |
OLD | NEW |