1 /* 2 * Copyright (C) 2023 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.systemui.util.test 18 19 import android.util.Log 20 21 /** 22 * Helper class that intercepts test errors which may be occurring on the wrong thread, and saves 23 * them so that they can be rethrown back on the correct thread. 24 */ 25 class TestExceptionDeferrer(private val tag: String, private val testThread: Thread) { 26 private val deferredErrors = mutableListOf<IllegalStateException>() 27 28 /** Ensure the [value] is `true`; otherwise [fail] with the produced [message] */ 29 fun check(value: Boolean, message: () -> Any?) { 30 if (value) return 31 fail(message().toString()) 32 } 33 34 /** 35 * If the [Thread.currentThread] is the [testThread], then [error], otherwise [Log] and defer 36 * the error until [throwDeferred] is called. 37 */ 38 fun fail(message: String) { 39 if (testThread == Thread.currentThread()) { 40 error(message) 41 } else { 42 val exception = IllegalStateException(message) 43 Log.e(tag, "Deferring error: ", exception) 44 deferredErrors.add(exception) 45 } 46 } 47 48 /** If any [fail] or failed [check] has happened, throw the first one. */ 49 fun throwDeferred() { 50 deferredErrors.firstOrNull()?.let { firstError -> 51 Log.e(tag, "Deferred errors: ${deferredErrors.size}") 52 deferredErrors.clear() 53 throw firstError 54 } 55 } 56 } 57