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