/ proof-of-concept / cymsim
Sign in
proof-of-concept / cymsim
cymsim / tests / test_cache.py
96 lines · 4.3 KBBlameHistoryRaw
1"""Cache keys: independent of the duration and the output naming, of whether a default is written
2out, and consistent with which runs can continue one another."""
3import copy
4import hashlib
5import json
6import re
8import yaml
10from cymsim.cache import MODEL_VERSION, cache_key, key_fields
11from cymsim.cli import main
12from cymsim.config import ForceExciter, Hit, MalletExciter, SimulationConfig, StickExciter, default_config
14# sha256 of the full default configuration. When this test fails, a default has changed or a field
15# was added. If the results of some existing configuration change, bump MODEL_VERSION in cache.py;
16# either way, update the fingerprint.
17DEFAULTS_FINGERPRINT = "4b9d969c01b47ddabc6ee40ac7315d0c1ed1ac998f4a95b120ed4e668268672c"
20def test_key_format():
21 assert re.fullmatch(rf"v{MODEL_VERSION}/[0-9a-f]{{64}}", cache_key(SimulationConfig()))
24def test_continuation_fields_do_not_change_the_key():
25 a = default_config("stick")
26 b = copy.deepcopy(a)
27 b.numerics.duration = 7.5
28 b.numerics.n_progress = 3
29 b.output.prefix, b.output.wav, b.output.npz, b.output.cascade_plot = "other", False, False, False
30 assert cache_key(a) == cache_key(b)
33def test_written_out_defaults_do_not_change_the_key(tmp_path):
34 full = tmp_path / "full.yaml"
35 default_config("stick").to_yaml(full) # every field written out
36 short = tmp_path / "short.yaml"
37 h = default_config("stick").hits[0]
38 short.write_text(yaml.safe_dump({"hits": [{"r": h.r, "phi": h.phi, "velocity": 7, "exciter": {"kind": "stick"}}]}))
39 assert cache_key(SimulationConfig.from_yaml(full)) == cache_key(SimulationConfig.from_yaml(short))
40 assert cache_key(SimulationConfig.from_yaml(full)) == cache_key(default_config("stick"))
43def test_physical_and_numerical_changes_change_the_key():
44 base = default_config("mallet")
45 variants = []
46 for change in (lambda c: setattr(c.hits[0], "velocity", 8.0001),
47 lambda c: setattr(c.hits[0], "exciter", StickExciter()),
48 lambda c: setattr(c.hits[0], "exciter", ForceExciter()),
49 lambda c: c.hits.append(Hit(time=0.5)),
50 lambda c: setattr(c.material, "E", 1.2e11),
51 lambda c: setattr(c.imperfections, "seed", 2),
52 lambda c: setattr(c.numerics, "dtype", "float64"),
53 lambda c: setattr(c.numerics, "steps_per_block", 10000),
54 lambda c: setattr(c.output, "probes", [(0.1, 0.0)]),
55 lambda c: setattr(c.output, "record_acceleration", True),
56 lambda c: setattr(c.listener, "position", (0.4, 0.3, 1.0))):
57 c = copy.deepcopy(base)
58 change(c)
59 variants.append(cache_key(c))
60 assert len(set(variants + [cache_key(base)])) == len(variants) + 1
63def test_exciters_at_their_defaults_are_told_apart():
64 keys = {cache_key(SimulationConfig(hits=[Hit(exciter=e)])) for e in (MalletExciter(), StickExciter(), ForceExciter())}
65 assert len(keys) == 3
66 assert key_fields(SimulationConfig(hits=[Hit(exciter=StickExciter())])) == {"hits": [{"exciter": {"kind": "stick"}}]}
69def test_equal_keys_mean_continuable_runs():
70 """The key and Simulator.check_resumable compare the same thing."""
71 base = default_config("stick")
72 cfgs = [base]
73 for change in (lambda c: setattr(c.numerics, "duration", 1.0), lambda c: setattr(c.output, "prefix", "z"),
74 lambda c: setattr(c.hits[0], "phi", 1.0), lambda c: setattr(c.output, "displacement_rate", 0.0)):
75 c = copy.deepcopy(base)
76 change(c)
77 cfgs.append(c)
78 for a in cfgs:
79 for b in cfgs:
80 assert (cache_key(a) == cache_key(b)) == (a.identity_dict() == b.identity_dict())
83def test_defaults_fingerprint():
84 text = json.dumps(SimulationConfig().to_dict(), sort_keys=True, separators=(",", ":"))
85 assert hashlib.sha256(text.encode()).hexdigest() == DEFAULTS_FINGERPRINT, (
86 "the default configuration changed: bump MODEL_VERSION in cache.py if results of existing "
87 "configurations change, then update DEFAULTS_FINGERPRINT")
90def test_cli_cache_key(tmp_path, capsys):
91 path = tmp_path / "c.yaml"
92 default_config("stick").to_yaml(path)
93 assert main(["cache-key", str(path), "--show"]) == 0
94 out = capsys.readouterr().out.splitlines()
95 assert out[0] == cache_key(default_config("stick"))
96 assert '"hits": [' in "\n".join(out)
↑↓ move↵openescclose