/*
* 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;
}
}