1 /*
<lambda>null2  * Copyright (C) 2024 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.launcher3.celllayout.testgenerator
18 
19 import android.graphics.Point
20 import com.android.launcher3.LauncherSettings
21 import com.android.launcher3.celllayout.board.CellLayoutBoard
22 import com.android.launcher3.model.data.LauncherAppWidgetInfo
23 import com.android.launcher3.model.gridmigration.WorkspaceItem
24 import java.util.Random
25 import java.util.concurrent.atomic.AtomicInteger
26 
27 /**
28  * Generate a list of WorkspaceItem's for the given test case.
29  *
30  * @param repeatAfter a number after which we would repeat the same number of icons and widgets to
31  *   account for cases where the user have the same item multiple times.
32  */
33 fun generateItemsForTest(
34     boards: List<CellLayoutBoard>,
35     repeatAfterRange: Point
36 ): List<WorkspaceItem> {
37     val id = AtomicInteger(0)
38     val widgetId = AtomicInteger(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - 1)
39     // Repeat the same appWidgetProvider and intent to have repeating widgets and icons and test
40     // that case too
41     val getIntent = { i: Int -> "Intent ${(i + repeatAfterRange.x) % repeatAfterRange.y}" }
42     val getProvider = { i: Int ->
43         "com.test/test.Provider${(i + repeatAfterRange.x) % repeatAfterRange.y }"
44     }
45     val hotseatEntries =
46         (0 until boards[0].width).map {
47             WorkspaceItem(
48                 x = it,
49                 y = 0,
50                 spanX = 1,
51                 spanY = 1,
52                 id = id.getAndAdd(1),
53                 screenId = it,
54                 title = "Hotseat ${id.get()}",
55                 appWidgetId = -1,
56                 appWidgetProvider = "Hotseat icons don't have a provider",
57                 intent = getIntent(id.get()),
58                 type = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION,
59                 container = LauncherSettings.Favorites.CONTAINER_HOTSEAT
60             )
61         }
62     var widgetEntries =
63         boards
64             .flatMapIndexed { i, board -> board.widgets.map { Pair(i, it) } }
65             .map {
66                 WorkspaceItem(
67                     x = it.second.cellX,
68                     y = it.second.cellY,
69                     spanX = it.second.spanX,
70                     spanY = it.second.spanY,
71                     id = id.getAndAdd(1),
72                     screenId = it.first,
73                     title = "Title Widget ${id.get()}",
74                     appWidgetId = widgetId.getAndAdd(-1),
75                     appWidgetProvider = getProvider(id.get()),
76                     intent = "Widgets don't have intent",
77                     type = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET,
78                     container = LauncherSettings.Favorites.CONTAINER_DESKTOP
79                 )
80             }
81     widgetEntries = widgetEntries.filter { it.appWidgetProvider.contains("Provider4") }
82     val iconEntries =
83         boards
84             .flatMapIndexed { i, board -> board.icons.map { Pair(i, it) } }
85             .map {
86                 WorkspaceItem(
87                     x = it.second.coord.x,
88                     y = it.second.coord.y,
89                     spanX = 1,
90                     spanY = 1,
91                     id = id.getAndAdd(1),
92                     screenId = it.first,
93                     title = "Title Icon ${id.get()}",
94                     appWidgetId = -1,
95                     appWidgetProvider = "Icons don't have providers",
96                     intent = getIntent(id.get()),
97                     type = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION,
98                     container = LauncherSettings.Favorites.CONTAINER_DESKTOP
99                 )
100             }
101     return widgetEntries + hotseatEntries + iconEntries
102 }
103 
104 data class GridMigrationUnitTestCase(
105     val boards: List<CellLayoutBoard>,
106     val destBoards: List<CellLayoutBoard>,
107     val srcSize: Point,
108     val targetSize: Point,
109     val seed: Long
110 )
111 
112 class ValidGridMigrationTestCaseGenerator(private val generator: Random) :
113     DeterministicRandomGenerator(generator) {
114 
115     companion object {
116         const val MAX_BOARD_SIZE = 12
117         const val MAX_BOARD_COUNT = 10
118         const val SEED = 10342
119     }
120 
generateBoardsnull121     private fun generateBoards(
122         boardGenerator: RandomBoardGenerator,
123         width: Int,
124         height: Int,
125         boardCount: Int
126     ): List<CellLayoutBoard> {
127         val boards = mutableListOf<CellLayoutBoard>()
128         for (i in 0 until boardCount) {
129             boards.add(
130                 boardGenerator.generateBoard(
131                     width,
132                     height,
133                     boardGenerator.getRandom(0, width * height)
134                 )
135             )
136         }
137         return boards
138     }
139 
generateTestCasenull140     fun generateTestCase(isDestEmpty: Boolean): GridMigrationUnitTestCase {
141         val seed = generator.nextLong()
142         val randomBoardGenerator = RandomBoardGenerator(Random(seed))
143         val width = randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
144         val height = randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
145         val targetSize =
146             Point(
147                 randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE),
148                 randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
149             )
150         val destBoards =
151             if (isDestEmpty) {
152                 listOf()
153             } else {
154                 generateBoards(
155                     boardGenerator = randomBoardGenerator,
156                     width = targetSize.x,
157                     height = targetSize.y,
158                     boardCount = randomBoardGenerator.getRandom(3, MAX_BOARD_COUNT)
159                 )
160             }
161         return GridMigrationUnitTestCase(
162             boards =
163                 generateBoards(
164                     boardGenerator = randomBoardGenerator,
165                     width = width,
166                     height = height,
167                     boardCount = randomBoardGenerator.getRandom(3, MAX_BOARD_COUNT)
168                 ),
169             destBoards = destBoards,
170             srcSize = Point(width, height),
171             targetSize = targetSize,
172             seed = seed
173         )
174     }
175 }
176