Skip to content

Commit

Permalink
8313613: Use JUnit in langtools/lib tests
Browse files Browse the repository at this point in the history
Reviewed-by: cstein, asotona
  • Loading branch information
Qing Xiao authored and sormuras committed Oct 16, 2023
1 parent 8c1bb2b commit 741ae06
Show file tree
Hide file tree
Showing 17 changed files with 471 additions and 346 deletions.
4 changes: 2 additions & 2 deletions test/langtools/lib/combo/TEST.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file identifies root(s) of the test-ng hierarchy.
# This file identifies root(s) of the JUnit hierarchy.

TestNG.dirs = .
JUnit.dirs = .

modules = \
jdk.compiler/com.sun.tools.javac.util
31 changes: 31 additions & 0 deletions test/langtools/lib/combo/tools/javac/combo/ComboWatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package tools.javac.combo;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;

public class ComboWatcher implements TestWatcher, AfterAllCallback {
private final Set<String> errors = Collections.synchronizedSet(new HashSet<>());

@Override
public void testFailed(ExtensionContext context, Throwable cause) {
if (context.getRequiredTestInstance() instanceof JavacTemplateTestBase instance) {
errors.addAll(instance.diags.errorKeys());
if (instance instanceof CompilationTestCase) {
// Make sure offending template ends up in log file on failure
System.err.printf("Diagnostics: %s%nTemplate: %s%n", instance.diags.errorKeys(),
instance.sourceFiles.stream().map(SourceFile::template).toList());
}
}
}

@Override
public void afterAll(ExtensionContext extensionContext) {
if (errors.isEmpty()) return;
System.err.println("Errors found in tests: " + errors);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, 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.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -31,30 +31,14 @@

import javax.tools.Diagnostic;

import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

import static java.util.stream.Collectors.toList;

/**
* Base class for negative and positive compilation tests.
*/
@Test
public class CompilationTestCase extends JavacTemplateTestBase {
private String[] compileOptions = new String[] { };
private String[] compileOptions = new String[]{};
private String defaultFileName = "Source.java";
private String programShell = "#";

@AfterMethod
public void dumpTemplateIfError(ITestResult result) {
// Make sure offending template ends up in log file on failure
if (!result.isSuccess()) {
System.err.printf("Diagnostics: %s%nTemplate: %s%n", diags.errorKeys(),
sourceFiles.stream().map(p -> p.snd).collect(toList()));
}
}

protected void setProgramShell(String shell) {
programShell = shell;
}
Expand All @@ -81,7 +65,7 @@ protected void removeLastCompileOptions(int i) {
throw new AssertionError("unexpected negative value " + i);
}
if (i >= compileOptions.length) {
compileOptions = new String[] {};
compileOptions = new String[]{};
} else {
compileOptions = Arrays.copyOf(compileOptions, compileOptions.length - i);
}
Expand All @@ -105,8 +89,7 @@ private File assertCompile(String program, Runnable postTest, boolean generate)
File dir = null;
try {
dir = compile(generate);
}
catch (IOException e) {
} catch (IOException e) {
throw new RuntimeException(e);
}
postTest.run();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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 @@ -33,10 +33,8 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import javax.tools.Diagnostic;
Expand All @@ -48,17 +46,13 @@
import javax.tools.ToolProvider;

import com.sun.source.util.JavacTask;
import com.sun.tools.javac.util.Pair;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.testng.Assert.fail;
import static org.junit.jupiter.api.Assertions.fail;

/**
* Base class for template-driven TestNG javac tests that support on-the-fly
* Base class for template-driven JUnit javac tests that support on-the-fly
* source file generation, compilation, classloading, execution, and separate
* compilation.
*
Expand All @@ -70,16 +64,15 @@
*
* @author Brian Goetz
*/
@Test
@ExtendWith(ComboWatcher.class)
public abstract class JavacTemplateTestBase {
private static final Set<String> suiteErrors = Collections.synchronizedSet(new HashSet<>());
private static final AtomicInteger counter = new AtomicInteger();
private static final File root = new File("gen");
private static final File nullDir = new File("empty");

protected final Map<String, Template> templates = new HashMap<>();
protected final Diagnostics diags = new Diagnostics();
protected final List<Pair<String, String>> sourceFiles = new ArrayList<>();
protected final List<SourceFile> sourceFiles = new ArrayList<>();
protected final List<String> compileOptions = new ArrayList<>();
protected final List<File> classpaths = new ArrayList<>();

Expand All @@ -95,7 +88,7 @@ protected void addTemplate(String name, String s) {

/** Add a source file */
protected void addSourceFile(String name, String template) {
sourceFiles.add(new Pair<>(name, template));
sourceFiles.add(new SourceFile(name, template));
}

/** Add a File to the class path to be used when loading classes; File values
Expand Down Expand Up @@ -130,7 +123,7 @@ protected void addCompileOptions(String... opts) {
protected void resetClassPaths() { classpaths.clear(); }

// Before each test method, reset everything
@BeforeMethod
@BeforeEach
public void reset() {
resetCompileOptions();
resetDiagnostics();
Expand All @@ -139,38 +132,6 @@ public void reset() {
resetClassPaths();
}

// After each test method, if the test failed, capture source files and diagnostics and put them in the log
@AfterMethod
public void copyErrors(ITestResult result) {
if (!result.isSuccess()) {
suiteErrors.addAll(diags.errorKeys());

List<Object> list = new ArrayList<>();
Collections.addAll(list, result.getParameters());
list.add("Test case: " + getTestCaseDescription());
for (Pair<String, String> e : sourceFiles)
list.add("Source file " + e.fst + ": " + e.snd);
if (diags.errorsFound())
list.add("Compile diagnostics: " + diags.toString());
result.setParameters(list.toArray(new Object[list.size()]));
}
}

@AfterSuite
// After the suite is done, dump any errors to output
public void dumpErrors() {
if (!suiteErrors.isEmpty())
System.err.println("Errors found in test suite: " + suiteErrors);
}

/**
* Get a description of this test case; since test cases may be combinatorially
* generated, this should include all information needed to describe the test case
*/
protected String getTestCaseDescription() {
return this.toString();
}

/** Assert that all previous calls to compile() succeeded */
protected void assertCompileSucceeded() {
if (diags.errorsFound())
Expand Down Expand Up @@ -258,23 +219,19 @@ protected void compile() throws IOException {
/** Compile all registered source files, optionally generating class files
* and returning a File describing the directory to which they were written */
protected File compile(boolean generate) throws IOException {
List<JavaFileObject> files = new ArrayList<>();
for (Pair<String, String> e : sourceFiles)
files.add(new FileAdapter(e.fst, e.snd));
var files = sourceFiles.stream().map(FileAdapter::new).toList();
return compile(classpaths, files, generate);
}

/** Compile all registered source files, using the provided list of class paths
* for finding required classfiles, optionally generating class files
* and returning a File describing the directory to which they were written */
protected File compile(List<File> classpaths, boolean generate) throws IOException {
List<JavaFileObject> files = new ArrayList<>();
for (Pair<String, String> e : sourceFiles)
files.add(new FileAdapter(e.fst, e.snd));
var files = sourceFiles.stream().map(FileAdapter::new).toList();
return compile(classpaths, files, generate);
}

private File compile(List<File> classpaths, List<JavaFileObject> files, boolean generate) throws IOException {
private File compile(List<File> classpaths, List<? extends JavaFileObject> files, boolean generate) throws IOException {
JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = systemJavaCompiler.getStandardFileManager(null, null, null)) {
if (classpaths.size() > 0)
Expand Down Expand Up @@ -327,9 +284,9 @@ public String toString() {
private class FileAdapter extends SimpleJavaFileObject {
private final String templateString;

FileAdapter(String filename, String templateString) {
super(URI.create("myfo:/" + filename), Kind.SOURCE);
this.templateString = templateString;
FileAdapter(SourceFile file) {
super(URI.create("myfo:/" + file.name()), Kind.SOURCE);
this.templateString = file.template();
}

public CharSequence getCharContent(boolean ignoreEncodingErrors) {
Expand Down
26 changes: 26 additions & 0 deletions test/langtools/lib/combo/tools/javac/combo/SourceFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 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.
*
* 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 tools.javac.combo;

public record SourceFile(String name, String template) {}
34 changes: 18 additions & 16 deletions test/langtools/lib/combo/tools/javac/combo/TemplateTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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 All @@ -23,34 +23,34 @@

package tools.javac.combo;

import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;

import java.util.HashMap;
import java.util.Map;

import static org.testng.Assert.assertEquals;

/**
* TemplateTest
*/
@Test
public class TemplateTest {
Map<String, Template> vars = new HashMap<>();
class TemplateTest {
final Map<String, Template> vars = new HashMap<>();

@BeforeTest
@BeforeEach
void before() { vars.clear(); }

private void assertTemplate(String expected, String template) {
String result = Template.expandTemplate(template, vars);
assertEquals(result, expected, "for " + template);
assertEquals(expected, result, "for " + template);
}

private String dotIf(String s) {
return s == null || s.isEmpty() ? "" : "." + s;
}

public void testTemplateExpansion() {
@Test
void testTemplateExpansion() {
vars.put("A", s -> "a" + dotIf(s));
vars.put("B", s -> "b" + dotIf(s));
vars.put("C", s -> "#{A}#{B}");
Expand All @@ -72,7 +72,8 @@ public void testTemplateExpansion() {
assertTemplate("#{A", "#{A");
}

public void testIndexedTemplate() {
@Test
void testIndexedTemplate() {
vars.put("A[0]", s -> "a" );
vars.put("A[1]", s -> "b" );
vars.put("A[2]", s -> "c" );
Expand All @@ -82,13 +83,14 @@ public void testIndexedTemplate() {
assertTemplate("c", "#{A[2]}");
}

public void testAngleBrackets() {
@Test
void testAngleBrackets() {
vars.put("X", s -> "xyz");
assertTemplate("List<String> ls = xyz;", "List<String> ls = #{X};");
}

@Test(expectedExceptions = IllegalStateException.class )
public void testUnknownKey() {
assertTemplate("#{Q}", "#{Q}");
@Test
void testUnknownKey() {
assertThrows(IllegalStateException.class, () -> assertTemplate("#{Q}", "#{Q}"));
}
}

1 comment on commit 741ae06

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.