/*
* 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.pysrc.internal;
import static com.google.template.soy.pysrc.internal.SoyExprForPySubject.assertThatSoyExpr;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.template.soy.exprtree.Operator;
import com.google.template.soy.pysrc.restricted.PyExpr;
import com.google.template.soy.pysrc.restricted.PyListExpr;
import com.google.template.soy.pysrc.restricted.PyStringExpr;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for TranslateToPyExprVisitor.
*
*/
@RunWith(JUnit4.class)
public class TranslateToPyExprVisitorTest {
@Test
public void testNullLiteral() {
assertThatSoyExpr("null").translatesTo("None", Integer.MAX_VALUE);
}
@Test
public void testBooleanLiteral() {
assertThatSoyExpr("true").translatesTo("True", Integer.MAX_VALUE);
assertThatSoyExpr("false").translatesTo("False", Integer.MAX_VALUE);
}
@Test
public void testStringLiteral() {
assertThatSoyExpr("'waldo'")
.translatesTo(new PyExpr("'waldo'", Integer.MAX_VALUE), PyStringExpr.class);
}
@Test
public void testListLiteral() {
assertThatSoyExpr("[]").translatesTo(new PyExpr("[]", Integer.MAX_VALUE), PyListExpr.class);
assertThatSoyExpr("['blah', 123, $foo]")
.translatesTo(
new PyExpr("['blah', 123, data.get('foo')]", Integer.MAX_VALUE), PyListExpr.class);
}
@Test
public void testMapLiteral() {
// Unquoted keys.
assertThatSoyExpr("[:]").translatesTo("collections.OrderedDict([])", Integer.MAX_VALUE);
assertThatSoyExpr("['aaa': 123, 'bbb': 'blah']")
.translatesTo(
"collections.OrderedDict([('aaa', 123), ('bbb', 'blah')])", Integer.MAX_VALUE);
assertThatSoyExpr("['aaa': $foo, 'bbb': 'blah']")
.translatesTo(
"collections.OrderedDict([('aaa', data.get('foo')), ('bbb', 'blah')])",
Integer.MAX_VALUE);
// Non-string keys are allowed in Python.
assertThatSoyExpr("[1: 'blah', 0: 123]")
.translatesTo("collections.OrderedDict([(1, 'blah'), (0, 123)])", Integer.MAX_VALUE);
}
@Test
public void testMapLiteral_quotedKeysIfJS() {
// quoteKeysIfJs should change nothing in Python.
assertThatSoyExpr("quoteKeysIfJs([:])")
.translatesTo("collections.OrderedDict([])", Integer.MAX_VALUE);
assertThatSoyExpr("quoteKeysIfJs( ['aaa': $foo, 'bbb': 'blah'] )")
.translatesTo(
"collections.OrderedDict([('aaa', data.get('foo')), ('bbb', 'blah')])",
Integer.MAX_VALUE);
}
@Test
public void testGlobals() {
ImmutableMap<String, Object> globals =
ImmutableMap.<String, Object>builder()
.put("STR", "Hello World")
.put("NUM", 55)
.put("BOOL", true)
.build();
assertThatSoyExpr("STR").withGlobals(globals).translatesTo("'Hello World'", Integer.MAX_VALUE);
assertThatSoyExpr("NUM").withGlobals(globals).translatesTo("55", Integer.MAX_VALUE);
assertThatSoyExpr("BOOL").withGlobals(globals).translatesTo("True", Integer.MAX_VALUE);
}
@Test
public void testDataRef() {
assertThatSoyExpr("$boo").translatesTo("data.get('boo')", Integer.MAX_VALUE);
assertThatSoyExpr("$boo.goo").translatesTo("data.get('boo').get('goo')", Integer.MAX_VALUE);
assertThatSoyExpr("$boo['goo']")
.translatesTo("runtime.key_safe_data_access(data.get('boo'), 'goo')", Integer.MAX_VALUE);
assertThatSoyExpr("$boo[0]")
.translatesTo("runtime.key_safe_data_access(data.get('boo'), 0)", Integer.MAX_VALUE);
assertThatSoyExpr("$boo[0]")
.translatesTo("runtime.key_safe_data_access(data.get('boo'), 0)", Integer.MAX_VALUE);
assertThatSoyExpr("$boo[$foo][$foo+1]")
.translatesTo(
"runtime.key_safe_data_access("
+ "runtime.key_safe_data_access(data.get('boo'), data.get('foo')), "
+ "runtime.type_safe_add(data.get('foo'), 1))",
Integer.MAX_VALUE);
assertThatSoyExpr("$boo?.goo")
.translatesTo(
"None if data.get('boo') is None else data.get('boo').get('goo')",
Operator.CONDITIONAL);
assertThatSoyExpr("$boo?[0]?[1]")
.translatesTo(
"None if data.get('boo') is None else "
+ "None if runtime.key_safe_data_access(data.get('boo'), 0) is None else "
+ "runtime.key_safe_data_access("
+ "runtime.key_safe_data_access(data.get('boo'), 0), 1)",
Operator.CONDITIONAL);
}
@Test
public void testDataRef_localVars() {
Map<String, PyExpr> frame = Maps.newHashMap();
frame.put("zoo", new PyExpr("zooData8", Integer.MAX_VALUE));
assertThatSoyExpr("$zoo").with(frame).translatesTo("zooData8", Integer.MAX_VALUE);
assertThatSoyExpr("$zoo.boo")
.with(frame)
.translatesTo("zooData8.get('boo')", Integer.MAX_VALUE);
}
@Test
public void testBasicOperators() {
assertThatSoyExpr("not $boo or true and $foo")
.translatesTo("not data.get('boo') or True and data.get('foo')", Operator.OR);
}
@Test
public void testEqualOperator() {
assertThatSoyExpr("'5' == 5 ? 1 : 0")
.translatesTo("1 if runtime.type_safe_eq('5', 5) else 0", 1);
assertThatSoyExpr("'5' == $boo ? 1 : 0")
.translatesTo("1 if runtime.type_safe_eq('5', data.get('boo')) else 0", 1);
}
@Test
public void testNotEqualOperator() {
assertThatSoyExpr("'5' != 5").translatesTo("not runtime.type_safe_eq('5', 5)", Operator.NOT);
}
@Test
public void testPlusOperator() {
assertThatSoyExpr("( (8-4) + (2-1) )")
.translatesTo("runtime.type_safe_add(8 - 4, 2 - 1)", Integer.MAX_VALUE);
}
@Test
public void testNullCoalescingOperator() {
assertThatSoyExpr("$boo ?: 5")
.translatesTo(
"data.get('boo') if data.get('boo') is not None else 5", Operator.CONDITIONAL);
}
@Test
public void testConditionalOperator() {
assertThatSoyExpr("$boo ? 5 : 6")
.translatesTo("5 if data.get('boo') else 6", Operator.CONDITIONAL);
}
@Test
public void testBuiltinFunction() {
assertThatSoyExpr("checkNotNull($boo) ? 1 : 0")
.translatesTo("1 if runtime.check_not_null(data.get('boo')) else 0", Operator.CONDITIONAL);
}
}