@ajksunkang-aios/kgraph-linux-x64 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kgraph-launcher +15 -3
- package/lib/kgraph/scripts/build-bundle.sh +17 -4
- package/lib/site-packages/outcome/__init__.py +20 -0
- package/lib/site-packages/outcome/_impl.py +239 -0
- package/lib/site-packages/outcome/_util.py +33 -0
- package/lib/site-packages/outcome/_version.py +7 -0
- package/lib/site-packages/outcome/py.typed +0 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sniffio/__init__.py +17 -0
- package/lib/site-packages/sniffio/_impl.py +95 -0
- package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
- package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
- package/lib/site-packages/sniffio/_version.py +3 -0
- package/lib/site-packages/sniffio/py.typed +0 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sortedcontainers/__init__.py +74 -0
- package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
- package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
- package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/trio/__init__.py +133 -0
- package/lib/site-packages/trio/__main__.py +3 -0
- package/lib/site-packages/trio/_abc.py +714 -0
- package/lib/site-packages/trio/_channel.py +610 -0
- package/lib/site-packages/trio/_core/__init__.py +94 -0
- package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
- package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
- package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
- package/lib/site-packages/trio/_core/_exceptions.py +169 -0
- package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
- package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
- package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
- package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
- package/lib/site-packages/trio/_core/_generated_run.py +269 -0
- package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
- package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
- package/lib/site-packages/trio/_core/_io_common.py +31 -0
- package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
- package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
- package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
- package/lib/site-packages/trio/_core/_ki.py +271 -0
- package/lib/site-packages/trio/_core/_local.py +104 -0
- package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
- package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
- package/lib/site-packages/trio/_core/_run.py +3148 -0
- package/lib/site-packages/trio/_core/_run_context.py +15 -0
- package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
- package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
- package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
- package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
- package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
- package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
- package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
- package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
- package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
- package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
- package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
- package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
- package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
- package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
- package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
- package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
- package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
- package/lib/site-packages/trio/_core/_traps.py +318 -0
- package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
- package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
- package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
- package/lib/site-packages/trio/_deprecate.py +171 -0
- package/lib/site-packages/trio/_dtls.py +1380 -0
- package/lib/site-packages/trio/_file_io.py +513 -0
- package/lib/site-packages/trio/_highlevel_generic.py +125 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
- package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
- package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
- package/lib/site-packages/trio/_highlevel_socket.py +423 -0
- package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
- package/lib/site-packages/trio/_path.py +289 -0
- package/lib/site-packages/trio/_repl.py +159 -0
- package/lib/site-packages/trio/_signals.py +185 -0
- package/lib/site-packages/trio/_socket.py +1326 -0
- package/lib/site-packages/trio/_ssl.py +964 -0
- package/lib/site-packages/trio/_subprocess.py +1178 -0
- package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
- package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
- package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
- package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
- package/lib/site-packages/trio/_sync.py +908 -0
- package/lib/site-packages/trio/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
- package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
- package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
- package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
- package/lib/site-packages/trio/_tests/test_abc.py +72 -0
- package/lib/site-packages/trio/_tests/test_channel.py +750 -0
- package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
- package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
- package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
- package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
- package/lib/site-packages/trio/_tests/test_exports.py +626 -0
- package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
- package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
- package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
- package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
- package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
- package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
- package/lib/site-packages/trio/_tests/test_path.py +279 -0
- package/lib/site-packages/trio/_tests/test_repl.py +428 -0
- package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
- package/lib/site-packages/trio/_tests/test_signals.py +186 -0
- package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
- package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
- package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
- package/lib/site-packages/trio/_tests/test_sync.py +735 -0
- package/lib/site-packages/trio/_tests/test_testing.py +682 -0
- package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
- package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
- package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
- package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
- package/lib/site-packages/trio/_tests/test_trio.py +8 -0
- package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
- package/lib/site-packages/trio/_tests/test_util.py +349 -0
- package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
- package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
- package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
- package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
- package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
- package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
- package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
- package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
- package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
- package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
- package/lib/site-packages/trio/_threads.py +610 -0
- package/lib/site-packages/trio/_timeouts.py +197 -0
- package/lib/site-packages/trio/_tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
- package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
- package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
- package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
- package/lib/site-packages/trio/_unix_pipes.py +197 -0
- package/lib/site-packages/trio/_util.py +385 -0
- package/lib/site-packages/trio/_version.py +3 -0
- package/lib/site-packages/trio/_wait_for_object.py +67 -0
- package/lib/site-packages/trio/_windows_pipes.py +144 -0
- package/lib/site-packages/trio/abc.py +23 -0
- package/lib/site-packages/trio/from_thread.py +13 -0
- package/lib/site-packages/trio/lowlevel.py +95 -0
- package/lib/site-packages/trio/py.typed +0 -0
- package/lib/site-packages/trio/socket.py +602 -0
- package/lib/site-packages/trio/testing/__init__.py +58 -0
- package/lib/site-packages/trio/testing/_check_streams.py +570 -0
- package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
- package/lib/site-packages/trio/testing/_fake_net.py +584 -0
- package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
- package/lib/site-packages/trio/testing/_network.py +36 -0
- package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
- package/lib/site-packages/trio/testing/_sequencer.py +87 -0
- package/lib/site-packages/trio/testing/_trio_test.py +50 -0
- package/lib/site-packages/trio/to_thread.py +4 -0
- package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
- package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
- package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
- package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
- package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
- package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# XX this should get broken up, like testing.py did
|
|
4
|
+
import tempfile
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from .. import _core, sleep, socket as tsocket
|
|
10
|
+
from .._core._tests.tutil import can_bind_ipv6
|
|
11
|
+
from .._highlevel_generic import StapledStream, aclose_forcefully
|
|
12
|
+
from .._highlevel_socket import SocketListener
|
|
13
|
+
from ..testing import *
|
|
14
|
+
from ..testing._check_streams import _assert_raises
|
|
15
|
+
from ..testing._memory_streams import _UnboundedByteQueue
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from trio import Nursery
|
|
19
|
+
from trio.abc import ReceiveStream, SendStream
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def test_wait_all_tasks_blocked() -> None:
|
|
23
|
+
record = []
|
|
24
|
+
|
|
25
|
+
async def busy_bee() -> None:
|
|
26
|
+
for _ in range(10):
|
|
27
|
+
await _core.checkpoint()
|
|
28
|
+
record.append("busy bee exhausted")
|
|
29
|
+
|
|
30
|
+
async def waiting_for_bee_to_leave() -> None:
|
|
31
|
+
await wait_all_tasks_blocked()
|
|
32
|
+
record.append("quiet at last!")
|
|
33
|
+
|
|
34
|
+
async with _core.open_nursery() as nursery:
|
|
35
|
+
nursery.start_soon(busy_bee)
|
|
36
|
+
nursery.start_soon(waiting_for_bee_to_leave)
|
|
37
|
+
nursery.start_soon(waiting_for_bee_to_leave)
|
|
38
|
+
|
|
39
|
+
# check cancellation
|
|
40
|
+
record = []
|
|
41
|
+
|
|
42
|
+
async def cancelled_while_waiting() -> None:
|
|
43
|
+
try:
|
|
44
|
+
await wait_all_tasks_blocked()
|
|
45
|
+
except _core.Cancelled:
|
|
46
|
+
record.append("ok")
|
|
47
|
+
|
|
48
|
+
async with _core.open_nursery() as nursery:
|
|
49
|
+
nursery.start_soon(cancelled_while_waiting)
|
|
50
|
+
nursery.cancel_scope.cancel()
|
|
51
|
+
assert record == ["ok"]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def test_wait_all_tasks_blocked_with_timeouts(mock_clock: MockClock) -> None:
|
|
55
|
+
record = []
|
|
56
|
+
|
|
57
|
+
async def timeout_task() -> None:
|
|
58
|
+
record.append("tt start")
|
|
59
|
+
await sleep(5)
|
|
60
|
+
record.append("tt finished")
|
|
61
|
+
|
|
62
|
+
async with _core.open_nursery() as nursery:
|
|
63
|
+
nursery.start_soon(timeout_task)
|
|
64
|
+
await wait_all_tasks_blocked()
|
|
65
|
+
assert record == ["tt start"]
|
|
66
|
+
mock_clock.jump(10)
|
|
67
|
+
await wait_all_tasks_blocked()
|
|
68
|
+
assert record == ["tt start", "tt finished"]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
async def test_wait_all_tasks_blocked_with_cushion() -> None:
|
|
72
|
+
record = []
|
|
73
|
+
|
|
74
|
+
async def blink() -> None:
|
|
75
|
+
record.append("blink start")
|
|
76
|
+
await sleep(0.01)
|
|
77
|
+
await sleep(0.01)
|
|
78
|
+
await sleep(0.01)
|
|
79
|
+
record.append("blink end")
|
|
80
|
+
|
|
81
|
+
async def wait_no_cushion() -> None:
|
|
82
|
+
await wait_all_tasks_blocked()
|
|
83
|
+
record.append("wait_no_cushion end")
|
|
84
|
+
|
|
85
|
+
async def wait_small_cushion() -> None:
|
|
86
|
+
await wait_all_tasks_blocked(0.02)
|
|
87
|
+
record.append("wait_small_cushion end")
|
|
88
|
+
|
|
89
|
+
async def wait_big_cushion() -> None:
|
|
90
|
+
await wait_all_tasks_blocked(0.03)
|
|
91
|
+
record.append("wait_big_cushion end")
|
|
92
|
+
|
|
93
|
+
async with _core.open_nursery() as nursery:
|
|
94
|
+
nursery.start_soon(blink)
|
|
95
|
+
nursery.start_soon(wait_no_cushion)
|
|
96
|
+
nursery.start_soon(wait_small_cushion)
|
|
97
|
+
nursery.start_soon(wait_small_cushion)
|
|
98
|
+
nursery.start_soon(wait_big_cushion)
|
|
99
|
+
|
|
100
|
+
assert record == [
|
|
101
|
+
"blink start",
|
|
102
|
+
"wait_no_cushion end",
|
|
103
|
+
"blink end",
|
|
104
|
+
"wait_small_cushion end",
|
|
105
|
+
"wait_small_cushion end",
|
|
106
|
+
"wait_big_cushion end",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
################################################################
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def test_assert_checkpoints(recwarn: pytest.WarningsRecorder) -> None:
|
|
114
|
+
with assert_checkpoints():
|
|
115
|
+
await _core.checkpoint()
|
|
116
|
+
|
|
117
|
+
with pytest.raises(AssertionError):
|
|
118
|
+
with assert_checkpoints():
|
|
119
|
+
1 + 1 # noqa: B018 # "useless expression"
|
|
120
|
+
|
|
121
|
+
# partial yield cases
|
|
122
|
+
# if you have a schedule point but not a cancel point, or vice-versa, then
|
|
123
|
+
# that's not a checkpoint.
|
|
124
|
+
for partial_yield in [
|
|
125
|
+
_core.checkpoint_if_cancelled,
|
|
126
|
+
_core.cancel_shielded_checkpoint,
|
|
127
|
+
]:
|
|
128
|
+
print(partial_yield)
|
|
129
|
+
with pytest.raises(AssertionError):
|
|
130
|
+
with assert_checkpoints():
|
|
131
|
+
await partial_yield()
|
|
132
|
+
|
|
133
|
+
# But both together count as a checkpoint
|
|
134
|
+
with assert_checkpoints():
|
|
135
|
+
await _core.checkpoint_if_cancelled()
|
|
136
|
+
await _core.cancel_shielded_checkpoint()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
async def test_assert_no_checkpoints(recwarn: pytest.WarningsRecorder) -> None:
|
|
140
|
+
with assert_no_checkpoints():
|
|
141
|
+
1 + 1 # noqa: B018 # "useless expression"
|
|
142
|
+
|
|
143
|
+
with pytest.raises(AssertionError):
|
|
144
|
+
with assert_no_checkpoints():
|
|
145
|
+
await _core.checkpoint()
|
|
146
|
+
|
|
147
|
+
# partial yield cases
|
|
148
|
+
# if you have a schedule point but not a cancel point, or vice-versa, then
|
|
149
|
+
# that doesn't make *either* version of assert_{no_,}yields happy.
|
|
150
|
+
for partial_yield in [
|
|
151
|
+
_core.checkpoint_if_cancelled,
|
|
152
|
+
_core.cancel_shielded_checkpoint,
|
|
153
|
+
]:
|
|
154
|
+
print(partial_yield)
|
|
155
|
+
with pytest.raises(AssertionError):
|
|
156
|
+
with assert_no_checkpoints():
|
|
157
|
+
await partial_yield()
|
|
158
|
+
|
|
159
|
+
# And both together also count as a checkpoint
|
|
160
|
+
with pytest.raises(AssertionError):
|
|
161
|
+
with assert_no_checkpoints():
|
|
162
|
+
await _core.checkpoint_if_cancelled()
|
|
163
|
+
await _core.cancel_shielded_checkpoint()
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
################################################################
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
async def test_Sequencer() -> None:
|
|
170
|
+
record = []
|
|
171
|
+
|
|
172
|
+
def t(val: object) -> None:
|
|
173
|
+
print(val)
|
|
174
|
+
record.append(val)
|
|
175
|
+
|
|
176
|
+
async def f1(seq: Sequencer) -> None:
|
|
177
|
+
async with seq(1):
|
|
178
|
+
t(("f1", 1))
|
|
179
|
+
async with seq(3):
|
|
180
|
+
t(("f1", 3))
|
|
181
|
+
async with seq(4):
|
|
182
|
+
t(("f1", 4))
|
|
183
|
+
|
|
184
|
+
async def f2(seq: Sequencer) -> None:
|
|
185
|
+
async with seq(0):
|
|
186
|
+
t(("f2", 0))
|
|
187
|
+
async with seq(2):
|
|
188
|
+
t(("f2", 2))
|
|
189
|
+
|
|
190
|
+
seq = Sequencer()
|
|
191
|
+
async with _core.open_nursery() as nursery:
|
|
192
|
+
nursery.start_soon(f1, seq)
|
|
193
|
+
nursery.start_soon(f2, seq)
|
|
194
|
+
async with seq(5):
|
|
195
|
+
await wait_all_tasks_blocked()
|
|
196
|
+
assert record == [("f2", 0), ("f1", 1), ("f2", 2), ("f1", 3), ("f1", 4)]
|
|
197
|
+
|
|
198
|
+
seq = Sequencer()
|
|
199
|
+
# Catches us if we try to reuse a sequence point:
|
|
200
|
+
async with seq(0):
|
|
201
|
+
pass
|
|
202
|
+
with pytest.raises(RuntimeError):
|
|
203
|
+
async with seq(0):
|
|
204
|
+
pass # pragma: no cover
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
async def test_Sequencer_cancel() -> None:
|
|
208
|
+
# Killing a blocked task makes everything blow up
|
|
209
|
+
record = []
|
|
210
|
+
seq = Sequencer()
|
|
211
|
+
|
|
212
|
+
async def child(i: int) -> None:
|
|
213
|
+
with _core.CancelScope() as scope:
|
|
214
|
+
if i == 1:
|
|
215
|
+
scope.cancel()
|
|
216
|
+
try:
|
|
217
|
+
async with seq(i):
|
|
218
|
+
pass # pragma: no cover
|
|
219
|
+
except RuntimeError:
|
|
220
|
+
record.append(f"seq({i}) RuntimeError")
|
|
221
|
+
|
|
222
|
+
async with _core.open_nursery() as nursery:
|
|
223
|
+
nursery.start_soon(child, 1)
|
|
224
|
+
nursery.start_soon(child, 2)
|
|
225
|
+
async with seq(0):
|
|
226
|
+
pass # pragma: no cover
|
|
227
|
+
|
|
228
|
+
assert record == ["seq(1) RuntimeError", "seq(2) RuntimeError"]
|
|
229
|
+
|
|
230
|
+
# Late arrivals also get errors
|
|
231
|
+
with pytest.raises(RuntimeError):
|
|
232
|
+
async with seq(3):
|
|
233
|
+
pass # pragma: no cover
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
################################################################
|
|
237
|
+
def test__assert_raises() -> None:
|
|
238
|
+
with pytest.raises(AssertionError):
|
|
239
|
+
with _assert_raises(RuntimeError):
|
|
240
|
+
1 + 1 # noqa: B018 # "useless expression"
|
|
241
|
+
|
|
242
|
+
with pytest.raises(TypeError):
|
|
243
|
+
with _assert_raises(RuntimeError):
|
|
244
|
+
"foo" + 1 # type: ignore[operator] # noqa: B018 # "useless expression"
|
|
245
|
+
|
|
246
|
+
with _assert_raises(RuntimeError):
|
|
247
|
+
raise RuntimeError
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# This is a private implementation detail, but it's complex enough to be worth
|
|
251
|
+
# testing directly
|
|
252
|
+
async def test__UnboundeByteQueue() -> None:
|
|
253
|
+
ubq = _UnboundedByteQueue()
|
|
254
|
+
|
|
255
|
+
ubq.put(b"123")
|
|
256
|
+
ubq.put(b"456")
|
|
257
|
+
assert ubq.get_nowait(1) == b"1"
|
|
258
|
+
assert ubq.get_nowait(10) == b"23456"
|
|
259
|
+
ubq.put(b"789")
|
|
260
|
+
assert ubq.get_nowait() == b"789"
|
|
261
|
+
|
|
262
|
+
with pytest.raises(_core.WouldBlock):
|
|
263
|
+
ubq.get_nowait(10)
|
|
264
|
+
with pytest.raises(_core.WouldBlock):
|
|
265
|
+
ubq.get_nowait()
|
|
266
|
+
|
|
267
|
+
with pytest.raises(TypeError):
|
|
268
|
+
ubq.put("string") # type: ignore[arg-type]
|
|
269
|
+
|
|
270
|
+
ubq.put(b"abc")
|
|
271
|
+
with assert_checkpoints():
|
|
272
|
+
assert await ubq.get(10) == b"abc"
|
|
273
|
+
ubq.put(b"def")
|
|
274
|
+
ubq.put(b"ghi")
|
|
275
|
+
with assert_checkpoints():
|
|
276
|
+
assert await ubq.get(1) == b"d"
|
|
277
|
+
with assert_checkpoints():
|
|
278
|
+
assert await ubq.get() == b"efghi"
|
|
279
|
+
|
|
280
|
+
async def putter(data: bytes) -> None:
|
|
281
|
+
await wait_all_tasks_blocked()
|
|
282
|
+
ubq.put(data)
|
|
283
|
+
|
|
284
|
+
async def getter(expect: bytes) -> None:
|
|
285
|
+
with assert_checkpoints():
|
|
286
|
+
assert await ubq.get() == expect
|
|
287
|
+
|
|
288
|
+
async with _core.open_nursery() as nursery:
|
|
289
|
+
nursery.start_soon(getter, b"xyz")
|
|
290
|
+
nursery.start_soon(putter, b"xyz")
|
|
291
|
+
|
|
292
|
+
# Two gets at the same time -> BusyResourceError
|
|
293
|
+
with pytest.RaisesGroup(_core.BusyResourceError):
|
|
294
|
+
async with _core.open_nursery() as nursery:
|
|
295
|
+
nursery.start_soon(getter, b"asdf")
|
|
296
|
+
nursery.start_soon(getter, b"asdf")
|
|
297
|
+
|
|
298
|
+
# Closing
|
|
299
|
+
|
|
300
|
+
ubq.close()
|
|
301
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
302
|
+
ubq.put(b"---")
|
|
303
|
+
|
|
304
|
+
assert ubq.get_nowait(10) == b""
|
|
305
|
+
assert ubq.get_nowait() == b""
|
|
306
|
+
assert await ubq.get(10) == b""
|
|
307
|
+
assert await ubq.get() == b""
|
|
308
|
+
|
|
309
|
+
# close is idempotent
|
|
310
|
+
ubq.close()
|
|
311
|
+
|
|
312
|
+
# close wakes up blocked getters
|
|
313
|
+
ubq2 = _UnboundedByteQueue()
|
|
314
|
+
|
|
315
|
+
async def closer() -> None:
|
|
316
|
+
await wait_all_tasks_blocked()
|
|
317
|
+
ubq2.close()
|
|
318
|
+
|
|
319
|
+
async with _core.open_nursery() as nursery:
|
|
320
|
+
nursery.start_soon(getter, b"")
|
|
321
|
+
nursery.start_soon(closer)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
async def test_MemorySendStream() -> None:
|
|
325
|
+
mss = MemorySendStream()
|
|
326
|
+
|
|
327
|
+
async def do_send_all(data: bytes) -> None:
|
|
328
|
+
with assert_checkpoints():
|
|
329
|
+
await mss.send_all(data)
|
|
330
|
+
|
|
331
|
+
await do_send_all(b"123")
|
|
332
|
+
assert mss.get_data_nowait(1) == b"1"
|
|
333
|
+
assert mss.get_data_nowait() == b"23"
|
|
334
|
+
|
|
335
|
+
with assert_checkpoints():
|
|
336
|
+
await mss.wait_send_all_might_not_block()
|
|
337
|
+
|
|
338
|
+
with pytest.raises(_core.WouldBlock):
|
|
339
|
+
mss.get_data_nowait()
|
|
340
|
+
with pytest.raises(_core.WouldBlock):
|
|
341
|
+
mss.get_data_nowait(10)
|
|
342
|
+
|
|
343
|
+
await do_send_all(b"456")
|
|
344
|
+
with assert_checkpoints():
|
|
345
|
+
assert await mss.get_data() == b"456"
|
|
346
|
+
|
|
347
|
+
# Call send_all twice at once; one should get BusyResourceError and one
|
|
348
|
+
# should succeed. But we can't let the error propagate, because it might
|
|
349
|
+
# cause the other to be cancelled before it can finish doing its thing,
|
|
350
|
+
# and we don't know which one will get the error.
|
|
351
|
+
resource_busy_count = 0
|
|
352
|
+
|
|
353
|
+
async def do_send_all_count_resourcebusy() -> None:
|
|
354
|
+
nonlocal resource_busy_count
|
|
355
|
+
try:
|
|
356
|
+
await do_send_all(b"xxx")
|
|
357
|
+
except _core.BusyResourceError:
|
|
358
|
+
resource_busy_count += 1
|
|
359
|
+
|
|
360
|
+
async with _core.open_nursery() as nursery:
|
|
361
|
+
nursery.start_soon(do_send_all_count_resourcebusy)
|
|
362
|
+
nursery.start_soon(do_send_all_count_resourcebusy)
|
|
363
|
+
|
|
364
|
+
assert resource_busy_count == 1
|
|
365
|
+
|
|
366
|
+
with assert_checkpoints():
|
|
367
|
+
await mss.aclose()
|
|
368
|
+
|
|
369
|
+
assert await mss.get_data() == b"xxx"
|
|
370
|
+
assert await mss.get_data() == b""
|
|
371
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
372
|
+
await do_send_all(b"---")
|
|
373
|
+
|
|
374
|
+
# hooks
|
|
375
|
+
|
|
376
|
+
assert mss.send_all_hook is None
|
|
377
|
+
assert mss.wait_send_all_might_not_block_hook is None
|
|
378
|
+
assert mss.close_hook is None
|
|
379
|
+
|
|
380
|
+
record = []
|
|
381
|
+
|
|
382
|
+
async def send_all_hook() -> None:
|
|
383
|
+
# hook runs after send_all does its work (can pull data out)
|
|
384
|
+
assert mss2.get_data_nowait() == b"abc"
|
|
385
|
+
record.append("send_all_hook")
|
|
386
|
+
|
|
387
|
+
async def wait_send_all_might_not_block_hook() -> None:
|
|
388
|
+
record.append("wait_send_all_might_not_block_hook")
|
|
389
|
+
|
|
390
|
+
def close_hook() -> None:
|
|
391
|
+
record.append("close_hook")
|
|
392
|
+
|
|
393
|
+
mss2 = MemorySendStream(
|
|
394
|
+
send_all_hook,
|
|
395
|
+
wait_send_all_might_not_block_hook,
|
|
396
|
+
close_hook,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
assert mss2.send_all_hook is send_all_hook
|
|
400
|
+
assert mss2.wait_send_all_might_not_block_hook is wait_send_all_might_not_block_hook
|
|
401
|
+
assert mss2.close_hook is close_hook
|
|
402
|
+
|
|
403
|
+
await mss2.send_all(b"abc")
|
|
404
|
+
await mss2.wait_send_all_might_not_block()
|
|
405
|
+
await aclose_forcefully(mss2)
|
|
406
|
+
mss2.close()
|
|
407
|
+
|
|
408
|
+
assert record == [
|
|
409
|
+
"send_all_hook",
|
|
410
|
+
"wait_send_all_might_not_block_hook",
|
|
411
|
+
"close_hook",
|
|
412
|
+
"close_hook",
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
async def test_MemoryReceiveStream() -> None:
|
|
417
|
+
mrs = MemoryReceiveStream()
|
|
418
|
+
|
|
419
|
+
async def do_receive_some(max_bytes: int | None) -> bytes:
|
|
420
|
+
with assert_checkpoints():
|
|
421
|
+
return await mrs.receive_some(max_bytes)
|
|
422
|
+
|
|
423
|
+
mrs.put_data(b"abc")
|
|
424
|
+
assert await do_receive_some(1) == b"a"
|
|
425
|
+
assert await do_receive_some(10) == b"bc"
|
|
426
|
+
mrs.put_data(b"abc")
|
|
427
|
+
assert await do_receive_some(None) == b"abc"
|
|
428
|
+
|
|
429
|
+
with pytest.RaisesGroup(_core.BusyResourceError):
|
|
430
|
+
async with _core.open_nursery() as nursery:
|
|
431
|
+
nursery.start_soon(do_receive_some, 10)
|
|
432
|
+
nursery.start_soon(do_receive_some, 10)
|
|
433
|
+
|
|
434
|
+
assert mrs.receive_some_hook is None
|
|
435
|
+
|
|
436
|
+
mrs.put_data(b"def")
|
|
437
|
+
mrs.put_eof()
|
|
438
|
+
mrs.put_eof()
|
|
439
|
+
|
|
440
|
+
assert await do_receive_some(10) == b"def"
|
|
441
|
+
assert await do_receive_some(10) == b""
|
|
442
|
+
assert await do_receive_some(10) == b""
|
|
443
|
+
|
|
444
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
445
|
+
mrs.put_data(b"---")
|
|
446
|
+
|
|
447
|
+
async def receive_some_hook() -> None:
|
|
448
|
+
mrs2.put_data(b"xxx")
|
|
449
|
+
|
|
450
|
+
record = []
|
|
451
|
+
|
|
452
|
+
def close_hook() -> None:
|
|
453
|
+
record.append("closed")
|
|
454
|
+
|
|
455
|
+
mrs2 = MemoryReceiveStream(receive_some_hook, close_hook)
|
|
456
|
+
assert mrs2.receive_some_hook is receive_some_hook
|
|
457
|
+
assert mrs2.close_hook is close_hook
|
|
458
|
+
|
|
459
|
+
mrs2.put_data(b"yyy")
|
|
460
|
+
assert await mrs2.receive_some(10) == b"yyyxxx"
|
|
461
|
+
assert await mrs2.receive_some(10) == b"xxx"
|
|
462
|
+
assert await mrs2.receive_some(10) == b"xxx"
|
|
463
|
+
|
|
464
|
+
mrs2.put_data(b"zzz")
|
|
465
|
+
mrs2.receive_some_hook = None
|
|
466
|
+
assert await mrs2.receive_some(10) == b"zzz"
|
|
467
|
+
|
|
468
|
+
mrs2.put_data(b"lost on close")
|
|
469
|
+
with assert_checkpoints():
|
|
470
|
+
await mrs2.aclose()
|
|
471
|
+
assert record == ["closed"]
|
|
472
|
+
|
|
473
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
474
|
+
await mrs2.receive_some(10)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
async def test_MemoryRecvStream_closing() -> None:
|
|
478
|
+
mrs = MemoryReceiveStream()
|
|
479
|
+
# close with no pending data
|
|
480
|
+
mrs.close()
|
|
481
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
482
|
+
assert await mrs.receive_some(10) == b""
|
|
483
|
+
# repeated closes ok
|
|
484
|
+
mrs.close()
|
|
485
|
+
# put_data now fails
|
|
486
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
487
|
+
mrs.put_data(b"123")
|
|
488
|
+
|
|
489
|
+
mrs2 = MemoryReceiveStream()
|
|
490
|
+
# close with pending data
|
|
491
|
+
mrs2.put_data(b"xyz")
|
|
492
|
+
mrs2.close()
|
|
493
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
494
|
+
await mrs2.receive_some(10)
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
async def test_memory_stream_pump() -> None:
|
|
498
|
+
mss = MemorySendStream()
|
|
499
|
+
mrs = MemoryReceiveStream()
|
|
500
|
+
|
|
501
|
+
# no-op if no data present
|
|
502
|
+
memory_stream_pump(mss, mrs)
|
|
503
|
+
|
|
504
|
+
await mss.send_all(b"123")
|
|
505
|
+
memory_stream_pump(mss, mrs)
|
|
506
|
+
assert await mrs.receive_some(10) == b"123"
|
|
507
|
+
|
|
508
|
+
await mss.send_all(b"456")
|
|
509
|
+
assert memory_stream_pump(mss, mrs, max_bytes=1)
|
|
510
|
+
assert await mrs.receive_some(10) == b"4"
|
|
511
|
+
assert memory_stream_pump(mss, mrs, max_bytes=1)
|
|
512
|
+
assert memory_stream_pump(mss, mrs, max_bytes=1)
|
|
513
|
+
assert not memory_stream_pump(mss, mrs, max_bytes=1)
|
|
514
|
+
assert await mrs.receive_some(10) == b"56"
|
|
515
|
+
|
|
516
|
+
mss.close()
|
|
517
|
+
memory_stream_pump(mss, mrs)
|
|
518
|
+
assert await mrs.receive_some(10) == b""
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
async def test_memory_stream_one_way_pair() -> None:
|
|
522
|
+
s, r = memory_stream_one_way_pair()
|
|
523
|
+
assert s.send_all_hook is not None
|
|
524
|
+
assert s.wait_send_all_might_not_block_hook is None
|
|
525
|
+
assert s.close_hook is not None
|
|
526
|
+
assert r.receive_some_hook is None
|
|
527
|
+
await s.send_all(b"123")
|
|
528
|
+
assert await r.receive_some(10) == b"123"
|
|
529
|
+
|
|
530
|
+
async def receiver(expected: bytes) -> None:
|
|
531
|
+
assert await r.receive_some(10) == expected
|
|
532
|
+
|
|
533
|
+
# This fails if we pump on r.receive_some_hook; we need to pump on s.send_all_hook
|
|
534
|
+
async with _core.open_nursery() as nursery:
|
|
535
|
+
nursery.start_soon(receiver, b"abc")
|
|
536
|
+
await wait_all_tasks_blocked()
|
|
537
|
+
await s.send_all(b"abc")
|
|
538
|
+
|
|
539
|
+
# And this fails if we don't pump from close_hook
|
|
540
|
+
async with _core.open_nursery() as nursery:
|
|
541
|
+
nursery.start_soon(receiver, b"")
|
|
542
|
+
await wait_all_tasks_blocked()
|
|
543
|
+
await s.aclose()
|
|
544
|
+
|
|
545
|
+
s, r = memory_stream_one_way_pair()
|
|
546
|
+
|
|
547
|
+
async with _core.open_nursery() as nursery:
|
|
548
|
+
nursery.start_soon(receiver, b"")
|
|
549
|
+
await wait_all_tasks_blocked()
|
|
550
|
+
s.close()
|
|
551
|
+
|
|
552
|
+
s, r = memory_stream_one_way_pair()
|
|
553
|
+
|
|
554
|
+
old = s.send_all_hook
|
|
555
|
+
s.send_all_hook = None
|
|
556
|
+
await s.send_all(b"456")
|
|
557
|
+
|
|
558
|
+
async def cancel_after_idle(nursery: Nursery) -> None:
|
|
559
|
+
await wait_all_tasks_blocked()
|
|
560
|
+
nursery.cancel_scope.cancel()
|
|
561
|
+
|
|
562
|
+
async def check_for_cancel() -> None:
|
|
563
|
+
with pytest.raises(_core.Cancelled):
|
|
564
|
+
# This should block forever... or until cancelled. Even though we
|
|
565
|
+
# sent some data on the send stream.
|
|
566
|
+
await r.receive_some(10)
|
|
567
|
+
|
|
568
|
+
async with _core.open_nursery() as nursery:
|
|
569
|
+
nursery.start_soon(cancel_after_idle, nursery)
|
|
570
|
+
nursery.start_soon(check_for_cancel)
|
|
571
|
+
|
|
572
|
+
s.send_all_hook = old
|
|
573
|
+
await s.send_all(b"789")
|
|
574
|
+
assert await r.receive_some(10) == b"456789"
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
async def test_memory_stream_pair() -> None:
|
|
578
|
+
a, b = memory_stream_pair()
|
|
579
|
+
await a.send_all(b"123")
|
|
580
|
+
await b.send_all(b"abc")
|
|
581
|
+
assert await b.receive_some(10) == b"123"
|
|
582
|
+
assert await a.receive_some(10) == b"abc"
|
|
583
|
+
|
|
584
|
+
await a.send_eof()
|
|
585
|
+
assert await b.receive_some(10) == b""
|
|
586
|
+
|
|
587
|
+
async def sender() -> None:
|
|
588
|
+
await wait_all_tasks_blocked()
|
|
589
|
+
await b.send_all(b"xyz")
|
|
590
|
+
|
|
591
|
+
async def receiver() -> None:
|
|
592
|
+
assert await a.receive_some(10) == b"xyz"
|
|
593
|
+
|
|
594
|
+
async with _core.open_nursery() as nursery:
|
|
595
|
+
nursery.start_soon(receiver)
|
|
596
|
+
nursery.start_soon(sender)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
async def test_memory_streams_with_generic_tests() -> None:
|
|
600
|
+
async def one_way_stream_maker() -> tuple[MemorySendStream, MemoryReceiveStream]:
|
|
601
|
+
return memory_stream_one_way_pair()
|
|
602
|
+
|
|
603
|
+
await check_one_way_stream(one_way_stream_maker, None)
|
|
604
|
+
|
|
605
|
+
async def half_closeable_stream_maker() -> tuple[
|
|
606
|
+
StapledStream[MemorySendStream, MemoryReceiveStream],
|
|
607
|
+
StapledStream[MemorySendStream, MemoryReceiveStream],
|
|
608
|
+
]:
|
|
609
|
+
return memory_stream_pair()
|
|
610
|
+
|
|
611
|
+
await check_half_closeable_stream(half_closeable_stream_maker, None)
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
async def test_lockstep_streams_with_generic_tests() -> None:
|
|
615
|
+
async def one_way_stream_maker() -> tuple[SendStream, ReceiveStream]:
|
|
616
|
+
return lockstep_stream_one_way_pair()
|
|
617
|
+
|
|
618
|
+
await check_one_way_stream(one_way_stream_maker, one_way_stream_maker)
|
|
619
|
+
|
|
620
|
+
async def two_way_stream_maker() -> tuple[
|
|
621
|
+
StapledStream[SendStream, ReceiveStream],
|
|
622
|
+
StapledStream[SendStream, ReceiveStream],
|
|
623
|
+
]:
|
|
624
|
+
return lockstep_stream_pair()
|
|
625
|
+
|
|
626
|
+
await check_two_way_stream(two_way_stream_maker, two_way_stream_maker)
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
async def test_open_stream_to_socket_listener() -> None:
|
|
630
|
+
async def check(listener: SocketListener) -> None:
|
|
631
|
+
async with listener:
|
|
632
|
+
client_stream = await open_stream_to_socket_listener(listener)
|
|
633
|
+
async with client_stream:
|
|
634
|
+
server_stream = await listener.accept()
|
|
635
|
+
async with server_stream:
|
|
636
|
+
await client_stream.send_all(b"x")
|
|
637
|
+
assert await server_stream.receive_some(1) == b"x"
|
|
638
|
+
|
|
639
|
+
# Listener bound to localhost
|
|
640
|
+
sock = tsocket.socket()
|
|
641
|
+
await sock.bind(("127.0.0.1", 0))
|
|
642
|
+
sock.listen(10)
|
|
643
|
+
await check(SocketListener(sock))
|
|
644
|
+
|
|
645
|
+
# Listener bound to IPv4 wildcard (needs special handling)
|
|
646
|
+
sock = tsocket.socket()
|
|
647
|
+
await sock.bind(("0.0.0.0", 0))
|
|
648
|
+
sock.listen(10)
|
|
649
|
+
await check(SocketListener(sock))
|
|
650
|
+
|
|
651
|
+
# true on all CI systems
|
|
652
|
+
if can_bind_ipv6: # pragma: no branch
|
|
653
|
+
# Listener bound to IPv6 wildcard (needs special handling)
|
|
654
|
+
sock = tsocket.socket(family=tsocket.AF_INET6)
|
|
655
|
+
await sock.bind(("::", 0))
|
|
656
|
+
sock.listen(10)
|
|
657
|
+
await check(SocketListener(sock))
|
|
658
|
+
|
|
659
|
+
if hasattr(tsocket, "AF_UNIX"):
|
|
660
|
+
# Listener bound to Unix-domain socket
|
|
661
|
+
sock = tsocket.socket(family=tsocket.AF_UNIX)
|
|
662
|
+
# can't use pytest's tmpdir; if we try then macOS says "OSError:
|
|
663
|
+
# AF_UNIX path too long"
|
|
664
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
665
|
+
path = f"{tmpdir}/sock"
|
|
666
|
+
await sock.bind(path)
|
|
667
|
+
sock.listen(10)
|
|
668
|
+
await check(SocketListener(sock))
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
def test_trio_test() -> None:
|
|
672
|
+
async def busy_kitchen(
|
|
673
|
+
*,
|
|
674
|
+
mock_clock: object,
|
|
675
|
+
autojump_clock: object,
|
|
676
|
+
) -> None: ... # pragma: no cover
|
|
677
|
+
|
|
678
|
+
with pytest.raises(ValueError, match=r"^too many clocks spoil the broth!$"):
|
|
679
|
+
trio_test(busy_kitchen)(
|
|
680
|
+
mock_clock=MockClock(),
|
|
681
|
+
autojump_clock=MockClock(autojump_threshold=0),
|
|
682
|
+
)
|