#include "asl/buffer.hpp" #include "asl/testing/testing.hpp" #include "asl/tests/test_types.hpp" struct Big { uint64_t data[8]; }; static_assert(asl::buffer::kInlineCapacity == 5); static_assert(asl::buffer::kInlineCapacity == 2); static_assert(asl::buffer::kInlineCapacity == 23); static_assert(asl::buffer::kInlineCapacity == 0); ASL_TEST(default_size) { asl::buffer b1; ASL_TEST_EXPECT(b1.size() == 0); ASL_TEST_EXPECT(b1.capacity() == 5); ASL_TEST_EXPECT(static_cast(b1.data()) == &b1); asl::buffer b2; ASL_TEST_EXPECT(b2.size() == 0); ASL_TEST_EXPECT(b2.capacity() == 0); ASL_TEST_EXPECT(b2.data() == nullptr); } struct CounterAllocator { isize_t* count; void* alloc(const asl::layout& layout) const { *count += 1; return asl::GlobalHeap::alloc(layout); } void* realloc(void* ptr, const asl::layout& old, const asl::layout& new_layout) const { *count += 1; return asl::GlobalHeap::realloc(ptr, old, new_layout); } static void dealloc(void* ptr, const asl::layout& layout) { asl::GlobalHeap::dealloc(ptr, layout); } constexpr bool operator==(const CounterAllocator&) const { return true; } }; static_assert(asl::allocator); ASL_TEST(reserve_capacity) { isize_t count = 0; asl::buffer b(CounterAllocator{&count}); ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() == 5); ASL_TEST_EXPECT(count == 0); b.reserve_capacity(4); ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() == 5); ASL_TEST_EXPECT(count == 0); b.reserve_capacity(12); ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() >= 12); ASL_TEST_EXPECT(count == 1); b.reserve_capacity(13); ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() >= 13); ASL_TEST_EXPECT(count == 1); b.reserve_capacity(130); ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() >= 130); ASL_TEST_EXPECT(count == 2); } ASL_TEST(push) { asl::buffer b; ASL_TEST_EXPECT(b.size() == 0); b.push(1); ASL_TEST_EXPECT(b.size() == 1); ASL_TEST_EXPECT(b[0] == 1); b.push(2); b.push(3); ASL_TEST_EXPECT(b.size() == 3); ASL_TEST_EXPECT(b[0] == 1); ASL_TEST_EXPECT(b[1] == 2); ASL_TEST_EXPECT(b[2] == 3); b.push(4); b.push(5); b.push(6); b.push(7); ASL_TEST_EXPECT(b.size() == 7); ASL_TEST_EXPECT(b[0] == 1); ASL_TEST_EXPECT(b[1] == 2); ASL_TEST_EXPECT(b[2] == 3); ASL_TEST_EXPECT(b[3] == 4); ASL_TEST_EXPECT(b[4] == 5); ASL_TEST_EXPECT(b[5] == 6); ASL_TEST_EXPECT(b[6] == 7); } struct MoveableType { int moved{}; int value; explicit MoveableType(int x) : value{x} {} MoveableType(const MoveableType&) = delete; MoveableType(MoveableType&& other) : moved{other.moved + 1}, value{other.value} {} MoveableType& operator=(const MoveableType&) = delete; MoveableType& operator=(MoveableType&&) = delete; }; static_assert(!asl::trivially_copy_constructible); static_assert(!asl::trivially_move_constructible); static_assert(!asl::copyable); static_assert(asl::move_constructible); ASL_TEST(push_move) { asl::buffer b; static_assert(asl::buffer::kInlineCapacity > 0); b.push(0); ASL_TEST_EXPECT(b[0].value == 0); ASL_TEST_EXPECT(b[0].moved == 0); b.push(1); ASL_TEST_EXPECT(b[0].value == 0); ASL_TEST_EXPECT(b[0].moved == 0); ASL_TEST_EXPECT(b[1].value == 1); ASL_TEST_EXPECT(b[1].moved == 0); b.push(2); ASL_TEST_EXPECT(b[0].value == 0); ASL_TEST_EXPECT(b[0].moved == 1); ASL_TEST_EXPECT(b[1].value == 1); ASL_TEST_EXPECT(b[1].moved == 1); ASL_TEST_EXPECT(b[2].value == 2); ASL_TEST_EXPECT(b[2].moved == 0); b.push(3); ASL_TEST_EXPECT(b[0].value == 0); ASL_TEST_EXPECT(b[0].moved == 1); ASL_TEST_EXPECT(b[1].value == 1); ASL_TEST_EXPECT(b[1].moved == 1); ASL_TEST_EXPECT(b[2].value == 2); ASL_TEST_EXPECT(b[2].moved == 0); ASL_TEST_EXPECT(b[3].value == 3); ASL_TEST_EXPECT(b[3].moved == 0); b.push(4); ASL_TEST_EXPECT(b[0].value == 0); ASL_TEST_EXPECT(b[0].moved == 2); ASL_TEST_EXPECT(b[1].value == 1); ASL_TEST_EXPECT(b[1].moved == 2); ASL_TEST_EXPECT(b[2].value == 2); ASL_TEST_EXPECT(b[2].moved == 1); ASL_TEST_EXPECT(b[3].value == 3); ASL_TEST_EXPECT(b[3].moved == 1); ASL_TEST_EXPECT(b[4].value == 4); ASL_TEST_EXPECT(b[4].moved == 0); } ASL_TEST(clear) { asl::buffer b; ASL_TEST_EXPECT(b.size() == 0); b.push(1); b.push(2); b.push(3); b.push(4); b.push(5); b.push(6); b.push(7); ASL_TEST_EXPECT(b.size() == 7); b.clear(); ASL_TEST_EXPECT(b.size() == 0); } ASL_TEST(clear_destructor_small) { bool d0 = false; bool d1 = false; asl::buffer buf; static_assert(asl::buffer::kInlineCapacity >= 2); buf.push(&d0); buf.push(&d1); buf.clear(); ASL_TEST_EXPECT(d0 == true); ASL_TEST_EXPECT(d1 == true); } ASL_TEST(clear_destructor_heap) { bool d0 = false; bool d1 = false; bool d2 = false; asl::buffer buf; static_assert(asl::buffer::kInlineCapacity < 3); buf.push(&d0); buf.push(&d1); buf.push(&d2); ASL_TEST_EXPECT(d0 == false); ASL_TEST_EXPECT(d1 == false); ASL_TEST_EXPECT(d2 == false); buf.clear(); ASL_TEST_EXPECT(d0 == true); ASL_TEST_EXPECT(d1 == true); ASL_TEST_EXPECT(d2 == true); } ASL_TEST(move_construct_from_heap) { bool d[3]{}; asl::buffer buf; buf.push(&d[0]); buf.push(&d[1]); buf.push(&d[2]); { asl::buffer buf2(ASL_MOVE(buf)); ASL_TEST_EXPECT(buf2.size() == 3); ASL_TEST_EXPECT(d[0] == false); ASL_TEST_EXPECT(d[1] == false); ASL_TEST_EXPECT(d[2] == false); } ASL_TEST_EXPECT(buf.size() == 0); ASL_TEST_EXPECT(d[0] == true); ASL_TEST_EXPECT(d[1] == true); ASL_TEST_EXPECT(d[2] == true); } ASL_TEST(move_construct_inline_trivial) { asl::buffer buf; buf.push(1U); buf.push(2U); asl::buffer buf2(ASL_MOVE(buf)); ASL_TEST_EXPECT(buf2[0] == 1U); ASL_TEST_EXPECT(buf2[1] == 2U); ASL_TEST_EXPECT(buf2.size() == 2); ASL_TEST_EXPECT(buf.size() == 0); } ASL_TEST(move_construct_from_inline_non_trivial) { bool d[2]{}; asl::buffer buf; buf.push(&d[0]); buf.push(&d[1]); { asl::buffer buf2(ASL_MOVE(buf)); ASL_TEST_EXPECT(buf2.size() == 2); ASL_TEST_EXPECT(d[0] == false); ASL_TEST_EXPECT(d[1] == false); } ASL_TEST_EXPECT(buf.size() == 0); ASL_TEST_EXPECT(d[0] == true); ASL_TEST_EXPECT(d[1] == true); }