11import importlib .util
2+ import json
23from pathlib import Path
34import shutil
45import subprocess
910pytestmark = pytest .mark .correctness
1011
1112
12- TEST_VECTORS : list [tuple [int , int , bool , int ]] = [
13- (5 , 10 , False , 50 ),
14- (5 , 10 , True , 75 ),
15- (8 , 12 , True , 100 ),
16- (1 , 1 , False , 1 ),
17- (- 4 , 10 , False , 0 ),
18- (0 , 999 , True , 25 ),
19- ]
13+ def _load_shared_vectors () -> list [dict ]:
14+ vectors_path = _repo_root () / "fixtures" / "vectors" / "legacy_calculator_vectors.json"
15+ with open (vectors_path , encoding = "utf-8" ) as handle :
16+ payload = json .load (handle )
17+ assert isinstance (payload , list )
18+ return payload
2019
2120
2221def _repo_root () -> Path :
2322 return Path (__file__ ).resolve ().parents [2 ]
2423
2524
25+ SHARED_VECTORS = _load_shared_vectors ()
26+
27+
2628def _read_fixture (relative_path : str ) -> str :
2729 return (_repo_root () / relative_path ).read_text (encoding = "utf-8" )
2830
@@ -43,11 +45,14 @@ def java_legacy_runner(tmp_path_factory):
4345
4446 workdir = tmp_path_factory .mktemp ("legacy_java_calc" )
4547 java_source = _read_fixture ("fixtures/java/simple/LegacyCalculator.java" )
48+ java_vector_runner = _read_fixture ("fixtures/java/simple/LegacyCalculatorVectorRunner.java" )
4649 java_path = workdir / "LegacyCalculator.java"
50+ java_runner_path = workdir / "LegacyCalculatorVectorRunner.java"
4751 java_path .write_text (java_source , encoding = "utf-8" )
52+ java_runner_path .write_text (java_vector_runner , encoding = "utf-8" )
4853
4954 compile_proc = subprocess .run (
50- ["javac" , str (java_path )],
55+ ["javac" , str (java_path ), str ( java_runner_path ) ],
5156 cwd = workdir ,
5257 check = False ,
5358 capture_output = True ,
@@ -71,20 +76,91 @@ def _run(base: int, multiplier: int, premium: bool) -> int:
7176 return _run
7277
7378
79+ @pytest .fixture (scope = "module" )
80+ def java_vector_batch_runner (tmp_path_factory ):
81+ if not shutil .which ("javac" ) or not shutil .which ("java" ):
82+ pytest .skip ("Java toolchain not available (requires javac and java)" )
83+
84+ workdir = tmp_path_factory .mktemp ("legacy_java_vector_batch" )
85+ java_source = _read_fixture ("fixtures/java/simple/LegacyCalculator.java" )
86+ java_vector_runner = _read_fixture ("fixtures/java/simple/LegacyCalculatorVectorRunner.java" )
87+ java_path = workdir / "LegacyCalculator.java"
88+ java_runner_path = workdir / "LegacyCalculatorVectorRunner.java"
89+ java_path .write_text (java_source , encoding = "utf-8" )
90+ java_runner_path .write_text (java_vector_runner , encoding = "utf-8" )
91+
92+ compile_proc = subprocess .run (
93+ ["javac" , str (java_path ), str (java_runner_path )],
94+ cwd = workdir ,
95+ check = False ,
96+ capture_output = True ,
97+ text = True ,
98+ )
99+ if compile_proc .returncode != 0 :
100+ pytest .fail (f"Failed compiling Java vector runner fixture: { compile_proc .stderr } " )
101+
102+ def _run (vectors_path : Path ) -> dict [str , tuple [int , int ]]:
103+ run_proc = subprocess .run (
104+ ["java" , "-cp" , str (workdir ), "LegacyCalculatorVectorRunner" , str (vectors_path )],
105+ cwd = workdir ,
106+ check = False ,
107+ capture_output = True ,
108+ text = True ,
109+ )
110+ if run_proc .returncode != 0 :
111+ pytest .fail (f"Legacy Java vector batch execution failed: { run_proc .stderr } " )
112+
113+ outputs : dict [str , tuple [int , int ]] = {}
114+ for line in run_proc .stdout .splitlines ():
115+ line = line .strip ()
116+ if not line :
117+ continue
118+ case_id , actual , expected = line .split ("," , 2 )
119+ outputs [case_id ] = (int (actual ), int (expected ))
120+ return outputs
121+
122+ return _run
123+
124+
74125def test_legacy_java_fixture_expected_values (java_legacy_runner ):
75- for base , multiplier , premium , expected in TEST_VECTORS :
126+ for vector in SHARED_VECTORS :
127+ base = int (vector ["input" ]["base" ])
128+ multiplier = int (vector ["input" ]["multiplier" ])
129+ premium = bool (vector ["input" ]["premium" ])
130+ expected = int (vector ["expected" ])
76131 assert java_legacy_runner (base , multiplier , premium ) == expected
77132
78133
79134def test_python_fixture_expected_values ():
80135 calculate_score = _load_python_calculator ()
81- for base , multiplier , premium , expected in TEST_VECTORS :
136+ for vector in SHARED_VECTORS :
137+ base = int (vector ["input" ]["base" ])
138+ multiplier = int (vector ["input" ]["multiplier" ])
139+ premium = bool (vector ["input" ]["premium" ])
140+ expected = int (vector ["expected" ])
82141 assert calculate_score (base , multiplier , premium ) == expected
83142
84143
85144def test_python_matches_legacy_java_outputs (java_legacy_runner ):
86145 calculate_score = _load_python_calculator ()
87- for base , multiplier , premium , _expected in TEST_VECTORS :
146+ for vector in SHARED_VECTORS :
147+ base = int (vector ["input" ]["base" ])
148+ multiplier = int (vector ["input" ]["multiplier" ])
149+ premium = bool (vector ["input" ]["premium" ])
88150 legacy_output = java_legacy_runner (base , multiplier , premium )
89151 python_output = calculate_score (base , multiplier , premium )
90- assert python_output == legacy_output
152+ assert python_output == legacy_output
153+
154+
155+ def test_java_batch_runner_reads_shared_json_vectors (java_vector_batch_runner ):
156+ vectors_path = _repo_root () / "fixtures" / "vectors" / "legacy_calculator_vectors.json"
157+ outputs = java_vector_batch_runner (vectors_path )
158+ assert outputs , "Expected java batch runner to produce vector outputs"
159+ assert len (outputs ) == len (SHARED_VECTORS )
160+ for vector in SHARED_VECTORS :
161+ case_id = str (vector ["id" ])
162+ expected = int (vector ["expected" ])
163+ assert case_id in outputs
164+ actual , runner_expected = outputs [case_id ]
165+ assert runner_expected == expected
166+ assert actual == expected
0 commit comments