Files
go-sip/scripts/test_contract_checkout.py
T

86 lines
3.8 KiB
Python

import importlib.util
from pathlib import Path
import subprocess
import tempfile
import unittest
spec = importlib.util.spec_from_file_location('contract_checker', Path(__file__).with_name('check-current-contracts.py'))
checker = importlib.util.module_from_spec(spec)
spec.loader.exec_module(checker)
URL = 'git@gitee.com:zzmbac/sip-contracts.git'
class ContractCheckoutTest(unittest.TestCase):
def git(self, cwd, *args):
return subprocess.check_output(['git', '-c', 'user.name=Contract Test', '-c', 'user.email=contracts@example.invalid', '-C', str(cwd), *args], stderr=subprocess.STDOUT, text=True).strip()
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
base = Path(self.temp.name)
source = base / 'source'
source.mkdir()
self.git(source, 'init', '-q')
(source / 'test.schema.json').write_text('{}\n')
self.git(source, 'add', '.')
self.git(source, 'commit', '-qm', 'initial')
self.root = base / 'consumer'
self.root.mkdir()
self.git(self.root, 'init', '-q')
self.git(self.root, '-c', 'protocol.file.allow=always', 'submodule', 'add', '-q', str(source), 'contracts/schema')
self.sub = self.root / 'contracts/schema'
self.git(self.sub, 'remote', 'set-url', 'origin', URL)
self.git(self.root, 'config', '-f', '.gitmodules', 'submodule.contracts/schema.url', URL)
self.git(self.root, 'add', '.')
self.git(self.root, 'commit', '-qm', 'pin contract')
def test_clean_pinned_checkout(self):
self.assertEqual(checker.check_checkout(self.root), self.git(self.sub, 'rev-parse', 'HEAD'))
def test_uninitialized_submodule_is_rejected(self):
self.git(self.root, 'submodule', 'deinit', '-f', '--', 'contracts/schema')
with self.assertRaisesRegex(ValueError, 'not initialized'):
checker.check_checkout(self.root)
def test_unpinned_commit_is_rejected(self):
(self.sub / 'test.schema.json').write_text('{"changed": true}\n')
self.git(self.sub, 'add', '.')
self.git(self.sub, 'commit', '-qm', 'changed')
with self.assertRaisesRegex(ValueError, 'does not match'):
checker.check_checkout(self.root)
def test_update_rechecks_an_unstaged_fast_forward(self):
(self.sub / 'test.schema.json').write_text('{"changed": true}\n')
self.git(self.sub, 'add', '.')
self.git(self.sub, 'commit', '-qm', 'changed')
self.assertEqual(checker.check_checkout(self.root, updating=True), self.git(self.sub, 'rev-parse', 'HEAD'))
(self.sub / 'untracked.txt').write_text('unexpected\n')
with self.assertRaisesRegex(ValueError, 'uncommitted'):
checker.check_checkout(self.root, updating=True)
def test_update_rejects_divergent_contract_history(self):
self.git(self.sub, 'checkout', '--orphan', 'unrelated')
self.git(self.sub, 'add', '.')
self.git(self.sub, 'commit', '-qm', 'unrelated root')
with self.assertRaises(subprocess.CalledProcessError):
checker.check_checkout(self.root, updating=True)
def test_dirty_submodule_is_rejected(self):
(self.sub / 'untracked.txt').write_text('unexpected\n')
with self.assertRaisesRegex(ValueError, 'uncommitted'):
checker.check_checkout(self.root)
def test_wrong_origin_is_rejected(self):
self.git(self.sub, 'remote', 'set-url', 'origin', 'https://example.invalid/other.git')
with self.assertRaisesRegex(ValueError, 'origin'):
checker.check_checkout(self.root)
def test_parallel_local_contract_is_rejected(self):
(self.root / 'contracts/local').mkdir()
with self.assertRaisesRegex(ValueError, 'parallel'):
checker.check_checkout(self.root)
if __name__ == '__main__':
unittest.main()