| /* |
| * 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 |