1 /*
2  * Copyright (C) 2022 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 package com.android.launcher3.model
17 
18 import android.graphics.Rect
19 import androidx.test.ext.junit.runners.AndroidJUnit4
20 import androidx.test.filters.SmallTest
21 import com.google.common.truth.Truth.assertThat
22 import org.junit.After
23 import org.junit.Before
24 import org.junit.Test
25 import org.junit.runner.RunWith
26 
27 /** Tests for [WorkspaceItemSpaceFinder] */
28 @SmallTest
29 @RunWith(AndroidJUnit4::class)
30 class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
31 
32     private val mItemSpaceFinder = WorkspaceItemSpaceFinder()
33 
34     @Before
setupnull35     override fun setup() {
36         super.setup()
37     }
38 
39     @After
tearDownnull40     override fun tearDown() {
41         super.tearDown()
42     }
43 
findSpacenull44     private fun findSpace(spanX: Int, spanY: Int): NewItemSpace =
45         mItemSpaceFinder
46             .findSpaceForItem(
47                 mAppState,
48                 mModelHelper.bgDataModel,
49                 mExistingScreens,
50                 mNewScreens,
51                 spanX,
52                 spanY
53             )
54             .let { NewItemSpace.fromIntArray(it) }
55 
assertRegionVacantnull56     private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) {
57         assertThat(
58                 mScreenOccupancy[newItemSpace.screenId].isRegionVacant(
59                     newItemSpace.cellX,
60                     newItemSpace.cellY,
61                     spanX,
62                     spanY
63                 )
64             )
65             .isTrue()
66     }
67 
68     @Test
justEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnFirstScreenIdnull69     fun justEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnFirstScreenId() {
70         setupWorkspacesWithSpaces(
71             // 3x2 space on screen 0, but it should be skipped
72             screen0 = listOf(Rect(2, 0, 5, 2)),
73             screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 space
74             //  2 spaces of sizes 3x2 and 2x3
75             screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
76         )
77 
78         val spaceFound = findSpace(1, 1)
79 
80         assertThat(spaceFound.screenId).isEqualTo(1)
81         assertRegionVacant(spaceFound, 1, 1)
82     }
83 
84     @Test
notEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnSecondScreenIdnull85     fun notEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnSecondScreenId() {
86         setupWorkspacesWithSpaces(
87             // 3x2 space on screen 0, but it should be skipped
88             screen0 = listOf(Rect(2, 0, 5, 2)),
89             screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 space
90             //  2 spaces of sizes 3x2 and 2x3
91             screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
92         )
93 
94         // Find a larger space
95         val spaceFound = findSpace(2, 3)
96 
97         assertThat(spaceFound.screenId).isEqualTo(2)
98         assertRegionVacant(spaceFound, 2, 3)
99     }
100 
101     @Test
notEnoughSpaceOnExistingScreens_returnNewScreenIdnull102     fun notEnoughSpaceOnExistingScreens_returnNewScreenId() {
103         setupWorkspacesWithSpaces(
104             // 3x2 space on screen 0, but it should be skipped
105             screen0 = listOf(Rect(2, 0, 5, 2)),
106             //  2 spaces of sizes 3x2 and 2x3
107             screen1 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
108             //  2 spaces of sizes 1x2 and 2x2
109             screen2 = listOf(Rect(1, 0, 2, 2), Rect(3, 2, 5, 4)),
110         )
111 
112         val oldScreens = mExistingScreens.clone()
113         val spaceFound = findSpace(3, 3)
114 
115         assertThat(oldScreens.contains(spaceFound.screenId)).isFalse()
116         assertThat(mNewScreens.contains(spaceFound.screenId)).isTrue()
117     }
118 
119     @Test
firstScreenIsEmptyButSecondIsNotEmpty_returnSecondScreenIdnull120     fun firstScreenIsEmptyButSecondIsNotEmpty_returnSecondScreenId() {
121         setupWorkspacesWithSpaces(
122             // 3x2 space on screen 0, but it should be skipped
123             screen0 = listOf(Rect(2, 0, 5, 2)),
124             // empty screens are skipped
125             screen2 = listOf(Rect(2, 0, 5, 2)), // 3x2 space
126         )
127 
128         val spaceFound = findSpace(2, 1)
129 
130         assertThat(spaceFound.screenId).isEqualTo(2)
131         assertRegionVacant(spaceFound, 2, 1)
132     }
133 
134     @Test
twoEmptyMiddleScreens_returnThirdScreennull135     fun twoEmptyMiddleScreens_returnThirdScreen() {
136         setupWorkspacesWithSpaces(
137             // 3x2 space on screen 0, but it should be skipped
138             screen0 = listOf(Rect(2, 0, 5, 2)),
139             // empty screens are skipped
140             screen3 = listOf(Rect(1, 1, 4, 4)), // 3x3 space
141         )
142 
143         val spaceFound = findSpace(2, 3)
144 
145         assertThat(spaceFound.screenId).isEqualTo(3)
146         assertRegionVacant(spaceFound, 2, 3)
147     }
148 
149     @Test
allExistingPagesAreFull_returnNewScreenIdnull150     fun allExistingPagesAreFull_returnNewScreenId() {
151         setupWorkspacesWithSpaces(
152             // 3x2 space on screen 0, but it should be skipped
153             screen0 = listOf(Rect(2, 0, 5, 2)),
154             screen1 = fullScreenSpaces,
155             screen2 = fullScreenSpaces,
156         )
157 
158         val spaceFound = findSpace(2, 3)
159 
160         assertThat(spaceFound.screenId).isEqualTo(3)
161         assertThat(mNewScreens.contains(spaceFound.screenId)).isTrue()
162     }
163 
164     @Test
firstTwoPagesAreFull_and_ThirdPageIsEmpty_returnThirdPagenull165     fun firstTwoPagesAreFull_and_ThirdPageIsEmpty_returnThirdPage() {
166         setupWorkspacesWithSpaces(
167             // 3x2 space on screen 0, but it should be skipped
168             screen0 = listOf(Rect(2, 0, 5, 2)),
169             screen1 = fullScreenSpaces, // full screens are skipped
170             screen2 = fullScreenSpaces, // full screens are skipped
171             screen3 = emptyScreenSpaces
172         )
173 
174         val spaceFound = findSpace(3, 1)
175 
176         assertThat(spaceFound.screenId).isEqualTo(3)
177         assertRegionVacant(spaceFound, 3, 1)
178     }
179 }
180