com.google.template.soy.jbcsrc.BytecodeUtilsTest.java Source code

Java tutorial

Introduction

Here is the source code for com.google.template.soy.jbcsrc.BytecodeUtilsTest.java

Source

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