tests: test FspYhPsu in separate test file
The test takes a long time (~20s). By separating it into separate file
we get better parallelization when running with ctest.
Change-Id: I6b7dfb0bebc5563038e6a6dbd0ea12050fa29f36
diff --git a/tests/hardware_fspyhpsu.cpp b/tests/hardware_fspyhpsu.cpp
new file mode 100644
index 0000000..fbf36c4
--- /dev/null
+++ b/tests/hardware_fspyhpsu.cpp
@@ -0,0 +1,199 @@
+#include "trompeloeil_doctest.h"
+#include <fstream>
+#include "fs-helpers/utils.h"
+#include "ietf-hardware/FspYhPsu.h"
+#include "pretty_printers.h"
+#include "test_log_setup.h"
+#include "test_sysrepo_helpers.h"
+#include "tests/configure.cmake.h"
+
+using namespace std::literals;
+
+class FakeI2C : public velia::ietf_hardware::TransientI2C {
+public:
+ FakeI2C(const std::string& fakeHwmonRoot)
+ : TransientI2C({}, {}, {})
+ , m_fakeHwmonRoot(fakeHwmonRoot)
+ {
+ }
+
+ MAKE_CONST_MOCK0(isPresent, bool(), override);
+ MAKE_CONST_MOCK0(bind_mock, void());
+ MAKE_CONST_MOCK0(unbind_mock, void());
+
+ void removeHwmonFile(const std::string& name) const
+ {
+ std::filesystem::remove(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / name);
+ }
+
+ void bind() const override
+ {
+ bind_mock();
+ removeDirectoryTreeIfExists(m_fakeHwmonRoot);
+ std::filesystem::create_directory(m_fakeHwmonRoot);
+ std::filesystem::create_directory(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)));
+
+ for (const auto& filename : {"name", "temp1_input", "temp2_input", "curr1_input", "curr2_input", "curr3_input", "in1_input", "in2_input", "in3_input", "power1_input", "power2_input", "fan1_input"}) {
+ std::ofstream ofs(m_fakeHwmonRoot / ("hwmon" + std::to_string(m_hwmonNo)) / filename);
+ // I don't really care about the values here, I just need the HWMon class to think that the files exist.
+ ofs << 0 << "\n";
+ }
+ }
+ void unbind() const override
+ {
+ unbind_mock();
+ removeDirectoryTreeIfExists(m_fakeHwmonRoot);
+ m_hwmonNo++;
+ }
+
+private:
+ std::filesystem::path m_fakeHwmonRoot;
+ mutable std::atomic<int> m_hwmonNo = 1;
+};
+
+TEST_CASE("FspYhPsu")
+{
+ TEST_INIT_LOGS;
+ std::atomic<int> counter = 0;
+ const auto fakeHwmonRoot = CMAKE_CURRENT_BINARY_DIR + "/tests/psu"s;
+ removeDirectoryTreeIfExists(fakeHwmonRoot);
+ auto fakeI2c = std::make_shared<FakeI2C>(fakeHwmonRoot);
+ trompeloeil::sequence seq1;
+ std::shared_ptr<velia::ietf_hardware::FspYhPsu> psu;
+ std::vector<std::unique_ptr<trompeloeil::expectation>> expectations;
+
+ auto i2cPresence = [&counter] {
+ switch (counter) {
+ case 0:
+ case 2:
+ case 4:
+ return false;
+ case 1:
+ case 3:
+ return true;
+ }
+
+ REQUIRE(false);
+ __builtin_unreachable();
+ };
+
+ ALLOW_CALL(*fakeI2c, isPresent()).LR_RETURN(i2cPresence());
+ REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 1).IN_SEQUENCE(seq1);
+ REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 2).IN_SEQUENCE(seq1);
+ REQUIRE_CALL(*fakeI2c, bind_mock()).LR_WITH(counter == 3).IN_SEQUENCE(seq1);
+ REQUIRE_CALL(*fakeI2c, unbind_mock()).LR_WITH(counter == 4).IN_SEQUENCE(seq1);
+
+ psu = std::make_shared<velia::ietf_hardware::FspYhPsu>(fakeHwmonRoot, "psu", fakeI2c);
+
+ for (auto i : {0, 1, 2, 3, 4}) {
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ velia::ietf_hardware::DataTree expected;
+
+ switch (i) {
+ case 0:
+ break;
+ case 1:
+ expected = {
+ {"/ietf-hardware:hardware/component[name='ne:psu']/class", "iana-hardware:power-supply"},
+ {"/ietf-hardware:hardware/component[name='ne:psu']/parent", "ne"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-12V']/sensor-data/value-type", "amperes"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-5Vsb']/sensor-data/value-type", "amperes"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:current-in']/sensor-data/value-type", "amperes"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan']/class", "iana-hardware:module"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/class", "iana-hardware:fan"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1']/parent", "ne:psu:fan"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/parent", "ne:psu:fan:fan1"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-scale", "units"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:fan:fan1:rpm']/sensor-data/value-type", "rpm"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-scale", "micro"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-in']/sensor-data/value-type", "watts"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-scale", "micro"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:power-out']/sensor-data/value-type", "watts"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-1']/sensor-data/value-type", "celsius"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:temperature-2']/sensor-data/value-type", "celsius"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-12V']/sensor-data/value-type", "volts-DC"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-5Vsb']/sensor-data/value-type", "volts-DC"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/class", "iana-hardware:sensor"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/parent", "ne:psu"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/oper-status", "ok"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-precision", "0"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-scale", "milli"},
+ {"/ietf-hardware:hardware/component[name='ne:psu:voltage-in']/sensor-data/value-type", "volts-AC"},
+ };
+ break;
+ case 2:
+ break;
+ case 3:
+ // Here I simulate read failure by a file from the hwmon directory. This happens when the user wants data from
+ // a PSU that's no longer there and the watcher thread didn't unbind it yet.
+ fakeI2c->removeHwmonFile("temp1_input");
+ break;
+ case 4:
+ break;
+ }
+
+ REQUIRE(psu->readValues() == expected);
+
+ counter++;
+ }
+
+ waitForCompletionAndBitMore(seq1);
+}