#include #include #include using namespace kpn; TEST_CASE("channel storage policy: small trivial type by value", "[channel]") { STATIC_REQUIRE(channel_storage_policy::by_value); STATIC_REQUIRE(channel_storage_policy::by_value); } TEST_CASE("channel storage policy: large type by shared_ptr", "[channel]") { struct Big { char data[64]; }; STATIC_REQUIRE(!channel_storage_policy::by_value); } TEST_CASE("push and pop single value", "[channel]") { Channel ch(5); ch.push(42); REQUIRE(ch.pop() == 42); } TEST_CASE("channel respects capacity", "[channel]") { Channel ch(2); ch.push(1); ch.push(2); REQUIRE_THROWS_AS(ch.push(3), ChannelOverflowError); } TEST_CASE("pop blocks until value available", "[channel]") { Channel ch(5); int result = 0; std::thread producer([&] { std::this_thread::sleep_for(std::chrono::milliseconds(20)); ch.push(99); }); result = ch.pop(); producer.join(); REQUIRE(result == 99); } TEST_CASE("try_pop returns false on timeout", "[channel]") { Channel ch(5); int out = 0; REQUIRE_FALSE(ch.try_pop(out, std::chrono::milliseconds(10))); } TEST_CASE("try_pop succeeds when value present", "[channel]") { Channel ch(5); ch.push(7); int out = 0; REQUIRE(ch.try_pop(out, std::chrono::milliseconds(10))); REQUIRE(out == 7); } TEST_CASE("disable unblocks waiting pop", "[channel]") { Channel ch(5); std::thread disabler([&] { std::this_thread::sleep_for(std::chrono::milliseconds(20)); ch.disable(); }); REQUIRE_THROWS_AS(ch.pop(), ChannelClosedError); disabler.join(); } TEST_CASE("push to disabled channel is silently dropped", "[channel]") { Channel ch(5); ch.disable(); ch.push(99); // must not throw, must not enqueue REQUIRE(ch.size() == 0); } TEST_CASE("disable clears existing queue contents", "[channel]") { Channel ch(5); ch.push(1); ch.push(2); REQUIRE(ch.size() == 2); ch.disable(); REQUIRE(ch.size() == 0); } TEST_CASE("enable re-accepts pushes after disable", "[channel]") { Channel ch(5); ch.disable(); ch.push(1); REQUIRE(ch.size() == 0); ch.enable(); ch.push(42); REQUIRE(ch.pop() == 42); } TEST_CASE("large type stored as shared_ptr — no copy on pop", "[channel]") { struct Big { char data[64]; int tag; }; Channel ch(5); Big b{}; b.tag = 123; ch.push(b); auto out = ch.pop(); REQUIRE(out.tag == 123); }