1/* 2 * Copyright (C) 2017 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 17package com.android.setupwizardlib.items; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertNull; 21import static org.junit.Assert.assertSame; 22import static org.mockito.Matchers.eq; 23import static org.mockito.Mockito.inOrder; 24import static org.mockito.Mockito.verify; 25import static org.mockito.Mockito.verifyNoMoreInteractions; 26 27import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner; 28 29import org.junit.Before; 30import org.junit.Test; 31import org.junit.runner.RunWith; 32import org.mockito.InOrder; 33import org.mockito.Mock; 34import org.mockito.MockitoAnnotations; 35import org.robolectric.annotation.Config; 36 37@RunWith(SuwLibRobolectricTestRunner.class) 38@Config(sdk = { Config.OLDEST_SDK, Config.NEWEST_SDK }) 39public class ItemGroupTest { 40 41 private static final Item CHILD_1 = new EqualsItem("Child 1"); 42 private static final Item CHILD_2 = new EqualsItem("Child 2"); 43 private static final Item CHILD_3 = new EqualsItem("Child 3"); 44 private static final Item CHILD_4 = new EqualsItem("Child 4"); 45 46 private ItemGroup mItemGroup; 47 48 @Mock 49 private ItemHierarchy.Observer mObserver; 50 51 @Before 52 public void setUp() { 53 MockitoAnnotations.initMocks(this); 54 mItemGroup = new ItemGroup(); 55 mItemGroup.registerObserver(mObserver); 56 } 57 58 @Test 59 public void testGroup() { 60 mItemGroup.addChild(CHILD_1); 61 mItemGroup.addChild(CHILD_2); 62 63 assertSame("Item at position 0 should be child1", CHILD_1, mItemGroup.getItemAt(0)); 64 assertSame("Item at position 1 should be child2", CHILD_2, mItemGroup.getItemAt(1)); 65 assertEquals("Should have 2 children", 2, mItemGroup.getCount()); 66 67 final InOrder inOrder = inOrder(mObserver); 68 inOrder.verify(mObserver).onItemRangeInserted(eq(mItemGroup), eq(0), eq(1)); 69 inOrder.verify(mObserver).onItemRangeInserted(eq(mItemGroup), eq(1), eq(1)); 70 } 71 72 @Test 73 public void testRemoveChild() { 74 mItemGroup.addChild(CHILD_1); 75 mItemGroup.addChild(CHILD_2); 76 mItemGroup.addChild(CHILD_3); 77 78 mItemGroup.removeChild(CHILD_2); 79 80 assertSame("Item at position 0 should be child1", CHILD_1, mItemGroup.getItemAt(0)); 81 assertSame("Item at position 1 should be child3", CHILD_3, mItemGroup.getItemAt(1)); 82 assertEquals("Should have 2 children", 2, mItemGroup.getCount()); 83 84 verify(mObserver).onItemRangeRemoved(eq(mItemGroup), eq(1), eq(1)); 85 } 86 87 @Test 88 public void testClear() { 89 mItemGroup.addChild(CHILD_1); 90 mItemGroup.addChild(CHILD_2); 91 92 mItemGroup.clear(); 93 94 assertEquals("Should have 0 child", 0, mItemGroup.getCount()); 95 96 verify(mObserver).onItemRangeRemoved(eq(mItemGroup), eq(0), eq(2)); 97 } 98 99 @Test 100 public void testNestedGroup() { 101 ItemGroup parentGroup = new ItemGroup(); 102 ItemGroup childGroup = new ItemGroup(); 103 parentGroup.registerObserver(mObserver); 104 105 parentGroup.addChild(CHILD_1); 106 childGroup.addChild(CHILD_2); 107 childGroup.addChild(CHILD_3); 108 parentGroup.addChild(childGroup); 109 parentGroup.addChild(CHILD_4); 110 111 assertSame("Position 0 should be child 1", CHILD_1, parentGroup.getItemAt(0)); 112 assertSame("Position 1 should be child 2", CHILD_2, parentGroup.getItemAt(1)); 113 assertSame("Position 2 should be child 3", CHILD_3, parentGroup.getItemAt(2)); 114 assertSame("Position 3 should be child 4", CHILD_4, parentGroup.getItemAt(3)); 115 116 final InOrder inOrder = inOrder(mObserver); 117 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(1)); 118 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(1), eq(2)); 119 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(3), eq(1)); 120 verifyNoMoreInteractions(mObserver); 121 } 122 123 @Test 124 public void testNestedGroupClearNotification() { 125 ItemGroup parentGroup = new ItemGroup(); 126 ItemGroup childGroup = new ItemGroup(); 127 parentGroup.registerObserver(mObserver); 128 129 parentGroup.addChild(CHILD_1); 130 childGroup.addChild(CHILD_2); 131 childGroup.addChild(CHILD_3); 132 parentGroup.addChild(childGroup); 133 parentGroup.addChild(CHILD_4); 134 135 childGroup.clear(); 136 137 final InOrder inOrder = inOrder(mObserver); 138 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(1)); 139 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(1), eq(2)); 140 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(3), eq(1)); 141 verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(1), eq(2)); 142 verifyNoMoreInteractions(mObserver); 143 } 144 145 @Test 146 public void testNestedGroupRemoveNotification() { 147 ItemGroup parentGroup = new ItemGroup(); 148 ItemGroup childGroup = new ItemGroup(); 149 parentGroup.registerObserver(mObserver); 150 151 parentGroup.addChild(CHILD_1); 152 childGroup.addChild(CHILD_2); 153 childGroup.addChild(CHILD_3); 154 parentGroup.addChild(childGroup); 155 parentGroup.addChild(CHILD_4); 156 157 childGroup.removeChild(CHILD_3); 158 childGroup.removeChild(CHILD_2); 159 160 final InOrder inOrder = inOrder(mObserver); 161 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(1)); 162 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(1), eq(2)); 163 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(3), eq(1)); 164 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(2), eq(1)); 165 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(1), eq(1)); 166 verifyNoMoreInteractions(mObserver); 167 } 168 169 @Test 170 public void testNestedGroupClear() { 171 ItemGroup parentGroup = new ItemGroup(); 172 ItemGroup childGroup = new ItemGroup(); 173 parentGroup.registerObserver(mObserver); 174 175 parentGroup.addChild(CHILD_1); 176 childGroup.addChild(CHILD_2); 177 childGroup.addChild(CHILD_3); 178 parentGroup.addChild(childGroup); 179 180 childGroup.clear(); 181 182 final InOrder inOrder = inOrder(mObserver); 183 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(1)); 184 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(1), eq(2)); 185 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(1), eq(2)); 186 verifyNoMoreInteractions(mObserver); 187 } 188 189 @Test 190 public void testNestedGroupRemoveLastChild() { 191 ItemGroup parentGroup = new ItemGroup(); 192 ItemGroup childGroup1 = new ItemGroup(); 193 ItemGroup childGroup2 = new ItemGroup(); 194 parentGroup.registerObserver(mObserver); 195 196 childGroup1.addChild(CHILD_1); 197 childGroup1.addChild(CHILD_2); 198 parentGroup.addChild(childGroup1); 199 childGroup2.addChild(CHILD_3); 200 childGroup2.addChild(CHILD_4); 201 parentGroup.addChild(childGroup2); 202 203 childGroup2.removeChild(CHILD_4); 204 childGroup2.removeChild(CHILD_3); 205 206 final InOrder inOrder = inOrder(mObserver); 207 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(2)); 208 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(2), eq(2)); 209 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(3), eq(1)); 210 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(2), eq(1)); 211 verifyNoMoreInteractions(mObserver); 212 } 213 214 @Test 215 public void testNestedGroupClearOnlyChild() { 216 ItemGroup parentGroup = new ItemGroup(); 217 ItemGroup childGroup = new ItemGroup(); 218 parentGroup.registerObserver(mObserver); 219 220 childGroup.addChild(CHILD_1); 221 childGroup.addChild(CHILD_2); 222 parentGroup.addChild(childGroup); 223 224 childGroup.clear(); 225 226 final InOrder inOrder = inOrder(mObserver); 227 inOrder.verify(mObserver).onItemRangeInserted(eq(parentGroup), eq(0), eq(2)); 228 inOrder.verify(mObserver).onItemRangeRemoved(eq(parentGroup), eq(0), eq(2)); 229 verifyNoMoreInteractions(mObserver); 230 } 231 232 @Test 233 public void testNotifyChange() { 234 mItemGroup.addChild(CHILD_1); 235 mItemGroup.addChild(CHILD_2); 236 237 CHILD_2.setTitle("Child 2 modified"); 238 239 verify(mObserver).onItemRangeChanged(eq(mItemGroup), eq(1), eq(1)); 240 } 241 242 @Test 243 public void testEmptyChildGroup() { 244 ItemGroup parentGroup = new ItemGroup(); 245 ItemGroup childGroup = new ItemGroup(); 246 247 parentGroup.addChild(CHILD_1); 248 parentGroup.addChild(childGroup); 249 parentGroup.addChild(CHILD_2); 250 251 assertSame("Position 0 should be child 1", CHILD_1, parentGroup.getItemAt(0)); 252 assertSame("Position 1 should be child 2", CHILD_2, parentGroup.getItemAt(1)); 253 } 254 255 @Test 256 public void testFindItemById() { 257 CHILD_1.setId(12345); 258 CHILD_2.setId(23456); 259 260 mItemGroup.addChild(CHILD_1); 261 mItemGroup.addChild(CHILD_2); 262 263 assertSame("Find item 23456 should return child 2", 264 CHILD_2, mItemGroup.findItemById(23456)); 265 } 266 267 @Test 268 public void testFindItemByIdNotFound() { 269 CHILD_1.setId(12345); 270 CHILD_2.setId(23456); 271 272 mItemGroup.addChild(CHILD_1); 273 mItemGroup.addChild(CHILD_2); 274 275 assertNull("ID not found should return null", mItemGroup.findItemById(56789)); 276 } 277 278 /** 279 * This class will always return true on {@link #equals(Object)}. Used to ensure that ItemGroup 280 * is using identity rather than equals(). Be sure to use assertSame rather than assertEquals 281 * when comparing items of this class. 282 */ 283 private static class EqualsItem extends Item { 284 285 EqualsItem(String name) { 286 setTitle(name); 287 } 288 289 @Override 290 public int hashCode() { 291 return 1; 292 } 293 294 @Override 295 public boolean equals(Object obj) { 296 return obj instanceof Item; 297 } 298 299 @Override 300 public String toString() { 301 return "EqualsItem{title=" + getTitle() + "}"; 302 } 303 } 304} 305