blob: 65d88f23387035e218e44e6289111f2987521525 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/silicon_creator/lib/error.h"
#include <climits>
#include <cstdint>
#include <map>
#include <string>
#include "gtest/gtest.h"
#include "sw/device/lib/base/bitfield.h"
namespace error_unittest {
namespace {
constexpr int kMinimumHammingDistance = 6;
const std::map<std::string, uint32_t> &GetErrorMap() {
#define STRINGIFY(x) #x
#define ERROR_MAP_INIT(name, value) \
{ STRINGIFY(name), value }
static std::map<std::string, uint32_t> errors = {
DEFINE_ERRORS(ERROR_MAP_INIT),
};
return errors;
}
rom_error_t ReturnIfError(rom_error_t value) {
RETURN_IF_ERROR(value);
// Return something other than kErrorOk just in case RETURN_IF_ERROR
// was wrong.
return static_cast<rom_error_t>(0);
}
int HammingDistance(uint32_t a, uint32_t b) {
// The hamming distance is the number of bits different between the two words.
return bitfield_popcount32(a ^ b);
}
// Checks that there are no duplicate values in the error definitions.
TEST(ErrorsTest, NoDuplicateValues) {
const auto &errors = GetErrorMap();
for (auto a = errors.begin(); a != errors.end(); ++a) {
for (auto b = a; b != errors.end(); ++b) {
if (a == b) {
continue;
}
EXPECT_NE(a->second, b->second)
<< "Error codes '" << a->first << "' and '" << b->first
<< "' have the same value.";
}
}
}
// Checks that the RETURN_IF_ERROR macro works as expected.
TEST(ErrorsTest, CheckReturnIfError) {
EXPECT_EQ(kErrorUnknown, ReturnIfError(kErrorUnknown));
rom_error_t ok = ReturnIfError(kErrorOk);
EXPECT_EQ(0, static_cast<int>(ok));
}
TEST(ErrorsTest, CheckHammingDistanceToOk) {
const auto &errors = GetErrorMap();
int max_distance = 0;
int min_distance = INT_MAX;
int distance;
for (const auto &a : errors) {
if (a.second == kErrorOk) {
distance = HammingDistance(a.second, 0);
std::cout << "Hamming distance between '" << a.first
<< "' and zero: " << distance << std::endl;
} else {
distance = HammingDistance(a.second, kErrorOk);
std::cout << "Hamming distance between '" << a.first
<< "' and kErrorOk: " << distance << std::endl;
}
EXPECT_GE(distance, kMinimumHammingDistance);
min_distance = std::min(min_distance, distance);
max_distance = std::max(max_distance, distance);
}
std::cout << "Minimum hamming distance observed: " << min_distance
<< std::endl;
std::cout << "Maximum hamming distance observed: " << max_distance
<< std::endl;
}
} // namespace
} // namespace error_unittest