Files
go-sip/contracts/test_verify.py
T

100 lines
4.6 KiB
Python

import json
from pathlib import Path
import re
import shutil
import tempfile
import unittest
from verify import verify_bundle
class ContractVerificationTest(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name) / 'contracts'
source = Path(__file__).parent
self.root.mkdir()
for name in ('schema', 'archive', 'examples'):
shutil.copytree(source / name, self.root / name,
ignore=shutil.ignore_patterns('.git', '__pycache__'))
shutil.copyfile(source / 'manifest.json', self.root / 'manifest.json')
def test_current_bundle(self):
verify_bundle(self.root)
def test_changed_schema_requires_manifest_update(self):
path = self.root / 'schema/http-sip.schema.json'
path.write_text(path.read_text() + '\n')
with self.assertRaisesRegex(ValueError, 'bundle hash mismatch'):
verify_bundle(self.root)
def test_missing_schema_reference_is_rejected_even_with_updated_hash(self):
path = self.root / 'schema/config-read.schema.json'
data = json.loads(path.read_text())
data['oneOf'][0]['$ref'] = './missing.schema.json#'
path.write_text(json.dumps(data))
with self.assertRaisesRegex(ValueError, 'missing schema reference'):
verify_bundle(self.root, write=True)
def test_invalid_pointer_is_rejected(self):
path = self.root / 'schema/config-read.schema.json'
data = json.loads(path.read_text())
data['oneOf'][0]['$ref'] = './http-sip.schema.json#/$defs/missing'
path.write_text(json.dumps(data))
with self.assertRaisesRegex(ValueError, 'invalid schema pointer'):
verify_bundle(self.root, write=True)
def test_archived_source_is_not_rehashed(self):
path = next((self.root / 'archive/sources').glob('*.md'))
path.write_text(path.read_text() + '\n')
with self.assertRaisesRegex(ValueError, 'source hash mismatch'):
verify_bundle(self.root, write=True)
def test_changed_business_document_requires_manifest_update(self):
path = self.root / 'schema/saas-dispatcher.md'
path.write_text(path.read_text() + '\n')
with self.assertRaisesRegex(ValueError, 'source hash mismatch'):
verify_bundle(self.root)
verify_bundle(self.root, write=True)
verify_bundle(self.root)
def test_shared_directory_contains_only_integration_files(self):
shared = self.root / 'schema'
allowed = {'README.md', 'saas-dispatcher.md', 'mq-topology.json', 'examples'}
for path in shared.iterdir():
if path.name not in allowed and not path.name.endswith('.schema.json'):
self.fail(f'non-integration file in shared repository: {path.name}')
self.assertFalse((shared / 'examples/invalid').exists())
self.assertTrue((self.root / 'examples/invalid').is_dir())
def test_readme_separates_schemas_examples_and_reference_links(self):
shared = self.root / 'schema'
readme = (shared / 'README.md').read_text()
introduction, schemas, examples = re.split(
r'^## (?:Schema 契约|Examples)\n', readme, flags=re.MULTILINE)
self.assertNotIn('|', introduction)
self.assertEqual(set(re.findall(r'\]\(([^)]+)\)', introduction)),
{'saas-dispatcher.md', 'mq-topology.json'})
for section, expected in (
(schemas, {p.name for p in shared.glob('*.schema.json')}),
(examples, {p.relative_to(shared).as_posix()
for p in (shared / 'examples').glob('*.json')})):
rows = section.strip().splitlines()
self.assertEqual(rows[:2], ['| 文件 | 作用 |', '| --- | --- |'])
self.assertTrue(all(re.fullmatch(
r'\| \[`[^`]+`\]\([^)]+\) \| .+ \|', row) for row in rows[2:]))
links = re.findall(r'\[`([^`]+)`\]\(([^)]+)\)', section)
self.assertTrue(all(label == target for label, target in links))
self.assertEqual(len(links), len(expected), 'duplicate or missing file rows')
self.assertEqual({target for _, target in links}, expected)
links = re.findall(r'\]\(([^)]+)\)', readme)
expected = {p.relative_to(shared).as_posix() for p in shared.rglob('*')
if p.is_file() and p.name not in {'.git', 'README.md'}}
self.assertEqual(len(links), len(set(links)), 'duplicate file links')
self.assertEqual(set(links), expected)
if __name__ == '__main__':
unittest.main()