blob: db75eea6d83a17d1dffcf99b091a27f2dca24799 [file] [log] [blame]
Václav Kubernát97e5ea12021-03-24 00:36:57 +01001#include <iostream>
Tomáš Pecka339bc672020-11-11 15:59:03 +01002#include "trompeloeil_doctest.h"
Václav Kubernát97e5ea12021-03-24 00:36:57 +01003#include <fstream>
4#include <future>
Tomáš Pecka339bc672020-11-11 15:59:03 +01005#include <iterator>
Václav Kubernát97e5ea12021-03-24 00:36:57 +01006#include "fs-helpers/utils.h"
7#include "ietf-hardware/FspYhPsu.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +01008#include "ietf-hardware/IETFHardware.h"
Tomáš Pecka98ad18d2020-11-13 15:39:55 +01009#include "ietf-hardware/sysrepo/Sysrepo.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +010010#include "mock/ietf_hardware.h"
11#include "pretty_printers.h"
12#include "test_log_setup.h"
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010013#include "test_sysrepo_helpers.h"
Tomáš Pecka339bc672020-11-11 15:59:03 +010014#include "tests/configure.cmake.h"
15
16using namespace std::literals;
17
18TEST_CASE("HardwareState")
19{
20 TEST_INIT_LOGS;
Tomáš Pecka83b62e12020-12-16 14:50:49 +010021 static const auto modulePrefix = "/ietf-hardware:hardware"s;
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>();
28 auto sysfsTempFront = std::make_shared<FakeHWMon>();
29 auto sysfsTempMII0 = std::make_shared<FakeHWMon>();
30 auto sysfsTempMII1 = std::make_shared<FakeHWMon>();
Václav Kubernát97e5ea12021-03-24 00:36:57 +010031 auto sysfsVoltageAc = std::make_shared<FakeHWMon>();
32 auto sysfsVoltageDc = std::make_shared<FakeHWMon>();
33 auto sysfsPower = std::make_shared<FakeHWMon>();
34 auto sysfsCurrent = std::make_shared<FakeHWMon>();
Tomáš Pecka339bc672020-11-11 15:59:03 +010035 auto emmc = std::make_shared<FakeEMMC>();
36
37 std::map<std::string, std::string> attributesEMMC;
38 std::map<std::string, int64_t> attributesHWMon;
39
40 // initialize all mocks
41 attributesEMMC = {
42 // FIXME passing initializer_list to macro is hell
43 {"date"s, "02/2017"s},
44 {"serial"s, "0x00a8808d"s},
45 {"name"s, "8GME4R"s},
46 };
47 FAKE_EMMC(emmc, attributesEMMC);
48
Václav Kubernátb0939dd2021-04-28 04:08:48 +020049 REQUIRE_CALL(*fans, attribute("fan1_input"s)).RETURN( 253);
50 REQUIRE_CALL(*fans, attribute("fan2_input"s)).RETURN( 0);
51 REQUIRE_CALL(*fans, attribute("fan3_input"s)).RETURN( 1280);
52 REQUIRE_CALL(*fans, attribute("fan4_input"s)).RETURN( 666);
Tomáš Pecka339bc672020-11-11 15:59:03 +010053
Václav Kubernát0dee6b92021-04-13 09:14:04 +020054 REQUIRE_CALL(*sysfsTempFront, attribute("temp1_input")).RETURN(30800);
55 REQUIRE_CALL(*sysfsTempCpu, attribute("temp1_input")).RETURN(41800);
56 REQUIRE_CALL(*sysfsTempMII0, attribute("temp1_input")).RETURN(39000);
57 REQUIRE_CALL(*sysfsTempMII1, attribute("temp1_input")).RETURN(36000);
Tomáš Pecka339bc672020-11-11 15:59:03 +010058
Václav Kubernát97e5ea12021-03-24 00:36:57 +010059 REQUIRE_CALL(*sysfsVoltageAc, attribute("in1_input")).RETURN(220000);
60 REQUIRE_CALL(*sysfsVoltageDc, attribute("in1_input")).RETURN(12000);
61 REQUIRE_CALL(*sysfsPower, attribute("power1_input")).RETURN(14000000);
62 REQUIRE_CALL(*sysfsCurrent, attribute("curr1_input")).RETURN(200);
63
Tomáš Pecka339bc672020-11-11 15:59:03 +010064 attributesEMMC = {{"life_time"s, "40"s}};
65 FAKE_EMMC(emmc, attributesEMMC);
66
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020067 using velia::ietf_hardware::data_reader::SensorType;
68 using velia::ietf_hardware::data_reader::StaticData;
69 using velia::ietf_hardware::data_reader::Fans;
70 using velia::ietf_hardware::data_reader::SysfsValue;
71 using velia::ietf_hardware::data_reader::EMMC;
Tomáš Pecka339bc672020-11-11 15:59:03 +010072 // register components into hw state
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020073 ietfHardware->registerDataReader(StaticData("ne", std::nullopt, {{"class", "iana-hardware:chassis"}, {"mfg-name", "CESNET"s}}));
74 ietfHardware->registerDataReader(StaticData("ne:ctrl", "ne", {{"class", "iana-hardware:module"}}));
75 ietfHardware->registerDataReader(Fans("ne:fans", "ne", fans, 4));
76 ietfHardware->registerDataReader(SysfsValue<SensorType::Temperature>("ne:ctrl:temperature-front", "ne:ctrl", sysfsTempFront, 1));
77 ietfHardware->registerDataReader(SysfsValue<SensorType::Temperature>("ne:ctrl:temperature-cpu", "ne:ctrl", sysfsTempCpu, 1));
78 ietfHardware->registerDataReader(SysfsValue<SensorType::Temperature>("ne:ctrl:temperature-internal-0", "ne:ctrl", sysfsTempMII0, 1));
79 ietfHardware->registerDataReader(SysfsValue<SensorType::Temperature>("ne:ctrl:temperature-internal-1", "ne:ctrl", sysfsTempMII1, 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));
Václav Kubernát6c17d0a2021-03-29 04:55:31 +020084 ietfHardware->registerDataReader(EMMC("ne:ctrl:emmc", "ne:ctrl", emmc));
Tomáš Pecka339bc672020-11-11 15:59:03 +010085
86 SECTION("Test HardwareState without sysrepo")
87 {
88 std::map<std::string, std::string> expected = {
Tomáš Pecka83b62e12020-12-16 14:50:49 +010089 {"/ietf-hardware:hardware/component[name='ne']/class", "iana-hardware:chassis"},
90 {"/ietf-hardware:hardware/component[name='ne']/mfg-name", "CESNET"},
Tomáš Pecka339bc672020-11-11 15:59:03 +010091
Tomáš Pecka83b62e12020-12-16 14:50:49 +010092 {"/ietf-hardware:hardware/component[name='ne:fans']/class", "iana-hardware:module"},
93 {"/ietf-hardware:hardware/component[name='ne:fans']/parent", "ne"},
94 {"/ietf-hardware:hardware/component[name='ne:fans:fan1']/class", "iana-hardware:fan"},
95 {"/ietf-hardware:hardware/component[name='ne:fans:fan1']/parent", "ne:fans"},
96 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/class", "iana-hardware:sensor"},
97 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/parent", "ne:fans:fan1"},
98 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/sensor-data/oper-status", "ok"},
99 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/sensor-data/value", "253"},
100 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/sensor-data/value-precision", "0"},
101 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/sensor-data/value-scale", "units"},
102 {"/ietf-hardware:hardware/component[name='ne:fans:fan1:rpm']/sensor-data/value-type", "rpm"},
103 {"/ietf-hardware:hardware/component[name='ne:fans:fan2']/class", "iana-hardware:fan"},
104 {"/ietf-hardware:hardware/component[name='ne:fans:fan2']/parent", "ne:fans"},
105 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/class", "iana-hardware:sensor"},
106 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/parent", "ne:fans:fan2"},
107 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/sensor-data/oper-status", "ok"},
108 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/sensor-data/value", "0"},
109 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/sensor-data/value-precision", "0"},
110 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/sensor-data/value-scale", "units"},
111 {"/ietf-hardware:hardware/component[name='ne:fans:fan2:rpm']/sensor-data/value-type", "rpm"},
112 {"/ietf-hardware:hardware/component[name='ne:fans:fan3']/class", "iana-hardware:fan"},
113 {"/ietf-hardware:hardware/component[name='ne:fans:fan3']/parent", "ne:fans"},
114 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/class", "iana-hardware:sensor"},
115 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/parent", "ne:fans:fan3"},
116 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/sensor-data/oper-status", "ok"},
117 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/sensor-data/value", "1280"},
118 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/sensor-data/value-precision", "0"},
119 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/sensor-data/value-scale", "units"},
120 {"/ietf-hardware:hardware/component[name='ne:fans:fan3:rpm']/sensor-data/value-type", "rpm"},
121 {"/ietf-hardware:hardware/component[name='ne:fans:fan4']/class", "iana-hardware:fan"},
122 {"/ietf-hardware:hardware/component[name='ne:fans:fan4']/parent", "ne:fans"},
123 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/class", "iana-hardware:sensor"},
124 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/parent", "ne:fans:fan4"},
125 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/sensor-data/oper-status", "ok"},
126 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/sensor-data/value", "666"},
127 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/sensor-data/value-precision", "0"},
128 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/sensor-data/value-scale", "units"},
129 {"/ietf-hardware:hardware/component[name='ne:fans:fan4:rpm']/sensor-data/value-type", "rpm"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100130
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100131 {"/ietf-hardware:hardware/component[name='ne:ctrl']/parent", "ne"},
132 {"/ietf-hardware:hardware/component[name='ne:ctrl']/class", "iana-hardware:module"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100133
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100134 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/class", "iana-hardware:sensor"},
135 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/parent", "ne:ctrl"},
136 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/sensor-data/oper-status", "ok"},
137 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/sensor-data/value", "41800"},
138 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/sensor-data/value-precision", "0"},
139 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/sensor-data/value-scale", "milli"},
140 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-cpu']/sensor-data/value-type", "celsius"},
141 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/class", "iana-hardware:sensor"},
142 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/parent", "ne:ctrl"},
143 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/sensor-data/oper-status", "ok"},
144 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/sensor-data/value", "30800"},
145 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/sensor-data/value-precision", "0"},
146 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/sensor-data/value-scale", "milli"},
147 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-front']/sensor-data/value-type", "celsius"},
148 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/class", "iana-hardware:sensor"},
149 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/parent", "ne:ctrl"},
150 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/sensor-data/oper-status", "ok"},
151 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/sensor-data/value", "39000"},
152 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/sensor-data/value-precision", "0"},
153 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/sensor-data/value-scale", "milli"},
154 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-0']/sensor-data/value-type", "celsius"},
155 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/class", "iana-hardware:sensor"},
156 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/parent", "ne:ctrl"},
157 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/sensor-data/oper-status", "ok"},
158 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/sensor-data/value", "36000"},
159 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/sensor-data/value-precision", "0"},
160 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/sensor-data/value-scale", "milli"},
161 {"/ietf-hardware:hardware/component[name='ne:ctrl:temperature-internal-1']/sensor-data/value-type", "celsius"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100162
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100163 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/class", "iana-hardware:sensor"},
164 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/parent", "ne:ctrl"},
165 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/sensor-data/oper-status", "ok"},
166 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/sensor-data/value", "14000000"},
167 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/sensor-data/value-precision", "0"},
168 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/sensor-data/value-scale", "micro"},
169 {"/ietf-hardware:hardware/component[name='ne:ctrl:power']/sensor-data/value-type", "watts"},
170
171 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/class", "iana-hardware:sensor"},
172 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/parent", "ne:ctrl"},
173 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/sensor-data/oper-status", "ok"},
174 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/sensor-data/value", "220000"},
175 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/sensor-data/value-precision", "0"},
176 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/sensor-data/value-scale", "micro"},
177 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-in']/sensor-data/value-type", "volts-AC"},
178 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/class", "iana-hardware:sensor"},
179 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/parent", "ne:ctrl"},
180 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/sensor-data/oper-status", "ok"},
181 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/sensor-data/value", "12000"},
182 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/sensor-data/value-precision", "0"},
183 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/sensor-data/value-scale", "micro"},
184 {"/ietf-hardware:hardware/component[name='ne:ctrl:voltage-out']/sensor-data/value-type", "volts-DC"},
185
186 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/class", "iana-hardware:sensor"},
187 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/parent", "ne:ctrl"},
188 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/sensor-data/oper-status", "ok"},
189 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/sensor-data/value", "200"},
190 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/sensor-data/value-precision", "0"},
191 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/sensor-data/value-scale", "milli"},
192 {"/ietf-hardware:hardware/component[name='ne:ctrl:current']/sensor-data/value-type", "amperes"},
193
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100194 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/parent", "ne:ctrl"},
195 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/class", "iana-hardware:module"},
196 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/serial-num", "0x00a8808d"},
197 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/mfg-date", "2017-02-01T00:00:00Z"},
198 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/model-name", "8GME4R"},
199 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/class", "iana-hardware:sensor"},
200 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/parent", "ne:ctrl:emmc"},
201 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/oper-status", "ok"},
202 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/value", "40"},
203 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/value-precision", "0"},
204 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/value-scale", "units"},
205 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/value-type", "other"},
206 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc:lifetime']/sensor-data/units-display", "percent"},
Tomáš Pecka339bc672020-11-11 15:59:03 +0100207 };
208
209 // exclude last-change node
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100210 auto result = ietfHardware->process();
Tomáš Pecka339bc672020-11-11 15:59:03 +0100211 result.erase(modulePrefix + "/last-change");
212 REQUIRE(result == expected);
213 }
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100214
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100215 SECTION("Test IETF Hardware from sysrepo's view")
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100216 {
217 TEST_SYSREPO_INIT_LOGS;
Tomáš Pecka749af2e2021-01-14 09:52:09 +0100218 TEST_SYSREPO_INIT;
219 TEST_SYSREPO_INIT_CLIENT;
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100220
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100221 auto ietfHardwareSysrepo = std::make_shared<velia::ietf_hardware::sysrepo::Sysrepo>(srSubs, ietfHardware);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100222
223 SECTION("test last-change")
224 {
225 // at least check that there is some timestamp
Tomáš Pecka749af2e2021-01-14 09:52:09 +0100226 REQUIRE(dataFromSysrepo(client, modulePrefix, SR_DS_OPERATIONAL).count("/last-change") > 0);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100227 }
228
229 SECTION("test components")
230 {
231 std::map<std::string, std::string> expected = {
232 {"[name='ne']/name", "ne"},
233 {"[name='ne']/class", "iana-hardware:chassis"},
234 {"[name='ne']/mfg-name", "CESNET"},
235 {"[name='ne']/sensor-data", ""},
236
237 {"[name='ne:fans']/class", "iana-hardware:module"},
238 {"[name='ne:fans']/name", "ne:fans"},
239 {"[name='ne:fans']/parent", "ne"},
240 {"[name='ne:fans']/sensor-data", ""},
241 {"[name='ne:fans:fan1']/class", "iana-hardware:fan"},
242 {"[name='ne:fans:fan1']/name", "ne:fans:fan1"},
243 {"[name='ne:fans:fan1']/parent", "ne:fans"},
244 {"[name='ne:fans:fan1']/sensor-data", ""},
245 {"[name='ne:fans:fan1:rpm']/class", "iana-hardware:sensor"},
246 {"[name='ne:fans:fan1:rpm']/name", "ne:fans:fan1:rpm"},
247 {"[name='ne:fans:fan1:rpm']/parent", "ne:fans:fan1"},
248 {"[name='ne:fans:fan1:rpm']/sensor-data", ""},
249 {"[name='ne:fans:fan1:rpm']/sensor-data/oper-status", "ok"},
250 {"[name='ne:fans:fan1:rpm']/sensor-data/value", "253"},
251 {"[name='ne:fans:fan1:rpm']/sensor-data/value-precision", "0"},
252 {"[name='ne:fans:fan1:rpm']/sensor-data/value-scale", "units"},
253 {"[name='ne:fans:fan1:rpm']/sensor-data/value-type", "rpm"},
254 {"[name='ne:fans:fan2']/class", "iana-hardware:fan"},
255 {"[name='ne:fans:fan2']/name", "ne:fans:fan2"},
256 {"[name='ne:fans:fan2']/parent", "ne:fans"},
257 {"[name='ne:fans:fan2']/sensor-data", ""},
258 {"[name='ne:fans:fan2:rpm']/class", "iana-hardware:sensor"},
259 {"[name='ne:fans:fan2:rpm']/name", "ne:fans:fan2:rpm"},
260 {"[name='ne:fans:fan2:rpm']/parent", "ne:fans:fan2"},
261 {"[name='ne:fans:fan2:rpm']/sensor-data", ""},
262 {"[name='ne:fans:fan2:rpm']/sensor-data/oper-status", "ok"},
263 {"[name='ne:fans:fan2:rpm']/sensor-data/value", "0"},
264 {"[name='ne:fans:fan2:rpm']/sensor-data/value-precision", "0"},
265 {"[name='ne:fans:fan2:rpm']/sensor-data/value-scale", "units"},
266 {"[name='ne:fans:fan2:rpm']/sensor-data/value-type", "rpm"},
267 {"[name='ne:fans:fan3']/class", "iana-hardware:fan"},
268 {"[name='ne:fans:fan3']/name", "ne:fans:fan3"},
269 {"[name='ne:fans:fan3']/parent", "ne:fans"},
270 {"[name='ne:fans:fan3']/sensor-data", ""},
271 {"[name='ne:fans:fan3:rpm']/class", "iana-hardware:sensor"},
272 {"[name='ne:fans:fan3:rpm']/name", "ne:fans:fan3:rpm"},
273 {"[name='ne:fans:fan3:rpm']/parent", "ne:fans:fan3"},
274 {"[name='ne:fans:fan3:rpm']/sensor-data", ""},
275 {"[name='ne:fans:fan3:rpm']/sensor-data/oper-status", "ok"},
276 {"[name='ne:fans:fan3:rpm']/sensor-data/value", "1280"},
277 {"[name='ne:fans:fan3:rpm']/sensor-data/value-precision", "0"},
278 {"[name='ne:fans:fan3:rpm']/sensor-data/value-scale", "units"},
279 {"[name='ne:fans:fan3:rpm']/sensor-data/value-type", "rpm"},
280 {"[name='ne:fans:fan4']/class", "iana-hardware:fan"},
281 {"[name='ne:fans:fan4']/name", "ne:fans:fan4"},
282 {"[name='ne:fans:fan4']/parent", "ne:fans"},
283 {"[name='ne:fans:fan4']/sensor-data", ""},
284 {"[name='ne:fans:fan4:rpm']/class", "iana-hardware:sensor"},
285 {"[name='ne:fans:fan4:rpm']/name", "ne:fans:fan4:rpm"},
286 {"[name='ne:fans:fan4:rpm']/parent", "ne:fans:fan4"},
287 {"[name='ne:fans:fan4:rpm']/sensor-data", ""},
288 {"[name='ne:fans:fan4:rpm']/sensor-data/oper-status", "ok"},
289 {"[name='ne:fans:fan4:rpm']/sensor-data/value", "666"},
290 {"[name='ne:fans:fan4:rpm']/sensor-data/value-precision", "0"},
291 {"[name='ne:fans:fan4:rpm']/sensor-data/value-scale", "units"},
292 {"[name='ne:fans:fan4:rpm']/sensor-data/value-type", "rpm"},
293
294 {"[name='ne:ctrl']/name", "ne:ctrl"},
295 {"[name='ne:ctrl']/parent", "ne"},
296 {"[name='ne:ctrl']/class", "iana-hardware:module"},
297 {"[name='ne:ctrl']/sensor-data", ""},
298
299 {"[name='ne:ctrl:temperature-cpu']/name", "ne:ctrl:temperature-cpu"},
300 {"[name='ne:ctrl:temperature-cpu']/class", "iana-hardware:sensor"},
301 {"[name='ne:ctrl:temperature-cpu']/parent", "ne:ctrl"},
302 {"[name='ne:ctrl:temperature-cpu']/sensor-data", ""},
303 {"[name='ne:ctrl:temperature-cpu']/sensor-data/oper-status", "ok"},
304 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value", "41800"},
305 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-precision", "0"},
306 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-scale", "milli"},
307 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-type", "celsius"},
308 {"[name='ne:ctrl:temperature-front']/name", "ne:ctrl:temperature-front"},
309 {"[name='ne:ctrl:temperature-front']/class", "iana-hardware:sensor"},
310 {"[name='ne:ctrl:temperature-front']/parent", "ne:ctrl"},
311 {"[name='ne:ctrl:temperature-front']/sensor-data", ""},
312 {"[name='ne:ctrl:temperature-front']/sensor-data/oper-status", "ok"},
313 {"[name='ne:ctrl:temperature-front']/sensor-data/value", "30800"},
314 {"[name='ne:ctrl:temperature-front']/sensor-data/value-precision", "0"},
315 {"[name='ne:ctrl:temperature-front']/sensor-data/value-scale", "milli"},
316 {"[name='ne:ctrl:temperature-front']/sensor-data/value-type", "celsius"},
317 {"[name='ne:ctrl:temperature-internal-0']/name", "ne:ctrl:temperature-internal-0"},
318 {"[name='ne:ctrl:temperature-internal-0']/class", "iana-hardware:sensor"},
319 {"[name='ne:ctrl:temperature-internal-0']/parent", "ne:ctrl"},
320 {"[name='ne:ctrl:temperature-internal-0']/sensor-data", ""},
321 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/oper-status", "ok"},
322 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value", "39000"},
323 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-precision", "0"},
324 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-scale", "milli"},
325 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-type", "celsius"},
326 {"[name='ne:ctrl:temperature-internal-1']/name", "ne:ctrl:temperature-internal-1"},
327 {"[name='ne:ctrl:temperature-internal-1']/class", "iana-hardware:sensor"},
328 {"[name='ne:ctrl:temperature-internal-1']/parent", "ne:ctrl"},
329 {"[name='ne:ctrl:temperature-internal-1']/sensor-data", ""},
330 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/oper-status", "ok"},
331 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value", "36000"},
332 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-precision", "0"},
333 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-scale", "milli"},
334 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-type", "celsius"},
335
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100336 {"[name='ne:ctrl:power']/name", "ne:ctrl:power"},
337 {"[name='ne:ctrl:power']/class", "iana-hardware:sensor"},
338 {"[name='ne:ctrl:power']/parent", "ne:ctrl"},
339 {"[name='ne:ctrl:power']/sensor-data", ""},
340 {"[name='ne:ctrl:power']/sensor-data/oper-status", "ok"},
341 {"[name='ne:ctrl:power']/sensor-data/value", "14000000"},
342 {"[name='ne:ctrl:power']/sensor-data/value-precision", "0"},
343 {"[name='ne:ctrl:power']/sensor-data/value-scale", "micro"},
344 {"[name='ne:ctrl:power']/sensor-data/value-type", "watts"},
345
346 {"[name='ne:ctrl:voltage-in']/name", "ne:ctrl:voltage-in"},
347 {"[name='ne:ctrl:voltage-in']/class", "iana-hardware:sensor"},
348 {"[name='ne:ctrl:voltage-in']/parent", "ne:ctrl"},
349 {"[name='ne:ctrl:voltage-in']/sensor-data", ""},
350 {"[name='ne:ctrl:voltage-in']/sensor-data/oper-status", "ok"},
351 {"[name='ne:ctrl:voltage-in']/sensor-data/value", "220000"},
352 {"[name='ne:ctrl:voltage-in']/sensor-data/value-precision", "0"},
353 {"[name='ne:ctrl:voltage-in']/sensor-data/value-scale", "micro"},
354 {"[name='ne:ctrl:voltage-in']/sensor-data/value-type", "volts-AC"},
355 {"[name='ne:ctrl:voltage-out']/name", "ne:ctrl:voltage-out"},
356 {"[name='ne:ctrl:voltage-out']/class", "iana-hardware:sensor"},
357 {"[name='ne:ctrl:voltage-out']/parent", "ne:ctrl"},
358 {"[name='ne:ctrl:voltage-out']/sensor-data", ""},
359 {"[name='ne:ctrl:voltage-out']/sensor-data/oper-status", "ok"},
360 {"[name='ne:ctrl:voltage-out']/sensor-data/value", "12000"},
361 {"[name='ne:ctrl:voltage-out']/sensor-data/value-precision", "0"},
362 {"[name='ne:ctrl:voltage-out']/sensor-data/value-scale", "micro"},
363 {"[name='ne:ctrl:voltage-out']/sensor-data/value-type", "volts-DC"},
364
365 {"[name='ne:ctrl:current']/name", "ne:ctrl:current"},
366 {"[name='ne:ctrl:current']/class", "iana-hardware:sensor"},
367 {"[name='ne:ctrl:current']/parent", "ne:ctrl"},
368 {"[name='ne:ctrl:current']/sensor-data", ""},
369 {"[name='ne:ctrl:current']/sensor-data/oper-status", "ok"},
370 {"[name='ne:ctrl:current']/sensor-data/value", "200"},
371 {"[name='ne:ctrl:current']/sensor-data/value-precision", "0"},
372 {"[name='ne:ctrl:current']/sensor-data/value-scale", "milli"},
373 {"[name='ne:ctrl:current']/sensor-data/value-type", "amperes"},
374
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100375 {"[name='ne:ctrl:emmc']/name", "ne:ctrl:emmc"},
376 {"[name='ne:ctrl:emmc']/parent", "ne:ctrl"},
377 {"[name='ne:ctrl:emmc']/class", "iana-hardware:module"},
378 {"[name='ne:ctrl:emmc']/serial-num", "0x00a8808d"},
379 {"[name='ne:ctrl:emmc']/mfg-date", "2017-02-01T00:00:00Z"},
380 {"[name='ne:ctrl:emmc']/model-name", "8GME4R"},
381 {"[name='ne:ctrl:emmc']/sensor-data", ""},
382 {"[name='ne:ctrl:emmc:lifetime']/name", "ne:ctrl:emmc:lifetime"},
383 {"[name='ne:ctrl:emmc:lifetime']/class", "iana-hardware:sensor"},
384 {"[name='ne:ctrl:emmc:lifetime']/parent", "ne:ctrl:emmc"},
385 {"[name='ne:ctrl:emmc:lifetime']/sensor-data", ""},
386 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/oper-status", "ok"},
387 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value", "40"},
388 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-precision", "0"},
389 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-scale", "units"},
390 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-type", "other"},
391 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/units-display", "percent"},
392 };
393
Tomáš Pecka749af2e2021-01-14 09:52:09 +0100394 REQUIRE(dataFromSysrepo(client, modulePrefix + "/component", SR_DS_OPERATIONAL) == expected);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100395 }
396
397 SECTION("test leafnode query")
398 {
399 const auto xpath = modulePrefix + "/component[name='ne:ctrl:emmc:lifetime']/class";
Tomáš Pecka749af2e2021-01-14 09:52:09 +0100400 client->session_switch_ds(SR_DS_OPERATIONAL);
401 auto val = client->get_item(xpath.c_str());
402 client->session_switch_ds(SR_DS_RUNNING);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100403 REQUIRE(!!val);
404 REQUIRE(val->data()->get_identityref() == "iana-hardware:sensor"s);
405 }
406 }
Tomáš Pecka339bc672020-11-11 15:59:03 +0100407}
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100408
409class FakeI2C : public velia::ietf_hardware::TransientI2C {
410public:
411 FakeI2C(const std::string& fakeHwmonRoot)
412 : TransientI2C({}, {}, {})
413 , m_fakeHwmonRoot(fakeHwmonRoot)
414 {
415 }
416
417 MAKE_CONST_MOCK0(isPresent, bool(), override);
418 MAKE_CONST_MOCK0(bind_mock, void());
419 MAKE_CONST_MOCK0(unbind_mock, void());
420
421 void removeHwmonFile(const std::string& name) const
422 {
423 std::filesystem::remove(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / name);
424 }
425
426 void bind() const override
427 {
428 bind_mock();
429 removeDirectoryTreeIfExists(m_fakeHwmonRoot);
430 std::filesystem::create_directory(m_fakeHwmonRoot);
431 std::filesystem::create_directory(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)));
432
433 for (const auto& filename : {"name", "temp1_input", "temp2_input", "curr1_input", "curr2_input", "curr3_input",
434 "in1_input", "in2_input", "in3_input", "power1_input", "power2_input", "fan1_input"} )
435 {
436 std::ofstream ofs(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / filename);
437 // I don't really care about the values here, I just need the HWMon class to think that the files exist.
438 ofs << 0 << "\n";
439 }
440 }
441 void unbind() const override
442 {
443 unbind_mock();
444 removeDirectoryTreeIfExists(m_fakeHwmonRoot);
445 m_hwmonNo++;
446 }
447
448private:
449
450 std::filesystem::path m_fakeHwmonRoot;
451 mutable std::atomic<int> m_hwmonNo = 1;
452};
453
454TEST_CASE("FspYhPsu")
455{
456 TEST_INIT_LOGS;
457 std::atomic<int> counter = 0;
458 const auto fakeHwmonRoot = CMAKE_CURRENT_BINARY_DIR + "/tests/psu"s;
459 removeDirectoryTreeIfExists(fakeHwmonRoot);
460 auto fakeI2c = std::make_shared<FakeI2C>(fakeHwmonRoot);
461 trompeloeil::sequence seq1;
462 std::shared_ptr<velia::ietf_hardware::FspYhPsu> psu;
463 std::vector<std::unique_ptr<trompeloeil::expectation>> expectations;
464
465 auto i2cPresence = [&counter] {
466 switch (counter) {
467 case 0:
468 case 2:
469 case 4:
470 return false;
471 case 1:
472 case 3:
473 return true;
474 }
475
476 REQUIRE(false);
477 __builtin_unreachable();
478 };
479
480 ALLOW_CALL(*fakeI2c, isPresent()).LR_RETURN(i2cPresence());
481 REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 1).IN_SEQUENCE(seq1);
482 REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 2).IN_SEQUENCE(seq1);
483 REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 3).IN_SEQUENCE(seq1);
484 REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 4).IN_SEQUENCE(seq1);
485
486 psu = std::make_shared<velia::ietf_hardware::FspYhPsu>(fakeHwmonRoot, "psu", fakeI2c);
487
488 for (auto i : {0, 1, 2, 3, 4}) {
489 std::this_thread::sleep_for(std::chrono::seconds(4));
490 velia::ietf_hardware::DataTree expected;
491
492 switch (i) {
493 case 0:
494 break;
495 case 1:
496 expected = {
497 {"/ietf-hardware:hardware/component[name='ne:psu']/class", "iana-hardware:power-supply"},
498 {"/ietf-hardware:hardware/component[name='ne:psu']/parent", "ne"},
499 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/class", "iana-hardware:sensor"},
500 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/parent", "ne:psu"},
501 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/oper-status", "ok"},
502 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value", "0"},
503 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-precision", "0"},
504 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-scale", "milli"},
505 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-type", "amperes"},
506 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/class", "iana-hardware:sensor"},
507 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/parent", "ne:psu"},
508 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/oper-status", "ok"},
509 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value", "0"},
510 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-precision", "0"},
511 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-scale", "milli"},
512 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-type", "amperes"},
513 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/class", "iana-hardware:sensor"},
514 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/parent", "ne:psu"},
515 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/oper-status", "ok"},
516 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value", "0"},
517 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-precision", "0"},
518 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-scale", "milli"},
519 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-type", "amperes"},
520 {"/ietf-hardware:hardware/component[name='ne:psu:fan']/class", "iana-hardware:module"},
521 {"/ietf-hardware:hardware/component[name='ne:psu:fan']/parent", "ne:psu"},
522 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/class", "iana-hardware:fan"},
523 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/parent", "ne:psu:fan"},
524 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/class", "iana-hardware:sensor"},
525 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/parent", "ne:psu:fan:fan1"},
526 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/oper-status", "ok"},
527 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value", "0"},
528 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-precision", "0"},
529 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-scale", "units"},
530 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-type", "rpm"},
531 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/class", "iana-hardware:sensor"},
532 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/parent", "ne:psu"},
533 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/oper-status", "ok"},
534 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value", "0"},
535 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-precision", "0"},
536 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-scale", "micro"},
537 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-type", "watts"},
538 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/class", "iana-hardware:sensor"},
539 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/parent", "ne:psu"},
540 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/oper-status", "ok"},
541 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value", "0"},
542 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-precision", "0"},
543 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-scale", "micro"},
544 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-type", "watts"},
545 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/class", "iana-hardware:sensor"},
546 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/parent", "ne:psu"},
547 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/oper-status", "ok"},
548 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value", "0"},
549 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-precision", "0"},
550 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-scale", "milli"},
551 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-type", "celsius"},
552 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/class", "iana-hardware:sensor"},
553 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/parent", "ne:psu"},
554 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/oper-status", "ok"},
555 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value", "0"},
556 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-precision", "0"},
557 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-scale", "milli"},
558 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-type", "celsius"},
559 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/class", "iana-hardware:sensor"},
560 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/parent", "ne:psu"},
561 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/oper-status", "ok"},
562 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value", "0"},
563 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-precision", "0"},
564 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-scale", "micro"},
565 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-type", "volts-DC"},
566 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/class", "iana-hardware:sensor"},
567 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/parent", "ne:psu"},
568 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/oper-status", "ok"},
569 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value", "0"},
570 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-precision", "0"},
571 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-scale", "micro"},
572 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-type", "volts-DC"},
573 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/class", "iana-hardware:sensor"},
574 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/parent", "ne:psu"},
575 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/oper-status", "ok"},
576 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value", "0"},
577 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-precision", "0"},
578 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-scale", "micro"},
579 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-type", "volts-AC"},
580 };
581 break;
582 case 2:
583 break;
584 case 3:
585 // Here I simulate read failure by a file from the hwmon directory. This happens when the user wants data from
586 // a PSU that's no longer there and the watcher thread didn't unbind it yet.
587 fakeI2c->removeHwmonFile("temp1_input");
588 break;
589 case 4:
590 break;
591 }
592
593 REQUIRE(psu->readValues() == expected);
594
595 counter++;
596 }
597
598 waitForCompletionAndBitMore(seq1);
599}