|  | /* | 
|  | * Copyright 2019 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 "packet/packet_builder.h" | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  | #include <forward_list> | 
|  | #include <memory> | 
|  |  | 
|  | using bluetooth::packet::BasePacketBuilder; | 
|  | using bluetooth::packet::BitInserter; | 
|  | using bluetooth::packet::PacketBuilder; | 
|  | 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 bluetooth { | 
|  | namespace packet { | 
|  |  | 
|  | 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()); | 
|  | BitInserter it(*packet); | 
|  | Serialize(it); | 
|  | return packet; | 
|  | } | 
|  |  | 
|  | virtual void Serialize(BitInserter& 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(const 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()); | 
|  | BitInserter it(*packet); | 
|  | Serialize(it); | 
|  | return packet; | 
|  | } | 
|  |  | 
|  | virtual void Serialize(BitInserter& it) const override { | 
|  | PacketBuilder<true>::insert_vector(vect_, it); | 
|  | } | 
|  |  | 
|  | private: | 
|  | std::vector<T> vect_; | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | class InsertElementsBuilder : public PacketBuilder<true> { | 
|  | public: | 
|  | InsertElementsBuilder(const 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()); | 
|  | BitInserter it(*packet); | 
|  | Serialize(it); | 
|  | return packet; | 
|  | } | 
|  |  | 
|  | virtual void Serialize(BitInserter& 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()); | 
|  | BitInserter it(*packet); | 
|  | Serialize(it); | 
|  | return packet; | 
|  | } | 
|  |  | 
|  | virtual void Serialize(BitInserter& 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 packet | 
|  | }  // namespace bluetooth |