blob: 45cdd4190f4e4149a6e1551dd07ecb6674709b1c [file] [log] [blame]
Tomáš Peckabaf289c2024-01-24 15:12:44 +01001/*
2 * Copyright (C) 2024 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Tomáš Pecka <tomas.pecka@cesnet.cz>
5 *
6 */
7
8#pragma once
9
10#include "trompeloeil_doctest.h"
Tomáš Pecka1211fd92024-01-24 15:24:07 +010011#include <optional>
Tomáš Peckabaf289c2024-01-24 15:12:44 +010012#include <sysrepo-cpp/Subscription.hpp>
13#include "sysrepo-helpers/common.h"
14#include "sysrepo-helpers/datastore.h"
15#include "sysrepo-helpers/rpc.h"
16#include "test_log_setup.h"
17
Tomáš Peckae66a1932024-01-25 13:43:51 +010018inline ValueChanges constructAlarmInventoryChange(const std::string& alarmType,
19 const std::string& alarmQualifier,
20 const std::set<std::string>& resources,
21 const std::set<std::string>& severities,
22 const std::optional<bool>& willClear,
23 const std::optional<std::string>& description)
Tomáš Pecka1211fd92024-01-24 15:24:07 +010024{
25 const std::string prefix = "/ietf-alarms:alarms/alarm-inventory/alarm-type[alarm-type-id='" + alarmType + "'][alarm-type-qualifier='" + alarmQualifier + "']";
26
27 ValueChanges ret{
28 {prefix + "/alarm-type-id", alarmType},
29 {prefix + "/alarm-type-qualifier", alarmQualifier},
30 };
31
Tomáš Peckae66a1932024-01-25 13:43:51 +010032 if (willClear) {
33 ret.emplace(prefix + "/will-clear", *willClear ? "true" : "false");
34 }
35
36 if (description) {
37 ret.emplace(prefix + "/description", *description);
38 }
39
Tomáš Pecka1211fd92024-01-24 15:24:07 +010040 size_t i = 1; /* YANG uses 1-based indexing */
41 for (const auto& severity : severities) {
42 ret.emplace(prefix + "/severity-level[" + std::to_string(i++) + "]", severity);
43 }
44
45 i = 1;
46 for (const auto& resource : resources) {
47 ret.emplace(prefix + "/resource[" + std::to_string(i++) + "]", resource);
48 }
49
50 return ret;
51}
52
Tomáš Peckabaf289c2024-01-24 15:12:44 +010053/** @brief A simple mock implementation of the alarm server */
54struct AlarmWatcher {
55 /** @brief Poor man's /ietf-alarms:alarms/alarm-inventory implementation in C++. */
56 struct AlarmInventory {
Tomáš Pecka1211fd92024-01-24 15:24:07 +010057 struct AlarmKey {
58 std::string type;
59 std::string qualifier;
60 auto operator<=>(const AlarmKey&) const = default;
61 };
62 struct AllowedResourcesAndSeverities {
63 std::set<std::string> resources;
64 std::set<std::string> severities;
65 };
66 std::map<AlarmKey, AllowedResourcesAndSeverities> inventory;
Tomáš Peckabaf289c2024-01-24 15:12:44 +010067
Tomáš Pecka1211fd92024-01-24 15:24:07 +010068 void add(const std::string& alarmTypeId, const std::string& alarmTypeQualifier, const std::set<std::string>& resources, const std::set<std::string>& severities);
69 bool contains(const std::string& alarmTypeId, const std::string& alarmTypeQualifier, const std::optional<std::string>& resource, const std::optional<std::string>& severity) const;
Tomáš Peckabaf289c2024-01-24 15:12:44 +010070 };
71
72 AlarmInventory alarmInventory;
73 DatastoreWatcher datastoreWatcher;
74 RPCWatcher rpcWatcher;
75
76 AlarmWatcher(sysrepo::Session& session);
77};
78
79// checks if the alarm is contained in AlarmInventory
Tomáš Pecka1211fd92024-01-24 15:24:07 +010080#define WITH_ALARM_IN_INVENTORY(INV, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITY) LR_WITH(INV.contains(ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITY))
Tomáš Peckabaf289c2024-01-24 15:12:44 +010081
82// inserts the alarm in AlarmInventory as a side effect
Tomáš Pecka1211fd92024-01-24 15:24:07 +010083#define INSERT_INTO_INVENTORY(INV, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITIES) LR_SIDE_EFFECT(INV.add(ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITIES))
Tomáš Peckabaf289c2024-01-24 15:12:44 +010084
Tomáš Peckae66a1932024-01-25 13:43:51 +010085#define REQUIRE_NEW_ALARM_INVENTORY_ENTRY(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION) \
86 REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION)) \
Tomáš Pecka1211fd92024-01-24 15:24:07 +010087 .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES)
Tomáš Peckabaf289c2024-01-24 15:12:44 +010088
89#define REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE) \
90 REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, \
91 (ValueChanges{ \
92 {"/ietf-alarms:alarms/alarm-inventory/alarm-type[alarm-type-id='" ALARM_TYPE "'][alarm-type-qualifier='" ALARM_QUALIFIER "']/resource[1]", RESOURCE}, \
93 })) \
Tomáš Pecka1211fd92024-01-24 15:24:07 +010094 .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, (std::set<std::string>{RESOURCE}), (std::set<std::string>{}))
Tomáš Peckabaf289c2024-01-24 15:12:44 +010095
96#define REQUIRE_NEW_ALARM(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITY, TEXT) \
97 REQUIRE_RPC_CALL(WATCHER.rpcWatcher, (Values{ \
98 {"/sysrepo-ietf-alarms:create-or-update-alarm", "(unprintable)"}, \
99 {"/sysrepo-ietf-alarms:create-or-update-alarm/alarm-text", TEXT}, \
100 {"/sysrepo-ietf-alarms:create-or-update-alarm/alarm-type-id", ALARM_TYPE}, \
101 {"/sysrepo-ietf-alarms:create-or-update-alarm/alarm-type-qualifier", ALARM_QUALIFIER}, \
102 {"/sysrepo-ietf-alarms:create-or-update-alarm/resource", RESOURCE}, \
103 {"/sysrepo-ietf-alarms:create-or-update-alarm/severity", SEVERITY}, \
104 })) \
Tomáš Pecka1211fd92024-01-24 15:24:07 +0100105 .WITH_ALARM_IN_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITY)