source: flexoentity/tests/test_id_stress.py@ 8aea9a0

Last change on this file since 8aea9a0 was 8aea9a0, checked in by Enrico Schwass <ennoausberlin@…>, 3 months ago

fix tests

  • Property mode set to 100644
File size: 3.5 KB
Line 
1"""
2Stress tests for the Flex-O ID lifecycle.
3Focus: collision avoidance, version ceiling, reproducibility.
4"""
5import os
6import sys
7import pytest
8
9sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10from flexoentity import FlexOID, EntityType, EntityState, FlexoEntity
11
12
13# ──────────────────────────────────────────────────────────────────────────────
14def test_bulk_generation_uniqueness():
15 """Generate 10,000 IDs and assert uniqueness (statistical test)."""
16 domain = "AF"
17 etype = EntityType.QUESTION
18 estate = EntityState.DRAFT
19 seeds = [f"question {i}" for i in range(10_000)]
20
21 ids = []
22 for seed in seeds:
23 flexo_id = FlexOID.generate(domain, etype, estate, seed)
24 ids.append(flexo_id)
25
26 assert len(ids) == len(set(ids)), "ID collisions detected in bulk generation"
27
28 def test_disambiguator_trigger():
29 """
30 Generating the same entity twice with same inputs yields identical ID.
31 (No runtime disambiguation; IDs are deterministic by design.)
32 """
33 domain = "AF"
34 etype = EntityType.QUESTION
35 estate = EntityState.DRAFT
36 text = "identical question text"
37 id1 = FlexOID.generate(domain, etype, estate, text)
38 id2 = FlexOID.generate(domain, etype, estate, text)
39 # IDs must be identical, because we now enforce determinism, not randomization
40 assert id1 == id2
41 assert id1.signature == id2.signature
42
43def test_id_reproducibility_across_runs():
44 """
45 The same seed on a new process (fresh _seen_hashes)
46 should yield the same base ID (without suffix).
47 """
48 domain = "AF"
49 etype = EntityType.CATALOG
50 estate = EntityState.DRAFT
51 seed = "reproducibility test seed"
52 id1 = FlexOID.generate(domain, etype, estate, seed)
53 # Reset hash cache
54 FlexOID._seen_hashes.clear()
55 id2 = FlexOID.generate(domain, etype, estate, seed)
56 assert id1 == id2
57 assert id1.signature == id2.signature
58
59
60def test_version_ceiling_enforcement():
61 """Simulate approaching @999 to trigger obsolescence guard."""
62 entity = FlexoEntity("AF", EntityType.EXAM, "Final Exam 2025", EntityState.DRAFT)
63 entity.approve()
64 # artificially bump version number to near ceiling
65
66 entity.flexo_id = FlexOID.from_oid_and_version(entity.flexo_id, 998)
67
68 # 998 → 999 is allowed
69 entity.sign()
70 assert entity.flexo_id.version == 999
71
72 # 999 → 1000 should raise RuntimeError
73 with pytest.raises(RuntimeError):
74 entity.sign()
75
76
77def test_massive_lifecycle_simulation():
78 """
79 Generate 100 random entities, simulate multiple edits and state transitions,
80 ensure all final IDs and fingerprints are unique and valid.
81 """
82 import random
83 texts = [f"random question {i}" for i in range(100)]
84 entities = [FlexoEntity("AF", EntityType.QUESTION, t) for t in texts]
85
86 for e in entities:
87 # random edit, approval, signing
88 e.modify_content(e.text_seed + " updated")
89 e.approve()
90 if random.random() > 0.3:
91 e.sign()
92 if random.random() > 0.6:
93 e.publish()
94
95 ids = [e.flexo_id for e in entities]
96 fps = [e.flexo_id.signature for e in entities]
97 assert len(ids) == len(set(ids)), "Duplicate IDs after random lifecycle"
98 assert len(fps) == len(set(fps)), "Duplicate fingerprints after random lifecycle"
Note: See TracBrowser for help on using the repository browser.