util: Fix buffer expansion and reformat unit tests

This commit is contained in:
Joshua Scott 2018-10-20 18:17:35 +01:00
parent 5183131b69
commit 3f5450c64e
5 changed files with 179 additions and 115 deletions

View File

@ -21,4 +21,4 @@ steps:
- task: PublishTestResults@2 - task: PublishTestResults@2
inputs: inputs:
testResultsFormat: 'JUnit' testResultsFormat: 'JUnit'
testResultsFiles: 'build/**/test-*.xml' testResultsFiles: 'build/Testing/reports/test-*.xml'

View File

@ -56,6 +56,11 @@ namespace ki
*/ */
void seek(stream_pos position); void seek(stream_pos position);
/**
* @return The current size of the internal buffer.
*/
std::size_t capacity() const;
/** /**
* @return A pointer to the start of the internal buffer. * @return A pointer to the start of the internal buffer.
*/ */

View File

@ -141,7 +141,12 @@ namespace ki
validate_buffer(); validate_buffer();
} }
const uint8_t* BitStream::data() const std::size_t BitStream::capacity() const
{
return m_buffer_size;
}
const uint8_t *BitStream::data() const
{ {
return m_buffer; return m_buffer;
} }
@ -149,7 +154,7 @@ namespace ki
void BitStream::expand_buffer() void BitStream::expand_buffer()
{ {
// Work out a new buffer size // Work out a new buffer size
auto new_size = (2 << (uint64_t)log2(m_position.get_byte())) + 2; auto new_size = (2 << (uint64_t)log2(m_position.get_byte()) + 1) + 2;
if (new_size < m_buffer_size) if (new_size < m_buffer_size)
new_size = std::numeric_limits<size_t>::max(); new_size = std::numeric_limits<size_t>::max();
@ -162,6 +167,7 @@ namespace ki
std::memcpy(new_buffer, m_buffer, m_buffer_size); std::memcpy(new_buffer, m_buffer, m_buffer_size);
delete[] m_buffer; delete[] m_buffer;
m_buffer = new_buffer; m_buffer = new_buffer;
m_buffer_size = new_size;
} }
void BitStream::validate_buffer() void BitStream::validate_buffer()

View File

@ -3,6 +3,7 @@ add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
file(COPY "samples" DESTINATION "${PROJECT_BINARY_DIR}/test") file(COPY "samples" DESTINATION "${PROJECT_BINARY_DIR}/test")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/reports/")
file(GLOB files "src/unit-*.cpp") file(GLOB files "src/unit-*.cpp")
foreach (file ${files}) foreach (file ${files})
@ -15,5 +16,5 @@ foreach (file ${files})
CXX_STANDARD 11 CXX_STANDARD 11
) )
target_link_libraries(${testcase} Catch ${PROJECT_NAME}) target_link_libraries(${testcase} Catch ${PROJECT_NAME})
add_test(${testcase} ${testcase} -s -r junit -o ${PROJECT_BINARY_DIR}/Testing/${testcase}.xml) add_test(${testcase} ${testcase} -s -r junit -o "${PROJECT_BINARY_DIR}/Testing/reports/${testcase}.xml")
endforeach() endforeach()

View File

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