Back to Repositories

Testing CLI Argument Processing Implementation in skylot/jadx

This test suite validates the command-line argument processing functionality in the JADX decompiler. It ensures proper handling of boolean flags, option overrides, and plugin configuration parameters through comprehensive unit testing.

Test Coverage Overview

The test suite provides thorough coverage of CLI argument processing in JADX.

Key areas tested include:
  • Boolean flag inversions (–no-* options)
  • Unicode escape handling
  • Source code generation options
  • Plugin option overrides and merging
  • Default value handling

Implementation Analysis

The testing approach utilizes JUnit Jupiter for structured unit testing with AssertJ assertions for enhanced verification capabilities.

Notable patterns include:
  • Helper methods for argument parsing and validation
  • Systematic option override testing
  • Map-based plugin option verification
  • Logging integration for debugging support

Technical Details

Testing infrastructure includes:
  • JUnit Jupiter test framework
  • SLF4J logging framework
  • AssertJ assertion library
  • Custom utility methods for map operations
  • JadxCLIArgs class for argument processing

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through methodical organization and thorough validation.

Key practices include:
  • Isolated test cases for each feature
  • Comprehensive edge case coverage
  • Clear test method naming
  • Reusable test utilities
  • Proper assertion usage

skylot/jadx

jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java

            
package jadx.cli;

import java.util.Collections;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static jadx.core.utils.Utils.newConstStringMap;
import static org.assertj.core.api.Assertions.assertThat;

public class JadxCLIArgsTest {

	private static final Logger LOG = LoggerFactory.getLogger(JadxCLIArgsTest.class);

	@Test
	public void testInvertedBooleanOption() {
		assertThat(parse("--no-replace-consts").isReplaceConsts()).isFalse();
		assertThat(parse("").isReplaceConsts()).isTrue();
	}

	@Test
	public void testEscapeUnicodeOption() {
		assertThat(parse("--escape-unicode").isEscapeUnicode()).isTrue();
		assertThat(parse("").isEscapeUnicode()).isFalse();
	}

	@Test
	public void testSrcOption() {
		assertThat(parse("--no-src").isSkipSources()).isTrue();
		assertThat(parse("-s").isSkipSources()).isTrue();
		assertThat(parse("").isSkipSources()).isFalse();
	}

	@Test
	public void testOptionsOverride() {
		assertThat(override(new JadxCLIArgs(), "--no-imports").isUseImports()).isFalse();
		assertThat(override(new JadxCLIArgs(), "--no-debug-info").isDebugInfo()).isFalse();
		assertThat(override(new JadxCLIArgs(), "").isUseImports()).isTrue();

		JadxCLIArgs args = new JadxCLIArgs();
		args.useImports = false;
		assertThat(override(args, "--no-imports").isUseImports()).isFalse();
		args.debugInfo = false;
		assertThat(override(args, "--no-debug-info").isDebugInfo()).isFalse();

		args = new JadxCLIArgs();
		args.useImports = false;
		assertThat(override(args, "").isUseImports()).isFalse();
	}

	@Test
	public void testPluginOptionsOverride() {
		// add key to empty base map
		checkPluginOptionsMerge(
				Collections.emptyMap(),
				"-Poption=otherValue",
				newConstStringMap("option", "otherValue"));

		// override one key
		checkPluginOptionsMerge(
				newConstStringMap("option", "value"),
				"-Poption=otherValue",
				newConstStringMap("option", "otherValue"));

		// merge different keys
		checkPluginOptionsMerge(
				Collections.singletonMap("option1", "value1"),
				"-Poption2=otherValue2",
				newConstStringMap("option1", "value1", "option2", "otherValue2"));

		// merge and override
		checkPluginOptionsMerge(
				newConstStringMap("option1", "value1", "option2", "value2"),
				"-Poption2=otherValue2",
				newConstStringMap("option1", "value1", "option2", "otherValue2"));
	}

	private void checkPluginOptionsMerge(Map<String, String> baseMap, String providedArgs, Map<String, String> expectedMap) {
		JadxCLIArgs args = new JadxCLIArgs();
		args.pluginOptions = baseMap;
		Map<String, String> resultMap = override(args, providedArgs).getPluginOptions();
		assertThat(resultMap).isEqualTo(expectedMap);
	}

	private JadxCLIArgs parse(String... args) {
		return parse(new JadxCLIArgs(), args);
	}

	private JadxCLIArgs parse(JadxCLIArgs jadxArgs, String... args) {
		return check(jadxArgs, jadxArgs.processArgs(args));
	}

	private JadxCLIArgs override(JadxCLIArgs jadxArgs, String... args) {
		return check(jadxArgs, jadxArgs.overrideProvided(args));
	}

	private static JadxCLIArgs check(JadxCLIArgs jadxArgs, boolean res) {
		assertThat(res).isTrue();
		LOG.info("Jadx args: {}", jadxArgs.toJadxArgs());
		return jadxArgs;
	}
}