Skip to content

⚡️ Speed up method MavenStrategy.get_build_output_dir by 52% in PR #1774 (feat/gradle-executor-from-java)#1801

Merged
HeshamHM28 merged 1 commit intofeat/gradle-executor-from-javafrom
codeflash/optimize-pr1774-2026-03-09T22.13.14
Mar 9, 2026
Merged

⚡️ Speed up method MavenStrategy.get_build_output_dir by 52% in PR #1774 (feat/gradle-executor-from-java)#1801
HeshamHM28 merged 1 commit intofeat/gradle-executor-from-javafrom
codeflash/optimize-pr1774-2026-03-09T22.13.14

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Mar 9, 2026

⚡️ This pull request contains optimizations for PR #1774

If you approve this dependent PR, these changes will be merged into the original PR branch feat/gradle-executor-from-java.

This PR will be automatically closed if the original PR is merged.


📄 52% (0.52x) speedup for MavenStrategy.get_build_output_dir in codeflash/languages/java/maven_strategy.py

⏱️ Runtime : 9.70 milliseconds 6.40 milliseconds (best of 148 runs)

📝 Explanation and details

Replacing the chained / operator (build_root / test_module / "target") with build_root.joinpath(test_module, _TARGET) eliminates the intermediate Path object created after build_root / test_module, cutting per-call overhead from ~15.9 µs to ~10.4 µs in the hot path (3323 hits). The profiler shows the hot line dropped from 97.3% to 96.3% of runtime, and hoisting "target" into a module constant _TARGET avoids repeated string allocations. Runtime improved 51% (9.70 ms → 6.40 ms) with no functional regressions across all test cases.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 3275 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
from pathlib import Path  # Path is used by the function under test

# imports
import pytest  # used for our unit tests
from codeflash.languages.java.maven_strategy import \
    MavenStrategy  # real class under test

def test_get_build_output_dir_with_none_module_returns_target():
    # Create a real MavenStrategy instance (do not mock or stub)
    strategy = MavenStrategy()
    # Use a simple relative build root path for deterministic behavior
    build_root = Path("project_root")
    # When test_module is None we expect the build_root/target path
    result = strategy.get_build_output_dir(build_root, None) # 3.40μs -> 3.22μs (5.60% faster)
    assert result == build_root / "target"  # exact Path equality

def test_get_build_output_dir_with_module_appends_module_and_target():
    # Instantiate the real strategy
    strategy = MavenStrategy()
    build_root = Path("project_root")
    test_module = "moduleA"
    # Expect the test module directory followed by "target"
    result = strategy.get_build_output_dir(build_root, test_module) # 5.29μs -> 3.91μs (35.4% faster)
    assert result == build_root / "moduleA" / "target"

def test_return_type_is_path_instance():
    # Verify the return type is a pathlib.Path instance
    strategy = MavenStrategy()
    build_root = Path("src")
    result = strategy.get_build_output_dir(build_root, "mod") # 5.01μs -> 3.75μs (33.7% faster)
    assert isinstance(result, Path)

@pytest.mark.parametrize(
    "test_module, expected_suffix",
    [
        ("", "target"),             # empty string is falsy -> treated like None
        (".", "./target"),          # single dot becomes a path segment
        ("..", "../target"),        # parent directory traversal preserved
        ("a/b/c", "a/b/c/target"),  # nested module path with separators
        ("mod with spaces", "mod with spaces/target"),  # spaces preserved
        ("special-!@#$%^&*()", "special-!@#$%^&*()/target"),  # special chars preserved
    ],
)
def test_various_special_test_module_values(test_module, expected_suffix):
    # Create instance and use a relative build root to keep assertions simple
    strategy = MavenStrategy()
    build_root = Path("rootdir")
    result = strategy.get_build_output_dir(build_root, test_module) # 32.4μs -> 24.8μs (30.8% faster)
    # Build the expected Path by joining the pieces; for empty string expected is rootdir/target
    if test_module:
        expected = build_root / Path(test_module) / "target"
    else:
        expected = build_root / "target"
    assert result == expected

def test_absolute_test_module_overrides_build_root():
    # If test_module is an absolute path string, Path behavior makes it replace the left side.
    strategy = MavenStrategy()
    build_root = Path("ignored_root")
    # Use an absolute POSIX-style path. On all platforms Path will treat '/abs/path' as absolute.
    test_module = "/abs/path"
    result = strategy.get_build_output_dir(build_root, test_module) # 8.02μs -> 5.89μs (36.2% faster)
    # Expect the absolute module path with "target" appended (build_root ignored)
    assert result == Path("/abs/path") / "target"

def test_many_module_names_generate_expected_paths():
    strategy = MavenStrategy()
    build_root = Path("bigroot")
    # Construct 1000 deterministic module names: module_0 .. module_999
    modules = [f"module_{i}" for i in range(1000)]
    for i, mod in enumerate(modules):
        # For each module check the returned path matches the expected composition
        result = strategy.get_build_output_dir(build_root, mod) # 2.90ms -> 1.87ms (55.4% faster)
        expected = build_root / mod / "target"
        assert result == expected, f"Mismatch at index {i}: {mod}"

def test_many_nested_module_names_generate_expected_paths():
    strategy = MavenStrategy()
    build_root = Path("bigroot")
    # Construct 1000 deterministic nested module names like pkg/subpkg_i
    modules = [f"pkg/subpkg_{i}" for i in range(1000)]
    for i, mod in enumerate(modules):
        result = strategy.get_build_output_dir(build_root, mod) # 3.22ms -> 2.20ms (46.4% faster)
        expected = build_root / Path(mod) / "target"
        assert result == expected, f"Nested mismatch at index {i}: {mod}"
from pathlib import Path

# imports
import pytest
from codeflash.languages.java.maven_strategy import MavenStrategy

class TestMavenStrategyGetBuildOutputDir:
    """Comprehensive unit tests for MavenStrategy.get_build_output_dir method."""

    @pytest.fixture
    def maven_strategy(self):
        """Create a real MavenStrategy instance for testing."""
        return MavenStrategy()

    # ============================================================================
    # BASIC TESTS - Verify fundamental functionality under normal conditions
    # ============================================================================

    def test_returns_target_dir_when_no_test_module(self, maven_strategy):
        """Test that target directory is returned when test_module is None."""
        # Arrange: Create a simple build root path
        build_root = Path("/home/user/project")
        test_module = None
        
        # Act: Call get_build_output_dir with None test_module
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 4.03μs -> 3.62μs (11.4% faster)
        
        # Assert: Result should be build_root / "target"
        assert result == Path("/home/user/project/target")
        assert result.name == "target"

    def test_returns_module_target_dir_when_test_module_provided(self, maven_strategy):
        """Test that module-specific target directory is returned when test_module is provided."""
        # Arrange: Create build root and test module name
        build_root = Path("/home/user/project")
        test_module = "my-module"
        
        # Act: Call get_build_output_dir with test_module
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.90μs -> 4.45μs (32.6% faster)
        
        # Assert: Result should be build_root / test_module / "target"
        assert result == Path("/home/user/project/my-module/target")
        assert result.name == "target"

    def test_returns_path_object(self, maven_strategy):
        """Test that the return type is always a Path object."""
        # Arrange
        build_root = Path("/home/user/project")
        
        # Act: Call with None test_module
        result1 = maven_strategy.get_build_output_dir(build_root, None) # 3.72μs -> 3.57μs (4.21% faster)
        
        # Assert: Result should be Path instance
        assert isinstance(result1, Path)
        
        # Act: Call with test_module
        result2 = maven_strategy.get_build_output_dir(build_root, "module") # 3.98μs -> 3.06μs (30.1% faster)
        
        # Assert: Result should be Path instance
        assert isinstance(result2, Path)

    def test_preserves_build_root_path(self, maven_strategy):
        """Test that the build_root path is preserved in the output."""
        # Arrange
        build_root = Path("/var/maven/projects/sample")
        
        # Act: Call without test_module
        result = maven_strategy.get_build_output_dir(build_root, None) # 3.51μs -> 3.35μs (4.75% faster)
        
        # Assert: build_root should be in the result path
        assert str(build_root) in str(result)
        assert result.parent == build_root

    def test_handles_nested_build_root(self, maven_strategy):
        """Test with deeply nested build_root path."""
        # Arrange
        build_root = Path("/home/user/workspace/projects/java/maven/app")
        
        # Act: Call without test_module
        result = maven_strategy.get_build_output_dir(build_root, None) # 3.48μs -> 3.32μs (4.79% faster)
        
        # Assert: Result should maintain the nested structure
        assert result == build_root / "target"
        assert str(result).count("/") == str(build_root).count("/") + 1

    # ============================================================================
    # EDGE TESTS - Evaluate behavior under extreme or unusual conditions
    # ============================================================================

    def test_with_empty_string_test_module(self, maven_strategy):
        """Test behavior when test_module is an empty string."""
        # Arrange: Empty string should be treated as a falsy value or as a module name
        build_root = Path("/home/user/project")
        test_module = ""
        
        # Act: Call with empty string
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.58μs -> 3.33μs (7.55% faster)
        
        # Assert: Empty string is falsy, so should return build_root / "target"
        # (Python treats empty string as falsy in if conditions)
        assert result == Path("/home/user/project/target")

    def test_with_dot_test_module(self, maven_strategy):
        """Test with single dot as test_module (current directory reference)."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "."
        
        # Act: Call with dot as module name
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.54μs -> 3.99μs (39.0% faster)
        
        # Assert: Should return build_root / "." / "target"
        assert result == Path("/home/user/project/./target")

    def test_with_parent_directory_reference_in_test_module(self, maven_strategy):
        """Test with '..' in test_module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "module/.."
        
        # Act: Call with parent directory reference
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 7.14μs -> 5.51μs (29.6% faster)
        
        # Assert: Path should contain the parent reference
        assert result == Path("/home/user/project/module/../target")

    def test_with_relative_build_root(self, maven_strategy):
        """Test with relative path as build_root."""
        # Arrange
        build_root = Path("./project")
        test_module = None
        
        # Act: Call with relative path
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.62μs -> 3.75μs (3.47% slower)
        
        # Assert: Should return relative path with target appended
        assert result == Path("./project/target")
        assert result.parts == (".", "project", "target")

    def test_with_relative_test_module(self, maven_strategy):
        """Test with relative path as test_module."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "./submodule"
        
        # Act: Call with relative module path
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 6.59μs -> 5.19μs (27.0% faster)
        
        # Assert: Should handle relative module reference
        assert result == Path("/home/user/project/./submodule/target")

    def test_with_hyphenated_module_name(self, maven_strategy):
        """Test with hyphenated module name (common in Maven)."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "my-app-module"
        
        # Act: Call with hyphenated module
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.71μs -> 4.15μs (37.7% faster)
        
        # Assert: Should preserve hyphenated name
        assert result == Path("/home/user/project/my-app-module/target")
        assert "my-app-module" in str(result)

    def test_with_underscore_module_name(self, maven_strategy):
        """Test with underscored module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "my_module_name"
        
        # Act: Call with underscored module
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.53μs -> 4.08μs (35.7% faster)
        
        # Assert: Should preserve underscored name
        assert result == Path("/home/user/project/my_module_name/target")

    def test_with_numeric_module_name(self, maven_strategy):
        """Test with numeric module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "module123"
        
        # Act: Call with numeric module name
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.51μs -> 4.08μs (35.1% faster)
        
        # Assert: Should handle numeric names
        assert result == Path("/home/user/project/module123/target")

    def test_with_uppercase_module_name(self, maven_strategy):
        """Test with uppercase module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "MyModule"
        
        # Act: Call with uppercase module name
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.42μs -> 4.05μs (33.9% faster)
        
        # Assert: Should preserve case
        assert result == Path("/home/user/project/MyModule/target")

    def test_with_root_path_as_build_root(self, maven_strategy):
        """Test with root path '/' as build_root."""
        # Arrange
        build_root = Path("/")
        test_module = None
        
        # Act: Call with root path
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.44μs -> 3.46μs (0.607% slower)
        
        # Assert: Should return /target
        assert result == Path("/target")

    def test_with_single_component_build_root(self, maven_strategy):
        """Test with single-component path as build_root."""
        # Arrange
        build_root = Path("project")
        test_module = None
        
        # Act: Call with single component
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.24μs -> 3.15μs (2.86% faster)
        
        # Assert: Should return project/target
        assert result == Path("project/target")

    def test_path_immutability(self, maven_strategy):
        """Test that original paths are not modified."""
        # Arrange
        build_root = Path("/home/user/project")
        original_build_root = Path(str(build_root))
        test_module = "module"
        
        # Act: Call get_build_output_dir
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.38μs -> 3.99μs (34.9% faster)
        
        # Assert: Original build_root should not be modified
        assert build_root == original_build_root
        assert result != build_root

    def test_returns_different_paths_for_different_modules(self, maven_strategy):
        """Test that different modules return different paths."""
        # Arrange
        build_root = Path("/home/user/project")
        module1 = "module-a"
        module2 = "module-b"
        
        # Act: Call with different modules
        result1 = maven_strategy.get_build_output_dir(build_root, module1) # 5.51μs -> 4.03μs (36.8% faster)
        result2 = maven_strategy.get_build_output_dir(build_root, module2)
        
        # Assert: Results should be different
        assert result1 != result2 # 3.51μs -> 2.67μs (31.1% faster)
        assert "module-a" in str(result1)
        assert "module-b" in str(result2)

    def test_with_spaces_in_module_name(self, maven_strategy):
        """Test with spaces in module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "my module"
        
        # Act: Call with spaces in module name
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.58μs -> 4.01μs (39.3% faster)
        
        # Assert: Should preserve spaces
        assert result == Path("/home/user/project/my module/target")

    def test_with_special_characters_in_module_name(self, maven_strategy):
        """Test with special characters in module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "module-name_v2.0"
        
        # Act: Call with special characters
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.47μs -> 4.02μs (36.1% faster)
        
        # Assert: Should preserve special characters
        assert result == Path("/home/user/project/module-name_v2.0/target")

    def test_none_test_module_explicitly(self, maven_strategy):
        """Test explicit None value for test_module."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = None
        
        # Act: Call with explicit None
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.49μs -> 3.38μs (3.29% faster)
        
        # Assert: Should not include module in path
        assert result == Path("/home/user/project/target")
        assert result.parts[-1] == "target"
        assert len(result.parts) == len(build_root.parts) + 1

    def test_with_very_long_module_name(self, maven_strategy):
        """Test with very long module name."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "a" * 255  # Very long but valid filename
        
        # Act: Call with very long module name
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 5.78μs -> 4.16μs (39.0% faster)
        
        # Assert: Should handle long names
        assert test_module in str(result)
        assert result.parent.name == test_module

    # ============================================================================
    # LARGE-SCALE TESTS - Assess performance and scalability
    # ============================================================================

    def test_with_many_build_root_components(self, maven_strategy):
        """Test with deeply nested build_root (many path components)."""
        # Arrange: Create a deeply nested path with 50 components
        path_parts = ["home", "user"] + ["level" + str(i) for i in range(50)]
        build_root = Path(*path_parts)
        test_module = None
        
        # Act: Call with deeply nested path
        result = maven_strategy.get_build_output_dir(build_root, test_module) # 3.48μs -> 3.29μs (5.78% faster)
        
        # Assert: Should handle many components
        assert "target" in str(result)
        assert result.name == "target"
        assert len(result.parts) == len(build_root.parts) + 1

    def test_performance_with_repeated_calls(self, maven_strategy):
        """Test performance with 1000 repeated calls."""
        # Arrange
        build_root = Path("/home/user/project")
        test_modules = ["module" + str(i % 10) for i in range(1000)]
        
        # Act & Assert: All calls should succeed and return correct paths
        results = []
        for test_module in test_modules:
            result = maven_strategy.get_build_output_dir(build_root, test_module) # 2.83ms -> 1.81ms (55.7% faster)
            results.append(result)
            # Assert each result contains expected components
            assert "target" in str(result)
            assert test_module in str(result)
        
        # Assert: All results should be Path instances
        assert len(results) == 1000
        assert all(isinstance(r, Path) for r in results)

    def test_with_varying_module_names_at_scale(self, maven_strategy):
        """Test with 100 different module names to ensure consistency."""
        # Arrange
        build_root = Path("/home/user/project")
        
        # Act & Assert: Generate 100 different module names
        for i in range(100):
            test_module = f"module-{i}-submodule-{i*2}"
            result = maven_strategy.get_build_output_dir(build_root, test_module) # 299μs -> 197μs (51.7% faster)
            
            # Assert: Each should produce correct path
            assert result == build_root / test_module / "target"
            assert result.name == "target"

    def test_consistency_across_multiple_calls_same_inputs(self, maven_strategy):
        """Test that multiple calls with same inputs produce same output."""
        # Arrange
        build_root = Path("/home/user/project")
        test_module = "test-module"
        
        # Act: Call 100 times with same inputs
        results = [
            maven_strategy.get_build_output_dir(build_root, test_module)
            for _ in range(100)
        ]
        
        # Assert: All results should be identical
        first_result = results[0]
        assert all(result == first_result for result in results)
        assert all(isinstance(result, Path) for result in results)

    def test_with_all_none_calls(self, maven_strategy):
        """Test 100 calls with None test_module."""
        # Arrange
        build_root = Path("/home/user/project")
        
        # Act: Call 100 times with None
        results = [
            maven_strategy.get_build_output_dir(build_root, None)
            for _ in range(100)
        ]
        
        # Assert: All should be identical and correct
        expected = Path("/home/user/project/target")
        assert all(result == expected for result in results)

    def test_different_build_roots_consistency(self, maven_strategy):
        """Test with 100 different build roots."""
        # Arrange: Create 100 different build roots
        test_module = "my-module"
        
        # Act & Assert: Each build root should produce consistent results
        for i in range(100):
            build_root = Path(f"/base/path{i}/project")
            result = maven_strategy.get_build_output_dir(build_root, test_module) # 281μs -> 185μs (51.9% faster)
            
            # Assert: Correct structure
            assert result == build_root / test_module / "target"
            assert result.name == "target"
            assert test_module in result.parts

To edit these changes git checkout codeflash/optimize-pr1774-2026-03-09T22.13.14 and push.

Codeflash Static Badge

Replacing the chained `/` operator (`build_root / test_module / "target"`) with `build_root.joinpath(test_module, _TARGET)` eliminates the intermediate Path object created after `build_root / test_module`, cutting per-call overhead from ~15.9 µs to ~10.4 µs in the hot path (3323 hits). The profiler shows the hot line dropped from 97.3% to 96.3% of runtime, and hoisting `"target"` into a module constant `_TARGET` avoids repeated string allocations. Runtime improved 51% (9.70 ms → 6.40 ms) with no functional regressions across all test cases.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Mar 9, 2026
@claude
Copy link
Contributor

claude bot commented Mar 9, 2026

Claude finished @codeflash-ai[bot]'s task in 1m 50s —— View job


PR Review Summary

  • Triage PR scope
  • Run lint and type checks
  • Resolve stale review threads
  • Review code changes
  • Check for duplicate code
  • Analyze test coverage
  • Post summary comment
  • Check optimization PRs

Prek Checks

All checks passed (ruff lint, ruff format). mypy reports no issues.

Code Review

One naming convention violation:

codeflash/languages/java/maven_strategy.py:25 — The constant _TARGET uses a leading underscore, which violates the project's naming convention: "NEVER use leading underscores — Python has no true private functions, use public names." It should be named TARGET. Fix this →

The optimization itself is functionally correct. Using joinpath(test_module, _TARGET) instead of chained / operators (build_root / test_module / "target") avoids creating an intermediate Path object, which is a legitimate micro-optimization. The 3275 regression tests pass with 100% coverage, confirming correctness.

Duplicate Detection

No duplicates detected. The only other implementation of get_build_output_dir is the abstract base in build_tool_strategy.py:61, which is the interface this method implements.

Test Coverage

3275 generated regression tests pass with 100% coverage as reported by the optimization tool. No existing unit tests were found for this method.


Last updated: 2026-03-09T22:14Z

@HeshamHM28 HeshamHM28 merged commit 6700ce8 into feat/gradle-executor-from-java Mar 9, 2026
27 of 29 checks passed
@HeshamHM28 HeshamHM28 deleted the codeflash/optimize-pr1774-2026-03-09T22.13.14 branch March 9, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant