ART: Refactor run-test 924
Move testing to a dedicated thread to have a known thread name.
Change event reporting to be Java-side. Use Java-side thread list
(from Thread.getAllStackTraces) as comparison for minimal expected
set of threads.
Bug: 32072923
Test: art/test/testrunner/testrunner.py -b --host -t 924
Change-Id: I238ffc202e42eea8d1788137715188d3dfbcc8fb
diff --git a/test/924-threads/expected.txt b/test/924-threads/expected.txt
index 4c0f4ea..1eb2e1b 100644
--- a/test/924-threads/expected.txt
+++ b/test/924-threads/expected.txt
@@ -1,10 +1,10 @@
currentThread OK
-main
+TestThread
5
false
java.lang.ThreadGroup[name=main,maxpri=10]
class dalvik.system.PathClassLoader
-main
+TestThread
5
false
java.lang.ThreadGroup[name=main,maxpri=10]
@@ -33,10 +33,11 @@
e1 = ALIVE|WAITING_WITH_TIMEOUT|SLEEPING|WAITING
5 = ALIVE|RUNNABLE
2 = TERMINATED
-[Thread[FinalizerDaemon,5,system], Thread[FinalizerWatchdogDaemon,5,system], Thread[HeapTaskDaemon,5,system], Thread[ReferenceQueueDaemon,5,system], Thread[Signal Catcher,5,system], Thread[main,5,main]]
+[Thread[FinalizerDaemon,5,system], Thread[FinalizerWatchdogDaemon,5,system], Thread[HeapTaskDaemon,5,system], Thread[ReferenceQueueDaemon,5,system], Thread[TestThread,5,main], Thread[main,5,main]]
JVMTI_ERROR_THREAD_NOT_ALIVE
JVMTI_ERROR_THREAD_NOT_ALIVE
Constructed thread
-Thread(EventTestThread): start
-Thread(EventTestThread): end
+[]
+[Thread(EventTestThread): start]
+[Thread(EventTestThread): end]
Thread joined
diff --git a/test/924-threads/src/art/Test924.java b/test/924-threads/src/art/Test924.java
index 160bf8e..5445939 100644
--- a/test/924-threads/src/art/Test924.java
+++ b/test/924-threads/src/art/Test924.java
@@ -25,17 +25,35 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public class Test924 {
public static void run() throws Exception {
Main.bindAgentJNIForClass(Test924.class);
- doTest();
+
+ // Run the test on its own thread, so we have a known state for the "current" thread.
+ Thread t = new Thread("TestThread") {
+ @Override
+ public void run() {
+ try {
+ doTest();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ t.start();
+ t.join();
}
private static void doTest() throws Exception {
Thread t1 = Thread.currentThread();
Thread t2 = getCurrentThread();
+ // Need to adjust priority, as on-device this may be unexpected (and we prefer not
+ // to special-case this.)
+ t1.setPriority(5);
+
if (t1 != t2) {
throw new RuntimeException("Expected " + t1 + " but got " + t2);
}
@@ -188,7 +206,32 @@
}
Collections.sort(threadList, THREAD_COMP);
- System.out.println(threadList);
+
+ List<Thread> expectedList = new ArrayList<>();
+ Set<Thread> threadsFromTraces = Thread.getAllStackTraces().keySet();
+
+ expectedList.add(findThreadByName(threadsFromTraces, "FinalizerDaemon"));
+ expectedList.add(findThreadByName(threadsFromTraces, "FinalizerWatchdogDaemon"));
+ expectedList.add(findThreadByName(threadsFromTraces, "HeapTaskDaemon"));
+ expectedList.add(findThreadByName(threadsFromTraces, "ReferenceQueueDaemon"));
+ // We can't get the signal catcher through getAllStackTraces. So ignore it.
+ // expectedList.add(findThreadByName(threadsFromTraces, "Signal Catcher"));
+ expectedList.add(findThreadByName(threadsFromTraces, "TestThread"));
+ expectedList.add(findThreadByName(threadsFromTraces, "main"));
+
+ if (!threadList.containsAll(expectedList)) {
+ throw new RuntimeException("Expected " + expectedList + " as subset, got " + threadList);
+ }
+ System.out.println(expectedList);
+ }
+
+ private static Thread findThreadByName(Set<Thread> threads, String name) {
+ for (Thread t : threads) {
+ if (t.getName().equals(name)) {
+ return t;
+ }
+ }
+ throw new RuntimeException("Did not find thread " + name + ": " + threads);
}
private static void doTLSTests() throws Exception {
@@ -256,13 +299,35 @@
private static void doTestEvents() throws Exception {
enableThreadEvents(true);
- Thread t = new Thread("EventTestThread");
+ final CountDownLatch cdl1 = new CountDownLatch(1);
+ final CountDownLatch cdl2 = new CountDownLatch(1);
+
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ cdl1.countDown();
+ cdl2.await();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ Thread t = new Thread(r, "EventTestThread");
System.out.println("Constructed thread");
Thread.yield();
+ Thread.sleep(100);
+ System.out.println(Arrays.toString(getThreadEventMessages()));
t.start();
+ cdl1.await();
+
+ System.out.println(Arrays.toString(getThreadEventMessages()));
+
+ cdl2.countDown();
t.join();
+ System.out.println(Arrays.toString(getThreadEventMessages()));
System.out.println("Thread joined");
@@ -337,4 +402,5 @@
private static native void setTLS(Thread t, long l);
private static native long getTLS(Thread t);
private static native void enableThreadEvents(boolean b);
+ private static native String[] getThreadEventMessages();
}
diff --git a/test/924-threads/threads.cc b/test/924-threads/threads.cc
index 701ab1d..e21dcc2 100644
--- a/test/924-threads/threads.cc
+++ b/test/924-threads/threads.cc
@@ -16,6 +16,10 @@
#include <stdio.h>
+#include <mutex>
+#include <string>
+#include <vector>
+
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "jni.h"
@@ -139,17 +143,27 @@
JvmtiErrorToException(env, jvmti_env, result);
}
+static std::mutex gEventsMutex;
+static std::vector<std::string> gEvents;
+
static void JNICALL ThreadEvent(jvmtiEnv* jvmti_env,
JNIEnv* jni_env,
jthread thread,
bool is_start) {
jvmtiThreadInfo info;
- jvmtiError result = jvmti_env->GetThreadInfo(thread, &info);
- if (result != JVMTI_ERROR_NONE) {
- printf("Error getting thread info");
- return;
+ {
+ std::lock_guard<std::mutex> guard(gEventsMutex);
+
+ jvmtiError result = jvmti_env->GetThreadInfo(thread, &info);
+ if (result != JVMTI_ERROR_NONE) {
+ gEvents.push_back("Error getting thread info");
+ return;
+ }
+
+ gEvents.push_back(android::base::StringPrintf("Thread(%s): %s",
+ info.name,
+ is_start ? "start" : "end"));
}
- printf("Thread(%s): %s\n", info.name, is_start ? "start" : "end");
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(info.name));
jni_env->DeleteLocalRef(info.thread_group);
@@ -205,5 +219,18 @@
JvmtiErrorToException(env, jvmti_env, ret);
}
+extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test924_getThreadEventMessages(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
+ std::lock_guard<std::mutex> guard(gEventsMutex);
+ jobjectArray ret = CreateObjectArray(env,
+ static_cast<jint>(gEvents.size()),
+ "java/lang/String",
+ [&](jint i) {
+ return env->NewStringUTF(gEvents[i].c_str());
+ });
+ gEvents.clear();
+ return ret;
+}
+
} // namespace Test924Threads
} // namespace art