"""Unit tests for offline research simulation only (not consensus tests).""" from __future__ import annotations import math import sys import tempfile import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts")) from simulate_pop_longterm import ( fee_for_window, progressive_fee, policy_for, should_buy, simulate, save_results, ) class LongtermSimulationTests(unittest.TestCase): def test_fee_models_and_free_entry(self): self.assertEqual(fee_for_window(1, 1000, "original"), 0) self.assertLess(fee_for_window(2, 1000, "low"), fee_for_window(2, 1000, "original")) self.assertGreater(progressive_fee(1000), progressive_fee(100)) self.assertGreater(fee_for_window(3, 100, "original"), fee_for_window(2, 100, "original")) def test_policy_and_budget(self): self.assertEqual([policy_for(x, "mixed") for x in range(4)], ["free", "rational", "rational", "always"]) ok, reason = should_buy("always", 2, 0, 100, "original", (0.7,)*3, 1) self.assertFalse(ok) self.assertEqual(reason, "budget") def test_zero_capital_never_goes_negative(self): res = simulate(12, 4, 7, "balanced", "mixed", "original", 1, 10) self.assertTrue(all(m["balance"] >= -1e-8 for m in res["miners"])) self.assertLessEqual(res["summary"]["issued"], 40) self.assertGreaterEqual(res["summary"]["burned"], 0) def test_free_scenario_no_fees(self): res = simulate(10, 2, 11, "original", "free", "original", 1, 16) self.assertEqual(res["summary"]["burned"], 0) self.assertTrue(all(m["paid_windows2"] == 0 for m in res["miners"])) def test_reproducible_and_report_files(self): a = simulate(5, 3, 2026, "balanced", "mixed", "mild", 1, 20) b = simulate(5, 3, 2026, "balanced", "mixed", "mild", 1, 20) self.assertEqual(a, b) with tempfile.TemporaryDirectory() as tmp: files = save_results(Path(tmp), a) self.assertEqual(len(files), 4) self.assertTrue(all(p.is_file() for p in files)) if __name__ == "__main__": unittest.main()