source: flexoentity/tests/test_id_stress.py@ d825c6b

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

another round of domain refactoring

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