1 /*
2  * Copyright (c) 2012, 2016, 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 /*
25  * @test
26  * @summary Test that the diagnostic command arguemnt parser works
27  * @modules java.base/jdk.internal.misc
28  * @library /test/lib
29  * @build sun.hotspot.WhiteBox
30  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
31  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
32  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest
33  */
34 
35 import java.math.BigInteger;
36 
37 import sun.hotspot.parser.DiagnosticCommand;
38 import sun.hotspot.parser.DiagnosticCommand.DiagnosticArgumentType;
39 import sun.hotspot.WhiteBox;
40 
41 public class ParserTest {
42     WhiteBox wb;
43 
ParserTest()44     public ParserTest() throws Exception {
45         wb = WhiteBox.getWhiteBox();
46 
47         testNanoTime();
48         testJLong();
49         testBool();
50         testQuotes();
51         testMemorySize();
52         testSingleLetterArg();
53     }
54 
main(String... args)55     public static void main(String... args) throws Exception  {
56          new ParserTest();
57     }
58 
testNanoTime()59     public void testNanoTime() throws Exception {
60         String name = "name";
61         DiagnosticCommand arg = new DiagnosticCommand(name,
62                 "desc", DiagnosticArgumentType.NANOTIME,
63                 false, "0");
64         DiagnosticCommand[] args = {arg};
65 
66         BigInteger bi = new BigInteger("7");
67         //These should work
68         parse(name, bi.toString(), name + "=7ns", args);
69 
70         bi = bi.multiply(BigInteger.valueOf(1000));
71         parse(name, bi.toString(), name + "=7us", args);
72 
73         bi = bi.multiply(BigInteger.valueOf(1000));
74         parse(name, bi.toString(), name + "=7ms", args);
75 
76         bi = bi.multiply(BigInteger.valueOf(1000));
77         parse(name, bi.toString(), name + "=7s", args);
78 
79         bi = bi.multiply(BigInteger.valueOf(60));
80         parse(name, bi.toString() , name + "=7m", args);
81 
82         bi = bi.multiply(BigInteger.valueOf(60));
83         parse(name, bi.toString() , name + "=7h", args);
84 
85         bi = bi.multiply(BigInteger.valueOf(24));
86         parse(name, bi.toString() , name + "=7d", args);
87 
88         parse(name, "0", name + "=0", args);
89 
90         shouldFail(name + "=7xs", args);
91         shouldFail(name + "=7mms", args);
92         shouldFail(name + "=7f", args);
93         //Currently, only value 0 is allowed without unit
94         shouldFail(name + "=7", args);
95     }
96 
testJLong()97     public void testJLong() throws Exception {
98         String name = "name";
99         DiagnosticCommand arg = new DiagnosticCommand(name,
100                 "desc", DiagnosticArgumentType.JLONG,
101                 false, "0");
102         DiagnosticCommand[] args = {arg};
103 
104         wb.parseCommandLine(name + "=10", ',', args);
105         parse(name, "10", name + "=10", args);
106         parse(name, "-5", name + "=-5", args);
107 
108         //shouldFail(name + "=12m", args); <-- should fail, doesn't
109     }
110 
testBool()111     public void testBool() throws Exception {
112         String name = "name";
113         DiagnosticCommand arg = new DiagnosticCommand(name,
114                 "desc", DiagnosticArgumentType.BOOLEAN,
115                 false, "false");
116         DiagnosticCommand[] args = {arg};
117 
118         parse(name, "true", name + "=true", args);
119         parse(name, "false", name + "=false", args);
120         parse(name, "true", name, args);
121 
122         //Empty commandline to parse, tests default value
123         //of the parameter "name"
124         parse(name, "false", "", args);
125     }
126 
testQuotes()127     public void testQuotes() throws Exception {
128         String name = "name";
129         DiagnosticCommand arg1 = new DiagnosticCommand(name,
130                 "desc", DiagnosticArgumentType.STRING,
131                 false, null);
132         DiagnosticCommand arg2 = new DiagnosticCommand("arg",
133                 "desc", DiagnosticArgumentType.STRING,
134                 false, null);
135         DiagnosticCommand[] args = {arg1, arg2};
136 
137         // try with a quoted value
138         parse(name, "Recording 1", name + "=\"Recording 1\"", args);
139         // try with a quoted argument
140         parse(name, "myrec", "\"" + name + "\"" + "=myrec", args);
141         // try with both a quoted value and a quoted argument
142         parse(name, "Recording 1", "\"" + name + "\"" + "=\"Recording 1\"", args);
143 
144         // now the same thing but with other arguments after
145 
146         // try with a quoted value
147         parse(name, "Recording 1", name + "=\"Recording 1\",arg=value", args);
148         // try with a quoted argument
149         parse(name, "myrec", "\"" + name + "\"" + "=myrec,arg=value", args);
150         // try with both a quoted value and a quoted argument
151         parse(name, "Recording 1", "\"" + name + "\"" + "=\"Recording 1\",arg=value", args);
152     }
153 
testSingleLetterArg()154     public void testSingleLetterArg() throws Exception {
155         DiagnosticCommand[] args = new DiagnosticCommand[]{
156             new DiagnosticCommand("flag", "desc", DiagnosticArgumentType.STRING, true, false, null),
157             new DiagnosticCommand("value", "desc", DiagnosticArgumentType.STRING, true, false, null)
158         };
159         parse("flag", "flag", "flag v", ' ', args);
160         parse("value", "v", "flag v", ' ', args);
161     }
162 
testMemorySize()163     public void testMemorySize() throws Exception {
164         String name = "name";
165         String defaultValue = "1024";
166         DiagnosticCommand arg = new DiagnosticCommand(name,
167                 "desc", DiagnosticArgumentType.MEMORYSIZE,
168                 false, defaultValue);
169         DiagnosticCommand[] args = {arg};
170 
171         BigInteger bi = new BigInteger("7");
172         parse(name, bi.toString(), name + "=7b", args);
173 
174         bi = bi.multiply(BigInteger.valueOf(1024));
175         parse(name, bi.toString(), name + "=7k", args);
176 
177         bi = bi.multiply(BigInteger.valueOf(1024));
178         parse(name, bi.toString(), name + "=7m", args);
179 
180         bi = bi.multiply(BigInteger.valueOf(1024));
181         parse(name, bi.toString(), name + "=7g", args);
182         parse(name, defaultValue, "", args);
183 
184         //shouldFail(name + "=7gg", args); <---- should fail, doesn't
185         //shouldFail(name + "=7t", args);  <----- should fail, doesn't
186     }
187 
parse(String searchName, String expectedValue, String cmdLine, DiagnosticCommand[] argumentTypes)188     public void parse(String searchName, String expectedValue,
189             String cmdLine, DiagnosticCommand[] argumentTypes) throws Exception {
190         parse(searchName, expectedValue, cmdLine, ',', argumentTypes);
191     }
parse(String searchName, String expectedValue, String cmdLine, char delim, DiagnosticCommand[] argumentTypes)192     public void parse(String searchName, String expectedValue,
193             String cmdLine, char delim, DiagnosticCommand[] argumentTypes) throws Exception {
194         //parseCommandLine will return an object array that looks like
195         //{<name of parsed object>, <of parsed object> ... }
196         Object[] res = wb.parseCommandLine(cmdLine, delim, argumentTypes);
197         for (int i = 0; i < res.length-1; i+=2) {
198             String parsedName = (String) res[i];
199             if (searchName.equals(parsedName)) {
200                 String parsedValue = (String) res[i+1];
201                 if (expectedValue.equals(parsedValue)) {
202                     return;
203                 } else {
204                     throw new Exception("Parsing of cmdline '" + cmdLine + "' failed!\n"
205                             + searchName + " parsed as " + parsedValue
206                             + "! Expected: " + expectedValue);
207                 }
208             }
209         }
210         throw new Exception(searchName + " not found as a parsed Argument!");
211     }
212 
shouldFail(String argument, DiagnosticCommand[] argumentTypes)213     private void shouldFail(String argument, DiagnosticCommand[] argumentTypes) throws Exception {
214         shouldFail(argument, ',', argumentTypes);
215     }
shouldFail(String argument, char delim, DiagnosticCommand[] argumentTypes)216     private void shouldFail(String argument, char delim, DiagnosticCommand[] argumentTypes) throws Exception {
217         try {
218             wb.parseCommandLine(argument, delim, argumentTypes);
219             throw new Exception("Parser accepted argument: " + argument);
220         } catch (IllegalArgumentException e) {
221             //expected
222         }
223     }
224 }
225