mirror of
https://github.com/codeflash-ai/codeflash.git
synced 2026-05-04 18:25:17 +00:00
fix: resolve remaining test failures after main sync
- Fix min/max_outer_loops → pytest_min/max_loops in Java test_run_and_parse - Update test_replacement.py for new replace_function_definitions_for_language API - Update JavaSupport.discover_functions signature to match protocol - Migrate _get_java_sources_root/_fix_java_test_paths to JavaFunctionOptimizer - Fix test_java_tests_project_rootdir to use set_current_language
This commit is contained in:
parent
e7687f2448
commit
f7fd593de3
7 changed files with 249 additions and 83 deletions
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
|
@ -141,6 +142,155 @@ class JavaFunctionOptimizer(FunctionOptimizer):
|
|||
preexisting_objects=set(),
|
||||
)
|
||||
|
||||
def _get_java_sources_root(self) -> Path:
|
||||
"""Get the Java sources root directory for test files.
|
||||
|
||||
For Java projects, tests_root might include the package path
|
||||
(e.g., test/src/com/aerospike/test). We need to find the base directory
|
||||
that should contain the package directories, not the tests_root itself.
|
||||
|
||||
This method looks for standard Java package prefixes (com, org, net, io, edu, gov)
|
||||
in the tests_root path and returns everything before that prefix.
|
||||
|
||||
Returns:
|
||||
Path to the Java sources root directory.
|
||||
|
||||
"""
|
||||
tests_root = self.test_cfg.tests_root
|
||||
parts = tests_root.parts
|
||||
|
||||
if tests_root.name == "src":
|
||||
return tests_root
|
||||
|
||||
if len(parts) >= 3 and parts[-3:] == ("src", "test", "java"):
|
||||
return tests_root
|
||||
|
||||
src_subdir = tests_root / "src"
|
||||
if src_subdir.exists() and src_subdir.is_dir():
|
||||
return src_subdir
|
||||
|
||||
maven_test_dir = tests_root / "src" / "test" / "java"
|
||||
if maven_test_dir.exists() and maven_test_dir.is_dir():
|
||||
return maven_test_dir
|
||||
|
||||
standard_package_prefixes = ("com", "org", "net", "io", "edu", "gov")
|
||||
for i, part in enumerate(parts):
|
||||
if part in standard_package_prefixes:
|
||||
if i > 0:
|
||||
return Path(*parts[:i])
|
||||
|
||||
for i, part in enumerate(parts):
|
||||
if part == "java" and i > 0:
|
||||
return Path(*parts[: i + 1])
|
||||
|
||||
return tests_root
|
||||
|
||||
def _fix_java_test_paths(
|
||||
self, behavior_source: str, perf_source: str, used_paths: set[Path]
|
||||
) -> tuple[Path, Path, str, str]:
|
||||
"""Fix Java test file paths to match package structure.
|
||||
|
||||
Java requires test files to be in directories matching their package.
|
||||
This method extracts the package and class from the generated tests
|
||||
and returns correct paths. If the path would conflict with an already
|
||||
used path, it renames the class by adding an index suffix.
|
||||
|
||||
Args:
|
||||
behavior_source: Source code of the behavior test.
|
||||
perf_source: Source code of the performance test.
|
||||
used_paths: Set of already used behavior file paths.
|
||||
|
||||
Returns:
|
||||
Tuple of (behavior_path, perf_path, modified_behavior_source, modified_perf_source)
|
||||
with correct package structure and unique class names.
|
||||
|
||||
"""
|
||||
package_match = re.search(r"^\s*package\s+([\w.]+)\s*;", behavior_source, re.MULTILINE)
|
||||
package_name = package_match.group(1) if package_match else ""
|
||||
|
||||
# JPMS: If a test module-info.java exists, remap the package to the
|
||||
# test module namespace to avoid split-package errors.
|
||||
test_dir = self._get_java_sources_root()
|
||||
test_module_info = test_dir / "module-info.java"
|
||||
if package_name and test_module_info.exists():
|
||||
mi_content = test_module_info.read_text(encoding="utf-8")
|
||||
mi_match = re.search(r"module\s+([\w.]+)", mi_content)
|
||||
if mi_match:
|
||||
test_module_name = mi_match.group(1)
|
||||
main_dir = test_dir.parent.parent / "main" / "java"
|
||||
main_module_info = main_dir / "module-info.java"
|
||||
if main_module_info.exists():
|
||||
main_content = main_module_info.read_text(encoding="utf-8")
|
||||
main_match = re.search(r"module\s+([\w.]+)", main_content)
|
||||
if main_match:
|
||||
main_module_name = main_match.group(1)
|
||||
if package_name.startswith(main_module_name):
|
||||
suffix = package_name[len(main_module_name) :]
|
||||
new_package = test_module_name + suffix
|
||||
old_decl = f"package {package_name};"
|
||||
new_decl = f"package {new_package};"
|
||||
behavior_source = behavior_source.replace(old_decl, new_decl, 1)
|
||||
perf_source = perf_source.replace(old_decl, new_decl, 1)
|
||||
package_name = new_package
|
||||
logger.debug(f"[JPMS] Remapped package: {old_decl} -> {new_decl}")
|
||||
|
||||
class_match = re.search(r"^(?:public\s+)?class\s+(\w+)", behavior_source, re.MULTILINE)
|
||||
behavior_class = class_match.group(1) if class_match else "GeneratedTest"
|
||||
|
||||
perf_class_match = re.search(r"^(?:public\s+)?class\s+(\w+)", perf_source, re.MULTILINE)
|
||||
perf_class = perf_class_match.group(1) if perf_class_match else "GeneratedPerfTest"
|
||||
|
||||
test_dir = self._get_java_sources_root()
|
||||
|
||||
if package_name:
|
||||
package_path = package_name.replace(".", "/")
|
||||
behavior_path = test_dir / package_path / f"{behavior_class}.java"
|
||||
perf_path = test_dir / package_path / f"{perf_class}.java"
|
||||
else:
|
||||
package_path = ""
|
||||
behavior_path = test_dir / f"{behavior_class}.java"
|
||||
perf_path = test_dir / f"{perf_class}.java"
|
||||
|
||||
modified_behavior_source = behavior_source
|
||||
modified_perf_source = perf_source
|
||||
if behavior_path in used_paths:
|
||||
index = 2
|
||||
while True:
|
||||
new_behavior_class = f"{behavior_class}_{index}"
|
||||
new_perf_class = f"{perf_class}_{index}"
|
||||
if package_path:
|
||||
new_behavior_path = test_dir / package_path / f"{new_behavior_class}.java"
|
||||
new_perf_path = test_dir / package_path / f"{new_perf_class}.java"
|
||||
else:
|
||||
new_behavior_path = test_dir / f"{new_behavior_class}.java"
|
||||
new_perf_path = test_dir / f"{new_perf_class}.java"
|
||||
if new_behavior_path not in used_paths:
|
||||
behavior_path = new_behavior_path
|
||||
perf_path = new_perf_path
|
||||
modified_behavior_source = re.sub(
|
||||
rf"^((?:public\s+)?class\s+){re.escape(behavior_class)}(\b)",
|
||||
rf"\g<1>{new_behavior_class}\g<2>",
|
||||
behavior_source,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
modified_perf_source = re.sub(
|
||||
rf"^((?:public\s+)?class\s+){re.escape(perf_class)}(\b)",
|
||||
rf"\g<1>{new_perf_class}\g<2>",
|
||||
perf_source,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
logger.debug(f"[JAVA] Renamed duplicate test class from {behavior_class} to {new_behavior_class}")
|
||||
break
|
||||
index += 1
|
||||
|
||||
behavior_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
perf_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
logger.debug(f"[JAVA] Fixed paths: behavior={behavior_path}, perf={perf_path}")
|
||||
return behavior_path, perf_path, modified_behavior_source, modified_perf_source
|
||||
|
||||
def compare_candidate_results(
|
||||
self,
|
||||
baseline_results: OriginalCodeBaseline,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from codeflash.languages.java.comparator import compare_test_results as _compare
|
|||
from codeflash.languages.java.concurrency_analyzer import analyze_function_concurrency
|
||||
from codeflash.languages.java.config import detect_java_project
|
||||
from codeflash.languages.java.context import extract_code_context, find_helper_functions
|
||||
from codeflash.languages.java.discovery import discover_functions, discover_functions_from_source
|
||||
from codeflash.languages.java.discovery import discover_functions_from_source
|
||||
from codeflash.languages.java.formatter import format_java_code, normalize_java_code
|
||||
from codeflash.languages.java.instrumentation import (
|
||||
instrument_existing_test,
|
||||
|
|
@ -151,10 +151,10 @@ class JavaSupport(LanguageSupport):
|
|||
# === Discovery ===
|
||||
|
||||
def discover_functions(
|
||||
self, file_path: Path, filter_criteria: FunctionFilterCriteria | None = None
|
||||
self, source: str, file_path: Path, filter_criteria: FunctionFilterCriteria | None = None
|
||||
) -> list[FunctionToOptimize]:
|
||||
"""Find all optimizable functions in a Java file."""
|
||||
return discover_functions(file_path, filter_criteria, self._analyzer)
|
||||
"""Find all optimizable functions in Java source code."""
|
||||
return discover_functions_from_source(source, file_path, filter_criteria, self._analyzer)
|
||||
|
||||
def discover_functions_from_source(
|
||||
self, source: str, file_path: Path | None = None, filter_criteria: FunctionFilterCriteria | None = None
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch
|
|||
|
||||
from codeflash.discovery.discover_unit_tests import discover_unit_tests
|
||||
from codeflash.languages.base import Language
|
||||
from codeflash.languages.current import set_current_language
|
||||
from codeflash.languages.current import reset_current_language, set_current_language
|
||||
from codeflash.verification.verification_utils import TestConfig
|
||||
|
||||
|
||||
|
|
@ -32,15 +32,18 @@ def test_java_tests_project_rootdir_set_to_tests_root(tmp_path):
|
|||
mock_java_function.language = "java"
|
||||
file_to_funcs = {Path("dummy.java"): [mock_java_function]}
|
||||
|
||||
# Mock is_python() to return False and is_java() to return True
|
||||
# These are imported from codeflash.languages
|
||||
with patch("codeflash.languages.is_python", return_value=False), \
|
||||
patch("codeflash.languages.is_java", return_value=True), \
|
||||
patch("codeflash.discovery.discover_unit_tests.discover_tests_for_language") as mock_discover:
|
||||
mock_discover.return_value = ({}, 0, 0)
|
||||
# Set current language to Java so is_python() returns False and
|
||||
# current_language_support() returns JavaSupport with its
|
||||
# adjust_test_config_for_discovery implementation
|
||||
set_current_language(Language.JAVA)
|
||||
try:
|
||||
with patch("codeflash.discovery.discover_unit_tests.discover_tests_for_language") as mock_discover:
|
||||
mock_discover.return_value = ({}, 0, 0)
|
||||
|
||||
# Call discover_unit_tests
|
||||
discover_unit_tests(test_cfg, file_to_funcs_to_optimize=file_to_funcs)
|
||||
# Call discover_unit_tests
|
||||
discover_unit_tests(test_cfg, file_to_funcs_to_optimize=file_to_funcs)
|
||||
finally:
|
||||
reset_current_language()
|
||||
|
||||
# Verify that tests_project_rootdir was updated to tests_root
|
||||
assert test_cfg.tests_project_rootdir == tests_root, (
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
"""Tests for Java test path handling in FunctionOptimizer."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from codeflash.languages.java.test_runner import (
|
||||
_extract_source_dirs_from_pom,
|
||||
_path_to_class_name,
|
||||
)
|
||||
from codeflash.languages.java.test_runner import _extract_source_dirs_from_pom, _path_to_class_name
|
||||
|
||||
|
||||
class TestGetJavaSourcesRoot:
|
||||
|
|
@ -16,15 +11,15 @@ class TestGetJavaSourcesRoot:
|
|||
|
||||
def _create_mock_optimizer(self, tests_root: str):
|
||||
"""Create a mock FunctionOptimizer with the given tests_root."""
|
||||
from codeflash.optimization.function_optimizer import FunctionOptimizer
|
||||
from codeflash.languages.java.function_optimizer import JavaFunctionOptimizer
|
||||
|
||||
# Create a minimal mock
|
||||
mock_optimizer = MagicMock(spec=FunctionOptimizer)
|
||||
mock_optimizer = MagicMock(spec=JavaFunctionOptimizer)
|
||||
mock_optimizer.test_cfg = MagicMock()
|
||||
mock_optimizer.test_cfg.tests_root = Path(tests_root)
|
||||
|
||||
# Bind the actual method to the mock
|
||||
mock_optimizer._get_java_sources_root = lambda: FunctionOptimizer._get_java_sources_root(mock_optimizer)
|
||||
mock_optimizer._get_java_sources_root = lambda: JavaFunctionOptimizer._get_java_sources_root(mock_optimizer)
|
||||
|
||||
return mock_optimizer
|
||||
|
||||
|
|
@ -97,15 +92,15 @@ class TestFixJavaTestPathsIntegration:
|
|||
|
||||
def _create_mock_optimizer(self, tests_root: str):
|
||||
"""Create a mock FunctionOptimizer with the given tests_root."""
|
||||
from codeflash.optimization.function_optimizer import FunctionOptimizer
|
||||
from codeflash.languages.java.function_optimizer import JavaFunctionOptimizer
|
||||
|
||||
mock_optimizer = MagicMock(spec=FunctionOptimizer)
|
||||
mock_optimizer = MagicMock(spec=JavaFunctionOptimizer)
|
||||
mock_optimizer.test_cfg = MagicMock()
|
||||
mock_optimizer.test_cfg.tests_root = Path(tests_root)
|
||||
|
||||
# Bind the actual methods
|
||||
mock_optimizer._get_java_sources_root = lambda: FunctionOptimizer._get_java_sources_root(mock_optimizer)
|
||||
mock_optimizer._fix_java_test_paths = lambda behavior_source, perf_source, used_paths: FunctionOptimizer._fix_java_test_paths(mock_optimizer, behavior_source, perf_source, used_paths)
|
||||
mock_optimizer._get_java_sources_root = lambda: JavaFunctionOptimizer._get_java_sources_root(mock_optimizer)
|
||||
mock_optimizer._fix_java_test_paths = lambda behavior_source, perf_source, used_paths: JavaFunctionOptimizer._fix_java_test_paths(mock_optimizer, behavior_source, perf_source, used_paths)
|
||||
|
||||
return mock_optimizer
|
||||
|
||||
|
|
|
|||
|
|
@ -10,26 +10,19 @@ from pathlib import Path
|
|||
import pytest
|
||||
|
||||
from codeflash.languages.code_replacer import replace_function_definitions_for_language
|
||||
from codeflash.languages.python.static_analysis.code_replacer import replace_function_definitions_in_module
|
||||
from codeflash.models.function_types import FunctionParent
|
||||
from codeflash.languages.base import Language
|
||||
from codeflash.languages import current as language_current
|
||||
from codeflash.languages.java.support import JavaSupport
|
||||
from codeflash.models.models import CodeStringsMarkdown
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def java_language_context():
|
||||
"""Set the current language to Java for the duration of the test."""
|
||||
original_language = language_current._current_language
|
||||
language_current._current_language = Language.JAVA
|
||||
yield
|
||||
language_current._current_language = original_language
|
||||
def java_support():
|
||||
return JavaSupport()
|
||||
|
||||
|
||||
class TestReplaceFunctionDefinitionsInModule:
|
||||
"""Tests for replace_function_definitions_in_module with Java."""
|
||||
"""Tests for replace_function_definitions_for_language with Java (basic cases)."""
|
||||
|
||||
def test_replace_simple_method(self, tmp_path: Path, java_language_context):
|
||||
def test_replace_simple_method(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a simple method in a Java class."""
|
||||
java_file = tmp_path / "Calculator.java"
|
||||
original_code = """public class Calculator {
|
||||
|
|
@ -50,12 +43,12 @@ public class Calculator {{
|
|||
|
||||
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
|
||||
|
||||
result = replace_function_definitions_in_module(
|
||||
result = replace_function_definitions_for_language(
|
||||
function_names=["add"],
|
||||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
preexisting_objects=set(),
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -68,7 +61,7 @@ public class Calculator {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_preserves_other_methods(self, tmp_path: Path, java_language_context):
|
||||
def test_replace_method_preserves_other_methods(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that replacing one method preserves other methods."""
|
||||
java_file = tmp_path / "Calculator.java"
|
||||
original_code = """public class Calculator {
|
||||
|
|
@ -105,12 +98,12 @@ public class Calculator {{
|
|||
|
||||
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
|
||||
|
||||
result = replace_function_definitions_in_module(
|
||||
result = replace_function_definitions_for_language(
|
||||
function_names=["add"],
|
||||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
preexisting_objects=set(),
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -131,7 +124,7 @@ public class Calculator {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_with_javadoc(self, tmp_path: Path, java_language_context):
|
||||
def test_replace_method_with_javadoc(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method that has Javadoc comments."""
|
||||
java_file = tmp_path / "MathUtils.java"
|
||||
original_code = """public class MathUtils {
|
||||
|
|
@ -172,12 +165,12 @@ public class MathUtils {{
|
|||
|
||||
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
|
||||
|
||||
result = replace_function_definitions_in_module(
|
||||
result = replace_function_definitions_for_language(
|
||||
function_names=["factorial"],
|
||||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
preexisting_objects=set(),
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -200,7 +193,7 @@ public class MathUtils {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_no_change_when_code_identical(self, tmp_path: Path, java_language_context):
|
||||
def test_no_change_when_code_identical(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that no change is made when optimized code is identical."""
|
||||
java_file = tmp_path / "Identity.java"
|
||||
original_code = """public class Identity {
|
||||
|
|
@ -221,12 +214,12 @@ public class Identity {{
|
|||
|
||||
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
|
||||
|
||||
result = replace_function_definitions_in_module(
|
||||
result = replace_function_definitions_for_language(
|
||||
function_names=["getValue"],
|
||||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
preexisting_objects=set(),
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is False
|
||||
|
|
@ -237,7 +230,7 @@ public class Identity {{
|
|||
class TestReplaceFunctionDefinitionsForLanguage:
|
||||
"""Tests for replace_function_definitions_for_language with Java."""
|
||||
|
||||
def test_replace_static_method(self, tmp_path: Path):
|
||||
def test_replace_static_method(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a static method."""
|
||||
java_file = tmp_path / "Utils.java"
|
||||
original_code = """public class Utils {
|
||||
|
|
@ -263,6 +256,7 @@ public class Utils {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -275,7 +269,7 @@ public class Utils {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_with_annotations(self, tmp_path: Path):
|
||||
def test_replace_method_with_annotations(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method with annotations."""
|
||||
java_file = tmp_path / "Service.java"
|
||||
original_code = """public class Service {
|
||||
|
|
@ -303,6 +297,7 @@ public class Service {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -316,7 +311,7 @@ public class Service {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_in_interface(self, tmp_path: Path):
|
||||
def test_replace_method_in_interface(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a default method in an interface."""
|
||||
java_file = tmp_path / "Processor.java"
|
||||
original_code = """public interface Processor {
|
||||
|
|
@ -342,6 +337,7 @@ public interface Processor {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -354,7 +350,7 @@ public interface Processor {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_in_enum(self, tmp_path: Path):
|
||||
def test_replace_method_in_enum(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method in an enum."""
|
||||
java_file = tmp_path / "Color.java"
|
||||
original_code = """public enum Color {
|
||||
|
|
@ -384,6 +380,7 @@ public enum Color {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -398,7 +395,7 @@ public enum Color {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_generic_method(self, tmp_path: Path):
|
||||
def test_replace_generic_method(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method with generics."""
|
||||
java_file = tmp_path / "Container.java"
|
||||
original_code = """import java.util.List;
|
||||
|
|
@ -438,6 +435,7 @@ public class Container<T> {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -455,7 +453,7 @@ public class Container<T> {
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_method_with_throws(self, tmp_path: Path):
|
||||
def test_replace_method_with_throws(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method with throws clause."""
|
||||
java_file = tmp_path / "FileReader.java"
|
||||
original_code = """import java.io.IOException;
|
||||
|
|
@ -489,6 +487,7 @@ public class FileReader {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -509,7 +508,7 @@ public class FileReader {
|
|||
class TestRealWorldOptimizationScenarios:
|
||||
"""Real-world optimization scenarios with complete valid Java code."""
|
||||
|
||||
def test_optimize_string_concatenation(self, tmp_path: Path):
|
||||
def test_optimize_string_concatenation(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimizing string concatenation to StringBuilder."""
|
||||
java_file = tmp_path / "StringJoiner.java"
|
||||
original_code = """public class StringJoiner {
|
||||
|
|
@ -543,6 +542,7 @@ public class StringJoiner {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -559,7 +559,7 @@ public class StringJoiner {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_optimize_list_iteration(self, tmp_path: Path):
|
||||
def test_optimize_list_iteration(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimizing list iteration with streams."""
|
||||
java_file = tmp_path / "ListProcessor.java"
|
||||
original_code = """import java.util.List;
|
||||
|
|
@ -593,6 +593,7 @@ public class ListProcessor {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -607,7 +608,7 @@ public class ListProcessor {
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_optimize_null_checks(self, tmp_path: Path):
|
||||
def test_optimize_null_checks(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimizing null checks with Objects utility."""
|
||||
java_file = tmp_path / "NullChecker.java"
|
||||
original_code = """public class NullChecker {
|
||||
|
|
@ -641,6 +642,7 @@ public class NullChecker {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -653,7 +655,7 @@ public class NullChecker {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_optimize_collection_creation(self, tmp_path: Path):
|
||||
def test_optimize_collection_creation(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimizing collection creation with factory methods."""
|
||||
java_file = tmp_path / "CollectionFactory.java"
|
||||
original_code = """import java.util.ArrayList;
|
||||
|
|
@ -689,6 +691,7 @@ public class CollectionFactory {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -708,7 +711,7 @@ public class CollectionFactory {
|
|||
class TestMultipleClassesAndMethods:
|
||||
"""Tests for files with multiple classes or multiple methods being optimized."""
|
||||
|
||||
def test_replace_method_in_first_class(self, tmp_path: Path):
|
||||
def test_replace_method_in_first_class(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method in the first class when multiple classes exist."""
|
||||
java_file = tmp_path / "MultiClass.java"
|
||||
original_code = """public class Calculator {
|
||||
|
|
@ -746,6 +749,7 @@ class Helper {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -764,7 +768,7 @@ class Helper {
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_replace_multiple_methods(self, tmp_path: Path):
|
||||
def test_replace_multiple_methods(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing multiple methods in the same class."""
|
||||
java_file = tmp_path / "MathOps.java"
|
||||
original_code = """public class MathOps {
|
||||
|
|
@ -806,6 +810,7 @@ public class MathOps {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -830,7 +835,7 @@ public class MathOps {{
|
|||
class TestNestedClasses:
|
||||
"""Tests for nested class scenarios."""
|
||||
|
||||
def test_replace_method_in_nested_class(self, tmp_path: Path):
|
||||
def test_replace_method_in_nested_class(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a method in a nested class."""
|
||||
java_file = tmp_path / "Outer.java"
|
||||
original_code = """public class Outer {
|
||||
|
|
@ -868,6 +873,7 @@ public class Outer {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -890,7 +896,7 @@ public class Outer {{
|
|||
class TestPreservesStructure:
|
||||
"""Tests that verify code structure is preserved during replacement."""
|
||||
|
||||
def test_preserves_fields_and_constructors(self, tmp_path: Path):
|
||||
def test_preserves_fields_and_constructors(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that fields and constructors are preserved."""
|
||||
java_file = tmp_path / "Counter.java"
|
||||
original_code = """public class Counter {
|
||||
|
|
@ -935,6 +941,7 @@ public class Counter {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -959,7 +966,7 @@ public class Counter {{
|
|||
class TestEdgeCases:
|
||||
"""Edge cases and error handling tests."""
|
||||
|
||||
def test_empty_optimized_code_returns_false(self, tmp_path: Path):
|
||||
def test_empty_optimized_code_returns_false(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that empty optimized code returns False."""
|
||||
java_file = tmp_path / "Empty.java"
|
||||
original_code = """public class Empty {
|
||||
|
|
@ -980,13 +987,14 @@ class TestEdgeCases:
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is False
|
||||
new_code = java_file.read_text(encoding="utf-8")
|
||||
assert new_code == original_code
|
||||
|
||||
def test_function_not_found_returns_false(self, tmp_path: Path):
|
||||
def test_function_not_found_returns_false(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that function not found returns False."""
|
||||
java_file = tmp_path / "NotFound.java"
|
||||
original_code = """public class NotFound {
|
||||
|
|
@ -1012,11 +1020,12 @@ public class NotFound {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_unicode_in_code(self, tmp_path: Path):
|
||||
def test_unicode_in_code(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test handling of unicode characters in code."""
|
||||
java_file = tmp_path / "Unicode.java"
|
||||
original_code = """public class Unicode {
|
||||
|
|
@ -1042,6 +1051,7 @@ public class Unicode {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1058,7 +1068,7 @@ public class Unicode {{
|
|||
class TestOptimizationWithStaticFields:
|
||||
"""Tests for optimizations that add new static fields to the class."""
|
||||
|
||||
def test_add_static_lookup_table(self, tmp_path: Path):
|
||||
def test_add_static_lookup_table(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimization that adds a static lookup table."""
|
||||
java_file = tmp_path / "Buffer.java"
|
||||
original_code = """public class Buffer {
|
||||
|
|
@ -1097,6 +1107,7 @@ public class Buffer {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1117,7 +1128,7 @@ public class Buffer {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_add_precomputed_array(self, tmp_path: Path):
|
||||
def test_add_precomputed_array(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimization that adds a precomputed static array."""
|
||||
java_file = tmp_path / "Encoder.java"
|
||||
original_code = """public class Encoder {
|
||||
|
|
@ -1154,6 +1165,7 @@ public class Encoder {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1176,7 +1188,7 @@ public class Encoder {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_preserve_existing_fields(self, tmp_path: Path):
|
||||
def test_preserve_existing_fields(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test that existing fields are preserved when adding new ones."""
|
||||
java_file = tmp_path / "Calculator.java"
|
||||
original_code = """public class Calculator {
|
||||
|
|
@ -1227,6 +1239,7 @@ public class Calculator {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1261,7 +1274,7 @@ public class Calculator {{
|
|||
class TestOptimizationWithHelperMethods:
|
||||
"""Tests for optimizations that add new helper methods."""
|
||||
|
||||
def test_add_private_helper_method(self, tmp_path: Path):
|
||||
def test_add_private_helper_method(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimization that adds a private helper method."""
|
||||
java_file = tmp_path / "StringUtils.java"
|
||||
original_code = """public class StringUtils {
|
||||
|
|
@ -1308,6 +1321,7 @@ public class StringUtils {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1330,7 +1344,7 @@ public class StringUtils {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_add_multiple_helpers(self, tmp_path: Path):
|
||||
def test_add_multiple_helpers(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimization that adds multiple helper methods."""
|
||||
java_file = tmp_path / "MathUtils.java"
|
||||
original_code = """public class MathUtils {
|
||||
|
|
@ -1370,6 +1384,7 @@ public class MathUtils {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1394,7 +1409,7 @@ public class MathUtils {{
|
|||
class TestOptimizationWithFieldsAndHelpers:
|
||||
"""Tests for optimizations that add both static fields and helper methods."""
|
||||
|
||||
def test_add_field_and_helper_together(self, tmp_path: Path):
|
||||
def test_add_field_and_helper_together(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test optimization that adds both a static field and helper method."""
|
||||
java_file = tmp_path / "Fibonacci.java"
|
||||
original_code = """public class Fibonacci {
|
||||
|
|
@ -1436,6 +1451,7 @@ public class Fibonacci {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1462,7 +1478,7 @@ public class Fibonacci {{
|
|||
"""
|
||||
assert new_code == expected
|
||||
|
||||
def test_real_world_bytes_to_hex_optimization(self, tmp_path: Path):
|
||||
def test_real_world_bytes_to_hex_optimization(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test the actual bytesToHexString optimization pattern from aerospike."""
|
||||
java_file = tmp_path / "Buffer.java"
|
||||
original_code = """package com.example;
|
||||
|
|
@ -1521,6 +1537,7 @@ public final class Buffer {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -1558,7 +1575,7 @@ public final class Buffer {
|
|||
class TestOverloadedMethods:
|
||||
"""Tests for handling overloaded methods (same name, different signatures)."""
|
||||
|
||||
def test_replace_specific_overload_by_line_number(self, tmp_path: Path):
|
||||
def test_replace_specific_overload_by_line_number(self, tmp_path: Path, java_support: JavaSupport):
|
||||
"""Test replacing a specific overload when multiple exist."""
|
||||
java_file = tmp_path / "Buffer.java"
|
||||
original_code = """public final class Buffer {
|
||||
|
|
@ -1604,7 +1621,7 @@ public final class Buffer {{
|
|||
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
|
||||
|
||||
# Create FunctionToOptimize with line info for the 3-arg version (lines 13-18)
|
||||
from codeflash.discovery.functions_to_optimize import FunctionToOptimize, FunctionParent
|
||||
from codeflash.discovery.functions_to_optimize import FunctionParent, FunctionToOptimize
|
||||
|
||||
function_to_optimize = FunctionToOptimize(
|
||||
function_name="bytesToHexString",
|
||||
|
|
@ -1621,6 +1638,7 @@ public final class Buffer {{
|
|||
optimized_code=optimized_code,
|
||||
module_abspath=java_file,
|
||||
project_root_path=tmp_path,
|
||||
lang_support=java_support,
|
||||
function_to_optimize=function_to_optimize,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -278,8 +278,8 @@ class TestJavaRunAndParseBehavior:
|
|||
test_env=test_env,
|
||||
test_files=func_optimizer.test_files,
|
||||
optimization_iteration=0,
|
||||
min_outer_loops=1,
|
||||
max_outer_loops=2,
|
||||
pytest_min_loops=1,
|
||||
pytest_max_loops=2,
|
||||
testing_time=0.1,
|
||||
)
|
||||
|
||||
|
|
@ -358,8 +358,8 @@ public class AdderMultiTest {
|
|||
test_env=test_env,
|
||||
test_files=func_optimizer.test_files,
|
||||
optimization_iteration=0,
|
||||
min_outer_loops=1,
|
||||
max_outer_loops=2,
|
||||
pytest_min_loops=1,
|
||||
pytest_max_loops=2,
|
||||
testing_time=0.1,
|
||||
)
|
||||
|
||||
|
|
@ -480,8 +480,8 @@ public class PreciseWaiterTest {
|
|||
test_env=test_env,
|
||||
test_files=func_optimizer.test_files,
|
||||
optimization_iteration=0,
|
||||
min_outer_loops=2,
|
||||
max_outer_loops=2,
|
||||
pytest_min_loops=2,
|
||||
pytest_max_loops=2,
|
||||
inner_iterations=inner_iterations,
|
||||
testing_time=0.0,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from pathlib import Path
|
|||
import pytest
|
||||
|
||||
from codeflash.languages.base import Language, LanguageSupport
|
||||
from codeflash.languages.java.support import JavaSupport, get_java_support
|
||||
from codeflash.languages.java.support import get_java_support
|
||||
|
||||
|
||||
class TestJavaSupportProtocol:
|
||||
|
|
|
|||
Loading…
Reference in a new issue