1 /* 2 * Copyright (C) 2019 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.systemui.controls.management 18 19 import android.app.PendingIntent 20 import android.content.ComponentName 21 import android.service.controls.Control 22 import android.testing.AndroidTestingRunner 23 import androidx.test.filters.SmallTest 24 import com.android.systemui.SysuiTestCase 25 import com.android.systemui.controls.ControlStatus 26 import com.android.systemui.controls.controller.ControlInfo 27 import org.junit.Assert.assertEquals 28 import org.junit.Assert.assertFalse 29 import org.junit.Assert.assertTrue 30 import org.junit.Before 31 import org.junit.Test 32 import org.junit.runner.RunWith 33 import org.mockito.Mock 34 import org.mockito.Mockito.never 35 import org.mockito.Mockito.times 36 import org.mockito.Mockito.verify 37 import org.mockito.MockitoAnnotations 38 39 @SmallTest 40 @RunWith(AndroidTestingRunner::class) 41 class AllModelTest : SysuiTestCase() { 42 43 companion object { 44 private const val EMPTY_STRING = "Other" 45 } 46 47 @Mock 48 lateinit var pendingIntent: PendingIntent 49 @Mock 50 lateinit var controlsModelCallback: ControlsModel.ControlsModelCallback 51 52 val idPrefix = "controlId" 53 val favoritesIndices = listOf(7, 3, 1, 9) 54 val favoritesList = favoritesIndices.map { "controlId$it" } 55 lateinit var controls: List<ControlStatus> 56 57 lateinit var model: AllModel 58 59 private fun zoneMap(id: Int): String? { 60 return when (id) { 61 10 -> "" 62 11 -> null 63 else -> ((id + 1) % 3).toString() 64 } 65 } 66 67 @Before 68 fun setUp() { 69 MockitoAnnotations.initMocks(this) 70 71 // controlId0 --> zone = 1 72 // controlId1 --> zone = 2, favorite 73 // controlId2 --> zone = 0 74 // controlId3 --> zone = 1, favorite 75 // controlId4 --> zone = 2 76 // controlId5 --> zone = 0 77 // controlId6 --> zone = 1 78 // controlId7 --> zone = 2, favorite 79 // controlId8 --> zone = 0 80 // controlId9 --> zone = 1, favorite 81 // controlId10 --> zone = "" 82 // controlId11 --> zone = null 83 controls = (0..11).map { 84 ControlStatus( 85 Control.StatelessBuilder("$idPrefix$it", pendingIntent) 86 .setZone(zoneMap(it)) 87 .build(), 88 ComponentName("", ""), 89 it in favoritesIndices 90 ) 91 } 92 model = AllModel(controls, favoritesList, EMPTY_STRING, controlsModelCallback) 93 } 94 95 @Test 96 fun testElements() { 97 98 // Zones are sorted by order of appearance, with empty at the end with special header. 99 val expected = listOf( 100 ZoneNameWrapper("1"), 101 ControlStatusWrapper(controls[0]), 102 ControlStatusWrapper(controls[3]), 103 ControlStatusWrapper(controls[6]), 104 ControlStatusWrapper(controls[9]), 105 ZoneNameWrapper("2"), 106 ControlStatusWrapper(controls[1]), 107 ControlStatusWrapper(controls[4]), 108 ControlStatusWrapper(controls[7]), 109 ZoneNameWrapper("0"), 110 ControlStatusWrapper(controls[2]), 111 ControlStatusWrapper(controls[5]), 112 ControlStatusWrapper(controls[8]), 113 ZoneNameWrapper(EMPTY_STRING), 114 ControlStatusWrapper(controls[10]), 115 ControlStatusWrapper(controls[11]) 116 ) 117 expected.zip(model.elements).forEachIndexed { index, it -> 118 assertEquals("Error in item at index $index", it.first, it.second) 119 } 120 } 121 122 private fun sameControl(controlInfo: ControlInfo, control: Control): Boolean { 123 return controlInfo.controlId == control.controlId && 124 controlInfo.controlTitle == control.title && 125 controlInfo.controlSubtitle == control.subtitle && 126 controlInfo.deviceType == control.deviceType 127 } 128 129 @Test 130 fun testAllEmpty_noHeader() { 131 val selected_controls = listOf(controls[10], controls[11]) 132 val new_model = AllModel(selected_controls, emptyList(), EMPTY_STRING, 133 controlsModelCallback) 134 val expected = listOf( 135 ControlStatusWrapper(controls[10]), 136 ControlStatusWrapper(controls[11]) 137 ) 138 139 expected.zip(new_model.elements).forEachIndexed { index, it -> 140 assertEquals("Error in item at index $index", it.first, it.second) 141 } 142 } 143 144 @Test 145 fun testFavorites() { 146 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 147 model.favorites.zip(expectedFavorites).forEach { 148 assertTrue(sameControl(it.first, it.second)) 149 } 150 } 151 152 @Test 153 fun testAddFavorite() { 154 val indexToAdd = 6 155 model.changeFavoriteStatus("$idPrefix$indexToAdd", true) 156 157 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + 158 controls[indexToAdd].control 159 160 model.favorites.zip(expectedFavorites).forEach { 161 assertTrue(sameControl(it.first, it.second)) 162 } 163 164 verify(controlsModelCallback).onFirstChange() 165 verify(controlsModelCallback).onChange() 166 } 167 168 @Test 169 fun testAddFavorite_changesModelFlag() { 170 val indexToAdd = 6 171 val id = "$idPrefix$indexToAdd" 172 model.changeFavoriteStatus(id, true) 173 assertTrue( 174 (model.elements.first { 175 it is ControlStatusWrapper && it.controlStatus.control.controlId == id 176 } as ControlStatusWrapper) 177 .controlStatus.favorite 178 ) 179 180 verify(controlsModelCallback).onFirstChange() 181 verify(controlsModelCallback).onChange() 182 } 183 184 @Test 185 fun testAddFavorite_alreadyThere() { 186 val indexToAdd = 7 187 model.changeFavoriteStatus("$idPrefix$indexToAdd", true) 188 189 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 190 191 assertEquals(expectedFavorites.size, model.favorites.size) 192 model.favorites.zip(expectedFavorites).forEach { 193 assertTrue(sameControl(it.first, it.second)) 194 } 195 196 verify(controlsModelCallback, never()).onFirstChange() 197 verify(controlsModelCallback, never()).onChange() 198 } 199 200 @Test 201 fun testRemoveFavorite() { 202 val indexToRemove = 3 203 model.changeFavoriteStatus("$idPrefix$indexToRemove", false) 204 205 val expectedFavorites = (favoritesIndices.filterNot { it == indexToRemove }) 206 .map(controls::get) 207 .map(ControlStatus::control) 208 209 model.favorites.zip(expectedFavorites).forEach { 210 assertTrue(sameControl(it.first, it.second)) 211 } 212 213 verify(controlsModelCallback).onFirstChange() 214 verify(controlsModelCallback).onChange() 215 } 216 217 @Test 218 fun testRemoveFavorite_changesModelFlag() { 219 val indexToRemove = 3 220 val id = "$idPrefix$indexToRemove" 221 model.changeFavoriteStatus(id, false) 222 assertFalse( 223 (model.elements.first { 224 it is ControlStatusWrapper && it.controlStatus.control.controlId == id 225 } as ControlStatusWrapper) 226 .controlStatus.favorite 227 ) 228 229 verify(controlsModelCallback).onFirstChange() 230 verify(controlsModelCallback).onChange() 231 } 232 233 @Test 234 fun testRemoveFavorite_notThere() { 235 val indexToRemove = 4 236 model.changeFavoriteStatus("$idPrefix$indexToRemove", false) 237 238 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 239 240 model.favorites.zip(expectedFavorites).forEach { 241 assertTrue(sameControl(it.first, it.second)) 242 } 243 244 verify(controlsModelCallback, never()).onFirstChange() 245 verify(controlsModelCallback, never()).onChange() 246 } 247 248 @Test 249 fun testAddSecondChange_callbacks() { 250 model.changeFavoriteStatus("${idPrefix}4", true) 251 model.changeFavoriteStatus("${idPrefix}5", true) 252 253 verify(controlsModelCallback).onFirstChange() 254 verify(controlsModelCallback, times(2)).onChange() 255 } 256 257 @Test 258 fun testRemoveSecondChange_callbacks() { 259 model.changeFavoriteStatus("${idPrefix}1", false) 260 model.changeFavoriteStatus("${idPrefix}3", false) 261 262 verify(controlsModelCallback).onFirstChange() 263 verify(controlsModelCallback, times(2)).onChange() 264 } 265 } 266