Skip to content

Commit

Permalink
7903373: Add ability to customize test execution using main wrapper p…
Browse files Browse the repository at this point in the history
…lugin

Reviewed-by: jjg
  • Loading branch information
lmesnik authored and jonathan-gibbons committed Mar 4, 2023
1 parent 2f5f269 commit 5b9e661
Show file tree
Hide file tree
Showing 17 changed files with 414 additions and 32 deletions.
15 changes: 8 additions & 7 deletions CHANGELOG.md
Expand Up @@ -16,20 +16,23 @@

* Fix incorrect format for version in error message [CODETOOLS-7903398](https://bugs.openjdk.org/browse/CODETOOLS-7903398)

* Add options -testThreadFactory and -testThreadFactoryPath to allow
the use of a custom thread factory, to be used to create the thread to run a test.
* [CODETOOLS-7903373](https://bugs.openjdk.org/browse/CODETOOLS-79033734)

## [7.1.1+1](https://git.openjdk.org/jtreg/compare/jtreg-7.1+1...jtreg-7.1.1+1)

* Summary reporter getter is now thread-safe.
* [CODETOOLS-7903390](https://bugs.openjdk.org/browse/CODETOOLS-7903390)


## [7.1+1](https://git.openjdk.org/jtreg/compare/jtreg-7+1...jtreg-7.1+1)

* Improved support for JUnit Jupiter.
* Avoid using TestNG mixed mode.
* Avoid using TestNG mixed mode.
[CODETOOLS-7903264](https://bugs.openjdk.org/browse/CODETOOLS-7903264)
* Support JUnit tests in a system module.
* Support JUnit tests in a system module.
[CODETOOLS-7903260](https://bugs.openjdk.org/browse/CODETOOLS-7903260)
* Support executing a single method.
* Support executing a single method.
[CODETOOLS-7903267](https://bugs.openjdk.org/browse/CODETOOLS-7903267)
* Improve per-class reporting of JUnit tests, in `.jtr` file.
[CODETOOLS-7903324](https://bugs.openjdk.org/browse/CODETOOLS-7903324)
Expand Down Expand Up @@ -120,7 +123,7 @@


* Add support for `Automatic-Module-Name` in jar files.

* Update versions of jtreg dependencies.
* [CODETOOLS-7902791](https://bugs.openjdk.org/browse/CODETOOLS-7902791)

Expand Down Expand Up @@ -194,5 +197,3 @@

* Introduce `test.file`.
* [CODETOOLS-7902545](https://bugs.openjdk.org/browse/CODETOOLS-7902545)


14 changes: 12 additions & 2 deletions src/share/classes/com/sun/javatest/regtest/agent/AgentServer.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -83,6 +83,8 @@ public static void main(String... args) {
public static final String HOST = "-host";
public static final String PORT = "-port";
public static final String TIMEOUTFACTOR = "-timeoutFactor";
public static final String CUSTOM_TEST_THREAD_FACTORY = "-testThreadFactory";
public static final String CUSTOM_TEST_THREAD_FACTORY_PATH = "-testThreadFactoryPath";

public static final byte DO_COMPILE = 1;
public static final byte DO_MAIN = 2;
Expand Down Expand Up @@ -144,6 +146,8 @@ public void run() {
}

private float timeoutFactor = 1.0f;
private String testThreadFactory;
private String testThreadFactoryPath;

public AgentServer(String... args) throws IOException {
if (traceServer) {
Expand Down Expand Up @@ -173,7 +177,11 @@ public AgentServer(String... args) throws IOException {
host = InetAddress.getByName(args[++i]);
} else if (arg.equals(TIMEOUTFACTOR) && i + 1 < args.length) {
timeoutFactor = Float.valueOf(args[++i]);
} else {
} else if (arg.equals(CUSTOM_TEST_THREAD_FACTORY) && i + 1 < args.length) {
testThreadFactory = args[++i];
} else if (arg.equals(CUSTOM_TEST_THREAD_FACTORY_PATH) && i + 1 < args.length) {
testThreadFactoryPath = args[++i];
} else {
throw new IllegalArgumentException(arg);
}
}
Expand Down Expand Up @@ -303,6 +311,8 @@ private void doMain() throws IOException {
.classArgs(classArgs)
.timeout(0)
.timeoutFactor(timeoutFactor)
.testThreadFactory(testThreadFactory)
.testThreadFactoryPath(testThreadFactoryPath)
.outputHandler(this)
.runClass();
writeStatus(status);
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -57,6 +57,8 @@ public class MainActionHelper extends ActionHelper {
private List<String> classArgs;
private int timeout;
private float timeoutFactor;
private String testThreadFactory;
private String testThreadFactoryPath;
private OutputHandler outputHandler;

MainActionHelper(String testName) {
Expand Down Expand Up @@ -113,6 +115,16 @@ MainActionHelper timeoutFactor(float timeoutFactor) {
return this;
}

MainActionHelper testThreadFactory(String testThreadFactory) {
this.testThreadFactory = testThreadFactory;
return this;
}

MainActionHelper testThreadFactoryPath(String testThreadFactoryPath) {
this.testThreadFactoryPath = testThreadFactoryPath;
return this;
}

MainActionHelper outputHandler(OutputHandler outputHandler) {
this.outputHandler = outputHandler;
return this;
Expand Down Expand Up @@ -183,16 +195,25 @@ public AStatus runClass() {
return stat;
}

AgentVMRunnable avmr = new AgentVMRunnable(method, methodArgs, err);

// Main and Thread are same here
// RUN JAVA IN ANOTHER THREADGROUP
AgentVMThreadGroup tg = new AgentVMThreadGroup(err, MSG_PREFIX, timeoutFactor);
AgentVMRunnable avmr = new AgentVMRunnable(method, methodArgs, err);
Thread t = new Thread(tg, avmr, "AgentVMThread");
Thread t;
if (testThreadFactory == null) {
t = new Thread(tg, avmr);
} else {
t = TestThreadFactoryHelper.loadThreadFactory(testThreadFactory, testThreadFactoryPath).newThread(avmr);
}

Alarm alarm = null;
if (timeout > 0) {
PrintWriter alarmOut = outputHandler.getPrintWriter(OutputHandler.OutputKind.LOG, true);
alarm = Alarm.schedulePeriodicInterrupt(timeout, TimeUnit.SECONDS, alarmOut, t);
}
Throwable error = null;
t.setName("AgentVMThread");
t.start();
try {
t.join();
Expand Down
24 changes: 19 additions & 5 deletions src/share/classes/com/sun/javatest/regtest/agent/MainWrapper.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -35,6 +35,10 @@
*/
public class MainWrapper
{

public static String TEST_THREAD_FACTORY = "jtreg.test.thread.factory";
public static String TEST_THREAD_FACTORY_PATH = "jtreg.test.thread.factory.path";

public static void main(String[] args) {
String moduleName;
String className;
Expand Down Expand Up @@ -65,8 +69,17 @@ public static void main(String[] args) {
}

// RUN JAVA IN ANOTHER THREADGROUP
MainThreadGroup tg = new MainThreadGroup();
Thread t = new Thread(tg, new MainThread(moduleName, className, classArgs), "MainThread");
MainThreadGroup tg = new MainThreadGroup();
Runnable task = new MainTask(moduleName, className, classArgs);
Thread t;
String testThreadFactory = System.getProperty(TEST_THREAD_FACTORY);
String testThreadFactoryPath = System.getProperty(TEST_THREAD_FACTORY_PATH);
if (testThreadFactory == null) {
t = new Thread(tg, task);
} else {
t = TestThreadFactoryHelper.loadThreadFactory(testThreadFactory, testThreadFactoryPath).newThread(task);
}
t.setName("MainThread");
t.start();
try {
t.join();
Expand Down Expand Up @@ -94,8 +107,8 @@ private static void handleTestException(Throwable e) {
}
}

static class MainThread extends Thread {
MainThread(String moduleName, String className, String[] args) {
static class MainTask implements Runnable {
MainTask(String moduleName, String className, String[] args) {
this.moduleName = moduleName;
this.className = className;
this.args = args;
Expand Down Expand Up @@ -219,4 +232,5 @@ public void uncaughtException(Thread t, Throwable e) {
MAIN_CANT_FIND_MAIN = "Can't find `main' method",
MAIN_SKIPPED = "Skipped: ";
private static final String SKIP_EXCEPTION = "jtreg.SkippedException";

}
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.javatest.regtest.agent;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadFactory;

/**
* A class which loads thread factory for threads used to run test by jtreg.
* By default, jtreg creates a new thread for each test using {@code new Thread(ThreadGroup tg, Runnable task);},
* but this may be overridden by providing an implementation of {@link java.util.concurrent.ThreadFactory},
* which might provide user-defined threads for test execution.
* Please note, that additional threads started by tests don't use this factory and remain the same.
* <p>
* Example:
* <pre>
* new Thread(() -> { ....; task.run(); ....; });
* or
* new VirtualThread(task);
* </pre>
* Implementation may be specified on the {@code jtreg} command line
* using {@code -testThreadFactory} and {@code -testThreadFactoryPath} arguments.
* It is executed by tested JDK in {@code agentvm} and {@code othervm} modes.
*/
public final class TestThreadFactoryHelper {
static ThreadFactory loadThreadFactory(String className, String path) {

List<URL> urls = new ArrayList<>();
if (path != null) {
SearchPath classpath = new SearchPath(path);
for (Path f : classpath.asList()) {
try {
urls.add(f.toUri().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}

try (URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[]{}), ClassLoader.getSystemClassLoader())) {
Class<? extends ThreadFactory> clz = loader.loadClass(className).asSubclass(ThreadFactory.class);
Constructor<? extends ThreadFactory> ctor = clz.getDeclaredConstructor();
ThreadFactory factory = ctor.newInstance();
return factory;
} catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException
| InstantiationException | IllegalAccessException | IOException e) {
throw new RuntimeException(e);
}
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -629,6 +629,8 @@ public boolean getCacheableValue(TestDescription td) throws Fault {
private static final String TIMEOUT_HANDLER = ".timeoutHandler";
private static final String TIMEOUT_HANDLER_PATH = ".timeoutHandlerPath";
private static final String TIMEOUT_HANDLER_TIMEOUT = ".timeoutHandlerTimeout";
private static final String CUSTOM_TEST_THREAD_FACTORY = ".testThreadFactory";
private static final String CUSTOM_TEST_THREAD_FACTORY_PATH = ".testThreadFactoryPath";
private static final String TEST_QUERIES = ".testQueries";

@Override
Expand Down Expand Up @@ -719,6 +721,14 @@ public void load(Map<String, String> data, boolean checkChecksum) throws Intervi
if (v != null)
setTimeoutHandlerTimeout(v);

v = data.get(prefix + CUSTOM_TEST_THREAD_FACTORY);
if (v != null)
setTestThreadFactory(v);

v = data.get(prefix + CUSTOM_TEST_THREAD_FACTORY_PATH);
if (v != null)
setTestThreadFactoryPath(v);

v = data.get(prefix + TEST_QUERIES);
if (v != null) {
setTestQueries(List.of(StringUtils.splitSeparator("\n", v)));
Expand Down Expand Up @@ -800,6 +810,14 @@ public void save(Map<String, String> data) {
data.put(prefix + TIMEOUT_HANDLER_TIMEOUT, String.valueOf(timeoutHandlerTimeout));
}

if (testThreadFactory != null) {
data.put(prefix + CUSTOM_TEST_THREAD_FACTORY, testThreadFactory);
}

if (testThreadFactoryPath != null) {
data.put(prefix + CUSTOM_TEST_THREAD_FACTORY_PATH, testThreadFactoryPath);
}

if (testQueries != null) {
data.put(prefix + TEST_QUERIES, join(testQueries, "\n"));
}
Expand Down Expand Up @@ -1245,7 +1263,27 @@ long getTimeoutHandlerTimeout() {
}

private long timeoutHandlerTimeout;
//---------------------------------------------------------------------

public void setTestThreadFactory(String testThreadFactory) {
this.testThreadFactory = testThreadFactory;
}

public String getTestThreadFactory() {
return testThreadFactory;
}

private String testThreadFactory;

public void setTestThreadFactoryPath(String testThreadFactoryPath) {
this.testThreadFactoryPath = testThreadFactoryPath;
}

public String getTestThreadFactoryPath() {
return testThreadFactoryPath;
}

private String testThreadFactoryPath;
//---------------------------------------------------------------------

public void setMatchLists(Path[] files) {
Expand Down

4 comments on commit 5b9e661

@sormuras
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/tag jtreg-7.2+1

@openjdk
Copy link

@openjdk openjdk bot commented on 5b9e661 Mar 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sormuras The given tag name jtreg-7.2+1 is not of the form jtreg(?:4\.1-b[0-9]{2}|5\.[01]-b[0-9]{2}|6|-[6789](?:\.[0-9]+)?+[0-9]+).

@sormuras
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/tag jtreg-7.2+1

@openjdk
Copy link

@openjdk openjdk bot commented on 5b9e661 Mar 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sormuras A tag with name jtreg-7.2+1 already exists that refers to commit 5b9e661e.

Please sign in to comment.