Path: blob/master/test/hotspot/jtreg/compiler/compilercontrol/share/scenario/Scenario.java
41161 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package compiler.compilercontrol.share.scenario;2425import compiler.compilercontrol.share.method.MethodDescriptor;26import compiler.compilercontrol.share.pool.PoolHelper;27import compiler.compilercontrol.share.processors.CommandProcessor;28import compiler.compilercontrol.share.processors.LogProcessor;29import compiler.compilercontrol.share.processors.PrintDirectivesProcessor;30import compiler.compilercontrol.share.processors.PrintProcessor;31import jdk.test.lib.Asserts;32import jdk.test.lib.process.OutputAnalyzer;33import jdk.test.lib.util.Pair;3435import java.lang.reflect.Executable;36import java.util.ArrayList;37import java.util.Collections;38import java.util.HashMap;39import java.util.LinkedHashSet;40import java.util.List;41import java.util.Map;42import java.util.Set;43import java.util.concurrent.Callable;44import java.util.function.Consumer;4546/**47* Test scenario48*/49public final class Scenario {50private final boolean isValid;51private final boolean isJcmdValid;52private final Map<Executable, State> states;53private final List<Consumer<OutputAnalyzer>> processors;54private final Executor executor;55private final Consumer<List<OutputAnalyzer>> jcmdProcessor;5657private Scenario(boolean isValid,58boolean isJcmdValid,59List<String> vmopts,60Map<Executable, State> states,61List<CompileCommand> compileCommands,62List<JcmdCommand> jcmdCommands,63List<CompileCommand> directives) {64this.isValid = isValid;65this.isJcmdValid = isJcmdValid;66this.states = states;67processors = new ArrayList<>();68processors.add(new LogProcessor(states));69processors.add(new PrintProcessor(states));70List<CompileCommand> nonQuieted = new ArrayList<>();71List<CompileCommand> quieted = new ArrayList<>();72boolean metQuiet = false;73for (CompileCommand cc : compileCommands) {74metQuiet |= cc.command == Command.QUIET;75if (metQuiet) {76quieted.add(cc);77} else {78nonQuieted.add(cc);79}80}81processors.add(new CommandProcessor(nonQuieted, quieted));82List<String> jcmdExecCommands = new ArrayList<>();83boolean addCommandMet = false;84boolean printCommandMet = false;85for (JcmdCommand cmd : jcmdCommands) {86switch (cmd.jcmdType) {87case ADD:88if (!addCommandMet) {89jcmdExecCommands.add(JcmdType.ADD.command);90}91addCommandMet = true;92break;93case PRINT:94printCommandMet = true;95break;96default:97jcmdExecCommands.add(cmd.jcmdType.command);98break;99}100}101// Add print command only in the end to get directives printed102if (printCommandMet) {103jcmdExecCommands.add(JcmdType.PRINT.command);104}105jcmdProcessor = new PrintDirectivesProcessor(directives);106executor = new Executor(isValid, vmopts, states, jcmdExecCommands);107}108109/**110* Executes scenario111*/112public void execute() {113List<OutputAnalyzer> outputList = executor.execute();114// The first one contains output from the test VM115OutputAnalyzer mainOutput = outputList.get(0);116if (isValid) {117mainOutput.shouldHaveExitValue(0);118processors.forEach(processor -> processor.accept(mainOutput));119// only the last output contains directives got from print command120List<OutputAnalyzer> last = new ArrayList<>();121last.add(outputList.get(outputList.size() - 1));122jcmdProcessor.accept(last);123} else {124// two cases for invalid inputs.125if (mainOutput.getExitValue() == 0) {126if (!isJcmdValid) {127boolean parse_error_found = false;128for(OutputAnalyzer out : outputList) {129if (out.getOutput().contains("Parsing of compiler directives failed")) {130parse_error_found = true;131break;132}133}134Asserts.assertTrue(parse_error_found, "'Parsing of compiler directives failed' missing from output");135} else {136mainOutput.shouldContain("CompileCommand: An error occurred during parsing");137}138} else {139Asserts.assertNE(mainOutput.getExitValue(), 0, "VM should exit with "140+ "error for incorrect directives");141mainOutput.shouldContain("Parsing of compiler directives failed");142}143}144}145146/**147* Gets states of methods for this scenario148*149* @return pairs of executable and its state150*/151public Map<Executable, State> getStates() {152return states;153}154155public static enum Compiler {156C1("c1"),157C2("c2");158159public final String name;160161Compiler(String name) {162this.name = name;163}164}165166/**167* Type of diagnostic (jcmd) command168*/169public static enum JcmdType {170ADD("Compiler.directives_add " + Type.JCMD.fileName),171PRINT("Compiler.directives_print"),172CLEAR("Compiler.directives_clear"),173REMOVE("Compiler.directives_remove");174175public final String command;176private JcmdType(String command) {177this.command = command;178}179}180181/**182* Type of the compile command183*/184public static enum Type {185OPTION(""), // CompilerOracle: -XX:CompileCommand=186FILE("command_file"), // CompilerOracle: -XX:CompileCommandFile=187DIRECTIVE("directives.json"),188JCMD("jcmd_directives.json") {189@Override190public CompileCommand createCompileCommand(Command command,191MethodDescriptor md, Compiler compiler) {192return new JcmdCommand(command, md, compiler, this,193JcmdType.ADD);194}195196@Override197public CompileCommand createCompileCommand(Command command,198MethodDescriptor md, Compiler compiler, String argument) {199return new JcmdCommand(command, md, compiler, this,200JcmdType.ADD, argument);201}202};203204public final String fileName;205206public CompileCommand createCompileCommand(Command command,207MethodDescriptor md, Compiler compiler) {208return new CompileCommand(command, md, compiler, this);209}210211public CompileCommand createCompileCommand(Command command,212MethodDescriptor md, Compiler compiler, String argument) {213return new CompileCommand(command, md, compiler, this, argument);214}215216private Type(String fileName) {217this.fileName = fileName;218}219}220221public static Builder getBuilder() {222return new Builder();223}224225public static class Builder {226private final Set<String> vmopts = new LinkedHashSet<>();227private final Map<Type, StateBuilder<CompileCommand>> builders228= new HashMap<>();229private final JcmdStateBuilder jcmdStateBuilder;230private final List<JcmdCommand> jcmdCommands = new ArrayList<>();231private boolean logCommandMet = false;232233public Builder() {234addFlag("-Xmixed");235builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName));236builders.put(Type.OPTION, new CommandOptionsBuilder());237builders.put(Type.DIRECTIVE, new DirectiveBuilder(238Type.DIRECTIVE.fileName));239jcmdStateBuilder = new JcmdStateBuilder(Type.JCMD.fileName);240}241242public void addFlag(String flag) {243vmopts.add(flag);244}245246public void add(CompileCommand compileCommand) {247System.out.println(compileCommand);248String[] vmOptions = compileCommand.command.vmOpts;249Collections.addAll(vmopts, vmOptions);250if (compileCommand.command == Command.LOG) {251logCommandMet = true;252}253if (compileCommand.type == Type.JCMD) {254jcmdStateBuilder.add((JcmdCommand) compileCommand);255jcmdCommands.add((JcmdCommand) compileCommand);256} else {257StateBuilder<CompileCommand> builder = builders.get(258compileCommand.type);259if (builder == null) {260throw new Error("TESTBUG: Missing builder for the type: "261+ compileCommand.type);262}263builder.add(compileCommand);264}265}266267public Scenario build() {268boolean isValid = true;269boolean isJcmdValid = true;270271// Get states from each of the state builders272Map<Executable, State> commandFileStates273= builders.get(Type.FILE).getStates();274Map<Executable, State> commandOptionStates275= builders.get(Type.OPTION).getStates();276Map<Executable, State> directiveFileStates277= builders.get(Type.DIRECTIVE).getStates();278279// check if directives stack was cleared by jcmd280boolean isClearedState = false;281if (jcmdContainsCommand(JcmdType.CLEAR)) {282isClearedState = true;283}284285// Merge states286List<Pair<Executable, Callable<?>>> methods = new PoolHelper()287.getAllMethods();288Map<Executable, State> finalStates = new HashMap<>();289Map<Executable, State> jcmdStates = jcmdStateBuilder.getStates();290for (Pair<Executable, Callable<?>> pair : methods) {291Executable x = pair.first;292State commandOptionState = commandOptionStates.get(x);293State commandFileState = commandFileStates.get(x);294State st = State.merge(commandOptionState, commandFileState);295if (!isClearedState) {296State directiveState = directiveFileStates.get(x);297State jcmdState = jcmdStates.get(x);298if (jcmdState != null) {299st = State.merge(st, jcmdState);300} else if (directiveState != null) {301st = State.merge(st, directiveState);302}303}304finalStates.put(x, st);305}306307/*308* Create a list of commands from options and file309* to handle quiet command310*/311List<CompileCommand> ccList = new ArrayList<>();312ccList.addAll(builders.get(Type.OPTION).getCompileCommands());313ccList.addAll(builders.get(Type.FILE).getCompileCommands());314315// Create a list of directives to check which one was printed316List<CompileCommand> directives = new ArrayList<>();317if (jcmdContainsCommand(JcmdType.PRINT)) {318if (!isClearedState) {319directives.addAll(builders.get(Type.DIRECTIVE)320.getCompileCommands());321}322directives.addAll(jcmdStateBuilder.getCompileCommands());323}324325// Get all VM options after we build all states and files326List<String> options = new ArrayList<>();327options.addAll(vmopts);328for (StateBuilder<?> builder : builders.values()) {329options.addAll(builder.getOptions());330isValid &= builder.isValid();331}332isJcmdValid = jcmdStateBuilder.isFileValid;333options.addAll(jcmdStateBuilder.getOptions());334335/*336* Update final states if LogCompilation is enabled and337* there is no any log command, then all methods should be logged338*/339boolean isLogComp = vmopts.stream()340.anyMatch(opt -> opt.contains("-XX:+LogCompilation"));341if (isLogComp && !logCommandMet) {342finalStates.entrySet()343.forEach(entry -> entry.getValue().setLog(true));344}345346return new Scenario(isValid, isJcmdValid, options, finalStates, ccList,347jcmdCommands, directives);348}349350// shows if jcmd have passed a specified jcmd command type351private boolean jcmdContainsCommand(JcmdType type) {352for (JcmdCommand jcmdCommand : jcmdCommands) {353if (jcmdCommand.jcmdType == type) {354return true;355}356}357return false;358}359}360}361362363