#define CATCH_CONFIG_MAIN #include #include /* * Define values we expect during testing. */ #define KI_TEST_BITSTREAM_BUI1 0b1 #define KI_TEST_BITSTREAM_BUI2 0b10 #define KI_TEST_BITSTREAM_BUI3 0b010 #define KI_TEST_BITSTREAM_BUI4 0b0101 #define KI_TEST_BITSTREAM_BUI5 0b10101 #define KI_TEST_BITSTREAM_BUI6 0b101010 #define KI_TEST_BITSTREAM_BUI7 0b0101010 #define KI_TEST_BITSTREAM_U8 0x01 #define KI_TEST_BITSTREAM_U16 0x0302 #define KI_TEST_BITSTREAM_U24 0x060504 #define KI_TEST_BITSTREAM_U32 0x0A090807 #define KI_TEST_BITSTREAM_U64 0x1211100F0E0D0C0BL #define KI_TEST_WRITE_BUI(n) bit_stream->write(KI_TEST_BITSTREAM_BUI##n, n) #define KI_TEST_READ_BUI(n) bit_stream->read(n) == KI_TEST_BITSTREAM_BUI##n using namespace ki; TEST_CASE("BitStream Functionality", "[bit-stream]") { auto *bit_stream = new BitStream(); SECTION("Writing values with a size less than 8 bits") { // Write an alternating pattern of bits KI_TEST_WRITE_BUI(1); KI_TEST_WRITE_BUI(2); KI_TEST_WRITE_BUI(3); KI_TEST_WRITE_BUI(4); KI_TEST_WRITE_BUI(5); KI_TEST_WRITE_BUI(6); KI_TEST_WRITE_BUI(7); KI_TEST_WRITE_BUI(4); // Make sure tell is reporting the right position auto position = bit_stream->tell(); if (position.get_byte() != 4 || position.get_bit() != 0) FAIL(); const auto size = position.get_byte(); // Validate what we've got here with a hand-written sample std::ifstream sample("samples/bitstream1.bin", std::ios::binary); if (!sample.is_open()) FAIL(); // Load the sample data and compare auto *sample_data = new char[size + 1]{ 0 }; sample.read(sample_data, size); if (strcmp(sample_data, (char *)bit_stream->data()) != 0) FAIL(); // Free resources delete[] sample_data; SUCCEED(); } SECTION("Writing values with a size greater than 8 bits") { // Write some values bit_stream->write(KI_TEST_BITSTREAM_U8, 8); bit_stream->write(KI_TEST_BITSTREAM_U16, 16); bit_stream->write(KI_TEST_BITSTREAM_U24, 24); bit_stream->write(KI_TEST_BITSTREAM_U32, 32); bit_stream->write(KI_TEST_BITSTREAM_U64, 64); // Make sure tell is reporting the right position auto position = bit_stream->tell(); if (position.get_byte() != 18 || position.get_bit() != 0) FAIL(); const auto size = position.get_byte(); // Validate what we've got here with a hand-written sample std::ifstream sample("samples/bitstream2.bin", std::ios::binary); if (!sample.is_open()) FAIL(); // Load the sample data and compare auto *sample_data = new char[size + 1]{ 0 }; sample.read(sample_data, size); if (strcmp(sample_data, (char *)bit_stream->data()) != 0) FAIL(); // Free resources delete[] sample_data; SUCCEED(); } SECTION("Reading values with a size lower than 8 bits") { // Open a previously hand-written sample std::ifstream sample("samples/bitstream1.bin", std::ios::binary); if (!sample.is_open()) FAIL(); // Load the sample data into the bit stream const auto begin = sample.tellg(); sample.seekg(0, std::ios::end); const auto end = sample.tellg(); const size_t size = end - begin; sample.seekg(std::ios::beg); sample.read((char *)bit_stream->data(), size); // Read the values and check they are what we are expecting if (!KI_TEST_READ_BUI(1)) FAIL(); if (!KI_TEST_READ_BUI(2)) FAIL(); if (!KI_TEST_READ_BUI(3)) FAIL(); if (!KI_TEST_READ_BUI(4)) FAIL(); if (!KI_TEST_READ_BUI(5)) FAIL(); if (!KI_TEST_READ_BUI(6)) FAIL(); if (!KI_TEST_READ_BUI(7)) FAIL(); if (!KI_TEST_READ_BUI(4)) FAIL(); SUCCEED(); } SECTION("Reading values with a size greater than 8 bits") { // Open a previously hand-written sample std::ifstream sample("samples/bitstream2.bin", std::ios::binary); if (!sample.is_open()) FAIL(); // Load the sample data into the bit stream const auto begin = sample.tellg(); sample.seekg(0, std::ios::end); const auto end = sample.tellg(); const size_t size = end - begin; sample.seekg(std::ios::beg); sample.read((char *)bit_stream->data(), size); // Read the values and check they are what we are expecting if (bit_stream->read(8) != KI_TEST_BITSTREAM_U8) FAIL(); if (bit_stream->read(16) != KI_TEST_BITSTREAM_U16) FAIL(); if (bit_stream->read(24) != KI_TEST_BITSTREAM_U24) FAIL(); if (bit_stream->read(32) != KI_TEST_BITSTREAM_U32) FAIL(); if (bit_stream->read(64) != KI_TEST_BITSTREAM_U64) FAIL(); SUCCEED(); } SECTION("Buffer underflow") { try { // Attempt to set the position less than 0 bit_stream->seek(BitStream::stream_pos(-1, 0)); FAIL(); } catch (std::runtime_error &e) { // An exception was thrown, which is intended behaviour SUCCEED(); } } // Free resources delete bit_stream; } TEST_CASE("BitStream buffer expansion", "[bit-stream]") { // Create a very small buffer that we know is going to expand auto *bit_stream = new BitStream(1); // Write a byte, and then check if the capacity grows bit_stream->write(0x55, 8); if (bit_stream->capacity() != 6) FAIL(); // Go back to the first byte, and make sure what we wrote stuck // around after the expansion bit_stream->seek(BitStream::stream_pos(0, 0)); if (bit_stream->read(8) != 0x55) FAIL(); // Free resources delete bit_stream; SUCCEED(); }