import configparser import socket import unittest from types import SimpleNamespace from unittest import mock import psutil from scripts import local_webcam as webcam class LocalWebcamTests(unittest.TestCase): def test_config_disables_audio_recording_and_other_protocols(self): config = webcam.make_config('[hook]\non_server_started=http://remote/\n[protocol]\nenable_mp4=1\n', 'test-secret', 'http://127.0.0.1:12345/publish/test') self.assertEqual(config['general']['listen_ip'], '127.0.0.1') for name in ('enable_audio', 'add_mute_audio', 'enable_mp4', 'enable_hls', 'enable_hls_fmp4'): self.assertEqual(config['protocol'][name], '0') for section in ('rtc', 'rtp_proxy', 'srt', 'shell', 'onvif'): self.assertEqual(config[section]['port'], '0') self.assertNotIn('on_server_started', config['hook']) self.assertEqual(config['rtsp']['rtpTransportType'], '0') self.assertEqual(config['ffmpeg']['bin'], '') def test_command_is_video_only_and_fixed_loopback_destination(self): command = webcam.capture_command('ffmpeg.exe') self.assertIn('-an', command) self.assertEqual(command[command.index('-i') + 1], 'video=Integrated Camera') self.assertEqual(command[command.index('-map') + 1], '0:v:0') self.assertEqual(command[-1], 'rtmp://127.0.0.1:10935/live/laptop_cam') self.assertNotIn('audio=', ' '.join(command)) def test_publish_gate_rejects_other_streams_and_remote_publishers(self): data = {'app': 'live', 'stream': 'laptop_cam', 'schema': 'rtmp', 'ip': '127.0.0.1'} self.assertTrue(webcam.allowed_publish(data)) for key, value in [('stream', 'other'), ('ip', '192.168.1.2'), ('app', 'rtp'), ('schema', 'rtsp')]: self.assertFalse(webcam.allowed_publish({**data, key: value})) def test_network_guard_rejects_exposure_udp_and_outbound_connections(self): proc = mock.Mock() local = SimpleNamespace(ip='127.0.0.1', port=10935) good = SimpleNamespace(type=socket.SOCK_STREAM, laddr=local, raddr=(), status=psutil.CONN_LISTEN) proc.connections.return_value = [good] self.assertEqual(webcam.check_connections([proc], {10935}), {10935}) proc.connections.return_value = [SimpleNamespace( type=socket.SOCK_STREAM, laddr=SimpleNamespace(ip='::1', port=60001), raddr=SimpleNamespace(ip='::1', port=60002), status=psutil.CONN_ESTABLISHED)] self.assertEqual(webcam.check_connections([proc], {10935}), set()) for bad in [dict(type=socket.SOCK_DGRAM), dict(laddr=SimpleNamespace(ip='0.0.0.0', port=10935)), dict(raddr=SimpleNamespace(ip='8.8.8.8', port=443))]: proc.connections.return_value = [SimpleNamespace(**{**vars(good), **bad})] with self.assertRaises(RuntimeError): webcam.check_connections([proc], {10935}) def test_webcam_does_not_bootstrap_full_service_manager(self): source = webcam.SCRIPT.read_text(encoding='utf-8') self.assertNotIn('get_service_manager().start()', source) self.assertNotIn('shell=True', source) self.assertIn('ServiceLeaderLock()', source)