blob: f6d4ff401c641705a8dd71c562862de60e8ad25f [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"},
Václav Kubernát693c7952021-11-12 16:07:18 +0100197 {"/ietf-hardware:hardware/component[name='ne:ctrl:emmc']/mfg-date", "2017-02-01T00:00:00-00:00"},
Tomáš Pecka83b62e12020-12-16 14:50:49 +0100198 {"/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
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100221 auto ietfHardwareSysrepo = std::make_shared<velia::ietf_hardware::sysrepo::Sysrepo>(srSess, ietfHardware);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100222
223 SECTION("test last-change")
224 {
225 // at least check that there is some timestamp
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100226 REQUIRE(dataFromSysrepo(client, modulePrefix, sysrepo::Datastore::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 = {
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100232 {"[name='ne']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100233 {"[name='ne']/name", "ne"},
234 {"[name='ne']/class", "iana-hardware:chassis"},
235 {"[name='ne']/mfg-name", "CESNET"},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100236
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100237 {"[name='ne:fans']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100238 {"[name='ne:fans']/class", "iana-hardware:module"},
239 {"[name='ne:fans']/name", "ne:fans"},
240 {"[name='ne:fans']/parent", "ne"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100241 {"[name='ne:fans:fan1']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100242 {"[name='ne:fans:fan1']/class", "iana-hardware:fan"},
243 {"[name='ne:fans:fan1']/name", "ne:fans:fan1"},
244 {"[name='ne:fans:fan1']/parent", "ne:fans"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100245 {"[name='ne:fans:fan1:rpm']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100246 {"[name='ne:fans:fan1:rpm']/class", "iana-hardware:sensor"},
247 {"[name='ne:fans:fan1:rpm']/name", "ne:fans:fan1:rpm"},
248 {"[name='ne:fans:fan1:rpm']/parent", "ne:fans:fan1"},
249 {"[name='ne:fans:fan1:rpm']/sensor-data", ""},
250 {"[name='ne:fans:fan1:rpm']/sensor-data/oper-status", "ok"},
251 {"[name='ne:fans:fan1:rpm']/sensor-data/value", "253"},
252 {"[name='ne:fans:fan1:rpm']/sensor-data/value-precision", "0"},
253 {"[name='ne:fans:fan1:rpm']/sensor-data/value-scale", "units"},
254 {"[name='ne:fans:fan1:rpm']/sensor-data/value-type", "rpm"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100255 {"[name='ne:fans:fan2']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100256 {"[name='ne:fans:fan2']/class", "iana-hardware:fan"},
257 {"[name='ne:fans:fan2']/name", "ne:fans:fan2"},
258 {"[name='ne:fans:fan2']/parent", "ne:fans"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100259 {"[name='ne:fans:fan2:rpm']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100260 {"[name='ne:fans:fan2:rpm']/class", "iana-hardware:sensor"},
261 {"[name='ne:fans:fan2:rpm']/name", "ne:fans:fan2:rpm"},
262 {"[name='ne:fans:fan2:rpm']/parent", "ne:fans:fan2"},
263 {"[name='ne:fans:fan2:rpm']/sensor-data", ""},
264 {"[name='ne:fans:fan2:rpm']/sensor-data/oper-status", "ok"},
265 {"[name='ne:fans:fan2:rpm']/sensor-data/value", "0"},
266 {"[name='ne:fans:fan2:rpm']/sensor-data/value-precision", "0"},
267 {"[name='ne:fans:fan2:rpm']/sensor-data/value-scale", "units"},
268 {"[name='ne:fans:fan2:rpm']/sensor-data/value-type", "rpm"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100269 {"[name='ne:fans:fan3']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100270 {"[name='ne:fans:fan3']/class", "iana-hardware:fan"},
271 {"[name='ne:fans:fan3']/name", "ne:fans:fan3"},
272 {"[name='ne:fans:fan3']/parent", "ne:fans"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100273 {"[name='ne:fans:fan3:rpm']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100274 {"[name='ne:fans:fan3:rpm']/class", "iana-hardware:sensor"},
275 {"[name='ne:fans:fan3:rpm']/name", "ne:fans:fan3:rpm"},
276 {"[name='ne:fans:fan3:rpm']/parent", "ne:fans:fan3"},
277 {"[name='ne:fans:fan3:rpm']/sensor-data", ""},
278 {"[name='ne:fans:fan3:rpm']/sensor-data/oper-status", "ok"},
279 {"[name='ne:fans:fan3:rpm']/sensor-data/value", "1280"},
280 {"[name='ne:fans:fan3:rpm']/sensor-data/value-precision", "0"},
281 {"[name='ne:fans:fan3:rpm']/sensor-data/value-scale", "units"},
282 {"[name='ne:fans:fan3:rpm']/sensor-data/value-type", "rpm"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100283 {"[name='ne:fans:fan4']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100284 {"[name='ne:fans:fan4']/class", "iana-hardware:fan"},
285 {"[name='ne:fans:fan4']/name", "ne:fans:fan4"},
286 {"[name='ne:fans:fan4']/parent", "ne:fans"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100287 {"[name='ne:fans:fan4:rpm']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100288 {"[name='ne:fans:fan4:rpm']/class", "iana-hardware:sensor"},
289 {"[name='ne:fans:fan4:rpm']/name", "ne:fans:fan4:rpm"},
290 {"[name='ne:fans:fan4:rpm']/parent", "ne:fans:fan4"},
291 {"[name='ne:fans:fan4:rpm']/sensor-data", ""},
292 {"[name='ne:fans:fan4:rpm']/sensor-data/oper-status", "ok"},
293 {"[name='ne:fans:fan4:rpm']/sensor-data/value", "666"},
294 {"[name='ne:fans:fan4:rpm']/sensor-data/value-precision", "0"},
295 {"[name='ne:fans:fan4:rpm']/sensor-data/value-scale", "units"},
296 {"[name='ne:fans:fan4:rpm']/sensor-data/value-type", "rpm"},
297
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100298 {"[name='ne:ctrl']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100299 {"[name='ne:ctrl']/name", "ne:ctrl"},
300 {"[name='ne:ctrl']/parent", "ne"},
301 {"[name='ne:ctrl']/class", "iana-hardware:module"},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100302
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100303 {"[name='ne:ctrl:temperature-cpu']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100304 {"[name='ne:ctrl:temperature-cpu']/name", "ne:ctrl:temperature-cpu"},
305 {"[name='ne:ctrl:temperature-cpu']/class", "iana-hardware:sensor"},
306 {"[name='ne:ctrl:temperature-cpu']/parent", "ne:ctrl"},
307 {"[name='ne:ctrl:temperature-cpu']/sensor-data", ""},
308 {"[name='ne:ctrl:temperature-cpu']/sensor-data/oper-status", "ok"},
309 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value", "41800"},
310 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-precision", "0"},
311 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-scale", "milli"},
312 {"[name='ne:ctrl:temperature-cpu']/sensor-data/value-type", "celsius"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100313 {"[name='ne:ctrl:temperature-front']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100314 {"[name='ne:ctrl:temperature-front']/name", "ne:ctrl:temperature-front"},
315 {"[name='ne:ctrl:temperature-front']/class", "iana-hardware:sensor"},
316 {"[name='ne:ctrl:temperature-front']/parent", "ne:ctrl"},
317 {"[name='ne:ctrl:temperature-front']/sensor-data", ""},
318 {"[name='ne:ctrl:temperature-front']/sensor-data/oper-status", "ok"},
319 {"[name='ne:ctrl:temperature-front']/sensor-data/value", "30800"},
320 {"[name='ne:ctrl:temperature-front']/sensor-data/value-precision", "0"},
321 {"[name='ne:ctrl:temperature-front']/sensor-data/value-scale", "milli"},
322 {"[name='ne:ctrl:temperature-front']/sensor-data/value-type", "celsius"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100323 {"[name='ne:ctrl:temperature-internal-0']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100324 {"[name='ne:ctrl:temperature-internal-0']/name", "ne:ctrl:temperature-internal-0"},
325 {"[name='ne:ctrl:temperature-internal-0']/class", "iana-hardware:sensor"},
326 {"[name='ne:ctrl:temperature-internal-0']/parent", "ne:ctrl"},
327 {"[name='ne:ctrl:temperature-internal-0']/sensor-data", ""},
328 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/oper-status", "ok"},
329 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value", "39000"},
330 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-precision", "0"},
331 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-scale", "milli"},
332 {"[name='ne:ctrl:temperature-internal-0']/sensor-data/value-type", "celsius"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100333 {"[name='ne:ctrl:temperature-internal-1']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100334 {"[name='ne:ctrl:temperature-internal-1']/name", "ne:ctrl:temperature-internal-1"},
335 {"[name='ne:ctrl:temperature-internal-1']/class", "iana-hardware:sensor"},
336 {"[name='ne:ctrl:temperature-internal-1']/parent", "ne:ctrl"},
337 {"[name='ne:ctrl:temperature-internal-1']/sensor-data", ""},
338 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/oper-status", "ok"},
339 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value", "36000"},
340 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-precision", "0"},
341 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-scale", "milli"},
342 {"[name='ne:ctrl:temperature-internal-1']/sensor-data/value-type", "celsius"},
343
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100344 {"[name='ne:ctrl:power']", ""},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100345 {"[name='ne:ctrl:power']/name", "ne:ctrl:power"},
346 {"[name='ne:ctrl:power']/class", "iana-hardware:sensor"},
347 {"[name='ne:ctrl:power']/parent", "ne:ctrl"},
348 {"[name='ne:ctrl:power']/sensor-data", ""},
349 {"[name='ne:ctrl:power']/sensor-data/oper-status", "ok"},
350 {"[name='ne:ctrl:power']/sensor-data/value", "14000000"},
351 {"[name='ne:ctrl:power']/sensor-data/value-precision", "0"},
352 {"[name='ne:ctrl:power']/sensor-data/value-scale", "micro"},
353 {"[name='ne:ctrl:power']/sensor-data/value-type", "watts"},
354
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100355 {"[name='ne:ctrl:voltage-in']", ""},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100356 {"[name='ne:ctrl:voltage-in']/name", "ne:ctrl:voltage-in"},
357 {"[name='ne:ctrl:voltage-in']/class", "iana-hardware:sensor"},
358 {"[name='ne:ctrl:voltage-in']/parent", "ne:ctrl"},
359 {"[name='ne:ctrl:voltage-in']/sensor-data", ""},
360 {"[name='ne:ctrl:voltage-in']/sensor-data/oper-status", "ok"},
361 {"[name='ne:ctrl:voltage-in']/sensor-data/value", "220000"},
362 {"[name='ne:ctrl:voltage-in']/sensor-data/value-precision", "0"},
363 {"[name='ne:ctrl:voltage-in']/sensor-data/value-scale", "micro"},
364 {"[name='ne:ctrl:voltage-in']/sensor-data/value-type", "volts-AC"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100365 {"[name='ne:ctrl:voltage-out']", ""},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100366 {"[name='ne:ctrl:voltage-out']/name", "ne:ctrl:voltage-out"},
367 {"[name='ne:ctrl:voltage-out']/class", "iana-hardware:sensor"},
368 {"[name='ne:ctrl:voltage-out']/parent", "ne:ctrl"},
369 {"[name='ne:ctrl:voltage-out']/sensor-data", ""},
370 {"[name='ne:ctrl:voltage-out']/sensor-data/oper-status", "ok"},
371 {"[name='ne:ctrl:voltage-out']/sensor-data/value", "12000"},
372 {"[name='ne:ctrl:voltage-out']/sensor-data/value-precision", "0"},
373 {"[name='ne:ctrl:voltage-out']/sensor-data/value-scale", "micro"},
374 {"[name='ne:ctrl:voltage-out']/sensor-data/value-type", "volts-DC"},
375
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100376 {"[name='ne:ctrl:current']", ""},
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100377 {"[name='ne:ctrl:current']/name", "ne:ctrl:current"},
378 {"[name='ne:ctrl:current']/class", "iana-hardware:sensor"},
379 {"[name='ne:ctrl:current']/parent", "ne:ctrl"},
380 {"[name='ne:ctrl:current']/sensor-data", ""},
381 {"[name='ne:ctrl:current']/sensor-data/oper-status", "ok"},
382 {"[name='ne:ctrl:current']/sensor-data/value", "200"},
383 {"[name='ne:ctrl:current']/sensor-data/value-precision", "0"},
384 {"[name='ne:ctrl:current']/sensor-data/value-scale", "milli"},
385 {"[name='ne:ctrl:current']/sensor-data/value-type", "amperes"},
386
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100387 {"[name='ne:ctrl:emmc']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100388 {"[name='ne:ctrl:emmc']/name", "ne:ctrl:emmc"},
389 {"[name='ne:ctrl:emmc']/parent", "ne:ctrl"},
390 {"[name='ne:ctrl:emmc']/class", "iana-hardware:module"},
391 {"[name='ne:ctrl:emmc']/serial-num", "0x00a8808d"},
Václav Kubernát693c7952021-11-12 16:07:18 +0100392 {"[name='ne:ctrl:emmc']/mfg-date", "2017-02-01T00:00:00-00:00"},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100393 {"[name='ne:ctrl:emmc']/model-name", "8GME4R"},
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100394 {"[name='ne:ctrl:emmc:lifetime']", ""},
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100395 {"[name='ne:ctrl:emmc:lifetime']/name", "ne:ctrl:emmc:lifetime"},
396 {"[name='ne:ctrl:emmc:lifetime']/class", "iana-hardware:sensor"},
397 {"[name='ne:ctrl:emmc:lifetime']/parent", "ne:ctrl:emmc"},
398 {"[name='ne:ctrl:emmc:lifetime']/sensor-data", ""},
399 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/oper-status", "ok"},
400 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value", "40"},
401 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-precision", "0"},
402 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-scale", "units"},
403 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/value-type", "other"},
404 {"[name='ne:ctrl:emmc:lifetime']/sensor-data/units-display", "percent"},
405 };
406
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100407 REQUIRE(dataFromSysrepo(client, modulePrefix + "/component", sysrepo::Datastore::Operational) == expected);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100408 }
409
410 SECTION("test leafnode query")
411 {
412 const auto xpath = modulePrefix + "/component[name='ne:ctrl:emmc:lifetime']/class";
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100413 client.switchDatastore(sysrepo::Datastore::Operational);
414 auto val = client.getData(xpath.c_str());
415 client.switchDatastore(sysrepo::Datastore::Running);
416 REQUIRE(val);
417 REQUIRE(val->findPath(xpath.c_str())->asTerm().valueStr() == "iana-hardware:sensor"s);
Tomáš Pecka98ad18d2020-11-13 15:39:55 +0100418 }
419 }
Tomáš Pecka339bc672020-11-11 15:59:03 +0100420}
Václav Kubernát97e5ea12021-03-24 00:36:57 +0100421
422class FakeI2C : public velia::ietf_hardware::TransientI2C {
423public:
424 FakeI2C(const std::string& fakeHwmonRoot)
425 : TransientI2C({}, {}, {})
426 , m_fakeHwmonRoot(fakeHwmonRoot)
427 {
428 }
429
430 MAKE_CONST_MOCK0(isPresent, bool(), override);
431 MAKE_CONST_MOCK0(bind_mock, void());
432 MAKE_CONST_MOCK0(unbind_mock, void());
433
434 void removeHwmonFile(const std::string& name) const
435 {
436 std::filesystem::remove(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / name);
437 }
438
439 void bind() const override
440 {
441 bind_mock();
442 removeDirectoryTreeIfExists(m_fakeHwmonRoot);
443 std::filesystem::create_directory(m_fakeHwmonRoot);
444 std::filesystem::create_directory(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)));
445
446 for (const auto& filename : {"name", "temp1_input", "temp2_input", "curr1_input", "curr2_input", "curr3_input",
447 "in1_input", "in2_input", "in3_input", "power1_input", "power2_input", "fan1_input"} )
448 {
449 std::ofstream ofs(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / filename);
450 // I don't really care about the values here, I just need the HWMon class to think that the files exist.
451 ofs << 0 << "\n";
452 }
453 }
454 void unbind() const override
455 {
456 unbind_mock();
457 removeDirectoryTreeIfExists(m_fakeHwmonRoot);
458 m_hwmonNo++;
459 }
460
461private:
462
463 std::filesystem::path m_fakeHwmonRoot;
464 mutable std::atomic<int> m_hwmonNo = 1;
465};
466
467TEST_CASE("FspYhPsu")
468{
469 TEST_INIT_LOGS;
470 std::atomic<int> counter = 0;
471 const auto fakeHwmonRoot = CMAKE_CURRENT_BINARY_DIR + "/tests/psu"s;
472 removeDirectoryTreeIfExists(fakeHwmonRoot);
473 auto fakeI2c = std::make_shared<FakeI2C>(fakeHwmonRoot);
474 trompeloeil::sequence seq1;
475 std::shared_ptr<velia::ietf_hardware::FspYhPsu> psu;
476 std::vector<std::unique_ptr<trompeloeil::expectation>> expectations;
477
478 auto i2cPresence = [&counter] {
479 switch (counter) {
480 case 0:
481 case 2:
482 case 4:
483 return false;
484 case 1:
485 case 3:
486 return true;
487 }
488
489 REQUIRE(false);
490 __builtin_unreachable();
491 };
492
493 ALLOW_CALL(*fakeI2c, isPresent()).LR_RETURN(i2cPresence());
494 REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 1).IN_SEQUENCE(seq1);
495 REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 2).IN_SEQUENCE(seq1);
496 REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 3).IN_SEQUENCE(seq1);
497 REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 4).IN_SEQUENCE(seq1);
498
499 psu = std::make_shared<velia::ietf_hardware::FspYhPsu>(fakeHwmonRoot, "psu", fakeI2c);
500
501 for (auto i : {0, 1, 2, 3, 4}) {
502 std::this_thread::sleep_for(std::chrono::seconds(4));
503 velia::ietf_hardware::DataTree expected;
504
505 switch (i) {
506 case 0:
507 break;
508 case 1:
509 expected = {
510 {"/ietf-hardware:hardware/component[name='ne:psu']/class", "iana-hardware:power-supply"},
511 {"/ietf-hardware:hardware/component[name='ne:psu']/parent", "ne"},
512 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/class", "iana-hardware:sensor"},
513 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/parent", "ne:psu"},
514 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/oper-status", "ok"},
515 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value", "0"},
516 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-precision", "0"},
517 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-scale", "milli"},
518 {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-type", "amperes"},
519 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/class", "iana-hardware:sensor"},
520 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/parent", "ne:psu"},
521 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/oper-status", "ok"},
522 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value", "0"},
523 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-precision", "0"},
524 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-scale", "milli"},
525 {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-type", "amperes"},
526 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/class", "iana-hardware:sensor"},
527 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/parent", "ne:psu"},
528 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/oper-status", "ok"},
529 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value", "0"},
530 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-precision", "0"},
531 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-scale", "milli"},
532 {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-type", "amperes"},
533 {"/ietf-hardware:hardware/component[name='ne:psu:fan']/class", "iana-hardware:module"},
534 {"/ietf-hardware:hardware/component[name='ne:psu:fan']/parent", "ne:psu"},
535 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/class", "iana-hardware:fan"},
536 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/parent", "ne:psu:fan"},
537 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/class", "iana-hardware:sensor"},
538 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/parent", "ne:psu:fan:fan1"},
539 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/oper-status", "ok"},
540 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value", "0"},
541 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-precision", "0"},
542 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-scale", "units"},
543 {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-type", "rpm"},
544 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/class", "iana-hardware:sensor"},
545 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/parent", "ne:psu"},
546 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/oper-status", "ok"},
547 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value", "0"},
548 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-precision", "0"},
549 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-scale", "micro"},
550 {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-type", "watts"},
551 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/class", "iana-hardware:sensor"},
552 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/parent", "ne:psu"},
553 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/oper-status", "ok"},
554 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value", "0"},
555 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-precision", "0"},
556 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-scale", "micro"},
557 {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-type", "watts"},
558 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/class", "iana-hardware:sensor"},
559 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/parent", "ne:psu"},
560 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/oper-status", "ok"},
561 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value", "0"},
562 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-precision", "0"},
563 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-scale", "milli"},
564 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-type", "celsius"},
565 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/class", "iana-hardware:sensor"},
566 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/parent", "ne:psu"},
567 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/oper-status", "ok"},
568 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value", "0"},
569 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-precision", "0"},
570 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-scale", "milli"},
571 {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-type", "celsius"},
572 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/class", "iana-hardware:sensor"},
573 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/parent", "ne:psu"},
574 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/oper-status", "ok"},
575 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value", "0"},
576 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-precision", "0"},
577 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-scale", "micro"},
578 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-type", "volts-DC"},
579 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/class", "iana-hardware:sensor"},
580 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/parent", "ne:psu"},
581 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/oper-status", "ok"},
582 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value", "0"},
583 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-precision", "0"},
584 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-scale", "micro"},
585 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-type", "volts-DC"},
586 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/class", "iana-hardware:sensor"},
587 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/parent", "ne:psu"},
588 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/oper-status", "ok"},
589 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value", "0"},
590 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-precision", "0"},
591 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-scale", "micro"},
592 {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-type", "volts-AC"},
593 };
594 break;
595 case 2:
596 break;
597 case 3:
598 // Here I simulate read failure by a file from the hwmon directory. This happens when the user wants data from
599 // a PSU that's no longer there and the watcher thread didn't unbind it yet.
600 fakeI2c->removeHwmonFile("temp1_input");
601 break;
602 case 4:
603 break;
604 }
605
606 REQUIRE(psu->readValues() == expected);
607
608 counter++;
609 }
610
611 waitForCompletionAndBitMore(seq1);
612}