From ca21ca5d81b57f58c570e87b89718fcc481c44e2 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sun, 24 Mar 2019 11:23:24 +0300 Subject: [PATCH] test: rewrite Spock tests to JUnit 5 --- build.gradle | 1 - .../java/jadx/core/dex/attributes/AType.java | 3 - .../jadx/tests/TestAttributeStorage.groovy | 82 ----------- .../groovy/jadx/tests/TestNameMapper.groovy | 39 ------ .../jadx/tests/TestSignatureParser.groovy | 107 --------------- .../groovy/jadx/tests/TestStringUtils.groovy | 43 ------ .../src/test/java/jadx/tests/TestsTest.java | 49 ------- .../functional/AttributeStorageTest.java | 84 ++++++++++++ .../jadx/tests/functional/NameMapperTest.java | 44 ++++++ .../tests/functional/SignatureParserTest.java | 128 ++++++++++++++++++ .../tests/functional/StringUtilsTest.java | 52 +++++++ .../integration/loops/TestLoopDetection3.java | 2 - .../jadx/gui/tests/TestJumpManager.groovy | 117 ---------------- .../jadx/gui/tests/TestStringRef.groovy | 71 ---------- .../gui/tests/TestVersionsComparator.groovy | 31 ----- .../gui/update/VersionComparatorTest.java | 33 +++++ .../java/jadx/gui/utils/JumpManagerTest.java | 123 +++++++++++++++++ .../jadx/gui/utils/search/StringRefTest.java | 71 ++++++++++ 18 files changed, 535 insertions(+), 545 deletions(-) delete mode 100644 jadx-core/src/test/groovy/jadx/tests/TestAttributeStorage.groovy delete mode 100644 jadx-core/src/test/groovy/jadx/tests/TestNameMapper.groovy delete mode 100644 jadx-core/src/test/groovy/jadx/tests/TestSignatureParser.groovy delete mode 100644 jadx-core/src/test/groovy/jadx/tests/TestStringUtils.groovy delete mode 100644 jadx-core/src/test/java/jadx/tests/TestsTest.java create mode 100644 jadx-core/src/test/java/jadx/tests/functional/AttributeStorageTest.java create mode 100644 jadx-core/src/test/java/jadx/tests/functional/NameMapperTest.java create mode 100644 jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java create mode 100644 jadx-core/src/test/java/jadx/tests/functional/StringUtilsTest.java delete mode 100644 jadx-gui/src/test/groovy/jadx/gui/tests/TestJumpManager.groovy delete mode 100644 jadx-gui/src/test/groovy/jadx/gui/tests/TestStringRef.groovy delete mode 100644 jadx-gui/src/test/groovy/jadx/gui/tests/TestVersionsComparator.groovy create mode 100644 jadx-gui/src/test/java/jadx/gui/update/VersionComparatorTest.java create mode 100644 jadx-gui/src/test/java/jadx/gui/utils/JumpManagerTest.java create mode 100644 jadx-gui/src/test/java/jadx/gui/utils/search/StringRefTest.java diff --git a/build.gradle b/build.gradle index 14eaf2653..db3f86c15 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,6 @@ allprojects { testCompile 'ch.qos.logback:logback-classic:1.2.3' testCompile 'org.hamcrest:hamcrest-library:2.1' testCompile 'org.mockito:mockito-core:2.25.1' - testCompile 'org.spockframework:spock-core:1.3-groovy-2.5' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.1' diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java b/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java index 1c518d772..35b7346cd 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/AType.java @@ -54,7 +54,4 @@ public class AType { public static final AType DECLARE_VARIABLES = new AType<>(); public static final AType LOOP_LABEL = new AType<>(); public static final AType IGNORE_EDGE = new AType<>(); - - private AType() { - } } diff --git a/jadx-core/src/test/groovy/jadx/tests/TestAttributeStorage.groovy b/jadx-core/src/test/groovy/jadx/tests/TestAttributeStorage.groovy deleted file mode 100644 index 89204f9e7..000000000 --- a/jadx-core/src/test/groovy/jadx/tests/TestAttributeStorage.groovy +++ /dev/null @@ -1,82 +0,0 @@ -package jadx.tests - -import jadx.core.dex.attributes.AType -import jadx.core.dex.attributes.AttributeStorage -import jadx.core.dex.attributes.IAttribute -import spock.lang.Specification - -import static jadx.core.dex.attributes.AFlag.SYNTHETIC - -class TestAttributeStorage extends Specification { - - AttributeStorage storage - - def setup() { - storage = new AttributeStorage() - } - - def "add flag"() { - when: - storage.add(SYNTHETIC) - then: - storage.contains(SYNTHETIC) - } - - def "remove flag"() { - setup: - storage.add(SYNTHETIC) - when: - storage.remove(SYNTHETIC) - then: - !storage.contains(SYNTHETIC) - } - - def TEST = new AType() - class TestAttr implements IAttribute { - AType getType() { TEST } - } - - def "add attribute"() { - setup: - def attr = new TestAttr() - when: - storage.add(attr) - then: - storage.contains(TEST) - storage.get(TEST) == attr - } - - def "remove attribute"() { - setup: - def attr = new TestAttr() - storage.add(attr) - when: - storage.remove(attr) - then: - !storage.contains(TEST) - storage.get(TEST) == null - } - - def "remove attribute other"() { - setup: - def attr = new TestAttr() - storage.add(attr) - when: - storage.remove(new TestAttr()) - then: - storage.contains(TEST) - storage.get(TEST) == attr - } - - def "clear"() { - setup: - storage.add(SYNTHETIC) - storage.add(new TestAttr()) - when: - storage.clear() - then: - !storage.contains(SYNTHETIC) - !storage.contains(TEST) - } - -} diff --git a/jadx-core/src/test/groovy/jadx/tests/TestNameMapper.groovy b/jadx-core/src/test/groovy/jadx/tests/TestNameMapper.groovy deleted file mode 100644 index ecd9b429c..000000000 --- a/jadx-core/src/test/groovy/jadx/tests/TestNameMapper.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package jadx.tests - -import spock.lang.Specification - -import static jadx.core.deobf.NameMapper.isValidFullIdentifier - -class TestNameMapper extends Specification { - - def "test is Valid Full Identifier"() { - expect: - isValidFullIdentifier(valid) - where: - valid << [ - 'C', - 'Cc', - 'b.C', - 'b.Cc', - 'aAa.b.Cc', - 'a.b.Cc', - 'a.b.C_c', - 'a.b.C$c', - 'a.b.C9' - ] - } - - def "test is not Valid Full Identifier"() { - expect: - !isValidFullIdentifier(invalid) - where: - invalid << [ - '', - '5', - '7A', - '.C', - 'b.9C', - 'b..C', - ] - } -} diff --git a/jadx-core/src/test/groovy/jadx/tests/TestSignatureParser.groovy b/jadx-core/src/test/groovy/jadx/tests/TestSignatureParser.groovy deleted file mode 100644 index 02f11fa61..000000000 --- a/jadx-core/src/test/groovy/jadx/tests/TestSignatureParser.groovy +++ /dev/null @@ -1,107 +0,0 @@ -package jadx.tests - -import jadx.core.dex.instructions.args.ArgType -import jadx.core.dex.nodes.parser.SignatureParser -import spock.lang.Specification - -import static jadx.core.dex.instructions.args.ArgType.* - -class TestSignatureParser extends Specification { - def "simple types"() { - expect: - new SignatureParser(str).consumeType() == result - - where: - str | result - "" | null - "I" | INT - "[I" | array(INT) - "Ljava/lang/Object;" | OBJECT - "[Ljava/lang/Object;" | array(OBJECT) - "[[I" | array(array(INT)) - } - - def "generics"() { - expect: - new SignatureParser(str).consumeType() == result - - where: - str | result - "TD;" | genericType("D") - "La;" | generic("La;", genericType("V"), object("b")) - "La;>;" | generic("La;", generic("Lb;", object("Lc;"))) - "La/b/C;>;" | generic("La/b/C;", generic("Ld/E;", object("Lf/G;"))) - "La.c;" | genericInner(generic("La;", genericType("D")), "c", null) - "La.c/d;" | genericInner(generic("La;", genericType("D")), "c.d", null) - "La.c;" | genericInner(generic("La;", object("Lb;")), "c", genericType("V")) - } - - def "inner generic"() { - expect: - new SignatureParser(str).consumeType().getObject() == result - - where: - str | result - "La.LinkedHashIterator;>;" | "a\$LinkedHashIterator" - } - - def "wildcards"() { - expect: - new SignatureParser("La<$s>;").consumeType() == generic("La;", r as ArgType[]) - - where: - s | r - "*" | wildcard() - "+Lb;" | wildcard(object("b"), 1) - "-Lb;" | wildcard(object("b"), -1) - "+TV;" | wildcard(genericType("V"), 1) - "-TV;" | wildcard(genericType("V"), -1) - - "**" | [wildcard(), wildcard()] - "*Lb;" | [wildcard(), object("b")] - "*TV;" | [wildcard(), genericType("V")] - "TV;*" | [genericType("V"), wildcard()] - "Lb;*" | [object("b"), wildcard()] - - "***" | [wildcard(), wildcard(), wildcard()] - "*Lb;*" | [wildcard(), object("b"), wildcard()] - } - - def "generic map"() { - expect: - new SignatureParser(str).consumeGenericMap() == result.collectEntries { [genericType(it.key), it.value] } - - where: - str | result - "" | [:] - "" | ["T": []] - "" | ["K": [], "LongType": []] - "" | ["ResultT": [object("java.lang.Exception")]] - } - - def "method args"() { - when: - def argTypes = new SignatureParser("(Ljava/util/List<*>;)V").consumeMethodArgs() - then: - argTypes.size() == 1 - argTypes.get(0) == generic("Ljava/util/List;", wildcard()) - } - - def "method args 2"() { - when: - def argTypes = new SignatureParser("(La/b/C.d/E;)V").consumeMethodArgs() - then: - argTypes.size() == 1 - def argType = argTypes.get(0) - argType.getObject().indexOf('/') == -1 - argTypes.get(0) == genericInner(generic("La/b/C;", genericType("T")), "d.E", null) - } - - def "generic map: bad signature"() { - when: - def map = new SignatureParser(" p.getFileName().toString().endsWith(".java") - && !p.getFileName().toString().endsWith(TestsTest.class.getSimpleName() + ".java")) - .forEach(p -> { - try { - - List lines = Files.readAllLines(p); - - for (String line : lines) { - if (line.contains("org.junit.Assert")) { - String className = dir.relativize(p).toString(); - className = className.substring(0, className.length() - ".java".length()); - className = className.replace(File.separatorChar, '.'); - - fail("Test class " + className + " should be migrated to JUnit 5"); - } - } - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } -} diff --git a/jadx-core/src/test/java/jadx/tests/functional/AttributeStorageTest.java b/jadx-core/src/test/java/jadx/tests/functional/AttributeStorageTest.java new file mode 100644 index 000000000..2cfe06c71 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/functional/AttributeStorageTest.java @@ -0,0 +1,84 @@ +package jadx.tests.functional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jadx.core.dex.attributes.AType; +import jadx.core.dex.attributes.AttributeStorage; +import jadx.core.dex.attributes.IAttribute; + +import static jadx.core.dex.attributes.AFlag.SYNTHETIC; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class AttributeStorageTest { + private AttributeStorage storage; + + @BeforeEach + public void setup() { + storage = new AttributeStorage(); + } + + @Test + public void testAdd() { + storage.add(SYNTHETIC); + assertThat(storage.contains(SYNTHETIC), is(true)); + } + + @Test + public void testRemove() { + storage.add(SYNTHETIC); + storage.remove(SYNTHETIC); + assertThat(storage.contains(SYNTHETIC), is(false)); + } + + public static final AType TEST = new AType<>(); + + public static class TestAttr implements IAttribute { + @Override + public AType getType() { + return TEST; + } + } + + @Test + public void testAddAttribute() { + TestAttr attr = new TestAttr(); + storage.add(attr); + + assertThat(storage.contains(TEST), is(true)); + assertThat(storage.get(TEST), is(attr)); + } + + @Test + public void testRemoveAttribute() { + TestAttr attr = new TestAttr(); + storage.add(attr); + storage.remove(attr); + + assertThat(storage.contains(TEST), is(false)); + assertThat(storage.get(TEST), nullValue()); + } + + @Test + public void testRemoveOtherAttribute() { + TestAttr attr = new TestAttr(); + storage.add(attr); + storage.remove(new TestAttr()); + + assertThat(storage.contains(TEST), is(true)); + assertThat(storage.get(TEST), is(attr)); + } + + @Test + public void clear() { + storage.add(SYNTHETIC); + storage.add(new TestAttr()); + storage.clear(); + + assertThat(storage.contains(SYNTHETIC), is(false)); + assertThat(storage.contains(TEST), is(false)); + assertThat(storage.get(TEST), nullValue()); + } +} diff --git a/jadx-core/src/test/java/jadx/tests/functional/NameMapperTest.java b/jadx-core/src/test/java/jadx/tests/functional/NameMapperTest.java new file mode 100644 index 000000000..58f4b6968 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/functional/NameMapperTest.java @@ -0,0 +1,44 @@ +package jadx.tests.functional; + +import org.junit.jupiter.api.Test; + +import jadx.core.deobf.NameMapper; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class NameMapperTest { + + @Test + public void testValidFullIdentifiers() { + String[] validNames = { + "C", + "Cc", + "b.C", + "b.Cc", + "aAa.b.Cc", + "a.b.Cc", + "a.b.C_c", + "a.b.C$c", + "a.b.C9" + }; + for (String validName : validNames) { + assertThat(NameMapper.isValidFullIdentifier(validName), is(true)); + } + } + + @Test + public void testInvalidFullIdentifiers() { + String[] invalidNames = { + "", + "5", + "7A", + ".C", + "b.9C", + "b..C", + }; + for (String invalidName : invalidNames) { + assertThat(NameMapper.isValidFullIdentifier(invalidName), is(false)); + } + } +} diff --git a/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java b/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java new file mode 100644 index 000000000..34d1c1271 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java @@ -0,0 +1,128 @@ +package jadx.tests.functional; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.nodes.parser.SignatureParser; + +import static jadx.core.dex.instructions.args.ArgType.INT; +import static jadx.core.dex.instructions.args.ArgType.OBJECT; +import static jadx.core.dex.instructions.args.ArgType.array; +import static jadx.core.dex.instructions.args.ArgType.generic; +import static jadx.core.dex.instructions.args.ArgType.genericInner; +import static jadx.core.dex.instructions.args.ArgType.genericType; +import static jadx.core.dex.instructions.args.ArgType.object; +import static jadx.core.dex.instructions.args.ArgType.wildcard; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anEmptyMap; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; + +class SignatureParserTest { + + @Test + public void testSimpleTypes() { + checkType("", null); + checkType("I", INT); + checkType("[I", array(INT)); + checkType("Ljava/lang/Object;", OBJECT); + checkType("[Ljava/lang/Object;", array(OBJECT)); + checkType("[[I", array(array(INT))); + } + + private static void checkType(String str, ArgType type) { + assertThat(new SignatureParser(str).consumeType(), is(type)); + } + + @Test + public void testGenerics() { + checkType("TD;", genericType("D")); + checkType("La;", generic("La;", new ArgType[]{genericType("V"), object("b")})); + checkType("La;>;", generic("La;", new ArgType[]{generic("Lb;", new ArgType[]{object("Lc;")})})); + checkType("La/b/C;>;", generic("La/b/C;", new ArgType[]{generic("Ld/E;", new ArgType[]{object("Lf/G;")})})); + checkType("La.c;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c", null)); + checkType("La.c/d;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c.d", null)); + checkType("La.c;", genericInner(generic("La;", new ArgType[]{object("Lb;")}), "c", new ArgType[]{genericType("V")})); + } + + @Test + public void testInnerGeneric() { + String signature = "La.LinkedHashIterator;>;"; + String objectStr = new SignatureParser(signature).consumeType().getObject(); + assertThat(objectStr, is("a$LinkedHashIterator")); + } + + @Test + public void testWildcards() { + checkWildcards("*", wildcard()); + checkWildcards("+Lb;", wildcard(object("b"), 1)); + checkWildcards("-Lb;", wildcard(object("b"), -1)); + checkWildcards("+TV;", wildcard(genericType("V"), 1)); + checkWildcards("-TV;", wildcard(genericType("V"), -1)); + + checkWildcards("**", wildcard(), wildcard()); + checkWildcards("*Lb;", wildcard(), object("b")); + checkWildcards("*TV;", wildcard(), genericType("V")); + checkWildcards("TV;*", genericType("V"), wildcard()); + checkWildcards("Lb;*", object("b"), wildcard()); + + checkWildcards("***", wildcard(), wildcard(), wildcard()); + checkWildcards("*Lb;*", wildcard(), object("b"), wildcard()); + } + + private static void checkWildcards(String w, ArgType... types) { + ArgType parsedType = new SignatureParser("La<" + w + ">;").consumeType(); + ArgType expectedType = generic("La;", types); + assertThat(parsedType, is(expectedType)); + } + + @Test + public void testGenericMap() { + checkGenerics(""); + checkGenerics("", "T", emptyList()); + checkGenerics("", "K", emptyList(), "LongType", emptyList()); + checkGenerics("", "ResultT", singletonList(object("java.lang.Exception"))); + } + + @SuppressWarnings("unchecked") + private static void checkGenerics(String g, Object... objs) { + Map> map = new SignatureParser(g).consumeGenericMap(); + Map> expectedMap = new LinkedHashMap<>(); + for (int i = 0; i < objs.length; i += 2) { + ArgType generic = genericType((String) objs[i]); + List list = (List) objs[i + 1]; + expectedMap.put(generic, list); + } + assertThat(map, is(expectedMap)); + } + + @Test + public void testMethodArgs() { + List argTypes = new SignatureParser("(Ljava/util/List<*>;)V").consumeMethodArgs(); + + assertThat(argTypes, hasSize(1)); + assertThat(argTypes.get(0), is(generic("Ljava/util/List;", new ArgType[]{wildcard()}))); + } + + @Test + public void testMethodArgs2() { + List argTypes = new SignatureParser("(La/b/C.d/E;)V").consumeMethodArgs(); + + assertThat(argTypes, hasSize(1)); + ArgType argType = argTypes.get(0); + assertThat(argType.getObject().indexOf('/'), is(-1)); + assertThat(argType, is(genericInner(generic("La/b/C;", new ArgType[]{genericType("T")}), "d.E", null))); + } + + @Test + public void testBadGenericMap() { + Map> map = new SignatureParser(" expectedStringRegList = Arrays.stream(result).map(StringRef::fromStr).collect(Collectors.toList()); + assertThat(StringRef.split(str, splitBy), is(expectedStringRegList)); + + // compare with original split + assertThat(str.split(splitBy), is(result)); + } +}