8138993: JEP-JDK-8046155: Test task: add check for Compiler.directives_print diagnostic command

Test Compiler.directive_print command

Reviewed-by: iignatyev, neliasso
This commit is contained in:
Pavel Punegov 2015-11-24 20:55:46 +03:00
parent faa5a2381c
commit 06c9ee5a1c
9 changed files with 265 additions and 35 deletions

View file

@ -26,7 +26,7 @@
* @bug 8137167
* @ignore 8140405
* @summary Tests jcmd to be able to clear directives added via options
* @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
* @library /testlibrary /test/lib /compiler/testlibrary ../share /
* @build ClearDirectivesFileStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
* compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
* @run main ClassFileInstaller sun.hotspot.WhiteBox
@ -73,9 +73,6 @@ public class ClearDirectivesFileStackTest extends AbstractTestBase {
compileCommand.print();
builder.add(compileCommand);
}
// print all directives before
builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
// clear the stack
builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));

View file

@ -25,7 +25,7 @@
* @test
* @bug 8137167
* @summary Tests clear JCMD command
* @library /testlibrary /../../test/lib /compiler/testlibrary ../share /
* @library /testlibrary /test/lib /compiler/testlibrary ../share /
* @build ClearDirectivesStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
* compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
* @run main ClassFileInstaller sun.hotspot.WhiteBox
@ -68,9 +68,6 @@ public class ClearDirectivesStackTest extends AbstractTestBase {
compileCommand.print();
builder.add(compileCommand);
}
// print all directives before
builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
// clear the stack
builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
Scenario.Type.JCMD, Scenario.JcmdType.CLEAR));

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2015, 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.
*/
/*
* @test
* @bug 8137167
* @summary Tests jcmd to be able to add a directive to compile only specified methods
* @library /testlibrary /test/lib /compiler/testlibrary ../share /
* @build pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
* compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.*
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm compiler.compilercontrol.jcmd.PrintDirectivesTest
*/
package compiler.compilercontrol.jcmd;
import compiler.compilercontrol.share.AbstractTestBase;
import compiler.compilercontrol.share.method.MethodDescriptor;
import compiler.compilercontrol.share.scenario.Command;
import compiler.compilercontrol.share.scenario.CommandGenerator;
import compiler.compilercontrol.share.scenario.CompileCommand;
import compiler.compilercontrol.share.scenario.JcmdCommand;
import compiler.compilercontrol.share.scenario.Scenario;
import jdk.test.lib.Utils;
import java.lang.reflect.Executable;
public class PrintDirectivesTest extends AbstractTestBase {
private static final int AMOUNT = Utils.getRandomInstance().nextInt(
Integer.getInteger("compiler.compilercontrol.jcmd."
+ "PrintDirectivesTest.amount", 20));
private final CommandGenerator cmdGen = new CommandGenerator();
public static void main(String[] args) {
new PrintDirectivesTest().test();
}
@Override
public void test() {
Scenario.Builder builder = Scenario.getBuilder();
// Add some commands with directives file
for (int i = 0; i < AMOUNT; i++) {
Executable exec = Utils.getRandomElement(METHODS).first;
MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec);
Command command = cmdGen.generateCommand();
if (command == Command.NONEXISTENT) {
// skip invalid command
command = Command.COMPILEONLY;
}
CompileCommand compileCommand = new CompileCommand(command,
methodDescriptor, cmdGen.generateCompiler(),
Scenario.Type.DIRECTIVE);
compileCommand.print();
builder.add(compileCommand);
}
// print all directives
builder.add(new JcmdCommand(Command.NONEXISTENT, null, null,
Scenario.Type.JCMD, Scenario.JcmdType.PRINT));
Scenario scenario = builder.build();
scenario.execute();
}
}

View file

@ -55,8 +55,8 @@ public abstract class StressAddJcmdBase {
public void test() {
List<String> commands = prepareCommands();
Executor executor = new TimeLimitedExecutor(commands);
OutputAnalyzer outputAnalyzer = executor.execute();
outputAnalyzer.shouldHaveExitValue(0);
List<OutputAnalyzer> outputAnalyzers = executor.execute();
outputAnalyzers.get(0).shouldHaveExitValue(0);
}
/**
@ -95,7 +95,7 @@ public abstract class StressAddJcmdBase {
}
@Override
protected void executeJCMD(int pid) {
protected OutputAnalyzer[] executeJCMD(int pid) {
TimeLimitedRunner runner = new TimeLimitedRunner(
Utils.DEFAULT_TEST_TIMEOUT,
Utils.TIMEOUT_FACTOR,
@ -106,6 +106,7 @@ public abstract class StressAddJcmdBase {
throw new Error("Exception during the execution: " + e, e);
}
finish();
return new OutputAnalyzer[0];
}
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, 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 compiler.compilercontrol.share.processors;
import compiler.compilercontrol.share.method.MethodDescriptor;
import compiler.compilercontrol.share.scenario.CompileCommand;
import jdk.test.lib.Asserts;
import jdk.test.lib.OutputAnalyzer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class PrintDirectivesProcessor
implements Consumer<List<OutputAnalyzer>> {
private final List<CompileCommand> commands;
private static final Pattern MATCH_PATTERN
= Pattern.compile(" matching: (.*)");
public PrintDirectivesProcessor(List<CompileCommand> commands) {
this.commands = commands;
}
@Override
public void accept(List<OutputAnalyzer> outputAnalyzers) {
List<String> directives = new ArrayList<>();
outputAnalyzers.forEach(outputAnalyzer ->
directives.addAll(getDirectives(outputAnalyzer)));
List<String> expectedDirectives = commands.stream()
.map(cc -> cc.methodDescriptor)
.map(MethodDescriptor::getCanonicalString)
.collect(Collectors.toList());
if (directives.size() != expectedDirectives.size()) {
printDirectives(directives, expectedDirectives);
throw new AssertionError(String.format("Different number of "
+ "directives. Expected: %d, actual: %d",
expectedDirectives.size(), directives.size()));
}
for (int i = 0; i < directives.size(); i++) {
if (!directives.get(i).equals(expectedDirectives.get(i))) {
printDirectives(directives, expectedDirectives);
throw new AssertionError(
String.format("Directives differ at %d, expected:%s%n",
i, expectedDirectives.get(i)));
}
}
}
private List<String> getDirectives(OutputAnalyzer outputAnalyzer) {
List<String> directives = new ArrayList<>();
List<String> inputStrings = outputAnalyzer.asLines();
Iterator<String> iterator = inputStrings.iterator();
while (iterator.hasNext()) {
String input = iterator.next();
if (input.equals("Directive:")) {
Asserts.assertTrue(iterator.hasNext(), "inconsistent directive"
+ "printed into the output");
String matchString = iterator.next();
Matcher matcher = MATCH_PATTERN.matcher(matchString);
Asserts.assertTrue(matcher.matches(), "Incorrect matching "
+ "string in directive");
directives.add(matcher.group(1));
}
}
return directives;
}
private void printDirectives(List<String> directives,
List<String> expected) {
System.err.println("Actual directives: " + directives);
System.err.println("Expected directives: " + expected);
}
}

View file

@ -36,6 +36,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
/**
* Directive file and state builder class
@ -66,7 +67,10 @@ public class DirectiveBuilder implements StateBuilder<CompileCommand> {
@Override
public List<CompileCommand> getCompileCommands() {
throw new Error("TESTBUG: isn't applicable for directives");
return matchBlocks.keySet().stream()
// only method descriptor is required to check print_directives
.map(md -> new CompileCommand(null, md, null, null))
.collect(Collectors.toList());
}
@Override

View file

@ -38,6 +38,7 @@ import java.lang.reflect.Executable;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -46,6 +47,7 @@ public class Executor {
private final List<String> vmOptions;
private final Map<Executable, State> states;
private final List<String> jcmdCommands;
private OutputAnalyzer[] jcmdOutputAnalyzers;
/**
* Constructor
@ -73,7 +75,7 @@ public class Executor {
* Executes separate VM a gets an OutputAnalyzer instance with the results
* of execution
*/
public OutputAnalyzer execute() {
public List<OutputAnalyzer> execute() {
// Add class name that would be executed in a separate VM
String classCmd = BaseAction.class.getName();
vmOptions.add(classCmd);
@ -99,7 +101,13 @@ public class Executor {
} catch (Throwable thr) {
throw new Error("Execution failed: " + thr.getMessage(), thr);
}
return output;
List<OutputAnalyzer> outputList = new ArrayList<>();
outputList.add(output);
if (jcmdOutputAnalyzers != null) {
Collections.addAll(outputList, jcmdOutputAnalyzers);
}
return outputList;
}
/*
@ -121,7 +129,7 @@ public class Executor {
// Get pid of the executed process
int pid = Integer.parseInt(in.readLine());
Asserts.assertNE(pid, 0, "Got incorrect pid");
executeJCMD(pid);
jcmdOutputAnalyzers = executeJCMD(pid);
if (states != null) {
// serialize and send state map
states.forEach((executable, state) -> {
@ -139,10 +147,13 @@ public class Executor {
}
// Executes all diagnostic commands
protected void executeJCMD(int pid) {
protected OutputAnalyzer[] executeJCMD(int pid) {
int size = jcmdCommands.size();
OutputAnalyzer[] outputArray = new OutputAnalyzer[size];
CommandExecutor jcmdExecutor = new PidJcmdExecutor(String.valueOf(pid));
for (String command : jcmdCommands) {
jcmdExecutor.execute(command);
for (int i = 0; i < size; i++) {
outputArray[i] = jcmdExecutor.execute(jcmdCommands.get(i));
}
return outputArray;
}
}

View file

@ -36,6 +36,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
private static final List<Pair<Executable, Callable<?>>> METHODS
@ -44,7 +45,6 @@ public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
private final DirectiveBuilder directiveBuilder;
private Map<MethodDescriptor, List<CompileCommand>> matchBlocks
= new LinkedHashMap<>();
private List<JcmdCommand> commands = new ArrayList<>();
private boolean isFileValid = true;
public JcmdStateBuilder(String fileName) {
@ -53,7 +53,6 @@ public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
@Override
public void add(JcmdCommand compileCommand) {
commands.add(compileCommand);
switch (compileCommand.jcmdType) {
case ADD:
directiveBuilder.add(compileCommand);
@ -159,6 +158,15 @@ public class JcmdStateBuilder implements StateBuilder<JcmdCommand> {
@Override
public List<JcmdCommand> getCompileCommands() {
return commands;
if (isFileValid) {
return matchBlocks.keySet().stream()
/* only method descriptor is required
to check print_directives */
.map(md -> new JcmdCommand(null, md, null, null,
Scenario.JcmdType.ADD))
.collect(Collectors.toList());
} else {
return new ArrayList<>();
}
}
}

View file

@ -26,6 +26,7 @@ package compiler.compilercontrol.share.scenario;
import compiler.compilercontrol.share.method.MethodDescriptor;
import compiler.compilercontrol.share.processors.CommandProcessor;
import compiler.compilercontrol.share.processors.LogProcessor;
import compiler.compilercontrol.share.processors.PrintDirectivesProcessor;
import compiler.compilercontrol.share.processors.PrintProcessor;
import compiler.compilercontrol.share.processors.QuietProcessor;
import jdk.test.lib.Asserts;
@ -52,12 +53,14 @@ public final class Scenario {
private final Map<Executable, State> states;
private final List<Consumer<OutputAnalyzer>> processors;
private final Executor executor;
private final Consumer<List<OutputAnalyzer>> jcmdProcessor;
private Scenario(boolean isValid,
List<String> vmopts,
Map<Executable, State> states,
List<CompileCommand> compileCommands,
List<JcmdCommand> jcmdCommands) {
List<JcmdCommand> jcmdCommands,
List<CompileCommand> directives) {
this.isValid = isValid;
this.states = states;
processors = new ArrayList<>();
@ -78,6 +81,7 @@ public final class Scenario {
processors.add(new QuietProcessor(quieted));
List<String> jcmdExecCommands = new ArrayList<>();
boolean addCommandMet = false;
boolean printCommandMet = false;
for (JcmdCommand cmd : jcmdCommands) {
switch (cmd.jcmdType) {
case ADD:
@ -86,11 +90,19 @@ public final class Scenario {
}
addCommandMet = true;
break;
case PRINT:
printCommandMet = true;
break;
default:
jcmdExecCommands.add(cmd.jcmdType.command);
break;
}
}
// Add print command only in the end to get directives printed
if (printCommandMet) {
jcmdExecCommands.add(JcmdType.PRINT.command);
}
jcmdProcessor = new PrintDirectivesProcessor(directives);
executor = new Executor(isValid, vmopts, states, jcmdExecCommands);
}
@ -98,14 +110,20 @@ public final class Scenario {
* Executes scenario
*/
public void execute() {
OutputAnalyzer output = executor.execute();
List<OutputAnalyzer> outputList = executor.execute();
// The first one contains output from the test VM
OutputAnalyzer mainOuput = outputList.get(0);
if (isValid) {
output.shouldHaveExitValue(0);
processors.forEach(processor -> processor.accept(output));
mainOuput.shouldHaveExitValue(0);
processors.forEach(processor -> processor.accept(mainOuput));
// only the last output contains directives got from print command
List<OutputAnalyzer> last = new ArrayList<>();
last.add(outputList.get(outputList.size() - 1));
jcmdProcessor.accept(last);
} else {
Asserts.assertNE(output.getExitValue(), 0, "VM should exit with "
Asserts.assertNE(mainOuput.getExitValue(), 0, "VM should exit with "
+ "error for incorrect directives");
output.shouldContain("Parsing of compiler directives failed");
mainOuput.shouldContain("Parsing of compiler directives failed");
}
}
@ -181,6 +199,7 @@ public final class Scenario {
private final Map<Type, StateBuilder<CompileCommand>> builders
= new HashMap<>();
private final JcmdStateBuilder jcmdStateBuilder;
private final List<JcmdCommand> jcmdCommands = new ArrayList<>();
public Builder() {
builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName));
@ -195,6 +214,7 @@ public final class Scenario {
Collections.addAll(vmopts, vmOptions);
if (compileCommand.type == Type.JCMD) {
jcmdStateBuilder.add((JcmdCommand) compileCommand);
jcmdCommands.add((JcmdCommand) compileCommand);
} else {
StateBuilder<CompileCommand> builder = builders.get(
compileCommand.type);
@ -217,11 +237,9 @@ public final class Scenario {
Map<Executable, State> directiveFileStates
= builders.get(Type.DIRECTIVE).getStates();
// get all jcmd commands
List<JcmdCommand> jcmdCommands = jcmdStateBuilder
.getCompileCommands();
// check if directives stack was cleared by jcmd
boolean isClearedState = false;
if (jcmdClearedState(jcmdCommands)) {
if (jcmdContainsCommand(JcmdType.CLEAR)) {
isClearedState = true;
}
@ -255,6 +273,18 @@ public final class Scenario {
ccList.addAll(builders.get(Type.OPTION).getCompileCommands());
ccList.addAll(builders.get(Type.FILE).getCompileCommands());
/*
* Create a list of directives to check which one was printed
*/
List<CompileCommand> directives = new ArrayList<>();
if (jcmdContainsCommand(JcmdType.PRINT)) {
if (!isClearedState) {
directives.addAll(builders.get(Type.DIRECTIVE)
.getCompileCommands());
}
directives.addAll(jcmdStateBuilder.getCompileCommands());
}
// Get all VM options after we build all states and files
List<String> options = new ArrayList<>();
options.addAll(vmopts);
@ -264,13 +294,13 @@ public final class Scenario {
}
options.addAll(jcmdStateBuilder.getOptions());
return new Scenario(isValid, options, finalStates, ccList,
jcmdCommands);
jcmdCommands, directives);
}
// shows if jcmd have passed a clear command
private boolean jcmdClearedState(List<JcmdCommand> jcmdCommands) {
// shows if jcmd have passed a specified jcmd command type
private boolean jcmdContainsCommand(JcmdType type) {
for (JcmdCommand jcmdCommand : jcmdCommands) {
if (jcmdCommand.jcmdType == JcmdType.CLEAR) {
if (jcmdCommand.jcmdType == type) {
return true;
}
}