source: flexoentity/tests/test_id_stress.py@ 223c9d5

main unify_backends
Last change on this file since 223c9d5 was 5c72356, checked in by Enrico Schwass <ennoausberlin@…>, 4 months ago

fix tests due to simplifying state and type

  • Property mode set to 100644
File size: 3.3 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
[02d288d]16def test_bulk_generation_uniqueness(domain):
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:
[8aa20c7]35 oid = FlexOID.safe_generate(domain.domain, entity_type.value, estate.value, seed, repo=repo)
[02d288d]36 assert isinstance(oid, FlexOID)
37 ids.append(str(oid))
38 repo[str(oid)] = oid # register for future collision detection
[59342ce]39
[02d288d]40 unique_count = len(set(ids))
41 total_count = len(ids)
42 collisions = total_count - unique_count
[59342ce]43
[02d288d]44 logger.info(f"Generated {total_count} IDs ({collisions} collisions handled).")
[8a238e2]45
[02d288d]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
[8aa20c7]50 assert all(id_str.startswith("GEN") for id_str in ids)
[02d288d]51 assert all("@" in id_str for id_str in ids)
52
53def test_id_generation_is_deterministic(domain):
[8a238e2]54 """
55 Generating the same entity twice with same inputs yields identical ID.
56 (No runtime disambiguation; IDs are deterministic by design.)
57 """
[8aa20c7]58 entity_type = EntityType.ITEM
[8a238e2]59 estate = EntityState.DRAFT
60 text = "identical question text"
[02d288d]61
[8aa20c7]62 id1 = FlexOID.generate(domain.domain, entity_type.value, estate.value, text)
63 id2 = FlexOID.generate(domain.domain, entity_type.value, estate.value, text)
[02d288d]64 # IDs must be identical because generation is deterministic
[8a238e2]65 assert id1 == id2
66
67
[8aa20c7]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"
[02d288d]76
[8aa20c7]77# id1 = FlexOID.generate(domain.domain, entity_type.value, estate.value, seed)
78# FlexOID._seen_hashes.clear()
79# id2 = FlexOID.generate(domain.domain, entity_type.value, estate.value, seed)
[02d288d]80
[8aa20c7]81# assert id1 == id2
[59342ce]82
83
[8aa20c7]84def test_massive_lifecycle_simulation(sample_question):
[59342ce]85 """
[8aa20c7]86 Generate 100 random SingleChoiceQuestions, simulate multiple edits and state transitions,
[59342ce]87 ensure all final IDs and fingerprints are unique and valid.
88 """
[02d288d]89 entities = [
[8aa20c7]90 copy.deepcopy(sample_question) for _ in range(100)
[02d288d]91 ]
[59342ce]92
[8aa20c7]93 for i, e in enumerate(entities):
[02d288d]94 # random edit
[8aa20c7]95 e.text += f" updated #{i}"
[8a238e2]96 e._update_fingerprint()
[02d288d]97
98 # lifecycle transitions
[59342ce]99 e.approve()
100 if random.random() > 0.3:
101 e.sign()
102 if random.random() > 0.6:
103 e.publish()
104
[02d288d]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.