1 /*
   2  * @test  /nodynamiccopyright/
   3  * @bug 6827009
   4  * @summary Check for non-constant case labels
   5  * @compile/fail -source 6 OneCaseSwitches.java
   6  * @compile                OneCaseSwitches.java
   7  * @run main OneCaseSwitches
   8  * @author  Joseph D. Darcy
   9  */
  10 
  11 import java.lang.reflect.*;
  12 import java.lang.annotation.*;
  13 import java.util.*;
  14 import static java.lang.annotation.RetentionPolicy.*;
  15 
  16 public class OneCaseSwitches {
  17     @Retention(RUNTIME)
  18     @interface TestMeForNull {}
  19 
  20     @TestMeForNull
  21     public static int zeroCasesNoDefault(String s, Set<String> stringSet, boolean expected) {
  22         int failures = 0;
  23         switch(s) {
  24         }
  25         return failures;
  26     }
  27 
  28     @TestMeForNull
  29     public static int zeroCasesWithDefault(String s, Set<String> stringSet, boolean expected) {
  30         int failures = 2;
  31         boolean addResult;
  32 
  33         switch(s) {
  34         default:
  35             failures = 0;
  36             addResult = stringSet.add(s);
  37             if (addResult != expected) {
  38                 failures++;
  39                 System.err.println("zeroCaseWithDefault: Expectedly got add result of " + addResult + 
  40                                    " on string " + s);
  41             }
  42         }
  43 
  44         return failures;
  45     }
  46 
  47     @TestMeForNull
  48     public static int zeroCasesWithDefaultBreak(String s, Set<String> stringSet, boolean expected) {
  49         int failures = 2;
  50         boolean addResult;
  51 
  52         switch(s) {
  53         default:
  54             failures = zeroCasesWithDefault(s, stringSet, expected);
  55             break;
  56         }
  57 
  58         return failures;
  59     }
  60 
  61     @TestMeForNull
  62     public static int oneCaseNoDefault(String s, Set<String> stringSet, boolean expected) {
  63         int failures = 2;
  64         boolean addResult;
  65 
  66         switch(s) {
  67         case "foo":
  68             failures = 0;
  69             addResult = stringSet.add(s);
  70             if (addResult != expected) {
  71                 failures++;
  72                 System.err.println("oneCaseNoDefault: Unexpectedly got add result of " + addResult + 
  73                                    " on string " + s);
  74             }
  75         }
  76 
  77         return failures;
  78     }
  79 
  80     @TestMeForNull
  81     public static int oneCaseNoDefaultBreak(String s, Set<String> stringSet, boolean expected) {
  82         int failures = 2;
  83         boolean addResult;
  84 
  85         switch(s) {
  86         case "foo":
  87             failures = oneCaseNoDefaultBreak(s, stringSet, expected);
  88             break;
  89         }
  90 
  91         return failures;
  92     }
  93 
  94     @TestMeForNull
  95     public static int oneCaseWithDefault(String s, Set<String> stringSet, boolean expected) {
  96         int failures = 2;
  97         boolean addResult;;
  98 
  99         switch(s) {
 100         case "foo":
 101             failures = 0;
 102             addResult = stringSet.add(s);
 103             if (addResult != expected) {
 104                 failures++;
 105                 System.err.println("oneCaseNoDefault: Expectedly got add result of " + addResult + 
 106                                    " on string " + s);
 107             }
 108             break;
 109         default:
 110             
 111             break;
 112         }
 113 
 114         return failures;
 115     }
 116 
 117     @TestMeForNull
 118     public static int oneCaseBreakOnly(String s, Set<String> stringSet, boolean expected) {
 119         int failures = 1;
 120         switch(s) {
 121         case "foo":
 122             break;
 123         }
 124         failures = 0;
 125         return failures;
 126     }
 127 
 128     @TestMeForNull
 129     public static int oneCaseDefaultBreakOnly(String s, Set<String> stringSet, boolean expected) {
 130         int failures = 1;
 131         switch(s) {
 132         default:
 133             break;
 134         }
 135         failures = 0;
 136         return failures;
 137     }
 138 
 139 
 140     static int testNullBehavior() {
 141         int failures = 0;
 142         int count = 0;
 143 
 144         Method[] methods = OneCaseSwitches.class.getDeclaredMethods();
 145 
 146         try { 
 147             for(Method method : methods) {
 148                 count++;
 149                 try {
 150                     if (method.isAnnotationPresent(TestMeForNull.class)) {
 151                         System.out.println("Testing method " + method);
 152                         method.invoke(null, (String)null, emptyStringSet, false);
 153                         failures++;
 154                         System.err.println("Didn't get NPE as expected from " + method);
 155                     }
 156                 } catch (InvocationTargetException ite) { // Expected
 157                     Throwable targetException = ite.getTargetException();
 158                     if (! (targetException instanceof NullPointerException)) {
 159                         failures++; // Wrong exception thrown
 160                         System.err.println("Didn't get expected target exception NPE, got " + 
 161                                            ite.getClass().getName());
 162                     }
 163                 }
 164             }
 165         } catch (Exception e) {
 166             throw new RuntimeException(e);
 167         }
 168 
 169         if (count == 0) {
 170             failures++;
 171             System.err.println("Did not find any annotated methods.");
 172         }
 173         
 174         return failures;
 175     }
 176 
 177     static int testZeroCases() {
 178         int failures = 0;
 179         Set<String> noDefaultSet = new HashSet<String>();
 180         Set<String> defaultSet   = new HashSet<String>();
 181 
 182         zeroCasesNoDefault(FOO, noDefaultSet, false);
 183         for(String word : words) {
 184             zeroCasesNoDefault(word, noDefaultSet, false);
 185         }
 186         
 187         if (!noDefaultSet.isEmpty()) {
 188             failures++;
 189             System.err.println("Non-empty set after zeroCasesNoDefault");
 190         }
 191 
 192         for(String word : words) {
 193             zeroCasesWithDefault(word, defaultSet, true);
 194         }
 195         if (defaultSet.size() != words.length) {
 196             failures++;
 197             System.err.println("Missing strings after zeroCasesWithDefault");
 198         }
 199 
 200         return failures;
 201     }
 202 
 203     static int testOneCaseNoDefault() {
 204         int failures = 0;
 205         Set<String> s = new HashSet<String>();
 206         s.add("foo");
 207         Set<String> fooSet = Collections.unmodifiableSet(s);
 208         Set<String> testSet   = new HashSet<String>();
 209 
 210         oneCaseNoDefault(FOO, testSet, true);
 211         if (!testSet.equals(fooSet)) {
 212             failures++;
 213             System.err.println("Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}");
 214         }
 215 
 216         for(String word : words) {
 217             oneCaseNoDefault(word, testSet, false);
 218         }
 219         if (!testSet.equals(fooSet)) {
 220             failures++;
 221             System.err.println("Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}");
 222         }
 223 
 224         return failures;
 225     }
 226 
 227     static int testBreakOnly() {
 228         int failures = 0;
 229 
 230         for(String word : words) {
 231             failures += oneCaseBreakOnly(word, emptyStringSet, true);
 232             failures += oneCaseDefaultBreakOnly(word, emptyStringSet, true);
 233         }
 234 
 235         return failures;
 236     }
 237 
 238     static int testExpressionEval() {
 239         String s = "a";
 240         int errors = 2;
 241 
 242         System.out.println("Testing expression evaluation.");
 243 
 244         switch (s + s) {
 245         case "aa":
 246             errors = 0;
 247             break;
 248 
 249         case "aaaa":
 250             errors = 1;
 251             System.err.println("Suspected bad expression evaluation.");
 252             break;
 253 
 254         default:
 255              throw new RuntimeException("Should not reach here.");
 256         }
 257         
 258         return errors;
 259     }
 260 
 261     static final String FOO = "foo";
 262 
 263     static final String[] words = {"baz",
 264                                    "quux",
 265                                    "wombat",
 266                                    "\u0ccc\u0012"}; // hash collision with "foo"
 267 
 268     final static Set<String> emptyStringSet = Collections.emptySet();
 269 
 270     public static void main(String... args) {
 271         int failures = 0;
 272 
 273         failures += testNullBehavior();
 274         failures += testZeroCases();
 275         failures += testOneCaseNoDefault();
 276         failures += testBreakOnly();
 277         failures += testExpressionEval();
 278 
 279         if (failures > 0) {
 280             throw new RuntimeException();
 281         }
 282     }
 283 }