/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.devtools.j2objc.translate; import com.google.devtools.j2objc.GenerationTest; import com.google.devtools.j2objc.ast.Block; import com.google.devtools.j2objc.ast.CompilationUnit; import com.google.devtools.j2objc.ast.MethodDeclaration; import com.google.devtools.j2objc.ast.Statement; import com.google.devtools.j2objc.ast.SwitchStatement; import com.google.devtools.j2objc.ast.TreeUtil; import com.google.devtools.j2objc.ast.TypeDeclaration; import com.google.devtools.j2objc.ast.VariableDeclarationStatement; import java.io.IOException; import java.util.List; /** * Unit tests for {@link SwitchRewriter}. * * @author Tom Ball, Keith Stanger */ public class SwitchRewriterTest extends GenerationTest { public void testVariableDeclarationsInSwitchStatement() throws IOException { String translation = translateSourceFile( "public class A { public void doSomething(int i) { switch (i) { " + "case 1: int j = i * 2; log(j); break; " + "case 2: log(i); break; " + "case 3: log(i); int k = i, l = 42; break; }}" + "private void log(int i) {}}", "A", "A.m"); assertTranslation(translation, "jint j;"); if (options.isJDT()) { assertTranslation(translation, "jint k, l;"); } else { assertTranslation(translation, "jint k;"); assertTranslation(translation, "jint l;"); } assertTranslation(translation, "case 1:"); assertTrue(translation.indexOf("jint j;") < translation.indexOf("case 1:")); if (options.isJDT()) { assertTrue(translation.indexOf("jint k, l;") < translation.indexOf("case 1:")); assertTrue(translation.indexOf("jint j;") < translation.indexOf("jint k, l;")); } else { assertTrue(translation.indexOf("jint k;") < translation.indexOf("case 1:")); assertTrue(translation.indexOf("jint l;") < translation.indexOf("case 1:")); assertTrue(translation.indexOf("jint j;") < translation.indexOf("jint k;")); assertTrue(translation.indexOf("jint k;") < translation.indexOf("jint l;")); } assertTranslation(translation, "j = i * 2;"); assertTranslation(translation, "k = i;"); assertTranslation(translation, "l = 42;"); assertTrue(translation.indexOf("k = i") < translation.indexOf("l = 42")); } public void testVariableDeclarationsInSwitchStatement2() throws IOException { CompilationUnit unit = translateType("A", "public class A { public void doSomething(int i) { switch (i) { " + "case 1: int j = i * 2; log(j); break; " + "case 2: log(i); break; " + "case 3: log(i); int k = i, l = 42; break; }}" + "private void log(int i) {}}"); TypeDeclaration testType = (TypeDeclaration) unit.getTypes().get(0); // First MethodDeclaration is the implicit default constructor. MethodDeclaration method = TreeUtil.getMethodDeclarationsList(testType).get(1); List<Statement> stmts = method.getBody().getStatements(); assertEquals(1, stmts.size()); Block block = (Block) stmts.get(0); stmts = block.getStatements(); if (options.isJDT()) { assertEquals(3, stmts.size()); assertTrue(stmts.get(0) instanceof VariableDeclarationStatement); assertTrue(stmts.get(1) instanceof VariableDeclarationStatement); assertTrue(stmts.get(2) instanceof SwitchStatement); } else { assertEquals(4, stmts.size()); assertTrue(stmts.get(0) instanceof VariableDeclarationStatement); assertTrue(stmts.get(1) instanceof VariableDeclarationStatement); assertTrue(stmts.get(2) instanceof VariableDeclarationStatement); assertTrue(stmts.get(3) instanceof SwitchStatement); } } public void testMultipleSwitchVariables() throws IOException { String translation = translateSourceFile( "public class A { public void doSomething(int n) { switch (n) { " + "case 1: int i; int j = 2; }}" + "private void log(int i) {}}", "A", "A.m"); int index = translation.indexOf("jint i;"); assertTrue(index >= 0 && index < translation.indexOf("switch")); index = translation.indexOf("jint j;"); assertTrue(index >= 0 && index < translation.indexOf("switch")); assertOccurrences(translation, "jint i;", 1); assertFalse(translation.contains("jint j = 2;")); } public void testEnumConstantsInSwitchStatement() throws IOException { String translation = translateSourceFile( "public class A { static enum EnumType { ONE, TWO }" + "public static void doSomething(EnumType e) {" + " switch (e) { case ONE: break; case TWO: break; }}}", "A", "A.m"); assertTranslation(translation, "switch ([e ordinal]) {"); assertTranslation(translation, "case A_EnumType_Enum_ONE:"); } public void testPrimitiveConstantInSwitchCase() throws IOException { String translation = translateSourceFile( "public class A { public static final char PREFIX = 'p';" + "public boolean doSomething(char c) { switch (c) { " + "case PREFIX: return true; " + "default: return false; }}}", "A", "A.h"); assertTranslation(translation, "#define A_PREFIX 'p'"); translation = getTranslatedFile("A.m"); assertTranslation(translation, "case A_PREFIX:"); } // Verify Java 7's switch statements with strings. public void testStringSwitchStatement() throws IOException { addSourceFile("class Foo { static final String TEST = \"test1\"; }", "Foo.java"); addSourceFile("interface Bar { String TEST = \"test2\"; }", "Bar.java"); addSourcesToSourcepaths(); String translation = translateSourceFile( "public class Test { " + "static final String constant = \"mumble\";" + "int test(String s) { " + " switch(s) {" + " case \"foo\": return 42;" + " case \"bar\": return 666;" + " case constant: return -1;" + " case Foo.TEST: return -2;" + " case Bar.TEST: return -3;" + " default: return -1;" + " }}}", "Test", "Test.m"); assertTranslatedLines(translation, "switch (JreIndexOfStr(s, (id[]){ @\"foo\", " + "@\"bar\", Test_constant, Foo_TEST, Bar_TEST }, 5)) {", " case 0:", " return 42;", " case 1:", " return 666;", " case 2:", " return -1;", " case 3:", " return -2;", " case 4:", " return -3;", " default:", " return -1;", "}"); } /** * Verify that when a the last switch case is empty (no statement), * an empty statement is added. Java doesn't require an empty statement * here, while C does. */ public void testEmptyLastCaseStatement() throws IOException { String translation = translateSourceFile( "public class A {" + " int test(int i) { " + " switch (i) { case 1: return 1; case 2: return 2; default: } return i; }}", "A", "A.m"); assertTranslatedLines(translation, "default:", ";", "}"); } public void testLocalFinalPrimitiveCaseValue() throws IOException { String translation = translateSourceFile( "public class Test { char test(int i) { final int ONE = 1, TWO = 2; " + "switch (i) { case ONE: return 'a'; case TWO: return 'b'; default: return 'z'; } } }", "Test", "Test.m"); assertTranslatedLines(translation, "switch (i) {", " case 1:", " return 'a';", " case 2:", " return 'b';", " default:", " return 'z';", "}"); } }