Skip to content

Commit 3b03249

Browse files
Merge remote-tracking branch 'origin/main' into cf-1087-field-injection-class-filter
2 parents fdc7a52 + 33c8cc1 commit 3b03249

9 files changed

Lines changed: 62 additions & 18 deletions

File tree

codeflash/languages/java/gradle_strategy.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
'spotbugsMain', 'spotbugsTest',
4646
'pmdMain', 'pmdTest',
4747
'rat', 'japicmp',
48-
'jarHell', 'thirdPartyAudit'
48+
'jarHell', 'thirdPartyAudit',
49+
'spotlessCheck', 'spotlessApply', 'spotlessJava', 'spotlessKotlin', 'spotlessScala'
4950
]
5051
}.configureEach {
5152
enabled = false

codeflash/languages/java/maven_strategy.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
"-Denforcer.skip=true",
4444
"-Djapicmp.skip=true",
4545
"-Derrorprone.skip=true",
46+
"-Dspotless.check.skip=true",
47+
"-Dspotless.apply.skip=true",
4648
"-Dmaven.compiler.failOnWarning=false",
4749
"-Dmaven.compiler.showWarnings=false",
4850
]

codeflash/languages/javascript/support.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2268,7 +2268,10 @@ def get_module_path(self, source_file: Path, project_root: Path, tests_root: Pat
22682268
source_without_ext = source_file_abs.with_suffix("")
22692269

22702270
# Use os.path.relpath to compute relative path from tests_root to source file
2271-
rel_path = os.path.relpath(str(source_without_ext), str(tests_root_abs))
2271+
# Replace backslashes with forward slashes — JavaScript import/require paths
2272+
# must use forward slashes. Backslashes are escape chars in JS strings
2273+
# (e.g. \t → tab, \n → newline) and would break imports on Windows.
2274+
rel_path = os.path.relpath(str(source_without_ext), str(tests_root_abs)).replace("\\", "/")
22722275

22732276
# For ESM, add .js extension (TypeScript convention)
22742277
# TypeScript requires imports to reference the OUTPUT file extension (.js),

codeflash/languages/javascript/test_runner.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ def _create_runtime_jest_config(base_config_path: Path | None, project_root: Pat
369369

370370
runtime_config_path = config_dir / f"jest.codeflash.runtime.config{config_ext}"
371371

372-
test_dirs_js = ", ".join(f"'{d}'" for d in sorted(test_dirs))
372+
# Normalize to forward slashes — backslashes in JS strings are escape chars
373+
# (e.g. \t → tab, \n → newline) and would corrupt paths on Windows.
374+
test_dirs_js = ", ".join(f"'{d.replace(chr(92), '/')}'" for d in sorted(test_dirs))
373375

374376
# In monorepos, add the root node_modules to moduleDirectories so Jest
375377
# can resolve workspace packages that are hoisted to the monorepo root.
@@ -382,6 +384,8 @@ def _create_runtime_jest_config(base_config_path: Path | None, project_root: Pat
382384
else:
383385
module_dirs_line_no_base = ""
384386

387+
project_root_posix = project_root.as_posix()
388+
385389
# TypeScript configs (.ts) cannot be required from CommonJS modules
386390
# because Node.js cannot parse TypeScript syntax in require().
387391
# When the base config is TypeScript, we create a standalone config
@@ -403,7 +407,7 @@ def _create_runtime_jest_config(base_config_path: Path | None, project_root: Pat
403407
else:
404408
config_content = f"""// Auto-generated by codeflash - runtime config with test roots
405409
module.exports = {{
406-
roots: ['{project_root}', {test_dirs_js}],
410+
roots: ['{project_root_posix}', {test_dirs_js}],
407411
testMatch: ['**/*.test.ts', '**/*.test.js', '**/*.test.tsx', '**/*.test.jsx'],
408412
{module_dirs_line_no_base}}};
409413
"""

codeflash/verification/coverage_utils.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,17 @@ def load_from_jest_json(
5454
return CoverageData.create_empty(source_code_path, function_name, code_context)
5555

5656
# Find the file entry in coverage data
57-
# Jest uses absolute paths as keys
57+
# Jest/Vitest always writes coverage keys with forward slashes (POSIX paths),
58+
# so we normalize our paths to POSIX for comparison — critical on Windows
59+
# where Path.resolve() and str(Path) produce backslash paths.
5860
file_coverage = None
59-
source_path_str = str(source_code_path.resolve())
61+
source_path_posix = source_code_path.resolve().as_posix()
62+
source_relative_posix = source_code_path.as_posix()
6063

6164
for file_path, file_data in coverage_data.items():
6265
# Match exact path or path ending with full relative path from src/
6366
# Avoid matching files with same name in different directories (e.g., db/utils.ts vs utils/utils.ts)
64-
if file_path == source_path_str or file_path.endswith(str(source_code_path)):
67+
if file_path == source_path_posix or file_path.endswith(source_relative_posix):
6568
file_coverage = file_data
6669
break
6770

tests/test_languages/test_java/test_build_tools.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,28 @@ def test_adds_dependency_to_nested_module(self, tmp_path):
641641
assert result is True
642642
nested_build = (nested / "build.gradle.kts").read_text(encoding="utf-8")
643643
assert "codeflash-runtime" in nested_build
644+
645+
646+
class TestValidationSkipFlags:
647+
"""Tests that validation skip flags include all known static analysis and formatting plugins."""
648+
649+
def test_maven_skip_flags_include_spotless(self):
650+
from codeflash.languages.java.maven_strategy import _MAVEN_VALIDATION_SKIP_FLAGS
651+
652+
flags_str = " ".join(_MAVEN_VALIDATION_SKIP_FLAGS)
653+
assert "-Dspotless.check.skip=true" in flags_str
654+
assert "-Dspotless.apply.skip=true" in flags_str
655+
656+
def test_maven_skip_flags_include_all_known_plugins(self):
657+
from codeflash.languages.java.maven_strategy import _MAVEN_VALIDATION_SKIP_FLAGS
658+
659+
flags_str = " ".join(_MAVEN_VALIDATION_SKIP_FLAGS)
660+
for plugin in ["rat", "checkstyle", "spotbugs", "pmd", "enforcer", "japicmp", "errorprone", "spotless"]:
661+
assert plugin in flags_str, f"Missing skip flag for {plugin}"
662+
663+
def test_gradle_skip_script_includes_spotless(self):
664+
from codeflash.languages.java.gradle_strategy import _GRADLE_SKIP_VALIDATION_INIT_SCRIPT
665+
666+
assert "spotlessCheck" in _GRADLE_SKIP_VALIDATION_INIT_SCRIPT
667+
assert "spotlessApply" in _GRADLE_SKIP_VALIDATION_INIT_SCRIPT
668+
assert "spotlessJava" in _GRADLE_SKIP_VALIDATION_INIT_SCRIPT

tests/test_languages/test_java/test_run_and_parse.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,16 @@ def test_performance_inner_loop_count_and_timing(self, java_project):
512512
stddev_runtime = statistics.stdev(runtimes)
513513
coefficient_of_variation = stddev_runtime / mean_runtime
514514

515-
# Target: 10ms (10,000,000 ns), allow <5% coefficient of variation
516-
# (accounts for JIT warmup - first iteration is cold, subsequent are optimized)
515+
# Target: 10ms (10,000,000 ns), allow <15% coefficient of variation.
516+
# The first iteration per test method runs with cold JIT, and shared CI VMs
517+
# (especially Windows) have ~15ms scheduler granularity that adds noise.
518+
# 15% still catches instrumentation bugs (e.g., 0ms or 100ms outliers)
519+
# while the ±5% mean check below validates timing accuracy.
517520
expected_ns = 10_000_000
518521
runtimes_ms = [r / 1_000_000 for r in runtimes]
519522

520-
assert coefficient_of_variation < 0.05, (
521-
f"Timing variance too high: CV={coefficient_of_variation:.2%} (should be <5%). "
523+
assert coefficient_of_variation < 0.15, (
524+
f"Timing variance too high: CV={coefficient_of_variation:.2%} (should be <15%). "
522525
f"Runtimes: {runtimes_ms} ms (mean={mean_runtime / 1_000_000:.3f}ms)"
523526
)
524527

@@ -597,13 +600,16 @@ def test_performance_multiple_test_methods_inner_loop(self, java_project):
597600
stddev_runtime = statistics.stdev(runtimes)
598601
coefficient_of_variation = stddev_runtime / mean_runtime
599602

600-
# Target: 10ms (10,000,000 ns), allow <5% coefficient of variation
601-
# (accounts for JIT warmup - first iteration is cold, subsequent are optimized)
603+
# Target: 10ms (10,000,000 ns), allow <15% coefficient of variation.
604+
# The first iteration per test method runs with cold JIT, and shared CI VMs
605+
# (especially Windows) have ~15ms scheduler granularity that adds noise.
606+
# 15% still catches instrumentation bugs (e.g., 0ms or 100ms outliers)
607+
# while the ±5% mean check below validates timing accuracy.
602608
expected_ns = 10_000_000
603609
runtimes_ms = [r / 1_000_000 for r in runtimes]
604610

605-
assert coefficient_of_variation < 0.05, (
606-
f"Timing variance too high: CV={coefficient_of_variation:.2%} (should be <5%). "
611+
assert coefficient_of_variation < 0.15, (
612+
f"Timing variance too high: CV={coefficient_of_variation:.2%} (should be <15%). "
607613
f"Runtimes: {runtimes_ms} ms (mean={mean_runtime / 1_000_000:.3f}ms)"
608614
)
609615

tests/test_languages/test_javascript_test_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def test_behavioral_tests_creates_runtime_config_for_external_tests(self):
122122
runtime_configs = [f for f in get_created_config_files() if "codeflash.runtime" in f.name]
123123
assert len(runtime_configs) == 1, f"Expected 1 runtime config, got {len(runtime_configs)}"
124124
config_content = runtime_configs[0].read_text(encoding="utf-8")
125-
assert str(external_path) in config_content, "Runtime config should contain external test directory"
125+
assert external_path.as_posix() in config_content, "Runtime config should contain external test directory"
126126

127127
clear_created_config_files()
128128

tests/test_languages/test_jest_typescript_config_bug.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def test_runtime_config_with_typescript_base_config_loads_without_error(self):
9191
capture_output=True,
9292
text=True,
9393
cwd=project_path,
94-
timeout=5,
94+
timeout=30,
9595
)
9696

9797
assert result.returncode == 0, (
@@ -148,7 +148,7 @@ def test_runtime_config_with_js_base_config_works(self):
148148
capture_output=True,
149149
text=True,
150150
cwd=project_path,
151-
timeout=5,
151+
timeout=30,
152152
)
153153

154154
assert result.returncode == 0, f"JS config should load: {result.stderr}"

0 commit comments

Comments
 (0)