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

Commit dd213a65 authored by Myles Watson's avatar Myles Watson
Browse files

PDL: Add support for test

Bug: 182216573
Test: atest libbt_packets_test
Tag: #gd-refactor
Change-Id: Ieffc9874c0ff17cb2a0acb5e9399b6222f585f7c
parent 46476a51
Loading
Loading
Loading
Loading
+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);
}
+2 −0
Original line number Diff line number Diff line
@@ -79,5 +79,7 @@ class PacketDef : public ParentDef {

  void GenRustBuilderStructImpls(std::ostream& s) const;

  void GenRustBuilderTest(std::ostream& s) const;

  void GenRustDef(std::ostream& s) const;
};
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,10 @@ void ParentDef::AddParentConstraint(std::string field_name, std::variant<int64_t
  parent_constraints_.insert(std::pair(field_name, value));
}

void ParentDef::AddTestCase(std::string packet_bytes) {
  test_cases_.insert(std::move(packet_bytes));
}

// Assign all size fields to their corresponding variable length fields.
// Will crash if
//  - there aren't any fields that don't match up to a field.
Loading