1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import com.oracle.java.testlibrary.*;
  25 
  26 /*
  27  * @test CheckCompileCommandOption
  28  * @bug 8055286 8056964 8059847
  29  * @summary "Checks parsing of -XX:+CompileCommand=option"
  30  * @library /testlibrary
  31  * @run main CheckCompileCommandOption
  32  */
  33 
  34 public class CheckCompileCommandOption {
  35 
  36     // Currently, two types of trailing options can be used with
  37     // -XX:CompileCommand=option
  38     //
  39     // (1) CompileCommand=option,Klass::method,flag
  40     // (2) CompileCommand=option,Klass::method,type,flag,value
  41     //
  42     // Type (1) is used to enable a boolean flag for a method.
  43     //
  44     // Type (2) is used to support flags with a value. Values can
  45     // have the the following types: intx, uintx, bool, ccstr,
  46     // ccstrlist, and double.
  47 
  48     private static final String[][] TYPE_1_ARGUMENTS = {
  49         {
  50             "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1",
  51             "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption2",
  52             "-XX:CompileCommand=option,com.oracle.Test::test,MyBoolOption3",
  53             "-XX:CompileCommand=option,com/oracle/Test::test,MyBoolOption4",
  54             "-version"
  55         },
  56         {
  57             "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1,MyBoolOption2",
  58             "-version"
  59         },
  60         {
  61             "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption1,MyBoolOption2",
  62             "-version"
  63         }
  64     };
  65 
  66     private static final String[][] TYPE_1_EXPECTED_OUTPUTS = {
  67         {
  68             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
  69             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
  70             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption3 = true",
  71             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption4 = true"
  72         },
  73         {
  74             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
  75             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
  76         },
  77         {
  78             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
  79             "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
  80         }
  81     };
  82 
  83     private static final String[][] TYPE_2_ARGUMENTS = {
  84         {
  85             "-XX:CompileCommand=option,Test::test,ccstrlist,MyListOption,_foo,_bar",
  86             "-XX:CompileCommand=option,Test::test,ccstr,MyStrOption,_foo",
  87             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false",
  88             "-XX:CompileCommand=option,Test::test,intx,MyIntxOption,-1",
  89             "-XX:CompileCommand=option,Test::test,uintx,MyUintxOption,1",
  90             "-XX:CompileCommand=option,Test::test,MyFlag",
  91             "-XX:CompileCommand=option,Test::test,double,MyDoubleOption,1.123",
  92             "-version"
  93         },
  94         {
  95             "-XX:CompileCommand=option,Test.test,double,MyDoubleOption,1.123",
  96             "-version"
  97         },
  98         {
  99             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx,MyIntxOption,-1,uintx,MyUintxOption,1,MyFlag,double,MyDoubleOption,1.123",
 100             "-version"
 101         }
 102     };
 103 
 104     private static final String[][] TYPE_2_EXPECTED_OUTPUTS = {
 105         {
 106             "CompilerOracle: option Test.test const char* MyListOption = '_foo _bar'",
 107             "CompilerOracle: option Test.test const char* MyStrOption = '_foo'",
 108             "CompilerOracle: option Test.test bool MyBoolOption = false",
 109             "CompilerOracle: option Test.test intx MyIntxOption = -1",
 110             "CompilerOracle: option Test.test uintx MyUintxOption = 1",
 111             "CompilerOracle: option Test.test bool MyFlag = true",
 112             "CompilerOracle: option Test.test double MyDoubleOption = 1.123000"
 113         },
 114         {
 115             "CompilerOracle: option Test.test double MyDoubleOption = 1.123000"
 116         },
 117         {
 118             "CompilerOracle: option Test.test bool MyBoolOption = false",
 119             "CompilerOracle: option Test.test intx MyIntxOption = -1",
 120             "CompilerOracle: option Test.test uintx MyUintxOption = 1",
 121             "CompilerOracle: option Test.test bool MyFlag = true",
 122             "CompilerOracle: option Test.test double MyDoubleOption = 1.123000",
 123         }
 124     };
 125 
 126     private static final String[][] TYPE_2_INVALID_ARGUMENTS = {
 127         {
 128             // bool flag name missing
 129             "-XX:CompileCommand=option,Test::test,bool",
 130             "-version"
 131         },
 132         {
 133             // bool flag value missing
 134             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption",
 135             "-version"
 136         },
 137         {
 138             // wrong value for bool flag
 139             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,100",
 140             "-version"
 141         },
 142         {
 143             // intx flag name missing
 144             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx",
 145             "-version"
 146         },
 147         {
 148             // intx flag value missing
 149             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx,MyIntOption",
 150             "-version"
 151         },
 152         {
 153             // wrong value for intx flag
 154             "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx,MyIntOption,true",
 155             "-version"
 156         },
 157         {
 158             // wrong value for flag double flag
 159             "-XX:CompileCommand=option,Test::test,double,MyDoubleOption,1",
 160             "-version"
 161         }
 162     };
 163 
 164     private static void verifyValidOption(String[] arguments, String[] expected_outputs) throws Exception {
 165         ProcessBuilder pb;
 166         OutputAnalyzer out;
 167 
 168         pb = ProcessTools.createJavaProcessBuilder(arguments);
 169         out = new OutputAnalyzer(pb.start());
 170 
 171         for (String expected_output : expected_outputs) {
 172             out.shouldContain(expected_output);
 173         }
 174 
 175         out.shouldNotContain("CompileCommand: unrecognized line");
 176         out.shouldHaveExitValue(0);
 177     }
 178 
 179     private static void verifyInvalidOption(String[] arguments) throws Exception {
 180         ProcessBuilder pb;
 181         OutputAnalyzer out;
 182 
 183         pb = ProcessTools.createJavaProcessBuilder(arguments);
 184         out = new OutputAnalyzer(pb.start());
 185 
 186         out.shouldContain("CompileCommand: unrecognized line");
 187         out.shouldHaveExitValue(0);
 188     }
 189 
 190     public static void main(String[] args) throws Exception {
 191 
 192         if (TYPE_1_ARGUMENTS.length != TYPE_1_EXPECTED_OUTPUTS.length) {
 193             throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (1) options does not match.");
 194         }
 195 
 196         if (TYPE_2_ARGUMENTS.length != TYPE_2_EXPECTED_OUTPUTS.length) {
 197             throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (2) options does not match.");
 198         }
 199 
 200         // Check if type (1) options are parsed correctly
 201         for (int i = 0; i < TYPE_1_ARGUMENTS.length; i++) {
 202             verifyValidOption(TYPE_1_ARGUMENTS[i], TYPE_1_EXPECTED_OUTPUTS[i]);
 203         }
 204 
 205         // Check if type (2) options are parsed correctly
 206         for (int i = 0; i < TYPE_2_ARGUMENTS.length; i++) {
 207             verifyValidOption(TYPE_2_ARGUMENTS[i], TYPE_2_EXPECTED_OUTPUTS[i]);
 208         }
 209 
 210         // Check if error is reported for invalid type (2) options
 211         // (flags with type information specified)
 212         for (String[] arguments: TYPE_2_INVALID_ARGUMENTS) {
 213             verifyInvalidOption(arguments);
 214         }
 215     }
 216 }