1 /*
   2  * Copyright (c) 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  * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089
  27  * @summary Simple jshell tool tests
  28  * @modules jdk.compiler/com.sun.tools.javac.api
  29  *          jdk.compiler/com.sun.tools.javac.main
  30  *          jdk.jdeps/com.sun.tools.javap
  31  *          jdk.jshell/jdk.internal.jshell.tool
  32  * @build KullaTesting TestingInputStream
  33  * @run testng ToolSimpleTest
  34  */
  35 import java.util.Arrays;
  36 import java.util.ArrayList;
  37 import java.util.List;
  38 import java.util.function.Consumer;
  39 import java.util.stream.Collectors;
  40 import java.util.stream.Stream;
  41 
  42 import org.testng.annotations.Test;
  43 
  44 import static org.testng.Assert.assertEquals;
  45 import static org.testng.Assert.assertTrue;
  46 
  47 @Test
  48 public class ToolSimpleTest extends ReplToolTesting {
  49 
  50     public void testRemaining() {
  51         test(
  52                 (a) -> assertCommand(a, "int z; z =", "z ==> 0"),
  53                 (a) -> assertCommand(a, "5", "z ==> 5"),
  54                 (a) -> assertCommand(a, "/*nada*/; int q =", ""),
  55                 (a) -> assertCommand(a, "77", "q ==> 77"),
  56                 (a) -> assertCommand(a, "//comment;", ""),
  57                 (a) -> assertCommand(a, "int v;", "v ==> 0"),
  58                 (a) -> assertCommand(a, "int v; int c",
  59                         "v ==> 0\n" +
  60                         "c ==> 0")
  61         );
  62     }
  63 
  64     public void testOpenComment() {
  65         test(
  66                 (a) -> assertCommand(a, "int z = /* blah", ""),
  67                 (a) -> assertCommand(a, "baz */ 5", "z ==> 5"),
  68                 (a) -> assertCommand(a, "/** hoge ", ""),
  69                 (a) -> assertCommand(a, "baz **/", ""),
  70                 (a) -> assertCommand(a, "int v", "v ==> 0")
  71         );
  72     }
  73 
  74     public void oneLineOfError() {
  75         test(
  76                 (a) -> assertCommand(a, "12+", null),
  77                 (a) -> assertCommandCheckOutput(a, "  true", (s) ->
  78                         assertTrue(s.contains("12+") && !s.contains("true"), "Output: '" + s + "'"))
  79         );
  80     }
  81 
  82     public void defineVariables() {
  83         test(
  84                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
  85                 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
  86                 (a) -> assertVariable(a, "int", "a"),
  87                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
  88                 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
  89                 (a) -> assertVariable(a, "double", "a", "1", "1.0"),
  90                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
  91                 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
  92                 (a) -> evaluateExpression(a, "double", "2 * a", "2.0"),
  93                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
  94                 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables())
  95         );
  96     }
  97 
  98     public void defineMethods() {
  99         test(
 100                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 101                 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 102                 (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
 103                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 104                 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 105                 (a) -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"),
 106                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 107                 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 108                 (a) -> assertMethod(a, "void g() {}", "()void", "g"),
 109                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 110                 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods())
 111         );
 112     }
 113 
 114     public void defineTypes() {
 115         test(
 116                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 117                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 118                 (a) -> assertClass(a, "class A { }", "class", "A"),
 119                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 120                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 121                 (a) -> assertClass(a, "interface A { }", "interface", "A"),
 122                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 123                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 124                 (a) -> assertClass(a, "enum A { }", "enum", "A"),
 125                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 126                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 127                 (a) -> assertClass(a, "@interface A { }", "@interface", "A"),
 128                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 129                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses())
 130         );
 131     }
 132 
 133     public void defineImports() {
 134         test(
 135                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 136                 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
 137                 (a) -> assertImport(a, "import java.util.stream.Stream;", "", "java.util.stream.Stream"),
 138                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 139                 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
 140                 (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
 141                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 142                 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
 143                 (a) -> assertImport(a, "import static java.lang.Math.PI;", "static", "java.lang.Math.PI"),
 144                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 145                 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
 146                 (a) -> assertImport(a, "import static java.lang.Math.*;", "static", "java.lang.Math.*"),
 147                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 148                 (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
 149         );
 150     }
 151 
 152     public void defineVar() {
 153         test(
 154                 (a) -> assertCommand(a, "int x = 72", "x ==> 72"),
 155                 (a) -> assertCommand(a, "x", "x ==> 72"),
 156                 (a) -> assertCommand(a, "/vars", "|    int x = 72")
 157         );
 158     }
 159 
 160     @Test(enabled = false) // TODO 8153897
 161     public void defineUnresolvedVar() {
 162         test(
 163                 (a) -> assertCommand(a, "undefined x",
 164                         "|  created variable x, however, it cannot be referenced until class undefined is declared"),
 165                 (a) -> assertCommand(a, "/vars", "|    undefined x = (not-active)")
 166         );
 167     }
 168 
 169     public void testUnresolved() {
 170         test(
 171                 (a) -> assertCommand(a, "int f() { return g() + x + new A().a; }",
 172                         "|  created method f(), however, it cannot be invoked until method g(), variable x, and class A are declared"),
 173                 (a) -> assertCommand(a, "f()",
 174                         "|  attempted to call method f() which cannot be invoked until method g(), variable x, and class A are declared"),
 175                 (a) -> assertCommandOutputStartsWith(a, "int g() { return x; }",
 176                         "|  created method g(), however, it cannot be invoked until variable x is declared"),
 177                 (a) -> assertCommand(a, "g()", "|  attempted to call method g() which cannot be invoked until variable x is declared")
 178         );
 179     }
 180 
 181     public void testUnknownCommand() {
 182         test((a) -> assertCommand(a, "/unknown",
 183                 "|  No such command or snippet id: /unknown\n" +
 184                 "|  Type /help for help."));
 185     }
 186 
 187     public void testEmptyClassPath() {
 188         test(after -> assertCommand(after, "/classpath", "|  The /classpath command requires a path argument."));
 189     }
 190 
 191     public void testNoArgument() {
 192         test(
 193                 (a) -> assertCommand(a, "/save",
 194                         "|  '/save' requires a filename argument."),
 195                 (a) -> assertCommand(a, "/open",
 196                         "|  '/open' requires a filename argument."),
 197                 (a) -> assertCommand(a, "/set start",
 198                         "|  Specify either one option or a startup file name -- /set start")
 199         );
 200     }
 201 
 202     public void testDebug() {
 203         test(
 204                 (a) -> assertCommand(a, "/deb", "|  Debugging on"),
 205                 (a) -> assertCommand(a, "/debug", "|  Debugging off"),
 206                 (a) -> assertCommand(a, "/debug", "|  Debugging on"),
 207                 (a) -> assertCommand(a, "/deb", "|  Debugging off")
 208         );
 209     }
 210 
 211     public void testDrop() {
 212         test(false, new String[]{"--no-startup"},
 213                 a -> assertVariable(a, "int", "a"),
 214                 a -> dropVariable(a, "/drop 1", "int a = 0", "|  dropped variable a"),
 215                 a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
 216                 a -> dropMethod(a, "/drop 2", "b ()I", "|  dropped method b()"),
 217                 a -> assertClass(a, "class A {}", "class", "A"),
 218                 a -> dropClass(a, "/drop 3", "class A", "|  dropped class A"),
 219                 a -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
 220                 a -> dropImport(a, "/drop 4", "import java.util.stream.*", ""),
 221                 a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
 222                 a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 223                 a -> assertCommandCheckOutput(a, "/types", assertClasses()),
 224                 a -> assertCommandCheckOutput(a, "/imports", assertImports())
 225         );
 226         test(false, new String[]{"--no-startup"},
 227                 a -> assertVariable(a, "int", "a"),
 228                 a -> dropVariable(a, "/drop a", "int a = 0", "|  dropped variable a"),
 229                 a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
 230                 a -> dropMethod(a, "/drop b", "b ()I", "|  dropped method b()"),
 231                 a -> assertClass(a, "class A {}", "class", "A"),
 232                 a -> dropClass(a, "/drop A", "class A", "|  dropped class A"),
 233                 a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
 234                 a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 235                 a -> assertCommandCheckOutput(a, "/types", assertClasses()),
 236                 a -> assertCommandCheckOutput(a, "/imports", assertImports())
 237         );
 238     }
 239 
 240     public void testDropNegative() {
 241         test(false, new String[]{"--no-startup"},
 242                 a -> assertCommandOutputStartsWith(a, "/drop 0", "|  No such snippet: 0"),
 243                 a -> assertCommandOutputStartsWith(a, "/drop a", "|  No such snippet: a"),
 244                 a -> assertCommandCheckOutput(a, "/drop",
 245                         assertStartsWith("|  In the /drop argument, please specify an import, variable, method, or class to drop.")),
 246                 a -> assertVariable(a, "int", "a"),
 247                 a -> assertCommand(a, "a", "a ==> 0"),
 248                 a -> assertCommand(a, "/drop 2",
 249                         "|  This command does not accept the snippet '2' : a\n" +
 250                         "|  See /types, /methods, /vars, or /list")
 251         );
 252     }
 253 
 254     public void testAmbiguousDrop() {
 255         Consumer<String> check = s -> {
 256             assertTrue(s.startsWith("|  The argument references more than one import, variable, method, or class"), s);
 257             int lines = s.split("\n").length;
 258             assertEquals(lines, 5, "Expected 3 ambiguous keys, but found: " + (lines - 2) + "\n" + s);
 259         };
 260         test(
 261                 a -> assertVariable(a, "int", "a"),
 262                 a -> assertMethod(a, "int a() { return 0; }", "()int", "a"),
 263                 a -> assertClass(a, "class a {}", "class", "a"),
 264                 a -> assertCommandCheckOutput(a, "/drop a", check),
 265                 a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
 266                 a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
 267                 a -> assertCommandCheckOutput(a, "/types", assertClasses()),
 268                 a -> assertCommandCheckOutput(a, "/imports", assertImports())
 269         );
 270         test(
 271                 a -> assertMethod(a, "int a() { return 0; }", "()int", "a"),
 272                 a -> assertMethod(a, "double a(int a) { return 0; }", "(int)double", "a"),
 273                 a -> assertMethod(a, "double a(double a) { return 0; }", "(double)double", "a"),
 274                 a -> assertCommandCheckOutput(a, "/drop a", check),
 275                 a -> assertCommandCheckOutput(a, "/methods", assertMethods())
 276         );
 277     }
 278 
 279     public void testHelpLength() {
 280         Consumer<String> testOutput = (s) -> {
 281             List<String> ss = Stream.of(s.split("\n"))
 282                     .filter(l -> !l.isEmpty())
 283                     .collect(Collectors.toList());
 284             assertTrue(ss.size() >= 10, "Help does not print enough lines:" + s);
 285         };
 286         test(
 287                 (a) -> assertCommandCheckOutput(a, "/?", testOutput),
 288                 (a) -> assertCommandCheckOutput(a, "/help", testOutput),
 289                 (a) -> assertCommandCheckOutput(a, "/help /list", testOutput)
 290         );
 291     }
 292 
 293     public void testHelp() {
 294         test(
 295                 (a) -> assertHelp(a, "/?", "/list", "/help", "/exit", "intro"),
 296                 (a) -> assertHelp(a, "/help", "/list", "/help", "/exit", "intro"),
 297                 (a) -> assertHelp(a, "/help short", "shortcuts", "<tab>"),
 298                 (a) -> assertHelp(a, "/? /li", "/list -all", "snippets"),
 299                 (a) -> assertHelp(a, "/help /help", "/help <command>")
 300         );
 301     }
 302 
 303     private void assertHelp(boolean a, String command, String... find) {
 304         assertCommandCheckOutput(a, command, s -> {
 305             for (String f : find) {
 306                 assertTrue(s.contains(f), "Expected output of " + command + " to contain: " + f);
 307             }
 308         });
 309     }
 310 
 311     // Check that each line of output contains the corresponding string from the list
 312     private void checkLineToList(String in, List<String> match) {
 313         String trimmed = in.trim();
 314         String[] res = trimmed.isEmpty()
 315                 ? new String[0]
 316                 : trimmed.split("\n");
 317         assertEquals(res.length, match.size(), "Got: " + Arrays.asList(res));
 318         for (int i = 0; i < match.size(); ++i) {
 319             assertTrue(res[i].contains(match.get(i)));
 320         }
 321     }
 322 
 323     public void testListArgs() {
 324         String arg = "qqqq";
 325         List<String> startVarList = new ArrayList<>(START_UP);
 326         startVarList.add("int aardvark");
 327         test(
 328                 a -> assertCommandCheckOutput(a, "/list -all",
 329                         s -> checkLineToList(s, START_UP)),
 330                 a -> assertCommandOutputStartsWith(a, "/list " + arg,
 331                         "|  No such snippet: " + arg),
 332                 a -> assertVariable(a, "int", "aardvark"),
 333                 a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"),
 334                 a -> assertCommandCheckOutput(a, "/list -start",
 335                         s -> checkLineToList(s, START_UP)),
 336                 a -> assertCommandCheckOutput(a, "/list -all",
 337                         s -> checkLineToList(s, startVarList)),
 338                 a -> assertCommandCheckOutput(a, "/list printf",
 339                         s -> assertTrue(s.contains("void printf"))),
 340                 a -> assertCommandOutputStartsWith(a, "/list " + arg,
 341                         "|  No such snippet: " + arg)
 342         );
 343     }
 344 
 345     public void testVarsArgs() {
 346         String arg = "qqqq";
 347         List<String> startVarList = new ArrayList<>();
 348         test(
 349                 a -> assertCommandCheckOutput(a, "/vars -all",
 350                         s -> checkLineToList(s, startVarList)),
 351                 a -> assertCommand(a, "/vars " + arg,
 352                         "|  No such snippet: " + arg),
 353                 a -> assertVariable(a, "int", "aardvark"),
 354                 a -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
 355                 a -> assertVariable(a, "int", "a"),
 356                 a -> assertVariable(a, "double", "a", "1", "1.0"),
 357                 a -> assertCommandOutputStartsWith(a, "/vars aardvark",
 358                         "|    int aardvark = 0"),
 359                 a -> assertCommandCheckOutput(a, "/vars -start",
 360                         s -> checkLineToList(s, startVarList)),
 361                 a -> assertCommandOutputStartsWith(a, "/vars -all",
 362                         "|    int aardvark = 0\n|    int a = "),
 363                 a -> assertCommandOutputStartsWith(a, "/vars printf",
 364                         "|  This command does not accept the snippet 'printf'"),
 365                 a -> assertCommand(a, "/var " + arg,
 366                         "|  No such snippet: " + arg)
 367         );
 368     }
 369 
 370     public void testMethodsArgs() {
 371         String arg = "qqqq";
 372         List<String> startMethodList = new ArrayList<>(START_UP_CMD_METHOD);
 373         test(
 374                 a -> assertCommandCheckOutput(a, "/methods -all",
 375                         s -> checkLineToList(s, startMethodList)),
 376                 a -> assertCommandCheckOutput(a, "/methods -start",
 377                         s -> checkLineToList(s, startMethodList)),
 378                 a -> assertCommandCheckOutput(a, "/methods printf",
 379                         s -> checkLineToList(s, startMethodList)),
 380                 a -> assertCommandCheckOutput(a, "/methods",
 381                         s -> checkLineToList(s, startMethodList)),
 382                 a -> assertCommandOutputStartsWith(a, "/methods " + arg,
 383                         "|  No such snippet: " + arg),
 384                 a -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
 385                 a -> assertVariable(a, "int", "aardvark"),
 386                 a -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"),
 387                 a -> assertMethod(a, "void g() {}", "()void", "g"),
 388                 a -> assertCommandOutputStartsWith(a, "/methods " + arg,
 389                         "|  No such snippet: " + arg),
 390                 a -> assertCommandOutputStartsWith(a, "/methods aardvark",
 391                         "|  This command does not accept the snippet 'aardvark' : int aardvark"),
 392                 a -> assertCommandCheckOutput(a, "/methods -start",
 393                         s -> checkLineToList(s, startMethodList)),
 394                 a -> assertCommandCheckOutput(a, "/methods printf",
 395                         s -> checkLineToList(s, startMethodList)),
 396                 a -> assertCommandOutputStartsWith(a, "/methods g",
 397                         "|    g ()void"),
 398                 a -> assertCommandOutputStartsWith(a, "/methods f",
 399                         "|    f ()int\n" +
 400                         "|    f (int)void")
 401         );
 402     }
 403 
 404     public void testTypesArgs() {
 405         String arg = "qqqq";
 406         List<String> startTypeList = new ArrayList<>();
 407         test(
 408                 a -> assertCommandCheckOutput(a, "/types -all",
 409                         s -> checkLineToList(s, startTypeList)),
 410                 a -> assertCommandCheckOutput(a, "/types -start",
 411                         s -> checkLineToList(s, startTypeList)),
 412                 a -> assertCommandOutputStartsWith(a, "/types " + arg,
 413                         "|  No such snippet: " + arg),
 414                 a -> assertVariable(a, "int", "aardvark"),
 415                 (a) -> assertClass(a, "class A { }", "class", "A"),
 416                 (a) -> assertClass(a, "interface A { }", "interface", "A"),
 417                 a -> assertCommandOutputStartsWith(a, "/types -all",
 418                         "|    class A\n" +
 419                         "|    interface A"),
 420                 (a) -> assertClass(a, "enum E { }", "enum", "E"),
 421                 (a) -> assertClass(a, "@interface B { }", "@interface", "B"),
 422                 a -> assertCommand(a, "/types aardvark",
 423                         "|  This command does not accept the snippet 'aardvark' : int aardvark;"),
 424                 a -> assertCommandOutputStartsWith(a, "/types A",
 425                         "|    interface A"),
 426                 a -> assertCommandOutputStartsWith(a, "/types E",
 427                         "|    enum E"),
 428                 a -> assertCommandOutputStartsWith(a, "/types B",
 429                         "|    @interface B"),
 430                 a -> assertCommandOutputStartsWith(a, "/types " + arg,
 431                         "|  No such snippet: " + arg),
 432                 a -> assertCommandCheckOutput(a, "/types -start",
 433                         s -> checkLineToList(s, startTypeList))
 434         );
 435     }
 436     public void defineClasses() {
 437         test(
 438                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 439                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 440                 (a) -> assertClass(a, "class A { }", "class", "A"),
 441                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 442                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 443                 (a) -> assertClass(a, "interface A { }", "interface", "A"),
 444                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 445                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 446                 (a) -> assertClass(a, "enum A { }", "enum", "A"),
 447                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 448                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
 449                 (a) -> assertClass(a, "@interface A { }", "@interface", "A"),
 450                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
 451                 (a) -> assertCommandCheckOutput(a, "/types", assertClasses())
 452         );
 453     }
 454     public void testCommandPrefix() {
 455         test(a -> assertCommandCheckOutput(a, "/s",
 456                       assertStartsWith("|  Command: '/s' is ambiguous: /save, /set")),
 457              a -> assertCommand(a, "int var", "var ==> 0"),
 458              a -> assertCommandCheckOutput(a, "/va",
 459                       assertStartsWith("|    int var = 0")),
 460              a -> assertCommandCheckOutput(a, "/save",
 461                       assertStartsWith("|  '/save' requires a filename argument.")));
 462     }
 463 
 464     public void testOptionQ() {
 465         test(new String[]{"-q", "--no-startup"},
 466                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
 467                 (a) -> assertCommand(a, "int x = 5", "")
 468         );
 469     }
 470 
 471     public void testOptionQq() {
 472         test(new String[]{"-s", "--no-startup"},
 473                 (a) -> assertCommand(a, "1+1", "")
 474         );
 475     }
 476 
 477     public void testOptionV() {
 478         test(new String[]{"-v", "--no-startup"},
 479                 (a) -> assertCommand(a, "1+1",
 480                         "$1 ==> 2\n" +
 481                         "|  created scratch variable $1 : int")
 482         );
 483     }
 484 
 485     public void testOptionFeedback() {
 486         test(new String[]{"--feedback", "concise", "--no-startup"},
 487                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
 488                 (a) -> assertCommand(a, "int x = 5", "")
 489         );
 490     }
 491 
 492     public void testOptionR() {
 493         test(new String[]{"-R-Dthe.sound=blorp", "--no-startup"},
 494                 (a) -> assertCommand(a, "System.getProperty(\"the.sound\")",
 495                         "$1 ==> \"blorp\"")
 496         );
 497     }
 498 
 499     public void test8156910() {
 500         test(
 501                 (a) -> assertCommandOutputContains(a, "System.out.println(\"%5d\", 10);", "%5d"),
 502                 (a) -> assertCommandOutputContains(a, "1234", "==> 1234")
 503         );
 504     }
 505 }