Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More testing and finalizing of themis #594

Merged
merged 10 commits into from
Jun 27, 2024
6 changes: 3 additions & 3 deletions docs/design/snitch.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ The alarm system is exposed through the `com.skaginn3x.Alarm` interface.
RegisterAlarm (s: tfc_id, i: alarm_level, b: latching) -> i: alarm_id Note errors can only be latched
# ListAlarms returns boolean true in_locale if translation exists otherwise english
ListAlarms () -> s -> json of: std::vector<struct { string description; string details; bool latching; enum alarm_level; std::map<locale, struct translations{ string description; string details}> ; }>
# Note active = -1 for all, alarm_level = -1 for all a max size of 100 alarms will be sent at a time
ListActivations (s: locale, i: start_count, i: count, i: alarm_level, i: active, x: startunixTimestamp, x: endUnixTimestamp) -> s -> json of: struct { string description; string details; bool latching; enum alarm_level; bool active; std::uint64_t millisec_from_epoch; };
# Note for state = -1 for all, alarm_level = -1 for all a max size of 100 alarms will be sent at a time
ListActivations (s: locale, i: start_count, i: count, i: alarm_level, i: state, x: startunixTimestamp, x: endUnixTimestamp) -> s -> json of: struct { string description; string details; bool latching; enum alarm_level; state_e state; std::uint64_t millisec_from_epoch; };
SetAlarm(i: alarm_id, as: variables)
ResetAlarm(i: alarm_id)
TryReset(i: alarm_id) # Transmits a signal to the alarm to reset itself
TryResetAll() # Transmits a signal to all alarms to reset themselfs
### Signals
AlarmActivationChanged(i: alarm_id, b: current_activation)
AlarmActivationChanged(i: alarm_id, n: level, n: state)
TryReset(i: alarm_id)
TryResetAll()
### Properties
Expand Down
25 changes: 10 additions & 15 deletions exes/themis/inc/alarm_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,9 @@ CREATE TABLE IF NOT EXISTS AlarmVariables(
db_ << "BEGIN;";
db_ << fmt::format(
"INSERT INTO Alarms(tfc_id, sha1sum, alarm_level, alarm_latching, registered_at) VALUES('{}','{}',{}, {}, {}) ON "
"CONFLICT (tfc_id, sha1sum) DO UPDATE SET registered_at={};",
"CONFLICT (tfc_id, sha1sum) DO UPDATE SET registered_at={} RETURNING alarm_id;",
tfc_id, sha1_ascii, std::to_underlying(alarm_level), latching ? 1 : 0, ms_count_registered_at,
ms_count_registered_at);
auto insert_id = db_.last_insert_rowid();
if (insert_id < 0) {
throw dbus_error("Failed to insert alarm into database");
}
alarm_id = static_cast<snitch::api::alarm_id_t>(insert_id);
ms_count_registered_at) >> [&](snitch::api::alarm_id_t id) { alarm_id = id; };
add_alarm_translation(alarm_id, "en", description, details);

// Reset the alarm if high on register
Expand Down Expand Up @@ -244,7 +239,7 @@ ON Alarms.sha1sum = AlarmTranslations.sha1sum;
std::uint64_t activation_id;
try {
db_ << fmt::format("INSERT INTO AlarmActivations(alarm_id, activation_time, activation_level) VALUES({},{},{})",
alarm_id, milliseconds_since_epoch(tp), std::to_underlying(tfc::snitch::api::active_e::active));
alarm_id, milliseconds_since_epoch(tp), std::to_underlying(tfc::snitch::api::state_e::active));
activation_id = static_cast<tfc::snitch::api::activation_id_t>(db_.last_insert_rowid());

for (auto& [key, value] : variables) {
Expand All @@ -263,10 +258,10 @@ ON Alarms.sha1sum = AlarmTranslations.sha1sum;
throw dbus_error("Cannot reset an inactive activation");
}
db_ << fmt::format("UPDATE AlarmActivations SET activation_level = {}, reset_time = {} WHERE activation_id = {};",
std::to_underlying(tfc::snitch::api::active_e::inactive), milliseconds_since_epoch(tp),
std::to_underlying(tfc::snitch::api::state_e::inactive), milliseconds_since_epoch(tp),
activation_id);
}
auto set_activation_status(snitch::api::alarm_id_t activation_id, tfc::snitch::api::active_e activation) -> void {
auto set_activation_status(snitch::api::alarm_id_t activation_id, tfc::snitch::api::state_e activation) -> void {
if (!is_activation_high(activation_id)) {
throw dbus_error("Cannot reset an inactive activation");
}
Expand All @@ -277,7 +272,7 @@ ON Alarms.sha1sum = AlarmTranslations.sha1sum;
auto get_activation_id_for_active_alarm(snitch::api::alarm_id_t alarm_id) -> std::optional<snitch::api::activation_id_t> {
std::optional<snitch::api::activation_id_t> activation_id = std::nullopt;
db_ << fmt::format("SELECT activation_id FROM AlarmActivations WHERE alarm_id = {} AND activation_level = {};", alarm_id,
std::to_underlying(tfc::snitch::api::active_e::active)) >>
std::to_underlying(tfc::snitch::api::state_e::active)) >>
[&](std::uint64_t id) { activation_id = id; };
return activation_id;
}
Expand All @@ -286,7 +281,7 @@ ON Alarms.sha1sum = AlarmTranslations.sha1sum;
std::uint64_t start_count,
std::uint64_t count,
tfc::snitch::level_e level,
tfc::snitch::api::active_e active,
tfc::snitch::api::state_e active,
std::optional<tfc::snitch::api::time_point> start,
std::optional<tfc::snitch::api::time_point> end)
-> std::vector<tfc::snitch::api::activation> {
Expand Down Expand Up @@ -314,7 +309,7 @@ WHERE activation_time >= {} AND activation_time <= {})",
if (level != tfc::snitch::level_e::all) {
populated_query += fmt::format(" AND alarm_level = {}", std::to_underlying(level));
}
if (active != tfc::snitch::api::active_e::all) {
if (active != tfc::snitch::api::state_e::all) {
populated_query += fmt::format(" AND activation_level = {}", std::to_underlying(active));
}
populated_query += fmt::format(" LIMIT {} OFFSET {};", count, start_count);
Expand All @@ -323,7 +318,7 @@ WHERE activation_time >= {} AND activation_time <= {})",

db_ << populated_query >> [&](snitch::api::activation_id_t activation_id, snitch::api::alarm_id_t alarm_id,
std::int64_t activation_time, std::optional<std::int64_t> reset_time,
std::underlying_type_t<snitch::api::active_e> activation_level,
std::underlying_type_t<snitch::api::state_e> activation_level,
std::optional<std::string> primary_details, std::optional<std::string> primary_description,
std::optional<std::string> backup_details, std::optional<std::string> backup_description,
bool alarm_latching, std::underlying_type_t<snitch::level_e> alarm_level) {
Expand All @@ -338,7 +333,7 @@ WHERE activation_time >= {} AND activation_time <= {})",
final_reset_time = timepoint_from_milliseconds(reset_time.value());
}
activations.emplace_back(alarm_id, activation_id, description, details,
static_cast<snitch::api::active_e>(activation_level),
static_cast<snitch::api::state_e>(activation_level),
static_cast<snitch::level_e>(alarm_level), alarm_latching,
timepoint_from_milliseconds(activation_time), final_reset_time, in_locale);
};
Expand Down
12 changes: 7 additions & 5 deletions exes/themis/inc/dbus_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,22 @@ class interface {
}
});
using tfc::snitch::level_e;
using tfc::snitch::api::active_e;
using tfc::snitch::api::state_e;
interface_->register_method(std::string(methods::list_activations),
[&](const std::string& locale, std::uint64_t start_count, std::uint64_t count,
std::underlying_type_t<level_e> alarm_level, std::underlying_type_t<active_e> active,
std::underlying_type_t<level_e> alarm_level, std::underlying_type_t<state_e> active,
int64_t start, int64_t end) -> std::string {
auto cstart = tfc::themis::alarm_database::timepoint_from_milliseconds(start);
auto cend = tfc::themis::alarm_database::timepoint_from_milliseconds(end);
return glz::write_json(database.list_activations(
locale, start_count, count, static_cast<tfc::snitch::level_e>(alarm_level),
static_cast<tfc::snitch::api::active_e>(active), cstart, cend));
static_cast<tfc::snitch::api::state_e>(active), cstart, cend));
});

// Signal alarm_id, current_activation, ack_status
interface_->register_signal<std::tuple<std::uint64_t, bool, bool>>(std::string(signals::alarm_activation_changed));
interface_->register_signal<std::tuple<tfc::snitch::api::alarm_id_t, std::underlying_type_t<tfc::snitch::level_e>,
std::underlying_type_t<tfc::snitch::api::state_e>>>(
std::string(signals::alarm_activation_changed));
interface_->register_signal<std::uint64_t>(std::string(signals::try_reset));
interface_->register_signal<void>(std::string(signals::try_reset_all));
name_lost_match_ = std::make_unique<sdbusplus::bus::match::match>(*connection_, match_rule_.data(),
Expand Down Expand Up @@ -112,7 +114,7 @@ class interface {
for (auto& alarm_id : alarm_vec) {
auto activation = database_.get_activation_id_for_active_alarm(alarm_id);
if (activation.has_value()) {
database_.set_activation_status(activation.value(), tfc::snitch::api::active_e::unknown);
database_.set_activation_status(activation.value(), tfc::snitch::api::state_e::unknown);
}
}
}
Expand Down
58 changes: 43 additions & 15 deletions exes/themis/tests/themis_database_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,25 @@ auto main(int argc, char** argv) -> int {

// Verify there is no sql logic error
auto activations = alarm_db.list_activations(
"es", 0, 10, tfc::snitch::level_e::unknown, tfc::snitch::api::active_e::all,
"es", 0, 10, tfc::snitch::level_e::unknown, tfc::snitch::api::state_e::all,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 0);

activations = alarm_db.list_activations(
"es", 0, 10, tfc::snitch::level_e::unknown, tfc::snitch::api::active_e::active,
"es", 0, 10, tfc::snitch::level_e::unknown, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 0);

activations = alarm_db.list_activations(
"es", 0, 10, tfc::snitch::level_e::info, tfc::snitch::api::active_e::active,
"es", 0, 10, tfc::snitch::level_e::info, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 0);

activations = alarm_db.list_activations(
"es", 0, 10, tfc::snitch::level_e::info, tfc::snitch::api::active_e::all,
"es", 0, 10, tfc::snitch::level_e::info, tfc::snitch::api::state_e::all,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 0);
Expand All @@ -101,17 +101,17 @@ auto main(int argc, char** argv) -> int {

// Verify our inserts
activations = alarm_db.list_activations(
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::all,
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::all,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 10) << activations.size();
activations = alarm_db.list_activations(
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::active,
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 0) << activations.size();
activations = alarm_db.list_activations(
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::inactive,
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::inactive,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 10) << activations.size();
Expand All @@ -122,7 +122,7 @@ auto main(int argc, char** argv) -> int {
alarm_db.add_alarm_translation(alarm_db.list_alarms().at(0).alarm_id, "es", "spanish description", "spanish details");
[[maybe_unused]] auto _ = alarm_db.set_alarm(insert_id, {});
auto activations = alarm_db.list_activations(
"is", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::active,
"is", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
Expand All @@ -131,7 +131,7 @@ auto main(int argc, char** argv) -> int {
expect(activations.at(0).in_requested_locale == false);

activations = alarm_db.list_activations(
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::active,
"es", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
Expand All @@ -146,7 +146,7 @@ auto main(int argc, char** argv) -> int {
expect(alarm_db.list_alarms().size() == 1);
[[maybe_unused]] auto _ = alarm_db.set_alarm(var_alarm_id, { { "var", "10.0" } });
auto activations = alarm_db.list_activations(
"en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::active,
"en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
Expand All @@ -161,23 +161,23 @@ auto main(int argc, char** argv) -> int {
"spanish details {var} {var2} {var3}");
_ = alarm_db.set_alarm(var_alarm_id, { { "var", "10.0" }, { "var2", "20.0" }, { "var3", "30.0" } });
activations = alarm_db.list_activations(
"en", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::active_e::active,
"en", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
expect(activations.at(0).alarm_id == var_alarm_id);
expect(activations.at(0).description == "description 10.0 20.0 30.0") << activations.at(0).description;
expect(activations.at(0).details == "details 10.0 20.0 30.0") << activations.at(0).details;
activations = alarm_db.list_activations(
"es", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::active_e::active,
"es", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
expect(activations.at(0).alarm_id == var_alarm_id);
expect(activations.at(0).description == "spanish description 10.0 20.0 30.0") << activations.at(0).description;
expect(activations.at(0).details == "spanish details 10.0 20.0 30.0") << activations.at(0).details;
activations = alarm_db.list_activations(
"is", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::active_e::active,
"is", 0, 10000, tfc::snitch::level_e::warning, tfc::snitch::api::state_e::active,
tfc::themis::alarm_database::timepoint_from_milliseconds(0),
tfc::themis::alarm_database::timepoint_from_milliseconds(std::numeric_limits<std::int64_t>::max()));
expect(activations.size() == 1);
Expand Down Expand Up @@ -206,14 +206,14 @@ auto main(int argc, char** argv) -> int {
time = alarm_database::timepoint_from_milliseconds(1);
auto activation_id = db.set_alarm(alarm_id, {}, time);
auto activations =
db.list_activations("en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::all, min_time, max_time);
db.list_activations("en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::all, min_time, max_time);
expect(activations.size() == 1);
expect(activations.at(0).set_timestamp == time);
expect(!activations.at(0).reset_timestamp.has_value());
auto reset_time = alarm_database::timepoint_from_milliseconds(2);
db.reset_alarm(activation_id, reset_time);
activations =
db.list_activations("en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::active_e::all, min_time, max_time);
db.list_activations("en", 0, 10000, tfc::snitch::level_e::info, tfc::snitch::api::state_e::all, min_time, max_time);
expect(!db.is_alarm_active(alarm_id));
expect(activations.size() == 1);
expect(activations.at(0).set_timestamp == time);
Expand Down Expand Up @@ -260,4 +260,32 @@ auto main(int argc, char** argv) -> int {
expect(alarm_id == new_alarm_id);
expect(!db.is_alarm_active(alarm_id));
};
"empty alarm list"_test = [] {
auto db = tfc::themis::alarm_database(true);
auto alarms = db.list_alarms();
expect(alarms.size() == 0);
};
"Second time an alarm is registered it should get the correct insert id"_test = []{
auto db = tfc::themis::alarm_database(true);
auto alarm_id = db.register_alarm_en("tfc_id", "description", "details", false, tfc::snitch::level_e::info);
auto alarm_id2 = db.register_alarm_en("tfc_id", "description", "details", false, tfc::snitch::level_e::info);
auto alarms = db.list_alarms();
expect(alarm_id == alarm_id2);
expect(alarms.size() == 1);
expect(alarms.at(0).alarm_id == alarm_id);
};

"Second time an alarm is registered it should get the correct insert id with a different alarm registered in the middle"_test = []{
auto db = tfc::themis::alarm_database(true);
auto alarm_id_first_time = db.register_alarm_en("tfc_id", "description", "details", false, tfc::snitch::level_e::info);
auto alarms = db.list_alarms();
expect(alarms.size() == 1);
auto other_alarm = db.register_alarm_en("tfc_other", "description", "details", false, tfc::snitch::level_e::info);
auto alarm_id_second_time = db.register_alarm_en("tfc_id", "description", "details", false, tfc::snitch::level_e::info);
alarms = db.list_alarms();
expect(alarm_id_first_time == alarm_id_second_time);
expect(alarm_id_first_time != other_alarm);
expect(alarms.size() == 2);
expect(alarms.at(0).alarm_id == alarm_id_first_time);
};
}
Loading
Loading