/* * Copyright (c) 2024 - 2025 Ember * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include using namespace std::literals; using namespace ember; TEST(StaticBuffer, InitialEmpty) { spark::io::StaticBuffer buffer; ASSERT_TRUE(buffer.empty()); ASSERT_EQ(buffer.size(), 0); } TEST(StaticBuffer, InitialNotEmpty) { spark::io::StaticBuffer buffer { '1', '2' }; ASSERT_FALSE(buffer.empty()); ASSERT_EQ(buffer.size(), 2); ASSERT_EQ(buffer[0], '1'); ASSERT_EQ(buffer[1], '2'); } TEST(StaticBuffer, Empty) { spark::io::StaticBuffer buffer; ASSERT_TRUE(buffer.empty()); char val = '\0'; buffer.write(&val, 1); ASSERT_FALSE(buffer.empty()); } TEST(StaticBuffer, ReadOne) { spark::io::StaticBuffer buffer { '1', '2', '3' }; char value = 0; buffer.read(&value, 1); ASSERT_EQ(buffer.size(), 2); ASSERT_EQ(value, '1'); } TEST(StaticBuffer, ReadAll) { spark::io::StaticBuffer buffer { '1', '2', '3' }; std::array expected{ '1', '2', '3' }; std::array values{}; buffer.read(values.data(), values.size()); ASSERT_TRUE(std::ranges::equal(values, expected)); } TEST(StaticBuffer, SingleSkipRead) { spark::io::StaticBuffer buffer { '1', '2', '3' }; std::uint8_t value = 0; buffer.skip(1); buffer.read(&value, 1); ASSERT_EQ(buffer.size(), 1); ASSERT_EQ(buffer[0], '3'); } TEST(StaticBuffer, MultiskipRead) { spark::io::StaticBuffer buffer { '1', '2', '3', '4', '5', '6' }; std::uint8_t value = 0; buffer.skip(5); buffer.read(&value, 1); ASSERT_TRUE(buffer.empty()); ASSERT_EQ(value, '6'); } TEST(StaticBuffer, Write) { spark::io::StaticBuffer buffer; const std::array values { 1, 2, 3, 4, 5, 6 }; buffer.write(values.data(), values.size()); ASSERT_EQ(buffer.size(), values.size()); ASSERT_TRUE(std::ranges::equal(values, buffer)); } TEST(StaticBuffer, CanWriteSeek) { spark::io::StaticBuffer buffer; ASSERT_TRUE(buffer.can_write_seek()); } TEST(StaticBuffer, WriteSeekBack) { spark::io::StaticBuffer buffer { '1', '2', '3' }; std::array values { '5', '6' }; buffer.write_seek(spark::io::BufferSeek::sk_backward, 2); buffer.write(values.data(), values.size()); std::array expected { '1', '5', '6' }; ASSERT_TRUE(std::ranges::equal(expected, buffer)); } TEST(StaticBuffer, WriteSeekStart) { spark::io::StaticBuffer buffer { '1', '2', '3' }; std::array values { '4', '5', '6' }; buffer.write_seek(spark::io::BufferSeek::sk_absolute, 0); buffer.write(values.data(), values.size()); ASSERT_EQ(buffer.size(), values.size()); ASSERT_TRUE(std::ranges::equal(buffer, values)); } TEST(StaticBuffer, ReadPtr) { spark::io::StaticBuffer buffer { '1', '2', '3' }; auto ptr = buffer.read_ptr(); ASSERT_EQ(*ptr, buffer[0]); buffer.skip(1); ptr = buffer.read_ptr(); ASSERT_EQ(*ptr, buffer[0]); buffer.skip(1); ptr = buffer.read_ptr(); ASSERT_EQ(*ptr, buffer[0]); } TEST(StaticBuffer, Subscript) { spark::io::StaticBuffer buffer { '1', '2', '3' }; ASSERT_EQ(buffer[0], '1'); ASSERT_EQ(buffer[1], '2'); ASSERT_EQ(buffer[2], '3'); buffer[0] = '4'; ASSERT_EQ(buffer[0], '4'); buffer[0] = '5'; ASSERT_EQ(buffer[0], '5'); ASSERT_EQ(buffer[0], buffer[0]); } TEST(StaticBuffer, FindFirstOf) { spark::io::StaticBuffer buffer; const auto str = "The quick brown fox jumped over the lazy dog"sv; buffer.write(str.data(), str.size()); auto pos = buffer.find_first_of('\0'); ASSERT_EQ(pos, buffer.npos); // direct string write is not terminated pos = buffer.find_first_of('g'); ASSERT_EQ(pos, 43); pos = buffer.find_first_of('T'); ASSERT_EQ(pos, 0); pos = buffer.find_first_of('t'); ASSERT_EQ(pos, 32); } TEST(StaticBuffer, AdvanceWrite) { spark::io::StaticBuffer buffer { 'a', 'b', 'c' }; buffer.write_seek(spark::io::BufferSeek::sk_absolute, 0); const char val = 'd'; buffer.advance_write(1); buffer.write(&val, 1); ASSERT_EQ(buffer[1], val); } TEST(StaticBuffer, Defragment) { spark::io::StaticBuffer buffer { 'a', 'b', 'c' }; ASSERT_EQ(buffer.free(), 0); char value = 0; buffer.read(&value, sizeof(value)); ASSERT_EQ(value, 'a'); ASSERT_EQ(buffer.free(), 0); buffer.defragment(); ASSERT_EQ(buffer.free(), 1); buffer.copy(&value, sizeof(value)); ASSERT_EQ(value, 'b'); ASSERT_EQ(buffer[0], 'b'); ASSERT_EQ(*buffer.read_ptr(), 'b'); buffer.read(&value, sizeof(value)); ASSERT_EQ(value, 'b'); buffer.read(&value, sizeof(value)); ASSERT_EQ(value, 'c'); ASSERT_THROW(buffer.read(&value, sizeof(value)), spark::io::buffer_underrun); } TEST(StaticBuffer, Free) { spark::io::StaticBuffer buffer; ASSERT_EQ(buffer.free(), 3); char value = 0; buffer.write(&value, sizeof(value)); ASSERT_EQ(buffer.free(), 2); buffer.write(&value, sizeof(value)); ASSERT_EQ(buffer.free(), 1); buffer.write(&value, sizeof(value)); ASSERT_EQ(buffer.free(), 0); ASSERT_THROW(buffer.write(&value, sizeof(value)), spark::io::buffer_overflow); }