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