import hashlib import json import tempfile import unittest from pathlib import Path from quant60.experiment import ( run_research_smoke, verify_research_manifest, write_research_artifacts, ) class ResearchExperimentTests(unittest.TestCase): def test_research_smoke_is_deterministic_and_verifiable(self): first = run_research_smoke(trading_days=260, seed=11) second = run_research_smoke(trading_days=260, seed=11) self.assertEqual(first, second) self.assertGreater(first["report"]["fold_count"], 0) self.assertFalse(first["report"]["investment_value_claim"]) self.assertTrue(first["targets"]) with tempfile.TemporaryDirectory() as left_dir, tempfile.TemporaryDirectory() as right_dir: left = write_research_artifacts(first, left_dir) right = write_research_artifacts(second, right_dir) for name in left: self.assertEqual( hashlib.sha256(Path(left[name]).read_bytes()).hexdigest(), hashlib.sha256(Path(right[name]).read_bytes()).hexdigest(), name, ) verified = verify_research_manifest(left["manifest"]) self.assertTrue(verified["ok"]) def test_research_verifier_rejects_tamper(self): result = run_research_smoke(trading_days=260, seed=12) with tempfile.TemporaryDirectory() as directory: paths = write_research_artifacts(result, directory) report = Path(paths["report"]) report.write_bytes(report.read_bytes() + b" ") with self.assertRaisesRegex(ValueError, "hash mismatch"): verify_research_manifest(paths["manifest"]) if __name__ == "__main__": unittest.main()