|
6 | 6 | from fastcs.controller import Controller |
7 | 7 | from fastcs.cs_methods import Command |
8 | 8 | from fastcs.datatypes import Int |
| 9 | +from fastcs.exceptions import FastCSException |
9 | 10 | from fastcs.wrappers import command, scan |
10 | 11 |
|
11 | 12 |
|
@@ -127,3 +128,40 @@ async def test_wrapper(): |
127 | 128 |
|
128 | 129 | assert len(backend._scan_tasks) == 1 |
129 | 130 | assert len(backend._initial_coros) == 2 |
| 131 | + |
| 132 | + |
| 133 | +def test_scan_raises_exception_via_callback(): |
| 134 | + class MyTestController(Controller): |
| 135 | + def __init__(self): |
| 136 | + super().__init__() |
| 137 | + |
| 138 | + @scan(0.1) |
| 139 | + async def raise_exception(self): |
| 140 | + raise ValueError("Scan Exception") |
| 141 | + |
| 142 | + controller = MyTestController() |
| 143 | + loop = asyncio.get_event_loop() |
| 144 | + backend = Backend(controller, loop) |
| 145 | + |
| 146 | + exception_info = {} |
| 147 | + # This will intercept the exception raised in _scan_done |
| 148 | + loop.set_exception_handler( |
| 149 | + lambda _loop, context: exception_info.update( |
| 150 | + {"exception": context.get("exception")} |
| 151 | + ) |
| 152 | + ) |
| 153 | + |
| 154 | + async def test_scan_wrapper(): |
| 155 | + await backend.serve() |
| 156 | + # This allows scan time to run |
| 157 | + await asyncio.sleep(0.2) |
| 158 | + # _scan_done should raise an exception |
| 159 | + assert isinstance(exception_info["exception"], FastCSException) |
| 160 | + for task in backend._scan_tasks: |
| 161 | + internal_exception = task.exception() |
| 162 | + assert internal_exception |
| 163 | + # The task exception comes from scan method raise_exception |
| 164 | + assert isinstance(internal_exception, ValueError) |
| 165 | + assert "Scan Exception" == str(internal_exception) |
| 166 | + |
| 167 | + loop.run_until_complete(test_scan_wrapper()) |
0 commit comments