8301767: Convert virtual thread tests to JUnit

Reviewed-by: cstein, lancea, jpai
This commit is contained in:
Alan Bateman 2023-02-08 14:56:28 +00:00
parent 9af2ea203d
commit ecf21a9a24
34 changed files with 1369 additions and 1244 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
* @bug 8284161 8287008 * @bug 8284161 8287008
* @summary Basic test for jcmd Thread.dump_to_file * @summary Basic test for jcmd Thread.dump_to_file
* @library /test/lib * @library /test/lib
* @run testng/othervm ThreadDumpToFileTest * @run junit/othervm ThreadDumpToFileTest
*/ */
import java.io.IOException; import java.io.IOException;
@ -37,16 +37,16 @@ import jdk.test.lib.dcmd.PidJcmdExecutor;
import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.threaddump.ThreadDump; import jdk.test.lib.threaddump.ThreadDump;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class ThreadDumpToFileTest { class ThreadDumpToFileTest {
/** /**
* Test thread dump, should be in plain text format. * Test thread dump, should be in plain text format.
*/ */
@Test @Test
public void testThreadDump() throws IOException { void testThreadDump() throws IOException {
Path file = genThreadDumpPath(".txt"); Path file = genThreadDumpPath(".txt");
testPlainThreadDump(file); testPlainThreadDump(file);
} }
@ -55,7 +55,7 @@ public class ThreadDumpToFileTest {
* Test thread dump in plain text format. * Test thread dump in plain text format.
*/ */
@Test @Test
public void testPlainThreadDump() throws IOException { void testPlainThreadDump() throws IOException {
Path file = genThreadDumpPath(".txt"); Path file = genThreadDumpPath(".txt");
testPlainThreadDump(file, "-format=plain"); testPlainThreadDump(file, "-format=plain");
} }
@ -64,7 +64,7 @@ public class ThreadDumpToFileTest {
* Test thread dump in JSON format. * Test thread dump in JSON format.
*/ */
@Test @Test
public void testJsonThreadDump() throws IOException { void testJsonThreadDump() throws IOException {
Path file = genThreadDumpPath(".json"); Path file = genThreadDumpPath(".json");
threadDump(file, "-format=json").shouldMatch("Created"); threadDump(file, "-format=json").shouldMatch("Created");
@ -85,21 +85,21 @@ public class ThreadDumpToFileTest {
* Test that an existing file is not overwritten. * Test that an existing file is not overwritten.
*/ */
@Test @Test
public void testDoNotOverwriteFile() throws IOException { void testDoNotOverwriteFile() throws IOException {
Path file = genThreadDumpPath(".txt"); Path file = genThreadDumpPath(".txt");
Files.writeString(file, "xxx"); Files.writeString(file, "xxx");
threadDump(file, "").shouldMatch("exists"); threadDump(file, "").shouldMatch("exists");
// file should not be overridden // file should not be overridden
assertEquals(Files.readString(file), "xxx"); assertEquals("xxx", Files.readString(file));
} }
/** /**
* Test overwriting an existing file. * Test overwriting an existing file.
*/ */
@Test @Test
public void testOverwriteFile() throws IOException { void testOverwriteFile() throws IOException {
Path file = genThreadDumpPath(".txt"); Path file = genThreadDumpPath(".txt");
Files.writeString(file, "xxx"); Files.writeString(file, "xxx");
testPlainThreadDump(file, "-overwrite"); testPlainThreadDump(file, "-overwrite");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,10 +27,10 @@
* @summary Basic test for com.sun.management.HotSpotDiagnosticMXBean.dumpThreads * @summary Basic test for com.sun.management.HotSpotDiagnosticMXBean.dumpThreads
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm DumpThreads * @run junit/othervm DumpThreads
* @run testng/othervm -Djdk.trackAllThreads DumpThreads * @run junit/othervm -Djdk.trackAllThreads DumpThreads
* @run testng/othervm -Djdk.trackAllThreads=true DumpThreads * @run junit/othervm -Djdk.trackAllThreads=true DumpThreads
* @run testng/othervm -Djdk.trackAllThreadds=false DumpThreads * @run junit/othervm -Djdk.trackAllThreadds=false DumpThreads
*/ */
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
@ -47,10 +47,10 @@ import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat; import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat;
import jdk.test.lib.threaddump.ThreadDump; import jdk.test.lib.threaddump.ThreadDump;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class DumpThreads { class DumpThreads {
private static final boolean TRACK_ALL_THREADS; private static final boolean TRACK_ALL_THREADS;
static { static {
String s = System.getProperty("jdk.trackAllThreads"); String s = System.getProperty("jdk.trackAllThreads");
@ -61,7 +61,7 @@ public class DumpThreads {
* Thread dump in plain text format. * Thread dump in plain text format.
*/ */
@Test @Test
public void testPlainText() throws Exception { void testPlainText() throws Exception {
var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
Path file = genOutputPath("txt"); Path file = genOutputPath("txt");
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
@ -98,7 +98,7 @@ public class DumpThreads {
* Thread dump in JSON format. * Thread dump in JSON format.
*/ */
@Test @Test
public void testJson() throws Exception { void testJson() throws Exception {
var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
Path file = genOutputPath("json"); Path file = genOutputPath("json");
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
@ -118,7 +118,7 @@ public class DumpThreads {
ZonedDateTime.parse(threadDump.time()); ZonedDateTime.parse(threadDump.time());
// test threadDump/runtimeVersion // test threadDump/runtimeVersion
assertEquals(threadDump.runtimeVersion(), Runtime.version().toString()); assertEquals(Runtime.version().toString(), threadDump.runtimeVersion());
// test root container // test root container
var rootContainer = threadDump.rootThreadContainer(); var rootContainer = threadDump.rootThreadContainer();
@ -150,7 +150,7 @@ public class DumpThreads {
* Test that dumpThreads throws if the output file already exists. * Test that dumpThreads throws if the output file already exists.
*/ */
@Test @Test
public void testFileAlreadyExsists() throws Exception { void testFileAlreadyExsists() throws Exception {
var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
String file = Files.createFile(genOutputPath("txt")).toString(); String file = Files.createFile(genOutputPath("txt")).toString();
assertThrows(FileAlreadyExistsException.class, assertThrows(FileAlreadyExistsException.class,
@ -163,7 +163,7 @@ public class DumpThreads {
* Test that dumpThreads throws if the file path is relative. * Test that dumpThreads throws if the file path is relative.
*/ */
@Test @Test
public void testRelativePath() throws Exception { void testRelativePath() throws Exception {
var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> mbean.dumpThreads("threads.txt", ThreadDumpFormat.TEXT_PLAIN)); () -> mbean.dumpThreads("threads.txt", ThreadDumpFormat.TEXT_PLAIN));
@ -175,7 +175,7 @@ public class DumpThreads {
* Test that dumpThreads throws with null parameters. * Test that dumpThreads throws with null parameters.
*/ */
@Test @Test
public void testNull() throws Exception { void testNull() throws Exception {
var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); var mbean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> mbean.dumpThreads(null, ThreadDumpFormat.TEXT_PLAIN)); () -> mbean.dumpThreads(null, ThreadDumpFormat.TEXT_PLAIN));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
* @test * @test
* @summary Unit test for Thread.Builder * @summary Unit test for Thread.Builder
* @enablePreview * @enablePreview
* @run testng BuilderTest * @run junit BuilderTest
*/ */
import java.util.concurrent.*; import java.util.concurrent.*;
@ -33,17 +33,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import org.testng.SkipException; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import static org.junit.jupiter.api.Assertions.*;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assumptions.*;
public class BuilderTest { class BuilderTest {
/** /**
* Test Thread.ofPlatform to create platform threads. * Test Thread.ofPlatform to create platform threads.
*/ */
@Test @Test
public void testPlatformThread() throws Exception { void testPlatformThread() throws Exception {
Thread parent = Thread.currentThread(); Thread parent = Thread.currentThread();
Thread.Builder.OfPlatform builder = Thread.ofPlatform(); Thread.Builder.OfPlatform builder = Thread.ofPlatform();
@ -94,7 +94,7 @@ public class BuilderTest {
* Test Thread.ofVirtual to create virtual threads. * Test Thread.ofVirtual to create virtual threads.
*/ */
@Test @Test
public void testVirtualThread() throws Exception { void testVirtualThread() throws Exception {
Thread parent = Thread.currentThread(); Thread parent = Thread.currentThread();
Thread.Builder.OfVirtual builder = Thread.ofVirtual(); Thread.Builder.OfVirtual builder = Thread.ofVirtual();
@ -141,7 +141,7 @@ public class BuilderTest {
* Test Thread.Builder.name. * Test Thread.Builder.name.
*/ */
@Test @Test
public void testName1() { void testName1() {
Thread.Builder builder = Thread.ofPlatform().name("duke"); Thread.Builder builder = Thread.ofPlatform().name("duke");
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -154,7 +154,7 @@ public class BuilderTest {
} }
@Test @Test
public void testName2() { void testName2() {
Thread.Builder builder = Thread.ofVirtual().name("duke"); Thread.Builder builder = Thread.ofVirtual().name("duke");
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -167,7 +167,7 @@ public class BuilderTest {
} }
@Test @Test
public void testName3() { void testName3() {
Thread.Builder builder = Thread.ofPlatform().name("duke-", 100); Thread.Builder builder = Thread.ofPlatform().name("duke-", 100);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -189,7 +189,7 @@ public class BuilderTest {
} }
@Test @Test
public void testName4() { void testName4() {
Thread.Builder builder = Thread.ofVirtual().name("duke-", 100); Thread.Builder builder = Thread.ofVirtual().name("duke-", 100);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -214,7 +214,7 @@ public class BuilderTest {
* Test Thread.Builder.OfPlatform.group. * Test Thread.Builder.OfPlatform.group.
*/ */
@Test @Test
public void testThreadGroup1() { void testThreadGroup1() {
ThreadGroup group = new ThreadGroup("groupies"); ThreadGroup group = new ThreadGroup("groupies");
Thread.Builder builder = Thread.ofPlatform().group(group); Thread.Builder builder = Thread.ofPlatform().group(group);
@ -240,9 +240,9 @@ public class BuilderTest {
} }
@Test @Test
public void testThreadGroup2() { void testThreadGroup2() {
ThreadGroup vgroup = Thread.ofVirtual().unstarted(() -> { }).getThreadGroup(); ThreadGroup vgroup = Thread.ofVirtual().unstarted(() -> { }).getThreadGroup();
assertEquals(vgroup.getName(), "VirtualThreads"); assertEquals("VirtualThreads", vgroup.getName());
Thread thread1 = Thread.ofVirtual().unstarted(() -> { }); Thread thread1 = Thread.ofVirtual().unstarted(() -> { });
Thread thread2 = Thread.ofVirtual().start(LockSupport::park); Thread thread2 = Thread.ofVirtual().start(LockSupport::park);
@ -261,7 +261,7 @@ public class BuilderTest {
* Test Thread.Builder.OfPlatform.priority. * Test Thread.Builder.OfPlatform.priority.
*/ */
@Test @Test
public void testPriority1() { void testPriority1() {
int priority = Thread.currentThread().getPriority(); int priority = Thread.currentThread().getPriority();
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
@ -275,7 +275,7 @@ public class BuilderTest {
} }
@Test @Test
public void testPriority2() { void testPriority2() {
int priority = Thread.MIN_PRIORITY; int priority = Thread.MIN_PRIORITY;
Thread.Builder builder = Thread.ofPlatform().priority(priority); Thread.Builder builder = Thread.ofPlatform().priority(priority);
@ -289,10 +289,9 @@ public class BuilderTest {
} }
@Test @Test
public void testPriority3() { void testPriority3() {
Thread currentThread = Thread.currentThread(); Thread currentThread = Thread.currentThread();
if (currentThread.isVirtual()) assumeFalse(currentThread.isVirtual(), "Main thread is a virtual thread");
throw new SkipException("Main test is a virtual thread");
int maxPriority = currentThread.getThreadGroup().getMaxPriority(); int maxPriority = currentThread.getThreadGroup().getMaxPriority();
int priority = Math.min(maxPriority + 1, Thread.MAX_PRIORITY); int priority = Math.min(maxPriority + 1, Thread.MAX_PRIORITY);
@ -308,14 +307,14 @@ public class BuilderTest {
} }
@Test @Test
public void testPriority4() { void testPriority4() {
var builder = Thread.ofPlatform(); var builder = Thread.ofPlatform();
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> builder.priority(Thread.MIN_PRIORITY - 1)); () -> builder.priority(Thread.MIN_PRIORITY - 1));
} }
@Test @Test
public void testPriority5() { void testPriority5() {
var builder = Thread.ofPlatform(); var builder = Thread.ofPlatform();
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> builder.priority(Thread.MAX_PRIORITY + 1)); () -> builder.priority(Thread.MAX_PRIORITY + 1));
@ -325,7 +324,7 @@ public class BuilderTest {
* Test Thread.Builder.OfPlatform.daemon. * Test Thread.Builder.OfPlatform.daemon.
*/ */
@Test @Test
public void testDaemon1() { void testDaemon1() {
Thread.Builder builder = Thread.ofPlatform().daemon(false); Thread.Builder builder = Thread.ofPlatform().daemon(false);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -338,7 +337,7 @@ public class BuilderTest {
} }
@Test @Test
public void testDaemon2() { void testDaemon2() {
Thread.Builder builder = Thread.ofPlatform().daemon(true); Thread.Builder builder = Thread.ofPlatform().daemon(true);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -351,7 +350,7 @@ public class BuilderTest {
} }
@Test @Test
public void testDaemon3() { void testDaemon3() {
Thread.Builder builder = Thread.ofPlatform().daemon(); Thread.Builder builder = Thread.ofPlatform().daemon();
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -364,7 +363,7 @@ public class BuilderTest {
} }
@Test @Test
public void testDaemon4() { void testDaemon4() {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -382,7 +381,7 @@ public class BuilderTest {
* Test Thread.ofVirtual creates daemon threads. * Test Thread.ofVirtual creates daemon threads.
*/ */
@Test @Test
public void testDaemon5() { void testDaemon5() {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
@ -399,7 +398,7 @@ public class BuilderTest {
* Test Thread.Builder.OfPlatform.stackSize. * Test Thread.Builder.OfPlatform.stackSize.
*/ */
@Test @Test
public void testStackSize1() { void testStackSize1() {
Thread.Builder builder = Thread.ofPlatform().stackSize(1024*1024); Thread.Builder builder = Thread.ofPlatform().stackSize(1024*1024);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
Thread thread2 = builder.start(() -> { }); Thread thread2 = builder.start(() -> { });
@ -407,7 +406,7 @@ public class BuilderTest {
} }
@Test @Test
public void testStackSize2() { void testStackSize2() {
Thread.Builder builder = Thread.ofPlatform().stackSize(0); Thread.Builder builder = Thread.ofPlatform().stackSize(0);
Thread thread1 = builder.unstarted(() -> { }); Thread thread1 = builder.unstarted(() -> { });
Thread thread2 = builder.start(() -> { }); Thread thread2 = builder.start(() -> { });
@ -415,7 +414,7 @@ public class BuilderTest {
} }
@Test @Test
public void testStackSize3() { void testStackSize3() {
var builder = Thread.ofPlatform(); var builder = Thread.ofPlatform();
assertThrows(IllegalArgumentException.class, () -> builder.stackSize(-1)); assertThrows(IllegalArgumentException.class, () -> builder.stackSize(-1));
} }
@ -424,7 +423,7 @@ public class BuilderTest {
* Test Thread.Builder.uncaughtExceptionHandler. * Test Thread.Builder.uncaughtExceptionHandler.
*/ */
@Test @Test
public void testUncaughtExceptionHandler1() throws Exception { void testUncaughtExceptionHandler1() throws Exception {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
AtomicReference<Thread> threadRef = new AtomicReference<>(); AtomicReference<Thread> threadRef = new AtomicReference<>();
AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
@ -441,7 +440,7 @@ public class BuilderTest {
} }
@Test @Test
public void testUncaughtExceptionHandler2() throws Exception { void testUncaughtExceptionHandler2() throws Exception {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
AtomicReference<Thread> threadRef = new AtomicReference<>(); AtomicReference<Thread> threadRef = new AtomicReference<>();
AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
@ -458,7 +457,7 @@ public class BuilderTest {
} }
@Test @Test
public void testUncaughtExceptionHandler3() throws Exception { void testUncaughtExceptionHandler3() throws Exception {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
AtomicReference<Thread> threadRef = new AtomicReference<>(); AtomicReference<Thread> threadRef = new AtomicReference<>();
AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
@ -477,7 +476,7 @@ public class BuilderTest {
} }
@Test @Test
public void testUncaughtExceptionHandler4() throws Exception { void testUncaughtExceptionHandler4() throws Exception {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
AtomicReference<Thread> threadRef = new AtomicReference<>(); AtomicReference<Thread> threadRef = new AtomicReference<>();
AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
@ -563,13 +562,13 @@ public class BuilderTest {
* Test Thread.Builder creates threads that allow thread locals. * Test Thread.Builder creates threads that allow thread locals.
*/ */
@Test @Test
public void testThreadLocals1() throws Exception { void testThreadLocals1() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
testThreadLocals(builder); testThreadLocals(builder);
} }
@Test @Test
public void testThreadLocals2() throws Exception { void testThreadLocals2() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
testThreadLocals(builder); testThreadLocals(builder);
} }
@ -579,7 +578,7 @@ public class BuilderTest {
* thread locals. * thread locals.
*/ */
@Test @Test
public void testThreadLocals3() throws Exception { void testThreadLocals3() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
// disallow // disallow
@ -592,7 +591,7 @@ public class BuilderTest {
} }
@Test @Test
public void testThreadLocals4() throws Exception { void testThreadLocals4() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
// disallow // disallow
@ -646,7 +645,7 @@ public class BuilderTest {
AtomicBoolean done = new AtomicBoolean(); AtomicBoolean done = new AtomicBoolean();
Runnable task = () -> { Runnable task = () -> {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
done.set(true); done.set(true);
}; };
@ -673,7 +672,7 @@ public class BuilderTest {
* the initial values of inheritable thread locals. * the initial values of inheritable thread locals.
*/ */
@Test @Test
public void testInheritedThreadLocals1() throws Exception { void testInheritedThreadLocals1() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
testInheritedThreadLocals(builder); // default testInheritedThreadLocals(builder); // default
@ -687,7 +686,7 @@ public class BuilderTest {
} }
@Test @Test
public void testInheritedThreadLocals2() throws Exception { void testInheritedThreadLocals2() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
testInheritedThreadLocals(builder); // default testInheritedThreadLocals(builder); // default
@ -701,7 +700,7 @@ public class BuilderTest {
} }
@Test @Test
public void testInheritedThreadLocals3() throws Exception { void testInheritedThreadLocals3() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
// thread locals not allowed // thread locals not allowed
@ -721,7 +720,7 @@ public class BuilderTest {
} }
@Test @Test
public void testInheritedThreadLocals4() throws Exception { void testInheritedThreadLocals4() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
// thread locals not allowed // thread locals not allowed
@ -824,7 +823,7 @@ public class BuilderTest {
* the thread context class loader. * the thread context class loader.
*/ */
@Test @Test
public void testContextClassLoader1() throws Exception { void testContextClassLoader1() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
testInheritContextClassLoader(builder); // default testInheritContextClassLoader(builder); // default
@ -838,7 +837,7 @@ public class BuilderTest {
} }
@Test @Test
public void testContextClassLoader2() throws Exception { void testContextClassLoader2() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
testInheritContextClassLoader(builder); // default testInheritContextClassLoader(builder); // default
@ -852,7 +851,7 @@ public class BuilderTest {
} }
@Test @Test
public void testContextClassLoader3() throws Exception { void testContextClassLoader3() throws Exception {
Thread.Builder builder = Thread.ofPlatform(); Thread.Builder builder = Thread.ofPlatform();
// thread locals not allowed // thread locals not allowed
@ -872,7 +871,7 @@ public class BuilderTest {
} }
@Test @Test
public void testContextClassLoader4() throws Exception { void testContextClassLoader4() throws Exception {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
// thread locals not allowed // thread locals not allowed
@ -895,7 +894,7 @@ public class BuilderTest {
* Test NullPointerException. * Test NullPointerException.
*/ */
@Test @Test
public void testNulls1() { void testNulls1() {
Thread.Builder.OfPlatform builder = Thread.ofPlatform(); Thread.Builder.OfPlatform builder = Thread.ofPlatform();
assertThrows(NullPointerException.class, () -> builder.group(null)); assertThrows(NullPointerException.class, () -> builder.group(null));
assertThrows(NullPointerException.class, () -> builder.name(null)); assertThrows(NullPointerException.class, () -> builder.name(null));
@ -906,7 +905,7 @@ public class BuilderTest {
} }
@Test @Test
public void testNulls2() { void testNulls2() {
Thread.Builder builder = Thread.ofVirtual(); Thread.Builder builder = Thread.ofVirtual();
assertThrows(NullPointerException.class, () -> builder.name(null)); assertThrows(NullPointerException.class, () -> builder.name(null));
assertThrows(NullPointerException.class, () -> builder.name(null, 0)); assertThrows(NullPointerException.class, () -> builder.name(null, 0));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,22 +24,22 @@
/** /**
* @test * @test
* @summary Test Thread.join(Duration) * @summary Test Thread.join(Duration)
* @run testng JoinWithDuration * @run junit JoinWithDuration
*/ */
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class JoinWithDuration { class JoinWithDuration {
/** /**
* Test join on unstarted thread. * Test join on unstarted thread.
*/ */
@Test @Test
public void testJoinOnUnstartedThread() { void testJoinOnUnstartedThread() {
var thread = new Thread(() -> { }); var thread = new Thread(() -> { });
assertThrows(IllegalThreadStateException.class, assertThrows(IllegalThreadStateException.class,
() -> thread.join(Duration.ofNanos(-100))); () -> thread.join(Duration.ofNanos(-100)));
@ -53,7 +53,7 @@ public class JoinWithDuration {
* Test join on thread that does not terminate while waiting. * Test join on thread that does not terminate while waiting.
*/ */
@Test @Test
public void testJoinOnRunningThread() throws Exception { void testJoinOnRunningThread() throws Exception {
var thread = new Thread(LockSupport::park); var thread = new Thread(LockSupport::park);
thread.start(); thread.start();
try { try {
@ -76,7 +76,7 @@ public class JoinWithDuration {
* Test join on thread that terminates while waiting. * Test join on thread that terminates while waiting.
*/ */
@Test @Test
public void testJoinOnTerminatingThread() throws Exception { void testJoinOnTerminatingThread() throws Exception {
var thread = new Thread(() -> { var thread = new Thread(() -> {
try { try {
Thread.sleep(50); Thread.sleep(50);
@ -90,7 +90,7 @@ public class JoinWithDuration {
* Test join on terminated thread. * Test join on terminated thread.
*/ */
@Test @Test
public void testJoinOnTerminatedThread() throws Exception { void testJoinOnTerminatedThread() throws Exception {
var thread = new Thread(() -> { }); var thread = new Thread(() -> { });
thread.start(); thread.start();
thread.join(); thread.join();
@ -103,7 +103,7 @@ public class JoinWithDuration {
* Test invoking join with interrupt status set. * Test invoking join with interrupt status set.
*/ */
@Test @Test
public void testJoinWithInterruptStatusSet() throws Exception { void testJoinWithInterruptStatusSet() throws Exception {
var thread = new Thread(LockSupport::park); var thread = new Thread(LockSupport::park);
thread.start(); thread.start();
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@ -122,8 +122,8 @@ public class JoinWithDuration {
* Test interrupting join. * Test interrupting join.
*/ */
@Test @Test
public void testInterruptJoin() throws Exception { void testInterruptJoin() throws Exception {
// schedule current thread to interrupted after 1s // schedule current thread to be interrupted after 1s
Thread targetThread = Thread.currentThread(); Thread targetThread = Thread.currentThread();
Thread wakerThread = new Thread(() -> { Thread wakerThread = new Thread(() -> {
try { try {
@ -144,7 +144,9 @@ public class JoinWithDuration {
// interrupt status should be cleared // interrupt status should be cleared
assertFalse(thread.isInterrupted()); assertFalse(thread.isInterrupted());
} finally { } finally {
wakerThread.interrupt(); LockSupport.unpark(thread);
thread.join();
wakerThread.join();
} }
} }
@ -152,7 +154,7 @@ public class JoinWithDuration {
* Test join on current thread. * Test join on current thread.
*/ */
@Test @Test
public void testJoinSelf() throws Exception { void testJoinSelf() throws Exception {
Thread thread = Thread.currentThread(); Thread thread = Thread.currentThread();
assertFalse(thread.join(Duration.ofNanos(-100))); assertFalse(thread.join(Duration.ofNanos(-100)));
@ -169,7 +171,7 @@ public class JoinWithDuration {
* Test join(null). * Test join(null).
*/ */
@Test @Test
public void testJoinNull() throws Exception { void testJoinNull() throws Exception {
var thread = new Thread(LockSupport::park); var thread = new Thread(LockSupport::park);
// unstarted // unstarted

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,22 +24,22 @@
/** /**
* @test * @test
* @summary Test Thread.sleep(Duration) * @summary Test Thread.sleep(Duration)
* @run testng SleepWithDuration * @run junit SleepWithDuration
*/ */
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class SleepWithDuration { class SleepWithDuration {
/** /**
* Basic test for sleep(Duration). * Basic test for sleep(Duration).
*/ */
@Test @Test
public void testSleep() throws Exception { void testSleep() throws Exception {
// sleep for 2 seconds // sleep for 2 seconds
long start = millisTime(); long start = millisTime();
Thread.sleep(Duration.ofMillis(2000)); Thread.sleep(Duration.ofMillis(2000));
@ -56,7 +56,7 @@ public class SleepWithDuration {
* Test Thread.sleep with interrupt status set. * Test Thread.sleep with interrupt status set.
*/ */
@Test @Test
public void testSleepWithInterruptStatusSet() throws Exception { void testSleepWithInterruptStatusSet() throws Exception {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
Thread.sleep(Duration.ofNanos(0)); Thread.sleep(Duration.ofNanos(0));
@ -78,8 +78,8 @@ public class SleepWithDuration {
* Test interrupting Thread.sleep. * Test interrupting Thread.sleep.
*/ */
@Test @Test
public void testInterruptSleep() throws Exception { void testInterruptSleep() throws Exception {
// schedule current thread to interrupted after 1s // schedule current thread to be interrupted after 1s
Thread targetThread = Thread.currentThread(); Thread targetThread = Thread.currentThread();
Thread wakerThread = new Thread(() -> { Thread wakerThread = new Thread(() -> {
try { try {
@ -97,7 +97,7 @@ public class SleepWithDuration {
// interrupt status should be cleared // interrupt status should be cleared
assertFalse(Thread.interrupted()); assertFalse(Thread.interrupted());
} finally { } finally {
wakerThread.interrupt(); wakerThread.join();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,10 +21,14 @@
* questions. * questions.
*/ */
import java.util.stream.Stream;
import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.ProcessTools;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments;
import static java.lang.System.err; import static java.lang.System.err;
import static java.lang.System.out; import static java.lang.System.out;
@ -36,35 +40,50 @@ import static java.lang.System.out;
* @author Martin Buchholz * @author Martin Buchholz
* @library /test/lib * @library /test/lib
* @build jdk.test.lib.process.* * @build jdk.test.lib.process.*
* @run testng UncaughtExceptionsTest * @run junit UncaughtExceptionsTest
*/ */
public class UncaughtExceptionsTest { class UncaughtExceptionsTest {
@DataProvider private static Stream<Arguments> testCases() {
public Object[][] testCases() { return Stream.of(
return new Object[][] { Arguments.of("ThreadIsDeadAfterJoin",
new Object[] { "ThreadIsDeadAfterJoin", 0,
0, UncaughtExitSimulator.EXPECTED_RESULT,
UncaughtExitSimulator.EXPECTED_RESULT, "Exception in thread \"Thread-\\d+\".*simulateUncaughtExitEvent"),
"Exception in thread \"Thread-\\d+\".*simulateUncaughtExitEvent" Arguments.of("MainThreadAbruptTermination",
}, 1,
new Object[] { UncaughtExitSimulator.EXPECTED_RESULT,
"MainThreadAbruptTermination", "Exception in thread \"main\".*simulateUncaughtExitEvent"),
1, Arguments.of("MainThreadNormalTermination",
UncaughtExitSimulator.EXPECTED_RESULT, 0,
"Exception in thread \"main\".*simulateUncaughtExitEvent" UncaughtExitSimulator.EXPECTED_RESULT,
}, ""),
new Object[] { "MainThreadNormalTermination", 0, UncaughtExitSimulator.EXPECTED_RESULT, ""}, Arguments.of("DefaultUncaughtExceptionHandlerOnMainThread",
new Object[] { "DefaultUncaughtExceptionHandlerOnMainThread", 1, UncaughtExitSimulator.EXPECTED_RESULT, "" }, 1,
new Object[] { "DefaultUncaughtExceptionHandlerOnMainThreadOverride", 1, UncaughtExitSimulator.EXPECTED_RESULT, "" }, UncaughtExitSimulator.EXPECTED_RESULT,
new Object[] { "DefaultUncaughtExceptionHandlerOnNonMainThreadOverride", 0, UncaughtExitSimulator.EXPECTED_RESULT, "" }, ""),
new Object[] { "DefaultUncaughtExceptionHandlerOnNonMainThread", 0, UncaughtExitSimulator.EXPECTED_RESULT, "" }, Arguments.of("DefaultUncaughtExceptionHandlerOnMainThreadOverride",
new Object[] { "ThreadGroupUncaughtExceptionHandlerOnNonMainThread", 0, UncaughtExitSimulator.EXPECTED_RESULT, "" } 1,
}; UncaughtExitSimulator.EXPECTED_RESULT,
""),
Arguments.of("DefaultUncaughtExceptionHandlerOnNonMainThreadOverride",
0,
UncaughtExitSimulator.EXPECTED_RESULT,
""),
Arguments.of("DefaultUncaughtExceptionHandlerOnNonMainThread",
0,
UncaughtExitSimulator.EXPECTED_RESULT,
""),
Arguments.of("ThreadGroupUncaughtExceptionHandlerOnNonMainThread",
0,
UncaughtExitSimulator.EXPECTED_RESULT,
"")
);
} }
@Test(dataProvider = "testCases") @ParameterizedTest
public void test(String className, int exitValue, String stdOutMatch, String stdErrMatch) throws Throwable { @MethodSource("testCases")
void test(String className, int exitValue, String stdOutMatch, String stdErrMatch) throws Throwable {
String cmd = "UncaughtExitSimulator$" + className; String cmd = "UncaughtExitSimulator$" + className;
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd); ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd);
OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(processBuilder); OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(processBuilder);
@ -91,7 +110,9 @@ class UncaughtExitSimulator extends Thread implements Runnable {
final static String EXPECTED_RESULT = "OK"; final static String EXPECTED_RESULT = "OK";
public static void throwRuntimeException() { throw new RuntimeException("simulateUncaughtExitEvent"); } public static void throwRuntimeException() {
throw new RuntimeException("simulateUncaughtExitEvent");
}
public void run() { throwRuntimeException(); } public void run() { throwRuntimeException(); }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,22 +25,22 @@
* @test * @test
* @summary Test that virtual threads are GC'ed * @summary Test that virtual threads are GC'ed
* @enablePreview * @enablePreview
* @run testng Collectable * @run junit Collectable
*/ */
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class Collectable { class Collectable {
/** /**
* Test that an unstarted virtual thread can be GC"ed. * Test that an unstarted virtual thread can be GC"ed.
*/ */
@Test @Test
public void testUnstartedThread() { void testUnstartedThread() {
var thread = Thread.ofVirtual().unstarted(() -> { }); var thread = Thread.ofVirtual().unstarted(() -> { });
var ref = new WeakReference<>(thread); var ref = new WeakReference<>(thread);
thread = null; thread = null;
@ -51,7 +51,7 @@ public class Collectable {
* Test that a terminated virtual thread can be GC'ed. * Test that a terminated virtual thread can be GC'ed.
*/ */
@Test @Test
public void testTerminatedThread() throws Exception { void testTerminatedThread() throws Exception {
var thread = Thread.ofVirtual().start(() -> { }); var thread = Thread.ofVirtual().start(() -> { });
thread.join(); thread.join();
var ref = new WeakReference<>(thread); var ref = new WeakReference<>(thread);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @requires vm.continuations * @requires vm.continuations
* @modules java.base/java.lang:+open * @modules java.base/java.lang:+open
* @enablePreview * @enablePreview
* @run testng CustomScheduler * @run junit CustomScheduler
*/ */
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -39,57 +39,57 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import org.testng.SkipException; import org.junit.jupiter.api.Test;
import org.testng.annotations.BeforeClass; import org.junit.jupiter.api.BeforeAll;
import org.testng.annotations.AfterClass; import org.junit.jupiter.api.AfterAll;
import org.testng.annotations.Test; import static org.junit.jupiter.api.Assertions.*;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assumptions.*;
public class CustomScheduler { class CustomScheduler {
private static final Executor DEFAULT_SCHEDULER = defaultScheduler(); private static final Executor DEFAULT_SCHEDULER = defaultScheduler();
private static ExecutorService SCHEDULER_1; private static ExecutorService scheduler1;
private static ExecutorService SCHEDULER_2; private static ExecutorService scheduler2;
@BeforeClass @BeforeAll
public void setup() { static void setup() {
SCHEDULER_1 = Executors.newFixedThreadPool(1); scheduler1 = Executors.newFixedThreadPool(1);
SCHEDULER_2 = Executors.newFixedThreadPool(1); scheduler2 = Executors.newFixedThreadPool(1);
} }
@AfterClass @AfterAll
public void shutdown() { static void shutdown() {
SCHEDULER_1.shutdown(); scheduler1.shutdown();
SCHEDULER_2.shutdown(); scheduler2.shutdown();
} }
/** /**
* Test platform thread creating a virtual thread that uses a custom scheduler. * Test platform thread creating a virtual thread that uses a custom scheduler.
*/ */
@Test @Test
public void testCustomScheduler1() throws Exception { void testCustomScheduler1() throws Exception {
AtomicReference<Executor> ref = new AtomicReference<>(); AtomicReference<Executor> ref = new AtomicReference<>();
ThreadBuilders.virtualThreadBuilder(SCHEDULER_1).start(() -> { ThreadBuilders.virtualThreadBuilder(scheduler1).start(() -> {
ref.set(scheduler(Thread.currentThread())); ref.set(scheduler(Thread.currentThread()));
}).join(); }).join();
assertTrue(ref.get() == SCHEDULER_1); assertTrue(ref.get() == scheduler1);
} }
/** /**
* Test virtual thread creating a virtual thread that uses a custom scheduler. * Test virtual thread creating a virtual thread that uses a custom scheduler.
*/ */
@Test @Test
public void testCustomScheduler2() throws Exception { void testCustomScheduler2() throws Exception {
AtomicReference<Executor> ref = new AtomicReference<>(); AtomicReference<Executor> ref = new AtomicReference<>();
Thread.ofVirtual().start(() -> { Thread.ofVirtual().start(() -> {
try { try {
ThreadBuilders.virtualThreadBuilder(SCHEDULER_1).start(() -> { ThreadBuilders.virtualThreadBuilder(scheduler1).start(() -> {
ref.set(scheduler(Thread.currentThread())); ref.set(scheduler(Thread.currentThread()));
}).join(); }).join();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
}).join(); }).join();
assertTrue(ref.get() == SCHEDULER_1); assertTrue(ref.get() == scheduler1);
} }
/** /**
@ -97,9 +97,9 @@ public class CustomScheduler {
* The scheduler should be inherited. * The scheduler should be inherited.
*/ */
@Test @Test
public void testCustomScheduler3() throws Exception { void testCustomScheduler3() throws Exception {
AtomicReference<Executor> ref = new AtomicReference<>(); AtomicReference<Executor> ref = new AtomicReference<>();
ThreadBuilders.virtualThreadBuilder(SCHEDULER_1).start(() -> { ThreadBuilders.virtualThreadBuilder(scheduler1).start(() -> {
try { try {
Thread.ofVirtual().start(() -> { Thread.ofVirtual().start(() -> {
ref.set(scheduler(Thread.currentThread())); ref.set(scheduler(Thread.currentThread()));
@ -108,7 +108,7 @@ public class CustomScheduler {
e.printStackTrace(); e.printStackTrace();
} }
}).join(); }).join();
assertTrue(ref.get() == SCHEDULER_1); assertTrue(ref.get() == scheduler1);
} }
/** /**
@ -116,25 +116,25 @@ public class CustomScheduler {
* that uses a different custom scheduler. * that uses a different custom scheduler.
*/ */
@Test @Test
public void testCustomScheduler4() throws Exception { void testCustomScheduler4() throws Exception {
AtomicReference<Executor> ref = new AtomicReference<>(); AtomicReference<Executor> ref = new AtomicReference<>();
ThreadBuilders.virtualThreadBuilder(SCHEDULER_1).start(() -> { ThreadBuilders.virtualThreadBuilder(scheduler1).start(() -> {
try { try {
ThreadBuilders.virtualThreadBuilder(SCHEDULER_2).start(() -> { ThreadBuilders.virtualThreadBuilder(scheduler2).start(() -> {
ref.set(scheduler(Thread.currentThread())); ref.set(scheduler(Thread.currentThread()));
}).join(); }).join();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
}).join(); }).join();
assertTrue(ref.get() == SCHEDULER_2); assertTrue(ref.get() == scheduler2);
} }
/** /**
* Test running task on a virtual thread, should thrown WrongThreadException. * Test running task on a virtual thread, should thrown WrongThreadException.
*/ */
@Test @Test
public void testBadCarrier() { void testBadCarrier() {
Executor scheduler = (task) -> { Executor scheduler = (task) -> {
var exc = new AtomicReference<Throwable>(); var exc = new AtomicReference<Throwable>();
try { try {
@ -160,10 +160,9 @@ public class CustomScheduler {
* carrier thread when the task completes. * carrier thread when the task completes.
*/ */
@Test @Test
public void testParkWithInterruptSet() { void testParkWithInterruptSet() {
Thread carrier = Thread.currentThread(); Thread carrier = Thread.currentThread();
if (carrier.isVirtual()) assumeFalse(carrier.isVirtual(), "Main thread is a virtual thread");
throw new SkipException("Main test is a virtual thread");
try { try {
var builder = ThreadBuilders.virtualThreadBuilder(Runnable::run); var builder = ThreadBuilders.virtualThreadBuilder(Runnable::run);
Thread vthread = builder.start(() -> { Thread vthread = builder.start(() -> {
@ -182,10 +181,9 @@ public class CustomScheduler {
* the carrier thread when the task completes. * the carrier thread when the task completes.
*/ */
@Test @Test
public void testTerminateWithInterruptSet() { void testTerminateWithInterruptSet() {
Thread carrier = Thread.currentThread(); Thread carrier = Thread.currentThread();
if (carrier.isVirtual()) assumeFalse(carrier.isVirtual(), "Main thread is a virtual thread");
throw new SkipException("Main test is a virtual thread");
try { try {
var builder = ThreadBuilders.virtualThreadBuilder(Runnable::run); var builder = ThreadBuilders.virtualThreadBuilder(Runnable::run);
Thread vthread = builder.start(() -> { Thread vthread = builder.start(() -> {
@ -202,9 +200,8 @@ public class CustomScheduler {
* Test running task with the carrier interrupt status set. * Test running task with the carrier interrupt status set.
*/ */
@Test @Test
public void testRunWithInterruptSet() throws Exception { void testRunWithInterruptSet() throws Exception {
if (Thread.currentThread().isVirtual()) assumeFalse(Thread.currentThread().isVirtual(), "Main thread is a virtual thread");
throw new SkipException("Main test is a virtual thread");
Executor scheduler = (task) -> { Executor scheduler = (task) -> {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
task.run(); task.run();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,9 +25,10 @@
* @test * @test
* @summary Test Thread.getStackTrace to examine the stack trace of a virtual * @summary Test Thread.getStackTrace to examine the stack trace of a virtual
* thread and its carrier * thread and its carrier
* @modules java.base/java.lang:+open * @requires vm.continuations
* @enablePreview * @enablePreview
* @run testng GetStackTrace * @modules java.base/java.lang:+open
* @run main GetStackTrace
*/ */
import java.util.Objects; import java.util.Objects;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @requires vm.continuations * @requires vm.continuations
* @modules java.base/java.lang:+open * @modules java.base/java.lang:+open
* @enablePreview * @enablePreview
* @run testng HoldsLock * @run junit HoldsLock
*/ */
/** /**
@ -36,7 +36,7 @@
* @requires vm.continuations & vm.debug * @requires vm.continuations & vm.debug
* @modules java.base/java.lang:+open * @modules java.base/java.lang:+open
* @enablePreview * @enablePreview
* @run testng/othervm -XX:+UseHeavyMonitors HoldsLock * @run junit/othervm -XX:+UseHeavyMonitors HoldsLock
*/ */
import java.lang.management.LockInfo; import java.lang.management.LockInfo;
@ -52,15 +52,17 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import org.junit.jupiter.api.Disabled;
import static org.junit.jupiter.api.Assertions.*;
public class HoldsLock { class HoldsLock {
static final Object LOCK1 = new Object(); static final Object LOCK1 = new Object();
static final Object LOCK2 = new Object(); static final Object LOCK2 = new Object();
@Test(enabled=false) // JDK-8281642 @Disabled("JDK-8281642")
public void testHoldsLock() throws Exception { @Test
void testHoldsLock() throws Exception {
var q = new ArrayBlockingQueue<Runnable>(5); var q = new ArrayBlockingQueue<Runnable>(5);
Thread carrier = Thread.ofPlatform().start(() -> { Thread carrier = Thread.ofPlatform().start(() -> {
@ -85,7 +87,7 @@ public class HoldsLock {
} }
@Test @Test
public void testThreadInfo() throws Exception { void testThreadInfo() throws Exception {
var q = new ArrayBlockingQueue<Runnable>(5); var q = new ArrayBlockingQueue<Runnable>(5);
Thread carrier = spawnCarrier(q); Thread carrier = spawnCarrier(q);
@ -123,10 +125,10 @@ public class HoldsLock {
if (tid == carrierId) { if (tid == carrierId) {
// Carrier is WAITING on vthread // Carrier is WAITING on vthread
assertEquals(info.getThreadState(), Thread.State.WAITING); assertTrue(info.getThreadState() == Thread.State.WAITING);
assertEquals(info.getLockInfo().getClassName(), vthread.getClass().getName()); assertEquals(vthread.getClass().getName(), info.getLockInfo().getClassName());
assertEquals(info.getLockInfo().getIdentityHashCode(), System.identityHashCode(vthread)); assertTrue(info.getLockInfo().getIdentityHashCode() == System.identityHashCode(vthread));
assertEquals(info.getLockOwnerId(), vthreadId); assertTrue(info.getLockOwnerId() == vthreadId);
foundCarrier = true; foundCarrier = true;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @requires vm.continuations * @requires vm.continuations
* @modules jdk.jfr java.base/java.lang:+open * @modules jdk.jfr java.base/java.lang:+open
* @enablePreview * @enablePreview
* @run testng/othervm JfrEvents * @run junit/othervm JfrEvents
*/ */
import java.io.IOException; import java.io.IOException;
@ -48,17 +48,17 @@ import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordingFile; import jdk.jfr.consumer.RecordingFile;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class JfrEvents { class JfrEvents {
private static final Object lock = new Object(); private static final Object lock = new Object();
/** /**
* Test jdk.VirtualThreadStart and jdk.VirtualThreadEnd events. * Test jdk.VirtualThreadStart and jdk.VirtualThreadEnd events.
*/ */
@Test @Test
public void testVirtualThreadStartAndEnd() throws Exception { void testVirtualThreadStartAndEnd() throws Exception {
try (Recording recording = new Recording()) { try (Recording recording = new Recording()) {
recording.enable("jdk.VirtualThreadStart"); recording.enable("jdk.VirtualThreadStart");
recording.enable("jdk.VirtualThreadEnd"); recording.enable("jdk.VirtualThreadEnd");
@ -89,7 +89,7 @@ public class JfrEvents {
* Test jdk.VirtualThreadPinned event. * Test jdk.VirtualThreadPinned event.
*/ */
@Test @Test
public void testVirtualThreadPinned() throws Exception { void testVirtualThreadPinned() throws Exception {
try (Recording recording = new Recording()) { try (Recording recording = new Recording()) {
recording.enable("jdk.VirtualThreadPinned") recording.enable("jdk.VirtualThreadPinned")
.withThreshold(Duration.ofMillis(500)); .withThreshold(Duration.ofMillis(500));
@ -126,7 +126,7 @@ public class JfrEvents {
* Test jdk.VirtualThreadSubmitFailed event. * Test jdk.VirtualThreadSubmitFailed event.
*/ */
@Test @Test
public void testVirtualThreadSubmitFailed() throws Exception { void testVirtualThreadSubmitFailed() throws Exception {
try (Recording recording = new Recording()) { try (Recording recording = new Recording()) {
recording.enable("jdk.VirtualThreadSubmitFailed"); recording.enable("jdk.VirtualThreadSubmitFailed");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
* @summary Test virtual threads using java.util.concurrent locks * @summary Test virtual threads using java.util.concurrent locks
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng Locking * @run junit Locking
*/ */
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -34,16 +34,16 @@ import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class Locking { class Locking {
/** /**
* Test lock/unlock. * Test lock/unlock.
*/ */
@Test @Test
public void testReentrantLock1() throws Exception { void testReentrantLock1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
assertFalse(lock.isHeldByCurrentThread()); assertFalse(lock.isHeldByCurrentThread());
@ -58,7 +58,7 @@ public class Locking {
* Test tryLock/unlock. * Test tryLock/unlock.
*/ */
@Test @Test
public void testReentrantLock2() throws Exception { void testReentrantLock2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
assertFalse(lock.isHeldByCurrentThread()); assertFalse(lock.isHeldByCurrentThread());
@ -74,7 +74,7 @@ public class Locking {
* Test lock/lock/unlock/unlock. * Test lock/lock/unlock/unlock.
*/ */
@Test @Test
public void testReentrantLock3() throws Exception { void testReentrantLock3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
assertFalse(lock.isHeldByCurrentThread()); assertFalse(lock.isHeldByCurrentThread());
@ -98,7 +98,7 @@ public class Locking {
* Test locked by platform thread, virtual thread tries to lock. * Test locked by platform thread, virtual thread tries to lock.
*/ */
@Test @Test
public void testReentrantLock4() throws Exception { void testReentrantLock4() throws Exception {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
var holdsLock = new AtomicBoolean(); var holdsLock = new AtomicBoolean();
@ -136,7 +136,7 @@ public class Locking {
* Test locked by virtual thread, platform thread tries to lock. * Test locked by virtual thread, platform thread tries to lock.
*/ */
@Test @Test
public void testReentrantLock5() throws Exception { void testReentrantLock5() throws Exception {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
lock.lock(); lock.lock();
@ -170,7 +170,7 @@ public class Locking {
* Test locked by virtual thread, another virtual thread tries to lock. * Test locked by virtual thread, another virtual thread tries to lock.
*/ */
@Test @Test
public void testReentrantLock6() throws Exception { void testReentrantLock6() throws Exception {
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
var thread1 = Thread.ofVirtual().start(() -> { var thread1 = Thread.ofVirtual().start(() -> {
lock.lock(); lock.lock();

View File

@ -27,17 +27,15 @@
* @requires vm.continuations * @requires vm.continuations
* @modules java.base/java.lang:+open * @modules java.base/java.lang:+open
* @enablePreview * @enablePreview
* @run testng ParkWithFixedThreadPool * @run main ParkWithFixedThreadPool
*/ */
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
public class ParkWithFixedThreadPool { public class ParkWithFixedThreadPool {
@Test public static void main(String[] args) throws Exception {
public static void multipleThreadPoolParkTest() throws Exception {
try (ExecutorService scheduler = Executors.newFixedThreadPool(8)) { try (ExecutorService scheduler = Executors.newFixedThreadPool(8)) {
int vthreadCount = 300; int vthreadCount = 300;
Thread[] vthreads = new Thread[vthreadCount]; Thread[] vthreads = new Thread[vthreadCount];

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
* @summary Test virtual threads using park/unpark * @summary Test virtual threads using park/unpark
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng Parking * @run junit Parking
*/ */
import java.time.Duration; import java.time.Duration;
@ -34,18 +34,17 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.SkipException; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import static org.junit.jupiter.api.Assertions.*;
import static org.testng.Assert.*;
public class Parking { class Parking {
private static final Object lock = new Object(); private static final Object lock = new Object();
/** /**
* Park, unparked by platform thread. * Park, unparked by platform thread.
*/ */
@Test @Test
public void testPark1() throws Exception { void testPark1() throws Exception {
var thread = Thread.ofVirtual().start(LockSupport::park); var thread = Thread.ofVirtual().start(LockSupport::park);
Thread.sleep(1000); // give time for virtual thread to park Thread.sleep(1000); // give time for virtual thread to park
LockSupport.unpark(thread); LockSupport.unpark(thread);
@ -56,7 +55,7 @@ public class Parking {
* Park, unparked by virtual thread. * Park, unparked by virtual thread.
*/ */
@Test @Test
public void testPark2() throws Exception { void testPark2() throws Exception {
var thread1 = Thread.ofVirtual().start(LockSupport::park); var thread1 = Thread.ofVirtual().start(LockSupport::park);
Thread.sleep(1000); // give time for virtual thread to park Thread.sleep(1000); // give time for virtual thread to park
var thread2 = Thread.ofVirtual().start(() -> LockSupport.unpark(thread1)); var thread2 = Thread.ofVirtual().start(() -> LockSupport.unpark(thread1));
@ -68,7 +67,7 @@ public class Parking {
* Park while holding monitor, unparked by platform thread. * Park while holding monitor, unparked by platform thread.
*/ */
@Test @Test
public void testPark3() throws Exception { void testPark3() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
synchronized (lock) { synchronized (lock) {
LockSupport.park(); LockSupport.park();
@ -83,15 +82,15 @@ public class Parking {
* Park with native frame on stack. * Park with native frame on stack.
*/ */
@Test @Test
public void testPark4() throws Exception { void testPark4() throws Exception {
throw new SkipException("Not implemented"); // not implemented
} }
/** /**
* Unpark before park. * Unpark before park.
*/ */
@Test @Test
public void testPark5() throws Exception { void testPark5() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
LockSupport.unpark(Thread.currentThread()); LockSupport.unpark(Thread.currentThread());
LockSupport.park(); LockSupport.park();
@ -103,7 +102,7 @@ public class Parking {
* 2 x unpark before park. * 2 x unpark before park.
*/ */
@Test @Test
public void testPark6() throws Exception { void testPark6() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
Thread me = Thread.currentThread(); Thread me = Thread.currentThread();
LockSupport.unpark(me); LockSupport.unpark(me);
@ -120,7 +119,7 @@ public class Parking {
* 2 x park and unpark by platform thread. * 2 x park and unpark by platform thread.
*/ */
@Test @Test
public void testPark7() throws Exception { void testPark7() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
LockSupport.park(); LockSupport.park();
LockSupport.park(); LockSupport.park();
@ -142,7 +141,7 @@ public class Parking {
* Park with interrupt status set. * Park with interrupt status set.
*/ */
@Test @Test
public void testPark8() throws Exception { void testPark8() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
t.interrupt(); t.interrupt();
@ -155,7 +154,7 @@ public class Parking {
* Thread interrupt when parked. * Thread interrupt when parked.
*/ */
@Test @Test
public void testPark9() throws Exception { void testPark9() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
scheduleInterrupt(t, 1000); scheduleInterrupt(t, 1000);
@ -169,7 +168,7 @@ public class Parking {
* Park while holding monitor and with interrupt status set. * Park while holding monitor and with interrupt status set.
*/ */
@Test @Test
public void testPark10() throws Exception { void testPark10() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
t.interrupt(); t.interrupt();
@ -184,7 +183,7 @@ public class Parking {
* Thread interrupt when parked while holding monitor * Thread interrupt when parked while holding monitor
*/ */
@Test @Test
public void testPark11() throws Exception { void testPark11() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
scheduleInterrupt(t, 1000); scheduleInterrupt(t, 1000);
@ -200,7 +199,7 @@ public class Parking {
* parkNanos(-1) completes immediately * parkNanos(-1) completes immediately
*/ */
@Test @Test
public void testParkNanos1() throws Exception { void testParkNanos1() throws Exception {
VThreadRunner.run(() -> LockSupport.parkNanos(-1)); VThreadRunner.run(() -> LockSupport.parkNanos(-1));
} }
@ -208,7 +207,7 @@ public class Parking {
* parkNanos(0) completes immediately * parkNanos(0) completes immediately
*/ */
@Test @Test
public void testParkNanos2() throws Exception { void testParkNanos2() throws Exception {
VThreadRunner.run(() -> LockSupport.parkNanos(0)); VThreadRunner.run(() -> LockSupport.parkNanos(0));
} }
@ -216,7 +215,7 @@ public class Parking {
* parkNanos(1000ms) parks thread. * parkNanos(1000ms) parks thread.
*/ */
@Test @Test
public void testParkNanos3() throws Exception { void testParkNanos3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
// park for 1000ms // park for 1000ms
long nanos = TimeUnit.NANOSECONDS.convert(1000, TimeUnit.MILLISECONDS); long nanos = TimeUnit.NANOSECONDS.convert(1000, TimeUnit.MILLISECONDS);
@ -234,7 +233,7 @@ public class Parking {
* Park with parkNanos, unparked by platform thread. * Park with parkNanos, unparked by platform thread.
*/ */
@Test @Test
public void testParkNanos4() throws Exception { void testParkNanos4() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS); long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
LockSupport.parkNanos(nanos); LockSupport.parkNanos(nanos);
@ -248,7 +247,7 @@ public class Parking {
* Park with parkNanos, unparked by virtual thread. * Park with parkNanos, unparked by virtual thread.
*/ */
@Test @Test
public void testParkNanos5() throws Exception { void testParkNanos5() throws Exception {
var thread1 = Thread.ofVirtual().start(() -> { var thread1 = Thread.ofVirtual().start(() -> {
long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS); long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
LockSupport.parkNanos(nanos); LockSupport.parkNanos(nanos);
@ -263,7 +262,7 @@ public class Parking {
* Unpark before parkNanos. * Unpark before parkNanos.
*/ */
@Test @Test
public void testParkNanos6() throws Exception { void testParkNanos6() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
LockSupport.unpark(Thread.currentThread()); LockSupport.unpark(Thread.currentThread());
long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS); long nanos = TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
@ -275,7 +274,7 @@ public class Parking {
* Unpark before parkNanos(0), should consume parking permit. * Unpark before parkNanos(0), should consume parking permit.
*/ */
@Test @Test
public void testParkNanos7() throws Exception { void testParkNanos7() throws Exception {
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
LockSupport.unpark(Thread.currentThread()); LockSupport.unpark(Thread.currentThread());
LockSupport.parkNanos(0); // should consume parking permit LockSupport.parkNanos(0); // should consume parking permit
@ -291,7 +290,7 @@ public class Parking {
* Park with parkNanos and interrupt status set. * Park with parkNanos and interrupt status set.
*/ */
@Test @Test
public void testParkNanos8() throws Exception { void testParkNanos8() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
t.interrupt(); t.interrupt();
@ -304,7 +303,7 @@ public class Parking {
* Thread interrupt when parked in parkNanos. * Thread interrupt when parked in parkNanos.
*/ */
@Test @Test
public void testParkNanos9() throws Exception { void testParkNanos9() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
scheduleInterrupt(t, 1000); scheduleInterrupt(t, 1000);
@ -318,7 +317,7 @@ public class Parking {
* Park with parkNanos while holding monitor and with interrupt status set. * Park with parkNanos while holding monitor and with interrupt status set.
*/ */
@Test @Test
public void testParkNanos10() throws Exception { void testParkNanos10() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
t.interrupt(); t.interrupt();
@ -333,7 +332,7 @@ public class Parking {
* Thread interrupt when parked in parkNanos and while holding monitor. * Thread interrupt when parked in parkNanos and while holding monitor.
*/ */
@Test @Test
public void testParkNanos11() throws Exception { void testParkNanos11() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
scheduleInterrupt(t, 1000); scheduleInterrupt(t, 1000);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,25 +24,25 @@
/** /**
* @test * @test
* @summary Test that preview APIs throws exception when preview features not enabled * @summary Test that preview APIs throws exception when preview features not enabled
* @run testng/othervm PreviewFeaturesNotEnabled * @run junit/othervm PreviewFeaturesNotEnabled
*/ */
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class PreviewFeaturesNotEnabled { class PreviewFeaturesNotEnabled {
/** /**
* Thread.ofVirtual should fail with UOE. * Thread.ofVirtual should fail with UOE.
*/ */
@Test @Test
public void testOfVirtual() throws Exception { void testOfVirtual() throws Exception {
Method ofVirtual = Thread.class.getDeclaredMethod("ofVirtual"); Method ofVirtual = Thread.class.getDeclaredMethod("ofVirtual");
var exc = expectThrows(InvocationTargetException.class, () -> ofVirtual.invoke(null)); var exc = assertThrows(InvocationTargetException.class, () -> ofVirtual.invoke(null));
assertTrue(exc.getCause() instanceof UnsupportedOperationException); assertTrue(exc.getCause() instanceof UnsupportedOperationException);
} }
@ -50,10 +50,10 @@ public class PreviewFeaturesNotEnabled {
* Thread.startVirtualThread should fail with UOE. * Thread.startVirtualThread should fail with UOE.
*/ */
@Test @Test
public void testStartVirutalThread() throws Exception { void testStartVirutalThread() throws Exception {
Method startVirtualThread = Thread.class.getMethod("startVirtualThread", Runnable.class); Method startVirtualThread = Thread.class.getMethod("startVirtualThread", Runnable.class);
Runnable task = () -> { }; Runnable task = () -> { };
var exc = expectThrows(InvocationTargetException.class, var exc = assertThrows(InvocationTargetException.class,
() -> startVirtualThread.invoke(null, task)); () -> startVirtualThread.invoke(null, task));
assertTrue(exc.getCause() instanceof UnsupportedOperationException); assertTrue(exc.getCause() instanceof UnsupportedOperationException);
} }
@ -62,9 +62,9 @@ public class PreviewFeaturesNotEnabled {
* Executors.newVirtualThreadPerTaskExecutor should fail with UOE. * Executors.newVirtualThreadPerTaskExecutor should fail with UOE.
*/ */
@Test @Test
public void testNewVirtualThreadPerTaskExecutor() throws Exception { void testNewVirtualThreadPerTaskExecutor() throws Exception {
Method newVirtualThreadPerTaskExecutor = Executors.class.getMethod("newVirtualThreadPerTaskExecutor"); Method newVirtualThreadPerTaskExecutor = Executors.class.getMethod("newVirtualThreadPerTaskExecutor");
var exc = expectThrows(InvocationTargetException.class, var exc = assertThrows(InvocationTargetException.class,
() -> newVirtualThreadPerTaskExecutor.invoke(null)); () -> newVirtualThreadPerTaskExecutor.invoke(null));
assertTrue(exc.getCause() instanceof UnsupportedOperationException); assertTrue(exc.getCause() instanceof UnsupportedOperationException);
} }
@ -73,8 +73,8 @@ public class PreviewFeaturesNotEnabled {
* Directly accessing internal Continuation class should fail with UOE. * Directly accessing internal Continuation class should fail with UOE.
*/ */
@Test @Test
public void testContinuationInitializer() throws Exception { void testContinuationInitializer() throws Exception {
var exc = expectThrows(ExceptionInInitializerError.class, var exc = assertThrows(ExceptionInInitializerError.class,
() -> Class.forName("jdk.internal.vm.Continuation")); () -> Class.forName("jdk.internal.vm.Continuation"));
assertTrue(exc.getCause() instanceof UnsupportedOperationException); assertTrue(exc.getCause() instanceof UnsupportedOperationException);
} }
@ -83,7 +83,7 @@ public class PreviewFeaturesNotEnabled {
* Thread.isVirtual should not fail. * Thread.isVirtual should not fail.
*/ */
@Test @Test
public void testIsVirtual() throws Exception { void testIsVirtual() throws Exception {
boolean isVirtual = isVirtual(Thread.currentThread()); boolean isVirtual = isVirtual(Thread.currentThread());
assertFalse(isVirtual); assertFalse(isVirtual);
} }
@ -92,7 +92,7 @@ public class PreviewFeaturesNotEnabled {
* Thread.ofPlatform should not fail. * Thread.ofPlatform should not fail.
*/ */
@Test @Test
public void testOfPlatform() throws Exception { void testOfPlatform() throws Exception {
Method ofPlatform = Thread.class.getDeclaredMethod("ofPlatform"); Method ofPlatform = Thread.class.getDeclaredMethod("ofPlatform");
Object builder = ofPlatform.invoke(null); Object builder = ofPlatform.invoke(null);
Method startMethod = Class.forName("java.lang.Thread$Builder") Method startMethod = Class.forName("java.lang.Thread$Builder")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @modules java.base/java.lang:+open * @modules java.base/java.lang:+open
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng Reflection * @run junit Reflection
*/ */
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -39,17 +39,17 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.SkipException; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import static org.junit.jupiter.api.Assertions.*;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assumptions.*;
public class Reflection { class Reflection {
/** /**
* Test invoking static method. * Test invoking static method.
*/ */
@Test @Test
public void testInvokeStatic1() throws Exception { void testInvokeStatic1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
int result = (int) divideMethod().invoke(null, 20, 2); int result = (int) divideMethod().invoke(null, 20, 2);
assertTrue(result == 10); assertTrue(result == 10);
@ -61,7 +61,7 @@ public class Reflection {
* exception. * exception.
*/ */
@Test @Test
public void testInvokeStatic2() throws Exception { void testInvokeStatic2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try { try {
divideMethod().invoke(null, 20, 0); divideMethod().invoke(null, 20, 0);
@ -77,7 +77,7 @@ public class Reflection {
* method with bad parameters. * method with bad parameters.
*/ */
@Test @Test
public void testInvokeStatic3() throws Exception { void testInvokeStatic3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> divideMethod().invoke(null)); () -> divideMethod().invoke(null));
@ -99,7 +99,7 @@ public class Reflection {
* method triggers its class to be initialized and it fails with exception. * method triggers its class to be initialized and it fails with exception.
*/ */
@Test @Test
public void testInvokeStatic4() throws Exception { void testInvokeStatic4() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Method foo = BadClass1.class.getDeclaredMethod("foo"); Method foo = BadClass1.class.getDeclaredMethod("foo");
try { try {
@ -123,7 +123,7 @@ public class Reflection {
* class to be initialized and it fails with an error. * class to be initialized and it fails with an error.
*/ */
@Test @Test
public void testInvokeStatic5() throws Exception { void testInvokeStatic5() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Method foo = BadClass2.class.getDeclaredMethod("foo"); Method foo = BadClass2.class.getDeclaredMethod("foo");
assertThrows(AbstractMethodError.class, () -> foo.invoke(null)); assertThrows(AbstractMethodError.class, () -> foo.invoke(null));
@ -141,9 +141,8 @@ public class Reflection {
* Test that invoking a static method does not pin the carrier thread. * Test that invoking a static method does not pin the carrier thread.
*/ */
@Test @Test
public void testInvokeStatic6() throws Exception { void testInvokeStatic6() throws Exception {
if (!ThreadBuilders.supportsCustomScheduler()) assumeTrue(ThreadBuilders.supportsCustomScheduler(), "No support for custom schedulers");
throw new SkipException("No support for custom schedulers");
Method parkMethod = Parker.class.getDeclaredMethod("park"); Method parkMethod = Parker.class.getDeclaredMethod("park");
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler); Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
@ -172,7 +171,7 @@ public class Reflection {
* Test invoking instance method. * Test invoking instance method.
*/ */
@Test @Test
public void testInvokeInstance1() throws Exception { void testInvokeInstance1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var adder = new Adder(); var adder = new Adder();
Adder.addMethod().invoke(adder, 5); Adder.addMethod().invoke(adder, 5);
@ -185,7 +184,7 @@ public class Reflection {
* exception. * exception.
*/ */
@Test @Test
public void testInvokeInstance2() throws Exception { void testInvokeInstance2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var adder = new Adder(); var adder = new Adder();
try { try {
@ -202,7 +201,7 @@ public class Reflection {
* trying to invoke an instance method with null or bad parameters. * trying to invoke an instance method with null or bad parameters.
*/ */
@Test @Test
public void testInvokeInstance3() throws Exception { void testInvokeInstance3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var adder = new Adder(); var adder = new Adder();
Method addMethod = Adder.addMethod(); Method addMethod = Adder.addMethod();
@ -223,7 +222,7 @@ public class Reflection {
* Test invoking newInstance to create an object. * Test invoking newInstance to create an object.
*/ */
@Test @Test
public void testNewInstance1() throws Exception { void testNewInstance1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class); Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class);
Adder adder = (Adder) ctor.newInstance(10); Adder adder = (Adder) ctor.newInstance(10);
@ -236,7 +235,7 @@ public class Reflection {
* exception. * exception.
*/ */
@Test @Test
public void testNewInstance2() throws Exception { void testNewInstance2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class); Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class);
try { try {
@ -253,7 +252,7 @@ public class Reflection {
* with bad parameters. * with bad parameters.
*/ */
@Test @Test
public void testNewInstance3() throws Exception { void testNewInstance3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var adder = new Adder(); var adder = new Adder();
Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class); Constructor<?> ctor = Adder.class.getDeclaredConstructor(long.class);
@ -275,7 +274,7 @@ public class Reflection {
* triggers the class to be initialized and it fails with exception. * triggers the class to be initialized and it fails with exception.
*/ */
@Test @Test
public void testNewInstance4() throws Exception { void testNewInstance4() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Constructor<?> ctor = BadClass3.class.getDeclaredConstructor(); Constructor<?> ctor = BadClass3.class.getDeclaredConstructor();
try { try {
@ -299,7 +298,7 @@ public class Reflection {
* to be initialized and it fails with an error. * to be initialized and it fails with an error.
*/ */
@Test @Test
public void testNewInstance5() throws Exception { void testNewInstance5() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Constructor<?> ctor = BadClass4.class.getDeclaredConstructor(); Constructor<?> ctor = BadClass4.class.getDeclaredConstructor();
assertThrows(AbstractMethodError.class, () -> ctor.newInstance((Object[])null)); assertThrows(AbstractMethodError.class, () -> ctor.newInstance((Object[])null));
@ -317,9 +316,8 @@ public class Reflection {
* Test that newInstance does not pin the carrier thread * Test that newInstance does not pin the carrier thread
*/ */
@Test @Test
public void testNewInstance6() throws Exception { void testNewInstance6() throws Exception {
if (!ThreadBuilders.supportsCustomScheduler()) assumeTrue(ThreadBuilders.supportsCustomScheduler(), "No support for custom schedulers");
throw new SkipException("No support for custom schedulers");
Constructor<?> ctor = Parker.class.getDeclaredConstructor(); Constructor<?> ctor = Parker.class.getDeclaredConstructor();
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler); Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,8 +29,8 @@
* @modules java.management * @modules java.management
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng StackTraces * @run junit StackTraces
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowCarrierFrames StackTraces * @run junit/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowCarrierFrames StackTraces
*/ */
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
@ -40,17 +40,17 @@ import java.util.concurrent.ForkJoinPool;
import static java.lang.StackWalker.Option.*; import static java.lang.StackWalker.Option.*;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class StackTraces { class StackTraces {
/** /**
* Test that the stack trace in exceptions does not include the carrier thread * Test that the stack trace in exceptions does not include the carrier thread
* frames, except when running with -XX:+ShowCarrierFrames. * frames, except when running with -XX:+ShowCarrierFrames.
*/ */
@Test @Test
public void testStackTrace() throws Exception { void testStackTrace() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Exception e = new Exception(); Exception e = new Exception();
boolean found = Arrays.stream(e.getStackTrace()) boolean found = Arrays.stream(e.getStackTrace())
@ -64,7 +64,7 @@ public class StackTraces {
* Test that StackWalker does not include carrier thread frames. * Test that StackWalker does not include carrier thread frames.
*/ */
@Test @Test
public void testStackWalker() throws Exception { void testStackWalker() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE)); StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE));
boolean found = walker.walk(sf -> boolean found = walker.walk(sf ->

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,14 +26,14 @@
* @summary Test Virtual threads using thread locals * @summary Test Virtual threads using thread locals
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng ThreadLocals * @run junit ThreadLocals
*/ */
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class ThreadLocals { class ThreadLocals {
static final ThreadLocal<Object> LOCAL = new ThreadLocal<>(); static final ThreadLocal<Object> LOCAL = new ThreadLocal<>();
static final ThreadLocal<Object> INHERITED_LOCAL = new InheritableThreadLocal<>(); static final ThreadLocal<Object> INHERITED_LOCAL = new InheritableThreadLocal<>();
@ -41,10 +41,10 @@ public class ThreadLocals {
* Basic test of thread local set/get. * Basic test of thread local set/get.
*/ */
@Test @Test
public void testThreadLocal1() throws Exception { void testThreadLocal1() throws Exception {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
assertTrue(LOCAL.get() == null); assertNull(LOCAL.get());
Object obj = new Object(); Object obj = new Object();
LOCAL.set(obj); LOCAL.set(obj);
assertTrue(LOCAL.get() == obj); assertTrue(LOCAL.get() == obj);
@ -56,9 +56,9 @@ public class ThreadLocals {
* Test setting thread local before blocking operation. * Test setting thread local before blocking operation.
*/ */
@Test @Test
public void testThreadLocal2() throws Exception { void testThreadLocal2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
assertTrue(LOCAL.get() == null); assertNull(LOCAL.get());
Object obj = new Object(); Object obj = new Object();
LOCAL.set(obj); LOCAL.set(obj);
try { Thread.sleep(100); } catch (InterruptedException e) { } try { Thread.sleep(100); } catch (InterruptedException e) { }
@ -70,7 +70,7 @@ public class ThreadLocals {
* Test Thread that cannot set values for its copy of thread-locals. * Test Thread that cannot set values for its copy of thread-locals.
*/ */
@Test @Test
public void testThreadLocal3() throws Exception { void testThreadLocal3() throws Exception {
Object INITIAL_VALUE = new Object(); Object INITIAL_VALUE = new Object();
ThreadLocal<Object> LOCAL2 = new ThreadLocal<>() { ThreadLocal<Object> LOCAL2 = new ThreadLocal<>() {
@Override @Override
@ -88,7 +88,7 @@ public class ThreadLocals {
VThreadRunner.run(VThreadRunner.NO_THREAD_LOCALS, () -> { VThreadRunner.run(VThreadRunner.NO_THREAD_LOCALS, () -> {
assertThrows(UnsupportedOperationException.class, () -> LOCAL.set(null)); assertThrows(UnsupportedOperationException.class, () -> LOCAL.set(null));
assertThrows(UnsupportedOperationException.class, () -> LOCAL.set(new Object())); assertThrows(UnsupportedOperationException.class, () -> LOCAL.set(new Object()));
assertTrue(LOCAL.get() == null); assertNull(LOCAL.get());
LOCAL.remove(); // should not throw LOCAL.remove(); // should not throw
assertThrows(UnsupportedOperationException.class, () -> LOCAL2.set(null)); assertThrows(UnsupportedOperationException.class, () -> LOCAL2.set(null));
@ -98,7 +98,7 @@ public class ThreadLocals {
assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL.set(null)); assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL.set(null));
assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL.set(new Object())); assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL.set(new Object()));
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
INHERITED_LOCAL.remove(); // should not throw INHERITED_LOCAL.remove(); // should not throw
assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL2.set(null)); assertThrows(UnsupportedOperationException.class, () -> INHERITED_LOCAL2.set(null));
@ -112,25 +112,25 @@ public class ThreadLocals {
* Basic test of inheritable thread local set/get, no initial value inherited. * Basic test of inheritable thread local set/get, no initial value inherited.
*/ */
@Test @Test
public void testInheritedThreadLocal1() throws Exception { void testInheritedThreadLocal1() throws Exception {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
Object obj = new Object(); Object obj = new Object();
INHERITED_LOCAL.set(obj); INHERITED_LOCAL.set(obj);
assertTrue(INHERITED_LOCAL.get() == obj); assertTrue(INHERITED_LOCAL.get() == obj);
}); });
} }
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
} }
/** /**
* Test inheriting initial value of InheritableThreadLocal from platform thread. * Test inheriting initial value of InheritableThreadLocal from platform thread.
*/ */
@Test @Test
public void testInheritedThreadLocal2() throws Exception { void testInheritedThreadLocal2() throws Exception {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
var obj = new Object(); var obj = new Object();
INHERITED_LOCAL.set(obj); INHERITED_LOCAL.set(obj);
try { try {
@ -146,8 +146,8 @@ public class ThreadLocals {
* Test inheriting initial value of InheritableThreadLocal from virtual thread. * Test inheriting initial value of InheritableThreadLocal from virtual thread.
*/ */
@Test @Test
public void testInheritedThreadLocal3() throws Exception { void testInheritedThreadLocal3() throws Exception {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var obj = new Object(); var obj = new Object();
INHERITED_LOCAL.set(obj); INHERITED_LOCAL.set(obj);
@ -157,7 +157,7 @@ public class ThreadLocals {
assertTrue(INHERITED_LOCAL.get() == obj); assertTrue(INHERITED_LOCAL.get() == obj);
}); });
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
} }
/** /**
@ -165,14 +165,14 @@ public class ThreadLocals {
* from platform thread. * from platform thread.
*/ */
@Test @Test
public void testInheritedThreadLocal4() throws Exception { void testInheritedThreadLocal4() throws Exception {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
var obj = new Object(); var obj = new Object();
INHERITED_LOCAL.set(obj); INHERITED_LOCAL.set(obj);
try { try {
int characteristics = VThreadRunner.NO_INHERIT_THREAD_LOCALS; int characteristics = VThreadRunner.NO_INHERIT_THREAD_LOCALS;
VThreadRunner.run(characteristics, () -> { VThreadRunner.run(characteristics, () -> {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
}); });
} finally { } finally {
INHERITED_LOCAL.remove(); INHERITED_LOCAL.remove();
@ -184,18 +184,18 @@ public class ThreadLocals {
* from virtual thread. * from virtual thread.
*/ */
@Test @Test
public void testInheritedThreadLocal5() throws Exception { void testInheritedThreadLocal5() throws Exception {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
var obj = new Object(); var obj = new Object();
INHERITED_LOCAL.set(obj); INHERITED_LOCAL.set(obj);
int characteristics = VThreadRunner.NO_INHERIT_THREAD_LOCALS; int characteristics = VThreadRunner.NO_INHERIT_THREAD_LOCALS;
VThreadRunner.run(characteristics, () -> { VThreadRunner.run(characteristics, () -> {
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
}); });
assertTrue(INHERITED_LOCAL.get() == obj); assertTrue(INHERITED_LOCAL.get() == obj);
}); });
assertTrue(INHERITED_LOCAL.get() == null); assertNull(INHERITED_LOCAL.get());
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,8 +28,8 @@
* @requires vm.continuations * @requires vm.continuations
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm -Djdk.tracePinnedThreads=full TracePinnedThreads * @run junit/othervm -Djdk.tracePinnedThreads=full TracePinnedThreads
* @run testng/othervm -Djdk.tracePinnedThreads=short TracePinnedThreads * @run junit/othervm -Djdk.tracePinnedThreads=short TracePinnedThreads
*/ */
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -38,10 +38,10 @@ import java.time.Duration;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class TracePinnedThreads { class TracePinnedThreads {
static final Object lock = new Object(); static final Object lock = new Object();
/** /**
@ -62,7 +62,7 @@ public class TracePinnedThreads {
* Test parking inside synchronized block. * Test parking inside synchronized block.
*/ */
@Test @Test
public void testPinnedCausedBySynchronizedBlock() throws Exception { void testPinnedCausedBySynchronizedBlock() throws Exception {
String output = run(() -> { String output = run(() -> {
synchronized (lock) { synchronized (lock) {
park(); park();
@ -76,7 +76,7 @@ public class TracePinnedThreads {
* Test parking with native frame on stack. * Test parking with native frame on stack.
*/ */
@Test @Test
public void testPinnedCausedByNativeMethod() throws Exception { void testPinnedCausedByNativeMethod() throws Exception {
System.loadLibrary("TracePinnedThreads"); System.loadLibrary("TracePinnedThreads");
String output = run(() -> invokePark()); String output = run(() -> invokePark());
assertContains(output, "(Native Method)"); assertContains(output, "(Native Method)");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,22 +26,22 @@
* @summary Test virtual threads using Object.wait/notifyAll * @summary Test virtual threads using Object.wait/notifyAll
* @library /test/lib * @library /test/lib
* @enablePreview * @enablePreview
* @run testng WaitNotify * @run junit WaitNotify
*/ */
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class WaitNotify { class WaitNotify {
/** /**
* Test virtual thread waits, notified by platform thread. * Test virtual thread waits, notified by platform thread.
*/ */
@Test @Test
public void testWaitNotify1() throws Exception { void testWaitNotify1() throws Exception {
var lock = new Object(); var lock = new Object();
var ready = new Semaphore(0); var ready = new Semaphore(0);
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
@ -64,7 +64,7 @@ public class WaitNotify {
* Test platform thread waits, notified by virtual thread. * Test platform thread waits, notified by virtual thread.
*/ */
@Test @Test
public void testWaitNotify2() throws Exception { void testWaitNotify2() throws Exception {
var lock = new Object(); var lock = new Object();
var ready = new Semaphore(0); var ready = new Semaphore(0);
var thread = Thread.ofVirtual().start(() -> { var thread = Thread.ofVirtual().start(() -> {
@ -84,7 +84,7 @@ public class WaitNotify {
* Test virtual thread waits, notified by another virtual thread. * Test virtual thread waits, notified by another virtual thread.
*/ */
@Test @Test
public void testWaitNotify3() throws Exception { void testWaitNotify3() throws Exception {
var lock = new Object(); var lock = new Object();
var ready = new Semaphore(0); var ready = new Semaphore(0);
var thread1 = Thread.ofVirtual().start(() -> { var thread1 = Thread.ofVirtual().start(() -> {
@ -109,7 +109,7 @@ public class WaitNotify {
* Test interrupt status set when calling Object.wait. * Test interrupt status set when calling Object.wait.
*/ */
@Test @Test
public void testWaitNotify4() throws Exception { void testWaitNotify4() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
t.interrupt(); t.interrupt();
@ -130,7 +130,7 @@ public class WaitNotify {
* Test interrupt when blocked in Object.wait. * Test interrupt when blocked in Object.wait.
*/ */
@Test @Test
public void testWaitNotify5() throws Exception { void testWaitNotify5() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
scheduleInterrupt(t, 1000); scheduleInterrupt(t, 1000);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/** /**
* @test * @test
* @summary Unit tests for java.lang.ThreadGroup * @summary Unit tests for java.lang.ThreadGroup
* @run testng BasicTests * @run junit BasicTests
*/ */
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -34,25 +34,25 @@ import java.util.Set;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class BasicTests { class BasicTests {
@Test @Test
public void testGetName1() { void testGetName1() {
ThreadGroup group = new ThreadGroup(null); ThreadGroup group = new ThreadGroup(null);
assertTrue(group.getName() == null); assertTrue(group.getName() == null);
} }
@Test @Test
public void testGetName2() { void testGetName2() {
ThreadGroup group = new ThreadGroup("fred"); ThreadGroup group = new ThreadGroup("fred");
assertEquals(group.getName(), "fred"); assertEquals("fred", group.getName());
} }
@Test @Test
public void testGetParent() { void testGetParent() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
ThreadGroup group3 = new ThreadGroup(group2, "group3"); ThreadGroup group3 = new ThreadGroup(group2, "group3");
@ -63,7 +63,7 @@ public class BasicTests {
} }
@Test @Test
public void testParentOf() { void testParentOf() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
ThreadGroup group3 = new ThreadGroup(group2, "group3"); ThreadGroup group3 = new ThreadGroup(group2, "group3");
@ -85,7 +85,7 @@ public class BasicTests {
} }
@Test @Test
public void testActiveCount1() { void testActiveCount1() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertTrue(group.activeCount() == 0); assertTrue(group.activeCount() == 0);
TestThread thread = TestThread.start(group, "foo"); TestThread thread = TestThread.start(group, "foo");
@ -98,7 +98,7 @@ public class BasicTests {
} }
@Test @Test
public void testActiveCount2() { void testActiveCount2() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
assertTrue(group1.activeCount() == 0); assertTrue(group1.activeCount() == 0);
@ -124,7 +124,7 @@ public class BasicTests {
} }
@Test @Test
public void enumerateThreads1() { void enumerateThreads1() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
Thread[] threads = new Thread[100]; Thread[] threads = new Thread[100];
assertTrue(group.enumerate(threads) == 0); assertTrue(group.enumerate(threads) == 0);
@ -156,7 +156,7 @@ public class BasicTests {
} }
@Test @Test
public void enumerateThreads2() { void enumerateThreads2() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
@ -203,12 +203,12 @@ public class BasicTests {
try { try {
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group1.enumerate(threads) == 2); assertTrue(group1.enumerate(threads) == 2);
assertEquals(toSet(threads, 2), Set.of(thread1, thread2)); assertEquals(Set.of(thread1, thread2), toSet(threads, 2));
assertTrue(threads[2] == null); assertTrue(threads[2] == null);
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group1.enumerate(threads, true) == 2); assertTrue(group1.enumerate(threads, true) == 2);
assertEquals(toSet(threads, 2), Set.of(thread1, thread2)); assertEquals(Set.of(thread1, thread2), toSet(threads, 2));
assertTrue(threads[2] == null); assertTrue(threads[2] == null);
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
@ -261,7 +261,7 @@ public class BasicTests {
} }
@Test @Test
public void enumerateThreads3() { void enumerateThreads3() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
ThreadGroup group3 = new ThreadGroup(group2, "group3"); ThreadGroup group3 = new ThreadGroup(group2, "group3");
@ -304,20 +304,20 @@ public class BasicTests {
try { try {
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group1.enumerate(threads) == 2); assertTrue(group1.enumerate(threads) == 2);
assertEquals(toSet(threads, 2), Set.of(thread2, thread3)); assertEquals(Set.of(thread2, thread3), toSet(threads, 2));
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group1.enumerate(threads, true) == 2); assertTrue(group1.enumerate(threads, true) == 2);
assertEquals(toSet(threads, 2), Set.of(thread2, thread3)); assertEquals(Set.of(thread2, thread3), toSet(threads, 2));
assertTrue(group1.enumerate(threads, false) == 0); assertTrue(group1.enumerate(threads, false) == 0);
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group2.enumerate(threads) == 2); assertTrue(group2.enumerate(threads) == 2);
assertEquals(toSet(threads, 2), Set.of(thread2, thread3)); assertEquals(Set.of(thread2, thread3), toSet(threads, 2));
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group2.enumerate(threads, true) == 2); assertTrue(group2.enumerate(threads, true) == 2);
assertEquals(toSet(threads, 2), Set.of(thread2, thread3)); assertEquals(Set.of(thread2, thread3), toSet(threads, 2));
Arrays.setAll(threads, i -> null); Arrays.setAll(threads, i -> null);
assertTrue(group2.enumerate(threads, false) == 1); assertTrue(group2.enumerate(threads, false) == 1);
@ -391,7 +391,7 @@ public class BasicTests {
* Test enumerate(Thread[]) with an array of insufficient size * Test enumerate(Thread[]) with an array of insufficient size
*/ */
@Test @Test
public void enumerateThreads4() { void enumerateThreads4() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
// array too small // array too small
@ -418,7 +418,7 @@ public class BasicTests {
} }
@Test @Test
public void testActiveGroupCount() throws Exception { void testActiveGroupCount() throws Exception {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
assertTrue(group1.activeGroupCount() == 0); assertTrue(group1.activeGroupCount() == 0);
@ -444,7 +444,7 @@ public class BasicTests {
} }
@Test @Test
public void testEnumerateGroups1() throws Exception { void testEnumerateGroups1() throws Exception {
ThreadGroup[] groups = new ThreadGroup[100]; ThreadGroup[] groups = new ThreadGroup[100];
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
@ -477,12 +477,12 @@ public class BasicTests {
Arrays.setAll(groups, i -> null); Arrays.setAll(groups, i -> null);
assertTrue(group1.enumerate(groups) == 2); assertTrue(group1.enumerate(groups) == 2);
assertEquals(toSet(groups, 2), Set.of(group2, group3)); assertEquals(Set.of(group2, group3), toSet(groups, 2));
assertTrue(groups[2] == null); assertTrue(groups[2] == null);
Arrays.setAll(groups, i -> null); Arrays.setAll(groups, i -> null);
assertTrue(group1.enumerate(groups, true) == 2); assertTrue(group1.enumerate(groups, true) == 2);
assertEquals(toSet(groups, 2), Set.of(group2, group3)); assertEquals(Set.of(group2, group3), toSet(groups, 2));
assertTrue(groups[2] == null); assertTrue(groups[2] == null);
Arrays.setAll(groups, i -> null); Arrays.setAll(groups, i -> null);
@ -546,7 +546,7 @@ public class BasicTests {
* Test enumerate(ThreadGroup[]) with an array of insufficient size * Test enumerate(ThreadGroup[]) with an array of insufficient size
*/ */
@Test @Test
public void testEnumerateGroups2() throws Exception { void testEnumerateGroups2() throws Exception {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
ThreadGroup child1 = new ThreadGroup(group, "child1"); ThreadGroup child1 = new ThreadGroup(group, "child1");
ThreadGroup child2 = new ThreadGroup(group,"child2"); ThreadGroup child2 = new ThreadGroup(group,"child2");
@ -568,7 +568,7 @@ public class BasicTests {
} }
@Test @Test
public void testMaxPriority1() { void testMaxPriority1() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
final int maxPriority = group.getMaxPriority(); final int maxPriority = group.getMaxPriority();
assertTrue(maxPriority == Thread.currentThread().getThreadGroup().getMaxPriority()); assertTrue(maxPriority == Thread.currentThread().getThreadGroup().getMaxPriority());
@ -592,7 +592,7 @@ public class BasicTests {
} }
@Test @Test
public void testMaxPriority2() { void testMaxPriority2() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
int maxPriority = group1.getMaxPriority(); int maxPriority = group1.getMaxPriority();
if (maxPriority > Thread.MIN_PRIORITY) { if (maxPriority > Thread.MIN_PRIORITY) {
@ -630,7 +630,7 @@ public class BasicTests {
} }
@Test @Test
public void testMaxPriority3() { void testMaxPriority3() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
if (group.getMaxPriority() > Thread.MIN_PRIORITY) { if (group.getMaxPriority() > Thread.MIN_PRIORITY) {
int maxPriority = Thread.MIN_PRIORITY + 1; int maxPriority = Thread.MIN_PRIORITY + 1;
@ -656,7 +656,7 @@ public class BasicTests {
} }
@Test @Test
public void testInterrupt1() { void testInterrupt1() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertTrue(group.activeCount() == 0); assertTrue(group.activeCount() == 0);
TestThread thread = TestThread.start(group, "foo"); TestThread thread = TestThread.start(group, "foo");
@ -669,7 +669,7 @@ public class BasicTests {
} }
@Test @Test
public void testInterrupt2() { void testInterrupt2() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
TestThread thread1 = TestThread.start(group1, "foo"); TestThread thread1 = TestThread.start(group1, "foo");
@ -685,7 +685,7 @@ public class BasicTests {
} }
@Test @Test
public void testInterrupt3() { void testInterrupt3() {
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
ThreadGroup group2 = new ThreadGroup(group1, "group2"); ThreadGroup group2 = new ThreadGroup(group1, "group2");
TestThread thread1 = TestThread.start(group1, "foo"); TestThread thread1 = TestThread.start(group1, "foo");
@ -701,7 +701,7 @@ public class BasicTests {
} }
@Test @Test
public void testDestroy() { void testDestroy() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertFalse(group.isDestroyed()); assertFalse(group.isDestroyed());
group.destroy(); // does nothing group.destroy(); // does nothing
@ -709,7 +709,7 @@ public class BasicTests {
} }
@Test @Test
public void testDaemon() { void testDaemon() {
boolean d = Thread.currentThread().getThreadGroup().isDaemon(); boolean d = Thread.currentThread().getThreadGroup().isDaemon();
ThreadGroup group1 = new ThreadGroup("group1"); ThreadGroup group1 = new ThreadGroup("group1");
@ -727,68 +727,68 @@ public class BasicTests {
} }
@Test @Test
public void testList() { void testList() {
ThreadGroup group = new ThreadGroup("foo"); ThreadGroup group = new ThreadGroup("foo");
group.list(); group.list();
} }
@Test @Test
public void testSuspend() { void testSuspend() {
ThreadGroup group = new ThreadGroup("foo"); ThreadGroup group = new ThreadGroup("foo");
assertThrows(UnsupportedOperationException.class, () -> group.suspend()); assertThrows(UnsupportedOperationException.class, () -> group.suspend());
} }
@Test @Test
public void testResume() { void testResume() {
ThreadGroup group = new ThreadGroup("foo"); ThreadGroup group = new ThreadGroup("foo");
assertThrows(UnsupportedOperationException.class, () -> group.resume()); assertThrows(UnsupportedOperationException.class, () -> group.resume());
} }
@Test @Test
public void testStop() { void testStop() {
ThreadGroup group = new ThreadGroup("foo"); ThreadGroup group = new ThreadGroup("foo");
assertThrows(UnsupportedOperationException.class, () -> group.stop()); assertThrows(UnsupportedOperationException.class, () -> group.stop());
} }
@Test @Test
public void testNull1() { void testNull1() {
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> new ThreadGroup(null, "group")); () -> new ThreadGroup(null, "group"));
} }
@Test @Test
public void testNull2() { void testNull2() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> group.enumerate((Thread[]) null)); () -> group.enumerate((Thread[]) null));
} }
@Test @Test
public void testNull3() { void testNull3() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> group.enumerate((Thread[]) null, false)); () -> group.enumerate((Thread[]) null, false));
} }
@Test @Test
public void testNull4() { void testNull4() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> group.enumerate((ThreadGroup[]) null)); () -> group.enumerate((ThreadGroup[]) null));
} }
@Test @Test
public void testNull5() { void testNull5() {
ThreadGroup group = new ThreadGroup("group"); ThreadGroup group = new ThreadGroup("group");
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> group.enumerate((ThreadGroup[]) null, false)); () -> group.enumerate((ThreadGroup[]) null, false));
} }
private <T> Set<T> toSet(T[] array, int len) { private static <T> Set<T> toSet(T[] array, int len) {
return Arrays.stream(array, 0, len).collect(Collectors.toSet()); return Arrays.stream(array, 0, len).collect(Collectors.toSet());
} }
static class TestThread extends Thread { private static class TestThread extends Thread {
TestThread(ThreadGroup group, String name) { TestThread(ThreadGroup group, String name) {
super(group, name); super(group, name);
} }
@ -802,6 +802,7 @@ public class BasicTests {
private volatile boolean done; private volatile boolean done;
private volatile boolean interrupted; private volatile boolean interrupted;
@Override
public void run() { public void run() {
if (Thread.currentThread() != this) if (Thread.currentThread() != this)
throw new IllegalCallerException(); throw new IllegalCallerException();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @summary Test java.lang.management.ThreadMXBean with virtual threads * @summary Test java.lang.management.ThreadMXBean with virtual threads
* @enablePreview * @enablePreview
* @modules java.base/java.lang:+open java.management * @modules java.base/java.lang:+open java.management
* @run testng/othervm VirtualThreads * @run junit/othervm VirtualThreads
*/ */
/** /**
@ -35,7 +35,7 @@
* @requires vm.continuations * @requires vm.continuations
* @enablePreview * @enablePreview
* @modules java.base/java.lang:+open java.management * @modules java.base/java.lang:+open java.management
* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreads * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreads
*/ */
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
@ -51,9 +51,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import org.testng.SkipException; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import static org.junit.jupiter.api.Assertions.*;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assumptions.*;
public class VirtualThreads { public class VirtualThreads {
@ -62,7 +62,7 @@ public class VirtualThreads {
* virtual threads. * virtual threads.
*/ */
@Test @Test
public void testGetAllThreadIds() throws Exception { void testGetAllThreadIds() throws Exception {
Thread vthread = Thread.startVirtualThread(LockSupport::park); Thread vthread = Thread.startVirtualThread(LockSupport::park);
try { try {
long[] tids = ManagementFactory.getThreadMXBean().getAllThreadIds(); long[] tids = ManagementFactory.getThreadMXBean().getAllThreadIds();
@ -83,7 +83,7 @@ public class VirtualThreads {
* Test that ThreadMXBean.getThreadInfo(long) returns null for a virtual thread. * Test that ThreadMXBean.getThreadInfo(long) returns null for a virtual thread.
*/ */
@Test @Test
public void testGetThreadInfo1() throws Exception { void testGetThreadInfo1() throws Exception {
Thread vthread = Thread.startVirtualThread(LockSupport::park); Thread vthread = Thread.startVirtualThread(LockSupport::park);
try { try {
long tid = vthread.threadId(); long tid = vthread.threadId();
@ -99,7 +99,7 @@ public class VirtualThreads {
* thread with its own thread id. * thread with its own thread id.
*/ */
@Test @Test
public void testGetThreadInfo2() throws Exception { void testGetThreadInfo2() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
long tid = Thread.currentThread().threadId(); long tid = Thread.currentThread().threadId();
ThreadInfo info = ManagementFactory.getThreadMXBean().getThreadInfo(tid); ThreadInfo info = ManagementFactory.getThreadMXBean().getThreadInfo(tid);
@ -112,9 +112,8 @@ public class VirtualThreads {
* The stack frames of the virtual thread should not be returned. * The stack frames of the virtual thread should not be returned.
*/ */
@Test @Test
public void testGetThreadInfo3() throws Exception { void testGetThreadInfo3() throws Exception {
if (!supportsCustomScheduler()) assumeTrue(supportsCustomScheduler(), "No support for custom schedulers");
throw new SkipException("No support for custom schedulers");
try (ExecutorService pool = Executors.newFixedThreadPool(1)) { try (ExecutorService pool = Executors.newFixedThreadPool(1)) {
var carrierRef = new AtomicReference<Thread>(); var carrierRef = new AtomicReference<Thread>();
Executor scheduler = (task) -> { Executor scheduler = (task) -> {
@ -157,7 +156,7 @@ public class VirtualThreads {
* elements that correspond to a virtual thread. * elements that correspond to a virtual thread.
*/ */
@Test @Test
public void testGetThreadInfo4() throws Exception { void testGetThreadInfo4() throws Exception {
Thread vthread = Thread.startVirtualThread(LockSupport::park); Thread vthread = Thread.startVirtualThread(LockSupport::park);
try { try {
long tid0 = Thread.currentThread().threadId(); long tid0 = Thread.currentThread().threadId();
@ -175,7 +174,7 @@ public class VirtualThreads {
* Test that ThreadMXBean.getThreadCpuTime(long) returns -1 for a virtual thread. * Test that ThreadMXBean.getThreadCpuTime(long) returns -1 for a virtual thread.
*/ */
@Test @Test
public void testGetThreadCpuTime1() { void testGetThreadCpuTime1() {
Thread vthread = Thread.startVirtualThread(LockSupport::park); Thread vthread = Thread.startVirtualThread(LockSupport::park);
try { try {
long tid = vthread.threadId(); long tid = vthread.threadId();
@ -191,7 +190,7 @@ public class VirtualThreads {
* virtual thread with its own thread id. * virtual thread with its own thread id.
*/ */
@Test @Test
public void testGetThreadCpuTime2() throws Exception { void testGetThreadCpuTime2() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
long tid = Thread.currentThread().threadId(); long tid = Thread.currentThread().threadId();
long cpuTime = ManagementFactory.getThreadMXBean().getThreadCpuTime(tid); long cpuTime = ManagementFactory.getThreadMXBean().getThreadCpuTime(tid);
@ -203,7 +202,7 @@ public class VirtualThreads {
* Test that ThreadMXBean.getThreadUserTime(long) returns -1 for a virtual thread. * Test that ThreadMXBean.getThreadUserTime(long) returns -1 for a virtual thread.
*/ */
@Test @Test
public void testGetThreadUserTime1() { void testGetThreadUserTime1() {
Thread vthread = Thread.startVirtualThread(LockSupport::park); Thread vthread = Thread.startVirtualThread(LockSupport::park);
try { try {
long tid = vthread.threadId(); long tid = vthread.threadId();
@ -219,7 +218,7 @@ public class VirtualThreads {
* virtual thread with its own thread id. * virtual thread with its own thread id.
*/ */
@Test @Test
public void testGetThreadUserTime2() throws Exception { void testGetThreadUserTime2() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
long tid = Thread.currentThread().threadId(); long tid = Thread.currentThread().threadId();
long userTime = ManagementFactory.getThreadMXBean().getThreadUserTime(tid); long userTime = ManagementFactory.getThreadMXBean().getThreadUserTime(tid);
@ -231,10 +230,11 @@ public class VirtualThreads {
* Test that ThreadMXBean::getCurrentThreadCpuTime throws UOE when invoked * Test that ThreadMXBean::getCurrentThreadCpuTime throws UOE when invoked
* on a virtual thread. * on a virtual thread.
*/ */
@Test(expectedExceptions = { UnsupportedOperationException.class }) @Test
public void testGetCurrentThreadCpuTime() throws Exception { void testGetCurrentThreadCpuTime() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime(); assertThrows(UnsupportedOperationException.class,
() -> ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime());
}); });
} }
@ -242,10 +242,11 @@ public class VirtualThreads {
* Test that ThreadMXBean::getCurrentThreadUserTime throws UOE when * Test that ThreadMXBean::getCurrentThreadUserTime throws UOE when
* invoked on a virtual thread. * invoked on a virtual thread.
*/ */
@Test(expectedExceptions = { UnsupportedOperationException.class }) @Test
public void testGetCurrentThreadUserTime() throws Exception { void testGetCurrentThreadUserTime() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
ManagementFactory.getThreadMXBean().getCurrentThreadUserTime(); assertThrows(UnsupportedOperationException.class,
() -> ManagementFactory.getThreadMXBean().getCurrentThreadUserTime());
}); });
} }
@ -254,7 +255,7 @@ public class VirtualThreads {
* invoked on a virtual thread. * invoked on a virtual thread.
*/ */
@Test @Test
public void testGetCurrentThreadAllocatedBytes() throws Exception { void testGetCurrentThreadAllocatedBytes() throws Exception {
runInVirtualThread(() -> { runInVirtualThread(() -> {
long allocated = ManagementFactory.getPlatformMXBean(com.sun.management.ThreadMXBean.class) long allocated = ManagementFactory.getPlatformMXBean(com.sun.management.ThreadMXBean.class)
.getCurrentThreadAllocatedBytes(); .getCurrentThreadAllocatedBytes();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @summary Test virtual threads doing blocking I/O on java.net sockets * @summary Test virtual threads doing blocking I/O on java.net sockets
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm BlockingSocketOps * @run junit BlockingSocketOps
*/ */
/** /**
@ -36,7 +36,7 @@
* the I/O poller configured to use direct registration * the I/O poller configured to use direct registration
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm -Djdk.useDirectRegister BlockingSocketOps * @run junit/othervm -Djdk.useDirectRegister BlockingSocketOps
*/ */
/** /**
@ -44,7 +44,7 @@
* @requires vm.continuations * @requires vm.continuations
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingSocketOps * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingSocketOps
*/ */
import java.io.Closeable; import java.io.Closeable;
@ -62,16 +62,16 @@ import java.net.SocketException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class BlockingSocketOps { class BlockingSocketOps {
/** /**
* Socket read/write, no blocking. * Socket read/write, no blocking.
*/ */
@Test @Test
public void testSocketReadWrite1() throws Exception { void testSocketReadWrite1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s1 = connection.socket1(); Socket s1 = connection.socket1();
@ -94,7 +94,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in read. * Virtual thread blocks in read.
*/ */
@Test @Test
public void testSocketRead1() throws Exception { void testSocketRead1() throws Exception {
testSocketRead(0); testSocketRead(0);
} }
@ -102,7 +102,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in timed read. * Virtual thread blocks in timed read.
*/ */
@Test @Test
public void testSocketRead2() throws Exception { void testSocketRead2() throws Exception {
testSocketRead(60_000); testSocketRead(60_000);
} }
@ -132,7 +132,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in write. * Virtual thread blocks in write.
*/ */
@Test @Test
public void testSocketWrite1() throws Exception { void testSocketWrite1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s1 = connection.socket1(); Socket s1 = connection.socket1();
@ -161,7 +161,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in read, peer closes connection gracefully. * Virtual thread blocks in read, peer closes connection gracefully.
*/ */
@Test @Test
public void testSocketReadPeerClose1() throws Exception { void testSocketReadPeerClose1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s1 = connection.socket1(); Socket s1 = connection.socket1();
@ -181,7 +181,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in read, peer closes connection abruptly. * Virtual thread blocks in read, peer closes connection abruptly.
*/ */
@Test @Test
public void testSocketReadPeerClose2() throws Exception { void testSocketReadPeerClose2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s1 = connection.socket1(); Socket s1 = connection.socket1();
@ -206,7 +206,7 @@ public class BlockingSocketOps {
* Socket close while virtual thread blocked in read. * Socket close while virtual thread blocked in read.
*/ */
@Test @Test
public void testSocketReadAsyncClose1() throws Exception { void testSocketReadAsyncClose1() throws Exception {
testSocketReadAsyncClose(0); testSocketReadAsyncClose(0);
} }
@ -214,7 +214,7 @@ public class BlockingSocketOps {
* Socket close while virtual thread blocked in timed read. * Socket close while virtual thread blocked in timed read.
*/ */
@Test @Test
public void testSocketReadAsyncClose2() throws Exception { void testSocketReadAsyncClose2() throws Exception {
testSocketReadAsyncClose(0); testSocketReadAsyncClose(0);
} }
@ -242,7 +242,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in Socket read. * Virtual thread interrupted while blocked in Socket read.
*/ */
@Test @Test
public void testSocketReadInterrupt1() throws Exception { void testSocketReadInterrupt1() throws Exception {
testSocketReadInterrupt(0); testSocketReadInterrupt(0);
} }
@ -250,7 +250,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in Socket read with timeout * Virtual thread interrupted while blocked in Socket read with timeout
*/ */
@Test @Test
public void testSocketReadInterrupt2() throws Exception { void testSocketReadInterrupt2() throws Exception {
testSocketReadInterrupt(60_000); testSocketReadInterrupt(60_000);
} }
@ -283,7 +283,7 @@ public class BlockingSocketOps {
* Socket close while virtual thread blocked in write. * Socket close while virtual thread blocked in write.
*/ */
@Test @Test
public void testSocketWriteAsyncClose() throws Exception { void testSocketWriteAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s = connection.socket1(); Socket s = connection.socket1();
@ -307,7 +307,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in Socket write. * Virtual thread interrupted while blocked in Socket write.
*/ */
@Test @Test
public void testSocketWriteInterrupt() throws Exception { void testSocketWriteInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s = connection.socket1(); Socket s = connection.socket1();
@ -335,7 +335,7 @@ public class BlockingSocketOps {
* Virtual thread reading urgent data when SO_OOBINLINE is enabled. * Virtual thread reading urgent data when SO_OOBINLINE is enabled.
*/ */
@Test @Test
public void testSocketReadUrgentData() throws Exception { void testSocketReadUrgentData() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
Socket s1 = connection.socket1(); Socket s1 = connection.socket1();
@ -367,7 +367,7 @@ public class BlockingSocketOps {
* ServerSocket accept, no blocking. * ServerSocket accept, no blocking.
*/ */
@Test @Test
public void testServerSocketAccept1() throws Exception { void testServerSocketAccept1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var listener = new ServerSocket()) { try (var listener = new ServerSocket()) {
InetAddress loopback = InetAddress.getLoopbackAddress(); InetAddress loopback = InetAddress.getLoopbackAddress();
@ -388,7 +388,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in accept. * Virtual thread blocks in accept.
*/ */
@Test @Test
public void testServerSocketAccept2() throws Exception { void testServerSocketAccept2() throws Exception {
testServerSocketAccept(0); testServerSocketAccept(0);
} }
@ -396,7 +396,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in timed accept. * Virtual thread blocks in timed accept.
*/ */
@Test @Test
public void testServerSocketAccept3() throws Exception { void testServerSocketAccept3() throws Exception {
testServerSocketAccept(60_000); testServerSocketAccept(60_000);
} }
@ -426,7 +426,7 @@ public class BlockingSocketOps {
* ServerSocket close while virtual thread blocked in accept. * ServerSocket close while virtual thread blocked in accept.
*/ */
@Test @Test
public void testServerSocketAcceptAsyncClose1() throws Exception { void testServerSocketAcceptAsyncClose1() throws Exception {
testServerSocketAcceptAsyncClose(0); testServerSocketAcceptAsyncClose(0);
} }
@ -434,7 +434,7 @@ public class BlockingSocketOps {
* ServerSocket close while virtual thread blocked in timed accept. * ServerSocket close while virtual thread blocked in timed accept.
*/ */
@Test @Test
public void testServerSocketAcceptAsyncClose2() throws Exception { void testServerSocketAcceptAsyncClose2() throws Exception {
testServerSocketAcceptAsyncClose(60_000); testServerSocketAcceptAsyncClose(60_000);
} }
@ -463,7 +463,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in ServerSocket accept. * Virtual thread interrupted while blocked in ServerSocket accept.
*/ */
@Test @Test
public void testServerSocketAcceptInterrupt1() throws Exception { void testServerSocketAcceptInterrupt1() throws Exception {
testServerSocketAcceptInterrupt(0); testServerSocketAcceptInterrupt(0);
} }
@ -471,7 +471,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in ServerSocket accept with timeout. * Virtual thread interrupted while blocked in ServerSocket accept with timeout.
*/ */
@Test @Test
public void testServerSocketAcceptInterrupt2() throws Exception { void testServerSocketAcceptInterrupt2() throws Exception {
testServerSocketAcceptInterrupt(60_000); testServerSocketAcceptInterrupt(60_000);
} }
@ -504,7 +504,7 @@ public class BlockingSocketOps {
* DatagramSocket receive/send, no blocking. * DatagramSocket receive/send, no blocking.
*/ */
@Test @Test
public void testDatagramSocketSendReceive1() throws Exception { void testDatagramSocketSendReceive1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramSocket s1 = new DatagramSocket(null); try (DatagramSocket s1 = new DatagramSocket(null);
DatagramSocket s2 = new DatagramSocket(null)) { DatagramSocket s2 = new DatagramSocket(null)) {
@ -523,7 +523,7 @@ public class BlockingSocketOps {
byte[] ba = new byte[100]; byte[] ba = new byte[100];
DatagramPacket p2 = new DatagramPacket(ba, ba.length); DatagramPacket p2 = new DatagramPacket(ba, ba.length);
s2.receive(p2); s2.receive(p2);
assertEquals(p2.getSocketAddress(), s1.getLocalSocketAddress()); assertEquals(s1.getLocalSocketAddress(), p2.getSocketAddress());
assertTrue(ba[0] == 'X'); assertTrue(ba[0] == 'X');
} }
}); });
@ -533,7 +533,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in DatagramSocket receive. * Virtual thread blocks in DatagramSocket receive.
*/ */
@Test @Test
public void testDatagramSocketSendReceive2() throws Exception { void testDatagramSocketSendReceive2() throws Exception {
testDatagramSocketSendReceive(0); testDatagramSocketSendReceive(0);
} }
@ -541,7 +541,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in DatagramSocket receive with timeout. * Virtual thread blocks in DatagramSocket receive with timeout.
*/ */
@Test @Test
public void testDatagramSocketSendReceive3() throws Exception { void testDatagramSocketSendReceive3() throws Exception {
testDatagramSocketSendReceive(60_000); testDatagramSocketSendReceive(60_000);
} }
@ -567,7 +567,7 @@ public class BlockingSocketOps {
byte[] ba = new byte[100]; byte[] ba = new byte[100];
DatagramPacket p2 = new DatagramPacket(ba, ba.length); DatagramPacket p2 = new DatagramPacket(ba, ba.length);
s2.receive(p2); s2.receive(p2);
assertEquals(p2.getSocketAddress(), s1.getLocalSocketAddress()); assertEquals(s1.getLocalSocketAddress(), p2.getSocketAddress());
assertTrue(ba[0] == 'X'); assertTrue(ba[0] == 'X');
} }
}); });
@ -577,7 +577,7 @@ public class BlockingSocketOps {
* Virtual thread blocks in DatagramSocket receive that times out. * Virtual thread blocks in DatagramSocket receive that times out.
*/ */
@Test @Test
public void testDatagramSocketReceiveTimeout() throws Exception { void testDatagramSocketReceiveTimeout() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramSocket s = new DatagramSocket(null)) { try (DatagramSocket s = new DatagramSocket(null)) {
InetAddress lh = InetAddress.getLoopbackAddress(); InetAddress lh = InetAddress.getLoopbackAddress();
@ -597,7 +597,7 @@ public class BlockingSocketOps {
* DatagramSocket close while virtual thread blocked in receive. * DatagramSocket close while virtual thread blocked in receive.
*/ */
@Test @Test
public void testDatagramSocketReceiveAsyncClose1() throws Exception { void testDatagramSocketReceiveAsyncClose1() throws Exception {
testDatagramSocketReceiveAsyncClose(0); testDatagramSocketReceiveAsyncClose(0);
} }
@ -605,7 +605,7 @@ public class BlockingSocketOps {
* DatagramSocket close while virtual thread blocked with timeout. * DatagramSocket close while virtual thread blocked with timeout.
*/ */
@Test @Test
public void testDatagramSocketReceiveAsyncClose2() throws Exception { void testDatagramSocketReceiveAsyncClose2() throws Exception {
testDatagramSocketReceiveAsyncClose(60_000); testDatagramSocketReceiveAsyncClose(60_000);
} }
@ -636,7 +636,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in DatagramSocket receive. * Virtual thread interrupted while blocked in DatagramSocket receive.
*/ */
@Test @Test
public void testDatagramSocketReceiveInterrupt1() throws Exception { void testDatagramSocketReceiveInterrupt1() throws Exception {
testDatagramSocketReceiveInterrupt(0); testDatagramSocketReceiveInterrupt(0);
} }
@ -644,7 +644,7 @@ public class BlockingSocketOps {
* Virtual thread interrupted while blocked in DatagramSocket receive with timeout. * Virtual thread interrupted while blocked in DatagramSocket receive with timeout.
*/ */
@Test @Test
public void testDatagramSocketReceiveInterrupt2() throws Exception { void testDatagramSocketReceiveInterrupt2() throws Exception {
testDatagramSocketReceiveInterrupt(60_000); testDatagramSocketReceiveInterrupt(60_000);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
* @summary Test virtual threads doing blocking I/O on NIO channels * @summary Test virtual threads doing blocking I/O on NIO channels
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm BlockingChannelOps * @run junit BlockingChannelOps
*/ */
/** /**
@ -36,7 +36,7 @@
* the I/O poller configured to use direct registration * the I/O poller configured to use direct registration
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm -Djdk.useDirectRegister BlockingChannelOps * @run junit/othervm -Djdk.useDirectRegister BlockingChannelOps
*/ */
/** /**
@ -44,7 +44,7 @@
* @requires vm.continuations * @requires vm.continuations
* @enablePreview * @enablePreview
* @library /test/lib * @library /test/lib
* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingChannelOps * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingChannelOps
*/ */
import java.io.Closeable; import java.io.Closeable;
@ -67,16 +67,16 @@ import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel; import java.nio.channels.WritableByteChannel;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class BlockingChannelOps { class BlockingChannelOps {
/** /**
* SocketChannel read/write, no blocking. * SocketChannel read/write, no blocking.
*/ */
@Test @Test
public void testSocketChannelReadWrite1() throws Exception { void testSocketChannelReadWrite1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
SocketChannel sc1 = connection.channel1(); SocketChannel sc1 = connection.channel1();
@ -100,7 +100,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in SocketChannel read. * Virtual thread blocks in SocketChannel read.
*/ */
@Test @Test
public void testSocketChannelRead() throws Exception { void testSocketChannelRead() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
SocketChannel sc1 = connection.channel1(); SocketChannel sc1 = connection.channel1();
@ -123,7 +123,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in SocketChannel write. * Virtual thread blocks in SocketChannel write.
*/ */
@Test @Test
public void testSocketChannelWrite() throws Exception { void testSocketChannelWrite() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
SocketChannel sc1 = connection.channel1(); SocketChannel sc1 = connection.channel1();
@ -151,7 +151,7 @@ public class BlockingChannelOps {
* SocketChannel close while virtual thread blocked in read. * SocketChannel close while virtual thread blocked in read.
*/ */
@Test @Test
public void testSocketChannelReadAsyncClose() throws Exception { void testSocketChannelReadAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
SocketChannel sc = connection.channel1(); SocketChannel sc = connection.channel1();
@ -168,7 +168,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in SocketChannel read. * Virtual thread interrupted while blocked in SocketChannel read.
*/ */
@Test @Test
public void testSocketChannelReadInterrupt() throws Exception { void testSocketChannelReadInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var connection = new Connection()) { try (var connection = new Connection()) {
SocketChannel sc = connection.channel1(); SocketChannel sc = connection.channel1();
@ -191,7 +191,7 @@ public class BlockingChannelOps {
* SocketChannel close while virtual thread blocked in write. * SocketChannel close while virtual thread blocked in write.
*/ */
@Test @Test
public void testSocketChannelWriteAsyncClose() throws Exception { void testSocketChannelWriteAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
boolean retry = true; boolean retry = true;
while (retry) { while (retry) {
@ -222,7 +222,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in SocketChannel write. * Virtual thread interrupted while blocked in SocketChannel write.
*/ */
@Test @Test
public void testSocketChannelWriteInterrupt() throws Exception { void testSocketChannelWriteInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
boolean retry = true; boolean retry = true;
while (retry) { while (retry) {
@ -256,7 +256,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in SocketChannel adaptor read. * Virtual thread blocks in SocketChannel adaptor read.
*/ */
@Test @Test
public void testSocketAdaptorRead1() throws Exception { void testSocketAdaptorRead1() throws Exception {
testSocketAdaptorRead(0); testSocketAdaptorRead(0);
} }
@ -264,7 +264,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in SocketChannel adaptor read with timeout. * Virtual thread blocks in SocketChannel adaptor read with timeout.
*/ */
@Test @Test
public void testSocketAdaptorRead2() throws Exception { void testSocketAdaptorRead2() throws Exception {
testSocketAdaptorRead(60_000); testSocketAdaptorRead(60_000);
} }
@ -293,7 +293,7 @@ public class BlockingChannelOps {
* ServerSocketChannel accept, no blocking. * ServerSocketChannel accept, no blocking.
*/ */
@Test @Test
public void testServerSocketChannelAccept1() throws Exception { void testServerSocketChannelAccept1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var ssc = ServerSocketChannel.open()) { try (var ssc = ServerSocketChannel.open()) {
ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
@ -310,7 +310,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in ServerSocketChannel accept. * Virtual thread blocks in ServerSocketChannel accept.
*/ */
@Test @Test
public void testServerSocketChannelAccept2() throws Exception { void testServerSocketChannelAccept2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var ssc = ServerSocketChannel.open()) { try (var ssc = ServerSocketChannel.open()) {
ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
@ -331,7 +331,7 @@ public class BlockingChannelOps {
* SeverSocketChannel close while virtual thread blocked in accept. * SeverSocketChannel close while virtual thread blocked in accept.
*/ */
@Test @Test
public void testServerSocketChannelAcceptAsyncClose() throws Exception { void testServerSocketChannelAcceptAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var ssc = ServerSocketChannel.open()) { try (var ssc = ServerSocketChannel.open()) {
InetAddress lh = InetAddress.getLoopbackAddress(); InetAddress lh = InetAddress.getLoopbackAddress();
@ -350,7 +350,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in ServerSocketChannel accept. * Virtual thread interrupted while blocked in ServerSocketChannel accept.
*/ */
@Test @Test
public void testServerSocketChannelAcceptInterrupt() throws Exception { void testServerSocketChannelAcceptInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (var ssc = ServerSocketChannel.open()) { try (var ssc = ServerSocketChannel.open()) {
InetAddress lh = InetAddress.getLoopbackAddress(); InetAddress lh = InetAddress.getLoopbackAddress();
@ -375,7 +375,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in ServerSocketChannel adaptor accept. * Virtual thread blocks in ServerSocketChannel adaptor accept.
*/ */
@Test @Test
public void testSocketChannelAdaptorAccept1() throws Exception { void testSocketChannelAdaptorAccept1() throws Exception {
testSocketChannelAdaptorAccept(0); testSocketChannelAdaptorAccept(0);
} }
@ -383,7 +383,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in ServerSocketChannel adaptor accept with timeout. * Virtual thread blocks in ServerSocketChannel adaptor accept with timeout.
*/ */
@Test @Test
public void testSocketChannelAdaptorAccept2() throws Exception { void testSocketChannelAdaptorAccept2() throws Exception {
testSocketChannelAdaptorAccept(60_000); testSocketChannelAdaptorAccept(60_000);
} }
@ -410,7 +410,7 @@ public class BlockingChannelOps {
* DatagramChannel receive/send, no blocking. * DatagramChannel receive/send, no blocking.
*/ */
@Test @Test
public void testDatagramChannelSendReceive1() throws Exception { void testDatagramChannelSendReceive1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramChannel dc1 = DatagramChannel.open(); try (DatagramChannel dc1 = DatagramChannel.open();
DatagramChannel dc2 = DatagramChannel.open()) { DatagramChannel dc2 = DatagramChannel.open()) {
@ -435,7 +435,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in DatagramChannel receive. * Virtual thread blocks in DatagramChannel receive.
*/ */
@Test @Test
public void testDatagramChannelSendReceive2() throws Exception { void testDatagramChannelSendReceive2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramChannel dc1 = DatagramChannel.open(); try (DatagramChannel dc1 = DatagramChannel.open();
DatagramChannel dc2 = DatagramChannel.open()) { DatagramChannel dc2 = DatagramChannel.open()) {
@ -459,7 +459,7 @@ public class BlockingChannelOps {
* DatagramChannel close while virtual thread blocked in receive. * DatagramChannel close while virtual thread blocked in receive.
*/ */
@Test @Test
public void testDatagramChannelReceiveAsyncClose() throws Exception { void testDatagramChannelReceiveAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramChannel dc = DatagramChannel.open()) { try (DatagramChannel dc = DatagramChannel.open()) {
InetAddress lh = InetAddress.getLoopbackAddress(); InetAddress lh = InetAddress.getLoopbackAddress();
@ -477,7 +477,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in DatagramChannel receive. * Virtual thread interrupted while blocked in DatagramChannel receive.
*/ */
@Test @Test
public void testDatagramChannelReceiveInterrupt() throws Exception { void testDatagramChannelReceiveInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
try (DatagramChannel dc = DatagramChannel.open()) { try (DatagramChannel dc = DatagramChannel.open()) {
InetAddress lh = InetAddress.getLoopbackAddress(); InetAddress lh = InetAddress.getLoopbackAddress();
@ -501,7 +501,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in DatagramSocket adaptor receive. * Virtual thread blocks in DatagramSocket adaptor receive.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceive1() throws Exception { void testDatagramSocketAdaptorReceive1() throws Exception {
testDatagramSocketAdaptorReceive(0); testDatagramSocketAdaptorReceive(0);
} }
@ -509,7 +509,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in DatagramSocket adaptor receive with timeout. * Virtual thread blocks in DatagramSocket adaptor receive with timeout.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceive2() throws Exception { void testDatagramSocketAdaptorReceive2() throws Exception {
testDatagramSocketAdaptorReceive(60_1000); testDatagramSocketAdaptorReceive(60_1000);
} }
@ -540,7 +540,7 @@ public class BlockingChannelOps {
* DatagramChannel close while virtual thread blocked in adaptor receive. * DatagramChannel close while virtual thread blocked in adaptor receive.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceiveAsyncClose1() throws Exception { void testDatagramSocketAdaptorReceiveAsyncClose1() throws Exception {
testDatagramSocketAdaptorReceiveAsyncClose(0); testDatagramSocketAdaptorReceiveAsyncClose(0);
} }
@ -549,7 +549,7 @@ public class BlockingChannelOps {
* with timeout. * with timeout.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceiveAsyncClose2() throws Exception { void testDatagramSocketAdaptorReceiveAsyncClose2() throws Exception {
testDatagramSocketAdaptorReceiveAsyncClose(60_1000); testDatagramSocketAdaptorReceiveAsyncClose(60_1000);
} }
@ -576,7 +576,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in DatagramSocket adaptor receive. * Virtual thread interrupted while blocked in DatagramSocket adaptor receive.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceiveInterrupt1() throws Exception { void testDatagramSocketAdaptorReceiveInterrupt1() throws Exception {
testDatagramSocketAdaptorReceiveInterrupt(0); testDatagramSocketAdaptorReceiveInterrupt(0);
} }
@ -585,7 +585,7 @@ public class BlockingChannelOps {
* with timeout. * with timeout.
*/ */
@Test @Test
public void testDatagramSocketAdaptorReceiveInterrupt2() throws Exception { void testDatagramSocketAdaptorReceiveInterrupt2() throws Exception {
testDatagramSocketAdaptorReceiveInterrupt(60_1000); testDatagramSocketAdaptorReceiveInterrupt(60_1000);
} }
@ -618,7 +618,7 @@ public class BlockingChannelOps {
* Pipe read/write, no blocking. * Pipe read/write, no blocking.
*/ */
@Test @Test
public void testPipeReadWrite1() throws Exception { void testPipeReadWrite1() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Pipe p = Pipe.open(); Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink(); try (Pipe.SinkChannel sink = p.sink();
@ -642,7 +642,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in Pipe.SourceChannel read. * Virtual thread blocks in Pipe.SourceChannel read.
*/ */
@Test @Test
public void testPipeReadWrite2() throws Exception { void testPipeReadWrite2() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Pipe p = Pipe.open(); Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink(); try (Pipe.SinkChannel sink = p.sink();
@ -665,7 +665,7 @@ public class BlockingChannelOps {
* Virtual thread blocks in Pipe.SinkChannel write. * Virtual thread blocks in Pipe.SinkChannel write.
*/ */
@Test @Test
public void testPipeReadWrite3() throws Exception { void testPipeReadWrite3() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Pipe p = Pipe.open(); Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink(); try (Pipe.SinkChannel sink = p.sink();
@ -693,7 +693,7 @@ public class BlockingChannelOps {
* Pipe.SourceChannel close while virtual thread blocked in read. * Pipe.SourceChannel close while virtual thread blocked in read.
*/ */
@Test @Test
public void testPipeReadAsyncClose() throws Exception { void testPipeReadAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Pipe p = Pipe.open(); Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink(); try (Pipe.SinkChannel sink = p.sink();
@ -711,7 +711,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in Pipe.SourceChannel read. * Virtual thread interrupted while blocked in Pipe.SourceChannel read.
*/ */
@Test @Test
public void testPipeReadInterrupt() throws Exception { void testPipeReadInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
Pipe p = Pipe.open(); Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink(); try (Pipe.SinkChannel sink = p.sink();
@ -735,7 +735,7 @@ public class BlockingChannelOps {
* Pipe.SinkChannel close while virtual thread blocked in write. * Pipe.SinkChannel close while virtual thread blocked in write.
*/ */
@Test @Test
public void testPipeWriteAsyncClose() throws Exception { void testPipeWriteAsyncClose() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
boolean retry = true; boolean retry = true;
while (retry) { while (retry) {
@ -767,7 +767,7 @@ public class BlockingChannelOps {
* Virtual thread interrupted while blocked in Pipe.SinkChannel write. * Virtual thread interrupted while blocked in Pipe.SinkChannel write.
*/ */
@Test @Test
public void testPipeWriteInterrupt() throws Exception { void testPipeWriteInterrupt() throws Exception {
VThreadRunner.run(() -> { VThreadRunner.run(() -> {
boolean retry = true; boolean retry = true;
while (retry) { while (retry) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,13 @@
* @test id=platform * @test id=platform
* @summary Basic tests for new thread-per-task executors * @summary Basic tests for new thread-per-task executors
* @enablePreview * @enablePreview
* @run testng/othervm -DthreadFactory=platform ThreadPerTaskExecutorTest * @run junit/othervm -DthreadFactory=platform ThreadPerTaskExecutorTest
*/ */
/* /*
* @test id=virtual * @test id=virtual
* @enablePreview * @enablePreview
* @run testng/othervm -DthreadFactory=virtual ThreadPerTaskExecutorTest * @run junit/othervm -DthreadFactory=virtual ThreadPerTaskExecutorTest
*/ */
import java.time.Duration; import java.time.Duration;
@ -45,32 +45,29 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.concurrent.Future.State.*; import static java.util.concurrent.Future.State.*;
import org.testng.annotations.AfterClass; import org.junit.jupiter.api.Test;
import org.testng.annotations.BeforeClass; import org.junit.jupiter.api.BeforeAll;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.AfterAll;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import static org.testng.Assert.*; import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
public class ThreadPerTaskExecutorTest { class ThreadPerTaskExecutorTest {
// long running interruptible task // long running interruptible task
private static final Callable<Void> SLEEP_FOR_A_DAY = () -> { private static final Callable<Void> SLEEP_FOR_A_DAY = () -> {
Thread.sleep(Duration.ofDays(1)); Thread.sleep(Duration.ofDays(1));
return null; return null;
}; };
private ScheduledExecutorService scheduler; private static ScheduledExecutorService scheduler;
private Object[][] threadFactories; private static List<ThreadFactory> threadFactories;
@BeforeClass @BeforeAll
public void setUp() throws Exception { static void setup() throws Exception {
ThreadFactory factory = (task) -> { scheduler = Executors.newSingleThreadScheduledExecutor();
Thread thread = new Thread(task);
thread.setDaemon(true);
return thread;
};
this.scheduler = Executors.newSingleThreadScheduledExecutor(factory);
// thread factories // thread factories
String value = System.getProperty("threadFactory"); String value = System.getProperty("threadFactory");
@ -80,27 +77,21 @@ public class ThreadPerTaskExecutorTest {
if (value == null || value.equals("virtual")) if (value == null || value.equals("virtual"))
list.add(Thread.ofVirtual().factory()); list.add(Thread.ofVirtual().factory());
assertTrue(list.size() > 0, "No thread factories for tests"); assertTrue(list.size() > 0, "No thread factories for tests");
this.threadFactories = list.stream() threadFactories = list;
.map(f -> new Object[] { f })
.toArray(Object[][]::new);
} }
@AfterClass @AfterAll
public void tearDown() { static void shutdown() {
scheduler.shutdown(); scheduler.shutdown();
} }
@DataProvider(name = "factories") private static Stream<ThreadFactory> factories() {
public Object[][] factories() { return threadFactories.stream();
return threadFactories;
} }
@DataProvider(name = "executors") private static Stream<ExecutorService> executors() {
public Object[][] executors() { return threadFactories.stream()
return Arrays.stream(threadFactories) .map(f -> Executors.newThreadPerTaskExecutor(f));
.map(f -> Executors.newThreadPerTaskExecutor((ThreadFactory) f[0]))
.map(e -> new Object[] { e })
.toArray(Object[][]::new);
} }
/** /**
@ -114,8 +105,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test that a thread is created for each task. * Test that a thread is created for each task.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testThreadPerTask(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testThreadPerTask(ThreadFactory factory) throws Exception {
final int NUM_TASKS = 100; final int NUM_TASKS = 100;
AtomicInteger threadCount = new AtomicInteger(); AtomicInteger threadCount = new AtomicInteger();
@ -135,7 +127,7 @@ public class ThreadPerTaskExecutorTest {
} }
assertTrue(executor.isTerminated()); assertTrue(executor.isTerminated());
assertEquals(threadCount.get(), NUM_TASKS); assertEquals(NUM_TASKS, threadCount.get());
for (int i=0; i<NUM_TASKS; i++) { for (int i=0; i<NUM_TASKS; i++) {
Future<Integer> future = futures.get(i); Future<Integer> future = futures.get(i);
assertEquals((int) future.get(), i); assertEquals((int) future.get(), i);
@ -146,7 +138,7 @@ public class ThreadPerTaskExecutorTest {
* Test that newThreadPerTaskExecutor uses the specified thread factory. * Test that newThreadPerTaskExecutor uses the specified thread factory.
*/ */
@Test @Test
public void testThreadFactory() throws Exception { void testThreadFactory() throws Exception {
var ref1 = new AtomicReference<Thread>(); var ref1 = new AtomicReference<Thread>();
var ref2 = new AtomicReference<Thread>(); var ref2 = new AtomicReference<Thread>();
ThreadFactory factory = task -> { ThreadFactory factory = task -> {
@ -166,8 +158,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test shutdown. * Test shutdown.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testShutdown(ExecutorService executor) throws Exception { @MethodSource("executors")
void testShutdown(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
assertFalse(executor.isShutdown()); assertFalse(executor.isShutdown());
assertFalse(executor.isTerminated()); assertFalse(executor.isTerminated());
@ -188,8 +181,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test shutdownNow. * Test shutdownNow.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testShutdownNow(ExecutorService executor) throws Exception { @MethodSource("executors")
void testShutdownNow(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
assertFalse(executor.isShutdown()); assertFalse(executor.isShutdown());
assertFalse(executor.isTerminated()); assertFalse(executor.isTerminated());
@ -201,7 +195,7 @@ public class ThreadPerTaskExecutorTest {
assertTrue(executor.isShutdown()); assertTrue(executor.isShutdown());
assertTrue(tasks.isEmpty()); assertTrue(tasks.isEmpty());
Throwable e = expectThrows(ExecutionException.class, result::get); Throwable e = assertThrows(ExecutionException.class, result::get);
assertTrue(e.getCause() instanceof InterruptedException); assertTrue(e.getCause() instanceof InterruptedException);
assertTrue(executor.awaitTermination(3, TimeUnit.SECONDS)); assertTrue(executor.awaitTermination(3, TimeUnit.SECONDS));
@ -215,8 +209,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test close with no threads running. * Test close with no threads running.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testClose1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testClose1(ExecutorService executor) throws Exception {
executor.close(); executor.close();
assertTrue(executor.isShutdown()); assertTrue(executor.isShutdown());
assertTrue(executor.isTerminated()); assertTrue(executor.isTerminated());
@ -226,8 +221,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test close with threads running. * Test close with threads running.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testClose2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testClose2(ExecutorService executor) throws Exception {
Future<String> future; Future<String> future;
try (executor) { try (executor) {
future = executor.submit(() -> { future = executor.submit(() -> {
@ -244,8 +240,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Invoke close with interrupt status set, should cancel task. * Invoke close with interrupt status set, should cancel task.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testClose3(ExecutorService executor) throws Exception { @MethodSource("executors")
void testClose3(ExecutorService executor) throws Exception {
Future<?> future; Future<?> future;
try (executor) { try (executor) {
future = executor.submit(SLEEP_FOR_A_DAY); future = executor.submit(SLEEP_FOR_A_DAY);
@ -257,14 +254,15 @@ public class ThreadPerTaskExecutorTest {
assertTrue(executor.isShutdown()); assertTrue(executor.isShutdown());
assertTrue(executor.isTerminated()); assertTrue(executor.isTerminated());
assertTrue(executor.awaitTermination(10, TimeUnit.MILLISECONDS)); assertTrue(executor.awaitTermination(10, TimeUnit.MILLISECONDS));
expectThrows(ExecutionException.class, future::get); assertThrows(ExecutionException.class, future::get);
} }
/** /**
* Interrupt thread blocked in close. * Interrupt thread blocked in close.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testClose4(ExecutorService executor) throws Exception { @MethodSource("executors")
void testClose4(ExecutorService executor) throws Exception {
Future<?> future; Future<?> future;
try (executor) { try (executor) {
future = executor.submit(SLEEP_FOR_A_DAY); future = executor.submit(SLEEP_FOR_A_DAY);
@ -275,14 +273,15 @@ public class ThreadPerTaskExecutorTest {
assertTrue(executor.isShutdown()); assertTrue(executor.isShutdown());
assertTrue(executor.isTerminated()); assertTrue(executor.isTerminated());
assertTrue(executor.awaitTermination(10, TimeUnit.MILLISECONDS)); assertTrue(executor.awaitTermination(10, TimeUnit.MILLISECONDS));
expectThrows(ExecutionException.class, future::get); assertThrows(ExecutionException.class, future::get);
} }
/** /**
* Close executor that is already closed. * Close executor that is already closed.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testClose5(ExecutorService executor) throws Exception { @MethodSource("executors")
void testClose5(ExecutorService executor) throws Exception {
executor.close(); executor.close();
executor.close(); // already closed executor.close(); // already closed
} }
@ -290,8 +289,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test awaitTermination when not shutdown. * Test awaitTermination when not shutdown.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testAwaitTermination1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testAwaitTermination1(ExecutorService executor) throws Exception {
assertFalse(executor.awaitTermination(100, TimeUnit.MILLISECONDS)); assertFalse(executor.awaitTermination(100, TimeUnit.MILLISECONDS));
executor.close(); executor.close();
assertTrue(executor.awaitTermination(100, TimeUnit.MILLISECONDS)); assertTrue(executor.awaitTermination(100, TimeUnit.MILLISECONDS));
@ -300,8 +300,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test awaitTermination with task running. * Test awaitTermination with task running.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testAwaitTermination2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testAwaitTermination2(ExecutorService executor) throws Exception {
Phaser barrier = new Phaser(2); Phaser barrier = new Phaser(2);
Future<?> result = executor.submit(barrier::arriveAndAwaitAdvance); Future<?> result = executor.submit(barrier::arriveAndAwaitAdvance);
try { try {
@ -317,8 +318,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test submit when the Executor is shutdown but not terminated. * Test submit when the Executor is shutdown but not terminated.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testSubmitAfterShutdown(ExecutorService executor) throws Exception { @MethodSource("executors")
void testSubmitAfterShutdown(ExecutorService executor) throws Exception {
Phaser barrier = new Phaser(2); Phaser barrier = new Phaser(2);
try (executor) { try (executor) {
// submit task to prevent executor from terminating // submit task to prevent executor from terminating
@ -326,7 +328,7 @@ public class ThreadPerTaskExecutorTest {
try { try {
executor.shutdown(); executor.shutdown();
assertTrue(executor.isShutdown() && !executor.isTerminated()); assertTrue(executor.isShutdown() && !executor.isTerminated());
expectThrows(RejectedExecutionException.class, assertThrows(RejectedExecutionException.class,
() -> executor.submit(() -> { })); () -> executor.submit(() -> { }));
} finally { } finally {
barrier.arriveAndAwaitAdvance(); barrier.arriveAndAwaitAdvance();
@ -337,24 +339,27 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test submit when the Executor is terminated. * Test submit when the Executor is terminated.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testSubmitAfterTermination(ExecutorService executor) throws Exception { @MethodSource("executors")
void testSubmitAfterTermination(ExecutorService executor) throws Exception {
executor.shutdown(); executor.shutdown();
assertTrue(executor.isShutdown() && executor.isTerminated()); assertTrue(executor.isShutdown() && executor.isTerminated());
expectThrows(RejectedExecutionException.class, () -> executor.submit(() -> {})); assertThrows(RejectedExecutionException.class, () -> executor.submit(() -> {}));
} }
/** /**
* Test submit with null. * Test submit with null.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testSubmitNulls1(ThreadFactory factory) { @MethodSource("factories")
void testSubmitNulls1(ThreadFactory factory) {
var executor = Executors.newThreadPerTaskExecutor(factory); var executor = Executors.newThreadPerTaskExecutor(factory);
assertThrows(NullPointerException.class, () -> executor.submit((Runnable) null)); assertThrows(NullPointerException.class, () -> executor.submit((Runnable) null));
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testSubmitNulls2(ThreadFactory factory) { @MethodSource("factories")
void testSubmitNulls2(ThreadFactory factory) {
var executor = Executors.newThreadPerTaskExecutor(factory); var executor = Executors.newThreadPerTaskExecutor(factory);
assertThrows(NullPointerException.class, () -> executor.submit((Callable<String>) null)); assertThrows(NullPointerException.class, () -> executor.submit((Callable<String>) null));
} }
@ -362,8 +367,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny where all tasks complete normally. * Test invokeAny where all tasks complete normally.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny1(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> "bar"; Callable<String> task2 = () -> "bar";
@ -376,8 +382,9 @@ public class ThreadPerTaskExecutorTest {
* Test invokeAny where all tasks complete normally. The completion of the * Test invokeAny where all tasks complete normally. The completion of the
* first task should cancel remaining tasks. * first task should cancel remaining tasks.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny2(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
AtomicBoolean task2Started = new AtomicBoolean(); AtomicBoolean task2Started = new AtomicBoolean();
AtomicReference<Throwable> task2Exception = new AtomicReference<>(); AtomicReference<Throwable> task2Exception = new AtomicReference<>();
@ -408,8 +415,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny where all tasks complete with exception. * Test invokeAny where all tasks complete with exception.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny3(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny3(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
Callable<String> task1 = () -> { throw new FooException(); }; Callable<String> task1 = () -> { throw new FooException(); };
@ -428,8 +436,9 @@ public class ThreadPerTaskExecutorTest {
* Test invokeAny where all tasks complete with exception. The completion * Test invokeAny where all tasks complete with exception. The completion
* of the last task is delayed. * of the last task is delayed.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny4(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny4(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
Callable<String> task1 = () -> { throw new FooException(); }; Callable<String> task1 = () -> { throw new FooException(); };
@ -450,8 +459,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny where some, not all, tasks complete normally. * Test invokeAny where some, not all, tasks complete normally.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny5(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny5(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
@ -465,8 +475,9 @@ public class ThreadPerTaskExecutorTest {
* Test invokeAny where some, not all, tasks complete normally. The * Test invokeAny where some, not all, tasks complete normally. The
* completion of the first task to complete normally is delayed. * completion of the first task to complete normally is delayed.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAny6(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAny6(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
Callable<String> task1 = () -> { Callable<String> task1 = () -> {
@ -482,8 +493,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test timed-invokeAny where all tasks complete normally before the timeout. * Test timed-invokeAny where all tasks complete normally before the timeout.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyWithTimeout1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyWithTimeout1(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> "bar"; Callable<String> task2 = () -> "bar";
@ -496,8 +508,9 @@ public class ThreadPerTaskExecutorTest {
* Test timed-invokeAny where one task completes normally before the timeout. * Test timed-invokeAny where one task completes normally before the timeout.
* The remaining tests should be cancelled. * The remaining tests should be cancelled.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyWithTimeout2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyWithTimeout2(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
AtomicBoolean task2Started = new AtomicBoolean(); AtomicBoolean task2Started = new AtomicBoolean();
AtomicReference<Throwable> task2Exception = new AtomicReference<>(); AtomicReference<Throwable> task2Exception = new AtomicReference<>();
@ -528,8 +541,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test timed-invokeAny where timeout expires before any task completes. * Test timed-invokeAny where timeout expires before any task completes.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyWithTimeout3(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyWithTimeout3(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> { Callable<String> task1 = () -> {
Thread.sleep(Duration.ofMinutes(1)); Thread.sleep(Duration.ofMinutes(1));
@ -548,8 +562,9 @@ public class ThreadPerTaskExecutorTest {
* Test invokeAny where timeout expires after some tasks have completed * Test invokeAny where timeout expires after some tasks have completed
* with exception. * with exception.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyWithTimeout4(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyWithTimeout4(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
Callable<String> task1 = () -> { throw new FooException(); }; Callable<String> task1 = () -> { throw new FooException(); };
@ -565,8 +580,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny with interrupt status set. * Test invokeAny with interrupt status set.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyWithInterruptSet(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyWithInterruptSet(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> "bar"; Callable<String> task2 = () -> "bar";
@ -585,8 +601,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test interrupting a thread blocked in invokeAny. * Test interrupting a thread blocked in invokeAny.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInterruptInvokeAny(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInterruptInvokeAny(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> { Callable<String> task1 = () -> {
Thread.sleep(Duration.ofMinutes(1)); Thread.sleep(Duration.ofMinutes(1));
@ -611,8 +628,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny after ExecutorService has been shutdown. * Test invokeAny after ExecutorService has been shutdown.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAnyAfterShutdown(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAnyAfterShutdown(ExecutorService executor) throws Exception {
executor.shutdown(); executor.shutdown();
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> "bar"; Callable<String> task2 = () -> "bar";
@ -623,8 +641,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny with empty collection. * Test invokeAny with empty collection.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAnyEmpty1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAnyEmpty1(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
assertThrows(IllegalArgumentException.class, () -> executor.invokeAny(Set.of())); assertThrows(IllegalArgumentException.class, () -> executor.invokeAny(Set.of()));
} }
@ -633,8 +652,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test timed-invokeAny with empty collection. * Test timed-invokeAny with empty collection.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAnyEmpty2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAnyEmpty2(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> executor.invokeAny(Set.of(), 1, TimeUnit.MINUTES)); () -> executor.invokeAny(Set.of(), 1, TimeUnit.MINUTES));
@ -644,8 +664,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny with null. * Test invokeAny with null.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAnyNull1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAnyNull1(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
assertThrows(NullPointerException.class, () -> executor.invokeAny(null)); assertThrows(NullPointerException.class, () -> executor.invokeAny(null));
} }
@ -654,8 +675,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAny with null element * Test invokeAny with null element
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAnyNull2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAnyNull2(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
List<Callable<String>> list = new ArrayList<>(); List<Callable<String>> list = new ArrayList<>();
list.add(() -> "foo"); list.add(() -> "foo");
@ -667,8 +689,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll where all tasks complete normally. * Test invokeAll where all tasks complete normally.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAll1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAll1(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> { Callable<String> task2 = () -> {
@ -692,8 +715,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll where all tasks complete with exception. * Test invokeAll where all tasks complete with exception.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAll2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAll2(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
class FooException extends Exception { } class FooException extends Exception { }
class BarException extends Exception { } class BarException extends Exception { }
@ -711,9 +735,9 @@ public class ThreadPerTaskExecutorTest {
assertFalse(notDone); assertFalse(notDone);
// check results // check results
Throwable e1 = expectThrows(ExecutionException.class, () -> list.get(0).get()); Throwable e1 = assertThrows(ExecutionException.class, () -> list.get(0).get());
assertTrue(e1.getCause() instanceof FooException); assertTrue(e1.getCause() instanceof FooException);
Throwable e2 = expectThrows(ExecutionException.class, () -> list.get(1).get()); Throwable e2 = assertThrows(ExecutionException.class, () -> list.get(1).get());
assertTrue(e2.getCause() instanceof BarException); assertTrue(e2.getCause() instanceof BarException);
} }
} }
@ -721,8 +745,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll where all tasks complete normally before the timeout expires. * Test invokeAll where all tasks complete normally before the timeout expires.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAll3(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAll3(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> { Callable<String> task2 = () -> {
@ -746,8 +771,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll where some tasks do not complete before the timeout expires. * Test invokeAll where some tasks do not complete before the timeout expires.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAll4(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAll4(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
AtomicReference<Exception> exc = new AtomicReference<>(); AtomicReference<Exception> exc = new AtomicReference<>();
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
@ -784,8 +810,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll with interrupt status set. * Test invokeAll with interrupt status set.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllInterrupt1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllInterrupt1(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> { Callable<String> task2 = () -> {
@ -808,8 +835,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test timed-invokeAll with interrupt status set. * Test timed-invokeAll with interrupt status set.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllInterrupt3(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllInterrupt3(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
Callable<String> task2 = () -> { Callable<String> task2 = () -> {
@ -832,8 +860,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test interrupt with thread blocked in invokeAll. * Test interrupt with thread blocked in invokeAll.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllInterrupt4(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllInterrupt4(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
DelayedResult<String> task2 = new DelayedResult("bar", Duration.ofMinutes(1)); DelayedResult<String> task2 = new DelayedResult("bar", Duration.ofMinutes(1));
@ -858,8 +887,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test interrupt with thread blocked in timed-invokeAll. * Test interrupt with thread blocked in timed-invokeAll.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllInterrupt6(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllInterrupt6(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
DelayedResult<String> task2 = new DelayedResult("bar", Duration.ofMinutes(1)); DelayedResult<String> task2 = new DelayedResult("bar", Duration.ofMinutes(1));
@ -884,8 +914,9 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll after ExecutorService has been shutdown. * Test invokeAll after ExecutorService has been shutdown.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllAfterShutdown1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllAfterShutdown1(ExecutorService executor) throws Exception {
executor.shutdown(); executor.shutdown();
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
@ -894,8 +925,9 @@ public class ThreadPerTaskExecutorTest {
() -> executor.invokeAll(Set.of(task1, task2))); () -> executor.invokeAll(Set.of(task1, task2)));
} }
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllAfterShutdown2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllAfterShutdown2(ExecutorService executor) throws Exception {
executor.shutdown(); executor.shutdown();
Callable<String> task1 = () -> "foo"; Callable<String> task1 = () -> "foo";
@ -907,31 +939,35 @@ public class ThreadPerTaskExecutorTest {
/** /**
* Test invokeAll with empty collection. * Test invokeAll with empty collection.
*/ */
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllEmpty1(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllEmpty1(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
List<Future<Object>> list = executor.invokeAll(Set.of()); List<Future<Object>> list = executor.invokeAll(Set.of());
assertTrue(list.size() == 0); assertTrue(list.size() == 0);
} }
} }
@Test(dataProvider = "executors") @ParameterizedTest
public void testInvokeAllEmpty2(ExecutorService executor) throws Exception { @MethodSource("executors")
void testInvokeAllEmpty2(ExecutorService executor) throws Exception {
try (executor) { try (executor) {
List<Future<Object>> list = executor.invokeAll(Set.of(), 1, TimeUnit.SECONDS); List<Future<Object>> list = executor.invokeAll(Set.of(), 1, TimeUnit.SECONDS);
assertTrue(list.size() == 0); assertTrue(list.size() == 0);
} }
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAllNull1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAllNull1(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
assertThrows(NullPointerException.class, () -> executor.invokeAll(null)); assertThrows(NullPointerException.class, () -> executor.invokeAll(null));
} }
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAllNull2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAllNull2(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
List<Callable<String>> tasks = new ArrayList<>(); List<Callable<String>> tasks = new ArrayList<>();
tasks.add(() -> "foo"); tasks.add(() -> "foo");
@ -940,16 +976,18 @@ public class ThreadPerTaskExecutorTest {
} }
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAllNull3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAllNull3(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> executor.invokeAll(null, 1, TimeUnit.SECONDS)); () -> executor.invokeAll(null, 1, TimeUnit.SECONDS));
} }
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAllNull4(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAllNull4(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
Callable<String> task = () -> "foo"; Callable<String> task = () -> "foo";
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
@ -957,8 +995,9 @@ public class ThreadPerTaskExecutorTest {
} }
} }
@Test(dataProvider = "factories") @ParameterizedTest
public void testInvokeAllNull5(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInvokeAllNull5(ThreadFactory factory) throws Exception {
try (var executor = Executors.newThreadPerTaskExecutor(factory)) { try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
List<Callable<String>> tasks = new ArrayList<>(); List<Callable<String>> tasks = new ArrayList<>();
tasks.add(() -> "foo"); tasks.add(() -> "foo");
@ -972,33 +1011,33 @@ public class ThreadPerTaskExecutorTest {
* Test ThreadFactory that does not produce any threads * Test ThreadFactory that does not produce any threads
*/ */
@Test @Test
public void testNoThreads1() throws Exception { void testNoThreads1() throws Exception {
ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null); ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null);
assertThrows(RejectedExecutionException.class, () -> executor.execute(() -> { })); assertThrows(RejectedExecutionException.class, () -> executor.execute(() -> { }));
} }
@Test @Test
public void testNoThreads2() throws Exception { void testNoThreads2() throws Exception {
ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null); ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null);
assertThrows(RejectedExecutionException.class, () -> executor.submit(() -> "foo")); assertThrows(RejectedExecutionException.class, () -> executor.submit(() -> "foo"));
} }
@Test @Test
public void testNoThreads3() throws Exception { void testNoThreads3() throws Exception {
ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null); ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null);
assertThrows(RejectedExecutionException.class, assertThrows(RejectedExecutionException.class,
() -> executor.invokeAll(List.of(() -> "foo"))); () -> executor.invokeAll(List.of(() -> "foo")));
} }
@Test @Test
public void testNoThreads4() throws Exception { void testNoThreads4() throws Exception {
ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null); ExecutorService executor = Executors.newThreadPerTaskExecutor(task -> null);
assertThrows(RejectedExecutionException.class, assertThrows(RejectedExecutionException.class,
() -> executor.invokeAny(List.of(() -> "foo"))); () -> executor.invokeAny(List.of(() -> "foo")));
} }
@Test @Test
public void testNull() { void testNull() {
assertThrows(NullPointerException.class, assertThrows(NullPointerException.class,
() -> Executors.newThreadPerTaskExecutor(null)); () -> Executors.newThreadPerTaskExecutor(null));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,7 @@
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @library /test/lib * @library /test/lib
* @key randomness * @key randomness
* @run testng ManyBindings * @run junit ManyBindings
*/ */
import jdk.incubator.concurrent.ScopedValue; import jdk.incubator.concurrent.ScopedValue;
@ -40,11 +40,10 @@ import java.util.Random;
import jdk.test.lib.RandomFactory; import jdk.test.lib.RandomFactory;
import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadRunner;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
@Test class ManyBindings {
public class ManyBindings {
private static final Random RND = RandomFactory.getRandom(); private static final Random RND = RandomFactory.getRandom();
// number of scoped values to create // number of scoped values to create
@ -56,14 +55,16 @@ public class ManyBindings {
/** /**
* Stress test bindings on platform thread. * Stress test bindings on platform thread.
*/ */
public void testPlatformThread() { @Test
void testPlatformThread() {
test(); test();
} }
/** /**
* Stress test bindings on virtual thread. * Stress test bindings on virtual thread.
*/ */
public void testVirtualThread() throws Exception { @Test
void testVirtualThread() throws Exception {
VThreadRunner.run(() -> test()); VThreadRunner.run(() -> test());
} }
@ -143,7 +144,7 @@ public class ManyBindings {
if (value == null) { if (value == null) {
assertFalse(key.isBound()); assertFalse(key.isBound());
} else { } else {
assertEquals(key.get(), value); assertEquals(value, key.get());
} }
} }
} }
@ -157,7 +158,7 @@ public class ManyBindings {
Integer value = array[index].value; Integer value = array[index].value;
if (value != null) { if (value != null) {
ScopedValue<Integer> key = array[index].key; ScopedValue<Integer> key = array[index].key;
assertEquals(key.get(), value); assertEquals(value, key.get());
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
* @summary Test ScopedValue API * @summary Test ScopedValue API
* @enablePreview * @enablePreview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng ScopeValueAPI * @run junit ScopeValueAPI
*/ */
import jdk.incubator.concurrent.ScopedValue; import jdk.incubator.concurrent.ScopedValue;
@ -35,27 +35,25 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.stream.Stream;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import static org.testng.Assert.*; import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
@Test class ScopeValueAPI {
public class ScopeValueAPI {
@DataProvider private static Stream<ThreadFactory> factories() {
public Object[][] factories() { return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
return new Object[][] {
{ Thread.ofPlatform().factory() },
{ Thread.ofVirtual().factory() },
};
} }
/** /**
* Test that the run method is invoked. * Test that the run method is invoked.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testRun(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testRun(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
class Box { static boolean executed; } class Box { static boolean executed; }
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
@ -67,8 +65,9 @@ public class ScopeValueAPI {
/** /**
* Test the run method throwing an exception. * Test the run method throwing an exception.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testRunThrows(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testRunThrows(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
@ -81,20 +80,22 @@ public class ScopeValueAPI {
/** /**
* Test that the call method is invoked. * Test that the call method is invoked.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCall(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCall(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
String result = ScopedValue.where(name, "duke", name::get); String result = ScopedValue.where(name, "duke", name::get);
assertEquals(result, "duke"); assertEquals("duke", result);
}); });
} }
/** /**
* Test the call method throwing an exception. * Test the call method throwing an exception.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCallThrows(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCallThrows(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
@ -107,8 +108,9 @@ public class ScopeValueAPI {
/** /**
* Test get method. * Test get method.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testGet(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testGet(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name1 = ScopedValue.newInstance(); ScopedValue<String> name1 = ScopedValue.newInstance();
ScopedValue<String> name2 = ScopedValue.newInstance(); ScopedValue<String> name2 = ScopedValue.newInstance();
@ -117,7 +119,7 @@ public class ScopeValueAPI {
// run // run
ScopedValue.where(name1, "duke", () -> { ScopedValue.where(name1, "duke", () -> {
assertEquals(name1.get(), "duke"); assertEquals("duke", name1.get());
assertThrows(NoSuchElementException.class, name2::get); assertThrows(NoSuchElementException.class, name2::get);
}); });
@ -126,7 +128,7 @@ public class ScopeValueAPI {
// call // call
ScopedValue.where(name1, "duke", () -> { ScopedValue.where(name1, "duke", () -> {
assertEquals(name1.get(), "duke"); assertEquals("duke", name1.get());
assertThrows(NoSuchElementException.class, name2::get); assertThrows(NoSuchElementException.class, name2::get);
return null; return null;
}); });
@ -138,8 +140,9 @@ public class ScopeValueAPI {
/** /**
* Test isBound method. * Test isBound method.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testIsBound(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testIsBound(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name1 = ScopedValue.newInstance(); ScopedValue<String> name1 = ScopedValue.newInstance();
ScopedValue<String> name2 = ScopedValue.newInstance(); ScopedValue<String> name2 = ScopedValue.newInstance();
@ -168,23 +171,24 @@ public class ScopeValueAPI {
/** /**
* Test orElse method. * Test orElse method.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testOrElse(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testOrElse(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
assertTrue(name.orElse(null) == null); assertNull(name.orElse(null));
assertEquals(name.orElse("default"), "default"); assertEquals("default", name.orElse("default"));
// run // run
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertEquals(name.orElse(null), "duke"); assertEquals("duke", name.orElse(null));
assertEquals(name.orElse("default"), "duke"); assertEquals("duke", name.orElse("default"));
}); });
// call // call
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertEquals(name.orElse(null), "duke"); assertEquals("duke", name.orElse(null));
assertEquals(name.orElse("default"), "duke"); assertEquals("duke", name.orElse("default"));
return null; return null;
}); });
}); });
@ -193,8 +197,9 @@ public class ScopeValueAPI {
/** /**
* Test orElseThrow method. * Test orElseThrow method.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testOrElseThrow(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testOrElseThrow(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
class FooException extends RuntimeException { } class FooException extends RuntimeException { }
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
@ -202,12 +207,12 @@ public class ScopeValueAPI {
// run // run
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertEquals(name.orElseThrow(FooException::new), "duke"); assertEquals("duke", name.orElseThrow(FooException::new));
}); });
// call // call
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertEquals(name.orElseThrow(FooException::new), "duke"); assertEquals("duke", name.orElseThrow(FooException::new));
return null; return null;
}); });
}); });
@ -216,8 +221,9 @@ public class ScopeValueAPI {
/** /**
* Test two bindings. * Test two bindings.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testTwoBindings(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testTwoBindings(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
ScopedValue<Integer> age = ScopedValue.newInstance(); ScopedValue<Integer> age = ScopedValue.newInstance();
@ -226,8 +232,8 @@ public class ScopeValueAPI {
ScopedValue.where(name, "duke").where(age, 100).run(() -> { ScopedValue.where(name, "duke").where(age, 100).run(() -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(age.isBound()); assertTrue(age.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
assertEquals((int) age.get(), 100); assertEquals(100, (int) age.get());
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
assertFalse(age.isBound()); assertFalse(age.isBound());
@ -236,8 +242,8 @@ public class ScopeValueAPI {
ScopedValue.where(name, "duke").where(age, 100).call(() -> { ScopedValue.where(name, "duke").where(age, 100).call(() -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(age.isBound()); assertTrue(age.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
assertEquals((int) age.get(), 100); assertEquals(100, (int) age.get());
return null; return null;
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
@ -249,39 +255,40 @@ public class ScopeValueAPI {
/** /**
* Test rebinding. * Test rebinding.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testRebinding(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testRebinding(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
// run // run
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
ScopedValue.where(name, "duchess", () -> { ScopedValue.where(name, "duchess", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue("duchess".equals(name.get())); assertEquals("duchess", name.get());
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
// call // call
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
ScopedValue.where(name, "duchess", () -> { ScopedValue.where(name, "duchess", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue("duchess".equals(name.get())); assertEquals("duchess", name.get());
return null; return null;
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
return null; return null;
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
@ -291,15 +298,16 @@ public class ScopeValueAPI {
/** /**
* Test rebinding from null vaue to another value. * Test rebinding from null vaue to another value.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testRebindingFromNull(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testRebindingFromNull(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
// run // run
ScopedValue.where(name, null, () -> { ScopedValue.where(name, null, () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), null); assertNull(name.get());
ScopedValue.where(name, "duchess", () -> { ScopedValue.where(name, "duchess", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
@ -307,14 +315,14 @@ public class ScopeValueAPI {
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(name.get() == null); assertNull(name.get());
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
// call // call
ScopedValue.where(name, null, () -> { ScopedValue.where(name, null, () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), null); assertNull(name.get());
ScopedValue.where(name, "duchess", () -> { ScopedValue.where(name, "duchess", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
@ -323,7 +331,7 @@ public class ScopeValueAPI {
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(name.get() == null); assertNull(name.get());
return null; return null;
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
@ -333,39 +341,40 @@ public class ScopeValueAPI {
/** /**
* Test rebinding to null value. * Test rebinding to null value.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testRebindingToNull(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testRebindingToNull(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
// run // run
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
ScopedValue.where(name, null, () -> { ScopedValue.where(name, null, () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(name.get() == null); assertNull(name.get());
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
// call // call
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
ScopedValue.where(name, null, () -> { ScopedValue.where(name, null, () -> {
assertTrue(name.isBound()); assertTrue(name.isBound());
assertTrue(name.get() == null); assertNull(name.get());
return null; return null;
}); });
assertTrue(name.isBound()); assertTrue(name.isBound());
assertEquals(name.get(), "duke"); assertEquals("duke", name.get());
return null; return null;
}); });
assertFalse(name.isBound()); assertFalse(name.isBound());
@ -375,28 +384,30 @@ public class ScopeValueAPI {
/** /**
* Test Carrier.get. * Test Carrier.get.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCarrierGet(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCarrierGet(ThreadFactory factory) throws Exception {
test(factory, () -> { test(factory, () -> {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
ScopedValue<Integer> age = ScopedValue.newInstance(); ScopedValue<Integer> age = ScopedValue.newInstance();
// one scoped value // one scoped value
var carrier1 = ScopedValue.where(name, "duke"); var carrier1 = ScopedValue.where(name, "duke");
assertEquals(carrier1.get(name), "duke"); assertEquals("duke", carrier1.get(name));
assertThrows(NoSuchElementException.class, () -> carrier1.get(age)); assertThrows(NoSuchElementException.class, () -> carrier1.get(age));
// two scoped values // two scoped values
var carrier2 = carrier1.where(age, 20); var carrier2 = carrier1.where(age, 20);
assertEquals(carrier2.get(name), "duke"); assertEquals("duke", carrier2.get(name));
assertEquals((int) carrier2.get(age), 20); assertEquals(20, (int) carrier2.get(age));
}); });
} }
/** /**
* Test NullPointerException. * Test NullPointerException.
*/ */
public void testNullPointerException() { @Test
void testNullPointerException() {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value")); assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value"));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,19 +26,19 @@
* @bug 8284199 * @bug 8284199
* @summary Test StructuredTaskScope without --enable-preview * @summary Test StructuredTaskScope without --enable-preview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng/othervm PreviewFeaturesNotEnabled * @run junit/othervm PreviewFeaturesNotEnabled
*/ */
import jdk.incubator.concurrent.StructuredTaskScope; import jdk.incubator.concurrent.StructuredTaskScope;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class PreviewFeaturesNotEnabled { class PreviewFeaturesNotEnabled {
/** /**
* One-arg constructor needs --enable-preview. * One-arg constructor needs --enable-preview.
*/ */
@Test @Test
public void testUnsupportedOperationException() { void testUnsupportedOperationException() {
assertThrows(UnsupportedOperationException.class, StructuredTaskScope::new); assertThrows(UnsupportedOperationException.class, StructuredTaskScope::new);
} }
@ -46,7 +46,7 @@ public class PreviewFeaturesNotEnabled {
* Two-arg constructor does not need --enable-preview. * Two-arg constructor does not need --enable-preview.
*/ */
@Test @Test
public void testNoUnsupportedOperationException() { void testNoUnsupportedOperationException() {
try (var scope = new StructuredTaskScope<Object>(null, Thread::new)) { try (var scope = new StructuredTaskScope<Object>(null, Thread::new)) {
} }
} }

View File

@ -27,14 +27,14 @@
* @summary Basic tests for StructuredTaskScope * @summary Basic tests for StructuredTaskScope
* @enablePreview * @enablePreview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng/othervm -DthreadFactory=platform StructuredTaskScopeTest * @run junit/othervm -DthreadFactory=platform StructuredTaskScopeTest
*/ */
/* /*
* @test id=virtual * @test id=virtual
* @enablePreview * @enablePreview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng/othervm -DthreadFactory=virtual StructuredTaskScopeTest * @run junit/othervm -DthreadFactory=virtual StructuredTaskScopeTest
*/ */
import jdk.incubator.concurrent.StructuredTaskScope; import jdk.incubator.concurrent.StructuredTaskScope;
@ -65,24 +65,21 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class StructuredTaskScopeTest { import org.junit.jupiter.api.Test;
private ScheduledExecutorService scheduler; import org.junit.jupiter.api.BeforeAll;
private Object[][] threadFactories; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
@BeforeClass class StructuredTaskScopeTest {
public void setUp() throws Exception { private static ScheduledExecutorService scheduler;
ThreadFactory factory = (task) -> { private static List<ThreadFactory> threadFactories;
Thread thread = new Thread(task);
thread.setDaemon(true); @BeforeAll
return thread; static void setup() throws Exception {
}; scheduler = Executors.newSingleThreadScheduledExecutor();
this.scheduler = Executors.newSingleThreadScheduledExecutor(factory);
// thread factories // thread factories
String value = System.getProperty("threadFactory"); String value = System.getProperty("threadFactory");
@ -92,29 +89,24 @@ public class StructuredTaskScopeTest {
if (value == null || value.equals("virtual")) if (value == null || value.equals("virtual"))
list.add(Thread.ofVirtual().factory()); list.add(Thread.ofVirtual().factory());
assertTrue(list.size() > 0, "No thread factories for tests"); assertTrue(list.size() > 0, "No thread factories for tests");
this.threadFactories = list.stream() threadFactories = list;
.map(f -> new Object[] { f })
.toArray(Object[][]::new);
} }
@AfterClass @AfterAll
public void tearDown() { static void shutdown() {
scheduler.shutdown(); scheduler.shutdown();
} }
/** private static Stream<ThreadFactory> factories() {
* A provider of ThreadFactory objects for tests. return threadFactories.stream();
*/
@DataProvider
public Object[][] factories() {
return threadFactories;
} }
/** /**
* Test that each fork creates a thread. * Test that each fork creates a thread.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFork1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFork1(ThreadFactory factory) throws Exception {
AtomicInteger count = new AtomicInteger(); AtomicInteger count = new AtomicInteger();
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -128,8 +120,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test that fork uses the specified thread factory. * Test that fork uses the specified thread factory.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFork2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFork2(ThreadFactory factory) throws Exception {
AtomicInteger count = new AtomicInteger(); AtomicInteger count = new AtomicInteger();
ThreadFactory countingFactory = task -> { ThreadFactory countingFactory = task -> {
count.incrementAndGet(); count.incrementAndGet();
@ -147,8 +140,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test fork is confined to threads in the scope "tree". * Test fork is confined to threads in the scope "tree".
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkConfined(ThreadFactory factory) throws Exception {
try (var scope1 = new StructuredTaskScope(); try (var scope1 = new StructuredTaskScope();
var scope2 = new StructuredTaskScope()) { var scope2 = new StructuredTaskScope()) {
@ -157,7 +151,7 @@ public class StructuredTaskScopeTest {
scope2.fork(() -> null).get(); scope2.fork(() -> null).get();
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future1::get); Throwable ex = assertThrows(ExecutionException.class, future1::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
// thread in scope2 can fork thread in scope1 // thread in scope2 can fork thread in scope1
@ -166,7 +160,7 @@ public class StructuredTaskScopeTest {
return null; return null;
}); });
future2.get(); future2.get();
assertTrue(future2.resultNow() == null); assertNull(future2.resultNow());
// random thread cannot fork // random thread cannot fork
try (var pool = Executors.newCachedThreadPool(factory)) { try (var pool = Executors.newCachedThreadPool(factory)) {
@ -174,7 +168,7 @@ public class StructuredTaskScopeTest {
scope1.fork(() -> null); scope1.fork(() -> null);
return null; return null;
}); });
ex = expectThrows(ExecutionException.class, future::get); ex = assertThrows(ExecutionException.class, future::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
} }
@ -186,8 +180,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test fork when scope is shutdown. * Test fork when scope is shutdown.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkAfterShutdown(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkAfterShutdown(ThreadFactory factory) throws Exception {
AtomicInteger count = new AtomicInteger(); AtomicInteger count = new AtomicInteger();
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
scope.shutdown(); scope.shutdown();
@ -204,8 +199,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test fork when scope is closed. * Test fork when scope is closed.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkAfterClose(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkAfterClose(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
scope.join(); scope.join();
scope.close(); scope.close();
@ -217,7 +213,7 @@ public class StructuredTaskScopeTest {
* Test fork when the thread factory rejects creating a thread. * Test fork when the thread factory rejects creating a thread.
*/ */
@Test @Test
public void testForkReject() throws Exception { void testForkReject() throws Exception {
ThreadFactory factory = task -> null; ThreadFactory factory = task -> null;
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
assertThrows(RejectedExecutionException.class, () -> scope.fork(() -> null)); assertThrows(RejectedExecutionException.class, () -> scope.fork(() -> null));
@ -255,8 +251,9 @@ public class StructuredTaskScopeTest {
* Test that handleComplete method is invoked for tasks that complete normally * Test that handleComplete method is invoked for tasks that complete normally
* and abnormally. * and abnormally.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testHandleComplete1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testHandleComplete1(ThreadFactory factory) throws Exception {
try (var scope = new CollectAll(factory)) { try (var scope = new CollectAll(factory)) {
// completes normally // completes normally
@ -275,17 +272,17 @@ public class StructuredTaskScopeTest {
scope.join(); scope.join();
Set<Future<String>> futures = scope.futuresAsSet(); Set<Future<String>> futures = scope.futuresAsSet();
assertEquals(futures, Set.of(future1, future2, future3)); assertEquals(Set.of(future1, future2, future3), futures);
} }
} }
/** /**
* Test that the handeComplete method is not invoked after the scope has been shutdown. * Test that the handeComplete method is not invoked after the scope has been shutdown.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testHandleComplete2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testHandleComplete2(ThreadFactory factory) throws Exception {
try (var scope = new CollectAll(factory)) { try (var scope = new CollectAll(factory)) {
var latch = new CountDownLatch(1); var latch = new CountDownLatch(1);
// start task that does not respond to interrupt // start task that does not respond to interrupt
@ -322,7 +319,7 @@ public class StructuredTaskScopeTest {
* Test join with no threads. * Test join with no threads.
*/ */
@Test @Test
public void testJoinWithNoThreads() throws Exception { void testJoinWithNoThreads() throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
scope.join(); scope.join();
} }
@ -331,30 +328,32 @@ public class StructuredTaskScopeTest {
/** /**
* Test join with threads running. * Test join with threads running.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinWithThreads(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinWithThreads(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofMillis(50)); Thread.sleep(Duration.ofMillis(50));
return "foo"; return "foo";
}); });
scope.join(); scope.join();
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
} }
} }
/** /**
* Test join is owner confined. * Test join is owner confined.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinConfined(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
// attempt to join on thread in scope // attempt to join on thread in scope
Future<Void> future1 = scope.fork(() -> { Future<Void> future1 = scope.fork(() -> {
scope.join(); scope.join();
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future1::get); Throwable ex = assertThrows(ExecutionException.class, future1::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
// random thread cannot join // random thread cannot join
@ -363,7 +362,7 @@ public class StructuredTaskScopeTest {
scope.join(); scope.join();
return null; return null;
}); });
ex = expectThrows(ExecutionException.class, future2::get); ex = assertThrows(ExecutionException.class, future2::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
} }
@ -374,11 +373,14 @@ public class StructuredTaskScopeTest {
/** /**
* Test join with interrupt status set. * Test join with interrupt status set.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptJoin1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptJoin1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1);
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofMillis(100)); latch.await();
return "foo"; return "foo";
}); });
@ -389,22 +391,28 @@ public class StructuredTaskScopeTest {
fail("join did not throw"); fail("join did not throw");
} catch (InterruptedException expected) { } catch (InterruptedException expected) {
assertFalse(Thread.interrupted()); // interrupt status should be clear assertFalse(Thread.interrupted()); // interrupt status should be clear
} finally {
// let task continue
latch.countDown();
} }
// join should complete // join should complete
scope.join(); scope.join();
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
} }
} }
/** /**
* Test interrupt of thread blocked in join. * Test interrupt of thread blocked in join.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptJoin2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptJoin2(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1);
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofSeconds(3)); latch.await();
return "foo"; return "foo";
}); });
@ -415,19 +423,23 @@ public class StructuredTaskScopeTest {
fail("join did not throw"); fail("join did not throw");
} catch (InterruptedException expected) { } catch (InterruptedException expected) {
assertFalse(Thread.interrupted()); // interrupt status should be clear assertFalse(Thread.interrupted()); // interrupt status should be clear
} finally {
// let task continue
latch.countDown();
} }
// join should complete // join should complete
scope.join(); scope.join();
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
} }
} }
/** /**
* Test join when scope is already shutdown. * Test join when scope is already shutdown.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinWithShutdown1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinWithShutdown1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofDays(1)); Thread.sleep(Duration.ofDays(1));
@ -444,8 +456,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test shutdown when owner is blocked in join. * Test shutdown when owner is blocked in join.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinWithShutdown2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinWithShutdown2(ThreadFactory factory) throws Exception {
class MyScope<T> extends StructuredTaskScope<T> { class MyScope<T> extends StructuredTaskScope<T> {
MyScope(ThreadFactory factory) { MyScope(ThreadFactory factory) {
super(null, factory); super(null, factory);
@ -479,7 +492,7 @@ public class StructuredTaskScopeTest {
* Test join after scope is shutdown. * Test join after scope is shutdown.
*/ */
@Test @Test
public void testJoinAfterShutdown() throws Exception { void testJoinAfterShutdown() throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
scope.shutdown(); scope.shutdown();
scope.join(); scope.join();
@ -490,7 +503,7 @@ public class StructuredTaskScopeTest {
* Test join after scope is closed. * Test join after scope is closed.
*/ */
@Test @Test
public void testJoinAfterClose() throws Exception { void testJoinAfterClose() throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
scope.join(); scope.join();
scope.close(); scope.close();
@ -502,8 +515,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test joinUntil, threads finish before deadline expires. * Test joinUntil, threads finish before deadline expires.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinUntil1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinUntil1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
try { try {
@ -514,7 +528,8 @@ public class StructuredTaskScopeTest {
long startMillis = millisTime(); long startMillis = millisTime();
scope.joinUntil(Instant.now().plusSeconds(30)); scope.joinUntil(Instant.now().plusSeconds(30));
assertTrue(future.isDone() && future.resultNow() == null); assertTrue(future.isDone());
assertNull(future.resultNow());
expectDuration(startMillis, /*min*/1900, /*max*/20_000); expectDuration(startMillis, /*min*/1900, /*max*/20_000);
} }
} }
@ -522,8 +537,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test joinUntil, deadline expires before threads finish. * Test joinUntil, deadline expires before threads finish.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinUntil2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinUntil2(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
try { try {
@ -545,8 +561,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test joinUntil many times. * Test joinUntil many times.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinUntil3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinUntil3(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
try { try {
@ -573,8 +590,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test joinUntil with a deadline that has already expired. * Test joinUntil with a deadline that has already expired.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testJoinUntil4(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testJoinUntil4(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
try { try {
@ -610,37 +628,46 @@ public class StructuredTaskScopeTest {
/** /**
* Test joinUntil with interrupt status set. * Test joinUntil with interrupt status set.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptJoinUntil1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptJoinUntil1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1);
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofSeconds(2)); latch.await();
return "foo"; return "foo";
}); });
// joinUntil should throw // joinUntil should throw
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
scope.joinUntil(Instant.now().plusSeconds(10)); scope.joinUntil(Instant.now().plusSeconds(30));
fail("joinUntil did not throw"); fail("joinUntil did not throw");
} catch (InterruptedException expected) { } catch (InterruptedException expected) {
assertFalse(Thread.interrupted()); // interrupt status should be clear assertFalse(Thread.interrupted()); // interrupt status should be clear
} finally {
// let task continue
latch.countDown();
} }
// join should complete // join should complete
scope.join(); scope.join();
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
} }
} }
/** /**
* Test interrupt of thread blocked in joinUntil. * Test interrupt of thread blocked in joinUntil.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptJoinUntil2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptJoinUntil2(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1);
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofSeconds(3)); latch.await();
return "foo"; return "foo";
}); });
@ -651,18 +678,22 @@ public class StructuredTaskScopeTest {
fail("joinUntil did not throw"); fail("joinUntil did not throw");
} catch (InterruptedException expected) { } catch (InterruptedException expected) {
assertFalse(Thread.interrupted()); // interrupt status should be clear assertFalse(Thread.interrupted()); // interrupt status should be clear
} finally {
// let task continue
latch.countDown();
} }
// join should complete // join should complete
scope.join(); scope.join();
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
} }
} }
/** /**
* Test shutdown after scope is closed. * Test shutdown after scope is closed.
*/ */
public void testShutdownAfterClose() throws Exception { @Test
void testShutdownAfterClose() throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
scope.join(); scope.join();
scope.close(); scope.close();
@ -673,8 +704,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test shutdown is confined to threads in the scope "tree". * Test shutdown is confined to threads in the scope "tree".
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testShutdownConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testShutdownConfined(ThreadFactory factory) throws Exception {
try (var scope1 = new StructuredTaskScope(); try (var scope1 = new StructuredTaskScope();
var scope2 = new StructuredTaskScope()) { var scope2 = new StructuredTaskScope()) {
@ -684,7 +716,7 @@ public class StructuredTaskScopeTest {
scope1.shutdown(); scope1.shutdown();
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future::get); Throwable ex = assertThrows(ExecutionException.class, future::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
} }
@ -693,7 +725,7 @@ public class StructuredTaskScopeTest {
scope2.shutdown(); scope2.shutdown();
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future1::get); Throwable ex = assertThrows(ExecutionException.class, future1::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
// thread in scope2 can shutdown scope1 // thread in scope2 can shutdown scope1
@ -702,7 +734,7 @@ public class StructuredTaskScopeTest {
return null; return null;
}); });
future2.get(); future2.get();
assertTrue(future2.resultNow() == null); assertNull(future2.resultNow());
scope2.join(); scope2.join();
scope1.join(); scope1.join();
@ -712,7 +744,8 @@ public class StructuredTaskScopeTest {
/** /**
* Test close without join, no threads forked. * Test close without join, no threads forked.
*/ */
public void testCloseWithoutJoin1() { @Test
void testCloseWithoutJoin1() {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
// do nothing // do nothing
} }
@ -721,8 +754,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test close without join, threads forked. * Test close without join, threads forked.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCloseWithoutJoin2(ThreadFactory factory) { @MethodSource("factories")
void testCloseWithoutJoin2(ThreadFactory factory) {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
Thread.sleep(Duration.ofDays(1)); Thread.sleep(Duration.ofDays(1));
@ -736,8 +770,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test close with threads forked after join. * Test close with threads forked after join.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCloseWithoutJoin3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCloseWithoutJoin3(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
scope.fork(() -> "foo"); scope.fork(() -> "foo");
scope.join(); scope.join();
@ -754,15 +789,16 @@ public class StructuredTaskScopeTest {
/** /**
* Test close is owner confined. * Test close is owner confined.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCloseConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCloseConfined(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
// attempt to close on thread in scope // attempt to close on thread in scope
Future<Void> future1 = scope.fork(() -> { Future<Void> future1 = scope.fork(() -> {
scope.close(); scope.close();
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future1::get); Throwable ex = assertThrows(ExecutionException.class, future1::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
// random thread cannot close scope // random thread cannot close scope
@ -771,7 +807,7 @@ public class StructuredTaskScopeTest {
scope.close(); scope.close();
return null; return null;
}); });
ex = expectThrows(ExecutionException.class, future2::get); ex = assertThrows(ExecutionException.class, future2::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
} }
@ -782,8 +818,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test close with interrupt status set. * Test close with interrupt status set.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptClose1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptClose1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1); var latch = new CountDownLatch(1);
@ -818,8 +855,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test interrupting thread waiting in close. * Test interrupting thread waiting in close.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptClose2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInterruptClose2(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
var latch = new CountDownLatch(1); var latch = new CountDownLatch(1);
@ -854,7 +892,7 @@ public class StructuredTaskScopeTest {
* nested scope. * nested scope.
*/ */
@Test @Test
public void testStructureViolation1() throws Exception { void testStructureViolation1() throws Exception {
try (var scope1 = new StructuredTaskScope()) { try (var scope1 = new StructuredTaskScope()) {
try (var scope2 = new StructuredTaskScope()) { try (var scope2 = new StructuredTaskScope()) {
@ -881,8 +919,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test Future::get, task completes normally. * Test Future::get, task completes normally.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFuture1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFuture1(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
@ -890,9 +929,9 @@ public class StructuredTaskScopeTest {
return "foo"; return "foo";
}); });
assertEquals(future.get(), "foo"); assertEquals("foo", future.get());
assertTrue(future.state() == Future.State.SUCCESS); assertTrue(future.state() == Future.State.SUCCESS);
assertEquals(future.resultNow(), "foo"); assertEquals("foo", future.resultNow());
scope.join(); scope.join();
} }
@ -901,8 +940,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test Future::get, task completes with exception. * Test Future::get, task completes with exception.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFuture2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFuture2(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
@ -910,7 +950,7 @@ public class StructuredTaskScopeTest {
throw new FooException(); throw new FooException();
}); });
Throwable ex = expectThrows(ExecutionException.class, future::get); Throwable ex = assertThrows(ExecutionException.class, future::get);
assertTrue(ex.getCause() instanceof FooException); assertTrue(ex.getCause() instanceof FooException);
assertTrue(future.state() == Future.State.FAILED); assertTrue(future.state() == Future.State.FAILED);
assertTrue(future.exceptionNow() instanceof FooException); assertTrue(future.exceptionNow() instanceof FooException);
@ -922,8 +962,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test Future::get, task is cancelled. * Test Future::get, task is cancelled.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFuture3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFuture3(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
Future<String> future = scope.fork(() -> { Future<String> future = scope.fork(() -> {
@ -948,8 +989,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test scope shutdown with a thread blocked in Future::get. * Test scope shutdown with a thread blocked in Future::get.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFutureWithShutdown(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFutureWithShutdown(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope(null, factory)) { try (var scope = new StructuredTaskScope(null, factory)) {
// long running task // long running task
@ -985,8 +1027,9 @@ public class StructuredTaskScopeTest {
/** /**
* Test Future::cancel throws if invoked by a thread that is not in the tree. * Test Future::cancel throws if invoked by a thread that is not in the tree.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testFutureCancelConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testFutureCancelConfined(ThreadFactory factory) throws Exception {
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
Future<String> future1 = scope.fork(() -> { Future<String> future1 = scope.fork(() -> {
Thread.sleep(Duration.ofDays(1)); Thread.sleep(Duration.ofDays(1));
@ -999,7 +1042,7 @@ public class StructuredTaskScopeTest {
future1.cancel(true); future1.cancel(true);
return null; return null;
}); });
Throwable ex = expectThrows(ExecutionException.class, future2::get); Throwable ex = assertThrows(ExecutionException.class, future2::get);
assertTrue(ex.getCause() instanceof WrongThreadException); assertTrue(ex.getCause() instanceof WrongThreadException);
} finally { } finally {
future1.cancel(true); future1.cancel(true);
@ -1012,7 +1055,7 @@ public class StructuredTaskScopeTest {
* Test StructuredTaskScope::toString includes the scope name. * Test StructuredTaskScope::toString includes the scope name.
*/ */
@Test @Test
public void testToString() throws Exception { void testToString() throws Exception {
ThreadFactory factory = Thread.ofVirtual().factory(); ThreadFactory factory = Thread.ofVirtual().factory();
try (var scope = new StructuredTaskScope("xxx", factory)) { try (var scope = new StructuredTaskScope("xxx", factory)) {
// open // open
@ -1033,7 +1076,7 @@ public class StructuredTaskScopeTest {
* Test for NullPointerException. * Test for NullPointerException.
*/ */
@Test @Test
public void testNulls() throws Exception { void testNulls() throws Exception {
assertThrows(NullPointerException.class, () -> new StructuredTaskScope("", null)); assertThrows(NullPointerException.class, () -> new StructuredTaskScope("", null));
try (var scope = new StructuredTaskScope()) { try (var scope = new StructuredTaskScope()) {
assertThrows(NullPointerException.class, () -> scope.fork(null)); assertThrows(NullPointerException.class, () -> scope.fork(null));
@ -1059,7 +1102,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnSuccess with no completed tasks. * Test ShutdownOnSuccess with no completed tasks.
*/ */
@Test @Test
public void testShutdownOnSuccess1() throws Exception { void testShutdownOnSuccess1() throws Exception {
try (var scope = new ShutdownOnSuccess<String>()) { try (var scope = new ShutdownOnSuccess<String>()) {
assertThrows(IllegalStateException.class, () -> scope.result()); assertThrows(IllegalStateException.class, () -> scope.result());
assertThrows(IllegalStateException.class, () -> scope.result(e -> null)); assertThrows(IllegalStateException.class, () -> scope.result(e -> null));
@ -1070,7 +1113,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnSuccess with tasks that completed normally. * Test ShutdownOnSuccess with tasks that completed normally.
*/ */
@Test @Test
public void testShutdownOnSuccess2() throws Exception { void testShutdownOnSuccess2() throws Exception {
try (var scope = new ShutdownOnSuccess<String>()) { try (var scope = new ShutdownOnSuccess<String>()) {
// two tasks complete normally // two tasks complete normally
@ -1079,8 +1122,8 @@ public class StructuredTaskScopeTest {
scope.fork(() -> "bar"); scope.fork(() -> "bar");
scope.join(); scope.join();
assertEquals(scope.result(), "foo"); assertEquals("foo", scope.result());
assertEquals(scope.result(e -> null), "foo"); assertEquals("foo", scope.result(e -> null));
} }
} }
@ -1088,7 +1131,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnSuccess with tasks that completed normally and abnormally. * Test ShutdownOnSuccess with tasks that completed normally and abnormally.
*/ */
@Test @Test
public void testShutdownOnSuccess3() throws Exception { void testShutdownOnSuccess3() throws Exception {
try (var scope = new ShutdownOnSuccess<String>()) { try (var scope = new ShutdownOnSuccess<String>()) {
// one task completes normally, the other with an exception // one task completes normally, the other with an exception
@ -1096,8 +1139,8 @@ public class StructuredTaskScopeTest {
scope.fork(() -> { throw new ArithmeticException(); }); scope.fork(() -> { throw new ArithmeticException(); });
scope.join(); scope.join();
assertEquals(scope.result(), "foo"); assertEquals("foo", scope.result());
assertEquals(scope.result(e -> null), "foo"); assertEquals("foo", scope.result(e -> null));
} }
} }
@ -1105,17 +1148,17 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnSuccess with a task that completed with an exception. * Test ShutdownOnSuccess with a task that completed with an exception.
*/ */
@Test @Test
public void testShutdownOnSuccess4() throws Exception { void testShutdownOnSuccess4() throws Exception {
try (var scope = new ShutdownOnSuccess<String>()) { try (var scope = new ShutdownOnSuccess<String>()) {
// tasks completes with exception // tasks completes with exception
scope.fork(() -> { throw new ArithmeticException(); }); scope.fork(() -> { throw new ArithmeticException(); });
scope.join(); scope.join();
Throwable ex = expectThrows(ExecutionException.class, () -> scope.result()); Throwable ex = assertThrows(ExecutionException.class, () -> scope.result());
assertTrue(ex.getCause() instanceof ArithmeticException); assertTrue(ex.getCause() instanceof ArithmeticException);
ex = expectThrows(FooException.class, () -> scope.result(e -> new FooException(e))); ex = assertThrows(FooException.class, () -> scope.result(e -> new FooException(e)));
assertTrue(ex.getCause() instanceof ArithmeticException); assertTrue(ex.getCause() instanceof ArithmeticException);
} }
} }
@ -1124,7 +1167,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnSuccess with a cancelled task. * Test ShutdownOnSuccess with a cancelled task.
*/ */
@Test @Test
public void testShutdownOnSuccess5() throws Exception { void testShutdownOnSuccess5() throws Exception {
try (var scope = new ShutdownOnSuccess<String>()) { try (var scope = new ShutdownOnSuccess<String>()) {
// cancelled task // cancelled task
@ -1137,7 +1180,7 @@ public class StructuredTaskScopeTest {
scope.join(); scope.join();
assertThrows(CancellationException.class, () -> scope.result()); assertThrows(CancellationException.class, () -> scope.result());
Throwable ex = expectThrows(FooException.class, Throwable ex = assertThrows(FooException.class,
() -> scope.result(e -> new FooException(e))); () -> scope.result(e -> new FooException(e)));
assertTrue(ex.getCause() instanceof CancellationException); assertTrue(ex.getCause() instanceof CancellationException);
} }
@ -1147,7 +1190,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnFailure with no completed tasks. * Test ShutdownOnFailure with no completed tasks.
*/ */
@Test @Test
public void testShutdownOnFailure1() throws Throwable { void testShutdownOnFailure1() throws Throwable {
try (var scope = new ShutdownOnFailure()) { try (var scope = new ShutdownOnFailure()) {
assertTrue(scope.exception().isEmpty()); assertTrue(scope.exception().isEmpty());
scope.throwIfFailed(); scope.throwIfFailed();
@ -1159,7 +1202,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnFailure with tasks that completed normally. * Test ShutdownOnFailure with tasks that completed normally.
*/ */
@Test @Test
public void testShutdownOnFailure2() throws Throwable { void testShutdownOnFailure2() throws Throwable {
try (var scope = new ShutdownOnFailure()) { try (var scope = new ShutdownOnFailure()) {
scope.fork(() -> "foo"); scope.fork(() -> "foo");
scope.fork(() -> "bar"); scope.fork(() -> "bar");
@ -1176,7 +1219,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnFailure with tasks that completed normally and abnormally. * Test ShutdownOnFailure with tasks that completed normally and abnormally.
*/ */
@Test @Test
public void testShutdownOnFailure3() throws Throwable { void testShutdownOnFailure3() throws Throwable {
try (var scope = new ShutdownOnFailure()) { try (var scope = new ShutdownOnFailure()) {
// one task completes normally, the other with an exception // one task completes normally, the other with an exception
@ -1187,10 +1230,10 @@ public class StructuredTaskScopeTest {
Throwable ex = scope.exception().orElse(null); Throwable ex = scope.exception().orElse(null);
assertTrue(ex instanceof ArithmeticException); assertTrue(ex instanceof ArithmeticException);
ex = expectThrows(ExecutionException.class, () -> scope.throwIfFailed()); ex = assertThrows(ExecutionException.class, () -> scope.throwIfFailed());
assertTrue(ex.getCause() instanceof ArithmeticException); assertTrue(ex.getCause() instanceof ArithmeticException);
ex = expectThrows(FooException.class, ex = assertThrows(FooException.class,
() -> scope.throwIfFailed(e -> new FooException(e))); () -> scope.throwIfFailed(e -> new FooException(e)));
assertTrue(ex.getCause() instanceof ArithmeticException); assertTrue(ex.getCause() instanceof ArithmeticException);
} }
@ -1200,7 +1243,7 @@ public class StructuredTaskScopeTest {
* Test ShutdownOnFailure with a cancelled task. * Test ShutdownOnFailure with a cancelled task.
*/ */
@Test @Test
public void testShutdownOnFailure4() throws Throwable { void testShutdownOnFailure4() throws Throwable {
try (var scope = new ShutdownOnFailure()) { try (var scope = new ShutdownOnFailure()) {
var future = scope.fork(() -> { var future = scope.fork(() -> {
@ -1216,7 +1259,7 @@ public class StructuredTaskScopeTest {
assertThrows(CancellationException.class, () -> scope.throwIfFailed()); assertThrows(CancellationException.class, () -> scope.throwIfFailed());
ex = expectThrows(FooException.class, ex = assertThrows(FooException.class,
() -> scope.throwIfFailed(e -> new FooException(e))); () -> scope.throwIfFailed(e -> new FooException(e)));
assertTrue(ex.getCause() instanceof CancellationException); assertTrue(ex.getCause() instanceof CancellationException);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,7 @@
* @enablePreview * @enablePreview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @library /test/lib * @library /test/lib
* @run testng/othervm StructuredThreadDumpTest * @run junit/othervm StructuredThreadDumpTest
*/ */
import jdk.incubator.concurrent.StructuredTaskScope; import jdk.incubator.concurrent.StructuredTaskScope;
@ -43,17 +43,17 @@ import java.util.stream.Stream;
import com.sun.management.HotSpotDiagnosticMXBean; import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat; import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat;
import jdk.test.lib.threaddump.ThreadDump; import jdk.test.lib.threaddump.ThreadDump;
import org.testng.annotations.Test; import org.junit.jupiter.api.Test;
import static org.testng.Assert.*; import static org.junit.jupiter.api.Assertions.*;
public class StructuredThreadDumpTest { class StructuredThreadDumpTest {
/** /**
* Test that a thread dump with a tree of task scopes contains a thread grouping for * Test that a thread dump with a tree of task scopes contains a thread grouping for
* each task scope. * each task scope.
*/ */
@Test @Test
public void testTree() throws Exception { void testTree() throws Exception {
ThreadFactory factory = Thread.ofVirtual().factory(); ThreadFactory factory = Thread.ofVirtual().factory();
try (var scope = new StructuredTaskScope<>("scope", factory)) { try (var scope = new StructuredTaskScope<>("scope", factory)) {
Thread thread1 = fork(scope, "child-scope-A"); Thread thread1 = fork(scope, "child-scope-A");
@ -95,7 +95,7 @@ public class StructuredThreadDumpTest {
* each task scope. * each task scope.
*/ */
@Test @Test
public void testNested() throws Exception { void testNested() throws Exception {
ThreadFactory factory = Thread.ofVirtual().factory(); ThreadFactory factory = Thread.ofVirtual().factory();
try (var scope1 = new StructuredTaskScope<>("scope-A", factory)) { try (var scope1 = new StructuredTaskScope<>("scope-A", factory)) {
Thread thread1 = fork(scope1); Thread thread1 = fork(scope1);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
* @summary Basic tests for StructuredTaskScope with scoped values * @summary Basic tests for StructuredTaskScope with scoped values
* @enablePreview * @enablePreview
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng WithScopedValue * @run junit WithScopedValue
*/ */
import jdk.incubator.concurrent.ScopedValue; import jdk.incubator.concurrent.ScopedValue;
@ -35,27 +35,25 @@ import jdk.incubator.concurrent.StructureViolationException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import static org.testng.Assert.*; import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
@Test class WithScopedValue {
public class WithScopedValue {
@DataProvider private static Stream<ThreadFactory> factories() {
public Object[][] factories() { return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
return new Object[][] {
{ Thread.ofPlatform().factory() },
{ Thread.ofVirtual().factory() },
};
} }
/** /**
* Test that fork inherits a scoped value into a child thread. * Test that fork inherits a scoped value into a child thread.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
String value = ScopedValue.where(name, "x", () -> { String value = ScopedValue.where(name, "x", () -> {
try (var scope = new StructuredTaskScope<String>(null, factory)) { try (var scope = new StructuredTaskScope<String>(null, factory)) {
@ -72,8 +70,9 @@ public class WithScopedValue {
/** /**
* Test that fork inherits a scoped value into a grandchild thread. * Test that fork inherits a scoped value into a grandchild thread.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
String value = ScopedValue.where(name, "x", () -> { String value = ScopedValue.where(name, "x", () -> {
try (var scope1 = new StructuredTaskScope<String>(null, factory)) { try (var scope1 = new StructuredTaskScope<String>(null, factory)) {
@ -96,8 +95,9 @@ public class WithScopedValue {
/** /**
* Test that fork inherits a rebound scoped value into a grandchild thread. * Test that fork inherits a rebound scoped value into a grandchild thread.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testForkInheritsScopedValue3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testForkInheritsScopedValue3(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
String value = ScopedValue.where(name, "x", () -> { String value = ScopedValue.where(name, "x", () -> {
try (var scope1 = new StructuredTaskScope<String>(null, factory)) { try (var scope1 = new StructuredTaskScope<String>(null, factory)) {
@ -128,7 +128,8 @@ public class WithScopedValue {
/** /**
* Test exiting a dynamic scope with an open task scope. * Test exiting a dynamic scope with an open task scope.
*/ */
public void testStructureViolation1() throws Exception { @Test
void testStructureViolation1() throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
class Box { class Box {
StructuredTaskScope<Object> scope; StructuredTaskScope<Object> scope;
@ -164,7 +165,8 @@ public class WithScopedValue {
/** /**
* Test closing a StructuredTaskScope while executing in a dynamic scope. * Test closing a StructuredTaskScope while executing in a dynamic scope.
*/ */
public void testStructureViolation2() throws Exception { @Test
void testStructureViolation2() throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var scope = new StructuredTaskScope<String>()) { try (var scope = new StructuredTaskScope<String>()) {
ScopedValue.where(name, "x", () -> { ScopedValue.where(name, "x", () -> {
@ -176,7 +178,8 @@ public class WithScopedValue {
/** /**
* Test fork when a scoped value is bound after a StructuredTaskScope is created. * Test fork when a scoped value is bound after a StructuredTaskScope is created.
*/ */
public void testStructureViolation3() throws Exception { @Test
void testStructureViolation3() throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var scope = new StructuredTaskScope<String>()) { try (var scope = new StructuredTaskScope<String>()) {
ScopedValue.where(name, "x", () -> { ScopedValue.where(name, "x", () -> {
@ -189,7 +192,8 @@ public class WithScopedValue {
/** /**
* Test fork when a scoped value is re-bound after a StructuredTaskScope is created. * Test fork when a scoped value is re-bound after a StructuredTaskScope is created.
*/ */
public void testStructureViolation4() throws Exception { @Test
void testStructureViolation4() throws Exception {
ScopedValue<String> name1 = ScopedValue.newInstance(); ScopedValue<String> name1 = ScopedValue.newInstance();
ScopedValue<String> name2 = ScopedValue.newInstance(); ScopedValue<String> name2 = ScopedValue.newInstance();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,14 +26,14 @@
* @summary Basic tests for ThreadFlock * @summary Basic tests for ThreadFlock
* @modules java.base/jdk.internal.misc * @modules java.base/jdk.internal.misc
* @enablePreview * @enablePreview
* @run testng/othervm -DthreadFactory=platform ThreadFlockTest * @run junit/othervm -DthreadFactory=platform ThreadFlockTest
*/ */
/* /*
* @test id=virtual * @test id=virtual
* @modules java.base/jdk.internal.misc * @modules java.base/jdk.internal.misc
* @enablePreview * @enablePreview
* @run testng/othervm -DthreadFactory=virtual ThreadFlockTest * @run junit/othervm -DthreadFactory=virtual ThreadFlockTest
*/ */
import java.time.Duration; import java.time.Duration;
@ -43,26 +43,23 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.misc.ThreadFlock; import jdk.internal.misc.ThreadFlock;
import org.testng.annotations.AfterClass; import org.junit.jupiter.api.Test;
import org.testng.annotations.BeforeClass; import org.junit.jupiter.api.BeforeAll;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.AfterAll;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import static org.testng.Assert.*; import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
public class ThreadFlockTest { class ThreadFlockTest {
private ScheduledExecutorService scheduler; private static ScheduledExecutorService scheduler;
private Object[][] threadFactories; private static List<ThreadFactory> threadFactories;
@BeforeClass @BeforeAll
public void setUp() throws Exception { static void setup() throws Exception {
ThreadFactory factory = (task) -> { scheduler = Executors.newSingleThreadScheduledExecutor();
Thread thread = new Thread(task);
thread.setDaemon(true);
return thread;
};
this.scheduler = Executors.newSingleThreadScheduledExecutor(factory);
// thread factories // thread factories
String value = System.getProperty("threadFactory"); String value = System.getProperty("threadFactory");
@ -72,35 +69,32 @@ public class ThreadFlockTest {
if (value == null || value.equals("virtual")) if (value == null || value.equals("virtual"))
list.add(Thread.ofVirtual().factory()); list.add(Thread.ofVirtual().factory());
assertTrue(list.size() > 0, "No thread factories for tests"); assertTrue(list.size() > 0, "No thread factories for tests");
this.threadFactories = list.stream() threadFactories = list;
.map(f -> new Object[] { f })
.toArray(Object[][]::new);
} }
@AfterClass @AfterAll
public void tearDown() { static void shutdown() {
scheduler.shutdown(); scheduler.shutdown();
} }
@DataProvider(name = "factories") private static Stream<ThreadFactory> factories() {
public Object[][] factories() { return threadFactories.stream();
return threadFactories;
} }
/** /**
* Test ThreadFlock::name. * Test ThreadFlock::name.
*/ */
@Test @Test
public void testName() { void testName() {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
assertEquals(flock.name(), null); assertNull(flock.name());
flock.close(); flock.close();
assertEquals(flock.name(), null); // after close assertNull(flock.name()); // after close
} }
try (var flock = ThreadFlock.open("fetcher")) { try (var flock = ThreadFlock.open("fetcher")) {
assertEquals(flock.name(), "fetcher"); assertEquals("fetcher", flock.name());
flock.close(); flock.close();
assertEquals(flock.name(), "fetcher"); // after close assertEquals("fetcher", flock.name()); // after close
} }
} }
@ -108,7 +102,7 @@ public class ThreadFlockTest {
* Test ThreadFlock::owner. * Test ThreadFlock::owner.
*/ */
@Test @Test
public void testOwner() { void testOwner() {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
assertTrue(flock.owner() == Thread.currentThread()); assertTrue(flock.owner() == Thread.currentThread());
flock.close(); flock.close();
@ -120,7 +114,7 @@ public class ThreadFlockTest {
* Test ThreadFlock::isXXXX methods. * Test ThreadFlock::isXXXX methods.
*/ */
@Test @Test
public void testState() { void testState() {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
assertFalse(flock.isShutdown()); assertFalse(flock.isShutdown());
assertFalse(flock.isClosed()); assertFalse(flock.isClosed());
@ -141,8 +135,9 @@ public class ThreadFlockTest {
/** /**
* Test ThreadFlock::threads enumerates all threads. * Test ThreadFlock::threads enumerates all threads.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testThreads(ThreadFactory factory) { @MethodSource("factories")
void testThreads(ThreadFactory factory) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable awaitLatch = () -> { Runnable awaitLatch = () -> {
@ -166,21 +161,22 @@ public class ThreadFlockTest {
} }
// check thread ThreadFlock::threads enumerates all threads // check thread ThreadFlock::threads enumerates all threads
assertEquals(threads, flock.threads().collect(Collectors.toSet())); assertEquals(flock.threads().collect(Collectors.toSet()), threads);
} finally { } finally {
latch.countDown(); // release threads latch.countDown(); // release threads
flock.close(); flock.close();
} }
assertTrue(flock.threads().count() == 0); assertTrue(flock.threads().count() == 0);
assertTrue(exception.get() == null); assertNull(exception.get());
} }
/** /**
* Test ThreadFlock::containsThread with nested flocks. * Test ThreadFlock::containsThread with nested flocks.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testContainsThread1(ThreadFactory factory) { @MethodSource("factories")
void testContainsThread1(ThreadFactory factory) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
@ -222,8 +218,9 @@ public class ThreadFlockTest {
/** /**
* Test ThreadFlock::containsThread with a tree of flocks. * Test ThreadFlock::containsThread with a tree of flocks.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testContainsThread2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testContainsThread2(ThreadFactory factory) throws Exception {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
@ -276,8 +273,9 @@ public class ThreadFlockTest {
/** /**
* Test that start causes a thread to execute. * Test that start causes a thread to execute.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStart(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testStart(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
AtomicBoolean executed = new AtomicBoolean(); AtomicBoolean executed = new AtomicBoolean();
Thread thread = factory.newThread(() -> executed.set(true)); Thread thread = factory.newThread(() -> executed.set(true));
@ -290,44 +288,48 @@ public class ThreadFlockTest {
/** /**
* Test that start throws IllegalStateException when shutdown * Test that start throws IllegalStateException when shutdown
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStartAfterShutdown(ThreadFactory factory) { @MethodSource("factories")
void testStartAfterShutdown(ThreadFactory factory) {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
flock.shutdown(); flock.shutdown();
Thread thread = factory.newThread(() -> { }); Thread thread = factory.newThread(() -> { });
expectThrows(IllegalStateException.class, () -> flock.start(thread)); assertThrows(IllegalStateException.class, () -> flock.start(thread));
} }
} }
/** /**
* Test that start throws IllegalStateException when closed * Test that start throws IllegalStateException when closed
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStartAfterClose(ThreadFactory factory) { @MethodSource("factories")
void testStartAfterClose(ThreadFactory factory) {
var flock = ThreadFlock.open(null); var flock = ThreadFlock.open(null);
flock.close();; flock.close();;
Thread thread = factory.newThread(() -> { }); Thread thread = factory.newThread(() -> { });
expectThrows(IllegalStateException.class, () -> flock.start(thread)); assertThrows(IllegalStateException.class, () -> flock.start(thread));
} }
/** /**
* Test that start throws IllegalThreadStateException when invoked to * Test that start throws IllegalThreadStateException when invoked to
* start a thread that has already started. * start a thread that has already started.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStartAfterStarted(ThreadFactory factory) { @MethodSource("factories")
void testStartAfterStarted(ThreadFactory factory) {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
Thread thread = factory.newThread(() -> { }); Thread thread = factory.newThread(() -> { });
flock.start(thread); flock.start(thread);
expectThrows(IllegalThreadStateException.class, () -> flock.start(thread)); assertThrows(IllegalThreadStateException.class, () -> flock.start(thread));
} }
} }
/** /**
* Test start is confined to threads in the flock. * Test start is confined to threads in the flock.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStartConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testStartConfined(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
// thread in flock // thread in flock
testStartConfined(flock, task -> { testStartConfined(flock, task -> {
@ -370,7 +372,7 @@ public class ThreadFlockTest {
thread.join(); thread.join();
Throwable cause = exception.get(); Throwable cause = exception.get();
if (flock.containsThread(thread)) { if (flock.containsThread(thread)) {
assertTrue(cause == null); assertNull(cause);
} else { } else {
assertTrue(cause instanceof WrongThreadException); assertTrue(cause instanceof WrongThreadException);
} }
@ -380,7 +382,7 @@ public class ThreadFlockTest {
* Test awaitAll with no threads. * Test awaitAll with no threads.
*/ */
@Test @Test
public void testAwaitAllWithNoThreads() throws Exception { void testAwaitAllWithNoThreads() throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
assertTrue(flock.awaitAll()); assertTrue(flock.awaitAll());
assertTrue(flock.awaitAll(Duration.ofSeconds(1))); assertTrue(flock.awaitAll(Duration.ofSeconds(1)));
@ -390,8 +392,9 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with threads running. * Test awaitAll with threads running.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllWithThreads(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllWithThreads(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
AtomicBoolean done = new AtomicBoolean(); AtomicBoolean done = new AtomicBoolean();
Runnable task = () -> { Runnable task = () -> {
@ -410,8 +413,9 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with timeout, threads finish before timeout expires. * Test awaitAll with timeout, threads finish before timeout expires.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllWithTimeout1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllWithTimeout1(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
Runnable task = () -> { Runnable task = () -> {
try { try {
@ -431,12 +435,15 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with timeout, timeout expires before threads finish. * Test awaitAll with timeout, timeout expires before threads finish.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllWithTimeout2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllWithTimeout2(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
var latch = new CountDownLatch(1);
Runnable task = () -> { Runnable task = () -> {
try { try {
Thread.sleep(Duration.ofSeconds(30)); latch.await();
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
}; };
Thread thread = factory.newThread(task); Thread thread = factory.newThread(task);
@ -451,7 +458,7 @@ public class ThreadFlockTest {
checkDuration(startMillis, 1900, 4000); checkDuration(startMillis, 1900, 4000);
} }
} finally { } finally {
thread.interrupt(); latch.countDown();
} }
} }
} }
@ -459,12 +466,15 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with timeout many times. * Test awaitAll with timeout many times.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllWithTimeout3(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllWithTimeout3(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
var latch = new CountDownLatch(1);
Runnable task = () -> { Runnable task = () -> {
try { try {
Thread.sleep(Duration.ofSeconds(30)); latch.await();
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
}; };
Thread thread = factory.newThread(task); Thread thread = factory.newThread(task);
@ -478,7 +488,7 @@ public class ThreadFlockTest {
} catch (TimeoutException expected) { } } catch (TimeoutException expected) { }
} }
} finally { } finally {
thread.interrupt(); latch.countDown();
} }
boolean done = flock.awaitAll(); boolean done = flock.awaitAll();
@ -489,12 +499,15 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with a 0 or negative timeout. * Test awaitAll with a 0 or negative timeout.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllWithTimeout4(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllWithTimeout4(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
var latch = new CountDownLatch(1);
Runnable task = () -> { Runnable task = () -> {
try { try {
Thread.sleep(Duration.ofSeconds(30)); latch.await();
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
}; };
Thread thread = factory.newThread(task); Thread thread = factory.newThread(task);
@ -510,7 +523,7 @@ public class ThreadFlockTest {
fail("awaitAll did not throw"); fail("awaitAll did not throw");
} catch (TimeoutException expected) { } } catch (TimeoutException expected) { }
} finally { } finally {
thread.interrupt(); latch.countDown();
} }
boolean done = flock.awaitAll(); boolean done = flock.awaitAll();
@ -521,8 +534,9 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with interrupt status set, should interrupt thread. * Test awaitAll with interrupt status set, should interrupt thread.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptAwaitAll1(ThreadFactory factory) { @MethodSource("factories")
void testInterruptAwaitAll1(ThreadFactory factory) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable awaitLatch = () -> { Runnable awaitLatch = () -> {
@ -568,14 +582,15 @@ public class ThreadFlockTest {
} }
// thread should not have throw any exception // thread should not have throw any exception
assertTrue(exception.get() == null); assertNull(exception.get());
} }
/** /**
* Test interrupt of awaitAll. * Test interrupt of awaitAll.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptAwaitAll2(ThreadFactory factory) { @MethodSource("factories")
void testInterruptAwaitAll2(ThreadFactory factory) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable awaitLatch = () -> { Runnable awaitLatch = () -> {
@ -619,14 +634,14 @@ public class ThreadFlockTest {
} }
// thread should not have throw any exception // thread should not have throw any exception
assertTrue(exception.get() == null); assertNull(exception.get());
} }
/** /**
* Test awaitAll after close. * Test awaitAll after close.
*/ */
@Test @Test
public void testAwaitAfterClose() throws Exception { void testAwaitAfterClose() throws Exception {
var flock = ThreadFlock.open(null); var flock = ThreadFlock.open(null);
flock.close(); flock.close();
assertTrue(flock.awaitAll()); assertTrue(flock.awaitAll());
@ -636,8 +651,9 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll is flock confined. * Test awaitAll is flock confined.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testAwaitAllConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testAwaitAllConfined(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
// thread in flock // thread in flock
testAwaitAllConfined(flock, task -> { testAwaitAllConfined(flock, task -> {
@ -676,8 +692,9 @@ public class ThreadFlockTest {
/** /**
* Test awaitAll with the wakeup permit. * Test awaitAll with the wakeup permit.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testWakeupAwaitAll1(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testWakeupAwaitAll1(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
@ -704,8 +721,9 @@ public class ThreadFlockTest {
/** /**
* Schedule a thread to wakeup the owner waiting in awaitAll. * Schedule a thread to wakeup the owner waiting in awaitAll.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testWakeupAwaitAll2(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testWakeupAwaitAll2(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
@ -737,8 +755,9 @@ public class ThreadFlockTest {
/** /**
* Test wakeup is flock confined. * Test wakeup is flock confined.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testWakeupConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testWakeupConfined(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
// thread in flock // thread in flock
testWakeupConfined(flock, task -> { testWakeupConfined(flock, task -> {
@ -772,7 +791,7 @@ public class ThreadFlockTest {
thread.join(); thread.join();
Throwable cause = exception.get(); Throwable cause = exception.get();
if (flock.containsThread(thread)) { if (flock.containsThread(thread)) {
assertTrue(cause == null); assertNull(cause);
} else { } else {
assertTrue(cause instanceof WrongThreadException); assertTrue(cause instanceof WrongThreadException);
} }
@ -782,7 +801,7 @@ public class ThreadFlockTest {
* Test close with no threads running. * Test close with no threads running.
*/ */
@Test @Test
public void testCloseWithNoThreads() { void testCloseWithNoThreads() {
var flock = ThreadFlock.open(null); var flock = ThreadFlock.open(null);
flock.close(); flock.close();
assertTrue(flock.isClosed()); assertTrue(flock.isClosed());
@ -792,8 +811,9 @@ public class ThreadFlockTest {
/** /**
* Test close with threads running. * Test close with threads running.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCloseWithThreads(ThreadFactory factory) { @MethodSource("factories")
void testCloseWithThreads(ThreadFactory factory) {
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable sleepTask = () -> { Runnable sleepTask = () -> {
try { try {
@ -811,14 +831,14 @@ public class ThreadFlockTest {
} }
assertTrue(flock.isClosed()); assertTrue(flock.isClosed());
assertTrue(flock.threads().count() == 0); assertTrue(flock.threads().count() == 0);
assertTrue(exception.get() == null); // no exception thrown assertNull(exception.get()); // no exception thrown
} }
/** /**
* Test close after flock is closed. * Test close after flock is closed.
*/ */
@Test @Test
public void testCloseAfterClose() { void testCloseAfterClose() {
var flock = ThreadFlock.open(null); var flock = ThreadFlock.open(null);
flock.close(); flock.close();
assertTrue(flock.isClosed()); assertTrue(flock.isClosed());
@ -829,8 +849,9 @@ public class ThreadFlockTest {
/** /**
* Test close is owner confined. * Test close is owner confined.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testCloseConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testCloseConfined(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
// thread in flock // thread in flock
testCloseConfined(flock, task -> { testCloseConfined(flock, task -> {
@ -869,8 +890,9 @@ public class ThreadFlockTest {
/** /**
* Test close with interrupt status set, should not interrupt threads. * Test close with interrupt status set, should not interrupt threads.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptClose1(ThreadFactory factory) { @MethodSource("factories")
void testInterruptClose1(ThreadFactory factory) {
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable sleepTask = () -> { Runnable sleepTask = () -> {
try { try {
@ -886,14 +908,15 @@ public class ThreadFlockTest {
} finally { } finally {
assertTrue(Thread.interrupted()); // clear interrupt assertTrue(Thread.interrupted()); // clear interrupt
} }
assertTrue(exception.get() == null); assertNull(exception.get());
} }
/** /**
* Test interrupt thread block in close. * Test interrupt thread block in close.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInterruptClose2(ThreadFactory factory) { @MethodSource("factories")
void testInterruptClose2(ThreadFactory factory) {
var exception = new AtomicReference<Exception>(); var exception = new AtomicReference<Exception>();
Runnable sleepTask = () -> { Runnable sleepTask = () -> {
try { try {
@ -909,14 +932,15 @@ public class ThreadFlockTest {
} finally { } finally {
assertTrue(Thread.interrupted()); // clear interrupt assertTrue(Thread.interrupted()); // clear interrupt
} }
assertTrue(exception.get() == null); assertNull(exception.get());
} }
/** /**
* Test shutdown is confined to threads in the flock. * Test shutdown is confined to threads in the flock.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testShutdownConfined(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testShutdownConfined(ThreadFactory factory) throws Exception {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
// thread in flock // thread in flock
testShutdownConfined(flock, task -> { testShutdownConfined(flock, task -> {
@ -958,7 +982,7 @@ public class ThreadFlockTest {
thread.join(); thread.join();
Throwable cause = exception.get(); Throwable cause = exception.get();
if (flock.containsThread(thread)) { if (flock.containsThread(thread)) {
assertTrue(cause == null); assertNull(cause);
} else { } else {
assertTrue(cause instanceof WrongThreadException); assertTrue(cause instanceof WrongThreadException);
} }
@ -968,7 +992,7 @@ public class ThreadFlockTest {
* Test that closing an enclosing thread flock closes a nested thread flocks. * Test that closing an enclosing thread flock closes a nested thread flocks.
*/ */
@Test @Test
public void testStructureViolation() { void testStructureViolation() {
try (var flock1 = ThreadFlock.open("flock1")) { try (var flock1 = ThreadFlock.open("flock1")) {
try (var flock2 = ThreadFlock.open("flock2")) { try (var flock2 = ThreadFlock.open("flock2")) {
try { try {
@ -986,8 +1010,9 @@ public class ThreadFlockTest {
/** /**
* Test Thread exiting with an open flock. The exiting thread should close the flock. * Test Thread exiting with an open flock. The exiting thread should close the flock.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testThreadExitWithOpenFlock(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testThreadExitWithOpenFlock(ThreadFactory factory) throws Exception {
var flockRef = new AtomicReference<ThreadFlock>(); var flockRef = new AtomicReference<ThreadFlock>();
var childRef = new AtomicReference<Thread>(); var childRef = new AtomicReference<Thread>();
@ -1017,7 +1042,7 @@ public class ThreadFlockTest {
* Test toString includes the flock name. * Test toString includes the flock name.
*/ */
@Test @Test
public void testToString() { void testToString() {
try (var flock = ThreadFlock.open("xxxx")) { try (var flock = ThreadFlock.open("xxxx")) {
assertTrue(flock.toString().contains("xxx")); assertTrue(flock.toString().contains("xxx"));
} }
@ -1027,11 +1052,11 @@ public class ThreadFlockTest {
* Test for NullPointerException. * Test for NullPointerException.
*/ */
@Test @Test
public void testNulls() { void testNulls() {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
expectThrows(NullPointerException.class, () -> flock.start(null)); assertThrows(NullPointerException.class, () -> flock.start(null));
expectThrows(NullPointerException.class, () -> flock.awaitAll(null)); assertThrows(NullPointerException.class, () -> flock.awaitAll(null));
expectThrows(NullPointerException.class, () -> flock.containsThread(null)); assertThrows(NullPointerException.class, () -> flock.containsThread(null));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,38 +27,33 @@
* @enablePreview * @enablePreview
* @modules java.base/jdk.internal.misc * @modules java.base/jdk.internal.misc
* @modules jdk.incubator.concurrent * @modules jdk.incubator.concurrent
* @run testng WithScopedValue * @run junit WithScopedValue
*/ */
import jdk.internal.misc.ThreadFlock; import jdk.internal.misc.ThreadFlock;
import jdk.incubator.concurrent.ScopedValue; import jdk.incubator.concurrent.ScopedValue;
import jdk.incubator.concurrent.StructureViolationException; import jdk.incubator.concurrent.StructureViolationException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import org.testng.annotations.DataProvider; import org.junit.jupiter.api.Test;
import org.testng.annotations.Test; import org.junit.jupiter.params.ParameterizedTest;
import static org.testng.Assert.*; import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
@Test class WithScopedValue {
public class WithScopedValue {
@DataProvider(name = "factories") private static Stream<ThreadFactory> factories() {
public Object[][] factories() { return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
var defaultThreadFactory = Executors.defaultThreadFactory();
var virtualThreadFactory = Thread.ofVirtual().factory();
return new Object[][]{
{ defaultThreadFactory, },
{ virtualThreadFactory, },
};
} }
/** /**
* Test inheritance of a scoped value. * Test inheritance of a scoped value.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testInheritsScopedValue(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testInheritsScopedValue(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
String value = ScopedValue.where(name, "duke", () -> { String value = ScopedValue.where(name, "duke", () -> {
var result = new AtomicReference<String>(); var result = new AtomicReference<String>();
@ -71,13 +66,14 @@ public class WithScopedValue {
} }
return result.get(); return result.get();
}); });
assertEquals(value, "duke"); assertEquals("duke", value);
} }
/** /**
* Test exiting a dynamic scope with open thread flocks. * Test exiting a dynamic scope with open thread flocks.
*/ */
public void testStructureViolation1() { @Test
void testStructureViolation1() {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
class Box { class Box {
ThreadFlock flock1; ThreadFlock flock1;
@ -99,7 +95,8 @@ public class WithScopedValue {
* Test closing a thread flock while in a dynamic scope and with enclosing thread * Test closing a thread flock while in a dynamic scope and with enclosing thread
* flocks. This test closes enclosing flock1. * flocks. This test closes enclosing flock1.
*/ */
public void testStructureViolation2() { @Test
void testStructureViolation2() {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) { try (var flock1 = ThreadFlock.open("flock1")) {
ScopedValue.where(name, "x1", () -> { ScopedValue.where(name, "x1", () -> {
@ -130,7 +127,8 @@ public class WithScopedValue {
* Test closing a thread flock while in a dynamic scope and with enclosing thread * Test closing a thread flock while in a dynamic scope and with enclosing thread
* flocks. This test closes enclosing flock2. * flocks. This test closes enclosing flock2.
*/ */
public void testStructureViolation3() { @Test
void testStructureViolation3() {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) { try (var flock1 = ThreadFlock.open("flock1")) {
ScopedValue.where(name, "x1", () -> { ScopedValue.where(name, "x1", () -> {
@ -161,7 +159,8 @@ public class WithScopedValue {
* Test closing a thread flock while in a dynamic scope and with enclosing thread * Test closing a thread flock while in a dynamic scope and with enclosing thread
* flocks. This test closes enclosing flock3. * flocks. This test closes enclosing flock3.
*/ */
public void testStructureViolation4() { @Test
void testStructureViolation4() {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var flock1 = ThreadFlock.open("flock1")) { try (var flock1 = ThreadFlock.open("flock1")) {
ScopedValue.where(name, "x1", () -> { ScopedValue.where(name, "x1", () -> {
@ -191,13 +190,14 @@ public class WithScopedValue {
/** /**
* Test start when a scoped value is bound after a thread flock is created. * Test start when a scoped value is bound after a thread flock is created.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStructureViolation5(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testStructureViolation5(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
Thread thread = factory.newThread(() -> { }); Thread thread = factory.newThread(() -> { });
expectThrows(StructureViolationException.class, () -> flock.start(thread)); assertThrows(StructureViolationException.class, () -> flock.start(thread));
}); });
} }
} }
@ -205,14 +205,15 @@ public class WithScopedValue {
/** /**
* Test start when a scoped value is re-bound after a thread flock is created. * Test start when a scoped value is re-bound after a thread flock is created.
*/ */
@Test(dataProvider = "factories") @ParameterizedTest
public void testStructureViolation6(ThreadFactory factory) throws Exception { @MethodSource("factories")
void testStructureViolation6(ThreadFactory factory) throws Exception {
ScopedValue<String> name = ScopedValue.newInstance(); ScopedValue<String> name = ScopedValue.newInstance();
ScopedValue.where(name, "duke", () -> { ScopedValue.where(name, "duke", () -> {
try (var flock = ThreadFlock.open(null)) { try (var flock = ThreadFlock.open(null)) {
ScopedValue.where(name, "duchess", () -> { ScopedValue.where(name, "duchess", () -> {
Thread thread = factory.newThread(() -> { }); Thread thread = factory.newThread(() -> { });
expectThrows(StructureViolationException.class, () -> flock.start(thread)); assertThrows(StructureViolationException.class, () -> flock.start(thread));
}); });
} }
}); });