Blame opae-libs/tests/xfpga/test_error_c.cpp

Packit 534379
// Copyright(c) 2018-2020, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
Packit 534379
extern "C" {
Packit 534379
#include "error_int.h"
Packit 534379
#include "token_list_int.h"
Packit 534379
}
Packit 534379
Packit 534379
#include <opae/error.h>
Packit 534379
#include <props.h>
Packit 534379
#include <fstream>
Packit 534379
#include <string>
Packit 534379
#include <cstring>
Packit 534379
#include "gtest/gtest.h"
Packit 534379
#include "mock/test_system.h"
Packit 534379
#include "types_int.h"
Packit 534379
#include "sysfs_int.h"
Packit 534379
#include "xfpga.h"
Packit 534379
Packit 534379
Packit 534379
extern "C" {
Packit 534379
int xfpga_plugin_initialize(void);
Packit 534379
int xfpga_plugin_finalize(void);
Packit 534379
}
Packit 534379
Packit 534379
using namespace opae::testing;
Packit 534379
const std::string sysfs_fme =
Packit 534379
    "/sys/class/fpga/intel-fpga-dev.0/intel-fpga-fme.0";
Packit 534379
const std::string dev_fme = "/dev/intel-fpga-fme.0";
Packit 534379
const std::string sysfs_port =
Packit 534379
    "/sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.0";
Packit 534379
const std::string dev_port = "/dev/intel-fpga-port.0";
Packit 534379
Packit 534379
class error_c_mock_p : public ::testing::TestWithParam<std::string> {
Packit 534379
 public:
Packit 534379
  int delete_errors(std::string, std::string);
Packit 534379
Packit 534379
 protected:
Packit 534379
  error_c_mock_p() : filter_(nullptr) {}
Packit 534379
Packit 534379
  virtual void SetUp() override {
Packit 534379
    ASSERT_TRUE(test_platform::exists(GetParam()));
Packit 534379
    platform_ = test_platform::get(GetParam());
Packit 534379
    system_ = test_system::instance();
Packit 534379
    system_->initialize();
Packit 534379
    system_->prepare_syfs(platform_);
Packit 534379
    tmpsysfs_ = system_->get_root();
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_plugin_initialize());
Packit 534379
    if (sysfs_device_count() > 0) {
Packit 534379
      const sysfs_fpga_device *device = sysfs_get_device(0);
Packit 534379
      ASSERT_NE(device, nullptr);
Packit 534379
      if (device->fme) {
Packit 534379
        sysfs_fme = std::string(device->fme->sysfs_path);
Packit 534379
        dev_fme = std::string("/dev/") + std::string(device->fme->sysfs_name);
Packit 534379
      }
Packit 534379
      if (device->port) {
Packit 534379
        sysfs_port = std::string(device->port->sysfs_path);
Packit 534379
        dev_port = std::string("/dev/") + std::string(device->port->sysfs_name);
Packit 534379
      }
Packit 534379
    }
Packit 534379
    memset(&fake_port_token_, 0, sizeof(fake_port_token_));
Packit 534379
    strncpy(fake_port_token_.sysfspath,
Packit 534379
              sysfs_port.c_str(), sysfs_port.size() + 1);
Packit 534379
    strncpy(fake_port_token_.devpath,
Packit 534379
              dev_port.c_str(), dev_port.size() + 1);
Packit 534379
    fake_port_token_.magic = FPGA_TOKEN_MAGIC;
Packit 534379
    fake_port_token_.device_instance = 0;
Packit 534379
    fake_port_token_.subdev_instance = 0;
Packit 534379
    fake_port_token_.errors = nullptr;
Packit 534379
Packit 534379
    memset(&fake_fme_token_, 0, sizeof(fake_fme_token_));
Packit 534379
    strncpy(fake_fme_token_.sysfspath,
Packit 534379
              sysfs_fme.c_str(), sysfs_fme.size() + 1);
Packit 534379
    strncpy(fake_fme_token_.devpath,
Packit 534379
              dev_fme.c_str(), dev_fme.size() + 1);
Packit 534379
    fake_fme_token_.magic = FPGA_TOKEN_MAGIC;
Packit 534379
    fake_fme_token_.device_instance = 0;
Packit 534379
    fake_fme_token_.subdev_instance = 0;
Packit 534379
    fake_fme_token_.errors = nullptr;
Packit 534379
  }
Packit 534379
Packit 534379
  virtual void TearDown() override {
Packit 534379
    if (fake_fme_token_.errors) {
Packit 534379
      free_error_list(fake_fme_token_.errors);
Packit 534379
    }
Packit 534379
    if (fake_port_token_.errors) {
Packit 534379
      free_error_list(fake_port_token_.errors);
Packit 534379
    }
Packit 534379
    if (filter_) {
Packit 534379
      EXPECT_EQ(fpgaDestroyProperties(&filter_), FPGA_OK);
Packit 534379
      filter_ = nullptr;
Packit 534379
    }
Packit 534379
    token_cleanup();
Packit 534379
    tmpsysfs_ = "";
Packit 534379
	xfpga_plugin_finalize();
Packit 534379
    system_->finalize();
Packit 534379
  }
Packit 534379
Packit 534379
  void free_error_list(struct error_list *p) {
Packit 534379
    while (p) {
Packit 534379
      struct error_list *q = p->next;
Packit 534379
      free(p);
Packit 534379
      p = q;
Packit 534379
    }
Packit 534379
  }
Packit 534379
Packit 534379
  fpga_properties filter_;
Packit 534379
  std::string tmpsysfs_;
Packit 534379
  test_platform platform_;
Packit 534379
  test_system *system_;
Packit 534379
  _fpga_token fake_fme_token_;
Packit 534379
  _fpga_token fake_port_token_;
Packit 534379
  std::string sysfs_fme;
Packit 534379
  std::string dev_fme;
Packit 534379
  std::string sysfs_port;
Packit 534379
  std::string dev_port;
Packit 534379
};
Packit 534379
Packit 534379
int error_c_mock_p::delete_errors(std::string fpga_type, std::string filename) {
Packit 534379
  int result;
Packit 534379
  std::string fme_sysfspath;
Packit 534379
  std::string port_sysfspath;
Packit 534379
  std::string cmd;
Packit 534379
Packit 534379
  if (tmpsysfs_.length() < 2) {
Packit 534379
    fme_sysfspath = tmpsysfs_ + sysfs_fme + "/" + filename;
Packit 534379
    port_sysfspath = tmpsysfs_ + sysfs_port + "/" + filename;
Packit 534379
  } else {
Packit 534379
    fme_sysfspath = tmpsysfs_ + "/" + sysfs_fme + "/" + filename;
Packit 534379
    port_sysfspath = tmpsysfs_ + "/" + sysfs_port + "/" + filename;
Packit 534379
  }
Packit 534379
Packit 534379
  if (fpga_type.compare("fme") == 0) {
Packit 534379
    cmd = "rm -rf " + fme_sysfspath;
Packit 534379
    goto remove;
Packit 534379
  } else if (fpga_type.compare("port") == 0) {
Packit 534379
    cmd = "rm -rf " + port_sysfspath;
Packit 534379
    goto remove;
Packit 534379
  } else {
Packit 534379
    return -1;
Packit 534379
  }
Packit 534379
Packit 534379
remove:
Packit 534379
  result = std::system(cmd.c_str());
Packit 534379
  (void)result;
Packit 534379
  return 1;
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_01
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid AFU token, the combination of
Packit 534379
 * fpgaGetProperties()
Packit 534379
 *             fpgaPropertiesGetNumErrors(), fpgaPropertiesGetErrorInfo() and
Packit 534379
 *             fpgaReadError() is able to print the status of all error
Packit 534379
 * registers.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_01) {
Packit 534379
#ifndef BUILD_ASE
Packit 534379
  fpga_error_info info;
Packit 534379
  unsigned int n = 0;
Packit 534379
  unsigned int i = 0;
Packit 534379
  uint64_t val = 0;
Packit 534379
  fpga_token t = &fake_port_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_port + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_port_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
           info.can_clear ? " (can clear)" : "");
Packit 534379
  }
Packit 534379
Packit 534379
  auto result = delete_errors("port", "errors");
Packit 534379
  (void)result;
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_EXCEPTION, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
           info.can_clear ? " (can clear)" : "");
Packit 534379
  }
Packit 534379
#endif
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_02
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid FME token, the combination of
Packit 534379
 * fpgaGetProperties()
Packit 534379
 *             fpgaPropertiesGetNumErrors(), fpgaPropertiesGetErrorInfo() and
Packit 534379
 *             fpgaReadError() is able to print the status of all error
Packit 534379
 * registers.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_02) {
Packit 534379
#ifndef BUILD_ASE
Packit 534379
  fpga_error_info info;
Packit 534379
  unsigned int n = 0;
Packit 534379
  unsigned int i = 0;
Packit 534379
  uint64_t val = 0;
Packit 534379
  fpga_token t = &fake_fme_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_fme + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_fme_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d FME error registers\n", n);
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
           info.can_clear ? " (can clear)" : "");
Packit 534379
  }
Packit 534379
Packit 534379
  auto result = delete_errors("fme", "errors");
Packit 534379
  (void)result;
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_NE(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
           info.can_clear ? " (can clear)" : "");
Packit 534379
  }
Packit 534379
#endif
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_03
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid AFU token for an AFU with PORT errors,
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearError() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_03) {
Packit 534379
  std::fstream clear_file;
Packit 534379
  std::ofstream error_file;
Packit 534379
  std::string clear_name = tmpsysfs_ + sysfs_port + "/errors/clear";
Packit 534379
  std::string error_name = tmpsysfs_ + sysfs_port + "/errors/errors";
Packit 534379
  uint64_t clear_val;
Packit 534379
Packit 534379
  fpga_error_info info;
Packit 534379
  unsigned int n = 0;
Packit 534379
  unsigned int i = 0;
Packit 534379
  uint64_t val = 0;
Packit 534379
  fpga_token t = &fake_port_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_port + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_port_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    ASSERT_EQ(val, 0);
Packit 534379
  }
Packit 534379
Packit 534379
  // ------------- MAKE SURE CLEAR FILE IS 0 ------------
Packit 534379
  clear_file.open(clear_name);
Packit 534379
  ASSERT_EQ(1, clear_file.is_open());
Packit 534379
  clear_file >> clear_val;
Packit 534379
  clear_file.close();
Packit 534379
  ASSERT_EQ(clear_val, 0);
Packit 534379
Packit 534379
  // ------------- INJECT PORT ERROR --------------------
Packit 534379
  error_file.open(error_name);
Packit 534379
  ASSERT_EQ(1, error_file.is_open());
Packit 534379
  error_file << "0x42" << std::endl;
Packit 534379
  error_file.close();
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    // if error, try to clear it (and check result)
Packit 534379
    if (val != 0) {
Packit 534379
      printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
             info.can_clear ? " (can clear)" : "");
Packit 534379
      EXPECT_EQ(FPGA_OK, xfpga_fpgaClearError(t, i));
Packit 534379
      // check if value was written to clear file
Packit 534379
      clear_file.open(clear_name.c_str());
Packit 534379
      clear_file >> std::hex >> clear_val;
Packit 534379
      clear_file.close();
Packit 534379
      ASSERT_EQ(clear_val, val);
Packit 534379
    }
Packit 534379
  }
Packit 534379
Packit 534379
  // --------------- WRITE 0 TO CLEAR AND ERROR FILES (CLEAN UP) -------------
Packit 534379
  error_file.open(error_name);
Packit 534379
  error_file << "0x0" << std::endl;
Packit 534379
  error_file.close();
Packit 534379
  clear_file.open(clear_name);
Packit 534379
  clear_file << "0x0" << std::endl;
Packit 534379
  clear_file.close();
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_04
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid AFU token for an AFU with PORT errors,
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearAllErrors() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_04) {
Packit 534379
  std::fstream clear_file;
Packit 534379
  std::ofstream error_file;
Packit 534379
  std::string clear_name = tmpsysfs_ + sysfs_port + "/errors/clear";
Packit 534379
  std::string error_name = tmpsysfs_ + sysfs_port + "/errors/errors";
Packit 534379
  uint64_t clear_val;
Packit 534379
Packit 534379
  fpga_error_info info;
Packit 534379
  unsigned int n = 0;
Packit 534379
  unsigned int i = 0;
Packit 534379
  uint64_t val = 0;
Packit 534379
  fpga_token t = &fake_port_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_port + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_port_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    ASSERT_EQ(val, 0);
Packit 534379
  }
Packit 534379
Packit 534379
  // ------------- MAKE SURE CLEAR FILE IS 0 ------------
Packit 534379
  clear_file.open(clear_name);
Packit 534379
  ASSERT_EQ(1, clear_file.is_open());
Packit 534379
  clear_file >> clear_val;
Packit 534379
  clear_file.close();
Packit 534379
  ASSERT_EQ(clear_val, 0);
Packit 534379
Packit 534379
  // ------------- INJECT PORT ERROR --------------------
Packit 534379
  error_file.open(error_name);
Packit 534379
  ASSERT_EQ(1, error_file.is_open());
Packit 534379
  error_file << "0x42" << std::endl;
Packit 534379
  error_file.close();
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(t, i, &val));
Packit 534379
    // if error, try to clear it (and check result)
Packit 534379
    if (val != 0) {
Packit 534379
      printf("[%u] %s: 0x%016lX%s\n", i, info.name, val,
Packit 534379
             info.can_clear ? " (can clear)" : "");
Packit 534379
      EXPECT_EQ(FPGA_OK, xfpga_fpgaClearAllErrors(t));
Packit 534379
      // check if value was written to clear file
Packit 534379
      clear_file.open(clear_name);
Packit 534379
      clear_file >> std::hex >> clear_val;
Packit 534379
      clear_file.close();
Packit 534379
      EXPECT_EQ(clear_val, val);
Packit 534379
    }
Packit 534379
  }
Packit 534379
Packit 534379
  // --------------- WRITE 0 TO CLEAR AND ERROR FILES (CLEAN UP) -------------
Packit 534379
  error_file.open(error_name);
Packit 534379
  error_file << "0x0" << std::endl;
Packit 534379
  error_file.close();
Packit 534379
  clear_file.open(clear_name);
Packit 534379
  clear_file << "0x0" << std::endl;
Packit 534379
  clear_file.close();
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_05
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid AFU token for an AFU with PORT errors,
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearError() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_05) {
Packit 534379
  unsigned int n = 0;
Packit 534379
  fpga_token t = &fake_port_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_port + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_port_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  struct error_list *p = fake_port_token_.errors;
Packit 534379
  p->info.can_clear = false;
Packit 534379
  EXPECT_EQ(FPGA_NOT_SUPPORTED, xfpga_fpgaClearError(t, 0));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_06
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid FME token,
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearError() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_06) {
Packit 534379
  fpga_error_info info;
Packit 534379
  unsigned int n = 0;
Packit 534379
  unsigned int i = 0;
Packit 534379
  fpga_token t = &fake_fme_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_fme + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_fme_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  // ASSERT_EQ(FPGA_OK, xfpga_fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d FME error registers\n", n);
Packit 534379
Packit 534379
  // for each error register, get info and read the current value
Packit 534379
  for (i = 0; i < n; i++) {
Packit 534379
    // get info struct for error register
Packit 534379
    ASSERT_EQ(FPGA_OK, xfpga_fpgaGetErrorInfo(t, i, &info));
Packit 534379
    // if error, try to clear it (and check result)
Packit 534379
    if (info.can_clear) {
Packit 534379
      EXPECT_EQ(FPGA_OK, xfpga_fpgaClearError(t, i));
Packit 534379
    }
Packit 534379
  }
Packit 534379
Packit 534379
  free_error_list(fake_fme_token_.errors);
Packit 534379
Packit 534379
  // set error list to null
Packit 534379
  fake_fme_token_.errors = nullptr;
Packit 534379
  EXPECT_EQ(FPGA_NOT_FOUND, xfpga_fpgaClearError(t, 0));
Packit 534379
}
Packit 534379
/**
Packit 534379
 * @test       error_07
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid FME token,
Packit 534379
 *             and delete error removes errors dir
Packit 534379
 *             fpgaReadError() and fpgaClearError will
Packit 534379
 *             returns FPGA_EXCEPTION
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_07) {
Packit 534379
  fpga_error_info info;
Packit 534379
  fpga_token t = &fake_fme_token_;
Packit 534379
  uint32_t num_errors = 0, i = 0;
Packit 534379
Packit 534379
  std::string errpath = sysfs_fme + "/errors";
Packit 534379
  // build errors and immediately remove errors dir
Packit 534379
  build_error_list(errpath.c_str(), &fake_fme_token_.errors);
Packit 534379
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  ASSERT_EQ(fpgaPropertiesGetNumErrors(filter_, &num_errors), FPGA_OK);
Packit 534379
  ASSERT_NE(num_errors, 0) << "No errors to clear";
Packit 534379
  for (i = 0; i < num_errors; i++) {
Packit 534379
    ASSERT_EQ(xfpga_fpgaGetErrorInfo(t, i, &info), FPGA_OK);
Packit 534379
    if (info.can_clear) {
Packit 534379
      auto ret = delete_errors("fme", "errors");
Packit 534379
      // get the clearable error
Packit 534379
      if (ret) {
Packit 534379
        EXPECT_EQ(FPGA_EXCEPTION, xfpga_fpgaClearError(t, i));
Packit 534379
      }
Packit 534379
      break;
Packit 534379
    }
Packit 534379
  }
Packit 534379
  EXPECT_NE(i, num_errors) << "Did not attempt to clear errors";
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_08
Packit 534379
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearError() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_08) {
Packit 534379
  unsigned int n = 0;
Packit 534379
  fpga_token t = &fake_port_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_port + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_port_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  EXPECT_EQ(FPGA_OK, xfpga_fpgaClearAllErrors(t));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_09
Packit 534379
 *
Packit 534379
 * @brief      When passed a valid FME token,
Packit 534379
 *             fpgaReadError() will report the correct error, and
Packit 534379
 *             fpgaClearError() will clear it.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_09) {
Packit 534379
  unsigned int n = 0;
Packit 534379
  fpga_token t = &fake_fme_token_;
Packit 534379
Packit 534379
  std::string errpath = sysfs_fme + "/errors";
Packit 534379
  build_error_list(errpath.c_str(), &fake_fme_token_.errors);
Packit 534379
Packit 534379
  // get number of error registers
Packit 534379
  ASSERT_EQ(FPGA_OK, xfpga_fpgaGetProperties(t, &filter_));
Packit 534379
  auto _prop = (_fpga_properties *)filter_;
Packit 534379
  SET_FIELD_VALID(_prop, FPGA_PROPERTY_NUM_ERRORS);
Packit 534379
  ASSERT_EQ(FPGA_OK, fpgaPropertiesGetNumErrors(filter_, &n);;
Packit 534379
  printf("Found %d PORT error registers\n", n);
Packit 534379
Packit 534379
  EXPECT_EQ(FPGA_OK, xfpga_fpgaClearAllErrors(t));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_12
Packit 534379
 * @brief      When passed an invalid token magic,
Packit 534379
 *             xfpga_fpgaClearAllErrors() should return FPGA_INVALID_PARAM.
Packit 534379
 */
Packit 534379
TEST_P(error_c_mock_p, error_12) {
Packit 534379
  auto fme = token_add(sysfs_fme.c_str(), dev_fme.c_str());
Packit 534379
  ASSERT_NE(fme, nullptr);
Packit 534379
  auto port = token_add(sysfs_port.c_str(), dev_port.c_str());
Packit 534379
  ASSERT_NE(port, nullptr);
Packit 534379
  auto parent = token_get_parent(port);
Packit 534379
  EXPECT_EQ(parent, fme);
Packit 534379
  auto tok = (struct _fpga_token *)parent;
Packit 534379
Packit 534379
  tok->magic = FPGA_TOKEN_MAGIC;
Packit 534379
  EXPECT_EQ(FPGA_OK, xfpga_fpgaClearAllErrors(parent));
Packit 534379
  tok->magic = 0x123;
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaClearAllErrors(parent));
Packit 534379
}
Packit 534379
Packit 534379
INSTANTIATE_TEST_CASE_P(error_c, error_c_mock_p,
Packit 534379
                        ::testing::ValuesIn(test_platform::mock_platforms({ "skx-p","dcp-rc","dcp-vc" })));
Packit 534379
Packit 534379
class error_c_p : public error_c_mock_p {};
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_10
Packit 534379
 *
Packit 534379
 * @brief      When passed an invalid token magic,
Packit 534379
 *             xfpga_fpgaReadError() should return FPGA_INVALID_PARAM.
Packit 534379
 *             when token doesn't have errpath
Packit 534379
 *             xfpga_fpgaReadError() should return FPGA_NOT_FOUND.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_p, error_10) {
Packit 534379
  auto fme = token_add(sysfs_fme.c_str(), dev_fme.c_str());
Packit 534379
  ASSERT_NE(fme, nullptr);
Packit 534379
  auto port = token_add(sysfs_port.c_str(), dev_port.c_str());
Packit 534379
  ASSERT_NE(port, nullptr);
Packit 534379
  auto parent = token_get_parent(port);
Packit 534379
  EXPECT_EQ(parent, fme);
Packit 534379
  auto tok = (struct _fpga_token *)parent;
Packit 534379
Packit 534379
  uint64_t val = 0;
Packit 534379
  tok->magic = 0x123;
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaReadError(parent, 0, &val));
Packit 534379
Packit 534379
  tok->magic = FPGA_TOKEN_MAGIC;
Packit 534379
  EXPECT_EQ(FPGA_OK, xfpga_fpgaReadError(parent, 0, &val));
Packit 534379
  EXPECT_EQ(FPGA_NOT_FOUND, xfpga_fpgaReadError(parent, 1000, &val));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_11
Packit 534379
 *
Packit 534379
 * @brief      When passed an invalid token magic,
Packit 534379
 *             xfpga_fpgaClearError() should return FPGA_INVALID_PARAM.
Packit 534379
 *             when token doesn't have errpath
Packit 534379
 *             xfpga_fpgaClearError() should return FPGA_NOT_FOUND.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST_P(error_c_p, error_11) {
Packit 534379
  auto fme = token_add(sysfs_fme.c_str(), dev_fme.c_str());
Packit 534379
  ASSERT_NE(fme, nullptr);
Packit 534379
  auto port = token_add(sysfs_port.c_str(), dev_port.c_str());
Packit 534379
  ASSERT_NE(port, nullptr);
Packit 534379
  auto parent = token_get_parent(port);
Packit 534379
  EXPECT_EQ(parent, fme);
Packit 534379
  auto tok = (struct _fpga_token *)parent;
Packit 534379
Packit 534379
  EXPECT_EQ(FPGA_NOT_FOUND, xfpga_fpgaClearError(parent, 1000));
Packit 534379
  tok->magic = 0x123;
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaClearError(parent, 0));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_13
Packit 534379
 * @brief      When passed an invalid token magic,
Packit 534379
 *             xfpga_fpgaClearAllErrors() should return FPGA_INVALID_PARAM.
Packit 534379
 *             when token doesn't have errpath
Packit 534379
 *             xfpga_fpgaClearAllErrors() should return FPGA_NOT_FOUND.
Packit 534379
 */
Packit 534379
TEST_P(error_c_p, error_13) {
Packit 534379
  auto fme = token_add(sysfs_fme.c_str(), dev_fme.c_str());
Packit 534379
  ASSERT_NE(fme, nullptr);
Packit 534379
  auto port = token_add(sysfs_port.c_str(), dev_port.c_str());
Packit 534379
  ASSERT_NE(port, nullptr);
Packit 534379
  auto parent = token_get_parent(port);
Packit 534379
  EXPECT_EQ(parent, fme);
Packit 534379
  auto tok = (struct _fpga_token *)parent;
Packit 534379
Packit 534379
  struct fpga_error_info info;
Packit 534379
  tok->magic = FPGA_TOKEN_MAGIC;
Packit 534379
  EXPECT_EQ(FPGA_NOT_FOUND, xfpga_fpgaGetErrorInfo(parent, 1000, &info));
Packit 534379
  tok->magic = 0x123;
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaGetErrorInfo(parent, 0, &info));
Packit 534379
}
Packit 534379
Packit 534379
INSTANTIATE_TEST_CASE_P(error_c, error_c_p,
Packit 534379
                        ::testing::ValuesIn(test_platform::platforms({ "skx-p","dcp-rc","dcp-vc"  })));
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_01
Packit 534379
 *
Packit 534379
 * @brief      When passed an NULL token
Packit 534379
 *             xfpga_fpgaReadError() should return FPGA_INVALID_PARAM.
Packit 534379
 *             xfpga_fpgaClearError() should return FPGA_INVALID_PARAM.
Packit 534379
 *             xfpga_fpgaClearAllErrors() should return FPGA_INVALID_PARAM.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST(error_c, error_01) {
Packit 534379
  fpga_token tok = NULL;
Packit 534379
  uint64_t val = 0;
Packit 534379
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaReadError(tok, 0, &val));
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaClearError(tok, 0));
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaClearAllErrors(tok));
Packit 534379
  EXPECT_EQ(FPGA_INVALID_PARAM, xfpga_fpgaGetErrorInfo(tok, 0, NULL));
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_06
Packit 534379
 *
Packit 534379
 * @brief      When passed in invalid errors path to build_error_list,
Packit 534379
 *             the function returns 0 for file doesn't exist.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST(error_c, error_06) {
Packit 534379
  struct _fpga_token _t;
Packit 534379
  strncpy(_t.sysfspath, sysfs_port.c_str(), sysfs_port.size() + 1);
Packit 534379
  strncpy(_t.devpath, dev_port.c_str(), dev_port.size() + 1);
Packit 534379
  _t.magic = FPGA_TOKEN_MAGIC;
Packit 534379
  _t.errors = nullptr;
Packit 534379
Packit 534379
  std::string invalid_errpath = sysfs_port + "/errorss";
Packit 534379
  auto result = build_error_list(invalid_errpath.c_str(), &_t.errors);
Packit 534379
  EXPECT_EQ(result, 0);
Packit 534379
}
Packit 534379
Packit 534379
/**
Packit 534379
 * @test       error_07
Packit 534379
 *
Packit 534379
 * @brief      When passed pathname longer than FILENAME_MAX
Packit 534379
 *             build_error_list() should return and not build anything
Packit 534379
 *
Packit 534379
 *@note        Must set env-variable LIBOPAE_LOG=1 to run this test.
Packit 534379
 *
Packit 534379
 */
Packit 534379
TEST(error_c, error_07) {
Packit 534379
  struct error_list *el = NULL;
Packit 534379
  std::string lpn(FILENAME_MAX + 1, 'a');
Packit 534379
  std::string exptout("path too long");
Packit 534379
Packit 534379
  char *loglv = secure_getenv("LIBOPAE_LOG");
Packit 534379
  if (loglv && atoi(loglv) > 0) {
Packit 534379
    testing::internal::CaptureStdout();
Packit 534379
Packit 534379
    build_error_list(lpn.c_str(), &el);
Packit 534379
Packit 534379
    std::string actout = testing::internal::GetCapturedStdout();
Packit 534379
    EXPECT_NE(std::string::npos, actout.find(exptout));
Packit 534379
  }
Packit 534379
Packit 534379
  EXPECT_EQ(NULL, el);
Packit 534379
}