* add buffered writer * rename
This commit is contained in:
parent
f5cece03e5
commit
605e2590f1
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
|
||||
struct Writer {
|
||||
virtual size_t write(const char* buffer, size_t count) = 0;
|
||||
virtual size_t flush() = 0;
|
||||
};
|
||||
|
||||
template <int TBufferSize>
|
||||
class BufferedWriter : public Writer {
|
||||
public:
|
||||
size_t write(const char* buffer, size_t count) override {
|
||||
size_t bytesFlushed = 0;
|
||||
|
||||
while (count) {
|
||||
if (m_bytesUsed == 0 && count >= TBufferSize) {
|
||||
// special case: write-thru, skip the copy
|
||||
bytesFlushed += writeInternal(buffer, count);
|
||||
count = 0;
|
||||
} else if (m_bytesUsed + count < TBufferSize) {
|
||||
// Write that will fit in the buffer, just copy to intermediate buffer
|
||||
memcpy(m_buffer + m_bytesUsed, buffer, count);
|
||||
m_bytesUsed += count;
|
||||
count = 0;
|
||||
} else {
|
||||
// Need to write partial, then flush buffer
|
||||
size_t bytesToWrite = TBufferSize - m_bytesUsed;
|
||||
// Copy this block in to place
|
||||
memcpy(m_buffer + m_bytesUsed, buffer, bytesToWrite);
|
||||
m_bytesUsed += bytesToWrite;
|
||||
|
||||
// Flush to underlying
|
||||
bytesFlushed += flush();
|
||||
// Step the read pointer ahead
|
||||
buffer += bytesToWrite;
|
||||
// Decrement remaining bytes
|
||||
count -= bytesToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesFlushed;
|
||||
}
|
||||
|
||||
// Flush the internal buffer to the underlying interface.
|
||||
size_t flush() override {
|
||||
size_t bytesToWrite = m_bytesUsed;
|
||||
|
||||
if (bytesToWrite > 0) {
|
||||
m_bytesUsed = 0;
|
||||
return writeInternal(m_buffer, bytesToWrite);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual size_t writeInternal(const char* buffer, size_t count) = 0;
|
||||
|
||||
private:
|
||||
char m_buffer[TBufferSize];
|
||||
size_t m_bytesUsed = 0;
|
||||
};
|
|
@ -14,6 +14,7 @@ TESTS_SRC_CPP = \
|
|||
tests/ignition_injection/test_fuelCut.cpp \
|
||||
tests/ignition_injection/test_fuel_computer.cpp \
|
||||
tests/ignition_injection/test_injector_model.cpp \
|
||||
tests/util/test_buffered_writer.cpp \
|
||||
tests/test_util.cpp \
|
||||
tests/test_hardware_reinit.cpp \
|
||||
tests/test_ion.cpp \
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#include "buffered_writer.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
template <int TBufferSize>
|
||||
struct MockBufferedWriter : public BufferedWriter<TBufferSize>
|
||||
{
|
||||
MOCK_METHOD(size_t, writeInternal, (const char*, size_t), (override));
|
||||
};
|
||||
|
||||
static const char* testBuffer = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
TEST(BufferedWriter, WriteSmall) {
|
||||
// No calls to dut expected
|
||||
StrictMock<MockBufferedWriter<10>> dut;
|
||||
|
||||
EXPECT_EQ(0, dut.write(testBuffer, 5));
|
||||
}
|
||||
|
||||
TEST(BufferedWriter, WriteSmallFlush) {
|
||||
StrictMock<MockBufferedWriter<10>> dut;
|
||||
EXPECT_CALL(dut, writeInternal(_, 5)).WillOnce(Return(5));
|
||||
|
||||
ASSERT_EQ(0, dut.write(testBuffer, 5));
|
||||
|
||||
EXPECT_EQ(dut.flush(), 5);
|
||||
}
|
||||
|
||||
TEST(BufferedWriter, WriteMultipleSmall) {
|
||||
StrictMock<MockBufferedWriter<10>> dut;
|
||||
{
|
||||
EXPECT_CALL(dut, writeInternal(_, 10)).WillOnce(Return(10));
|
||||
EXPECT_CALL(dut, writeInternal(_, 2)).WillOnce(Return(2));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, dut.write(testBuffer, 3));
|
||||
EXPECT_EQ(0, dut.write(testBuffer, 3));
|
||||
EXPECT_EQ(0, dut.write(testBuffer, 3));
|
||||
EXPECT_EQ(10, dut.write(testBuffer, 3)); // <- this one should trigger a flush
|
||||
|
||||
// Flush the remainder
|
||||
EXPECT_EQ(dut.flush(), 2);
|
||||
}
|
||||
|
||||
TEST(BufferedWriter, WriteSingleFullBufferSize) {
|
||||
StrictMock<MockBufferedWriter<50>> dut;
|
||||
|
||||
EXPECT_CALL(dut, writeInternal(_, 50)).WillOnce(Return(50));
|
||||
|
||||
EXPECT_EQ(50, dut.write(testBuffer, 50));
|
||||
|
||||
// Nothing left to flush!
|
||||
EXPECT_EQ(0, dut.flush());
|
||||
}
|
||||
|
||||
TEST(BufferedWriter, WriteLarge) {
|
||||
StrictMock<MockBufferedWriter<10>> dut;
|
||||
|
||||
{
|
||||
EXPECT_CALL(dut, writeInternal(_, 45)).WillOnce(Return(45));
|
||||
}
|
||||
|
||||
EXPECT_EQ(45, dut.write(testBuffer, 45));
|
||||
|
||||
EXPECT_EQ(0, dut.flush());
|
||||
}
|
||||
|
||||
TEST(BufferedWriter, WriteLargeAfterSmall) {
|
||||
StrictMock<MockBufferedWriter<10>> dut;
|
||||
|
||||
{
|
||||
EXPECT_CALL(dut, writeInternal(_, 10)).WillOnce(Return(10));
|
||||
EXPECT_CALL(dut, writeInternal(_, 36)).WillOnce(Return(36));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, dut.write(testBuffer, 1));
|
||||
|
||||
EXPECT_EQ(46, dut.write(testBuffer, 45));
|
||||
|
||||
EXPECT_EQ(0, dut.flush());
|
||||
}
|
Loading…
Reference in New Issue