| 1 | """
|
|---|
| 2 | Persistence and integrity verification tests for Flex-O entities.
|
|---|
| 3 | Ensures fingerprints survive JSON export/import and detect tampering.
|
|---|
| 4 | """
|
|---|
| 5 | import json
|
|---|
| 6 | import pytest
|
|---|
| 7 |
|
|---|
| 8 | from flexoentity import Domain
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 | @pytest.fixture
|
|---|
| 12 | def approved_domain(sample_domain):
|
|---|
| 13 | """Provide a fully approved and published Domain for persistence tests."""
|
|---|
| 14 | sample_domain.approve()
|
|---|
| 15 | sample_domain.sign()
|
|---|
| 16 | sample_domain.publish()
|
|---|
| 17 | return sample_domain
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 | def test_json_roundtrip_preserves_integrity(approved_domain):
|
|---|
| 21 | """
|
|---|
| 22 | Export to JSON and reload — ensure fingerprints and signatures remain valid.
|
|---|
| 23 | """
|
|---|
| 24 | json_str = approved_domain.to_json()
|
|---|
| 25 | loaded = Domain.from_json(json_str)
|
|---|
| 26 |
|
|---|
| 27 | # Fingerprint and state should match — integrity must pass
|
|---|
| 28 | assert Domain.verify_integrity(loaded)
|
|---|
| 29 |
|
|---|
| 30 | # Metadata should be preserved exactly
|
|---|
| 31 | assert approved_domain.fingerprint == loaded.fingerprint
|
|---|
| 32 | assert approved_domain.flexo_id == loaded.flexo_id
|
|---|
| 33 | assert loaded.state == approved_domain.state
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 | def test_json_tampering_detection(approved_domain):
|
|---|
| 37 | """Tampering with content should invalidate fingerprint verification."""
|
|---|
| 38 | json_str = approved_domain.to_json()
|
|---|
| 39 | tampered = json.loads(json_str)
|
|---|
| 40 | tampered["content"]["fullname"] = "Tampered content injection"
|
|---|
| 41 | tampered_json = json.dumps(tampered)
|
|---|
| 42 |
|
|---|
| 43 | loaded = Domain.from_json(tampered_json)
|
|---|
| 44 | assert not Domain.verify_integrity(loaded)
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 | def test_json_file_corruption(approved_domain, tmp_path):
|
|---|
| 48 | """Simulate file corruption — integrity check must fail."""
|
|---|
| 49 | file = tmp_path / "question.json"
|
|---|
| 50 | json_str = approved_domain.to_json()
|
|---|
| 51 | file.write_text(json_str)
|
|---|
| 52 |
|
|---|
| 53 | # Corrupt the file (simulate accidental byte modification)
|
|---|
| 54 | corrupted = json_str.replace("ARITHMETIC", "ARITHM")
|
|---|
| 55 | file.write_text(corrupted)
|
|---|
| 56 |
|
|---|
| 57 | loaded = Domain.from_json(file.read_text())
|
|---|
| 58 | assert not Domain.verify_integrity(loaded)
|
|---|