Some test cases for switch expression

Brian Goetz brian.goetz at oracle.com
Mon Apr 16 19:19:00 UTC 2018


I just pushed the start of a test framework, based on the existing javac 
combo-test framework, for testing the nesting of constructs with 
nonlocal control flow.  I did the first few easy ones :)

It starts with some snippets:

     private static final String RUNNABLE = "Runnable r = () -> { # };";
     private static final String INT_FN = 
"java.util.function.IntSupplier r = () -> { # };";
     private static final String LABEL = "label: #";
     private static final String FOR = "for (int i=0; i<10; i++) { # };";
     private static final String WHILE = "while (cond) { # };";
     private static final String DO = "do { # } while (cond);";
     private static final String SSWITCH = "switch (x) { case 0: # };";
     private static final String ESWITCH = "int res = switch (x) { case 
0: # default -> 0; };";
     private static final String IF = "if (cond) { # };";
     private static final String BLOCK = "{ # };";
     private static final String BREAK_Z = "break 0;";
     private static final String BREAK_N = "break;";
     private static final String BREAK_L = "break label;";
     private static final String RETURN_Z = "return 0;";
     private static final String RETURN_N = "return;";
     private static final String CONTINUE_N = "continue;";
     private static final String CONTINUE_L = "continue label;";
     private static final String NOTHING = "System.out.println();";

where # means "expand the next snippet here".  This lets you set up 
chains of nesting, like "LABEL, FOR, ESWITCH, BREAK_L", which means 
"labeled-break in expr-switch in for-loop in labeled-statement".

Then you can assert whether things compile or not, and if not, with what 
diagnostic.  Here's the rules for lambdas:

     public void testLambda() {
         assertOK(RUNNABLE, RETURN_N);
         assertOK(RUNNABLE, NOTHING);
         assertOK(INT_FN, RETURN_Z);
         assertFail("compiler.err.break.outside.switch.loop", RUNNABLE, 
BREAK_N);
assertFail("compiler.err.break.complex.value.no.switch.expression", 
INT_FN, BREAK_Z);
         assertFail("compiler.err.cont.outside.loop", RUNNABLE, CONTINUE_N);
         assertFail("compiler.err.undef.label", RUNNABLE, BREAK_L);
         assertFail("compiler.err.undef.label", RUNNABLE, CONTINUE_L);
         assertFail("compiler.err.undef.label", LABEL, BLOCK, RUNNABLE, 
BREAK_L);
         assertFail("compiler.err.undef.label", LABEL, BLOCK, RUNNABLE, 
CONTINUE_L);
     }

which means that its OK to return out of a lambda, but not to break or 
continue.

Here's the rules for expression switch:

     public void testEswitch() {
         assertOK(ESWITCH, BREAK_Z);
         assertOK(LABEL, BLOCK, ESWITCH, BREAK_Z);
         assertFail("compiler.err.break.missing.value", ESWITCH, BREAK_N);
         assertFail("compiler.err.cant.resolve.location", ESWITCH, BREAK_L);
         assertFail("compiler.err.break.outside.switch.expression", 
LABEL, BLOCK, ESWITCH, BREAK_L);
         assertFail("compiler.err.undef.label", ESWITCH, CONTINUE_L);
         assertFail("compiler.err.cont.outside.loop", ESWITCH, CONTINUE_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH, 
RETURN_N);
assertFail("compiler.err.return.outside.switch.expression", ESWITCH, 
RETURN_Z);
     }

It's a good start.





More information about the amber-dev mailing list