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.test.tracing.coroutines.util 18 19 import kotlin.concurrent.Volatile 20 import org.junit.Assert.assertFalse 21 22 private val ALL_THREAD_STATES = hashMapOf<Thread, MutableList<String>>() 23 24 private class ThreadTraceState : ThreadLocal<MutableList<String>>() { initialValuenull25 override fun initialValue(): MutableList<String> { 26 synchronized(ALL_THREAD_STATES) { 27 val newValue = mutableListOf<String>() 28 ALL_THREAD_STATES[Thread.currentThread()] = newValue 29 return newValue 30 } 31 } 32 } 33 34 private val CURRENT_TRACE_STATE = ThreadTraceState() 35 currentThreadTraceStatenull36private fun currentThreadTraceState(): MutableList<String> { 37 return CURRENT_TRACE_STATE.get()!! 38 } 39 40 object FakeTraceState { 41 42 @Volatile @JvmStatic var isTracingEnabled: Boolean = true 43 clearAllnull44 fun clearAll() { 45 synchronized(ALL_THREAD_STATES) { ALL_THREAD_STATES.entries.forEach { it.value.clear() } } 46 } 47 beginnull48 fun begin(sectionName: String) { 49 currentThreadTraceState().add(sectionName) 50 } 51 endnull52 fun end() { 53 val threadId = Thread.currentThread().threadId() 54 val traceSections = currentThreadTraceState() 55 assertFalse( 56 "Attempting to close trace section on thread #$threadId, " + 57 "but there are no open sections", 58 traceSections.isEmpty(), 59 ) 60 traceSections.removeLast() 61 } 62 getOpenTraceSectionsOnCurrentThreadnull63 fun getOpenTraceSectionsOnCurrentThread(): Array<String> { 64 return currentThreadTraceState().toTypedArray() 65 } 66 67 /** 68 * Helper function for debugging; use as follows: 69 * ``` 70 * println(FakeThreadStateLocal) 71 * ``` 72 */ toStringnull73 override fun toString(): String { 74 val sb = StringBuilder() 75 synchronized(ALL_THREAD_STATES) { 76 ALL_THREAD_STATES.entries.forEach { sb.appendLine("${it.key} -> ${it.value}") } 77 } 78 return sb.toString() 79 } 80 } 81