source: flexoentity/tests/test_id_stress.py@ 59342ce

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

all tests green

  • Property mode set to 100644
File size: 3.4 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
29def test_disambiguator_trigger():
30 """
31 Force a deterministic collision by hashing same text twice.
32 Should produce -A suffix for second one.
33 """
34 domain = "AF"
35 etype = EntityType.QUESTION
36 estate = EntityState.DRAFT
37 text = "identical question text"
38 id1 = FlexOID.generate(domain, etype, estate, text)
39 id2 = FlexOID.generate(domain, etype, estate, text)
40 assert id1 != id2
41 assert id1.signature == id2.signature
42 assert "-A" in str(id2), f"Expected '-A' suffix in disambiguated ID, got {id2}"
43
44
45def test_id_reproducibility_across_runs():
46 """
47 The same seed on a new process (fresh _seen_hashes)
48 should yield the same base ID (without suffix).
49 """
50 domain = "AF"
51 etype = EntityType.CATALOG
52 estate = EntityState.DRAFT
53 seed = "reproducibility test seed"
54 id1 = FlexOID.generate(domain, etype, estate, seed)
55 # Reset hash cache
56 FlexOID._seen_hashes.clear()
57 id2 = FlexOID.generate(domain, etype, estate, seed)
58 assert id1 == id2
59 assert id1.signature == id2.signature
60
61
62def test_version_ceiling_enforcement():
63 """Simulate approaching @999 to trigger obsolescence guard."""
64 entity = FlexoEntity("AF", EntityType.EXAM, "Final Exam 2025", EntityState.DRAFT)
65 entity.approve()
66 # artificially bump version number to near ceiling
67
68 entity.flexo_id = FlexOID.from_oid_and_version(entity.flexo_id, 998)
69
70 # 998 → 999 is allowed
71 entity.sign()
72 assert entity.flexo_id.version == 999
73
74 # 999 → 1000 should raise RuntimeError
75 with pytest.raises(RuntimeError):
76 entity.sign()
77
78
79def test_massive_lifecycle_simulation():
80 """
81 Generate 100 random entities, simulate multiple edits and state transitions,
82 ensure all final IDs and fingerprints are unique and valid.
83 """
84 import random
85 texts = [f"random question {i}" for i in range(100)]
86 entities = [FlexoEntity("AF", EntityType.QUESTION, t) for t in texts]
87
88 for e in entities:
89 # random edit, approval, signing
90 e.modify_content(e.text_seed + " updated")
91 e.approve()
92 if random.random() > 0.3:
93 e.sign()
94 if random.random() > 0.6:
95 e.publish()
96
97 ids = [e.flexo_id for e in entities]
98 fps = [e.flexo_id.signature for e in entities]
99 assert len(ids) == len(set(ids)), "Duplicate IDs after random lifecycle"
100 assert len(fps) == len(set(fps)), "Duplicate fingerprints after random lifecycle"
Note: See TracBrowser for help on using the repository browser.