blob: c8408436d9e93f20799abf254a1be2b07faa2c7f [file] [log] [blame]
/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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 net.hydromatic.linq4j.test;
import net.hydromatic.linq4j.expressions.*;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Unit test for {@link net.hydromatic.linq4j.expressions.BlockBuilder}
* optimization capabilities.
*/
public class OptimizerTest extends BlockBuilderBase {
@Test
public void optimizeComparison() {
assertEquals("{\n return true;\n}\n", optimize(
Expressions.equal(ONE, ONE)));
}
@Test
public void optimizeTernaryAlwaysTrue() {
// true ? 1 : 2
assertEquals("{\n return 1;\n}\n", optimize(
Expressions.condition(TRUE, ONE, TWO)));
}
@Test
public void optimizeTernaryAlwaysFalse() {
// false ? 1 : 2
assertEquals("{\n return 2;\n}\n", optimize(
Expressions.condition(FALSE, ONE, TWO)));
}
@Test
public void optimizeTernaryAlwaysSame() {
// bool ? 1 : 1
assertEquals("{\n return 1;\n}\n", optimize(Expressions.condition(
Expressions.parameter(boolean.class, "bool"), ONE, ONE)));
}
@Test
public void nonOptimizableTernary() {
// bool ? 1 : 2
assertEquals("{\n return bool ? 1 : 2;\n}\n",
optimize(Expressions.condition(
Expressions.parameter(boolean.class, "bool"), ONE, TWO)));
}
@Test
public void optimizeTernaryRotateNot() {
// !bool ? 1 : 2
assertEquals("{\n return bool ? 2 : 1;\n}\n",
optimize(Expressions.condition(
Expressions.not(Expressions.parameter(boolean.class, "bool")),
ONE, TWO)));
}
@Test
public void optimizeTernaryRotateEqualFalse() {
// bool == false ? 1 : 2
assertEquals("{\n return bool ? 2 : 1;\n}\n",
optimize(Expressions.condition(
Expressions.equal(Expressions.parameter(boolean.class, "bool"),
FALSE),
ONE, TWO)));
}
@Test
public void optimizeTernaryInEqualABCeqB() {
// (v ? (Integer) null : inp0_) == null
assertEquals("{\n return v || inp0_ == null;\n}\n",
optimize(Expressions.equal(Expressions.condition(
Expressions.parameter(boolean.class, "v"),
NULL_INTEGER, Expressions.parameter(Integer.class, "inp0_")),
NULL))
);
}
@Test
public void optimizeTernaryInEqualABCeqC() {
// (v ? inp0_ : (Integer) null) == null
assertEquals("{\n return !v || inp0_ == null;\n}\n",
optimize(Expressions.equal(Expressions.condition(
Expressions.parameter(boolean.class, "v"),
Expressions.parameter(Integer.class, "inp0_"), NULL_INTEGER),
NULL))
);
}
@Test
public void optimizeTernaryAeqBBA() {
// a == b ? b : a
ParameterExpression a = Expressions.parameter(boolean.class, "a");
ParameterExpression b = Expressions.parameter(boolean.class, "b");
assertEquals("{\n return a;\n}\n",
optimize(Expressions.condition(Expressions.equal(a, b), b, a)));
}
@Test
public void optimizeTernaryAeqBAB() {
// a == b ? b : a
ParameterExpression a = Expressions.parameter(boolean.class, "a");
ParameterExpression b = Expressions.parameter(boolean.class, "b");
assertEquals("{\n return b;\n}\n",
optimize(Expressions.condition(Expressions.equal(a, b), a, b)));
}
@Test
public void optimizeTernaryInEqualABCneqB() {
// (v ? (Integer) null : inp0_) != null
assertEquals("{\n return !(v || inp0_ == null);\n}\n",
optimize(Expressions.notEqual(Expressions.condition(
Expressions.parameter(boolean.class, "v"),
NULL_INTEGER, Expressions.parameter(Integer.class, "inp0_")),
NULL))
);
}
@Test
public void optimizeTernaryInEqualABCneqC() {
// (v ? inp0_ : (Integer) null) != null
assertEquals("{\n return !(!v || inp0_ == null);\n}\n",
optimize(Expressions.notEqual(Expressions.condition(
Expressions.parameter(boolean.class, "v"),
Expressions.parameter(Integer.class, "inp0_"), NULL_INTEGER),
NULL))
);
}
@Test
public void optimizeTernaryAneqBBA() {
// a != b ? b : a
ParameterExpression a = Expressions.parameter(boolean.class, "a");
ParameterExpression b = Expressions.parameter(boolean.class, "b");
assertEquals("{\n return b;\n}\n",
optimize(Expressions.condition(Expressions.notEqual(a, b), b, a)));
}
@Test
public void optimizeTernaryAneqBAB() {
// a != b ? a : b
ParameterExpression a = Expressions.parameter(boolean.class, "a");
ParameterExpression b = Expressions.parameter(boolean.class, "b");
assertEquals("{\n return a;\n}\n",
optimize(Expressions.condition(Expressions.notEqual(a, b), a, b)));
}
@Test
public void andAlsoTrueBool() {
// true && bool
assertEquals("{\n return bool;\n}\n", optimize(Expressions.andAlso(TRUE,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void andAlsoBoolTrue() {
// bool && true
assertEquals("{\n return bool;\n}\n", optimize(Expressions.andAlso(
Expressions.parameter(boolean.class,
"bool"), TRUE)));
}
@Test
public void andAlsoFalseBool() {
// false && bool
assertEquals("{\n return false;\n}\n", optimize(Expressions.andAlso(FALSE,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void andAlsoNullBool() {
// null && bool
assertEquals("{\n return null && bool;\n}\n",
optimize(Expressions.andAlso(NULL,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void andAlsoXY() {
// x && y
assertEquals("{\n return x && y;\n}\n", optimize(Expressions.andAlso(
Expressions.parameter(
boolean.class, "x"),
Expressions.parameter(boolean.class,
"y"))));
}
@Test
public void andAlsoXX() {
// x && x
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return x;\n}\n", optimize(Expressions.andAlso(x, x)));
}
@Test
public void orElseTrueBool() {
// true || bool
assertEquals("{\n return true;\n}\n", optimize(Expressions.orElse(TRUE,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void orElseFalseBool() {
// false || bool
assertEquals("{\n return bool;\n}\n", optimize(Expressions.orElse(FALSE,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void orElseNullBool() {
// null || bool
assertEquals("{\n return null || bool;\n}\n",
optimize(Expressions.orElse(NULL,
Expressions.parameter(boolean.class,
"bool"))));
}
@Test
public void orElseXY() {
// x || y
assertEquals("{\n return x || y;\n}\n", optimize(Expressions.orElse(
Expressions.parameter(
boolean.class, "x"),
Expressions.parameter(boolean.class,
"y"))));
}
@Test
public void orElseXX() {
// x || x
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return x;\n}\n", optimize(Expressions.orElse(x, x)));
}
@Test
public void equalSameConst() {
// 1 == 1
assertEquals("{\n return true;\n}\n", optimize(Expressions.equal(ONE,
Expressions.constant(1))));
}
@Test
public void equalDifferentConst() {
// 1 == 2
assertEquals("{\n return false;\n}\n", optimize(Expressions.equal(ONE,
TWO)));
}
@Test
public void equalSameExpr() {
// x == x
ParameterExpression x = Expressions.parameter(int.class, "x");
assertEquals("{\n return true;\n}\n", optimize(Expressions.equal(x, x)));
}
@Test
public void equalDifferentExpr() {
// x == y
ParameterExpression x = Expressions.parameter(int.class, "x");
ParameterExpression y = Expressions.parameter(int.class, "y");
assertEquals("{\n return x == y;\n}\n", optimize(Expressions.equal(x, y)));
}
@Test
public void equalPrimitiveNull() {
// (int) x == null
ParameterExpression x = Expressions.parameter(int.class, "x");
assertEquals("{\n return false;\n}\n", optimize(Expressions.equal(x,
NULL)));
}
@Test
public void equalObjectNull() {
// (Integer) x == null
ParameterExpression x = Expressions.parameter(Integer.class, "x");
assertEquals("{\n return x == null;\n}\n",
optimize(Expressions.equal(x,
NULL)));
}
@Test
public void equalStringNull() {
// "Y" == null
assertEquals("{\n return false;\n}\n",
optimize(Expressions.equal(Expressions.constant("Y"), NULL)));
}
@Test
public void equalTypedNullUntypedNull() {
// (Integer) null == null
assertEquals("{\n return true;\n}\n",
optimize(Expressions.equal(NULL_INTEGER, NULL)));
}
@Test
public void equalUnypedNullTypedNull() {
// null == (Integer) null
assertEquals("{\n return true;\n}\n",
optimize(Expressions.equal(NULL, NULL_INTEGER)));
}
@Test
public void equalBoolTrue() {
// x == true
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return x;\n}\n", optimize(Expressions.equal(x, TRUE)));
}
@Test
public void equalBoolFalse() {
// x == false
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return !x;\n}\n", optimize(Expressions.equal(x, FALSE)));
}
@Test
public void notEqualSameConst() {
// 1 != 1
assertEquals("{\n return false;\n}\n", optimize(Expressions.notEqual(
ONE, Expressions.constant(1))));
}
@Test
public void notEqualDifferentConst() {
// 1 != 2
assertEquals("{\n return true;\n}\n", optimize(Expressions.notEqual(ONE,
TWO)));
}
@Test
public void notEqualSameExpr() {
// x != x
ParameterExpression x = Expressions.parameter(int.class, "x");
assertEquals("{\n return false;\n}\n", optimize(Expressions.notEqual(x,
x)));
}
@Test
public void notEqualDifferentExpr() {
// x != y
ParameterExpression x = Expressions.parameter(int.class, "x");
ParameterExpression y = Expressions.parameter(int.class, "y");
assertEquals("{\n return x != y;\n}\n", optimize(Expressions.notEqual(x,
y)));
}
@Test
public void notEqualPrimitiveNull() {
// (int) x == null
ParameterExpression x = Expressions.parameter(int.class, "x");
assertEquals("{\n return true;\n}\n", optimize(Expressions.notEqual(x,
NULL)));
}
@Test
public void notEqualObjectNull() {
// (Integer) x == null
ParameterExpression x = Expressions.parameter(Integer.class, "x");
assertEquals("{\n return x != null;\n}\n",
optimize(Expressions.notEqual(
x, NULL)));
}
@Test
public void notEqualStringNull() {
// "Y" != null
assertEquals("{\n return true;\n}\n",
optimize(Expressions.notEqual(Expressions.constant("Y"), NULL)));
}
@Test
public void notEqualTypedNullUntypedNull() {
// (Integer) null != null
assertEquals("{\n return false;\n}\n",
optimize(Expressions.notEqual(NULL_INTEGER, NULL)));
}
@Test
public void notEqualUnypedNullTypedNull() {
// null != (Integer) null
assertEquals("{\n return false;\n}\n",
optimize(Expressions.notEqual(NULL, NULL_INTEGER)));
}
@Test
public void notEqualBoolTrue() {
// x != true
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return !x;\n}\n", optimize(Expressions.notEqual(x,
TRUE)));
}
@Test
public void notEqualBoolFalse() {
// x != false
ParameterExpression x = Expressions.parameter(boolean.class, "x");
assertEquals("{\n return x;\n}\n", optimize(Expressions.notEqual(x,
FALSE)));
}
@Test
public void multipleFolding() {
// ( 1 == 2 ? 3 : 4 ) != (5 != 6 ? 4 : 8) ? 9 : 10
assertEquals("{\n return 10;\n}\n", optimize(Expressions.condition(
Expressions.notEqual(
Expressions.condition(Expressions.equal(ONE, TWO),
Expressions.constant(3),
Expressions.constant(4)), Expressions.condition(
Expressions.notEqual(
Expressions.constant(5), Expressions.constant(6)),
Expressions.constant(4), Expressions.constant(8))),
Expressions.constant(9),
Expressions.constant(10))));
}
@Test
public void conditionalIfTrue() {
// if (true) {return 1}
assertEquals("{\n return 1;\n}\n", optimize(Expressions.ifThen(TRUE,
Expressions.return_(null, ONE))));
}
@Test
public void conditionalIfTrueElse() {
// if (true) {return 1} else {return 2}
assertEquals("{\n return 1;\n}\n", optimize(Expressions.ifThenElse(TRUE,
Expressions.return_(null, ONE), Expressions.return_(null, TWO))));
}
@Test
public void conditionalIfFalse() {
// if (false) {return 1}
assertEquals("{}", optimize(Expressions.ifThen(FALSE,
Expressions.return_(null, ONE))));
}
@Test
public void conditionalIfFalseElse() {
// if (false) {return 1} else {return 2}
assertEquals("{\n return 2;\n}\n", optimize(Expressions.ifThenElse(FALSE,
Expressions.return_(null, ONE), Expressions.return_(null, TWO))));
}
@Test
public void conditionalIfBoolTrue() {
// if (bool) {return 1} else if (true) {return 2}
Expression bool = Expressions.parameter(boolean.class, "bool");
assertEquals("{\n"
+ " if (bool) {\n"
+ " return 1;\n"
+ " } else {\n"
+ " return 2;\n"
+ " }\n"
+ "}\n", optimize(Expressions.ifThenElse(bool,
Expressions.return_(null, ONE), TRUE, Expressions.return_(null,
TWO))));
}
@Test
public void conditionalIfBoolTrueElse() {
// if (bool) {return 1} else if (true) {return 2} else {return 3}
Expression bool = Expressions.parameter(boolean.class, "bool");
assertEquals("{\n"
+ " if (bool) {\n"
+ " return 1;\n"
+ " } else {\n"
+ " return 2;\n"
+ " }\n"
+ "}\n", optimize(Expressions.ifThenElse(bool,
Expressions.return_(null, ONE), TRUE, Expressions.return_(null,
TWO), Expressions.return_(null, THREE))));
}
@Test
public void conditionalIfBoolFalse() {
// if (bool) {return 1} else if (false) {return 2}
Expression bool = Expressions.parameter(boolean.class, "bool");
assertEquals("{\n"
+ " if (bool) {\n"
+ " return 1;\n"
+ " }\n"
+ "}\n", optimize(Expressions.ifThenElse(bool,
Expressions.return_(null, ONE), FALSE, Expressions.return_(null,
TWO))));
}
@Test
public void conditionalIfBoolFalseElse() {
// if (bool) {return 1} else if (false) {return 2} else {return 3}
Expression bool = Expressions.parameter(boolean.class, "bool");
assertEquals("{\n"
+ " if (bool) {\n"
+ " return 1;\n"
+ " } else {\n"
+ " return 3;\n"
+ " }\n"
+ "}\n", optimize(Expressions.ifThenElse(bool,
Expressions.return_(null, ONE), FALSE, Expressions.return_(null,
TWO), Expressions.return_(null, THREE))));
}
@Test
public void conditionalIfBoolFalseTrue() {
// if (bool) {1} else if (false) {2} if (true) {4} else {5}
Expression bool = Expressions.parameter(boolean.class, "bool");
assertEquals("{\n"
+ " if (bool) {\n"
+ " return 1;\n"
+ " } else {\n"
+ " return 4;\n"
+ " }\n"
+ "}\n", optimize(Expressions.ifThenElse(bool,
Expressions.return_(null, ONE), FALSE, Expressions.return_(null,
TWO), TRUE, Expressions.return_(null, FOUR),
Expressions.return_(null, Expressions.constant(5)))));
}
@Test
public void castIntToShort() {
// return (short) 1 --> return (short) 1
assertEquals("{\n return (short)1;\n}\n", optimize(Expressions.convert_(
ONE, short.class)));
}
@Test
public void castIntToInt() {
// return (int) 1 --> return 1L
assertEquals("{\n return 1;\n}\n", optimize(Expressions.convert_(ONE,
int.class)));
}
@Test
public void castIntToLong() {
// return (long) 1 --> return 1L
assertEquals("{\n return 1L;\n}\n", optimize(Expressions.convert_(ONE,
long.class)));
}
}