Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f70a5e1 authored by Myles Watson's avatar Myles Watson
Browse files

test_vendor: Add PacketView for copyless parsing

A View is holds bounds and a shared pointer.
A PacketView is a forward list of View, templated for endianness.
A BaseIterator iterates over PacketViews.
An Iterator is a BaseIterator with extract, which is templated for endianness.

Test: rootcanal-packets_test_host
Change-Id: I68d6502861be61f411c0f5f2da33ead3d2392694
parent fd1aeefb
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -68,6 +68,17 @@ COVERAGE_TESTS = [
        "covered_files": [
            "packages/modules/Bluetooth/system/profile/sdp",
        ],
    }, {
        "test_name": "test-vendor_test_host",
        "covered_files": [
            "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/include",
            "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/src",
        ],
    }, {
        "test_name": "rootcanal-packets_test_host",
        "covered_files": [
            "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/packets",
        ],
    },
]

+12 −3
Original line number Diff line number Diff line
@@ -35,7 +35,10 @@ cc_library_static {
    local_include_dirs: [
        "include",
    ],
    export_include_dirs: ["include"],
    export_include_dirs: [
        "include",
        ".",
    ],
    header_libs: [
        "libbluetooth_headers",
    ],
@@ -52,14 +55,19 @@ cc_library_static {
    ],
    static_libs: [
        "libbluetooth-types",
    ]
        "libbt-rootcanal-packets",
    ],
}

// test-vendor unit tests for host
// ========================================================
cc_test_host {
    name: "test-vendor_test_host",
    defaults: ["libchrome_support_defaults"],
    defaults: [
        "libchrome_support_defaults",
        "clang_file_coverage",
        "clang_coverage_bin",
    ],
    srcs: [
        "src/async_manager.cc",
        "src/bt_address.cc",
@@ -94,6 +102,7 @@ cc_test_host {
    ],
    static_libs: [
        "libbluetooth-types",
        "libbt-rootcanal-packets",
    ],
    cflags: [
        "-fvisibility=hidden",
+65 −0
Original line number Diff line number Diff line
// packet library for libbt-rootcanal
// ========================================================
cc_library_static {
    name: "libbt-rootcanal-packets",
    defaults: [
        "libchrome_support_defaults",
        "clang_file_coverage",
    ],
    host_supported: true,
    proprietary: true,
    srcs: [
        "iterator.cc",
        "packet_view.cc",
        "view.cc",
    ],
    cflags: [
        "-fvisibility=hidden",
    ],
    local_include_dirs: [
        ".",
    ],
    export_include_dirs: ["."],
    include_dirs: [
        "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/include",
        "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/",
        "packages/modules/Bluetooth/system/",
    ],
    shared_libs: [
        "libbase",
        "liblog",
    ],
}

// Unit tests for the host
// ========================================================
cc_test_host {
    name: "rootcanal-packets_test_host",
    defaults: [
        "libchrome_support_defaults",
        "clang_file_coverage",
        "clang_coverage_bin",
    ],
    srcs: [
        "test/packet_view_test.cc",
    ],
    header_libs: [
        "libbluetooth_headers",
    ],
    local_include_dirs: [
        ".",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/hci/include",
        "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib",
        "packages/modules/Bluetooth/system/vendor_libs/test_vendor_lib/include",
    ],
    shared_libs: [
        "liblog",
    ],
    static_libs: [
        "libbluetooth-types",
        "libbt-rootcanal-packets",
    ],
}
+168 −0
Original line number Diff line number Diff line
/*
 * 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 "iterator.h"

#include <base/logging.h>

namespace test_vendor_lib {
namespace packets {

template <bool little_endian>
Iterator<little_endian>::Iterator(std::forward_list<View> data, size_t offset) {
  data_ = data;
  index_ = offset;
  length_ = 0;
  for (auto& view : data) {
    length_ += view.size();
  }
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator+(int offset) {
  auto itr(*this);

  return itr += offset;
}

template <bool little_endian>
Iterator<little_endian>& Iterator<little_endian>::operator+=(int offset) {
  index_ += offset;
  return *this;
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator++(int) {
  auto itr(*this);
  index_++;
  return itr;
}

template <bool little_endian>
Iterator<little_endian>& Iterator<little_endian>::operator++() {
  index_++;
  return *this;
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator-(int offset) {
  auto itr(*this);

  return itr -= offset;
}

template <bool little_endian>
int Iterator<little_endian>::operator-(Iterator<little_endian>& itr) {
  return index_ - itr.index_;
}

template <bool little_endian>
Iterator<little_endian>& Iterator<little_endian>::operator-=(int offset) {
  index_ -= offset;

  return *this;
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator--(int) {
  auto itr(*this);
  if (index_ != 0) index_--;

  return itr;
}

template <bool little_endian>
Iterator<little_endian>& Iterator<little_endian>::operator--() {
  if (index_ != 0) index_--;

  return *this;
}

template <bool little_endian>
Iterator<little_endian>& Iterator<little_endian>::operator=(
    const Iterator<little_endian>& itr) {
  data_ = itr.data_;
  index_ = itr.index_;

  return *this;
}

template <bool little_endian>
bool Iterator<little_endian>::operator==(
    const Iterator<little_endian>& itr) const {
  return index_ == itr.index_;
}

template <bool little_endian>
bool Iterator<little_endian>::operator!=(
    const Iterator<little_endian>& itr) const {
  return !(*this == itr);
}

template <bool little_endian>
bool Iterator<little_endian>::operator<(
    const Iterator<little_endian>& itr) const {
  return index_ < itr.index_;
}

template <bool little_endian>
bool Iterator<little_endian>::operator>(
    const Iterator<little_endian>& itr) const {
  return index_ > itr.index_;
}

template <bool little_endian>
bool Iterator<little_endian>::operator<=(
    const Iterator<little_endian>& itr) const {
  return index_ <= itr.index_;
}

template <bool little_endian>
bool Iterator<little_endian>::operator>=(
    const Iterator<little_endian>& itr) const {
  return index_ >= itr.index_;
}

template <bool little_endian>
uint8_t Iterator<little_endian>::operator*() const {
  CHECK(index_ < length_) << "Index " << index_
                          << " out of bounds: " << length_;
  size_t index = index_;

  for (auto view : data_) {
    if (index < view.size()) {
      return view[index];
    }
    index -= view.size();
  }
  CHECK(false) << "Out of fragments searching for Index " << index_;
  return 0;
}

template <bool little_endian>
size_t Iterator<little_endian>::NumBytesRemaining() const {
  if (length_ > index_) {
    return length_ - index_;
  } else {
    return 0;
  }
}

// Explicit instantiations for both types of Iterators.
template class Iterator<true>;
template class Iterator<false>;
}  // namespace packets
}  // namespace test_vendor_lib
+87 −0
Original line number Diff line number Diff line
/*
 * 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 "types/raw_address.h"
#include "view.h"

namespace test_vendor_lib {
namespace packets {

// Templated Iterator for endianness
template <bool little_endian>
class Iterator
    : public std::iterator<std::random_access_iterator_tag, uint8_t> {
 public:
  Iterator(std::forward_list<View> data, size_t offset);
  Iterator(const Iterator& itr) = default;
  virtual ~Iterator() = default;

  // All addition and subtraction operators are unbounded.
  Iterator operator+(int offset);
  Iterator& operator+=(int offset);
  Iterator operator++(int);
  Iterator& operator++();

  Iterator operator-(int offset);
  int operator-(Iterator& itr);
  Iterator& operator-=(int offset);
  Iterator operator--(int);
  Iterator& operator--();

  Iterator& operator=(const Iterator& itr);

  bool operator!=(const Iterator& itr) const;
  bool operator==(const Iterator& itr) const;

  bool operator<(const Iterator& itr) const;
  bool operator>(const Iterator& itr) const;

  bool operator<=(const Iterator& itr) const;
  bool operator>=(const Iterator& itr) const;

  uint8_t operator*() const;
  uint8_t operator->() const;

  size_t NumBytesRemaining() const;

  // Get the next sizeof(FixedWidthPODType) bytes and return the filled type
  template <typename FixedWidthPODType>
  FixedWidthPODType extract() {
    static_assert(std::is_pod<FixedWidthPODType>::value,
                  "Iterator::extract requires an fixed type.");
    FixedWidthPODType extracted_value;
    uint8_t* value_ptr = (uint8_t*)&extracted_value;

    for (size_t i = 0; i < sizeof(FixedWidthPODType); i++) {
      size_t index = (little_endian ? i : sizeof(FixedWidthPODType) - i - 1);
      value_ptr[index] = *((*this)++);
    }
    return extracted_value;
  }

 private:
  std::forward_list<View> data_;
  size_t index_;
  size_t length_;
};

}  // namespace packets
}  // namespace test_vendor_lib
Loading