Ctrl K
ComunidadGuías…

tests/test_netwatch.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import os
import sys
import time
import unittest
from unittest.mock import patch

from peach.netwatch import NETWORK_CHANGE, NetworkChangeWatcher


class NetworkChangeWatcherTests(unittest.TestCase):
    def test_key_is_the_system_network_change_notification(self):
        self.assertEqual(NETWORK_CHANGE, b"com.apple.system.config.network_change")

    @unittest.skipUnless(sys.platform == "darwin", "Darwin 通知只在 macOS 上存在")
    def test_start_subscribes_and_stop_returns_promptly(self):
        """stop() 不能等到下一次网络事件才生效。

        select 只盯通知描述符的话,没有网络变化时线程会一直阻塞,退出要等到用户下次
        换网络——所以另开了一根管道专门用来叫醒它。
        """
        watcher = NetworkChangeWatcher(lambda: None)
        self.assertTrue(watcher.start())
        time.sleep(0.3)
        started = time.monotonic()
        watcher.stop()
        self.assertLess(time.monotonic() - started, 3.0)

    @unittest.skipUnless(sys.platform == "darwin", "Darwin 通知只在 macOS 上存在")
    def test_double_start_is_a_no_op(self):
        watcher = NetworkChangeWatcher(lambda: None)
        self.addCleanup(watcher.stop)
        self.assertTrue(watcher.start())
        self.assertFalse(watcher.start())

    @unittest.skipUnless(sys.platform == "darwin", "Darwin 通知只在 macOS 上存在")
    def test_a_failing_callback_does_not_kill_the_watcher(self):
        """回调挂掉不该带走整个托盘。"""
        calls = []
        notify_read, notify_write = os.pipe()
        self.addCleanup(os.close, notify_read)
        self.addCleanup(os.close, notify_write)

        class FakeLibSystem:
            @staticmethod
            def notify_register_file_descriptor(_key, descriptor, _flags, token):
                descriptor._obj.value = notify_read
                token._obj.value = 1
                return 0

            @staticmethod
            def notify_cancel(_token):
                return 0

        def boom():
            calls.append(1)
            raise RuntimeError("boom")

        watcher = NetworkChangeWatcher(boom)
        self.addCleanup(watcher.stop)
        with patch("peach.netwatch._libsystem", return_value=FakeLibSystem()), \
                self.assertLogs("peach.netwatch", level="ERROR") as captured:
            watcher.start()
            os.write(notify_write, b"ping")
            for _ in range(20):
                if calls:
                    break
                time.sleep(0.01)
            self.assertEqual(calls, [1])
            self.assertTrue(watcher._thread.is_alive())
            watcher.stop()
        self.assertIn("RuntimeError: boom", "\n".join(captured.output))

    @unittest.skipIf(sys.platform == "darwin", "非 macOS 才走这条")
    def test_unsupported_platform_reports_itself(self):
        watcher = NetworkChangeWatcher(lambda: None)
        self.assertFalse(watcher.supported)
        self.assertFalse(watcher.start())


if __name__ == "__main__":
    unittest.main()