darcy@430: /* katleman@1448: * Copyright (c) 2009, 2011, 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@1063: * @bug 6827009 7071246 darcy@430: * @summary Positive tests for strings in switch. darcy@430: * @author Joseph D. Darcy darcy@430: */ darcy@430: darcy@430: public class StringSwitches { darcy@430: darcy@430: public static void main(String... args) { darcy@430: int failures = 0; darcy@430: darcy@430: failures += testPileup(); darcy@430: failures += testSwitchingTwoWays(); darcy@430: failures += testNamedBreak(); darcy@1063: failures += testExtraParens(); darcy@430: darcy@430: if (failures > 0) { darcy@430: throw new RuntimeException(); darcy@430: } darcy@430: } darcy@430: darcy@430: /* darcy@430: * A zero length string and all strings consisting only of the darcy@430: * zero character \u0000 have a hash code of zero. This method darcy@430: * maps such strings to the number of times \u0000 appears for 0 darcy@430: * through 6 occurrences. darcy@430: */ darcy@430: private static int zeroHashes(String s) { darcy@430: int result = Integer.MAX_VALUE; darcy@430: switch(s) { darcy@430: case "": darcy@430: return 0; darcy@430: darcy@430: case "\u0000": darcy@430: result = 1; break; darcy@430: darcy@430: case "\u0000\u0000": darcy@430: return 2; darcy@430: darcy@430: case "\u0000\u0000\u0000": darcy@430: result = 3; break; darcy@430: darcy@430: case "\u0000\u0000\u0000\u0000": darcy@430: return 4; darcy@430: darcy@430: case "\u0000\u0000\u0000\u0000\u0000": darcy@430: result = 5; break; darcy@430: darcy@430: case "\u0000\u0000\u0000\u0000\u0000\u0000": darcy@430: return 6; darcy@430: darcy@430: default: darcy@430: result = -1; darcy@430: } darcy@430: return result; darcy@430: } darcy@430: darcy@430: private static int testPileup() { darcy@430: int failures = 0; darcy@430: String zero = ""; darcy@430: for(int i = 0; i <= 6; i++, zero += "\u0000") { darcy@430: int result = zeroHashes(zero); darcy@430: if (result != i) { darcy@430: failures++; darcy@430: System.err.printf("For string \"%s\" unexpectedly got %d instead of %d%n.", darcy@430: zero, result, i); darcy@430: } darcy@430: } darcy@430: darcy@430: if (zeroHashes("foo") != -1) { darcy@430: failures++; darcy@430: System.err.println("Failed to get -1 for input string."); darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: /** darcy@430: * Verify that a switch on an enum and a switch with the same darcy@430: * structure on the string name of an enum compute equivalent darcy@430: * values. darcy@430: */ darcy@430: private static int testSwitchingTwoWays() { darcy@430: int failures = 0; darcy@430: darcy@430: for(MetaSynVar msv : MetaSynVar.values()) { darcy@430: int enumResult = enumSwitch(msv); darcy@430: int stringResult = stringSwitch(msv.name()); darcy@430: darcy@430: if (enumResult != stringResult) { darcy@430: failures++; darcy@430: System.err.printf("One value %s, computed 0x%x with the enum switch " + darcy@430: "and 0x%x with the string one.%n", darcy@430: msv, enumResult, stringResult); darcy@430: } darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: private static enum MetaSynVar { darcy@430: FOO, darcy@430: BAR, darcy@430: BAZ, darcy@430: QUX, darcy@430: QUUX, darcy@430: QUUUX, darcy@430: MUMBLE, darcy@430: FOOBAR; darcy@430: } darcy@430: darcy@430: private static int enumSwitch(MetaSynVar msv) { darcy@430: int result = 0; darcy@430: switch(msv) { darcy@430: case FOO: darcy@430: result |= (1<<0); darcy@430: // fallthrough: darcy@430: darcy@430: case BAR: darcy@430: case BAZ: darcy@430: result |= (1<<1); darcy@430: break; darcy@430: darcy@430: default: darcy@430: switch(msv) { darcy@430: case QUX: darcy@430: result |= (1<<2); darcy@430: break; darcy@430: darcy@430: case QUUX: darcy@430: result |= (1<<3); darcy@430: darcy@430: default: darcy@430: result |= (1<<4); darcy@430: } darcy@430: result |= (1<<5); darcy@430: break; darcy@430: darcy@430: case MUMBLE: darcy@430: result |= (1<<6); darcy@430: return result; darcy@430: darcy@430: case FOOBAR: darcy@430: result |= (1<<7); darcy@430: break; darcy@430: } darcy@430: result |= (1<<8); darcy@430: return result; darcy@430: } darcy@430: darcy@430: private static int stringSwitch(String msvName) { darcy@430: int result = 0; darcy@430: switch(msvName) { darcy@430: case "FOO": darcy@430: result |= (1<<0); darcy@430: // fallthrough: darcy@430: darcy@430: case "BAR": darcy@430: case "BAZ": darcy@430: result |= (1<<1); darcy@430: break; darcy@430: darcy@430: default: darcy@430: switch(msvName) { darcy@430: case "QUX": darcy@430: result |= (1<<2); darcy@430: break; darcy@430: darcy@430: case "QUUX": darcy@430: result |= (1<<3); darcy@430: darcy@430: default: darcy@430: result |= (1<<4); darcy@430: } darcy@430: result |= (1<<5); darcy@430: break; darcy@430: darcy@430: case "MUMBLE": darcy@430: result |= (1<<6); darcy@430: return result; darcy@430: darcy@430: case "FOOBAR": darcy@430: result |= (1<<7); darcy@430: break; darcy@430: } darcy@430: result |= (1<<8); darcy@430: return result; darcy@430: } darcy@430: darcy@430: private static int testNamedBreak() { darcy@430: int failures = 0; darcy@430: String[] testStrings = {"a", "b", "c", "d", "e"}; darcy@430: int[] testExpected = { 0b101011, 0b101, 0b100001, 0b101000, 0b10000}; darcy@430: darcy@430: for(int i = 0; i < testStrings.length; i++) { darcy@430: int expected = testExpected[i]; darcy@430: int result = namedBreak(testStrings[i]); darcy@430: darcy@430: if (result != expected) { darcy@430: failures++; darcy@430: darcy@430: System.err.printf("On input %s, got %d instead of %d.%n", darcy@430: testStrings[i], result, expected); darcy@430: } darcy@430: } darcy@430: darcy@430: return failures; darcy@430: } darcy@430: darcy@430: private static int namedBreak(String s) { darcy@430: int result = 0; darcy@430: outer: switch(s) { darcy@430: case "a": darcy@430: case "b": darcy@430: case "c": darcy@430: result |= (1<<0); darcy@430: inner: switch(s + s) { darcy@430: case "aa": darcy@430: result |= (1<<1); darcy@430: break inner; darcy@430: darcy@430: case "cc": darcy@430: break outer; darcy@430: darcy@430: default: darcy@430: result |= (1<<2); darcy@430: return result; darcy@430: } darcy@430: darcy@430: case "d": darcy@430: result |= (1<<3); darcy@430: break outer; darcy@430: darcy@430: default: darcy@430: return result |= (1<<4); darcy@430: } darcy@430: result |= (1<<5); darcy@430: return result; darcy@430: } darcy@1063: darcy@1063: private static int testExtraParens() { darcy@1063: int failures = 1; darcy@1063: String s = "first"; darcy@1063: darcy@1063: switch(s) { darcy@1063: case (("first")): darcy@1063: failures = 0; darcy@1063: break; darcy@1063: case ("second"): darcy@1063: throw new RuntimeException("Should not be reached."); darcy@1063: } darcy@1063: darcy@1063: return failures; darcy@1063: } darcy@430: }