Java tutorial
/* * Copyright 2015 Google Inc. * * 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.template.soy.jbcsrc; import static com.google.template.soy.jbcsrc.BytecodeUtils.compare; import static com.google.template.soy.jbcsrc.BytecodeUtils.constant; import static com.google.template.soy.jbcsrc.BytecodeUtils.logicalAnd; import static com.google.template.soy.jbcsrc.BytecodeUtils.logicalNot; import static com.google.template.soy.jbcsrc.BytecodeUtils.logicalOr; import static com.google.template.soy.jbcsrc.ExpressionTester.assertThatExpression; import com.google.common.collect.ImmutableList; import junit.framework.TestCase; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.util.List; /** * Tests for {@link BytecodeUtils} */ public class BytecodeUtilsTest extends TestCase { public void testConstantExpressions() { // there are special cases for variously sized integers, test them all. assertThatExpression(constant(0)).evaluatesTo(0); assertThatExpression(constant(1)).evaluatesTo(1); assertThatExpression(constant(0L)).evaluatesTo(0L); assertThatExpression(constant(1L)).evaluatesTo(1L); assertThatExpression(constant(0.0)).evaluatesTo(0.0); assertThatExpression(constant(1.0)).evaluatesTo(1.0); assertThatExpression(constant(127)).evaluatesTo(127); assertThatExpression(constant(255)).evaluatesTo(255); assertThatExpression(constant(Integer.MAX_VALUE)).evaluatesTo(Integer.MAX_VALUE); assertThatExpression(constant(Integer.MIN_VALUE)).evaluatesTo(Integer.MIN_VALUE); assertThatExpression(constant(Long.MAX_VALUE)).evaluatesTo(Long.MAX_VALUE); assertThatExpression(constant(Long.MIN_VALUE)).evaluatesTo(Long.MIN_VALUE); assertThatExpression(constant('\n')).evaluatesTo('\n'); assertThatExpression(constant("hello world")).evaluatesTo("hello world"); } public void testLogicalNot() { assertThatExpression(logicalNot(constant(false))).evaluatesTo(true); assertThatExpression(logicalNot(constant(true))).evaluatesTo(false); } public void testCompareLongs() { Expression one = constant(1L); Expression two = constant(2L); assertThatExpression(compare(Opcodes.IFNE, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFLT, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFLE, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFGT, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGE, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFEQ, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLE, two, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFGE, two, two)).evaluatesTo(true); } public void testCompareDoubles() { Expression one = constant(1D); Expression two = constant(2D); Expression nan = constant(Double.NaN); assertThatExpression(compare(Opcodes.IFNE, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFLT, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFLE, one, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFGT, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGE, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFEQ, one, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLE, two, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFGE, two, two)).evaluatesTo(true); // There are special cases for NaN that we need to test, basically every expression involving // NaN should evaluate to false with the exception of NaN != * which always == true assertThatExpression(compare(Opcodes.IFNE, nan, two)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFNE, two, nan)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFNE, nan, nan)).evaluatesTo(true); assertThatExpression(compare(Opcodes.IFEQ, nan, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFEQ, two, nan)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFEQ, nan, nan)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLE, nan, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLE, two, nan)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLT, nan, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFLT, two, nan)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGE, nan, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGE, two, nan)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGT, nan, two)).evaluatesTo(false); assertThatExpression(compare(Opcodes.IFGT, two, nan)).evaluatesTo(false); } public void testShortCircuitingLogicalOperators_basic() { assertThatExpression(logicalOr(constant(false))).evaluatesTo(false); assertThatExpression(logicalOr(constant(true))).evaluatesTo(true); assertThatExpression(logicalAnd(constant(false))).evaluatesTo(false); assertThatExpression(logicalAnd(constant(true))).evaluatesTo(true); assertThatExpression(logicalOr(constant(false), constant(false))).evaluatesTo(false); assertThatExpression(logicalOr(constant(false), constant(true))).evaluatesTo(true); assertThatExpression(logicalOr(constant(true), constant(false))).evaluatesTo(true); assertThatExpression(logicalOr(constant(true), constant(true))).evaluatesTo(true); assertThatExpression(logicalAnd(constant(false), constant(false))).evaluatesTo(false); assertThatExpression(logicalAnd(constant(false), constant(true))).evaluatesTo(false); assertThatExpression(logicalAnd(constant(true), constant(false))).evaluatesTo(false); assertThatExpression(logicalAnd(constant(true), constant(true))).evaluatesTo(true); } public void testShortCircuitingLogicalOperators_compatibleWithJavaOperators() { ImmutableList<Boolean> bools = ImmutableList.of(true, false); for (boolean a : bools) { for (boolean b : bools) { for (boolean c : bools) { for (boolean d : bools) { List<Expression> exprs = ImmutableList.of(constant(a), constant(b), constant(c), constant(d)); assertThatExpression(logicalOr(exprs)).evaluatesTo(a || b || c || d); assertThatExpression(logicalAnd(exprs)).evaluatesTo(a && b && c && d); } } } } } // Use an expression that only ever throws for branches that are supposed to be skipped. public void testShortCircuitingLogicalOperators_shortCircuits() { assertThatExpression(throwingBoolExpression()).throwsException(IllegalStateException.class); assertThatExpression(logicalOr(ImmutableList.of(constant(true), throwingBoolExpression()))) .evaluatesTo(true); assertThatExpression(logicalAnd(ImmutableList.of(constant(false), throwingBoolExpression()))) .evaluatesTo(false); } private static Expression throwingBoolExpression() { return new Expression(Type.BOOLEAN_TYPE) { @Override void doGen(CodeBuilder adapter) { adapter.throwException(Type.getType(IllegalStateException.class), "shouldn't have called me"); } }; } }