diff options
| author | Jack Mordaunt <jackmordaunt.dev@gmail.com> | 2025-06-13 18:07:21 -0300 |
|---|---|---|
| committer | Jack Mordaunt <jackmordaunt.dev@gmail.com> | 2025-06-13 18:07:21 -0300 |
| commit | 130b2dc36d6c573b07b0db0454b7e20e4c5ad9c4 (patch) | |
| tree | 3d13b72f573ce8fdd5bb3bb6ad129528e2dcd902 /tests | |
| parent | 760d8c1cdd870aa3f48aceb6c6a9de0e9b57b001 (diff) | |
tests/core/sync/chan: test concurrent send/close/recv
This test is designed to ensure that a call to send will always
correctly report whether the value was transmitted. If recv wins, a
close call should not be able to intercept the send thread.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/core/sync/chan/test_core_sync_chan.odin | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/tests/core/sync/chan/test_core_sync_chan.odin b/tests/core/sync/chan/test_core_sync_chan.odin index 8267d6bef..fdac61550 100644 --- a/tests/core/sync/chan/test_core_sync_chan.odin +++ b/tests/core/sync/chan/test_core_sync_chan.odin @@ -619,3 +619,58 @@ test_try_select_raw_no_toctou :: proc(t: ^testing.T) { thread.join(thief) thread.destroy(thief) } + +// Ensures that a sender will always report correctly whether the value was received +// or not in the event of channel closure. +// +// 1. send thread does a blocking send +// 2. recv and close threads race +// 3. send returns false if close won and reports true if recv won +// +// We know if recv won by whether it sends us the original value on the results channel. +// This test is non-deterministic. +@test +test_send_close_read :: proc(t: ^testing.T) { + trigger, trigger_err := chan.create(chan.Chan(int), context.allocator) + assert(trigger_err == nil, "allocation failed") + defer chan.destroy(trigger) + + ch, alloc_err := chan.create(chan.Chan(int), context.allocator) + assert(alloc_err == nil, "allocation failed") + defer chan.destroy(ch) + + results, results_err := chan.create(chan.Chan(int), 1, context.allocator) + assert(results_err == nil, "allocation failed") + defer chan.destroy(results) + + receiver := thread.create_and_start_with_poly_data3(trigger, results, ch, proc(trigger, results, ch: chan.Chan(int)) { + _, _ = chan.recv(trigger) + v, _ := chan.recv(ch) + assert(chan.send(results, v)) + }) + + closer := thread.create_and_start_with_poly_data2(trigger, ch, proc(trigger, ch: chan.Chan(int)) { + _, _ = chan.recv(trigger) + ok := chan.close(ch) + assert(ok) + }) + + testing.expect(t, chan.close(trigger)) + + did_send := chan.send(ch, 42) + + v, ok := chan.recv(results) + testing.expect(t, ok) + + if v == 42 { + testing.expect(t, did_send) + } else { + testing.expect(t, !did_send) + } + + thread.join_multiple(receiver, closer) + thread.destroy(receiver) + thread.destroy(closer) +} + + |