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