| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- """Offline release selection and integrity tests with synthetic files only."""
- import json
- from pathlib import Path
- import shutil
- import subprocess
- import sys
- import tempfile
- import unittest
- import zipfile
- from scripts import offline_release
- class OfflineReleaseTests(unittest.TestCase):
- def setUp(self):
- temporary = tempfile.TemporaryDirectory()
- self.addCleanup(temporary.cleanup)
- self.root = Path(temporary.name)
- subprocess.run(['git', 'init', '-q'], cwd=self.root, check=True, capture_output=True)
- (self.root / '.gitignore').write_text('.env\nmodels/\nknowledge/prepared/\noutput/\n')
- (self.root / '.env').write_text('SYNTHETIC_SECRET=never_package\n')
- (self.root / 'src').mkdir()
- (self.root / 'src/app.py').write_text('print("synthetic")\n')
- (self.root / 'config').mkdir()
- (self.root / 'config/dms_schema.json').write_text('{"synthetic":true}')
- (self.root / 'scripts').mkdir()
- for name in ('offline_release.py', 'offline_release_bootstrap.py'):
- shutil.copyfile(Path(offline_release.__file__).parent / name, self.root / 'scripts' / name)
- self.snapshot = self.root / 'output/source.zip'
- self.snapshot.parent.mkdir()
- self.snapshot.write_bytes(b'synthetic knowledge snapshot')
- (self.root / 'models/bge-large-zh-v1.5').mkdir(parents=True)
- (self.root / 'models/bge-large-zh-v1.5/model.bin').write_bytes(b'synthetic model')
- (self.root / 'models/deepseek-tokenizer').mkdir(parents=True)
- (self.root / offline_release.TOKENIZER_TARGET).write_bytes(b'synthetic tokenizer')
- manifest = self.root / 'knowledge/prepared/ingestion/manifest.json'
- manifest.parent.mkdir(parents=True)
- manifest.write_text(json.dumps({'complete': True, 'model_files': {'model.bin': 'synthetic'}}))
- self.bundle = self.root / 'release.zip'
- def test_one_archive_contains_code_knowledge_and_required_models_only(self):
- offline_release.pack(self.root, self.snapshot, self.bundle)
- self.assertEqual(offline_release.verify(self.bundle)['files'], 10)
- runnable = subprocess.run([sys.executable, str(self.bundle), 'verify', str(self.bundle)],
- capture_output=True, text=True, check=True)
- self.assertTrue(json.loads(runnable.stdout)['ok'])
- with zipfile.ZipFile(self.bundle) as archive:
- names = set(archive.namelist())
- self.assertIn('src/app.py', names)
- self.assertIn('__main__.py', names)
- self.assertIn(offline_release.SNAPSHOT_TARGET, names)
- self.assertIn('models/bge-large-zh-v1.5/model.bin', names)
- self.assertIn(offline_release.TOKENIZER_TARGET, names)
- self.assertIn('.env', names)
- self.assertIn('config/dms_schema.json', names)
- self.assertNotIn('knowledge/prepared/ingestion/manifest.json', names)
- target = self.root / 'server'
- offline_release.extract(self.bundle, target)
- self.assertEqual((target / offline_release.SNAPSHOT_TARGET).read_bytes(), self.snapshot.read_bytes())
- self.assertEqual((target / '.env').read_text(), 'SYNTHETIC_SECRET=never_package\n')
- with self.assertRaisesRegex(ValueError, 'release_target_not_empty'):
- offline_release.extract(self.bundle, target)
- def test_rejects_archive_with_extra_file(self):
- offline_release.pack(self.root, self.snapshot, self.bundle)
- with zipfile.ZipFile(self.bundle, 'a') as archive:
- archive.writestr('unexpected.txt', 'extra')
- with self.assertRaisesRegex(ValueError, 'unexpected_release_members'):
- offline_release.verify(self.bundle)
- def test_missing_model_and_existing_output_fail(self):
- (self.root / 'models/bge-large-zh-v1.5/model.bin').unlink()
- with self.assertRaisesRegex(ValueError, 'missing_release_file'):
- offline_release.pack(self.root, self.snapshot, self.bundle)
- (self.root / 'models/bge-large-zh-v1.5/model.bin').write_bytes(b'synthetic model')
- offline_release.pack(self.root, self.snapshot, self.bundle)
- with self.assertRaisesRegex(ValueError, 'release_already_exists'):
- offline_release.pack(self.root, self.snapshot, self.bundle)
- def test_missing_dms_schema_fails(self):
- (self.root / 'config/dms_schema.json').unlink()
- with self.assertRaisesRegex(ValueError, 'missing_release_file'):
- offline_release.pack(self.root, self.snapshot, self.bundle)
|