79 lines
3.9 KiB
Python
79 lines
3.9 KiB
Python
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
from scripts import local_server as server
|
|
|
|
|
|
class LocalServerTests(unittest.TestCase):
|
|
def test_environment_overrides_unsafe_inherited_values(self):
|
|
with mock.patch.dict('os.environ', {
|
|
'MONITOR_BOOTSTRAP_SERVICES': 'true', 'MONITOR_SERVICE_MODE': 'embedded',
|
|
'MONITOR_ALLOWED_HOSTS': '*', 'MONITOR_HTTPS': 'true',
|
|
'IMAGEIO_FFMPEG_EXE': 'C:/unrelated/ffmpeg.exe',
|
|
}):
|
|
env = server.local_environment()
|
|
self.assertEqual(env['MONITOR_BOOTSTRAP_SERVICES'], 'false')
|
|
self.assertEqual(env['MONITOR_SERVICE_MODE'], 'disabled')
|
|
self.assertEqual(env['MONITOR_ALLOWED_HOSTS'], '127.0.0.1,localhost')
|
|
self.assertEqual(env['MONITOR_HTTPS'], 'false')
|
|
self.assertEqual(env['MONITOR_TELEMETRY_ENDPOINT'], '')
|
|
self.assertEqual(env['YOLO_OFFLINE'], 'true')
|
|
self.assertEqual(env['YOLO_AUTOINSTALL'], 'false')
|
|
self.assertEqual(env['CI'], 'true')
|
|
self.assertTrue(Path(env['MONITOR_FFMPEG']).is_relative_to(server.ROOT / '.venv'))
|
|
|
|
def test_only_exact_project_runserver_command_is_owned(self):
|
|
proc = mock.Mock()
|
|
args = [str(server.PYTHON), str(server.MANAGE), 'runserver', '127.0.0.1:10001', '--noreload']
|
|
proc.cmdline.return_value = args
|
|
self.assertTrue(server.is_project_process(proc))
|
|
proc.cmdline.return_value = args[:3] + ['0.0.0.0:10001', '--noreload']
|
|
self.assertFalse(server.is_project_process(proc))
|
|
proc.cmdline.return_value = args[:1] + ['C:/another/manage.py'] + args[2:]
|
|
self.assertFalse(server.is_project_process(proc))
|
|
|
|
def test_busy_port_does_not_launch_or_stop_anything(self):
|
|
with mock.patch.object(server, 'recorded_process', return_value=None), \
|
|
mock.patch.object(server, 'port_open', return_value=True), \
|
|
mock.patch.object(server, 'discover_project_listener', return_value=None), \
|
|
mock.patch.object(server, 'backup') as backup, \
|
|
mock.patch.object(server.subprocess, 'Popen') as popen:
|
|
with self.assertRaises(RuntimeError):
|
|
server.start()
|
|
backup.assert_not_called()
|
|
popen.assert_not_called()
|
|
|
|
def test_existing_owned_server_is_reused(self):
|
|
with mock.patch.object(server, 'recorded_process', return_value=mock.Mock(pid=123)), \
|
|
mock.patch.object(server, 'port_open', return_value=True), \
|
|
mock.patch.object(server.subprocess, 'Popen') as popen:
|
|
server.start()
|
|
popen.assert_not_called()
|
|
|
|
def test_pid_reuse_is_not_treated_as_owned(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
path = Path(temp) / 'pid.json'
|
|
path.write_text(json.dumps({'pid': 123, 'create_time': 1, 'root': str(server.ROOT)}))
|
|
proc = mock.Mock()
|
|
proc.create_time.return_value = 2
|
|
with mock.patch.object(server, 'PID_FILE', path), \
|
|
mock.patch.object(server.psutil, 'Process', return_value=proc):
|
|
self.assertIsNone(server.recorded_process())
|
|
proc.terminate.assert_not_called()
|
|
|
|
def test_foreign_command_is_not_stopped(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
path = Path(temp) / 'pid.json'
|
|
path.write_text(json.dumps({'pid': 123, 'create_time': 1, 'root': str(server.ROOT)}))
|
|
proc = mock.Mock()
|
|
proc.create_time.return_value = 1
|
|
proc.cmdline.return_value = ['C:/foreign/python.exe', 'other.py']
|
|
with mock.patch.object(server, 'PID_FILE', path), \
|
|
mock.patch.object(server.psutil, 'Process', return_value=proc):
|
|
with self.assertRaises(RuntimeError):
|
|
server.stop()
|
|
proc.terminate.assert_not_called()
|