"""Test pygount determinism with serial and parallel execution.""" import subprocess import json from pathlib import Path import concurrent.futures test_file = Path("pyucc/core/countings_impl.py") print(f"Testing: {test_file}") print(f"File size: {test_file.stat().st_size} bytes") print() def run_pygount(run_id): """Run pygount once and return results.""" proc = subprocess.run( ["pygount", "--format", "json", str(test_file)], capture_output=True, text=True, check=True, ) data = json.loads(proc.stdout) if isinstance(data, list): item = data[0] else: item = data["files"][0] return { "id": run_id, "lineCount": item.get("lineCount"), "sourceCount": item.get("sourceCount"), "codeCount": item.get("codeCount"), "documentationCount": item.get("documentationCount"), "emptyCount": item.get("emptyCount"), "language": item.get("language"), } # Test serial print("Serial execution (5 runs):") serial_results = [] for i in range(5): result = run_pygount(i + 1) serial_results.append(result) print( f' Run {result["id"]}: code={result["codeCount"]}, ' f'doc={result["documentationCount"]}, empty={result["emptyCount"]}' ) # Test parallel print() print("Parallel execution (10 runs):") with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(run_pygount, i + 1) for i in range(10)] parallel_results = [f.result() for f in futures] for result in parallel_results: print( f' Run {result["id"]}: code={result["codeCount"]}, ' f'doc={result["documentationCount"]}, empty={result["emptyCount"]}' ) # Check consistency print() base = {k: v for k, v in serial_results[0].items() if k != "id"} all_serial = all( {k: v for k, v in r.items() if k != "id"} == base for r in serial_results ) all_parallel = all( {k: v for k, v in r.items() if k != "id"} == base for r in parallel_results ) print(f"Serial results consistent: {all_serial}") print(f"Parallel results consistent: {all_parallel}") print(f"Serial == Parallel: {all_serial and all_parallel}") if not (all_serial and all_parallel): print() print("FOUND INCONSISTENCIES!") print("First result:", base) if not all_serial: print("Serial differences:") for r in serial_results: r_clean = {k: v for k, v in r.items() if k != "id"} if r_clean != base: print(f' Run {r["id"]}: {r_clean}') if not all_parallel: print("Parallel differences:") for r in parallel_results: r_clean = {k: v for k, v in r.items() if k != "id"} if r_clean != base: print(f' Run {r["id"]}: {r_clean}')