/* * Copyright (C) 2011 Red Hat, Inc. and/or its affiliates. * * 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 org.jboss.errai.codegen.test; import static org.jboss.errai.codegen.test.LoopBuilderTestResult.*; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.List; import java.util.Map; import javax.enterprise.util.TypeLiteral; import org.jboss.errai.codegen.AssignmentOperator; import org.jboss.errai.codegen.BooleanOperator; import org.jboss.errai.codegen.Context; import org.jboss.errai.codegen.Statement; import org.jboss.errai.codegen.Variable; import org.jboss.errai.codegen.builder.Builder; import org.jboss.errai.codegen.builder.impl.ContextBuilder; import org.jboss.errai.codegen.builder.impl.StatementBuilder; import org.jboss.errai.codegen.exception.InvalidExpressionException; import org.jboss.errai.codegen.exception.InvalidTypeException; import org.jboss.errai.codegen.exception.OutOfScopeException; import org.jboss.errai.codegen.exception.TypeNotIterableException; import org.jboss.errai.codegen.util.Bool; import org.jboss.errai.codegen.util.Stmt; import org.junit.Test; /** * Tests the generation of loops using the {@link StatementBuilder} API. * * @author Christian Sadilek <csadilek@redhat.com> */ @SuppressWarnings("serial") public class LoopBuilderTest extends AbstractCodegenTest { @Test public void testForeachLoopWithStringInParameterizedList() { String foreachWithListOfStrings = StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreach("element") .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a List<String>", FOREACH_STRING_IN_LIST, foreachWithListOfStrings); } @Test public void testForeachLoopWithStringInArray() { Statement createObject = StatementBuilder.create().newObject(String.class); String foreachWithStringArray = StatementBuilder.create(Context.create().addVariable("list", String[].class)) .loadVariable("list") .foreach("element") .append(createObject) .finish() .toJavaString(); assertEquals("Failed to generate foreach loop using a String[]", FOREACH_STRING_IN_ARRAY_ONE_STATEMENT, foreachWithStringArray); } @Test public void testForeachLoopWithStringInList() { Statement createObject = StatementBuilder.create().newObject(String.class); Statement createAnotherObject = StatementBuilder.create().newObject(Object.class); String foreachWithList = StatementBuilder.create() .declareVariable("list", List.class) .loadVariable("list") .foreach("element") .append(createObject) .append(createAnotherObject) .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a List<?>", FOREACH_OBJECT_IN_LIST_TWO_STATEMENTS, foreachWithList); } @Test public void testForeachLoopWithUndefinedCollection() { try { StatementBuilder.create() .loadVariable("list") .foreach("element", Integer.class) .finish().toJavaString(); fail("Expected OutOfScopeException"); } catch (OutOfScopeException e) { // expected } } @Test public void testForeachLoopWithProvidedLoopVarType() { Builder builder = StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreach("element", Object.class) .finish(); assertEquals("Failed to generate foreach loop with provided loop var type", FOREACH_OBJECT_IN_LIST, builder.toJavaString()); try { StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreach("element", Integer.class) .finish().toJavaString(); fail("Expected InvalidTypeException"); } catch (InvalidTypeException e) { // expected } } @Test public void testForeachLoopsNested() { Statement createObject = StatementBuilder.create().newObject(String.class); Builder outerLoop = StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreach("element") .append(StatementBuilder.create( ContextBuilder.create().addVariable(Variable.create("anotherList", new TypeLiteral<List<String>>() {})).getContext()) .loadVariable("anotherList") .foreach("anotherElement") .append(createObject) .finish() ).finish(); assertEquals("Failed to generate nested foreach loops", FOREACH_NESTED_STRING_IN_LIST, outerLoop.toJavaString()); } @Test public void testForeachLoopWithInvalidCollectionType() { try { StatementBuilder.create() .declareVariable("list", String.class) .loadVariable("list") .foreach("element") .finish().toJavaString(); fail("Expected TypeNotIterableException"); } catch (TypeNotIterableException e) { // expected } } @Test public void testForeachLoopWithInvoke() { Builder loop = StatementBuilder.create() .declareVariable("map", Map.class) .loadVariable("map") .invoke("keySet") .foreach("key") .append(Stmt.loadStatic(System.class, "out").invoke("println", Variable.get("key"))) .finish(); assertEquals("Failed to generate foreach loop using invoke()", FOREACH_KEYSET_LOOP, loop.toJavaString()); } @Test public void testForeachLoopWithLiterals() { String s = StatementBuilder.create() .loadLiteral(new String[] { "s1", "s2" }) .foreach("s") .append(StatementBuilder.create().loadVariable("s").invoke("getBytes")) .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a literal String array", FOREACH_LITERAL_STRING_ARRAY, s); } @Test public void testForeachLoopWithProvidedContext() { Context c = ContextBuilder.create().addVariable(Variable.create("s", String.class)).getContext(); String s = StatementBuilder.create(c) .loadLiteral(new String[] { "s1", "s2" }) .foreach("s") .append(StatementBuilder.create().loadVariable("s").invoke("getBytes")) .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a literal String array", FOREACH_LITERAL_STRING_ARRAY, s); } @Test public void testForeachLoopWithNullCheck() { String foreachWithListOfStrings = StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreachIfNotNull("element") .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a List<String> and null check", FOREACH_STRING_IN_LIST_NOT_NULL, foreachWithListOfStrings); } @Test public void testForeachLoopWithNullCheckAndProviderVarType() { String foreachWithListOfStrings = StatementBuilder.create() .declareVariable("list", new TypeLiteral<List<String>>() {}) .loadVariable("list") .foreachIfNotNull("element", Object.class) .finish().toJavaString(); assertEquals("Failed to generate foreach loop using a List<String> and null check", FOREACH_OBJECT_IN_LIST_NOT_NULL, foreachWithListOfStrings); } @Test public void testWhileLoopWithInvalidExpression() { try { StatementBuilder.create() .declareVariable("n", Integer.class) .loadVariable("n") .while_().finish().toJavaString(); fail("Expected InvalidTypeException"); } catch (InvalidTypeException e) { // expected } try { StatementBuilder.create() .declareVariable("str", String.class) .declareVariable("str2", String.class) .loadVariable("str") .while_(BooleanOperator.GreaterThan, Variable.get("str2")).finish() .toJavaString(); fail("Expected InvalidExpressionException"); } catch (InvalidExpressionException iee) { // expected assertTrue("Wrong exception thrown", iee.getMessage().contains(String.class.getName())); } } @Test public void testWhileLoopChainedWithEmptyExpressionWithoutBody() { String s = StatementBuilder.create() .declareVariable("b", Boolean.class) .loadVariable("b") .while_().finish().toJavaString(); assertEquals("Failed to generate empty while loop with chained lhs", WHILE_EMPTY, s); } @Test public void testWhileLoopChainedWithEmptyExpressionWithBody() { String s = StatementBuilder.create() .declareVariable("b", Boolean.class) .loadVariable("b") .while_() .append(StatementBuilder.create().loadVariable("b").assignValue(false)) .finish().toJavaString(); assertEquals("Failed to generate while loop with chained lhs and body", WHILE_WITH_BODY, s); } @Test public void testWhileLoopChainedWithNullCheck() { String s = StatementBuilder.create() .declareVariable("str", String.class) .loadVariable("str") .while_(BooleanOperator.NotEquals, null) .finish().toJavaString(); assertEquals("Failed to generate while loop with chained lhs, rhs (null check) and no body", WHILE_RHS_NULL_EMPTY, s); } @Test public void testWhileLoopChainedWithExpression() { String s = StatementBuilder.create() .declareVariable("str", String.class) .loadVariable("str") .invoke("length") .while_(BooleanOperator.GreaterThanOrEqual, 2) .finish().toJavaString(); assertEquals("Failed to generate while loop with chained lhs, rhs and no body", WHILE_RHS_EMPTY, s); } @Test public void testWhileLoopUnchainedWithExpression() { Context ctx = Context.create().addVariable("str", String.class); String s = StatementBuilder.create(ctx) .while_(Bool.expr(Stmt.loadVariable("str").invoke("length"), BooleanOperator.GreaterThanOrEqual, 2)) .finish().toJavaString(); assertEquals("Failed to generate while loop with rhs and no body", WHILE_RHS_EMPTY, s); } @Test public void testWhileLoopUnchainedWithNestedExpressions() { String s = StatementBuilder.create() .declareVariable("str", String.class) .while_(Bool.expr( Bool.expr(Variable.get("str"), BooleanOperator.NotEquals, null), BooleanOperator.And, Bool.expr(Stmt.loadVariable("str").invoke("length"), BooleanOperator.GreaterThan, 0))) .finish().toJavaString(); assertEquals("Failed to generate while loop with nested expressions and no body", WHILE_NESTED_EMPTY, s); } @Test public void testWhileLoopsNested() { Context c = Context.create().addVariable("str", String.class).addVariable("str2", String.class); String s = StatementBuilder.create(c) .loadVariable("str") .while_(BooleanOperator.NotEquals, null) .append( StatementBuilder.create(c) .while_(Bool.expr(Variable.get("str2"), BooleanOperator.NotEquals, null)) .finish()) .finish().toJavaString(); assertEquals("Failed to generate nested while loops", WHILE_NESTED_LOOPS, s); } @Test public void testForLoopUnchainedWithoutInitializerAndCountingExpression() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .for_(Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100)) .finish().toJavaString(); assertEquals("Failed to generate for loop without initializer", FOR_NO_INITIALIZER_NO_COUNTING_EXP_EMPTY, s); } @Test public void testForLoopChainedWithoutCountingExpression() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(BooleanOperator.LessThan, 100)) .finish().toJavaString(); assertEquals("Failed to generate for loop with initializer and chained lhs", FOR_CHAINED_INITIALIZER_NO_COUNTING_EXP_EMPTY, s); } @Test public void testForLoopUnchainedWithInitializer() { String s = StatementBuilder.create() .declareVariable("i", Integer.class) .for_(StatementBuilder.create().loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100)) .finish().toJavaString(); assertEquals("Failed to generate for loop with initializer", FOR_INITIALIZER_NO_COUNTING_EXP_EMPTY, s); } @Test public void testForLoopChainedWithCountingExpression() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(BooleanOperator.LessThan, 100), StatementBuilder.create().loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .finish().toJavaString(); assertEquals("Failed to generate for loop with initializer and counting expression and chained lhs", FOR_CHAINED_INITIALIZER_COUNTING_EXP_EMPTY, s); } @Test public void testForLoopUnchainedWithInitializerAndCountingExpression() { String s = StatementBuilder.create() .declareVariable("i", Integer.class) .for_(StatementBuilder.create().loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), StatementBuilder.create().loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .finish().toJavaString(); assertEquals("Failed to generate for loop with initializer and counting expression", FOR_INITIALIZER_COUNTING_EXP_EMPTY, s); } @Test public void testForLoopUnchainedWithDeclaringInitializerAndCountingExpression() { String s = StatementBuilder.create() .for_(Stmt.declareVariable(int.class).named("i").initializeWith(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), StatementBuilder.create().loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append(StatementBuilder.create().loadStatic(System.class, "out").invoke("println", Variable.get("i"))) .finish().toJavaString(); assertEquals("Failed to generate for loop with declaring initializer and counting expression", FOR_DECLARE_INITIALIZER_COUNTING_EXP, s); } @Test public void testDoWhileLoopUnchainedWithoutRhs() { String s = StatementBuilder.create() .declareVariable("b", Boolean.class) .do_() .append(StatementBuilder.create().loadVariable("b").assignValue(false)) .finish() .while_(Bool.expr(Variable.get("b"))) .toJavaString(); assertEquals("Failed to generate do while loop with simple expression (no operator and rhs)", DOWHILE_SIMPLE_EXPRESSION_NO_OP, s); } @Test public void testDoWhileLoopChainedWithoutRhs() { String s = StatementBuilder.create() .declareVariable("b", Boolean.class) .loadVariable("b") .do_() .append(StatementBuilder.create().loadVariable("b").assignValue(false)) .finish() .while_() .toJavaString(); assertEquals("Failed to generate for do while loop with simple expression (no operator and rhs) and chained lhs", DOWHILE_SIMPLE_EXPRESSION_NO_OP, s); } @Test public void testDoWhileLoopChainedWithRhs() { String s = StatementBuilder.create() .declareVariable("n", Integer.class) .loadVariable("n") .do_() .append(StatementBuilder.create().loadVariable("n").assignValue(1)) .finish() .while_(BooleanOperator.GreaterThanOrEqual, 1) .toJavaString(); assertEquals("Failed to generate for do while loop with simple expression (no operator and rhs) and chained lhs", DOWHILE_SIMPLE_EXPRESSION, s); } @Test public void testDoWhileLoopUnchainedWithNestedExpressions() { String s = StatementBuilder.create() .declareVariable("str", String.class) .do_() .append(StatementBuilder.create().loadStatic(System.class, "out").invoke("println", Variable.get("str"))) .finish() .while_(Bool.expr( Bool.expr(Variable.get("str"), BooleanOperator.NotEquals, null), BooleanOperator.And, Bool.expr(Stmt.loadVariable("str").invoke("length"), BooleanOperator.GreaterThan, 0))) .toJavaString(); assertEquals("Failed to generate do while loop with nested expression", DOWHILE_NESTED_EXPRESSION, s); } @Test public void testLoopWithContinue() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .if_(BooleanOperator.GreaterThan, 100) .append(Stmt .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), Stmt.loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append( Stmt.if_(Bool.expr(Variable.get("i"), BooleanOperator.Equals, 50)) .append(Stmt.continue_()) .finish()) .finish()) .finish() .toJavaString(); assertEquals("Failed to generate loop with continue", LOOP_WITH_CONTINUE, s); } @Test public void testLoopWithContinueAndLabel() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .if_(BooleanOperator.GreaterThan, 100) .append(Stmt.label("label")) .append(Stmt .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), Stmt.loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append(Stmt .if_(Bool.expr(Variable.get("i"), BooleanOperator.Equals, 50)) .append(Stmt.continue_("label")) .finish()) .finish()) .finish() .toJavaString(); assertEquals("Failed to generate loop with continue and label", LOOP_WITH_CONTINUE_AND_LABEL, s); } @Test public void testLoopWithBreak() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .if_(BooleanOperator.GreaterThan, 100) .append(Stmt .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), Stmt.loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append(Stmt .if_(Bool.expr(Variable.get("i"), BooleanOperator.Equals, 50)) .append(Stmt.break_()) .finish()) .finish()) .finish() .toJavaString(); assertEquals("Failed to generate loop with continue", LOOP_WITH_BREAK, s); } @Test public void testLoopWithBreakAndLabel() { String s = StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .if_(BooleanOperator.GreaterThan, 100) .append(Stmt.label("label")) .append(Stmt .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), Stmt.loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append(Stmt .if_(Bool.expr(Variable.get("i"), BooleanOperator.Equals, 50)) .append(Stmt.break_("label")) .finish()) .finish()) .finish() .toJavaString(); assertEquals("Failed to generate loop with continue and label", LOOP_WITH_BREAK_AND_LABEL, s); } @Test public void testLoopWithInvalidLabel() { try { StatementBuilder.create() .declareVariable("i", Integer.class, 0) .loadVariable("i") .if_(BooleanOperator.GreaterThan, 100) .append(Stmt.label("label")) .append(Stmt .for_(Stmt.loadVariable("i").assignValue(0), Bool.expr(Variable.get("i"), BooleanOperator.LessThan, 100), Stmt.loadVariable("i").assignValue(AssignmentOperator.PreIncrementAssign, 1)) .append(Stmt.continue_("undefinedlabel")) .finish()) .finish() .toJavaString(); fail("expected OutOfScopeException"); } catch (OutOfScopeException e) { // expected } } }