blob: b9828d490c68c5cfcf411a49adb2753029d94356 [file] [log] [blame]
Tomáš Pecka339bc672020-11-11 15:59:03 +01001#include "trompeloeil_doctest.h"
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +02002#include <cstdint>
Tomáš Pecka339bc672020-11-11 15:59:03 +01003#include "ietf-hardware/IETFHardware.h"
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +02004#include "ietf-hardware/thresholds.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +01005#include "mock/ietf_hardware.h"
6#include "pretty_printers.h"
7#include "test_log_setup.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +01008
9using namespace std::literals;
10
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020011#define NUKE_LAST_CHANGE(DATA) DATA.erase("/ietf-hardware:hardware/last-change")
12
Jan Kundrátbf39bcb2024-01-10 17:46:59 +010013#define COMPONENT(RESOURCE) "/ietf-hardware:hardware/component[name='" RESOURCE "']"
14
15#define THRESHOLD_STATE(RESOURCE, STATE) {COMPONENT(RESOURCE) "/sensor-data/value", STATE}
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020016
17using velia::ietf_hardware::State;
18
Tomáš Pecka339bc672020-11-11 15:59:03 +010019TEST_CASE("HardwareState")
20{
21 TEST_INIT_LOGS;
Tomáš Pecka339bc672020-11-11 15:59:03 +010022
23 trompeloeil::sequence seq1;
Tomáš Pecka83b62e12020-12-16 14:50:49 +010024 auto ietfHardware = std::make_shared<velia::ietf_hardware::IETFHardware>();
Tomáš Pecka339bc672020-11-11 15:59:03 +010025
26 auto fans = std::make_shared<FakeHWMon>();
27 auto sysfsTempCpu = std::make_shared<FakeHWMon>();
Václav Kubernát97e5ea12021-03-24 00:36:57 +010028 auto sysfsVoltageAc = std::make_shared<FakeHWMon>();
29 auto sysfsVoltageDc = std::make_shared<FakeHWMon>();
30 auto sysfsPower = std::make_shared<FakeHWMon>();
31 auto sysfsCurrent = std::make_shared<FakeHWMon>();
Tomáš Pecka339bc672020-11-11 15:59:03 +010032 auto emmc = std::make_shared<FakeEMMC>();
33
34 std::map<std::string, std::string> attributesEMMC;
35 std::map<std::string, int64_t> attributesHWMon;
36
37 // initialize all mocks
38 attributesEMMC = {
39 // FIXME passing initializer_list to macro is hell
40 {"date"s, "02/2017"s},
41 {"serial"s, "0x00a8808d"s},
42 {"name"s, "8GME4R"s},
43 };
44 FAKE_EMMC(emmc, attributesEMMC);
45
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020046 std::array<int64_t, 4> fanValues = {777, 0, 1280, 666};
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +010047 REQUIRE_CALL(*fans, attribute("fan1_input"s)).LR_RETURN(fanValues[0]).TIMES(5);
48 REQUIRE_CALL(*fans, attribute("fan2_input"s)).LR_RETURN(fanValues[1]).TIMES(5);
49 REQUIRE_CALL(*fans, attribute("fan3_input"s)).LR_RETURN(fanValues[2]).TIMES(5);
50 REQUIRE_CALL(*fans, attribute("fan4_input"s)).LR_RETURN(fanValues[3]).TIMES(5);
Tomáš Pecka339bc672020-11-11 15:59:03 +010051
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +010052 REQUIRE_CALL(*sysfsTempCpu, attribute("temp1_input")).RETURN(41800).TIMES(5);
Tomáš Pecka339bc672020-11-11 15:59:03 +010053
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +010054 REQUIRE_CALL(*sysfsVoltageAc, attribute("in1_input")).RETURN(220000).TIMES(5);
55 REQUIRE_CALL(*sysfsVoltageDc, attribute("in1_input")).RETURN(12000).TIMES(5);
56 REQUIRE_CALL(*sysfsPower, attribute("power1_input")).RETURN(14000000).TIMES(5);
57 REQUIRE_CALL(*sysfsCurrent, attribute("curr1_input")).RETURN(200).TIMES(5);
Václav Kubernát97e5ea12021-03-24 00:36:57 +010058
Tomáš Pecka339bc672020-11-11 15:59:03 +010059 attributesEMMC = {{"life_time"s, "40"s}};
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +010060 FAKE_EMMC(emmc, attributesEMMC).TIMES(5);
Tomáš Pecka339bc672020-11-11 15:59:03 +010061
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020062 using velia::ietf_hardware::OneThreshold;
63 using velia::ietf_hardware::Thresholds;
Tomáš Pecka63c3c3c2023-04-13 18:20:22 +020064 using velia::ietf_hardware::data_reader::EMMC;
65 using velia::ietf_hardware::data_reader::Fans;
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020066 using velia::ietf_hardware::data_reader::SensorType;
67 using velia::ietf_hardware::data_reader::StaticData;
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020068 using velia::ietf_hardware::data_reader::SysfsValue;
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020069
Tomáš Pecka339bc672020-11-11 15:59:03 +010070 // register components into hw state
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020071 ietfHardware->registerDataReader(StaticData("ne", std::nullopt, {{"class", "iana-hardware:chassis"}, {"mfg-name", "CESNET"s}}));
72 ietfHardware->registerDataReader(StaticData("ne:ctrl", "ne", {{"class", "iana-hardware:module"}}));
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020073 ietfHardware->registerDataReader(Fans("ne:fans", "ne", fans, 4, Thresholds<int64_t>{
74 .criticalLow = OneThreshold<int64_t>{300, 200},
75 .warningLow = OneThreshold<int64_t>{600, 200},
76 .warningHigh = std::nullopt,
77 .criticalHigh =std::nullopt,
78 }));
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020079 ietfHardware->registerDataReader(SysfsValue<SensorType::Temperature>("ne:ctrl:temperature-cpu", "ne:ctrl", sysfsTempCpu, 1));
Václav Kubernát97e5ea12021-03-24 00:36:57 +010080 ietfHardware->registerDataReader(SysfsValue<SensorType::VoltageAC>("ne:ctrl:voltage-in", "ne:ctrl", sysfsVoltageAc, 1));
81 ietfHardware->registerDataReader(SysfsValue<SensorType::VoltageDC>("ne:ctrl:voltage-out", "ne:ctrl", sysfsVoltageDc, 1));
82 ietfHardware->registerDataReader(SysfsValue<SensorType::Power>("ne:ctrl:power", "ne:ctrl", sysfsPower, 1));
83 ietfHardware->registerDataReader(SysfsValue<SensorType::Current>("ne:ctrl:current", "ne:ctrl", sysfsCurrent, 1));
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020084 ietfHardware->registerDataReader(EMMC("ne:ctrl:emmc", "ne:ctrl", emmc, Thresholds<int64_t>{
85 .criticalLow = OneThreshold<int64_t>{20, 0},
86 .warningLow = OneThreshold<int64_t>{50, 0},
87 .warningHigh = std::nullopt,
88 .criticalHigh = std::nullopt,
89 }));
90
91 /* Some data readers (like our PSU reader, see the FspYhPsu test) may set oper-state to enabled/disabled depending on whether the device is present.
92 * If the device is not present we also don't want to report some elements of the data tree that contain a sensor (ne:psu:child in this case).
93 * This should also trigger the alarm reporting that the sensor is missing so we should test that the State::NoValue is reported when the sensor disappears.
94 */
95 struct PsuDataReader {
96 const bool& active;
97
Tomáš Peckac0991ce2023-12-20 15:46:03 +010098 velia::ietf_hardware::SensorPollData operator()()
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +020099 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100100 velia::ietf_hardware::SideLoadedAlarm alarm;
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100101 velia::ietf_hardware::ThresholdsBySensorPath thr;
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200102 velia::ietf_hardware::DataTree res = {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100103 {COMPONENT("ne:psu") "/class", "iana-hardware:power-supply"},
104 {COMPONENT("ne:psu") "/parent", "ne"},
105 {COMPONENT("ne:psu") "/state/oper-state", "disabled"},
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200106 };
107
108 if (active) {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100109 res[COMPONENT("ne:psu") "/state/oper-state"] = "enabled";
110 res[COMPONENT("ne:psu:child") "/class"] = "iana-hardware:sensor";
111 res[COMPONENT("ne:psu:child") "/parent"] = "ne:psu";
112 res[COMPONENT("ne:psu:child") "/state/oper-state"] = "enabled";
113 res[COMPONENT("ne:psu:child") "/sensor-data/oper-status"] = "ok";
114 res[COMPONENT("ne:psu:child") "/sensor-data/value"] = "20000";
115 res[COMPONENT("ne:psu:child") "/sensor-data/value-precision"] = "0";
116 res[COMPONENT("ne:psu:child") "/sensor-data/value-scale"] = "milli";
117 res[COMPONENT("ne:psu:child") "/sensor-data/value-type"] = "volts-DC";
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100118
119 thr[COMPONENT("ne:psu:child") "/sensor-data/value"] = Thresholds<int64_t>{
120 .criticalLow = std::nullopt,
121 .warningLow = OneThreshold<int64_t>{10000, 2000},
122 .warningHigh = OneThreshold<int64_t>{15000, 2000},
123 .criticalHigh = std::nullopt,
124 };
Tomáš Pecka26b38212024-01-16 17:23:31 +0100125
126 alarm = {"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "cleared", "PSU missing."};
127 } else {
128 alarm = {"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "critical", "PSU missing."};
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200129 }
130
Tomáš Pecka26b38212024-01-16 17:23:31 +0100131 return {res, thr, {alarm}};
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200132 }
133 };
134 bool psuActive = true;
135 ietfHardware->registerDataReader(PsuDataReader{psuActive});
Tomáš Pecka339bc672020-11-11 15:59:03 +0100136
Tomáš Pecka3f811962023-04-14 10:54:32 +0200137 std::map<std::string, std::string> expected = {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100138 {COMPONENT("ne") "/class", "iana-hardware:chassis"},
139 {COMPONENT("ne") "/mfg-name", "CESNET"},
140 {COMPONENT("ne") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100141
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100142 {COMPONENT("ne:fans") "/class", "iana-hardware:module"},
143 {COMPONENT("ne:fans") "/parent", "ne"},
144 {COMPONENT("ne:fans") "/state/oper-state", "enabled"},
145 {COMPONENT("ne:fans:fan1") "/class", "iana-hardware:fan"},
146 {COMPONENT("ne:fans:fan1") "/parent", "ne:fans"},
147 {COMPONENT("ne:fans:fan1") "/state/oper-state", "enabled"},
148 {COMPONENT("ne:fans:fan1:rpm") "/class", "iana-hardware:sensor"},
149 {COMPONENT("ne:fans:fan1:rpm") "/parent", "ne:fans:fan1"},
150 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/oper-status", "ok"},
151 THRESHOLD_STATE("ne:fans:fan1:rpm", "777"),
152 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-precision", "0"},
153 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-scale", "units"},
154 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-type", "rpm"},
155 {COMPONENT("ne:fans:fan1:rpm") "/state/oper-state", "enabled"},
156 {COMPONENT("ne:fans:fan2") "/class", "iana-hardware:fan"},
157 {COMPONENT("ne:fans:fan2") "/parent", "ne:fans"},
158 {COMPONENT("ne:fans:fan2") "/state/oper-state", "enabled"},
159 {COMPONENT("ne:fans:fan2:rpm") "/class", "iana-hardware:sensor"},
160 {COMPONENT("ne:fans:fan2:rpm") "/parent", "ne:fans:fan2"},
161 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/oper-status", "ok"},
162 THRESHOLD_STATE("ne:fans:fan2:rpm", "0"),
163 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-precision", "0"},
164 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-scale", "units"},
165 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-type", "rpm"},
166 {COMPONENT("ne:fans:fan2:rpm") "/state/oper-state", "enabled"},
167 {COMPONENT("ne:fans:fan3") "/class", "iana-hardware:fan"},
168 {COMPONENT("ne:fans:fan3") "/parent", "ne:fans"},
169 {COMPONENT("ne:fans:fan3") "/state/oper-state", "enabled"},
170 {COMPONENT("ne:fans:fan3:rpm") "/class", "iana-hardware:sensor"},
171 {COMPONENT("ne:fans:fan3:rpm") "/parent", "ne:fans:fan3"},
172 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/oper-status", "ok"},
173 THRESHOLD_STATE("ne:fans:fan3:rpm", "1280"),
174 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-precision", "0"},
175 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-scale", "units"},
176 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-type", "rpm"},
177 {COMPONENT("ne:fans:fan3:rpm") "/state/oper-state", "enabled"},
178 {COMPONENT("ne:fans:fan4") "/class", "iana-hardware:fan"},
179 {COMPONENT("ne:fans:fan4") "/parent", "ne:fans"},
180 {COMPONENT("ne:fans:fan4") "/state/oper-state", "enabled"},
181 {COMPONENT("ne:fans:fan4:rpm") "/class", "iana-hardware:sensor"},
182 {COMPONENT("ne:fans:fan4:rpm") "/parent", "ne:fans:fan4"},
183 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/oper-status", "ok"},
184 THRESHOLD_STATE("ne:fans:fan4:rpm", "666"),
185 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-precision", "0"},
186 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-scale", "units"},
187 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-type", "rpm"},
188 {COMPONENT("ne:fans:fan4:rpm") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100189
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100190 {COMPONENT("ne:ctrl") "/parent", "ne"},
191 {COMPONENT("ne:ctrl") "/class", "iana-hardware:module"},
192 {COMPONENT("ne:ctrl") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100193
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100194 {COMPONENT("ne:ctrl:temperature-cpu") "/class", "iana-hardware:sensor"},
195 {COMPONENT("ne:ctrl:temperature-cpu") "/parent", "ne:ctrl"},
196 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/oper-status", "ok"},
197 THRESHOLD_STATE("ne:ctrl:temperature-cpu", "41800"),
198 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-precision", "0"},
199 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-scale", "milli"},
200 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-type", "celsius"},
201 {COMPONENT("ne:ctrl:temperature-cpu") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100202
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100203 {COMPONENT("ne:ctrl:power") "/class", "iana-hardware:sensor"},
204 {COMPONENT("ne:ctrl:power") "/parent", "ne:ctrl"},
205 {COMPONENT("ne:ctrl:power") "/sensor-data/oper-status", "ok"},
206 THRESHOLD_STATE("ne:ctrl:power", "14000000"),
207 {COMPONENT("ne:ctrl:power") "/sensor-data/value-precision", "0"},
208 {COMPONENT("ne:ctrl:power") "/sensor-data/value-scale", "micro"},
209 {COMPONENT("ne:ctrl:power") "/sensor-data/value-type", "watts"},
210 {COMPONENT("ne:ctrl:power") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100211
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100212 {COMPONENT("ne:ctrl:voltage-in") "/class", "iana-hardware:sensor"},
213 {COMPONENT("ne:ctrl:voltage-in") "/parent", "ne:ctrl"},
214 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/oper-status", "ok"},
215 THRESHOLD_STATE("ne:ctrl:voltage-in", "220000"),
216 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-precision", "0"},
217 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-scale", "milli"},
218 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-type", "volts-AC"},
219 {COMPONENT("ne:ctrl:voltage-in") "/state/oper-state", "enabled"},
220 {COMPONENT("ne:ctrl:voltage-out") "/class", "iana-hardware:sensor"},
221 {COMPONENT("ne:ctrl:voltage-out") "/parent", "ne:ctrl"},
222 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/oper-status", "ok"},
223 THRESHOLD_STATE("ne:ctrl:voltage-out", "12000"),
224 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-precision", "0"},
225 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-scale", "milli"},
226 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-type", "volts-DC"},
227 {COMPONENT("ne:ctrl:voltage-out") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100228
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100229 {COMPONENT("ne:ctrl:current") "/class", "iana-hardware:sensor"},
230 {COMPONENT("ne:ctrl:current") "/parent", "ne:ctrl"},
231 {COMPONENT("ne:ctrl:current") "/sensor-data/oper-status", "ok"},
232 THRESHOLD_STATE("ne:ctrl:current", "200"),
233 {COMPONENT("ne:ctrl:current") "/sensor-data/value-precision", "0"},
234 {COMPONENT("ne:ctrl:current") "/sensor-data/value-scale", "milli"},
235 {COMPONENT("ne:ctrl:current") "/sensor-data/value-type", "amperes"},
236 {COMPONENT("ne:ctrl:current") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100237
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100238 {COMPONENT("ne:ctrl:emmc") "/parent", "ne:ctrl"},
239 {COMPONENT("ne:ctrl:emmc") "/class", "iana-hardware:module"},
240 {COMPONENT("ne:ctrl:emmc") "/serial-num", "0x00a8808d"},
241 {COMPONENT("ne:ctrl:emmc") "/mfg-date", "2017-02-01T00:00:00-00:00"},
242 {COMPONENT("ne:ctrl:emmc") "/model-name", "8GME4R"},
243 {COMPONENT("ne:ctrl:emmc") "/state/oper-state", "enabled"},
244 {COMPONENT("ne:ctrl:emmc:lifetime") "/class", "iana-hardware:sensor"},
245 {COMPONENT("ne:ctrl:emmc:lifetime") "/parent", "ne:ctrl:emmc"},
246 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/oper-status", "ok"},
247 THRESHOLD_STATE("ne:ctrl:emmc:lifetime", "40"),
248 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-precision", "0"},
249 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-scale", "units"},
250 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-type", "other"},
251 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/units-display", "percent"},
252 {COMPONENT("ne:ctrl:emmc:lifetime") "/state/oper-state", "enabled"},
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200253
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100254 {COMPONENT("ne:psu") "/class", "iana-hardware:power-supply"},
255 {COMPONENT("ne:psu") "/parent", "ne"},
256 {COMPONENT("ne:psu") "/state/oper-state", "enabled"},
257 {COMPONENT("ne:psu:child") "/class", "iana-hardware:sensor"},
258 {COMPONENT("ne:psu:child") "/parent", "ne:psu"},
259 {COMPONENT("ne:psu:child") "/state/oper-state", "enabled"},
260 {COMPONENT("ne:psu:child") "/sensor-data/oper-status", "ok"},
261 THRESHOLD_STATE("ne:psu:child", "20000"),
262 {COMPONENT("ne:psu:child") "/sensor-data/value-precision", "0"},
263 {COMPONENT("ne:psu:child") "/sensor-data/value-scale", "milli"},
264 {COMPONENT("ne:psu:child") "/sensor-data/value-type", "volts-DC"},
Tomáš Pecka3f811962023-04-14 10:54:32 +0200265 };
Tomáš Pecka339bc672020-11-11 15:59:03 +0100266
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200267 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100268 auto [data, alarms, activeSensors, sideLoadedAlarms] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200269 NUKE_LAST_CHANGE(data);
270 REQUIRE(data == expected);
271 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
272 THRESHOLD_STATE("ne:ctrl:current", State::Disabled),
273 THRESHOLD_STATE("ne:ctrl:power", State::Disabled),
274 THRESHOLD_STATE("ne:ctrl:temperature-cpu", State::Disabled),
275 THRESHOLD_STATE("ne:ctrl:voltage-in", State::Disabled),
276 THRESHOLD_STATE("ne:ctrl:voltage-out", State::Disabled),
277 THRESHOLD_STATE("ne:ctrl:emmc:lifetime", State::WarningLow),
278 THRESHOLD_STATE("ne:fans:fan1:rpm", State::Normal),
279 THRESHOLD_STATE("ne:fans:fan2:rpm", State::CriticalLow),
280 THRESHOLD_STATE("ne:fans:fan3:rpm", State::Normal),
281 THRESHOLD_STATE("ne:fans:fan4:rpm", State::Normal),
282 THRESHOLD_STATE("ne:psu:child", State::WarningHigh),
283 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100284 REQUIRE(activeSensors == std::set<std::string>{
285 COMPONENT("ne:ctrl:current") "/sensor-data/value",
286 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
287 COMPONENT("ne:ctrl:power") "/sensor-data/value",
288 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
289 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
290 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
291 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
292 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
293 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
294 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
295 COMPONENT("ne:psu:child") "/sensor-data/value",
296 });
Tomáš Pecka26b38212024-01-16 17:23:31 +0100297 REQUIRE(sideLoadedAlarms == std::set<velia::ietf_hardware::SideLoadedAlarm>{{"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "cleared", "PSU missing."}});
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200298 }
299
300 fanValues[1] = 500;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100301 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "500";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200302 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100303 auto [data, alarms, activeSensors, sideLoadedAlarms] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200304 NUKE_LAST_CHANGE(data);
305 REQUIRE(data == expected);
306 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
307 THRESHOLD_STATE("ne:fans:fan2:rpm", State::WarningLow),
308 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100309 REQUIRE(activeSensors == std::set<std::string>{
310 COMPONENT("ne:ctrl:current") "/sensor-data/value",
311 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
312 COMPONENT("ne:ctrl:power") "/sensor-data/value",
313 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
314 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
315 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
316 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
317 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
318 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
319 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
320 COMPONENT("ne:psu:child") "/sensor-data/value",
321 });
Tomáš Pecka26b38212024-01-16 17:23:31 +0100322 REQUIRE(sideLoadedAlarms == std::set<velia::ietf_hardware::SideLoadedAlarm>{{"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "cleared", "PSU missing."}});
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200323 }
324
325 psuActive = false;
326 fanValues[1] = 1;
327 fanValues[2] = 5000;
328
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100329 expected.erase(COMPONENT("ne:psu:child") "/class");
330 expected.erase(COMPONENT("ne:psu:child") "/parent");
331 expected.erase(COMPONENT("ne:psu:child") "/state/oper-state");
332 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/oper-status");
333 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value");
334 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-precision");
335 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-scale");
336 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-type");
337 expected[COMPONENT("ne:psu") "/state/oper-state"] = "disabled";
338 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "1";
339 expected[COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value"] = "5000";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200340
341 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100342 auto [data, alarms, activeSensors, sideLoadedAlarms] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200343 NUKE_LAST_CHANGE(data);
344
345 REQUIRE(data == expected);
346 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
347 THRESHOLD_STATE("ne:fans:fan2:rpm", State::CriticalLow),
348 THRESHOLD_STATE("ne:psu:child", State::NoValue),
349 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100350 REQUIRE(activeSensors == std::set<std::string>{
351 COMPONENT("ne:ctrl:current") "/sensor-data/value",
352 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
353 COMPONENT("ne:ctrl:power") "/sensor-data/value",
354 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
355 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
356 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
357 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
358 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
359 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
360 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
361 });
Tomáš Pecka26b38212024-01-16 17:23:31 +0100362 REQUIRE(sideLoadedAlarms == std::set<velia::ietf_hardware::SideLoadedAlarm>{{"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "critical", "PSU missing."}});
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200363 }
364
365 psuActive = true;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100366 expected[COMPONENT("ne:psu") "/class"] = "iana-hardware:power-supply";
367 expected[COMPONENT("ne:psu") "/parent"] = "ne";
368 expected[COMPONENT("ne:psu") "/state/oper-state"] = "enabled";
369 expected[COMPONENT("ne:psu:child") "/class"] = "iana-hardware:sensor";
370 expected[COMPONENT("ne:psu:child") "/parent"] = "ne:psu";
371 expected[COMPONENT("ne:psu:child") "/state/oper-state"] = "enabled";
372 expected[COMPONENT("ne:psu:child") "/sensor-data/oper-status"] = "ok";
373 expected[COMPONENT("ne:psu:child") "/sensor-data/value"] = "20000";
374 expected[COMPONENT("ne:psu:child") "/sensor-data/value-precision"] = "0";
375 expected[COMPONENT("ne:psu:child") "/sensor-data/value-scale"] = "milli";
376 expected[COMPONENT("ne:psu:child") "/sensor-data/value-type"] = "volts-DC";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200377
378 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100379 auto [data, alarms, activeSensors, sideLoadedAlarms] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200380 NUKE_LAST_CHANGE(data);
381
382 REQUIRE(data == expected);
383 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
384 THRESHOLD_STATE("ne:psu:child", State::WarningHigh),
385 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100386 REQUIRE(activeSensors == std::set<std::string>{
387 COMPONENT("ne:ctrl:current") "/sensor-data/value",
388 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
389 COMPONENT("ne:ctrl:power") "/sensor-data/value",
390 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
391 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
392 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
393 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
394 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
395 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
396 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
397 COMPONENT("ne:psu:child") "/sensor-data/value",
398 });
Tomáš Pecka26b38212024-01-16 17:23:31 +0100399 REQUIRE(sideLoadedAlarms == std::set<velia::ietf_hardware::SideLoadedAlarm>{{"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "cleared", "PSU missing."}});
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200400 }
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100401
402
403 fanValues[0] = -1'000'000'001;
404 fanValues[1] = 1'000'000'001;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100405 expected[COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value"] = "-1000000000";
406 expected[COMPONENT("ne:fans:fan1:rpm") "/sensor-data/oper-status"] = "nonoperational";
407 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "1000000000";
408 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/oper-status"] = "nonoperational";
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100409
410 {
Tomáš Pecka26b38212024-01-16 17:23:31 +0100411 auto [data, alarms, activeSensors, sideLoadedAlarms] = ietfHardware->process();
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100412 NUKE_LAST_CHANGE(data);
413
414 REQUIRE(data == expected);
415 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
416 THRESHOLD_STATE("ne:fans:fan1:rpm", State::CriticalLow),
417 THRESHOLD_STATE("ne:fans:fan2:rpm", State::Normal),
418 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100419 REQUIRE(activeSensors == std::set<std::string>{
420 COMPONENT("ne:ctrl:current") "/sensor-data/value",
421 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
422 COMPONENT("ne:ctrl:power") "/sensor-data/value",
423 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
424 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
425 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
426 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
427 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
428 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
429 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
430 COMPONENT("ne:psu:child") "/sensor-data/value",
431 });
Tomáš Pecka26b38212024-01-16 17:23:31 +0100432 REQUIRE(sideLoadedAlarms == std::set<velia::ietf_hardware::SideLoadedAlarm>{{"velia-alarms:sensor-missing", COMPONENT("ne:psu"), "cleared", "PSU missing."}});
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100433 }
Tomáš Pecka339bc672020-11-11 15:59:03 +0100434}