1 /*
2  * 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.recyclerview
18 
19 import android.content.Context
20 import android.view.View
21 import android.view.ViewGroup
22 import androidx.recyclerview.widget.RecyclerView
23 import androidx.recyclerview.widget.RecyclerView.LayoutManager
24 import androidx.recyclerview.widget.RecyclerView.ViewHolder
25 import androidx.test.ext.junit.runners.AndroidJUnit4
26 import androidx.test.filters.SmallTest
27 import com.android.launcher3.util.Executors
28 import com.android.launcher3.views.ActivityContext
29 import com.google.common.truth.Truth.assertThat
30 import org.junit.Before
31 import org.junit.Test
32 import org.junit.runner.RunWith
33 import org.mockito.ArgumentMatchers.any
34 import org.mockito.Mock
35 import org.mockito.Mockito.never
36 import org.mockito.Mockito.spy
37 import org.mockito.Mockito.times
38 import org.mockito.Mockito.verify
39 import org.mockito.Mockito.`when`
40 import org.mockito.MockitoAnnotations
41 
42 @SmallTest
43 @RunWith(AndroidJUnit4::class)
44 class AllAppsRecyclerViewPoolTest<T> where T : Context, T : ActivityContext {
45 
46     private lateinit var underTest: AllAppsRecyclerViewPool<T>
47     private lateinit var adapter: RecyclerView.Adapter<*>
48 
49     @Mock private lateinit var parent: RecyclerView
50     @Mock private lateinit var itemView: View
51     @Mock private lateinit var layoutManager: LayoutManager
52 
53     @Before
setUpnull54     fun setUp() {
55         MockitoAnnotations.initMocks(this)
56         underTest = spy(AllAppsRecyclerViewPool())
57         adapter =
58             object : RecyclerView.Adapter<ViewHolder>() {
59                 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
60                     object : ViewHolder(itemView) {}
61 
62                 override fun getItemCount() = 0
63 
64                 override fun onBindViewHolder(holder: ViewHolder, position: Int) {}
65             }
66         underTest.setMaxRecycledViews(VIEW_TYPE, 20)
67         `when`(parent.layoutManager).thenReturn(layoutManager)
68     }
69 
70     @Test
preinflate_successnull71     fun preinflate_success() {
72         underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
73 
74         awaitTasksCompleted()
75         assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(10)
76     }
77 
78     @Test
preinflate_not_triggerednull79     fun preinflate_not_triggered() {
80         underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 0) { 0 }
81 
82         awaitTasksCompleted()
83         assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(0)
84     }
85 
86     @Test
preinflate_cancel_before_runOnMainThreadnull87     fun preinflate_cancel_before_runOnMainThread() {
88         underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
89         assertThat(underTest.mCancellableTask!!.canceled).isFalse()
90 
91         underTest.clear()
92 
93         awaitTasksCompleted()
94         verify(underTest, never()).putRecycledView(any(ViewHolder::class.java))
95         assertThat(underTest.mCancellableTask!!.canceled).isTrue()
96         assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(0)
97     }
98 
99     @Test
preinflate_cancel_after_runnull100     fun preinflate_cancel_after_run() {
101         underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
102         assertThat(underTest.mCancellableTask!!.canceled).isFalse()
103         awaitTasksCompleted()
104 
105         underTest.clear()
106 
107         verify(underTest, times(10)).putRecycledView(any(ViewHolder::class.java))
108         assertThat(underTest.mCancellableTask!!.canceled).isTrue()
109         assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(0)
110     }
111 
awaitTasksCompletednull112     private fun awaitTasksCompleted() {
113         Executors.VIEW_PREINFLATION_EXECUTOR.submit<Any> { null }.get()
114         Executors.MAIN_EXECUTOR.submit<Any> { null }.get()
115     }
116 
117     companion object {
118         private const val VIEW_TYPE: Int = 4
119     }
120 }
121