source: flexoentity/tests/test_id_stress.py@ 269fdc2

Last change on this file since 269fdc2 was 269fdc2, checked in by Enrico Schwass <ennoausberlin@…>, 2 months ago

adjustments to domain handling - with_domain constructor added

  • Property mode set to 100644
File size: 3.3 KB
Line 
1"""
2Stress tests for the Flex-O ID lifecycle.
3Focus: collision avoidance, version ceiling, reproducibility.
4"""
5
6import copy
7import logging
8import random
9
10import pytest
11
12from flexoentity import FlexOID, EntityType, EntityState
13
14logger = logging.getLogger(__name__)
15
16def test_bulk_generation_uniqueness(domain):
17 """
18 Generate 100,000 IDs and ensure uniqueness using safe_generate().
19 If a collision occurs, safe_generate() must resolve it automatically
20 via salt + date adjustment.
21 """
22 entity_type = EntityType.ITEM
23 estate = EntityState.DRAFT
24 seeds = [f"question {i}" for i in range(100000)]
25
26 # Simulate a simple in-memory repository for collision detection
27 repo = {}
28
29 def repo_get(oid_str):
30 return repo.get(str(oid_str))
31
32 # Generate IDs using safe_generate
33 ids = []
34 for seed in seeds:
35 oid = FlexOID.safe_generate(domain.domain_code, entity_type.value, estate.value, seed, repo=repo)
36 assert isinstance(oid, FlexOID)
37 ids.append(str(oid))
38 repo[str(oid)] = oid # register for future collision detection
39
40 unique_count = len(set(ids))
41 total_count = len(ids)
42 collisions = total_count - unique_count
43
44 logger.info(f"Generated {total_count} IDs ({collisions} collisions handled).")
45
46 # Assert that safe_generate avoided duplicates
47 assert total_count == unique_count, f"Unexpected duplicate IDs ({collisions} found)"
48
49 # Sanity check: IDs should look canonical
50 assert all(id_str.startswith("GEN") for id_str in ids)
51 assert all("@" in id_str for id_str in ids)
52
53def test_id_generation_is_deterministic(domain):
54 """
55 Generating the same entity twice with same inputs yields identical ID.
56 (No runtime disambiguation; IDs are deterministic by design.)
57 """
58 entity_type = EntityType.ITEM
59 estate = EntityState.DRAFT
60 text = "identical question text"
61
62 id1 = FlexOID.generate(domain.domain_code, entity_type.value, estate.value, text)
63 id2 = FlexOID.generate(domain.domain_code, entity_type.value, estate.value, text)
64 # IDs must be identical because generation is deterministic
65 assert id1 == id2
66
67
68# def test_id_reproducibility_across_runs(domain):
69# """
70# The same seed on a new process (fresh _seen_hashes)
71# should yield the same base ID (without suffix).
72# """
73# entity_type = EntityType.CATALOG
74# estate = EntityState.DRAFT
75# seed = "reproducibility test seed"
76
77# id1 = FlexOID.generate(domain.domain_code, entity_type.value, estate.value, seed)
78# FlexOID._seen_hashes.clear()
79# id2 = FlexOID.generate(domain.domain_code, entity_type.value, estate.value, seed)
80
81# assert id1 == id2
82
83
84def test_massive_lifecycle_simulation(sample_question):
85 """
86 Generate 100 random SingleChoiceQuestions, simulate multiple edits and state transitions,
87 ensure all final IDs and fingerprints are unique and valid.
88 """
89 entities = [
90 copy.deepcopy(sample_question) for _ in range(100)
91 ]
92
93 for i, e in enumerate(entities):
94 # random edit
95 e.text += f" updated #{i}"
96 e._update_fingerprint()
97
98 # lifecycle transitions
99 e.approve()
100 if random.random() > 0.3:
101 e.sign()
102 if random.random() > 0.6:
103 e.publish()
104
105 flexoids = [e.flexo_id for e in entities]
106 assert len(flexoids) == len(set(flexoids)), "Duplicate FlexOIDs after lifecycle simulation"
Note: See TracBrowser for help on using the repository browser.