/*
* 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.exprtree;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Equivalence.Wrapper;
import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.exprparse.ExpressionParser;
import com.google.template.soy.exprparse.SoyParsingContext;
import com.google.template.soy.exprtree.ExprNode.ParentExprNode;
import com.google.template.soy.exprtree.OperatorNodes.PlusOpNode;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link ExprEquivalence}. */
@RunWith(JUnit4.class)
public final class ExprEquivalenceTest {
@Test
public void testReflexive() {
assertReflexive("1");
assertReflexive("'a'");
assertReflexive("$map['a']");
assertReflexive("$list[1][2]");
}
@Test
public void testSubExpressions() {
PlusOpNode node = (PlusOpNode) parse("$foo.a.b + $foo.a.b");
assertEquivalent(node.getChild(0), node.getChild(1));
assertNotEquivalent(node, node.getChild(0));
assertNotEquivalent(node, node.getChild(1));
}
private void assertReflexive(String expr) {
// We parse twice so we don't get trivial == equality
assertEquivalent(parse(expr), parse(expr));
}
private static ExprNode parse(String input) {
return new ExpressionParser(input, SourceLocation.UNKNOWN, SoyParsingContext.exploding())
.parseExpression();
}
private void assertEquivalent(ExprNode left, ExprNode right) {
Wrapper<ExprNode> wrappedLeft = ExprEquivalence.get().wrap(left);
Wrapper<ExprNode> wrappedRight = ExprEquivalence.get().wrap(right);
assertThat(wrappedLeft).isEqualTo(wrappedRight);
// Test symmetry
assertThat(wrappedRight).isEqualTo(wrappedLeft);
assertThat(wrappedLeft.hashCode()).isEqualTo(wrappedRight.hashCode());
// If two expressions are equal, then all subexpressions must also be equal
if (left instanceof ParentExprNode) {
List<ExprNode> leftChildren = ((ParentExprNode) left).getChildren();
List<ExprNode> rightChildren = ((ParentExprNode) right).getChildren();
for (int i = 0; i < leftChildren.size(); i++) {
assertEquivalent(leftChildren.get(i), rightChildren.get(i));
}
}
}
private static void assertNotEquivalent(ExprNode left, ExprNode right) {
// test symmetry
assertThat(ExprEquivalence.get().wrap(left)).isNotEqualTo(ExprEquivalence.get().wrap(right));
assertThat(ExprEquivalence.get().wrap(right)).isNotEqualTo(ExprEquivalence.get().wrap(left));
}
}