1 /* <lambda>null2 * Copyright (C) 2019 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.testutils 18 19 import android.os.Handler 20 import android.os.HandlerThread 21 import com.android.testutils.FunctionalUtils.ThrowingSupplier 22 import kotlin.test.assertEquals 23 import kotlin.test.assertFailsWith 24 import kotlin.test.assertNull 25 import org.junit.Test 26 import org.junit.runner.RunWith 27 import org.junit.runners.JUnit4 28 29 private const val ATTEMPTS = 50 // Causes testWaitForIdle to take about 150ms on aosp_crosshatch-eng 30 private const val TIMEOUT_MS = 1000 31 32 @RunWith(JUnit4::class) 33 class HandlerUtilsTest { 34 @Test 35 fun testWaitForIdle() { 36 val handlerThread = HandlerThread("testHandler").apply { start() } 37 38 // Tests that waitForIdle can be called many times without ill impact if the service is 39 // already idle. 40 repeat(ATTEMPTS) { 41 handlerThread.waitForIdle(TIMEOUT_MS) 42 } 43 44 // Tests that calling waitForIdle waits for messages to be processed. Use both an 45 // inline runnable that's instantiated at each loop run and a runnable that's instantiated 46 // once for all. 47 val tempRunnable = object : Runnable { 48 // Use StringBuilder preferentially to StringBuffer because StringBuilder is NOT 49 // thread-safe. It's part of the point that both runnables run on the same thread 50 // so if anything is wrong in that space it's better to opportunistically use a class 51 // where things might go wrong, even if there is no guarantee of failure. 52 var memory = StringBuilder() 53 override fun run() { 54 memory.append("b") 55 } 56 } 57 repeat(ATTEMPTS) { i -> 58 handlerThread.threadHandler.post { tempRunnable.memory.append("a"); } 59 handlerThread.threadHandler.post(tempRunnable) 60 handlerThread.waitForIdle(TIMEOUT_MS) 61 assertEquals(tempRunnable.memory.toString(), "ab".repeat(i + 1)) 62 } 63 } 64 65 // Statistical test : even if visibleOnHandlerThread doesn't work this is likely to succeed, 66 // but it will be at least flaky. 67 @Test 68 fun testVisibleOnHandlerThread() { 69 val handlerThread = HandlerThread("testHandler").apply { start() } 70 val handler = Handler(handlerThread.looper) 71 72 repeat(ATTEMPTS) { attempt -> 73 var x = -10 74 var y = -11 75 y = visibleOnHandlerThread(handler, ThrowingSupplier<Int> { x = attempt; attempt }) 76 assertEquals(attempt, x) 77 assertEquals(attempt, y) 78 handler.post { assertEquals(attempt, x) } 79 } 80 81 assertFailsWith<IllegalArgumentException> { 82 visibleOnHandlerThread(handler) { throw IllegalArgumentException() } 83 } 84 85 // Null values may be returned by the supplier 86 assertNull(visibleOnHandlerThread(handler, ThrowingSupplier<Nothing?> { null })) 87 } 88 } 89