darcy@430: /* ohair@554: * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. darcy@430: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. darcy@430: * darcy@430: * This code is free software; you can redistribute it and/or modify it darcy@430: * under the terms of the GNU General Public License version 2 only, as darcy@430: * published by the Free Software Foundation. darcy@430: * darcy@430: * This code is distributed in the hope that it will be useful, but WITHOUT darcy@430: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or darcy@430: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License darcy@430: * version 2 for more details (a copy is included in the LICENSE file that darcy@430: * accompanied this code). darcy@430: * darcy@430: * You should have received a copy of the GNU General Public License version darcy@430: * 2 along with this work; if not, write to the Free Software Foundation, darcy@430: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. darcy@430: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. darcy@430: */ darcy@430: darcy@430: /* darcy@430: * @test darcy@430: * @bug 6827009 darcy@430: * @summary Positive tests for strings in switch with few alternatives. darcy@430: * @compile/fail -source 6 OneCaseSwitches.java darcy@430: * @compile OneCaseSwitches.java darcy@430: * @run main OneCaseSwitches darcy@430: * @author Joseph D. Darcy darcy@430: */ darcy@430: darcy@430: import java.lang.reflect.*; darcy@430: import java.lang.annotation.*; darcy@430: import java.util.*; darcy@430: import static java.lang.annotation.RetentionPolicy.*; darcy@430: darcy@430: public class OneCaseSwitches { darcy@430: @Retention(RUNTIME) darcy@430: @interface TestMeForNull {} darcy@430: darcy@430: @TestMeForNull darcy@430: public static int zeroCasesNoDefault(String s, Set stringSet, boolean expected) { darcy@430: int failures = 0; darcy@430: switch(s) { darcy@430: } darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int zeroCasesWithDefault(String s, Set stringSet, boolean expected) { darcy@430: int failures = 2; darcy@430: boolean addResult; darcy@430: darcy@430: switch(s) { darcy@430: default: darcy@430: failures = 0; darcy@430: addResult = stringSet.add(s); darcy@430: if (addResult != expected) { darcy@430: failures++; darcy@430: System.err.println("zeroCaseWithDefault: Expectedly got add result of " + addResult + darcy@430: " on string " + s); darcy@430: } darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int zeroCasesWithDefaultBreak(String s, Set stringSet, boolean expected) { darcy@430: int failures = 2; darcy@430: boolean addResult; darcy@430: darcy@430: switch(s) { darcy@430: default: darcy@430: failures = zeroCasesWithDefault(s, stringSet, expected); darcy@430: break; darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int oneCaseNoDefault(String s, Set stringSet, boolean expected) { darcy@430: int failures = 2; darcy@430: boolean addResult; darcy@430: darcy@430: switch(s) { darcy@430: case "foo": darcy@430: failures = 0; darcy@430: addResult = stringSet.add(s); darcy@430: if (addResult != expected) { darcy@430: failures++; darcy@430: System.err.println("oneCaseNoDefault: Unexpectedly got add result of " + addResult + darcy@430: " on string " + s); darcy@430: } darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int oneCaseNoDefaultBreak(String s, Set stringSet, boolean expected) { darcy@430: int failures = 2; darcy@430: boolean addResult; darcy@430: darcy@430: switch(s) { darcy@430: case "foo": darcy@430: failures = oneCaseNoDefaultBreak(s, stringSet, expected); darcy@430: break; darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int oneCaseWithDefault(String s, Set stringSet, boolean expected) { darcy@430: int failures = 2; darcy@430: boolean addResult;; darcy@430: darcy@430: switch(s) { darcy@430: case "foo": darcy@430: failures = 0; darcy@430: addResult = stringSet.add(s); darcy@430: if (addResult != expected) { darcy@430: failures++; darcy@430: System.err.println("oneCaseNoDefault: Expectedly got add result of " + addResult + darcy@430: " on string " + s); darcy@430: } darcy@430: break; darcy@430: default: darcy@430: break; darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int oneCaseBreakOnly(String s, Set stringSet, boolean expected) { darcy@430: int failures = 1; darcy@430: switch(s) { darcy@430: case "foo": darcy@430: break; darcy@430: } darcy@430: failures = 0; darcy@430: return failures; darcy@430: } darcy@430: darcy@430: @TestMeForNull darcy@430: public static int oneCaseDefaultBreakOnly(String s, Set stringSet, boolean expected) { darcy@430: int failures = 1; darcy@430: switch(s) { darcy@430: default: darcy@430: break; darcy@430: } darcy@430: failures = 0; darcy@430: return failures; darcy@430: } darcy@430: darcy@430: darcy@430: static int testNullBehavior() { darcy@430: int failures = 0; darcy@430: int count = 0; darcy@430: darcy@430: Method[] methods = OneCaseSwitches.class.getDeclaredMethods(); darcy@430: darcy@430: try { darcy@430: for(Method method : methods) { darcy@430: count++; darcy@430: try { darcy@430: if (method.isAnnotationPresent(TestMeForNull.class)) { darcy@430: System.out.println("Testing method " + method); darcy@430: method.invoke(null, (String)null, emptyStringSet, false); darcy@430: failures++; darcy@430: System.err.println("Didn't get NPE as expected from " + method); darcy@430: } darcy@430: } catch (InvocationTargetException ite) { // Expected darcy@430: Throwable targetException = ite.getTargetException(); darcy@430: if (! (targetException instanceof NullPointerException)) { darcy@430: failures++; // Wrong exception thrown darcy@430: System.err.println("Didn't get expected target exception NPE, got " + darcy@430: ite.getClass().getName()); darcy@430: } darcy@430: } darcy@430: } darcy@430: } catch (Exception e) { darcy@430: throw new RuntimeException(e); darcy@430: } darcy@430: darcy@430: if (count == 0) { darcy@430: failures++; darcy@430: System.err.println("Did not find any annotated methods."); darcy@430: } darcy@430: return failures; darcy@430: } darcy@430: darcy@430: static int testZeroCases() { darcy@430: int failures = 0; darcy@430: Set noDefaultSet = new HashSet(); darcy@430: Set defaultSet = new HashSet(); darcy@430: darcy@430: zeroCasesNoDefault(FOO, noDefaultSet, false); darcy@430: for(String word : words) { darcy@430: zeroCasesNoDefault(word, noDefaultSet, false); darcy@430: } darcy@430: darcy@430: if (!noDefaultSet.isEmpty()) { darcy@430: failures++; darcy@430: System.err.println("Non-empty set after zeroCasesNoDefault"); darcy@430: } darcy@430: darcy@430: for(String word : words) { darcy@430: zeroCasesWithDefault(word, defaultSet, true); darcy@430: } darcy@430: if (defaultSet.size() != words.length) { darcy@430: failures++; darcy@430: System.err.println("Missing strings after zeroCasesWithDefault"); darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: static int testOneCaseNoDefault() { darcy@430: int failures = 0; darcy@430: Set s = new HashSet(); darcy@430: s.add("foo"); darcy@430: Set fooSet = Collections.unmodifiableSet(s); darcy@430: Set testSet = new HashSet(); darcy@430: darcy@430: oneCaseNoDefault(FOO, testSet, true); darcy@430: if (!testSet.equals(fooSet)) { darcy@430: failures++; darcy@430: System.err.println("Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}"); darcy@430: } darcy@430: darcy@430: for(String word : words) { darcy@430: oneCaseNoDefault(word, testSet, false); darcy@430: } darcy@430: if (!testSet.equals(fooSet)) { darcy@430: failures++; darcy@430: System.err.println("Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}"); darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: static int testBreakOnly() { darcy@430: int failures = 0; darcy@430: darcy@430: for(String word : words) { darcy@430: failures += oneCaseBreakOnly(word, emptyStringSet, true); darcy@430: failures += oneCaseDefaultBreakOnly(word, emptyStringSet, true); darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: static int testExpressionEval() { darcy@430: String s = "a"; darcy@430: int errors = 2; darcy@430: darcy@430: System.out.println("Testing expression evaluation."); darcy@430: darcy@430: switch (s + s) { darcy@430: case "aa": darcy@430: errors = 0; darcy@430: break; darcy@430: darcy@430: case "aaaa": darcy@430: errors = 1; darcy@430: System.err.println("Suspected bad expression evaluation."); darcy@430: break; darcy@430: darcy@430: default: darcy@430: throw new RuntimeException("Should not reach here."); darcy@430: } darcy@430: return errors; darcy@430: } darcy@430: darcy@430: static final String FOO = "foo"; darcy@430: darcy@430: static final String[] words = {"baz", darcy@430: "quux", darcy@430: "wombat", darcy@430: "\u0ccc\u0012"}; // hash collision with "foo" darcy@430: darcy@430: final static Set emptyStringSet = Collections.emptySet(); darcy@430: darcy@430: public static void main(String... args) { darcy@430: int failures = 0; darcy@430: darcy@430: failures += testNullBehavior(); darcy@430: failures += testZeroCases(); darcy@430: failures += testOneCaseNoDefault(); darcy@430: failures += testBreakOnly(); darcy@430: failures += testExpressionEval(); darcy@430: darcy@430: if (failures > 0) { darcy@430: throw new RuntimeException(); darcy@430: } darcy@430: } darcy@430: }