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_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()