blob: 0d9c135da381c6f155421347d2396db9a4f15af1 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
#include "gtest/gtest.h"
#include "garnet/drivers/bluetooth/lib/common/test_helpers.h"
namespace btlib {
namespace common {
namespace {
TEST(ByteBufferTest, StaticByteBuffer) {
constexpr size_t kBufferSize = 5;
StaticByteBuffer<kBufferSize> buffer;
EXPECT_EQ(kBufferSize, buffer.size());
buffer.SetToZeros();
buffer[3] = 3;
constexpr std::array<uint8_t, kBufferSize> kExpected{
{0x00, 0x00, 0x00, 0x03, 0x00}};
EXPECT_TRUE(ContainersEqual(kExpected, buffer));
// Moving will result in a copy.
StaticByteBuffer<kBufferSize> buffer_copy = std::move(buffer);
EXPECT_EQ(kBufferSize, buffer.size());
EXPECT_EQ(kBufferSize, buffer_copy.size());
EXPECT_TRUE(ContainersEqual(kExpected, buffer));
EXPECT_TRUE(ContainersEqual(kExpected, buffer_copy));
// Copying should also copy.
StaticByteBuffer<kBufferSize> buffer_copy1 = buffer;
EXPECT_EQ(kBufferSize, buffer.size());
EXPECT_EQ(kBufferSize, buffer_copy1.size());
EXPECT_TRUE(ContainersEqual(kExpected, buffer));
EXPECT_TRUE(ContainersEqual(kExpected, buffer_copy1));
}
TEST(ByteBufferTest, StaticByteBufferVariadicConstructor) {
constexpr size_t kBufferSize = 3;
StaticByteBuffer<kBufferSize> buffer0;
buffer0[0] = 0x01;
buffer0[1] = 0x02;
buffer0[2] = 0x03;
StaticByteBuffer<kBufferSize> buffer1{0x01, 0x02, 0x03};
auto buffer2 = CreateStaticByteBuffer(0x01, 0x02, 0x03);
EXPECT_TRUE(ContainersEqual(buffer0, buffer1));
EXPECT_TRUE(ContainersEqual(buffer0, buffer2));
EXPECT_TRUE(ContainersEqual(buffer1, buffer2));
}
TEST(ByteBufferTest, DynamicByteBuffer) {
constexpr size_t kBufferSize = 5;
DynamicByteBuffer buffer(kBufferSize);
EXPECT_EQ(kBufferSize, buffer.size());
buffer.SetToZeros();
buffer[3] = 3;
constexpr std::array<uint8_t, kBufferSize> kExpected{
{0x00, 0x00, 0x00, 0x03, 0x00}};
EXPECT_TRUE(ContainersEqual(kExpected, buffer));
// Moving will invalidate the source buffer.
DynamicByteBuffer buffer_moved = std::move(buffer);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(kBufferSize, buffer_moved.size());
EXPECT_EQ(nullptr, buffer.data());
EXPECT_TRUE(ContainersEqual(kExpected, buffer_moved));
}
TEST(ByteBufferTest, DynamicByteBufferZeroSize) {
DynamicByteBuffer buffer;
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(nullptr, buffer.data());
DynamicByteBuffer zerosize(0);
EXPECT_EQ(0u, zerosize.size());
EXPECT_EQ(nullptr, buffer.data());
}
TEST(ByteBufferTest, DynamicByteBufferConstructFromBuffer) {
constexpr size_t kBufferSize = 3;
StaticByteBuffer<kBufferSize> buffer({1, 2, 3});
DynamicByteBuffer dyn_buffer(buffer);
EXPECT_EQ(kBufferSize, dyn_buffer.size());
EXPECT_TRUE(ContainersEqual(buffer, dyn_buffer));
}
TEST(ByteBufferTest, DynamicByteBufferConstructFromBytes) {
constexpr size_t kBufferSize = 3;
std::array<uint8_t, kBufferSize> kExpected{{0, 1, 2}};
auto bytes = std::make_unique<uint8_t[]>(kBufferSize);
std::memcpy(bytes.get(), kExpected.data(), kBufferSize);
DynamicByteBuffer buffer(kBufferSize, std::move(bytes));
EXPECT_EQ(nullptr, bytes.get());
EXPECT_TRUE(ContainersEqual(kExpected, buffer));
}
TEST(ByteBufferTest, BufferViewTest) {
constexpr size_t kBufferSize = 5;
DynamicByteBuffer buffer(kBufferSize);
EXPECT_EQ(kBufferSize, buffer.size());
buffer.SetToZeros();
BufferView view(buffer);
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x00, view[0]);
EXPECT_EQ(kBufferSize, buffer.size());
EXPECT_EQ(kBufferSize, view.size());
}
TEST(ByteBufferTest, MutableBufferViewTest) {
constexpr size_t kBufferSize = 5;
constexpr size_t kViewSize = 3;
DynamicByteBuffer buffer(kBufferSize);
EXPECT_EQ(kBufferSize, buffer.size());
buffer.SetToZeros();
MutableBufferView view(buffer.mutable_data(), kViewSize);
view[0] = 0x01;
EXPECT_EQ(0x01, buffer[0]);
EXPECT_EQ(0x01, view[0]);
EXPECT_EQ(kBufferSize, buffer.size());
EXPECT_EQ(kViewSize, view.size());
MutableBufferView view2(view);
view2[0] = 0x00;
EXPECT_EQ(0x00, buffer[0]);
EXPECT_EQ(0x00, view[0]);
EXPECT_EQ(0x00, view2[0]);
EXPECT_EQ(kBufferSize, buffer.size());
EXPECT_EQ(kViewSize, view.size());
}
TEST(ByteBufferTest, Copy) {
auto buffer = common::CreateStaticByteBuffer('T', 'e', 's', 't');
BufferView empty_buffer;
// Create a large enough buffer.
StaticByteBuffer<10> target_buffer;
// Copying an empty buffer should copy 0 bytes.
EXPECT_EQ(0u, empty_buffer.Copy(&target_buffer));
// Copy all of |buffer|. The first |buffer.size()| octets of |target_buffer|
// should match the contents of |buffer|.
size_t expected_write_size = buffer.size();
ASSERT_EQ(expected_write_size, buffer.Copy(&target_buffer));
EXPECT_TRUE(
ContainersEqual(buffer, BufferView(target_buffer, expected_write_size)));
// Copy all of |buffer| starting at index 1.
target_buffer.SetToZeros();
expected_write_size = buffer.size() - 1;
ASSERT_EQ(expected_write_size, buffer.Copy(&target_buffer, 1));
BufferView sub = buffer.view(1);
EXPECT_TRUE(
ContainersEqual(sub, BufferView(target_buffer, expected_write_size)));
// Copy one octet of |buffer| starting at index 2
target_buffer.SetToZeros();
expected_write_size = 1;
ASSERT_EQ(expected_write_size, buffer.Copy(&target_buffer, 1, 1));
EXPECT_EQ(buffer[1], target_buffer[0]);
// Zero the buffer and copy its contents for later comparison.
target_buffer.SetToZeros();
auto target_buffer_copy = target_buffer;
// Copy all remaining octets starting just past the end of |buffer|. This
// should copy zero bytes and |target_buffer| should remain unchanged.
ASSERT_EQ(0u, buffer.Copy(&target_buffer, buffer.size()));
EXPECT_TRUE(ContainersEqual(target_buffer_copy, target_buffer));
}
TEST(ByteBufferTest, View) {
auto buffer = common::CreateStaticByteBuffer('T', 'e', 's', 't');
BufferView empty_buffer;
BufferView view = empty_buffer.view();
EXPECT_EQ(0u, view.size());
view = empty_buffer.view(0, 200);
EXPECT_EQ(0u, view.size());
view = buffer.view();
EXPECT_EQ("Test", view.AsString());
view = buffer.view(4);
EXPECT_EQ(0u, view.size());
view = buffer.view(1);
EXPECT_EQ("est", view.AsString());
view = buffer.view(1, 1);
EXPECT_EQ("e", view.AsString());
view = buffer.view(1, 2);
EXPECT_EQ("es", view.AsString());
}
TEST(ByteBufferTest, MutableView) {
auto buffer = common::CreateStaticByteBuffer('T', 'e', 's', 't');
MutableBufferView empty_buffer;
MutableBufferView view;
view = empty_buffer.mutable_view();
EXPECT_EQ(0u, view.size());
view = empty_buffer.mutable_view(0, 200);
EXPECT_EQ(0u, view.size());
view = buffer.mutable_view();
EXPECT_EQ("Test", view.AsString());
view = buffer.mutable_view(4);
EXPECT_EQ(0u, view.size());
view = buffer.mutable_view(1);
EXPECT_EQ("est", view.AsString());
view = buffer.mutable_view(1, 1);
EXPECT_EQ("e", view.AsString());
view = buffer.mutable_view(1, 2);
EXPECT_EQ("es", view.AsString());
// MutableView can modify the underlying buffer.
view[0] = 'E';
EXPECT_EQ("Es", view.AsString());
EXPECT_EQ("TEst", buffer.AsString());
}
TEST(ByteBufferTest, ByteBufferEqualityFail) {
const auto kData0 = common::CreateStaticByteBuffer('T', 'e', 's', 't');
const auto kData1 = common::CreateStaticByteBuffer('F', 'o', 'o');
EXPECT_FALSE(kData0 == kData1);
}
TEST(ByteBufferTest, ByteBufferEqualitySuccess) {
const auto kData0 = common::CreateStaticByteBuffer('T', 'e', 's', 't');
const auto kData1 = common::CreateStaticByteBuffer('T', 'e', 's', 't');
EXPECT_TRUE(kData0 == kData1);
}
TEST(ByteBufferTest, MutableByteBufferWrite) {
const auto kData0 = common::CreateStaticByteBuffer('T', 'e', 's', 't');
const auto kData1 = common::CreateStaticByteBuffer('F', 'o', 'o');
auto buffer =
common::CreateStaticByteBuffer('X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
EXPECT_EQ("XXXXXXXX", buffer.AsString());
buffer.Write(kData0);
EXPECT_EQ("TestXXXX", buffer.AsString());
// Write from raw pointer.
buffer =
common::CreateStaticByteBuffer('X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
buffer.Write(kData0.data(), kData0.size());
EXPECT_EQ("TestXXXX", buffer.AsString());
// Write at offset.
buffer.Write(kData1, 1);
EXPECT_EQ("TFooXXXX", buffer.AsString());
// Write at offset from raw pointer
buffer.Write(kData1.data(), kData1.size(), 3);
EXPECT_EQ("TFoFooXX", buffer.AsString());
// Writing zero bytes should have no effect.
buffer =
common::CreateStaticByteBuffer('X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
buffer.Write(kData1.data(), 0u);
buffer.Write(nullptr, 0u); // Passing nullptr is OK when size is 0
EXPECT_EQ("XXXXXXXX", buffer.AsString());
// Writing zero bytes just past the buffer should be accepted (i.e. no
// assertion) and have no effect.
buffer.Write(kData1.data(), 0u, buffer.size());
EXPECT_EQ("XXXXXXXX", buffer.AsString());
}
TEST(ByteBufferTest, AsString) {
auto buffer = common::CreateStaticByteBuffer('T', 'e', 's', 't');
EXPECT_EQ("Test", buffer.AsString());
}
TEST(ByteBufferTest, Fill) {
StaticByteBuffer<5> buffer;
buffer.Fill('A');
EXPECT_EQ("AAAAA", buffer.AsString());
}
} // namespace
} // namespace common
} // namespace btlib