| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * 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.android.tools.lint.detector.api; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.File; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| import lombok.ast.CompilationUnit; |
| import lombok.ast.Expression; |
| import lombok.ast.ForwardingAstVisitor; |
| import lombok.ast.VariableDefinitionEntry; |
| |
| public class ConstantEvaluatorTest extends TestCase { |
| private static void check(Object expected, String source, final String targetVariable) { |
| JavaContext context = LintUtilsTest.parse(source, new File("src/test/pkg/Test.java")); |
| assertNotNull(context); |
| CompilationUnit unit = (CompilationUnit) context.getCompilationUnit(); |
| assertNotNull(unit); |
| |
| // Find the expression |
| final AtomicReference<Expression> reference = new AtomicReference<Expression>(); |
| unit.accept(new ForwardingAstVisitor() { |
| @Override |
| public boolean visitVariableDefinitionEntry(VariableDefinitionEntry node) { |
| if (node.astName().astValue().equals(targetVariable)) { |
| reference.set(node.astInitializer()); |
| } |
| return super.visitVariableDefinitionEntry(node); |
| } |
| }); |
| Expression expression = reference.get(); |
| Object actual = ConstantEvaluator.evaluate(context, expression); |
| if (expected == null) { |
| assertNull(actual); |
| } else { |
| assertNotNull("Couldn't compute value for " + source + ", expected " + expected, |
| actual); |
| assertEquals(expected.getClass(), actual.getClass()); |
| assertEquals(expected.toString(), actual.toString()); |
| } |
| assertEquals(expected, actual); |
| if (expected instanceof String) { |
| assertEquals(expected, ConstantEvaluator.evaluateString(context, expression, |
| false)); |
| } |
| } |
| |
| private static void checkStatements(Object expected, String statementsSource, |
| final String targetVariable) { |
| String source = "" |
| + "package test.pkg;\n" |
| + "public class Test {\n" |
| + " public void test() {\n" |
| + " " + statementsSource + "\n" |
| + " }\n" |
| + " public static final int MY_INT_FIELD = 5;\n" |
| + " public static final boolean MY_BOOLEAN_FIELD = true;\n" |
| + " public static final String MY_STRING_FIELD = \"test\";\n" |
| + "}\n"; |
| |
| check(expected, source, targetVariable); |
| } |
| |
| private static void checkExpression(Object expected, String expressionSource) { |
| String source = "" |
| + "package test.pkg;\n" |
| + "public class Test {\n" |
| + " public void test() {\n" |
| + " Object expression = " + expressionSource + ";\n" |
| + " }\n" |
| + " public static final int MY_INT_FIELD = 5;\n" |
| + " public static final boolean MY_BOOLEAN_FIELD = true;\n" |
| + " public static final String MY_STRING_FIELD = \"test\";\n" |
| + "}\n"; |
| |
| check(expected, source, "expression"); |
| } |
| |
| public void testStrings() throws Exception { |
| checkExpression(null, "null"); |
| checkExpression("hello", "\"hello\""); |
| checkExpression("abcd", "\"ab\" + \"cd\""); |
| } |
| |
| public void testBooleans() throws Exception { |
| checkExpression(true, "true"); |
| checkExpression(false, "false"); |
| checkExpression(false, "false && true"); |
| checkExpression(true, "false || true"); |
| checkExpression(true, "!false"); |
| } |
| |
| public void testCasts() throws Exception { |
| checkExpression(1, "(int)1"); |
| checkExpression(1L, "(long)1"); |
| checkExpression(1, "(int)1.1f"); |
| checkExpression((short)65537, "(short)65537"); |
| checkExpression((byte)1023, "(byte)1023"); |
| checkExpression(1.5, "(double)1.5f"); |
| checkExpression(-5.0, "(double)-5"); |
| } |
| |
| public void testArithmetic() throws Exception { |
| checkExpression(1, "1"); |
| checkExpression(1L, "1L"); |
| checkExpression(4, "1 + 3"); |
| checkExpression(-2, "1 - 3"); |
| checkExpression(10, "2 * 5"); |
| checkExpression(2, "10 / 5"); |
| checkExpression(1, "11 % 5"); |
| checkExpression(8, "1 << 3"); |
| checkExpression(16, "32 >> 1"); |
| checkExpression(16, "32 >>> 1"); |
| checkExpression(5, "5 | 1"); |
| checkExpression(1, "5 & 1"); |
| checkExpression(~5, "~5"); |
| checkExpression(~(long)5, "~(long)5"); |
| checkExpression(~(short)5, "~(short)5"); |
| checkExpression(~(byte)5, "~(byte)5"); |
| checkExpression(-(long)5, "-(long)5"); |
| checkExpression(-(short)5, "-(short)5"); |
| checkExpression(-(byte)5, "-(byte)5"); |
| checkExpression(-(double)5, "-(double)5"); |
| checkExpression(-(float)5, "-(float)5"); |
| checkExpression(-2, "1 + -3"); |
| |
| checkExpression(false, "11 == 5"); |
| checkExpression(true, "11 == 11"); |
| checkExpression(true, "11 != 5"); |
| checkExpression(false, "11 != 11"); |
| checkExpression(true, "11 > 5"); |
| checkExpression(false, "5 > 11"); |
| checkExpression(false, "11 < 5"); |
| checkExpression(true, "5 < 11"); |
| checkExpression(true, "11 >= 5"); |
| checkExpression(false, "5 >= 11"); |
| checkExpression(false, "11 <= 5"); |
| checkExpression(true, "5 <= 11"); |
| |
| checkExpression(3.5f, "1.0f + 2.5f"); |
| } |
| |
| public void testFieldReferences() throws Exception { |
| checkExpression(5, "MY_INT_FIELD"); |
| checkExpression("test", "MY_STRING_FIELD"); |
| checkExpression("prefix-test-postfix", "\"prefix-\" + MY_STRING_FIELD + \"-postfix\""); |
| checkExpression(-4, "3 - (MY_INT_FIELD + 2)"); |
| } |
| |
| public void testStatements() throws Exception { |
| checkStatements(9, "" |
| + "int x = +5;\n" |
| + "int y = x;\n" |
| + "int w;\n" |
| + "w = -1;\n" |
| + "int z = x + 5 + w;\n", |
| "z"); |
| checkStatements("hello world", "" |
| + "String initial = \"hello\";\n" |
| + "String other;\n" |
| + "other = \" world\";\n" |
| + "String finalString = initial + other;\n", |
| "finalString"); |
| } |
| |
| public void testConditionals() throws Exception { |
| checkStatements(-5, "" |
| + "boolean condition = false;\n" |
| + "condition = !condition;\n" |
| + "int z = condition ? -5 : 4;\n", |
| "z"); |
| checkStatements(-4, "" |
| + "boolean condition = true && false;\n" |
| + "int z = condition ? 5 : -4;\n", |
| "z"); |
| } |
| } |