blob: 0e73c5b7fd4fc5552f53a8d8ee8ca44daece8a1a [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áš Peckac0991ce2023-12-20 15:46:03 +0100100 velia::ietf_hardware::ThresholdsBySensorPath thr;
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200101 velia::ietf_hardware::DataTree res = {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100102 {COMPONENT("ne:psu") "/class", "iana-hardware:power-supply"},
103 {COMPONENT("ne:psu") "/parent", "ne"},
104 {COMPONENT("ne:psu") "/state/oper-state", "disabled"},
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200105 };
106
107 if (active) {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100108 res[COMPONENT("ne:psu") "/state/oper-state"] = "enabled";
109 res[COMPONENT("ne:psu:child") "/class"] = "iana-hardware:sensor";
110 res[COMPONENT("ne:psu:child") "/parent"] = "ne:psu";
111 res[COMPONENT("ne:psu:child") "/state/oper-state"] = "enabled";
112 res[COMPONENT("ne:psu:child") "/sensor-data/oper-status"] = "ok";
113 res[COMPONENT("ne:psu:child") "/sensor-data/value"] = "20000";
114 res[COMPONENT("ne:psu:child") "/sensor-data/value-precision"] = "0";
115 res[COMPONENT("ne:psu:child") "/sensor-data/value-scale"] = "milli";
116 res[COMPONENT("ne:psu:child") "/sensor-data/value-type"] = "volts-DC";
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100117
118 thr[COMPONENT("ne:psu:child") "/sensor-data/value"] = Thresholds<int64_t>{
119 .criticalLow = std::nullopt,
120 .warningLow = OneThreshold<int64_t>{10000, 2000},
121 .warningHigh = OneThreshold<int64_t>{15000, 2000},
122 .criticalHigh = std::nullopt,
123 };
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200124 }
125
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100126 return {res, thr};
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200127 }
128 };
129 bool psuActive = true;
130 ietfHardware->registerDataReader(PsuDataReader{psuActive});
Tomáš Pecka339bc672020-11-11 15:59:03 +0100131
Tomáš Pecka3f811962023-04-14 10:54:32 +0200132 std::map<std::string, std::string> expected = {
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100133 {COMPONENT("ne") "/class", "iana-hardware:chassis"},
134 {COMPONENT("ne") "/mfg-name", "CESNET"},
135 {COMPONENT("ne") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100136
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100137 {COMPONENT("ne:fans") "/class", "iana-hardware:module"},
138 {COMPONENT("ne:fans") "/parent", "ne"},
139 {COMPONENT("ne:fans") "/state/oper-state", "enabled"},
140 {COMPONENT("ne:fans:fan1") "/class", "iana-hardware:fan"},
141 {COMPONENT("ne:fans:fan1") "/parent", "ne:fans"},
142 {COMPONENT("ne:fans:fan1") "/state/oper-state", "enabled"},
143 {COMPONENT("ne:fans:fan1:rpm") "/class", "iana-hardware:sensor"},
144 {COMPONENT("ne:fans:fan1:rpm") "/parent", "ne:fans:fan1"},
145 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/oper-status", "ok"},
146 THRESHOLD_STATE("ne:fans:fan1:rpm", "777"),
147 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-precision", "0"},
148 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-scale", "units"},
149 {COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value-type", "rpm"},
150 {COMPONENT("ne:fans:fan1:rpm") "/state/oper-state", "enabled"},
151 {COMPONENT("ne:fans:fan2") "/class", "iana-hardware:fan"},
152 {COMPONENT("ne:fans:fan2") "/parent", "ne:fans"},
153 {COMPONENT("ne:fans:fan2") "/state/oper-state", "enabled"},
154 {COMPONENT("ne:fans:fan2:rpm") "/class", "iana-hardware:sensor"},
155 {COMPONENT("ne:fans:fan2:rpm") "/parent", "ne:fans:fan2"},
156 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/oper-status", "ok"},
157 THRESHOLD_STATE("ne:fans:fan2:rpm", "0"),
158 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-precision", "0"},
159 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-scale", "units"},
160 {COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value-type", "rpm"},
161 {COMPONENT("ne:fans:fan2:rpm") "/state/oper-state", "enabled"},
162 {COMPONENT("ne:fans:fan3") "/class", "iana-hardware:fan"},
163 {COMPONENT("ne:fans:fan3") "/parent", "ne:fans"},
164 {COMPONENT("ne:fans:fan3") "/state/oper-state", "enabled"},
165 {COMPONENT("ne:fans:fan3:rpm") "/class", "iana-hardware:sensor"},
166 {COMPONENT("ne:fans:fan3:rpm") "/parent", "ne:fans:fan3"},
167 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/oper-status", "ok"},
168 THRESHOLD_STATE("ne:fans:fan3:rpm", "1280"),
169 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-precision", "0"},
170 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-scale", "units"},
171 {COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value-type", "rpm"},
172 {COMPONENT("ne:fans:fan3:rpm") "/state/oper-state", "enabled"},
173 {COMPONENT("ne:fans:fan4") "/class", "iana-hardware:fan"},
174 {COMPONENT("ne:fans:fan4") "/parent", "ne:fans"},
175 {COMPONENT("ne:fans:fan4") "/state/oper-state", "enabled"},
176 {COMPONENT("ne:fans:fan4:rpm") "/class", "iana-hardware:sensor"},
177 {COMPONENT("ne:fans:fan4:rpm") "/parent", "ne:fans:fan4"},
178 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/oper-status", "ok"},
179 THRESHOLD_STATE("ne:fans:fan4:rpm", "666"),
180 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-precision", "0"},
181 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-scale", "units"},
182 {COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value-type", "rpm"},
183 {COMPONENT("ne:fans:fan4:rpm") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100184
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100185 {COMPONENT("ne:ctrl") "/parent", "ne"},
186 {COMPONENT("ne:ctrl") "/class", "iana-hardware:module"},
187 {COMPONENT("ne:ctrl") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100188
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100189 {COMPONENT("ne:ctrl:temperature-cpu") "/class", "iana-hardware:sensor"},
190 {COMPONENT("ne:ctrl:temperature-cpu") "/parent", "ne:ctrl"},
191 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/oper-status", "ok"},
192 THRESHOLD_STATE("ne:ctrl:temperature-cpu", "41800"),
193 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-precision", "0"},
194 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-scale", "milli"},
195 {COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value-type", "celsius"},
196 {COMPONENT("ne:ctrl:temperature-cpu") "/state/oper-state", "enabled"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100197
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100198 {COMPONENT("ne:ctrl:power") "/class", "iana-hardware:sensor"},
199 {COMPONENT("ne:ctrl:power") "/parent", "ne:ctrl"},
200 {COMPONENT("ne:ctrl:power") "/sensor-data/oper-status", "ok"},
201 THRESHOLD_STATE("ne:ctrl:power", "14000000"),
202 {COMPONENT("ne:ctrl:power") "/sensor-data/value-precision", "0"},
203 {COMPONENT("ne:ctrl:power") "/sensor-data/value-scale", "micro"},
204 {COMPONENT("ne:ctrl:power") "/sensor-data/value-type", "watts"},
205 {COMPONENT("ne:ctrl:power") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100206
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100207 {COMPONENT("ne:ctrl:voltage-in") "/class", "iana-hardware:sensor"},
208 {COMPONENT("ne:ctrl:voltage-in") "/parent", "ne:ctrl"},
209 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/oper-status", "ok"},
210 THRESHOLD_STATE("ne:ctrl:voltage-in", "220000"),
211 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-precision", "0"},
212 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-scale", "milli"},
213 {COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value-type", "volts-AC"},
214 {COMPONENT("ne:ctrl:voltage-in") "/state/oper-state", "enabled"},
215 {COMPONENT("ne:ctrl:voltage-out") "/class", "iana-hardware:sensor"},
216 {COMPONENT("ne:ctrl:voltage-out") "/parent", "ne:ctrl"},
217 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/oper-status", "ok"},
218 THRESHOLD_STATE("ne:ctrl:voltage-out", "12000"),
219 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-precision", "0"},
220 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-scale", "milli"},
221 {COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value-type", "volts-DC"},
222 {COMPONENT("ne:ctrl:voltage-out") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100223
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100224 {COMPONENT("ne:ctrl:current") "/class", "iana-hardware:sensor"},
225 {COMPONENT("ne:ctrl:current") "/parent", "ne:ctrl"},
226 {COMPONENT("ne:ctrl:current") "/sensor-data/oper-status", "ok"},
227 THRESHOLD_STATE("ne:ctrl:current", "200"),
228 {COMPONENT("ne:ctrl:current") "/sensor-data/value-precision", "0"},
229 {COMPONENT("ne:ctrl:current") "/sensor-data/value-scale", "milli"},
230 {COMPONENT("ne:ctrl:current") "/sensor-data/value-type", "amperes"},
231 {COMPONENT("ne:ctrl:current") "/state/oper-state", "enabled"},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100232
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100233 {COMPONENT("ne:ctrl:emmc") "/parent", "ne:ctrl"},
234 {COMPONENT("ne:ctrl:emmc") "/class", "iana-hardware:module"},
235 {COMPONENT("ne:ctrl:emmc") "/serial-num", "0x00a8808d"},
236 {COMPONENT("ne:ctrl:emmc") "/mfg-date", "2017-02-01T00:00:00-00:00"},
237 {COMPONENT("ne:ctrl:emmc") "/model-name", "8GME4R"},
238 {COMPONENT("ne:ctrl:emmc") "/state/oper-state", "enabled"},
239 {COMPONENT("ne:ctrl:emmc:lifetime") "/class", "iana-hardware:sensor"},
240 {COMPONENT("ne:ctrl:emmc:lifetime") "/parent", "ne:ctrl:emmc"},
241 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/oper-status", "ok"},
242 THRESHOLD_STATE("ne:ctrl:emmc:lifetime", "40"),
243 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-precision", "0"},
244 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-scale", "units"},
245 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value-type", "other"},
246 {COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/units-display", "percent"},
247 {COMPONENT("ne:ctrl:emmc:lifetime") "/state/oper-state", "enabled"},
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200248
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100249 {COMPONENT("ne:psu") "/class", "iana-hardware:power-supply"},
250 {COMPONENT("ne:psu") "/parent", "ne"},
251 {COMPONENT("ne:psu") "/state/oper-state", "enabled"},
252 {COMPONENT("ne:psu:child") "/class", "iana-hardware:sensor"},
253 {COMPONENT("ne:psu:child") "/parent", "ne:psu"},
254 {COMPONENT("ne:psu:child") "/state/oper-state", "enabled"},
255 {COMPONENT("ne:psu:child") "/sensor-data/oper-status", "ok"},
256 THRESHOLD_STATE("ne:psu:child", "20000"),
257 {COMPONENT("ne:psu:child") "/sensor-data/value-precision", "0"},
258 {COMPONENT("ne:psu:child") "/sensor-data/value-scale", "milli"},
259 {COMPONENT("ne:psu:child") "/sensor-data/value-type", "volts-DC"},
Tomáš Pecka3f811962023-04-14 10:54:32 +0200260 };
Tomáš Pecka339bc672020-11-11 15:59:03 +0100261
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200262 {
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100263 auto [data, alarms, activeSensors] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200264 NUKE_LAST_CHANGE(data);
265 REQUIRE(data == expected);
266 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
267 THRESHOLD_STATE("ne:ctrl:current", State::Disabled),
268 THRESHOLD_STATE("ne:ctrl:power", State::Disabled),
269 THRESHOLD_STATE("ne:ctrl:temperature-cpu", State::Disabled),
270 THRESHOLD_STATE("ne:ctrl:voltage-in", State::Disabled),
271 THRESHOLD_STATE("ne:ctrl:voltage-out", State::Disabled),
272 THRESHOLD_STATE("ne:ctrl:emmc:lifetime", State::WarningLow),
273 THRESHOLD_STATE("ne:fans:fan1:rpm", State::Normal),
274 THRESHOLD_STATE("ne:fans:fan2:rpm", State::CriticalLow),
275 THRESHOLD_STATE("ne:fans:fan3:rpm", State::Normal),
276 THRESHOLD_STATE("ne:fans:fan4:rpm", State::Normal),
277 THRESHOLD_STATE("ne:psu:child", State::WarningHigh),
278 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100279 REQUIRE(activeSensors == std::set<std::string>{
280 COMPONENT("ne:ctrl:current") "/sensor-data/value",
281 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
282 COMPONENT("ne:ctrl:power") "/sensor-data/value",
283 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
284 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
285 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
286 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
287 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
288 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
289 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
290 COMPONENT("ne:psu:child") "/sensor-data/value",
291 });
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200292 }
293
294 fanValues[1] = 500;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100295 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "500";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200296 {
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100297 auto [data, alarms, activeSensors] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200298 NUKE_LAST_CHANGE(data);
299 REQUIRE(data == expected);
300 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
301 THRESHOLD_STATE("ne:fans:fan2:rpm", State::WarningLow),
302 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100303 REQUIRE(activeSensors == std::set<std::string>{
304 COMPONENT("ne:ctrl:current") "/sensor-data/value",
305 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
306 COMPONENT("ne:ctrl:power") "/sensor-data/value",
307 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
308 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
309 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
310 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
311 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
312 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
313 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
314 COMPONENT("ne:psu:child") "/sensor-data/value",
315 });
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200316 }
317
318 psuActive = false;
319 fanValues[1] = 1;
320 fanValues[2] = 5000;
321
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100322 expected.erase(COMPONENT("ne:psu:child") "/class");
323 expected.erase(COMPONENT("ne:psu:child") "/parent");
324 expected.erase(COMPONENT("ne:psu:child") "/state/oper-state");
325 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/oper-status");
326 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value");
327 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-precision");
328 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-scale");
329 expected.erase(COMPONENT("ne:psu:child") "/sensor-data/value-type");
330 expected[COMPONENT("ne:psu") "/state/oper-state"] = "disabled";
331 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "1";
332 expected[COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value"] = "5000";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200333
334 {
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100335 auto [data, alarms, activeSensors] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200336 NUKE_LAST_CHANGE(data);
337
338 REQUIRE(data == expected);
339 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
340 THRESHOLD_STATE("ne:fans:fan2:rpm", State::CriticalLow),
341 THRESHOLD_STATE("ne:psu:child", State::NoValue),
342 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100343 REQUIRE(activeSensors == std::set<std::string>{
344 COMPONENT("ne:ctrl:current") "/sensor-data/value",
345 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
346 COMPONENT("ne:ctrl:power") "/sensor-data/value",
347 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
348 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
349 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
350 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
351 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
352 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
353 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
354 });
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200355 }
356
357 psuActive = true;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100358 expected[COMPONENT("ne:psu") "/class"] = "iana-hardware:power-supply";
359 expected[COMPONENT("ne:psu") "/parent"] = "ne";
360 expected[COMPONENT("ne:psu") "/state/oper-state"] = "enabled";
361 expected[COMPONENT("ne:psu:child") "/class"] = "iana-hardware:sensor";
362 expected[COMPONENT("ne:psu:child") "/parent"] = "ne:psu";
363 expected[COMPONENT("ne:psu:child") "/state/oper-state"] = "enabled";
364 expected[COMPONENT("ne:psu:child") "/sensor-data/oper-status"] = "ok";
365 expected[COMPONENT("ne:psu:child") "/sensor-data/value"] = "20000";
366 expected[COMPONENT("ne:psu:child") "/sensor-data/value-precision"] = "0";
367 expected[COMPONENT("ne:psu:child") "/sensor-data/value-scale"] = "milli";
368 expected[COMPONENT("ne:psu:child") "/sensor-data/value-type"] = "volts-DC";
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200369
370 {
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100371 auto [data, alarms, activeSensors] = ietfHardware->process();
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200372 NUKE_LAST_CHANGE(data);
373
374 REQUIRE(data == expected);
375 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
376 THRESHOLD_STATE("ne:psu:child", State::WarningHigh),
377 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100378 REQUIRE(activeSensors == std::set<std::string>{
379 COMPONENT("ne:ctrl:current") "/sensor-data/value",
380 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
381 COMPONENT("ne:ctrl:power") "/sensor-data/value",
382 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
383 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
384 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
385 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
386 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
387 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
388 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
389 COMPONENT("ne:psu:child") "/sensor-data/value",
390 });
Tomáš Pecka0d8d8ee2023-05-10 12:22:58 +0200391 }
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100392
393
394 fanValues[0] = -1'000'000'001;
395 fanValues[1] = 1'000'000'001;
Jan Kundrátbf39bcb2024-01-10 17:46:59 +0100396 expected[COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value"] = "-1000000000";
397 expected[COMPONENT("ne:fans:fan1:rpm") "/sensor-data/oper-status"] = "nonoperational";
398 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value"] = "1000000000";
399 expected[COMPONENT("ne:fans:fan2:rpm") "/sensor-data/oper-status"] = "nonoperational";
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100400
401 {
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100402 auto [data, alarms, activeSensors] = ietfHardware->process();
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100403 NUKE_LAST_CHANGE(data);
404
405 REQUIRE(data == expected);
406 REQUIRE(alarms == std::map<std::string, velia::ietf_hardware::State>{
407 THRESHOLD_STATE("ne:fans:fan1:rpm", State::CriticalLow),
408 THRESHOLD_STATE("ne:fans:fan2:rpm", State::Normal),
409 });
Tomáš Peckac0991ce2023-12-20 15:46:03 +0100410 REQUIRE(activeSensors == std::set<std::string>{
411 COMPONENT("ne:ctrl:current") "/sensor-data/value",
412 COMPONENT("ne:ctrl:emmc:lifetime") "/sensor-data/value",
413 COMPONENT("ne:ctrl:power") "/sensor-data/value",
414 COMPONENT("ne:ctrl:temperature-cpu") "/sensor-data/value",
415 COMPONENT("ne:ctrl:voltage-in") "/sensor-data/value",
416 COMPONENT("ne:ctrl:voltage-out") "/sensor-data/value",
417 COMPONENT("ne:fans:fan1:rpm") "/sensor-data/value",
418 COMPONENT("ne:fans:fan2:rpm") "/sensor-data/value",
419 COMPONENT("ne:fans:fan3:rpm") "/sensor-data/value",
420 COMPONENT("ne:fans:fan4:rpm") "/sensor-data/value",
421 COMPONENT("ne:psu:child") "/sensor-data/value",
422 });
Tomáš Peckacd7f9cc2023-12-11 15:52:48 +0100423 }
Tomáš Pecka339bc672020-11-11 15:59:03 +0100424}