| [59342ce] | 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 |
|
|---|
| [ef964d8] | 8 | from flexoentity import Domain
|
|---|
| 9 |
|
|---|
| [59342ce] | 10 |
|
|---|
| 11 | @pytest.fixture
|
|---|
| [ef964d8] | 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
|
|---|
| [59342ce] | 18 |
|
|---|
| [02d288d] | 19 |
|
|---|
| [ef964d8] | 20 | def test_json_roundtrip_preserves_integrity(approved_domain):
|
|---|
| [59342ce] | 21 | """
|
|---|
| [02d288d] | 22 | Export to JSON and reload — ensure fingerprints and signatures remain valid.
|
|---|
| [59342ce] | 23 | """
|
|---|
| [ef964d8] | 24 | json_str = approved_domain.to_json()
|
|---|
| 25 | loaded = Domain.from_json(json_str)
|
|---|
| [59342ce] | 26 |
|
|---|
| [8a238e2] | 27 | # Fingerprint and state should match — integrity must pass
|
|---|
| [ef964d8] | 28 | assert Domain.verify_integrity(loaded)
|
|---|
| [59342ce] | 29 |
|
|---|
| [8a238e2] | 30 | # Metadata should be preserved exactly
|
|---|
| [ef964d8] | 31 | assert approved_domain.fingerprint == loaded.fingerprint
|
|---|
| 32 | assert approved_domain.flexo_id == loaded.flexo_id
|
|---|
| 33 | assert loaded.state == approved_domain.state
|
|---|
| 34 |
|
|---|
| [02d288d] | 35 |
|
|---|
| [ef964d8] | 36 | def test_json_tampering_detection(approved_domain):
|
|---|
| [59342ce] | 37 | """Tampering with content should invalidate fingerprint verification."""
|
|---|
| [ef964d8] | 38 | json_str = approved_domain.to_json()
|
|---|
| [02d288d] | 39 | tampered = json.loads(json_str)
|
|---|
| [ef964d8] | 40 | tampered["content"]["fullname"] = "Tampered content injection"
|
|---|
| [02d288d] | 41 | tampered_json = json.dumps(tampered)
|
|---|
| [59342ce] | 42 |
|
|---|
| [ef964d8] | 43 | loaded = Domain.from_json(tampered_json)
|
|---|
| 44 | assert not Domain.verify_integrity(loaded)
|
|---|
| 45 |
|
|---|
| [8a238e2] | 46 |
|
|---|
| [ef964d8] | 47 | def test_json_file_corruption(approved_domain, tmp_path):
|
|---|
| [59342ce] | 48 | """Simulate file corruption — integrity check must fail."""
|
|---|
| [02d288d] | 49 | file = tmp_path / "question.json"
|
|---|
| [ef964d8] | 50 | json_str = approved_domain.to_json()
|
|---|
| 51 | print("JSON", json_str)
|
|---|
| [59342ce] | 52 | file.write_text(json_str)
|
|---|
| 53 |
|
|---|
| [02d288d] | 54 | # Corrupt the file (simulate accidental byte modification)
|
|---|
| [ef964d8] | 55 | corrupted = json_str.replace("ARITHMETIC", "ARITHM")
|
|---|
| [59342ce] | 56 | file.write_text(corrupted)
|
|---|
| 57 |
|
|---|
| [ef964d8] | 58 | loaded = Domain.from_json(file.read_text())
|
|---|
| 59 | assert not Domain.verify_integrity(loaded)
|
|---|