import io,tempfile,unittest,wave from pathlib import Path from unittest.mock import Mock,patch from voxcpm_test import VoxCPMTests,validate_reference class VoiceTests(unittest.TestCase): def test_reference_limits(self): for data in (b'',b'not audio',b'x'*(8*1024**2+1)): with self.assertRaises(ValueError):validate_reference(data) def wav(seconds): b=io.BytesIO() with wave.open(b,'wb') as w:w.setnchannels(1);w.setsampwidth(2);w.setframerate(16000);w.writeframes(b'\0\0'*int(seconds*16000)) return b.getvalue() validate_reference(wav(2)) with self.assertRaises(ValueError):validate_reference(wav(31)) def test_not_installed_and_components_reported_separately(self): profiles=Mock();profiles._component.side_effect=ValueError('missing');runtime=Mock();runtime.status.return_value={'installed':False} t=VoxCPMTests('/tmp/no-voice',profiles,runtime);p=dict(model=dict(kind='voice',repo='openbmb/VoxCPM2',file='model.safetensors'),components={}) self.assertEqual(len(t.blockers(p)),6) runtime.status.return_value={'installed':True};self.assertEqual(len(t.blockers(p)),5) def test_missing_gpu_releases_reservation_and_records_failure(self): with tempfile.TemporaryDirectory() as d: p=dict(id='test',model=dict(kind='voice',repo='openbmb/VoxCPM2',file='model.safetensors'),components={}) profiles=Mock();profiles.status.return_value={'profiles':[p]};runtime=Mock();runtime.status.return_value={'installed':True} t=VoxCPMTests(d,profiles,runtime);release=Mock();t.acquire=Mock(return_value=release) with patch('voxcpm_test.probe',return_value=[]): with self.assertRaisesRegex(ValueError,'VRAM'):t.start('test','synthetic test') release.assert_called_once();self.assertEqual(t.job['state'],'failed') self.assertEqual(list(Path(d).iterdir()),[]) def test_invalid_options_rejected_before_gpu_reservation(self): t=VoxCPMTests('/tmp/no-voice',Mock(),Mock());t.acquire=Mock() for args in (dict(text=''),dict(text='x',device='cpu'),dict(text='x',steps=0),dict(text='x',seed=-1)): with self.assertRaises(ValueError):t.start('id',**args) t.acquire.assert_not_called() def test_worker_completion_failure_and_cancellation_cleanup(self): for outcome in ('complete','failed','cancelled'): with tempfile.TemporaryDirectory() as d: t=VoxCPMTests(d,Mock(),Mock());ident='a'*32;t.job=dict(id=ident,state='running');t.stage=lambda p,root:(root/'model').mkdir();t.runtime.paths.return_value=(Path('/fake-python'),None) root=Path(d)/ident;release=Mock() def launch(*args,**kwargs): (root/'result.json').write_text('{"ok":false,"error":"synthetic OOM"}' if outcome=='failed' else '{"ok":true,"duration":1,"sample_rate":16000}') if outcome=='complete': with wave.open(str(root/'result.wav'),'wb') as w:w.setnchannels(1);w.setsampwidth(2);w.setframerate(16000);w.writeframes(b'\0\0'*16000) process=Mock();process.poll.return_value=0;return process if outcome=='cancelled':t.cancel.set() with patch('voxcpm_test.subprocess.Popen',side_effect=launch):t._run_voice({},ident,dict(text='synthetic'),b'reference',{'uuid':'test'},release) self.assertEqual(t.job['state'],outcome);release.assert_called_once() self.assertFalse((root/'reference.wav').exists());self.assertFalse((root/'model').exists());self.assertFalse(t.status()['loaded']) self.assertEqual((root/'complete').exists(),outcome=='complete')