package jadx.tests.functional;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.IfOp;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.regions.conditions.Compare;
import jadx.core.dex.regions.conditions.IfCondition;
import org.junit.Test;
import static jadx.core.dex.regions.conditions.IfCondition.Mode;
import static jadx.core.dex.regions.conditions.IfCondition.merge;
import static jadx.core.dex.regions.conditions.IfCondition.not;
import static jadx.core.dex.regions.conditions.IfCondition.simplify;
import static org.junit.Assert.assertEquals;
public class TestIfCondition {
private static IfCondition makeCondition(IfOp op, InsnArg a, InsnArg b) {
return IfCondition.fromIfNode(new IfNode(op, -1, a, b));
}
private static IfCondition makeSimpleCondition() {
return makeCondition(IfOp.EQ, mockArg(), LiteralArg.TRUE);
}
private static IfCondition makeNegCondition() {
return makeCondition(IfOp.NE, mockArg(), LiteralArg.TRUE);
}
private static InsnArg mockArg() {
return InsnArg.reg(0, ArgType.INT);
}
@Test
public void testNormalize() {
// 'a != false' => 'a == true'
InsnArg a = mockArg();
IfCondition c = makeCondition(IfOp.NE, a, LiteralArg.FALSE);
IfCondition simp = simplify(c);
assertEquals(simp.getMode(), Mode.COMPARE);
Compare compare = simp.getCompare();
assertEquals(compare.getA(), a);
assertEquals(compare.getB(), LiteralArg.TRUE);
}
@Test
public void testMerge() {
IfCondition a = makeSimpleCondition();
IfCondition b = makeSimpleCondition();
IfCondition c = merge(Mode.OR, a, b);
assertEquals(c.getMode(), Mode.OR);
assertEquals(c.first(), a);
assertEquals(c.second(), b);
}
@Test
public void testSimplifyNot() {
// !(!a) => a
IfCondition a = not(not(makeSimpleCondition()));
assertEquals(simplify(a), a);
}
@Test
public void testSimplifyNot2() {
// !(!a) => a
IfCondition a = not(makeNegCondition());
assertEquals(simplify(a), a);
}
@Test
public void testSimplify() {
// '!(!a || !b)' => 'a && b'
IfCondition a = makeSimpleCondition();
IfCondition b = makeSimpleCondition();
IfCondition c = not(merge(Mode.OR, not(a), not(b)));
IfCondition simp = simplify(c);
assertEquals(simp.getMode(), Mode.AND);
assertEquals(simp.first(), a);
assertEquals(simp.second(), b);
}
@Test
public void testSimplify2() {
// '(!a || !b) && !c' => '!((a && b) || c)'
IfCondition a = makeSimpleCondition();
IfCondition b = makeSimpleCondition();
IfCondition c = makeSimpleCondition();
IfCondition cond = merge(Mode.AND, merge(Mode.OR, not(a), not(b)), not(c));
IfCondition simp = simplify(cond);
assertEquals(simp.getMode(), Mode.NOT);
IfCondition f = simp.first();
assertEquals(f.getMode(), Mode.OR);
assertEquals(f.first().getMode(), Mode.AND);
assertEquals(f.first().first(), a);
assertEquals(f.first().second(), b);
assertEquals(f.second(), c);
}
}