source: flexoentity/tests/test_persistance_integrity.py@ 37b5d11

Last change on this file since 37b5d11 was 02d288d, checked in by Enrico Schwass <ennoausberlin@…>, 3 months ago

improve hash generation and collision handler - move signature from FlexOID to FlexoEntity

  • Property mode set to 100644
File size: 3.3 KB
RevLine 
[59342ce]1"""
2Persistence and integrity verification tests for Flex-O entities.
3Ensures fingerprints survive JSON export/import and detect tampering.
4"""
5import json
6import pytest
7
[02d288d]8from flexoentity import EntityState
9from builder.questions import RadioQuestion, AnswerOption
[59342ce]10
11
[8a238e2]12# ──────────────────────────────────────────────────────────────────────────────
[59342ce]13@pytest.fixture
[02d288d]14def approved_question(domain):
15 """Provide a fully approved and published RadioQuestion for persistence tests."""
16 q = RadioQuestion(
17 domain=domain,
18 etype=None, # RadioQuestion sets this internally to EntityType.QUESTION
[59342ce]19 state=EntityState.DRAFT,
[02d288d]20 text="What is Ohm’s law?",
21 options=[
22 AnswerOption(text="U = R × I", points=1),
23 AnswerOption(text="U = I / R", points=0),
24 AnswerOption(text="R = U × I", points=0),
25 ],
[59342ce]26 )
[02d288d]27 q.approve()
28 q.sign()
29 q.publish()
30 return q
[59342ce]31
[02d288d]32
33@pytest.mark.skip(reason="FlexOIDs regenerated on import; enable once JSON format is stable")
34def test_json_roundtrip_preserves_integrity(approved_question):
[59342ce]35 """
[02d288d]36 Export to JSON and reload — ensure fingerprints and signatures remain valid.
[59342ce]37 """
[02d288d]38 json_str = approved_question.to_json()
39 loaded = RadioQuestion.from_json(json_str)
[59342ce]40
[8a238e2]41 # Fingerprint and state should match — integrity must pass
[02d288d]42 assert RadioQuestion.verify_integrity(loaded)
[59342ce]43
[8a238e2]44 # Metadata should be preserved exactly
[02d288d]45 assert approved_question.signature == loaded.signature
46 assert approved_question.flexo_id == loaded.flexo_id
47 assert loaded.state == approved_question.state
48
[59342ce]49
[8a238e2]50# ──────────────────────────────────────────────────────────────────────────────
[59342ce]51
[02d288d]52@pytest.mark.skip(reason="FlexOIDs regenerated on import; tampering detection not yet implemented")
53def test_json_tampering_detection(approved_question):
[59342ce]54 """Tampering with content should invalidate fingerprint verification."""
[02d288d]55 json_str = approved_question.to_json()
56 tampered = json.loads(json_str)
57 tampered["text"] = "Tampered content injection"
58 tampered_json = json.dumps(tampered)
[59342ce]59
[02d288d]60 loaded = RadioQuestion.from_json(tampered_json)
61 assert not RadioQuestion.verify_integrity(loaded)
[8a238e2]62
63
64# ──────────────────────────────────────────────────────────────────────────────
65
66@pytest.mark.skip(reason="FlexOIDs regenerated on import; corruption detection not yet applicable")
[02d288d]67def test_json_file_corruption(approved_question, tmp_path):
[59342ce]68 """Simulate file corruption — integrity check must fail."""
[02d288d]69 file = tmp_path / "question.json"
70 json_str = approved_question.to_json()
[59342ce]71 file.write_text(json_str)
72
[02d288d]73 # Corrupt the file (simulate accidental byte modification)
[59342ce]74 corrupted = json_str.replace("Ohm’s", "Omm’s")
75 file.write_text(corrupted)
76
[02d288d]77 loaded = RadioQuestion.from_json(file.read_text())
78 assert not RadioQuestion.verify_integrity(loaded)
Note: See TracBrowser for help on using the repository browser.