blob: d742da026453526c6e5de09d618500eba52fd05e [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/lib/dif/dif_alert_handler.h"
#include <cstring>
#include <limits>
#include <ostream>
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/testing/mock_mmio.h"
#include "alert_handler_regs.h" // Generated.
namespace dif_alert_handler_unittest {
namespace {
using ::mock_mmio::LeInt;
using ::mock_mmio::MmioTest;
using ::mock_mmio::MockDevice;
using ::testing::_;
using ::testing::Return;
constexpr uint32_t kAlerts = 12;
constexpr uint32_t kAllOnes = std::numeric_limits<uint32_t>::max();
class AlertTest : public testing::Test, public MmioTest {
protected:
dif_alert_handler_t handler_ = {.params = {
.base_addr = dev().region(),
.alert_count = kAlerts,
.escalation_signal_count = 4,
}};
};
class InitTest : public AlertTest,
public testing::WithParamInterface<uint32_t> {};
TEST_P(InitTest, Success) {
dif_alert_handler_params_t params = {
.base_addr = dev().region(),
.alert_count = GetParam(),
.escalation_signal_count = 4,
};
dif_alert_handler_t handler;
EXPECT_EQ(dif_alert_handler_init(params, &handler), kDifAlertHandlerOk);
}
TEST_P(InitTest, NullArgs) {
dif_alert_handler_params_t params = {
.base_addr = dev().region(),
.alert_count = GetParam(),
.escalation_signal_count = 4,
};
EXPECT_EQ(dif_alert_handler_init(params, nullptr), kDifAlertHandlerBadArg);
}
INSTANTIATE_TEST_SUITE_P(InitTestSignalCounts, InitTest,
testing::Values(1, 2, 12, 16, 24, 32, 64,
ALERT_HANDLER_PARAM_N_ALERTS));
class ConfigTest : public AlertTest {
// We provide our own dev_ member variable in this fixture, in order to
// support IgnoreMmioCalls().
//
// NOTE: This must come before handler_!
private:
std::unique_ptr<MockDevice> dev_ =
std::make_unique<testing::StrictMock<MockDevice>>();
protected:
ConfigTest() { handler_.params.base_addr = dev().region(); }
// Non-virtual-override dev(), so that EXPECT_*() functions look this one
// up instead of AlertTest::dev().
MockDevice &dev() { return *dev_; }
// Disables expectations on MMIO operations. This is useful for configuration
// tests that partially configure the device but fail due to a configuration
// error, returning kError.
void IgnoreMmioCalls() {
dev_ = std::make_unique<testing::NiceMock<MockDevice>>();
handler_.params.base_addr = dev().region();
// Make sure that the peripheral looks unlocked.
ON_CALL(*dev_, Read32(_)).WillByDefault(Return(kAllOnes));
}
};
TEST_F(ConfigTest, Locked) {
dif_alert_handler_config_t config = {
.ping_timeout = 0,
};
EXPECT_READ32(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
true}});
EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
kDifAlertHandlerConfigLocked);
}
TEST_F(ConfigTest, NoClassInit) {
dif_alert_handler_config_t config = {
.ping_timeout = 50,
};
EXPECT_READ32(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
false}});
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_PING_TIMEOUT_CYC_SHADOWED_OFFSET,
50}});
EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
kDifAlertHandlerConfigOk);
}
TEST_F(ConfigTest, TimeoutTooBig) {
dif_alert_handler_config_t config = {
.ping_timeout =
ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_PING_TIMEOUT_CYC_SHADOWED_MASK +
1,
};
EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
kDifAlertHandlerConfigBadArg);
}
TEST_F(ConfigTest, BadClassPtr) {
dif_alert_handler_config_t config = {
.ping_timeout = 50,
.classes = nullptr,
.classes_len = 2,
};
EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
kDifAlertHandlerConfigBadArg);
}
TEST_F(ConfigTest, ClassInit) {
std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, 5};
std::vector<dif_alert_handler_local_alert_t> locals_a = {
kDifAlertHandlerLocalAlertEscalationPingFail,
};
std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
{.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
{.phase = kDifAlertHandlerClassStatePhase2, .signal = 1},
};
std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
{.phase = kDifAlertHandlerClassStatePhase1, .cycles = 20000},
{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
};
std::vector<dif_alert_handler_alert_t> alerts_b = {9, 6, 11};
std::vector<dif_alert_handler_local_alert_t> locals_b = {
kDifAlertHandlerLocalAlertAlertPingFail,
kDifAlertHandlerLocalAlertAlertIntegrityFail,
};
std::vector<dif_alert_handler_class_phase_signal_t> signals_b = {
{.phase = kDifAlertHandlerClassStatePhase1, .signal = 0},
};
std::vector<dif_alert_handler_class_phase_duration_t> durations_b = {
{.phase = kDifAlertHandlerClassStatePhase1, .cycles = 20000},
{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
{.phase = kDifAlertHandlerClassStatePhase3, .cycles = 150000},
};
std::vector<dif_alert_handler_class_config_t> classes = {
{
.alert_class = kDifAlertHandlerClassA,
.alerts = alerts_a.data(),
.alerts_len = alerts_a.size(),
.local_alerts = locals_a.data(),
.local_alerts_len = locals_a.size(),
.use_escalation_protocol = kDifAlertHandlerToggleDisabled,
.automatic_locking = kDifAlertHandlerToggleEnabled,
.accumulator_threshold = 12,
.irq_deadline_cycles = 30000,
.phase_signals = signals_a.data(),
.phase_signals_len = signals_a.size(),
.phase_durations = durations_a.data(),
.phase_durations_len = durations_a.size(),
},
{
.alert_class = kDifAlertHandlerClassB,
.alerts = alerts_b.data(),
.alerts_len = alerts_b.size(),
.local_alerts = locals_b.data(),
.local_alerts_len = locals_b.size(),
.use_escalation_protocol = kDifAlertHandlerToggleEnabled,
.automatic_locking = kDifAlertHandlerToggleDisabled,
.accumulator_threshold = 8,
.irq_deadline_cycles = 2000,
.phase_signals = signals_b.data(),
.phase_signals_len = signals_b.size(),
.phase_durations = durations_b.data(),
.phase_durations_len = durations_b.size(),
},
};
dif_alert_handler_config_t config = {
.ping_timeout = 50,
.classes = classes.data(),
.classes_len = classes.size(),
};
// The alert handler needs to be unlocked for it to be configured.
EXPECT_READ32(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
false}});
// Configure class A alerts.
// Unfortunately, we can't use EXPECT_MASK for these reads/writes, since the
// target registers are shadowed.
for (auto alert : alerts_a) {
// The various alerts should be enabled.
ptrdiff_t alert_enable_reg_offset =
ALERT_HANDLER_ALERT_EN_SHADOWED_0_REG_OFFSET + alert * sizeof(uint32_t);
EXPECT_READ32(alert_enable_reg_offset, 0);
EXPECT_WRITE32_SHADOWED(
alert_enable_reg_offset,
{{ALERT_HANDLER_ALERT_EN_SHADOWED_0_EN_A_0_BIT, true}});
// The various alerts should be classified.
ptrdiff_t alert_class_reg_offset =
ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_REG_OFFSET +
alert * sizeof(uint32_t);
EXPECT_READ32(alert_class_reg_offset, 0);
EXPECT_WRITE32_SHADOWED(
alert_class_reg_offset,
ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_CLASS_A_0_VALUE_CLASSA);
}
// Configure class A local alerts.
// Unfortunately, we can't use EXPECT_MASK for these reads/writes, since the
// target registers are shadowed.
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_REG_RESVAL);
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1_REG_RESVAL);
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_REG_OFFSET,
{{ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_1_EN_LA_1_BIT, true}});
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_1_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_CLASS_LA_0_VALUE_CLASSA);
// Configure class A control register.
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_CLASSA_CTRL_SHADOWED_REG_OFFSET,
{
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_EN_BIT, false},
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_LOCK_BIT, true},
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_EN_E0_BIT, true},
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_MAP_E0_OFFSET, 3},
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_EN_E2_BIT, true},
{ALERT_HANDLER_CLASSA_CTRL_SHADOWED_MAP_E2_OFFSET, 1},
});
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSA_ACCUM_THRESH_SHADOWED_REG_OFFSET,
12);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSA_TIMEOUT_CYC_SHADOWED_REG_OFFSET,
30000);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSA_PHASE1_CYC_SHADOWED_REG_OFFSET,
20000);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSA_PHASE2_CYC_SHADOWED_REG_OFFSET,
15000);
// Configure class B alerts.
// Unfortunately, we can't use EXPECT_MASK for these reads/writes, since the
// target registers are shadowed.
for (auto alert : alerts_b) {
// The various alerts should be enabled.
ptrdiff_t alert_enable_reg_offset =
ALERT_HANDLER_ALERT_EN_SHADOWED_0_REG_OFFSET + alert * sizeof(uint32_t);
EXPECT_READ32(alert_enable_reg_offset, 0);
EXPECT_WRITE32_SHADOWED(
alert_enable_reg_offset,
{{ALERT_HANDLER_ALERT_EN_SHADOWED_0_EN_A_0_BIT, true}});
// The various alerts should be classified.
ptrdiff_t alert_class_reg_offset =
ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_REG_OFFSET +
alert * sizeof(uint32_t);
EXPECT_READ32(alert_class_reg_offset, 0);
EXPECT_WRITE32_SHADOWED(
alert_class_reg_offset,
ALERT_HANDLER_ALERT_CLASS_SHADOWED_0_CLASS_A_0_VALUE_CLASSB);
}
// Configure class B local alerts.
// Unfortunately, we can't use EXPECT_MASK for these reads/writes, since the
// target registers are shadowed.
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_REG_RESVAL);
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_REG_RESVAL);
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_REG_OFFSET,
{{ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_0_EN_LA_0_BIT, true}});
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_CLASS_LA_0_VALUE_CLASSB);
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_REG_RESVAL);
EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2_REG_RESVAL);
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_REG_OFFSET,
{{ALERT_HANDLER_LOC_ALERT_EN_SHADOWED_2_EN_LA_2_BIT, true}});
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_2_REG_OFFSET,
ALERT_HANDLER_LOC_ALERT_CLASS_SHADOWED_0_CLASS_LA_0_VALUE_CLASSB);
// Configure class B control register.
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_CLASSB_CTRL_SHADOWED_REG_OFFSET,
{
{ALERT_HANDLER_CLASSB_CTRL_SHADOWED_EN_BIT, true},
{ALERT_HANDLER_CLASSB_CTRL_SHADOWED_LOCK_BIT, false},
{ALERT_HANDLER_CLASSB_CTRL_SHADOWED_EN_E1_BIT, true},
{ALERT_HANDLER_CLASSB_CTRL_SHADOWED_MAP_E1_OFFSET, 0},
});
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSB_ACCUM_THRESH_SHADOWED_REG_OFFSET,
8);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSB_TIMEOUT_CYC_SHADOWED_REG_OFFSET,
2000);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSB_PHASE1_CYC_SHADOWED_REG_OFFSET,
20000);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSB_PHASE2_CYC_SHADOWED_REG_OFFSET,
15000);
EXPECT_WRITE32_SHADOWED(ALERT_HANDLER_CLASSB_PHASE3_CYC_SHADOWED_REG_OFFSET,
150000);
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_PING_TIMEOUT_CYC_SHADOWED_OFFSET,
50}});
EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
kDifAlertHandlerConfigOk);
}
// TEST_F(ConfigTest, BadAlert) {
// IgnoreMmioCalls();
// std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, kAlerts + 1};
// std::vector<dif_alert_handler_local_alert_t> locals_a = {
// kDifAlertHandlerLocalAlertEscalationPingFail,
//};
// std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
//{.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
//{.phase = kDifAlertHandlerClassStatePhase2, .signal = 1},
//};
// std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
//{.phase = kDifAlertHandlerClassStatePhase1, .cycles = 20000},
//{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
//};
// std::vector<dif_alert_handler_class_config_t> classes = {
//{
//.alert_class = kDifAlertHandlerClassA,
//.alerts = alerts_a.data(),
//.alerts_len = alerts_a.size(),
//.local_alerts = locals_a.data(),
//.local_alerts_len = locals_a.size(),
//.use_escalation_protocol = kDifAlertHandlerToggleDisabled,
//.automatic_locking = kDifAlertHandlerToggleEnabled,
//.accumulator_threshold = 12,
//.irq_deadline_cycles = 30000,
//.phase_signals = signals_a.data(),
//.phase_signals_len = signals_a.size(),
//.phase_durations = durations_a.data(),
//.phase_durations_len = durations_a.size(),
//},
//};
// dif_alert_handler_config_t config = {
//.ping_timeout = 50,
//.classes = classes.data(),
//.classes_len = classes.size(),
//};
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
//}
// TEST_F(ConfigTest, BadSignalPhase) {
// IgnoreMmioCalls();
// std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, 5};
// std::vector<dif_alert_handler_local_alert_t> locals_a = {
// kDifAlertHandlerLocalAlertEscalationPingFail,
//};
// std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
//{.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
//{.phase = kDifAlertHandlerClassStateTerminal, .signal = 1},
//};
// std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
//{.phase = kDifAlertHandlerClassStatePhase1, .cycles = 20000},
//{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
//};
// std::vector<dif_alert_handler_class_config_t> classes = {
//{
//.alert_class = kDifAlertHandlerClassA,
//.alerts = alerts_a.data(),
//.alerts_len = alerts_a.size(),
//.local_alerts = locals_a.data(),
//.local_alerts_len = locals_a.size(),
//.use_escalation_protocol = kDifAlertHandlerToggleDisabled,
//.automatic_locking = kDifAlertHandlerToggleEnabled,
//.accumulator_threshold = 12,
//.irq_deadline_cycles = 30000,
//.phase_signals = signals_a.data(),
//.phase_signals_len = signals_a.size(),
//.phase_durations = durations_a.data(),
//.phase_durations_len = durations_a.size(),
//},
//};
// dif_alert_handler_config_t config = {
//.ping_timeout = 50,
//.classes = classes.data(),
//.classes_len = classes.size(),
//};
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
//}
// TEST_F(ConfigTest, BadDurationPhase) {
// IgnoreMmioCalls();
// std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, 5};
// std::vector<dif_alert_handler_local_alert_t> locals_a = {
// kDifAlertHandlerLocalAlertEscalationPingFail,
//};
// std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
//{.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
//{.phase = kDifAlertHandlerClassStatePhase2, .signal = 1},
//};
// std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
//{.phase = kDifAlertHandlerClassStateTerminal, .cycles = 20000},
//{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
//};
// std::vector<dif_alert_handler_class_config_t> classes = {
//{
//.alert_class = kDifAlertHandlerClassA,
//.alerts = alerts_a.data(),
//.alerts_len = alerts_a.size(),
//.local_alerts = locals_a.data(),
//.local_alerts_len = locals_a.size(),
//.use_escalation_protocol = kDifAlertHandlerToggleDisabled,
//.automatic_locking = kDifAlertHandlerToggleEnabled,
//.accumulator_threshold = 12,
//.irq_deadline_cycles = 30000,
//.phase_signals = signals_a.data(),
//.phase_signals_len = signals_a.size(),
//.phase_durations = durations_a.data(),
//.phase_durations_len = durations_a.size(),
//},
//};
// dif_alert_handler_config_t config = {
//.ping_timeout = 50,
//.classes = classes.data(),
//.classes_len = classes.size(),
//};
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
//}
// TEST_F(ConfigTest, BadPointers) {
// IgnoreMmioCalls();
// std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, 5};
// std::vector<dif_alert_handler_local_alert_t> locals_a = {
// kDifAlertHandlerLocalAlertEscalationPingFail,
//};
// std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
//{.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
//{.phase = kDifAlertHandlerClassStatePhase2, .signal = 1},
//};
// std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
//{.phase = kDifAlertHandlerClassStateTerminal, .cycles = 20000},
//{.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
//};
// std::vector<dif_alert_handler_class_config_t> classes = {
//{
//.alert_class = kDifAlertHandlerClassA,
//.alerts = alerts_a.data(),
//.alerts_len = alerts_a.size(),
//.local_alerts = locals_a.data(),
//.local_alerts_len = locals_a.size(),
//.use_escalation_protocol = kDifAlertHandlerToggleDisabled,
//.automatic_locking = kDifAlertHandlerToggleEnabled,
//.accumulator_threshold = 12,
//.irq_deadline_cycles = 30000,
//.phase_signals = signals_a.data(),
//.phase_signals_len = signals_a.size(),
//.phase_durations = durations_a.data(),
//.phase_durations_len = durations_a.size(),
//},
//};
// dif_alert_handler_config_t config = {
//.ping_timeout = 50,
//.classes = classes.data(),
//.classes_len = classes.size(),
//};
// classes[0].alerts = nullptr;
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
// classes[0].alerts = alerts_a.data();
// classes[0].local_alerts = nullptr;
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
// classes[0].local_alerts = locals_a.data();
// classes[0].phase_signals = nullptr;
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
// classes[0].phase_signals = signals_a.data();
// classes[0].phase_durations = nullptr;
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
//}
// TEST_F(ConfigTest, BadClass) {
// IgnoreMmioCalls();
// std::vector<dif_alert_handler_alert_t> alerts_a = {1, 2, 5};
// std::vector<dif_alert_handler_local_alert_t> locals_a = {
// kDifAlertHandlerLocalAlertEscalationPingFail,
// };
// std::vector<dif_alert_handler_class_phase_signal_t> signals_a = {
// {.phase = kDifAlertHandlerClassStatePhase0, .signal = 3},
// {.phase = kDifAlertHandlerClassStatePhase2, .signal = 1},
// };
// std::vector<dif_alert_handler_class_phase_duration_t> durations_a = {
// {.phase = kDifAlertHandlerClassStateTerminal, .cycles = 20000},
// {.phase = kDifAlertHandlerClassStatePhase2, .cycles = 15000},
// };
// std::vector<dif_alert_handler_class_config_t> classes = {
// {
// .alert_class = static_cast<dif_alert_handler_class_t>(12),
// .alerts = alerts_a.data(),
// .alerts_len = alerts_a.size(),
// .local_alerts = locals_a.data(),
// .local_alerts_len = locals_a.size(),
// .use_escalation_protocol = kDifAlertHandlerToggleDisabled,
// .automatic_locking = kDifAlertHandlerToggleEnabled,
// .accumulator_threshold = 12,
// .irq_deadline_cycles = 30000,
// .phase_signals = signals_a.data(),
// .phase_signals_len = signals_a.size(),
// .phase_durations = durations_a.data(),
// .phase_durations_len = durations_a.size(),
// },
// };
// dif_alert_handler_config_t config = {
// .ping_timeout = 50,
// .classes = classes.data(),
// .classes_len = classes.size(),
// };
// EXPECT_EQ(dif_alert_handler_configure(&handler_, config),
// kDifAlertHandlerConfigError);
// }
TEST_F(ConfigTest, NullArgs) {
EXPECT_EQ(dif_alert_handler_configure(nullptr, {}),
kDifAlertHandlerConfigBadArg);
}
class LockTest : public AlertTest {};
TEST_F(LockTest, IsLocked) {
bool flag;
EXPECT_READ32(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
false}});
EXPECT_EQ(dif_alert_handler_is_locked(&handler_, &flag), kDifAlertHandlerOk);
EXPECT_FALSE(flag);
EXPECT_READ32(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
true}});
EXPECT_EQ(dif_alert_handler_is_locked(&handler_, &flag), kDifAlertHandlerOk);
EXPECT_TRUE(flag);
}
TEST_F(LockTest, Lock) {
EXPECT_WRITE32_SHADOWED(
ALERT_HANDLER_PING_TIMER_EN_SHADOWED_REG_OFFSET,
{{ALERT_HANDLER_PING_TIMER_EN_SHADOWED_PING_TIMER_EN_SHADOWED_BIT,
true}});
EXPECT_EQ(dif_alert_handler_lock(&handler_), kDifAlertHandlerOk);
}
TEST_F(LockTest, NullArgs) {
bool flag;
EXPECT_EQ(dif_alert_handler_is_locked(nullptr, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_is_locked(&handler_, nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_lock(nullptr), kDifAlertHandlerBadArg);
}
class IrqTest : public AlertTest {};
TEST_F(IrqTest, IsPending) {
bool flag;
EXPECT_READ32(ALERT_HANDLER_INTR_STATE_REG_OFFSET,
{
{ALERT_HANDLER_INTR_COMMON_CLASSB_BIT, true},
{ALERT_HANDLER_INTR_COMMON_CLASSD_BIT, true},
});
EXPECT_EQ(dif_alert_handler_irq_is_pending(&handler_, kDifAlertHandlerClassA,
&flag),
kDifAlertHandlerOk);
EXPECT_FALSE(flag);
EXPECT_READ32(ALERT_HANDLER_INTR_STATE_REG_OFFSET,
{
{ALERT_HANDLER_INTR_COMMON_CLASSB_BIT, true},
{ALERT_HANDLER_INTR_COMMON_CLASSD_BIT, true},
});
EXPECT_EQ(dif_alert_handler_irq_is_pending(&handler_, kDifAlertHandlerClassB,
&flag),
kDifAlertHandlerOk);
EXPECT_TRUE(flag);
}
TEST_F(IrqTest, Ack) {
EXPECT_MASK32(ALERT_HANDLER_INTR_STATE_REG_OFFSET,
{{ALERT_HANDLER_INTR_COMMON_CLASSC_BIT, 1, true}});
EXPECT_EQ(
dif_alert_handler_irq_acknowledge(&handler_, kDifAlertHandlerClassC),
kDifAlertHandlerOk);
}
TEST_F(IrqTest, GetEnabled) {
dif_alert_handler_toggle_t flag;
EXPECT_READ32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET,
{
{ALERT_HANDLER_INTR_COMMON_CLASSB_BIT, true},
{ALERT_HANDLER_INTR_COMMON_CLASSD_BIT, true},
});
EXPECT_EQ(dif_alert_handler_irq_get_enabled(&handler_, kDifAlertHandlerClassA,
&flag),
kDifAlertHandlerOk);
EXPECT_EQ(flag, kDifAlertHandlerToggleDisabled);
EXPECT_READ32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET,
{
{ALERT_HANDLER_INTR_COMMON_CLASSB_BIT, true},
{ALERT_HANDLER_INTR_COMMON_CLASSD_BIT, true},
});
EXPECT_EQ(dif_alert_handler_irq_get_enabled(&handler_, kDifAlertHandlerClassB,
&flag),
kDifAlertHandlerOk);
EXPECT_EQ(flag, kDifAlertHandlerToggleEnabled);
}
TEST_F(IrqTest, SetEnabled) {
EXPECT_MASK32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET,
{{ALERT_HANDLER_INTR_COMMON_CLASSC_BIT, 1, true}});
EXPECT_EQ(dif_alert_handler_irq_set_enabled(&handler_, kDifAlertHandlerClassC,
kDifAlertHandlerToggleEnabled),
kDifAlertHandlerOk);
}
TEST_F(IrqTest, SetDisabled) {
EXPECT_MASK32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET,
{{ALERT_HANDLER_INTR_COMMON_CLASSD_BIT, 1, false}});
EXPECT_EQ(dif_alert_handler_irq_set_enabled(&handler_, kDifAlertHandlerClassD,
kDifAlertHandlerToggleDisabled),
kDifAlertHandlerOk);
}
TEST_F(IrqTest, Force) {
EXPECT_WRITE32(ALERT_HANDLER_INTR_TEST_REG_OFFSET,
{{ALERT_HANDLER_INTR_COMMON_CLASSC_BIT, true}});
EXPECT_EQ(dif_alert_handler_irq_force(&handler_, kDifAlertHandlerClassC),
kDifAlertHandlerOk);
}
TEST_F(IrqTest, Snapshot) {
EXPECT_WRITE32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_EQ(dif_alert_handler_irq_disable_all(&handler_, nullptr),
kDifAlertHandlerOk);
EXPECT_READ32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET, 0xaa4242aa);
EXPECT_WRITE32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET, 0);
dif_alert_handler_irq_snapshot_t snap;
EXPECT_EQ(dif_alert_handler_irq_disable_all(&handler_, &snap),
kDifAlertHandlerOk);
EXPECT_WRITE32(ALERT_HANDLER_INTR_ENABLE_REG_OFFSET, 0xaa4242aa);
EXPECT_EQ(dif_alert_handler_irq_restore_all(&handler_, &snap),
kDifAlertHandlerOk);
}
TEST_F(IrqTest, NullArgs) {
bool flag;
EXPECT_EQ(
dif_alert_handler_irq_is_pending(nullptr, kDifAlertHandlerClassA, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_is_pending(&handler_, kDifAlertHandlerClassA,
nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_acknowledge(nullptr, kDifAlertHandlerClassA),
kDifAlertHandlerBadArg);
dif_alert_handler_toggle_t toggle;
EXPECT_EQ(dif_alert_handler_irq_get_enabled(nullptr, kDifAlertHandlerClassA,
&toggle),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_get_enabled(&handler_, kDifAlertHandlerClassA,
nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_set_enabled(nullptr, kDifAlertHandlerClassA,
kDifAlertHandlerToggleEnabled),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_force(nullptr, kDifAlertHandlerClassA),
kDifAlertHandlerBadArg);
dif_alert_handler_irq_snapshot_t snap;
EXPECT_EQ(dif_alert_handler_irq_disable_all(nullptr, &snap),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_disable_all(nullptr, &snap),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_irq_restore_all(&handler_, nullptr),
kDifAlertHandlerBadArg);
}
class CauseTest : public AlertTest {};
TEST_F(CauseTest, IsCause) {
bool flag;
EXPECT_READ32(ALERT_HANDLER_ALERT_CAUSE_5_REG_OFFSET, {{0, true}});
EXPECT_EQ(dif_alert_handler_alert_is_cause(&handler_, 5, &flag),
kDifAlertHandlerOk);
EXPECT_TRUE(flag);
EXPECT_READ32(ALERT_HANDLER_ALERT_CAUSE_6_REG_OFFSET, {{0, false}});
EXPECT_EQ(dif_alert_handler_alert_is_cause(&handler_, 6, &flag),
kDifAlertHandlerOk);
EXPECT_FALSE(flag);
}
TEST_F(CauseTest, Ack) {
EXPECT_WRITE32(ALERT_HANDLER_ALERT_CAUSE_0_REG_OFFSET, {{11, true}});
EXPECT_EQ(dif_alert_handler_alert_acknowledge(&handler_, 11),
kDifAlertHandlerOk);
}
TEST_F(CauseTest, BadAlert) {
bool flag;
EXPECT_EQ(dif_alert_handler_alert_is_cause(&handler_, kAlerts, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_alert_acknowledge(&handler_, kAlerts),
kDifAlertHandlerBadArg);
}
// TEST_F(CauseTest, IsCauseLocal) {
// bool flag;
// EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_CAUSE_0_REG_OFFSET,
// {{ALERT_HANDLER_LOC_ALERT_CAUSE_0_LA_0_BIT, true},
// {ALERT_HANDLER_LOC_ALERT_CAUSE_1_LA_1_BIT, true}});
// EXPECT_EQ(dif_alert_handler_local_alert_is_cause(
// &handler_, kDifAlertHandlerLocalAlertEscalationPingFail,
// &flag),
// kDifAlertHandlerOk);
// EXPECT_TRUE(flag);
// EXPECT_READ32(ALERT_HANDLER_LOC_ALERT_CAUSE_0_REG_OFFSET,
// {{ALERT_HANDLER_LOC_ALERT_CAUSE_0_LA_0_BIT, true},
// {ALERT_HANDLER_LOC_ALERT_CAUSE_1_LA_1_BIT, true}});
// EXPECT_EQ(dif_alert_handler_local_alert_is_cause(
// &handler_, kDifAlertHandlerLocalAlertAlertIntegrityFail,
// &flag),
// kDifAlertHandlerOk);
// EXPECT_FALSE(flag);
// }
TEST_F(CauseTest, AckLocal) {
EXPECT_WRITE32(ALERT_HANDLER_LOC_ALERT_CAUSE_3_REG_OFFSET,
{{ALERT_HANDLER_LOC_ALERT_CAUSE_3_LA_3_BIT, true}});
EXPECT_EQ(dif_alert_handler_local_alert_acknowledge(
&handler_, kDifAlertHandlerLocalAlertEscalationIntegrityFail),
kDifAlertHandlerOk);
EXPECT_WRITE32(ALERT_HANDLER_LOC_ALERT_CAUSE_4_REG_OFFSET,
{{ALERT_HANDLER_LOC_ALERT_CAUSE_4_LA_4_BIT, true}});
EXPECT_EQ(dif_alert_handler_local_alert_acknowledge(
&handler_, kDifAlertHandlerLocalAlertBusIntegrityFail),
kDifAlertHandlerOk);
}
TEST_F(CauseTest, NullArgs) {
bool flag;
EXPECT_EQ(dif_alert_handler_alert_is_cause(nullptr, 5, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_alert_is_cause(&handler_, 5, nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_alert_acknowledge(nullptr, 11),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_local_alert_is_cause(
nullptr, kDifAlertHandlerLocalAlertEscalationPingFail, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(
dif_alert_handler_local_alert_is_cause(
&handler_, kDifAlertHandlerLocalAlertEscalationPingFail, nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_local_alert_acknowledge(
nullptr, kDifAlertHandlerLocalAlertEscalationIntegrityFail),
kDifAlertHandlerBadArg);
}
class EscalationTest : public AlertTest {};
TEST_F(EscalationTest, CanClear) {
bool flag;
EXPECT_READ32(ALERT_HANDLER_CLASSB_CLR_REGWEN_REG_OFFSET, true);
EXPECT_EQ(dif_alert_handler_escalation_can_clear(
&handler_, kDifAlertHandlerClassB, &flag),
kDifAlertHandlerOk);
EXPECT_TRUE(flag);
EXPECT_READ32(ALERT_HANDLER_CLASSA_CLR_REGWEN_REG_OFFSET, false);
EXPECT_EQ(dif_alert_handler_escalation_can_clear(
&handler_, kDifAlertHandlerClassA, &flag),
kDifAlertHandlerOk);
EXPECT_FALSE(flag);
}
TEST_F(EscalationTest, Disable) {
EXPECT_WRITE32(ALERT_HANDLER_CLASSC_CLR_REGWEN_REG_OFFSET, true);
EXPECT_EQ(dif_alert_handler_escalation_disable_clearing(
&handler_, kDifAlertHandlerClassC),
kDifAlertHandlerOk);
}
TEST_F(EscalationTest, Clear) {
EXPECT_WRITE32(ALERT_HANDLER_CLASSD_CLR_REG_OFFSET, true);
EXPECT_EQ(
dif_alert_handler_escalation_clear(&handler_, kDifAlertHandlerClassD),
kDifAlertHandlerOk);
}
TEST_F(EscalationTest, NullArgs) {
bool flag;
EXPECT_EQ(dif_alert_handler_escalation_can_clear(
nullptr, kDifAlertHandlerClassB, &flag),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_escalation_can_clear(
&handler_, kDifAlertHandlerClassB, nullptr),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_escalation_disable_clearing(
nullptr, kDifAlertHandlerClassC),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_escalation_clear(nullptr, kDifAlertHandlerClassD),
kDifAlertHandlerBadArg);
}
class GetterTest : public AlertTest {};
TEST_F(GetterTest, GetAcc) {
uint16_t alerts;
EXPECT_READ32(ALERT_HANDLER_CLASSB_ACCUM_CNT_REG_OFFSET, 0xaaaa);
EXPECT_EQ(dif_alert_handler_get_accumulator(&handler_, kDifAlertHandlerClassB,
&alerts),
kDifAlertHandlerOk);
EXPECT_EQ(alerts, 0xaaaa);
}
TEST_F(GetterTest, GetCycles) {
uint32_t cycles;
EXPECT_READ32(ALERT_HANDLER_CLASSD_ESC_CNT_REG_OFFSET, 0xaaaaaaaa);
EXPECT_EQ(dif_alert_handler_get_escalation_counter(
&handler_, kDifAlertHandlerClassD, &cycles),
kDifAlertHandlerOk);
EXPECT_EQ(cycles, 0xaaaaaaaa);
}
TEST_F(GetterTest, GetState) {
dif_alert_handler_class_state_t state;
EXPECT_READ32(ALERT_HANDLER_CLASSC_STATE_REG_OFFSET,
ALERT_HANDLER_CLASSA_STATE_CLASSA_STATE_VALUE_TIMEOUT);
EXPECT_EQ(dif_alert_handler_get_class_state(&handler_, kDifAlertHandlerClassC,
&state),
kDifAlertHandlerOk);
EXPECT_EQ(state, kDifAlertHandlerClassStateTimeout);
EXPECT_READ32(ALERT_HANDLER_CLASSA_STATE_REG_OFFSET,
ALERT_HANDLER_CLASSA_STATE_CLASSA_STATE_VALUE_PHASE2);
EXPECT_EQ(dif_alert_handler_get_class_state(&handler_, kDifAlertHandlerClassA,
&state),
kDifAlertHandlerOk);
EXPECT_EQ(state, kDifAlertHandlerClassStatePhase2);
}
TEST_F(GetterTest, NullArgs) {
uint16_t alerts;
EXPECT_EQ(dif_alert_handler_get_accumulator(nullptr, kDifAlertHandlerClassB,
&alerts),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_get_accumulator(&handler_, kDifAlertHandlerClassB,
nullptr),
kDifAlertHandlerBadArg);
uint32_t cycles;
EXPECT_EQ(dif_alert_handler_get_escalation_counter(
nullptr, kDifAlertHandlerClassB, &cycles),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_get_escalation_counter(
&handler_, kDifAlertHandlerClassB, nullptr),
kDifAlertHandlerBadArg);
dif_alert_handler_class_state_t state;
EXPECT_EQ(dif_alert_handler_get_class_state(nullptr, kDifAlertHandlerClassC,
&state),
kDifAlertHandlerBadArg);
EXPECT_EQ(dif_alert_handler_get_class_state(&handler_, kDifAlertHandlerClassC,
nullptr),
kDifAlertHandlerBadArg);
}
} // namespace
} // namespace dif_alert_handler_unittest