move asm related tests from FilterOpTest to OptimizedAsmParser testcase

This commit is contained in:
wea_ondara
2022-07-27 15:27:59 +02:00
parent 3824a6f595
commit 23e046ef7e
5 changed files with 217 additions and 197 deletions

View File

@@ -0,0 +1,42 @@
package jef.asm;
import jef.expressions.Expression;
import jef.expressions.modifier.ExpressionOptimizerBottomUp;
import jef.expressions.modifier.IConst0Fixer;
import jef.expressions.modifier.TableAliasInjector;
import jef.expressions.modifier.TernaryRewriter;
import jef.serializable.SerializableFunction;
import jef.serializable.SerializablePredicate;
import lombok.Getter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.util.stream.IntStream;
@Getter
public class OptimizedAsmParser extends AsmParser{
public OptimizedAsmParser(SerializablePredicate<?> predicate) {
super(predicate);
}
public OptimizedAsmParser(SerializableFunction<?, ?> function) {
super(function);
}
public Expression parse() throws AsmParseException {
var expr = super.parse();
System.out.println(expr);
expr = new TernaryRewriter().modify(expr);
System.out.println(expr);
expr = new IConst0Fixer().modify(expr);
System.out.println(expr);
expr = new ExpressionOptimizerBottomUp().modify(expr);
return expr;
}
}

View File

@@ -23,6 +23,6 @@ public class IntermediateFieldExpression extends ConstantExpression implements S
@Override @Override
public String toString() { public String toString() {
return name; return "`" + name + "`";
} }
} }

View File

@@ -3,6 +3,7 @@ package jef.operations;
import jef.Queryable; import jef.Queryable;
import jef.asm.AsmParseException; import jef.asm.AsmParseException;
import jef.asm.AsmParser; import jef.asm.AsmParser;
import jef.asm.OptimizedAsmParser;
import jef.expressions.Expression; import jef.expressions.Expression;
import jef.expressions.SelectExpression; import jef.expressions.SelectExpression;
import jef.expressions.WhereExpression; import jef.expressions.WhereExpression;
@@ -27,20 +28,14 @@ public class FilterOp<T extends Serializable> implements Queryable<T>, Operation
public FilterOp(Queryable<T> queryable, SerializablePredicate<? super T> predicate) { public FilterOp(Queryable<T> queryable, SerializablePredicate<? super T> predicate) {
this.queryable = queryable; this.queryable = queryable;
this.predicate = predicate; this.predicate = predicate;
var parser = new AsmParser(predicate); var parser = new OptimizedAsmParser(predicate);
Expression expr; Expression expr;
try { try {
expr = parser.parse(); expr = parser.parse();
} catch (AsmParseException e) { } catch (AsmParseException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
System.out.println(expr);
expr = new TernaryRewriter().modify(expr);
System.out.println(expr);
expr = new IConst0Fixer().modify(expr);
System.out.println(expr);
// expr = new ExpressionOptimizer().modify(expr);
expr = new ExpressionOptimizerBottomUp().modify(expr);
expr = new TableAliasInjector(getTableAlias()).modify(expr);//TODO this does not work together with expression optimization expr = new TableAliasInjector(getTableAlias()).modify(expr);//TODO this does not work together with expression optimization
this.predicateExpr = expr; this.predicateExpr = expr;
//TODO optimize whole expression //TODO optimize whole expression

View File

@@ -0,0 +1,170 @@
package jef.asm;
import jef.serializable.SerializableObject;
import jef.serializable.SerializablePredicate;
import lombok.Getter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
public class OptimizedAsmParserTest {
@Test
public void testTrue() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> true).parse().toString();
Assertions.assertEquals("1", act);
}
@Test
public void testCompareWithEntityMember() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1).parse().toString();
Assertions.assertEquals("`i` = 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i != 1).parse().toString();
Assertions.assertEquals("`i` <> 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i < 1).parse().toString();
Assertions.assertEquals("`i` < 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i > 1).parse().toString();
Assertions.assertEquals("`i` > 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i <= 1).parse().toString();
Assertions.assertEquals("`i` <= 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i >= 1).parse().toString();
Assertions.assertEquals("`i` >= 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337).parse().toString();
Assertions.assertEquals("`i` = 1337", act);
}
@Test
public void testContainsWithEntityMember() throws AsmParseException {
var s = List.of(1, 3);
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i)).parse().toString();
Assertions.assertEquals("`i` IN (1, 3)", act);
//TODO
// act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> List.of(1, 3).contains(e.i)).parse().toString();
// Assertions.assertEquals("`i` IN (1, 3)", act);
}
@Test
public void testComplexExpression() throws AsmParseException {
String act;
var s = List.of(1, 3);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337).parse().toString();
Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && e.i == 1337 && e.i == 420).parse().toString();
Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337 AND `i` = 420", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i != 420 || s.contains(e.i)).parse().toString();
Assertions.assertEquals("`i` = 1337 OR `i` <> 420 OR `i` IN (1, 3)", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || e.i == 420 || s.contains(e.i)).parse().toString();
Assertions.assertEquals("`i` = 1337 OR `i` = 420 OR `i` IN (1, 3)", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 1337 || s.contains(e.i) || e.i == 420).parse().toString();
Assertions.assertEquals("`i` = 1337 OR `i` IN (1, 3) OR `i` = 420", act);
}
@Test
public void testComplexExpressionMixedAndOr() throws AsmParseException {
String act;
var s = List.of(1, 3);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i) && (e.i == 1337 || e.i == 420)).parse().toString();
Assertions.assertEquals("`i` IN (1, 3) AND (`i` = 1337 OR `i` = 420)", act);
// act = new OptimizedAsmParser((SerializablePredicate<?>)(TestClass e) -> (e.i == 1337 || e.i == 420) && s.contains(e.i)).toString();
// Assertions.assertEquals("(`i` = 1337 OR `i` = 420) AND `i` IN (1, 3)", act);
// //actually produced, it's not wrong but the expression is weird
// Assertions.assertEquals("`i` <> 1337 AND `i` = 420 AND `i` IN (1, 3) OR `i` = 1337 AND `i` IN (1, 3)", act);
}
@Test
public void testObject() throws AsmParseException {
String act;
var s = Arrays.asList(null, 4);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o == null).parse().toString();
Assertions.assertEquals("`o` IS NULL", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null).parse().toString();
Assertions.assertEquals("`o` IS NOT NULL", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.o != null || s.contains(e.o)).parse().toString();
Assertions.assertEquals("`o` IS NOT NULL OR `o` IN (NULL, 4)", act);
}
@Test
public void testFloatingPoint() throws AsmParseException {
String act;
var s = Arrays.asList(null, 2);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 3.14d).parse().toString();
Assertions.assertEquals("`d` = 3.14", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 3.14f).parse().toString();
Assertions.assertEquals("`f` = 3.14", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d != 1d || e.f != 1 || s.contains(e.d)).parse().toString();
Assertions.assertEquals("`d` <> 1 OR `f` <> 1 OR `d` IN (NULL, 2)", act);
}
@Test
public void testIDFLConst() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5).parse().toString();
Assertions.assertEquals("`i` = 0 OR `i` = 1 OR `i` = 2 OR `i` = 3 OR `i` = 4 OR `i` = 5", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.d == 0D || e.d == 1D).parse().toString();
Assertions.assertEquals("`d` = 0 OR `d` = 1", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.f == 0F || e.f == 1F || e.f == 2F).parse().toString();
Assertions.assertEquals("`f` = 0 OR `f` = 1 OR `f` = 2", act);
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.l == 0L || e.l == 1L).parse().toString();
Assertions.assertEquals("`l` = 0 OR `l` = 1", act);
}
@Test
public void testMemberViaGetter() throws AsmParseException {
String act;
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.getI() == 1337).parse().toString();
Assertions.assertEquals("`i` = 1337", act);
}
@Getter
public static class TestClass extends SerializableObject {
public int i = 1;
public Object o = new Object();
public double d;
public float f;
public long l;
}
}

View File

@@ -12,7 +12,7 @@ import java.util.List;
public class FilterOpTest { public class FilterOpTest {
@Test @Test
public void testTrue() { public void testSimple() {
String act; String act;
act = new DbSet<>(TestClass.class, "table1") act = new DbSet<>(TestClass.class, "table1")
.filter(e -> true) .filter(e -> true)
@@ -20,61 +20,6 @@ public class FilterOpTest {
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE 1", act); Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE 1", act);
} }
@Test
public void testCompareWithEntityMember() {
String act;
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i != 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <> 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i < 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` < 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i > 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` > 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i <= 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <= 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i >= 1)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` >= 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 1337)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337", act);
}
@Test
public void testContainsWithEntityMember() {
var s = List.of(1, 3);
String act;
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> s.contains(e.i))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)", act);
}
@Test @Test
public void testMultipleFilter() { public void testMultipleFilter() {
String act; String act;
@@ -86,138 +31,6 @@ public class FilterOpTest {
Assertions.assertEquals("SELECT * FROM (SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)) b WHERE `b`.`i` = 1337", act); Assertions.assertEquals("SELECT * FROM (SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)) b WHERE `b`.`i` = 1337", act);
} }
@Test
public void testComplexExpression() {
String act;
var s = List.of(1, 3);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> s.contains(e.i) && e.i == 1337)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND `a`.`i` = 1337", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> s.contains(e.i) && e.i == 1337 && e.i == 420)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND `a`.`i` = 1337 AND `a`.`i` = 420", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 1337 || e.i != 420 || s.contains(e.i))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` <> 420 OR `a`.`i` IN (1, 3)", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 1337 || e.i == 420 || s.contains(e.i))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` = 420 OR `a`.`i` IN (1, 3)", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 1337 || s.contains(e.i) || e.i == 420)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` IN (1, 3) OR `a`.`i` = 420", act);
}
@Test
public void testComplexExpressionMixedAndOr() {
String act;
var s = List.of(1, 3);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> s.contains(e.i) && (e.i == 1337 || e.i == 420))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND (`a`.`i` = 1337 OR `a`.`i` = 420)", act);
// act = new DbSet<>(TestClass.class, "table1")
// .filter(e -> (e.i == 1337 || e.i == 420) && s.contains(e.i))
// .toString();
// Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE (`a`.`i` = 1337 OR `a`.`i` = 420) AND `a`.`i` IN (1, 3)", act);
// //actually produced, it's not wrong but the expression is weird
// Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <> 1337 AND `a`.`i` = 420 AND `a`.`i` IN (1, 3) OR `a`.`i` = 1337 AND `a`.`i` IN (1, 3)", act);
}
@Test
public void testObject() {
String act;
var s = Arrays.asList(null, 4);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.o == null)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`o` IS NULL", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.o != null)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`o` IS NOT NULL", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.o != null || s.contains(e.o))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`o` IS NOT NULL OR `a`.`o` IN (NULL, 4)", act);
}
@Test
public void testFloatingPoint() {
String act;
var s = Arrays.asList(null, 2);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.d == 3.14d)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` = 3.14", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.f == 3.14f)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`f` = 3.14", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.d != 1d || e.f != 1 || s.contains(e.d))
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` <> 1 OR `a`.`f` <> 1 OR `a`.`d` IN (NULL, 2)", act);
}
@Test
public void testIDFLConst() {
String act;
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 OR `a`.`i` = 1 OR `a`.`i` = 2 OR `a`.`i` = 3 OR `a`.`i` = 4 OR `a`.`i` = 5", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.d == 0D || e.d == 1D)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` = 0 OR `a`.`d` = 1", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.f == 0F || e.f == 1F || e.f == 2F)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`f` = 0 OR `a`.`f` = 1 OR `a`.`f` = 2", act);
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.l == 0L || e.l == 1L)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`l` = 0 OR `a`.`l` = 1", act);
}
@Test
public void testMemberViaGetter() {
String act;
act = new DbSet<>(TestClass.class, "table1")
.filter(e -> e.getI() == 1337)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337", act);
}
@Getter @Getter
public static class TestClass extends SerializableObject { public static class TestClass extends SerializableObject {
public int i = 1; public int i = 1;