/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3.util import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.util.rule.TestStabilityRule import java.util.concurrent.ExecutorService import java.util.concurrent.locks.ReentrantLock import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith /** Unit test for [CancellableTask] */ @SmallTest @RunWith(AndroidJUnit4::class) class CancellableTaskTest { private lateinit var underTest: CancellableTask<Int> private val lock = ReentrantLock() private var result: Int = -1 private var isTaskExecuted = false private var isCallbackExecuted = false @get:Rule(order = 0) val testStabilityRule = TestStabilityRule() @Before fun setup() { reset() submitJob() } private fun submitJob() { underTest = CancellableTask( { isTaskExecuted = true 1 }, Executors.VIEW_PREINFLATION_EXECUTOR, { isCallbackExecuted = true result = it + 1 } ) Executors.UI_HELPER_EXECUTOR.execute(underTest) } @Test fun run_and_complete() { awaitAllExecutorCompleted() assertTrue("task should be executed", isTaskExecuted) assertTrue("callback should be executed", isCallbackExecuted) assertEquals(2, result) } @Test fun run_and_cancel_cancelTaskAndCallback() { awaitAllExecutorCompleted() reset() lock.lock() Executors.UI_HELPER_EXECUTOR.submit { lock.lock() } submitJob() underTest.cancel() lock.unlock() // unblock task on UI_HELPER_EXECUTOR awaitAllExecutorCompleted() assertFalse("task should not be executed.", isTaskExecuted) assertFalse("callback should not be executed.", isCallbackExecuted) assertEquals(0, result) } @Test fun run_and_cancel_cancelCallback() { awaitAllExecutorCompleted() reset() lock.lock() Executors.VIEW_PREINFLATION_EXECUTOR.submit { lock.lock() } submitJob() awaitExecutorCompleted(Executors.UI_HELPER_EXECUTOR) assertTrue("task should be executed.", isTaskExecuted) underTest.cancel() lock.unlock() // unblock callback on VIEW_PREINFLATION_EXECUTOR awaitExecutorCompleted(Executors.VIEW_PREINFLATION_EXECUTOR) assertFalse("callback should not be executed.", isCallbackExecuted) assertEquals(0, result) } @Test fun run_and_cancelAfterCompletion_executeAll() { awaitAllExecutorCompleted() underTest.cancel() assertTrue("task should be executed", isTaskExecuted) assertTrue("callback should be executed", isCallbackExecuted) assertEquals(2, result) } private fun awaitExecutorCompleted(executor: ExecutorService) { executor.submit<Any> { null }.get() } private fun awaitAllExecutorCompleted() { awaitExecutorCompleted(Executors.UI_HELPER_EXECUTOR) awaitExecutorCompleted(Executors.VIEW_PREINFLATION_EXECUTOR) } private fun reset() { result = 0 isTaskExecuted = false isCallbackExecuted = false } }