bool BpfTester::runBpfTesterFromFixtures()

in katran/lib/testing/BpfTester.cpp [140:261]


bool BpfTester::runBpfTesterFromFixtures(
    int progFd,
    std::unordered_map<int, std::string> retvalTranslation,
    std::vector<void*> ctxs_in,
    uint32_t ctx_size) {
  if (ctxs_in.size() != 0) {
    if (ctx_size == 0) {
      LOG(INFO)
          << "size of single ctx value must be non zero if ctxs are specified";
      return false;
    }
    if (ctxs_in.size() != config_.testData.size()) {
      LOG(INFO) << "ctxs and input datasets must have equal number of elements";
      return false;
    }
  }

  uint32_t output_pckt_size{0};
  uint32_t prog_ret_val{0};
  uint64_t pckt_num{1};
  std::string ret_val_str;
  std::string test_result;
  uint64_t packetsRoutedGlobalLruBefore{0};
  uint64_t packetsRoutedGlobalLruAfter{0};
  bool overallSuccess{true};
  for (int i = 0; i < config_.testData.size(); i++) {
    bool iterationSuccess = true;

    if (config_.singleTestRunPacketNumber_ &&
        *config_.singleTestRunPacketNumber_ != (i + 1)) {
      ++pckt_num;
      VLOG(2) << "Skipped test for packet #" << i;
      continue;
    }
    void* ctx_in = ctxs_in.size() != 0 ? ctxs_in[i] : nullptr;
    auto pckt_buf = folly::IOBuf::create(kMaxXdpPcktSize);
    auto input_pckt =
        parser_.getPacketFromBase64(config_.testData[i].inputPacket);
    writePcapOutput(input_pckt->cloneOne());
    if (config_.testData[i].routedThroughGlobalLru) {
      packetsRoutedGlobalLruBefore = getGlobalLruRoutedPackets();
    }
    auto res = adapter_.testXdpProg(
        progFd,
        kTestRepeatCount,
        input_pckt->writableData(),
        input_pckt->length(),
        pckt_buf->writableData(),
        &output_pckt_size,
        &prog_ret_val,
        nullptr, // duration
        ctx_in,
        ctx_size);
    if (res < 0) {
      LOG(INFO) << "failed to run bpf test on pckt #" << pckt_num << " errno "
                << errno << " : " << folly::errnoStr(errno);
      ++pckt_num;
      overallSuccess = false;
      continue;
    }
    if (config_.testData[i].routedThroughGlobalLru) {
      packetsRoutedGlobalLruAfter = getGlobalLruRoutedPackets();
    }
    bool packetRoutedThroughGlobalLru =
        ((packetsRoutedGlobalLruAfter - packetsRoutedGlobalLruBefore) == 1);

    auto ret_val_iter = retvalTranslation.find(prog_ret_val);
    if (ret_val_iter == retvalTranslation.end()) {
      ret_val_str = "UNKNOWN";
    } else {
      ret_val_str = ret_val_iter->second;
    }
    // adjust IOBuf so data data_end will acount for writen data
    pckt_buf->append(output_pckt_size);
    writePcapOutput(pckt_buf->cloneOne());

    if (ret_val_str != config_.testData[i].expectedReturnValue) {
      VLOG(2) << "value from test: " << ret_val_str
              << " expected: " << config_.testData[i].expectedReturnValue;
      test_result = "\033[31mFailed\033[0m";
      iterationSuccess = false;
    }

    if (iterationSuccess && config_.testData[i].routedThroughGlobalLru) {
      if (*config_.testData[i].routedThroughGlobalLru &&
          !packetRoutedThroughGlobalLru) {
        VLOG(2)
            << "packet should have been routed through global lru, but wasn't";
        test_result = "\033[31mFailed\033[0m";
        iterationSuccess = false;
      } else if (
          !*config_.testData[i].routedThroughGlobalLru &&
          packetRoutedThroughGlobalLru) {
        VLOG(2)
            << "packet should not have been routed through global lru, but was";
        test_result = "\033[31mFailed\033[0m";
        iterationSuccess = false;
      }
    }

    if (iterationSuccess) {
      test_result = "\033[32mPassed\033[0m";
      auto output_test_pckt =
          parser_.convertPacketToBase64(std::move(pckt_buf));
      if (output_test_pckt != config_.testData[i].expectedOutputPacket) {
        VLOG(2) << "output packet not equal to expected one; expected pkt="
                << config_.testData[i].expectedOutputPacket
                << ", actual=" << output_test_pckt;
        test_result = "\033[31mFailed\033[0m";
        iterationSuccess = false;
      }
    }

    overallSuccess = overallSuccess && iterationSuccess;

    VLOG(2) << "pckt #" << pckt_num;
    LOG(INFO) << folly::format(
        "Test: {:60} result: {}", config_.testData[i].description, test_result);
    ++pckt_num;
  }
  return overallSuccess;
}