// Copyright 2015 The Chromium OS Authors. All rights reserved.
|
// Use of this source code is governed by a BSD-style license that can be
|
// found in the LICENSE file.
|
|
#include <stdint.h>
|
|
#include <vector>
|
|
#include "buffer_writer.h"
|
#include "compat/test.h"
|
|
namespace quipper {
|
|
// Move the cursor around and make sure the offset is properly set each time.
|
TEST(BufferWriterTest, MoveOffset) {
|
std::vector<uint8_t> buffer(1000);
|
|
BufferWriter writer(buffer.data(), buffer.size());
|
EXPECT_EQ(0, writer.Tell());
|
EXPECT_EQ(buffer.size(), writer.size());
|
|
// Move the write cursor around.
|
writer.SeekSet(100);
|
EXPECT_EQ(100, writer.Tell());
|
writer.SeekSet(900);
|
EXPECT_EQ(900, writer.Tell());
|
writer.SeekSet(500);
|
EXPECT_EQ(500, writer.Tell());
|
|
// The cursor can be set to past the end of the buffer, but can't perform any
|
// write operations there.
|
writer.SeekSet(1200);
|
EXPECT_EQ(1200, writer.Tell());
|
int dummy = 0;
|
EXPECT_FALSE(writer.WriteData(&dummy, sizeof(dummy)));
|
}
|
|
// Make sure that the writer can handle a write size of zero.
|
TEST(BufferWriterTest, WriteZeroBytes) {
|
std::vector<uint8_t> output(10);
|
BufferWriter writer(output.data(), output.size());
|
writer.SeekSet(5);
|
EXPECT_TRUE(writer.WriteData(NULL, 0));
|
// Make sure the write pointer hasn't moved.
|
EXPECT_EQ(5, writer.Tell());
|
}
|
|
// Write a chunk of data to the output buffer.
|
TEST(BufferWriterTest, WriteSingleChunk) {
|
const string kInputData = "abcdefghijklmnopqrstuvwxyz";
|
std::vector<uint8_t> output(kInputData.size());
|
BufferWriter writer(output.data(), output.size());
|
|
EXPECT_TRUE(writer.WriteData(kInputData.data(), kInputData.size()));
|
EXPECT_EQ(output.size(), writer.Tell());
|
|
// Compare input and output data, converting the latter to a string for
|
// clarity of error messages.
|
EXPECT_EQ(kInputData, string(output.begin(), output.end()));
|
}
|
|
// Test the WriteDataValue() function, which is a wrapper around WriteData().
|
TEST(BufferWriterTest, WriteDataValue) {
|
const string kInputData = "abcdefghijklmnopqrstuvwxyz";
|
std::vector<uint8_t> output(kInputData.size());
|
BufferWriter writer(output.data(), output.size());
|
|
EXPECT_TRUE(
|
writer.WriteDataValue(kInputData.data(), kInputData.size(), "data"));
|
EXPECT_EQ(output.size(), writer.Tell());
|
|
EXPECT_EQ(kInputData, string(output.begin(), output.end()));
|
}
|
|
// Write in all data from the input buffer in multiple chunks, in order.
|
TEST(BufferWriterTest, WriteMultipleChunks) {
|
// This string is 26 characters long.
|
const string kInputData = "abcdefghijklmnopqrstuvwxyz";
|
|
std::vector<uint8_t> output(kInputData.size());
|
BufferWriter writer(output.data(), output.size());
|
|
// Write all the data in multiple operations. Make sure the cursor is updated.
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 10));
|
EXPECT_EQ(10, writer.Tell());
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 5));
|
EXPECT_EQ(15, writer.Tell());
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 5));
|
EXPECT_EQ(20, writer.Tell());
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 6));
|
EXPECT_EQ(26, writer.Tell());
|
|
EXPECT_EQ(kInputData, string(output.begin(), output.end()));
|
}
|
|
// Write all data from the input buffer in multiple chunks, but not in order.
|
TEST(BufferWriterTest, WriteWithJumps) {
|
// This string contains four parts, each 10 characters long.
|
const string kInputData =
|
"0:abcdefg;"
|
"1:hijklmn;"
|
"2:opqrstu;"
|
"3:vwxyzABC";
|
|
std::vector<uint8_t> output(kInputData.size());
|
BufferWriter writer(output.data(), output.size());
|
|
writer.SeekSet(20);
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + 20, 10));
|
EXPECT_EQ(30, writer.Tell());
|
EXPECT_EQ("2:opqrstu;", string(output.begin() + 20, output.begin() + 30));
|
|
writer.SeekSet(10);
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + 10, 10));
|
EXPECT_EQ(20, writer.Tell());
|
EXPECT_EQ("1:hijklmn;", string(output.begin() + 10, output.begin() + 20));
|
|
writer.SeekSet(30);
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + 30, 10));
|
EXPECT_EQ(40, writer.Tell());
|
EXPECT_EQ("3:vwxyzABC", string(output.begin() + 30, output.begin() + 40));
|
|
writer.SeekSet(0);
|
EXPECT_TRUE(writer.WriteData(kInputData.data(), 10));
|
EXPECT_EQ(10, writer.Tell());
|
EXPECT_EQ("0:abcdefg;", string(output.begin(), output.begin() + 10));
|
}
|
|
// Test writing past the end of the buffer.
|
TEST(BufferWriterTest, WritePastEndOfData) {
|
// This string is 26 characters long.
|
const string kInputData = "abcdefghijklmnopqrstuvwxyz";
|
std::vector<uint8_t> output(kInputData.size());
|
BufferWriter writer(output.data(), output.size());
|
|
// Must not be able to write past the end of the buffer.
|
writer.SeekSet(0);
|
EXPECT_FALSE(writer.WriteData(kInputData.data() + writer.Tell(), 30));
|
// The write pointer should not have moved.
|
EXPECT_EQ(0, writer.Tell());
|
|
// Should still be able to write within the bounds of the buffer, despite the
|
// out-of-bounds write earlier.
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 13));
|
EXPECT_EQ(13, writer.Tell());
|
|
// Now attempt another write past the end of the buffer, but starting from the
|
// ending position of the previous write operation.
|
EXPECT_FALSE(writer.WriteData(kInputData.data() + writer.Tell(), 20));
|
// The write pointer should be unchanged.
|
EXPECT_EQ(13, writer.Tell());
|
|
// Write the rest of the data and make sure it matches the input.
|
EXPECT_TRUE(writer.WriteData(kInputData.data() + writer.Tell(), 13));
|
EXPECT_EQ(26, writer.Tell());
|
|
EXPECT_EQ(kInputData, string(output.begin(), output.end()));
|
}
|
|
// Test string writes.
|
TEST(BufferWriterTest, WriteString) {
|
// Construct an input string.
|
string input("The quick brown fox jumps over the lazy dog.");
|
|
// Write the full string.
|
std::vector<char> full_output(input.size());
|
BufferWriter full_writer(full_output.data(), full_output.size());
|
EXPECT_TRUE(full_writer.WriteString(input, input.size()));
|
EXPECT_EQ(input.size(), full_writer.Tell());
|
// There is no null pointer at the end of the output buffer, so create a
|
// string out of it using the known length of the input string.
|
EXPECT_EQ(input, string(full_output.data(), input.size()));
|
|
// Write the full string plus the null pointer.
|
std::vector<char> full_null_output(input.size() + 1);
|
BufferWriter full_null_writer(full_null_output.data(),
|
full_null_output.size());
|
EXPECT_TRUE(full_null_writer.WriteString(input, input.size() + 1));
|
EXPECT_EQ(input.size() + 1, full_null_writer.Tell());
|
// The null pointer should have been written. It should determine the end of
|
// the string.
|
EXPECT_EQ(input, string(full_null_output.data()));
|
|
// Write the first half of the string.
|
std::vector<char> half_output(input.size() / 2);
|
BufferWriter half_writer(half_output.data(), half_output.size());
|
EXPECT_TRUE(half_writer.WriteString(input, input.size() / 2));
|
EXPECT_EQ(input.size() / 2, half_writer.Tell());
|
// Null terminator is not guaranteed, so use the input string size to limit
|
// the output string during comparison.
|
EXPECT_EQ(input.substr(0, input.size() / 2),
|
string(half_output.data(), input.size() / 2));
|
|
// Attempt to write past the end of the buffer. Should fail.
|
std::vector<char> past_end_buffer(input.size());
|
BufferWriter past_end_writer(past_end_buffer.data(), past_end_buffer.size());
|
EXPECT_FALSE(past_end_writer.WriteString(input, input.size() + 2));
|
|
// Write string with some extra padding.
|
std::vector<char> extra_padding_output(input.size() + 10);
|
BufferWriter vector_writer(extra_padding_output.data(),
|
extra_padding_output.size());
|
EXPECT_TRUE(vector_writer.WriteString(input, extra_padding_output.size()));
|
// The writer should have written both the string data and padding bytes.
|
EXPECT_EQ(extra_padding_output.size(), vector_writer.Tell());
|
// But the string should still be null-terminated.
|
EXPECT_EQ(input, extra_padding_output.data());
|
}
|
|
// Writes data to a buffer and verifies that the buffer has not been modified
|
// beyond the writable boundaries.
|
TEST(BufferWriterTest, NoWritingOutOfBounds) {
|
// A sentinel value that fills memory to detect when that section of memory is
|
// overwritten. If the memory shows another value, it means it has been
|
// overwritten.
|
const uint8_t kUnwrittenValue = 0xaa;
|
|
std::vector<uint8_t> buffer(1000, kUnwrittenValue);
|
// Only write to the range [100, 900).
|
BufferWriter writer(buffer.data() + 100, 800);
|
|
// Create some input data that's filled with zeroes. Write this to the buffer.
|
std::vector<uint8_t> input(800, 0);
|
EXPECT_TRUE(writer.WriteData(input.data(), input.size()));
|
EXPECT_EQ(input.size(), writer.Tell());
|
|
// Check that the data was written to the writable part of the buffer.
|
EXPECT_EQ(input,
|
std::vector<uint8_t>(buffer.begin() + 100, buffer.begin() + 900));
|
|
// Now make sure that the other parts of the buffer haven't been overwritten.
|
const std::vector<uint8_t> expected_unwritten_part(100, kUnwrittenValue);
|
EXPECT_EQ(expected_unwritten_part,
|
std::vector<uint8_t>(buffer.begin(), buffer.begin() + 100));
|
EXPECT_EQ(expected_unwritten_part,
|
std::vector<uint8_t>(buffer.begin() + 900, buffer.begin() + 1000));
|
}
|
|
// Writes a string to a buffer and verifies that the buffer has not been
|
// modified beyond the writable boundaries.
|
TEST(BufferWriterTest, NoWritingStringOutOfBounds) {
|
// Construct an input string.
|
string input("This line is forty characters long.....");
|
|
// A sentinel value that fills memory to detect when that section of memory is
|
// overwritten. If the memory shows another value, it means it has been
|
// overwritten.
|
const uint8_t kUnwrittenValue = 0xaa;
|
std::vector<char> buffer(100, kUnwrittenValue);
|
|
// Only write to the range [20, 61). This includes enough space for the string
|
// and the null terminator. Make sure the string is short enough that it fits
|
// inside the buffer and leaves at least one byte of extra space at the end,
|
// beyond the null terminator.
|
ASSERT_LT(input.size() + 1, buffer.size() - 20);
|
BufferWriter writer(buffer.data() + 20, input.size() + 1);
|
|
// Write the string plus null terminator, and verify that it was written.
|
EXPECT_TRUE(writer.WriteString(input, input.size() + 1));
|
EXPECT_EQ(input, buffer.data() + 20);
|
EXPECT_EQ(input.size() + 1, writer.Tell());
|
|
// Now make sure that the other parts of the buffer haven't been overwritten.
|
EXPECT_EQ(std::vector<char>(20, kUnwrittenValue),
|
std::vector<char>(buffer.begin(), buffer.begin() + 20));
|
// There are 39 bytes between offset 61 (end of the string contents) and the
|
// end of the buffer.
|
EXPECT_EQ(std::vector<char>(39, kUnwrittenValue),
|
std::vector<char>(buffer.begin() + 61, buffer.end()));
|
}
|
|
} // namespace quipper
|