Files
c3c/test/unit/stdlib/threads/channel.c3
Christoffer Lerno 5c77c9a754 - Change distinct -> typedef.
- Order of attribute declaration is changed for `alias`.
- Added `LANGUAGE_DEV_VERSION` env constant.
- Rename `anyfault` -> `fault`.
- Changed `fault` -> `faultdef`.
- Added `attrdef` instead of `alias` for attribute aliases.
2025-03-15 20:10:47 +01:00

338 lines
5.2 KiB
Plaintext

module thread_test;
import std::thread::channel;
import std::thread;
import std::time;
import std::io;
fn void init_destroy_buffered() @test
{
for (usz i = 0; i < 20; i++)
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
}
}
fn void init_destroy_unbuffered() @test
{
for (usz i = 0; i < 20; i++)
{
UnbufferedChannel{int} c;
c.init(mem)!!;
defer c.destroy()!!;
}
}
fn void push_to_buffered_channel_no_lock() @test
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
c.push(1)!!;
}
fn void push_pop_buffered_no_locks() @test
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
c.push(123)!!;
int got = c.pop()!!;
assert(got == 123);
}
fn void push_pop_unbuffered_with_locks() @test
{
UnbufferedChannel{int} c;
c.init(mem)!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
UnbufferedChannel{int} c = (UnbufferedChannel{int})arg;
c.push(123)!!;
c.push(321)!!;
return 0;
}, (void*)c)!!;
int got = c.pop()!!;
assert(got == 123);
got = c.pop()!!;
assert(got == 321);
}
fn void sending_to_closed_unbuffered_chan_is_forbidden() @test
{
UnbufferedChannel{int} c;
c.init(mem, )!!;
defer c.destroy()!!;
c.close()!!;
if (catch err = c.push(123))
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void sending_to_closed_buffered_chan_is_forbidden() @test
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
c.close()!!;
if (catch err = c.push(123))
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void reading_from_empty_closed_unbuffered_chan_is_forbidden() @test
{
UnbufferedChannel{int} c;
c.init(mem, )!!;
defer c.destroy()!!;
c.close()!!;
if (catch err = c.pop())
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void reading_from_empty_closed_buffered_chan_is_forbidden() @test
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
c.close()!!;
if (catch err = c.pop())
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void reading_from_non_empty_closed_buffered_chan_is_ok() @test
{
BufferedChannel{int} c;
c.init(mem, 3)!!;
defer c.destroy()!!;
c.push(1)!!;
c.push(2)!!;
c.push(3)!!;
c.close()!!;
int got = c.pop()!!;
assert(got == 1);
got = c.pop()!!;
assert(got == 2);
got = c.pop()!!;
assert(got == 3);
int? got_err = c.pop();
if (catch err = got_err)
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void reading_from_empty_buffered_chan_aborted_by_close() @test
{
BufferedChannel{int} c;
c.init(mem, 3)!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
BufferedChannel{int} c = (BufferedChannel{int})arg;
c.close()!!;
return 0;
}, (void*)c)!!;
int? res = c.pop();
if (catch err = res)
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void reading_from_unbuffered_chan_aborted_by_close() @test
{
UnbufferedChannel{int} c;
c.init(mem, )!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
UnbufferedChannel{int} c = (UnbufferedChannel{int})arg;
c.close()!!;
return 0;
}, (void*)c)!!;
int? res = c.pop();
if (catch err = res)
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void sending_to_full_buffered_chan_aborted_by_close() @test
{
BufferedChannel{int} c;
c.init(mem, 1)!!;
defer c.destroy()!!;
c.push(1)!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
BufferedChannel{int} c = (BufferedChannel{int})arg;
c.close()!!;
return 0;
}, (void*)c)!!;
fault err = @catch(c.push(1));
if (err)
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void sending_to_unbuffered_chan_aborted_by_close() @test
{
UnbufferedChannel{int} c;
c.init(mem, )!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
UnbufferedChannel{int} c = (UnbufferedChannel{int})arg;
c.close()!!;
return 0;
}, (void*)c)!!;
fault err = @catch(c.push(1));
if (err)
{
assert(err == thread::CHANNEL_CLOSED);
return;
}
assert(false);
}
fn void multiple_actions_unbuffered() @test
{
UnbufferedChannel{int} c;
c.init(mem, )!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
UnbufferedChannel{int} c = (UnbufferedChannel{int})arg;
for (int i = 0; i <= 100; i++)
{
c.push(i)!!;
}
return 0;
}, (void*)c)!!;
int sum;
for (int i = 0; i <= 100; i++)
{
int? res = c.pop();
if (catch err = res)
{
assert(false);
}
sum += res;
}
assert(sum == 5050);
}
fn void multiple_actions_buffered() @test
{
BufferedChannel{int} c;
c.init(mem, 10)!!;
defer c.destroy()!!;
Thread thread;
defer thread.join()!!;
thread.create(fn int(void* arg)
{
BufferedChannel{int} c = (BufferedChannel{int})arg;
for (int i = 0; i <= 100; i++)
{
c.push(i)!!;
}
return 0;
}, (void*)c)!!;
int sum;
for (int i = 0; i <= 100; i++)
{
int? res = c.pop();
if (catch err = res)
{
assert(false);
}
sum += res;
}
assert(sum == 5050);
}