import time import unittest from app.services.hardware import GPIOController class GPIOControllerTests(unittest.TestCase): def setUp(self) -> None: GPIOController._reset_for_tests() def tearDown(self) -> None: GPIOController._reset_for_tests() def test_singleton_instance(self) -> None: c1 = GPIOController.get_instance(pin=18, simulation_mode=True) c2 = GPIOController.get_instance(pin=99, simulation_mode=False) self.assertIs(c1, c2) def test_on_off_state_transitions(self) -> None: ctrl = GPIOController.get_instance(pin=18, simulation_mode=True) self.assertFalse(ctrl.rpi_gpio_available) self.assertFalse(ctrl.is_on()) ctrl.on() self.assertTrue(ctrl.is_on()) ctrl.off() self.assertFalse(ctrl.is_on()) def test_blink_runs_in_background_and_finishes_off(self) -> None: ctrl = GPIOController.get_instance(pin=18, simulation_mode=True) start = time.time() ctrl.blink(times=2, delay=0.02) # non-blocking start self.assertLess(time.time() - start, 0.05) time.sleep(0.15) self.assertFalse(ctrl.is_on()) def test_stop_blink(self) -> None: ctrl = GPIOController.get_instance(pin=18, simulation_mode=True) ctrl.blink(times=10, delay=0.05) time.sleep(0.06) ctrl.stop_blink() self.assertFalse(ctrl.is_on()) if __name__ == "__main__": unittest.main()