| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- """Bootstrap sequencing with a fake uv; no installs, downloads or services."""
- import json
- import os
- from pathlib import Path
- import shutil
- import subprocess
- import tempfile
- import unittest
- from unittest.mock import patch
- from scripts import download_model
- ROOT = Path(__file__).resolve().parents[1]
- BASH = shutil.which('bash') or ('C:/Program Files/Git/bin/bash.exe' if Path('C:/Program Files/Git/bin/bash.exe').exists() else None)
- @unittest.skipUnless(BASH, 'bash is unavailable')
- class BootstrapTests(unittest.TestCase):
- def run_script(self, action, fail='', env_exists=True, args=()):
- with tempfile.TemporaryDirectory() as tmp:
- root=Path(tmp)
- shutil.copy2(ROOT/'deploy.sh',root/'deploy.sh')
- (root/'.env.example').write_text('EXAMPLE=1\n')
- if env_exists: (root/'.env').write_text('KEEP=unchanged\n')
- bin_dir=root/'bin'; bin_dir.mkdir()
- fake=bin_dir/'uv'
- fake.write_text('#!/bin/sh\nprintf "%s\\n" "$*" >> "$CALL_LOG"\ncase "$*" in *"$FAIL_MATCH"*) if [ -n "$FAIL_MATCH" ]; then exit 9; fi ;; esac\n')
- fake.chmod(0o755)
- env={**os.environ,'PATH':str(bin_dir)+os.pathsep+os.environ['PATH'],'CALL_LOG':str(root/'calls.log'),'FAIL_MATCH':fail}
- result=subprocess.run([BASH,str(root/'deploy.sh'),action,*args],env=env,capture_output=True,text=True)
- calls=(root/'calls.log').read_text() if (root/'calls.log').exists() else ''
- return result.returncode,calls,(root/'.env').read_text()
- def test_templates_and_dms_bootstrap_then_deploy(self):
- for action in ('templates','dms','start'):
- code,calls,env=self.run_script(action)
- self.assertEqual(code,0,calls)
- self.assertLess(calls.index('python install'),calls.index('sync --frozen'))
- self.assertLess(calls.index('sync --frozen'),calls.index('download_model.py'))
- lines=calls.splitlines()
- self.assertTrue(lines[-1].endswith('scripts/start_service.py'))
- if action == 'start':
- self.assertNotIn('update_data.py',calls)
- else:
- self.assertIn('update_data.py --mode '+action,lines[-2])
- self.assertLess(calls.index('download_model.py'),calls.index('update_data.py'))
- self.assertEqual(env,'KEEP=unchanged\n')
- def test_restart_starts_with_restart_flag_without_data_update(self):
- code,calls,_=self.run_script('restart')
- self.assertEqual(code,0)
- self.assertNotIn('update_data.py',calls)
- self.assertTrue(calls.splitlines()[-1].endswith('start_service.py --restart'))
- def test_setup_never_runs_business_deployment(self):
- code,calls,_=self.run_script('setup')
- self.assertEqual(code,0)
- self.assertIn('download_model.py',calls)
- self.assertNotIn('update_data.py',calls)
- self.assertNotIn('start_service.py',calls)
- def test_environment_and_download_failures_stop_pipeline(self):
- for failure in ('sync --frozen','download_model.py'):
- code,calls,_=self.run_script('templates',failure)
- self.assertEqual(code,9)
- self.assertNotIn('update_data.py',calls)
- self.assertNotIn('scripts/start_service.py\n',calls)
- def test_update_failure_prevents_start(self):
- for action in ('templates','dms'):
- code,calls,_=self.run_script(action,'update_data.py')
- self.assertEqual(code,9)
- self.assertIn('update_data.py --mode '+action,calls)
- self.assertNotIn('scripts/start_service.py\n',calls)
- def test_start_failure_and_arguments(self):
- code,calls,_=self.run_script('start',args=('--host','127.0.0.1','--port','8123'))
- self.assertEqual(code,0)
- self.assertTrue(calls.splitlines()[-1].endswith('start_service.py --host 127.0.0.1 --port 8123'))
- code,_,_=self.run_script('start','start_service.py --host',args=('--host','127.0.0.1'))
- self.assertEqual(code,9)
- def test_invalid_config_prevents_model_and_update(self):
- code,calls,_=self.run_script('templates','--check-config')
- self.assertEqual(code,9)
- self.assertNotIn('download_model.py',calls)
- self.assertNotIn('update_data.py',calls)
- def test_missing_env_is_created_without_business_update(self):
- code,calls,env=self.run_script('templates',env_exists=False)
- self.assertEqual(code,2)
- self.assertEqual(calls,'')
- self.assertEqual(env,'EXAMPLE=1\n')
- class ModelTests(unittest.TestCase):
- def test_incomplete_shards_do_not_count_as_ready(self):
- with tempfile.TemporaryDirectory() as tmp:
- root=Path(tmp)
- for name in ('config.json','tokenizer.json','tokenizer_config.json'):
- (root/name).write_text('{}')
- (root/'modules.json').write_text('[{"type":"sentence_transformers.models.Normalize","path":"2_Normalize"}]')
- (root/'model.safetensors.index.json').write_text(json.dumps({'weight_map':{'a':'part1','b':'part2'}}))
- (root/'part1').write_text('weight')
- self.assertFalse(download_model.model_files_ready(root))
- (root/'part2').write_text('weight')
- self.assertTrue(download_model.model_files_ready(root))
- def test_ready_model_skips_network_but_verifies_loading(self):
- with patch.object(download_model,'get_embedding_model_dir',return_value=Path('model')), patch.object(download_model,'model_files_ready',return_value=True), patch.object(download_model,'verify_model') as verify, patch.object(download_model.subprocess,'run') as run:
- download_model.ensure_model()
- run.assert_not_called()
- verify.assert_called_once()
- def test_check_only_missing_model_never_downloads(self):
- with patch.object(download_model,'get_embedding_model_dir',return_value=Path('model')), patch.object(download_model,'model_files_ready',return_value=False), patch.object(download_model.subprocess,'run') as run:
- with self.assertRaises(RuntimeError): download_model.ensure_model(check_only=True)
- run.assert_not_called()
- if __name__=='__main__': unittest.main()
|