Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ private static Map<String, byte[]> readTestResults(String dbPath) throws Excepti
try (Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT iteration_id, return_value FROM test_results WHERE loop_index = 1")) {
"SELECT test_module_path, test_class_name, test_function_name, iteration_id, return_value FROM test_results WHERE loop_index = 1")) {
while (rs.next()) {
String testModulePath = rs.getString("test_module_path");
String testClassName = rs.getString("test_class_name");
String testFunctionName = rs.getString("test_function_name");
String iterationId = rs.getString("iteration_id");
byte[] returnValue = rs.getBytes("return_value");
// Strip the CODEFLASH_TEST_ITERATION suffix (e.g. "7_0" -> "7")
Expand All @@ -155,7 +158,10 @@ private static Map<String, byte[]> readTestResults(String dbPath) throws Excepti
if (lastUnderscore > 0) {
iterationId = iterationId.substring(0, lastUnderscore);
}
results.put(iterationId, returnValue);
// Use module:class:function:iteration as key to uniquely identify
// each invocation across different test files, classes, and methods
String key = testModulePath + ":" + testClassName + ":" + testFunctionName + "::" + iterationId;
results.put(key, returnValue);
}
}
return results;
Expand Down
8 changes: 4 additions & 4 deletions codeflash/languages/java/instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ def build_instrumented_body(
timing_lines = [
f"{indent}for (int _cf_i{current_id} = 0; _cf_i{current_id} < _cf_innerIterations{current_id}; _cf_i{current_id}++) {{",
f"{inner_indent}int _cf_loopId{current_id} = _cf_outerLoop{current_id} * _cf_maxInnerIterations{current_id} + _cf_i{current_id};",
f'{inner_indent}System.out.println("!$######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":" + _cf_i{current_id} + "######$!");',
f'{inner_indent}System.out.println("!$######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":" + "{current_id}" + "######$!");',
f"{inner_indent}long _cf_end{current_id} = -1;",
f"{inner_indent}long _cf_start{current_id} = 0;",
f"{inner_indent}try {{",
Expand All @@ -1083,7 +1083,7 @@ def build_instrumented_body(
f"{inner_indent}}} finally {{",
f"{inner_body_indent}long _cf_end{current_id}_finally = System.nanoTime();",
f"{inner_body_indent}long _cf_dur{current_id} = (_cf_end{current_id} != -1 ? _cf_end{current_id} : _cf_end{current_id}_finally) - _cf_start{current_id};",
f'{inner_body_indent}System.out.println("!######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":" + _cf_i{current_id} + ":" + _cf_dur{current_id} + "######!");',
f'{inner_body_indent}System.out.println("!######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":" + "{current_id}" + ":" + _cf_dur{current_id} + "######!");',
f"{inner_indent}}}",
f"{indent}}}",
]
Expand Down Expand Up @@ -1140,7 +1140,7 @@ def build_instrumented_body(
timing_lines = [
f"{indent}for (int _cf_i{current_id} = 0; _cf_i{current_id} < _cf_innerIterations{current_id}; _cf_i{current_id}++) {{",
f"{inner_indent}int _cf_loopId{current_id} = _cf_outerLoop{current_id} * _cf_maxInnerIterations{current_id} + _cf_i{current_id};",
f'{inner_indent}System.out.println("!$######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":{current_id}_" + _cf_i{current_id} + "######$!");',
f'{inner_indent}System.out.println("!$######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":{current_id}" + "######$!");',
f"{inner_indent}long _cf_end{current_id} = -1;",
f"{inner_indent}long _cf_start{current_id} = 0;",
f"{inner_indent}try {{",
Expand All @@ -1150,7 +1150,7 @@ def build_instrumented_body(
f"{inner_indent}}} finally {{",
f"{inner_body_indent}long _cf_end{current_id}_finally = System.nanoTime();",
f"{inner_body_indent}long _cf_dur{current_id} = (_cf_end{current_id} != -1 ? _cf_end{current_id} : _cf_end{current_id}_finally) - _cf_start{current_id};",
f'{inner_body_indent}System.out.println("!######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":{current_id}_" + _cf_i{current_id} + ":" + _cf_dur{current_id} + "######!");',
f'{inner_body_indent}System.out.println("!######" + _cf_mod{current_id} + ":" + _cf_cls{current_id} + "." + _cf_test{current_id} + ":" + _cf_fn{current_id} + ":" + _cf_loopId{current_id} + ":{current_id}" + ":" + _cf_dur{current_id} + "######!");',
f"{inner_indent}}}",
f"{indent}}}",
]
Expand Down
Binary file modified codeflash/languages/java/resources/codeflash-runtime-1.0.0.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,6 @@ def detect_unused_helper_functions(
"""
# Skip this analysis for non-Python languages since we use Python's ast module
if not is_python():
logger.debug("Skipping unused helper function detection for non-Python languages")
return []

if isinstance(optimized_code, CodeStringsMarkdown) and len(optimized_code.code_strings) > 0:
Expand Down
19 changes: 0 additions & 19 deletions codeflash/verification/parse_test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,23 +605,16 @@ def parse_sqlite_test_results(sqlite_file_path: Path, test_files: TestFiles, tes
else:
# Try original_file_path first (for existing tests that were instrumented)
test_type = test_files.get_test_type_by_original_file_path(test_file_path)
logger.debug(f"[PARSE-DEBUG] test_module={test_module_path}, test_file_path={test_file_path}")
logger.debug(f"[PARSE-DEBUG] by_original_file_path: {test_type}")
# If not found, try instrumented_behavior_file_path (for generated tests)
if test_type is None:
test_type = test_files.get_test_type_by_instrumented_file_path(test_file_path)
logger.debug(f"[PARSE-DEBUG] by_instrumented_file_path: {test_type}")
# Default to GENERATED_REGRESSION for Jest/Java tests when test type can't be determined
if test_type is None and (is_jest or is_java_test):
test_type = TestType.GENERATED_REGRESSION
logger.debug(
f"[PARSE-DEBUG] defaulting to GENERATED_REGRESSION ({'Jest' if is_jest else 'Java'})"
)
elif test_type is None:
# Skip results where test type cannot be determined
logger.debug(f"Skipping result for {test_function_name}: could not determine test type")
continue
logger.debug(f"[PARSE-DEBUG] FINAL test_type={test_type}")

# Deserialize return value
# For Jest/Java: Store as serialized JSON - comparison happens via language-specific comparator
Expand Down Expand Up @@ -699,10 +692,6 @@ def parse_test_xml(
return test_results
# Always use tests_project_rootdir since pytest is now the test runner for all frameworks
base_dir = test_config.tests_project_rootdir
logger.debug(f"[PARSE-XML] base_dir for resolution: {base_dir}")
logger.debug(
f"[PARSE-XML] Registered test files: {[str(tf.instrumented_behavior_file_path) for tf in test_files.test_files]}"
)

# For Java: pre-parse fallback stdout once (not per testcase) to avoid O(n²) complexity
java_fallback_stdout = None
Expand Down Expand Up @@ -763,13 +752,9 @@ def parse_test_xml(
if test_file_name is None:
if test_class_path:
# TODO : This might not be true if the test is organized under a class
logger.debug(f"[PARSE-XML] Resolving test_class_path={test_class_path} in base_dir={base_dir}")
test_file_path = resolve_test_file_from_class_path(test_class_path, base_dir)

if test_file_path is None:
logger.error(
f"[PARSE-XML] ERROR: Could not resolve test_class_path={test_class_path}, base_dir={base_dir}"
)
logger.warning(f"Could not find the test for file name - {test_class_path} ")
continue
else:
Expand All @@ -782,15 +767,11 @@ def parse_test_xml(
logger.warning(f"Could not find the test for file name - {test_file_path} ")
continue
# Try to match by instrumented file path first (for generated/instrumented tests)
logger.debug(f"[PARSE-XML] Looking up test_type by instrumented_file_path: {test_file_path}")
test_type = test_files.get_test_type_by_instrumented_file_path(test_file_path)
logger.debug(f"[PARSE-XML] Lookup by instrumented path result: {test_type}")
if test_type is None:
# Fallback: try to match by original file path (for existing unit tests that were instrumented)
# JUnit XML may reference the original class name, resolving to the original file path
logger.debug(f"[PARSE-XML] Looking up test_type by original_file_path: {test_file_path}")
test_type = test_files.get_test_type_by_original_file_path(test_file_path)
logger.debug(f"[PARSE-XML] Lookup by original path result: {test_type}")
if test_type is None:
# Log registered paths for debugging
registered_paths = [str(tf.instrumented_behavior_file_path) for tf in test_files.test_files]
Expand Down
Loading
Loading