// SPDX-License-Identifier: MPL-2.0 #include "aare/ProducerConsumerQueue.hpp" #include #include #include #include using aare::ProducerConsumerQueue; // The queue is a fixed-capacity SPSC ring with const size and buffer, as in // the upstream folly implementation. Moving one is not thread safe and the // previous move operations left the source pointing at a null buffer, so the // type is deliberately neither copyable nor movable. Hold it by value or in a // unique_ptr instead. static_assert(!std::is_copy_constructible_v>); static_assert(!std::is_copy_assignable_v>); static_assert(!std::is_move_constructible_v>); static_assert(!std::is_move_assignable_v>); TEST_CASE("ProducerConsumerQueue round trips non trivial elements", "[queue]") { ProducerConsumerQueue q(3); // capacity 2 REQUIRE(q.capacity() == 2); REQUIRE(q.isEmpty()); REQUIRE(q.write(std::string(64, 'a'))); REQUIRE(q.write(std::string(64, 'b'))); CHECK(q.isFull()); CHECK_FALSE(q.write(std::string(64, 'c'))); std::string out; REQUIRE(q.read(out)); CHECK(out == std::string(64, 'a')); // Wrap around the ring and leave an element behind for the destructor. REQUIRE(q.write(std::string(64, 'd'))); REQUIRE(q.frontPtr() != nullptr); CHECK(*q.frontPtr() == std::string(64, 'b')); q.popFront(); CHECK(q.sizeGuess() == 1); } TEST_CASE("ProducerConsumerQueue rejects sizes below two in every build type", "[queue]") { // A plain assert would be compiled out in Release builds and a zero-size // queue would then overflow its buffer on the first write. CHECK_THROWS_AS(ProducerConsumerQueue(0), std::invalid_argument); CHECK_THROWS_AS(ProducerConsumerQueue(1), std::invalid_argument); ProducerConsumerQueue smallest(2); CHECK(smallest.capacity() == 1); CHECK(smallest.write(7)); CHECK(smallest.isFull()); }