--- /dev/null
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include "base_packet_builder.h"
+#include "types/raw_address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Abstract base class that is subclassed to build specifc packets.
+// The template parameter little_endian controls the generation of insert().
+template <bool little_endian>
+class PacketBuilder : public BasePacketBuilder {
+ public:
+ PacketBuilder() = default;
+ virtual ~PacketBuilder() = default;
+
+ // Classes which need fragmentation should define a function like this:
+ // std::forward_list<DerivedBuilder>& Fragment(size_t max_size);
+
+ protected:
+ // Write sizeof(FixedWidthIntegerType) bytes using the iterator
+ template <typename FixedWidthIntegerType>
+ void insert(FixedWidthIntegerType value,
+ std::back_insert_iterator<std::vector<uint8_t>> it) const {
+ static_assert(std::is_integral<FixedWidthIntegerType>::value,
+ "PacketBuilder::insert requires an integral type.");
+ for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+ if (little_endian == true) {
+ *it = static_cast<uint8_t>(value >> (i * 8));
+ } else {
+ *it = static_cast<uint8_t>(
+ value >> ((sizeof(FixedWidthIntegerType) - i - 1) * 8));
+ }
+ it++;
+ }
+ }
+
+ // Write a vector of FixedWidthIntegerType using the iterator
+ template <typename FixedWidthIntegerType>
+ void insert_vector(const std::vector<FixedWidthIntegerType>& vec,
+ std::back_insert_iterator<std::vector<uint8_t>> it) const {
+ static_assert(std::is_integral<FixedWidthIntegerType>::value,
+ "PacketBuilder::insert requires an integral type vector.");
+ for (const auto& element : vec) {
+ insert(element, it);
+ }
+ }
+
+ void insert_address(
+ const RawAddress& addr,
+ std::back_insert_iterator<std::vector<uint8_t>> it) const {
+ for (const auto& element : addr.address) {
+ insert(element, it);
+ }
+ }
+};
+
+} // namespace packets
+} // namespace test_vendor_lib
--- /dev/null
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+ 0x00,
+ 0x01,
+ 0x02,
+};
+
+vector<uint8_t> count_2 = {
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+} // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <bool little_endian>
+class EndianBuilder : public PacketBuilder<little_endian> {
+ public:
+ EndianBuilder(uint8_t byte, uint16_t two_bytes, uint32_t four_bytes,
+ uint64_t eight_bytes)
+ : byte_(byte),
+ two_bytes_(two_bytes),
+ four_bytes_(four_bytes),
+ eight_bytes_(eight_bytes) {}
+ ~EndianBuilder() = default;
+
+ virtual size_t size() const override {
+ return sizeof(signature_) + sizeof(byte_) + sizeof(two_bytes_) +
+ sizeof(four_bytes_) + sizeof(eight_bytes_);
+ }
+
+ virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+ std::unique_ptr<std::vector<uint8_t>> packet =
+ std::make_unique<std::vector<uint8_t>>();
+ packet->reserve(size());
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+ Serialize(it);
+ return packet;
+ }
+
+ virtual void Serialize(
+ std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ PacketBuilder<little_endian>::insert(signature_, it);
+ PacketBuilder<little_endian>::insert(byte_, it);
+ PacketBuilder<little_endian>::insert(two_bytes_, it);
+ PacketBuilder<little_endian>::insert(four_bytes_, it);
+ PacketBuilder<little_endian>::insert(eight_bytes_, it);
+ }
+
+ private:
+ uint32_t signature_{(little_endian ? 0x03020100 : 0x00010203)};
+ uint8_t byte_;
+ uint16_t two_bytes_;
+ uint32_t four_bytes_;
+ uint64_t eight_bytes_;
+};
+
+class PacketBuilderEndianTest : public ::testing::Test {
+ public:
+ PacketBuilderEndianTest() = default;
+ ~PacketBuilderEndianTest() = default;
+};
+
+TEST(PacketBuilderEndianTest, insertTest) {
+ EndianBuilder<true> little(0x04, 0x0605, 0x0a090807, 0x1211100f0e0d0c0b);
+ EndianBuilder<false> big(0x04, 0x0506, 0x0708090a, 0x0b0c0d0e0f101112);
+ ASSERT_EQ(*big.FinalPacket(), *little.FinalPacket());
+}
+
+template <typename T>
+class VectorBuilder : public PacketBuilder<true> {
+ public:
+ VectorBuilder(std::vector<uint64_t> vect) {
+ for (uint64_t element : vect) {
+ vect.push_back(static_cast<T>(element));
+ }
+ }
+ ~VectorBuilder() = default;
+
+ virtual size_t size() const override { return vect_.size() * sizeof(T); }
+
+ virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+ std::unique_ptr<std::vector<uint8_t>> packet =
+ std::make_unique<std::vector<uint8_t>>();
+ packet->reserve(size());
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+ Serialize(it);
+ return packet;
+ }
+
+ virtual void Serialize(
+ std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ PacketBuilder<true>::insert_vector(vect_, it);
+ }
+
+ private:
+ std::vector<T> vect_;
+};
+
+template <typename T>
+class InsertElementsBuilder : public PacketBuilder<true> {
+ public:
+ InsertElementsBuilder(std::vector<uint64_t> vect) {
+ for (uint64_t element : vect) {
+ vect.push_back(static_cast<T>(element));
+ }
+ }
+ virtual ~InsertElementsBuilder() = default;
+
+ virtual size_t size() const override { return vect_.size() * sizeof(T); }
+
+ virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+ std::unique_ptr<std::vector<uint8_t>> packet =
+ std::make_unique<std::vector<uint8_t>>();
+ packet->reserve(size());
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+ Serialize(it);
+ return packet;
+ }
+
+ virtual void Serialize(
+ std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ for (T elem : vect_) {
+ PacketBuilder<true>::insert(elem, it);
+ }
+ }
+
+ private:
+ std::vector<T> vect_;
+};
+
+std::vector<uint64_t> vector_data{
+ 0x7060504030201000, 0x7161514131211101, 0x7262524232221202,
+ 0x7363534333231303, 0x7464544434241404, 0x7565554535251505,
+ 0x7666564636261606, 0x7767574737271707, 0x7868584838281808,
+};
+
+template <typename T>
+class VectorBuilderTest : public ::testing::Test {
+ public:
+ VectorBuilderTest() = default;
+ ~VectorBuilderTest() = default;
+
+ void SetUp() {
+ packet_1_ =
+ std::shared_ptr<VectorBuilder<T>>(new VectorBuilder<T>(vector_data));
+ packet_2_ = std::shared_ptr<InsertElementsBuilder<T>>(
+ new InsertElementsBuilder<T>(vector_data));
+ }
+
+ void TearDown() {
+ packet_1_.reset();
+ packet_2_.reset();
+ }
+
+ std::shared_ptr<VectorBuilder<T>> packet_1_;
+ std::shared_ptr<InsertElementsBuilder<T>> packet_2_;
+};
+
+using VectorBaseTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t,
+ int8_t, int16_t, int32_t, int64_t>;
+TYPED_TEST_CASE(VectorBuilderTest, VectorBaseTypes);
+
+TYPED_TEST(VectorBuilderTest, insertVectorTest) {
+ ASSERT_EQ(*(this->packet_1_->FinalPacket()),
+ *(this->packet_2_->FinalPacket()));
+}
+
+class NestedBuilder : public PacketBuilder<true> {
+ public:
+ ~NestedBuilder() = default;
+
+ virtual size_t size() const override {
+ size_t payload_size = (payload_ ? payload_->size() : 0);
+ return 1 + payload_size;
+ }
+
+ static std::unique_ptr<NestedBuilder> Create(uint8_t level) {
+ return std::unique_ptr<NestedBuilder>(new NestedBuilder(level));
+ }
+
+ static std::unique_ptr<NestedBuilder> CreateNested(
+ std::unique_ptr<BasePacketBuilder> payload, uint8_t level) {
+ return std::unique_ptr<NestedBuilder>(
+ new NestedBuilder(std::move(payload), level));
+ }
+
+ virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+ std::unique_ptr<std::vector<uint8_t>> packet =
+ std::make_unique<std::vector<uint8_t>>();
+ packet->reserve(size());
+ std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+ Serialize(it);
+ return packet;
+ }
+
+ virtual void Serialize(
+ std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+ PacketBuilder<true>::insert(level_, it);
+ if (payload_) {
+ payload_->Serialize(it);
+ }
+ }
+
+ private:
+ std::unique_ptr<BasePacketBuilder> payload_;
+ uint8_t level_;
+
+ NestedBuilder(std::unique_ptr<BasePacketBuilder> inner, uint8_t level)
+ : payload_(std::move(inner)), level_(level) {}
+ NestedBuilder(uint8_t level) : level_(level) {}
+};
+
+class BuilderBuilderTest : public ::testing::Test {};
+
+TEST(BuilderBuilderTest, nestingTest) {
+ std::unique_ptr<BasePacketBuilder> innermost = NestedBuilder::Create(0);
+ std::unique_ptr<BasePacketBuilder> number_1 =
+ NestedBuilder::CreateNested(std::move(innermost), 1);
+ std::unique_ptr<BasePacketBuilder> number_2 =
+ NestedBuilder::CreateNested(std::move(number_1), 2);
+ std::unique_ptr<BasePacketBuilder> number_3 =
+ NestedBuilder::CreateNested(std::move(number_2), 3);
+ std::unique_ptr<BasePacketBuilder> number_4 =
+ NestedBuilder::CreateNested(std::move(number_3), 4);
+ std::unique_ptr<NestedBuilder> number_5 =
+ NestedBuilder::CreateNested(std::move(number_4), 5);
+
+ std::vector<uint8_t> count_down{5, 4, 3, 2, 1, 0};
+ ASSERT_EQ(*number_5->FinalPacket(), count_down);
+}
+} // namespace packets
+} // namespace test_vendor_lib