| /* | |
| * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * @test | |
| * @bug 6827009 7071246 | |
| * @summary Positive tests for strings in switch. | |
| * @author Joseph D. Darcy | |
| */ | |
| public class StringSwitches { | |
| public static void main(String... args) { | |
| int failures = 0; | |
| failures += testPileup(); | |
| failures += testSwitchingTwoWays(); | |
| failures += testNamedBreak(); | |
| failures += testExtraParens(); | |
| if (failures > 0) { | |
| throw new RuntimeException(); | |
| } | |
| } | |
| /* | |
| * A zero length string and all strings consisting only of the | |
| * zero character \u0000 have a hash code of zero. This method | |
| * maps such strings to the number of times \u0000 appears for 0 | |
| * through 6 occurrences. | |
| */ | |
| private static int zeroHashes(String s) { | |
| int result = Integer.MAX_VALUE; | |
| switch(s) { | |
| case "": | |
| return 0; | |
| case "\u0000": | |
| result = 1; break; | |
| case "\u0000\u0000": | |
| return 2; | |
| case "\u0000\u0000\u0000": | |
| result = 3; break; | |
| case "\u0000\u0000\u0000\u0000": | |
| return 4; | |
| case "\u0000\u0000\u0000\u0000\u0000": | |
| result = 5; break; | |
| case "\u0000\u0000\u0000\u0000\u0000\u0000": | |
| return 6; | |
| default: | |
| result = -1; | |
| } | |
| return result; | |
| } | |
| private static int testPileup() { | |
| int failures = 0; | |
| String zero = ""; | |
| for(int i = 0; i <= 6; i++, zero += "\u0000") { | |
| int result = zeroHashes(zero); | |
| if (result != i) { | |
| failures++; | |
| System.err.printf("For string \"%s\" unexpectedly got %d instead of %d%n.", | |
| zero, result, i); | |
| } | |
| } | |
| if (zeroHashes("foo") != -1) { | |
| failures++; | |
| System.err.println("Failed to get -1 for input string."); | |
| } | |
| return failures; | |
| } | |
| /** | |
| * Verify that a switch on an enum and a switch with the same | |
| * structure on the string name of an enum compute equivalent | |
| * values. | |
| */ | |
| private static int testSwitchingTwoWays() { | |
| int failures = 0; | |
| for(MetaSynVar msv : MetaSynVar.values()) { | |
| int enumResult = enumSwitch(msv); | |
| int stringResult = stringSwitch(msv.name()); | |
| if (enumResult != stringResult) { | |
| failures++; | |
| System.err.printf("One value %s, computed 0x%x with the enum switch " + | |
| "and 0x%x with the string one.%n", | |
| msv, enumResult, stringResult); | |
| } | |
| } | |
| return failures; | |
| } | |
| private static enum MetaSynVar { | |
| FOO, | |
| BAR, | |
| BAZ, | |
| QUX, | |
| QUUX, | |
| QUUUX, | |
| MUMBLE, | |
| FOOBAR; | |
| } | |
| private static int enumSwitch(MetaSynVar msv) { | |
| int result = 0; | |
| switch(msv) { | |
| case FOO: | |
| result |= (1<<0); | |
| // fallthrough: | |
| case BAR: | |
| case BAZ: | |
| result |= (1<<1); | |
| break; | |
| default: | |
| switch(msv) { | |
| case QUX: | |
| result |= (1<<2); | |
| break; | |
| case QUUX: | |
| result |= (1<<3); | |
| default: | |
| result |= (1<<4); | |
| } | |
| result |= (1<<5); | |
| break; | |
| case MUMBLE: | |
| result |= (1<<6); | |
| return result; | |
| case FOOBAR: | |
| result |= (1<<7); | |
| break; | |
| } | |
| result |= (1<<8); | |
| return result; | |
| } | |
| private static int stringSwitch(String msvName) { | |
| int result = 0; | |
| switch(msvName) { | |
| case "FOO": | |
| result |= (1<<0); | |
| // fallthrough: | |
| case "BAR": | |
| case "BAZ": | |
| result |= (1<<1); | |
| break; | |
| default: | |
| switch(msvName) { | |
| case "QUX": | |
| result |= (1<<2); | |
| break; | |
| case "QUUX": | |
| result |= (1<<3); | |
| default: | |
| result |= (1<<4); | |
| } | |
| result |= (1<<5); | |
| break; | |
| case "MUMBLE": | |
| result |= (1<<6); | |
| return result; | |
| case "FOOBAR": | |
| result |= (1<<7); | |
| break; | |
| } | |
| result |= (1<<8); | |
| return result; | |
| } | |
| private static int testNamedBreak() { | |
| int failures = 0; | |
| String[] testStrings = {"a", "b", "c", "d", "e"}; | |
| int[] testExpected = { 0b101011, 0b101, 0b100001, 0b101000, 0b10000}; | |
| for(int i = 0; i < testStrings.length; i++) { | |
| int expected = testExpected[i]; | |
| int result = namedBreak(testStrings[i]); | |
| if (result != expected) { | |
| failures++; | |
| System.err.printf("On input %s, got %d instead of %d.%n", | |
| testStrings[i], result, expected); | |
| } | |
| } | |
| return failures; | |
| } | |
| private static int namedBreak(String s) { | |
| int result = 0; | |
| outer: switch(s) { | |
| case "a": | |
| case "b": | |
| case "c": | |
| result |= (1<<0); | |
| inner: switch(s + s) { | |
| case "aa": | |
| result |= (1<<1); | |
| break inner; | |
| case "cc": | |
| break outer; | |
| default: | |
| result |= (1<<2); | |
| return result; | |
| } | |
| case "d": | |
| result |= (1<<3); | |
| break outer; | |
| default: | |
| return result |= (1<<4); | |
| } | |
| result |= (1<<5); | |
| return result; | |
| } | |
| private static int testExtraParens() { | |
| int failures = 1; | |
| String s = "first"; | |
| switch(s) { | |
| case (("first")): | |
| failures = 0; | |
| break; | |
| case ("second"): | |
| throw new RuntimeException("Should not be reached."); | |
| } | |
| return failures; | |
| } | |
| } |