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

Commit 8f418550 authored by Myles Watson's avatar Myles Watson Committed by Gerrit Code Review
Browse files

Merge changes I40975081,Ia1fe07b4,Ieffc9874

* changes:
  PDL: Add example test packets
  Rust: Add a packet test
  PDL: Add support for test
parents 36b07485 720b5faa
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -548,6 +548,22 @@ rust_library {
    ],
}

rust_test_host {
    name: "libbt_packets_test",
    defaults: ["gd_rust_defaults"],
    srcs: ["rust/packets/lib.rs", ":BluetoothGeneratedPackets_rust"],
    test_suites: ["general-tests"],
    edition: "2018",
    proc_macros: ["libnum_derive"],
    rustlibs: [
        "libbytes",
        "libnum_traits",
        "libthiserror",
        "libbt_hci_custom_types",
        "liblog_rust",
    ],
}

// Generates binary schema data to be bundled and source file generated
genrule {
    name: "BluetoothGeneratedDumpsysBinarySchema_bfbs",
+9 −0
Original line number Diff line number Diff line
@@ -1601,10 +1601,19 @@ packet SetEventMaskComplete : CommandComplete (command_op_code = SET_EVENT_MASK)
packet Reset : Command (op_code = RESET) {
}

test Reset {
  "\x03\x0c\x00",
}

packet ResetComplete : CommandComplete (command_op_code = RESET) {
  status : ErrorCode,
}

test ResetComplete {
  "\x0e\x04\x01\x03\x0c\x00",
  "\x0e\x04\x01\x03\x0c\x01", // unknown command
}

enum FilterType : 8 {
  CLEAR_ALL_FILTERS = 0x00,
  INQUIRY_RESULT = 0x01,
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ string_literal \".*\"
"enum"                  { return(token::ENUM); }
"group"                 { return(token::GROUP); }
"packet"                { return(token::PACKET); }
"test"                  { return(token::TEST); }
"struct"                { return(token::STRUCT); }
"little_endian_packets" {
                          yylval->integer = 1;
+51 −1
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@

  StructDef* struct_definition_value;

  std::set<std::string*>* test_cases_t;
  std::string* test_case_t;

  std::map<std::string, std::variant<int64_t, std::string>>* constraint_list_t;
  std::pair<std::string, std::variant<int64_t, std::string>>* constraint_t;
}
@@ -70,6 +73,7 @@
%token CHECKSUM "checksum"
%token CHECKSUM_START "checksum_start"
%token PADDING "padding"
%token TEST "test"

%type<enum_definition> enum_definition
%type<enumeration_values> enumeration_list
@@ -92,6 +96,10 @@

%type<struct_definition_value> struct_definition;

%type<test_cases_t> test_definition;
%type<test_cases_t> test_case_list;
%type<test_case_t> test_case;

%type<constraint_list_t> constraint_list;
%type<constraint_t> constraint;
%destructor { std::cout << "DESTROYING STRING " << *$$ << "\n"; delete $$; } IDENTIFIER STRING SIZE_MODIFIER
@@ -141,6 +149,10 @@ declaration
    {
      // All actions are handled in custom_field_definition
    }
  | test_definition
    {
      // All actions are handled in test_definition
    }

enum_definition
  : ENUM IDENTIFIER ':' INTEGER '{' enumeration_list ',' '}'
@@ -211,6 +223,44 @@ custom_field_definition
      delete $3;
    }

test_definition
  : TEST IDENTIFIER '{' test_case_list ',' '}'
    {
      auto&& packet_name = *$2;
      DEBUG() << "Test Declared: name=" << *$2 << "\n";
      auto packet = decls->GetPacketDef(packet_name);
      if (packet == nullptr) {
        ERRORLOC(LOC) << "Could not find packet " << packet_name << "\n";
      }

      for (const auto& t : *$4) {
        packet->AddTestCase(*t);
      }
      delete $2;
      delete $4;
    }

test_case_list
  : test_case
    {
      DEBUG() << "Test case with comma\n";
      $$ = new std::set<std::string*>();
      $$->insert($1);
    }
  | test_case_list ',' test_case
    {
      DEBUG() << "Test case with list\n";
      $$ = $1;
      $$->insert($3);
    }

test_case
  : STRING
    {
      DEBUG() << "Test Case: name=" << *$1 << "\n";
      $$ = $1;
    }

struct_definition
  : STRUCT IDENTIFIER '{' field_definition_list '}'
    {
@@ -340,7 +390,7 @@ packet_definition
      auto parent_packet = decls->GetPacketDef(parent_packet_name);
      if (parent_packet == nullptr) {
        ERRORLOC(LOC) << "Could not find packet " << parent_packet_name
                  << " used as parent for " << packet_name;
                  << " used as parent for " << packet_name << "\n";
      }

      auto packet_definition = new PacketDef(std::move(packet_name), std::move(field_definition_list), parent_packet);
+68 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "packet_def.h"

#include <iomanip>
#include <list>
#include <set>

@@ -1217,19 +1218,81 @@ void PacketDef::GenRustBuilderStructImpls(std::ostream& s) const {
  s << "}\n";

  s << "}\n";
  lineage = GetAncestors();
  for (auto it = lineage.begin(); it != lineage.end(); it++) {
    auto def = *it;
    s << "impl Into<" << def->name_ << "Packet> for " << name_ << "Builder {";
    s << " fn into(self) -> " << def->name_ << "Packet { self.build().into() }";
  for (const auto ancestor : GetAncestors()) {
    s << "impl Into<" << ancestor->name_ << "Packet> for " << name_ << "Builder {";
    s << " fn into(self) -> " << ancestor->name_ << "Packet { self.build().into() }";
    s << "}\n";
  }
}

void PacketDef::GenRustBuilderTest(std::ostream& s) const {
  auto lineage = GetAncestors();
  lineage.push_back(this);
  if (!lineage.empty() && !test_cases_.empty()) {
    s << "macro_rules! " << util::CamelCaseToUnderScore(name_) << "_builder_tests { ";
    s << "($($name:ident: $byte_string:expr,)*) => {";
    s << "$(";
    s << "\n#[test]\n";
    s << "pub fn $name() { ";
    s << "let raw_bytes = $byte_string;";
    for (size_t i = 0; i < lineage.size(); i++) {
      s << "/* (" << i << ") */\n";
      if (i == 0) {
        s << "match " << lineage[i]->name_ << "Packet::parse(raw_bytes) {";
        s << "Ok(" << util::CamelCaseToUnderScore(lineage[i]->name_) << "_packet) => {";
        s << "match " << util::CamelCaseToUnderScore(lineage[i]->name_) << "_packet.specialize() {";
      } else if (i != lineage.size() - 1) {
        s << lineage[i - 1]->name_ << "Child::" << lineage[i]->name_ << "(";
        s << util::CamelCaseToUnderScore(lineage[i]->name_) << "_packet) => {";
        s << "match " << util::CamelCaseToUnderScore(lineage[i]->name_) << "_packet.specialize() {";
      } else {
        s << lineage[i - 1]->name_ << "Child::" << lineage[i]->name_ << "(packet) => {";
        s << "let rebuilder = " << lineage[i]->name_ << "Builder {";
        FieldList params = GetParamList().GetFieldsWithoutTypes({
            BodyField::kFieldType,
        });
        for (const auto param : params) {
          s << param->GetName() << " : packet." << util::CamelCaseToUnderScore(param->GetGetterFunctionName()) << "(),";
        }
        s << "};";
        s << "let rebuilder_base : " << lineage[0]->name_ << "Packet = rebuilder.into();";
        s << "let rebuilder_bytes : &[u8] = &rebuilder_base.to_bytes();";
        s << "assert_eq!(rebuilder_bytes, raw_bytes);";
        s << "}";
      }
    }
    for (size_t i = 1; i < lineage.size(); i++) {
      s << "_ => {";
      s << "println!(\"Couldn't parse " << util::CamelCaseToUnderScore(lineage[lineage.size() - i]->name_);
      s << "{:02x?}\", " << util::CamelCaseToUnderScore(lineage[lineage.size() - i - 1]->name_) << "_packet); ";
      s << "}}}";
    }

    s << ",";
    s << "Err(e) => panic!(\"could not parse " << lineage[0]->name_ << ": {:?} {:02x?}\", e, raw_bytes),";
    s << "}";
    s << "}";
    s << ")*";
    s << "}";
    s << "}";

    s << util::CamelCaseToUnderScore(name_) << "_builder_tests! { ";
    int number = 0;
    for (const auto& test_case : test_cases_) {
      s << util::CamelCaseToUnderScore(name_) << "_builder_test_";
      s << std::setfill('0') << std::setw(2) << number++ << ": ";
      s << "b\"" << test_case << "\",";
    }
    s << "}";
    s << "\n";
  }
}

void PacketDef::GenRustDef(std::ostream& s) const {
  GenRustChildEnums(s);
  GenRustStructDeclarations(s);
  GenRustStructImpls(s);
  GenRustAccessStructImpls(s);
  GenRustBuilderStructImpls(s);
  GenRustBuilderTest(s);
}
Loading