Skip to content

4. Understanding Tests System

EpicPlayerA10 edited this page Sep 5, 2025 · 4 revisions

🧪 How do these tests work?

The deobfuscator has a very clever test system. It works as follows:

  1. The registered samples are transformed using corresponding transformers.
  2. The output gets decompiled using Vineflower (FernFlower fork).
  3. The decompiled code is compared against the expected output.

The testing framework uses a fluent API pattern where each test is configured with:

  • Name: Human-readable test description
  • Transformers: List of transformer classes to apply
  • Input: Type and location of test input (Java source, compiled class, or JAR)
  • Output: Single class or multiple classes expected

📁 Test Structure

The test suite is organized in several key directories:

  • /testData/src/java/ - Contains Java source files that serve as test inputs for basic transformer functionality. These are simple, clean Java classes that get compiled and then processed by transformers.
  • /testData/compiled/custom-classes/ - Contains pre-obfuscated .class files from various real-world obfuscators, organized by obfuscator type in subdirectories.
  • /testData/compiled/custom-jars/ - Contains complete obfuscated JAR files for testing full application deobfuscation.
  • /testData/results/ (Expected Outputs) - Contains expected decompiled output files that the test framework compares against actual transformer results.

▶️ How to run tests?

Run command mvn test in the root directory of the project. The test framework will:

  1. Execute all registered tests in parallel where possible
  2. Apply specified transformers to each test input
  3. Decompile results using Vineflower
  4. Compare against expected outputs
  5. Report any differences or failures

⚙️ Test Registration System

All tests are registered in TestDeobfuscation.java using a fluent API:

test("Test name")
    .transformers(ExampleTransformer::new, AnotherTransformer::new)
    .inputClass(InputType.JAVA_CODE, "TestClass.class")
    .register();

Input Methods:

  • inputClass(InputType, path) - For single class files
  • inputClassesDir(InputType, path) - For directories containing multiple classes
  • inputJar(path) - For JAR files (automatically uses InputType.CUSTOM_JAR)

Input Types:

  • JAVA_CODE: Source files from testData/src/java/
  • CUSTOM_CLASS: Compiled classes from testData/compiled/custom-classes/
  • CUSTOM_JAR: JAR files from testData/compiled/custom-jars/

✏️ Creating Your Own Tests

  1. For simple cases: Write Java source in testData/src/java/src/main/java/
  2. For real obfuscation: Place .class files in appropriate subdirectory of testData/compiled/custom-classes/
  3. For complete applications: Place .jar files in testData/compiled/custom-jars/
  4. Register the test in TestDeobfuscation.java with appropriate transformers
  5. Run once to generate expected output, then verify it's correct
  6. Future runs will compare against this baseline

The testing system ensures that transformers maintain their effectiveness as the codebase evolves and helps identify regressions when modifying existing functionality.

Clone this wiki locally