add health_metric_collection implementation
Add the interface and implementation for health_metric_collection which
encapsulates various health_metrics.
This change is in relation to following design and D-Bus interface
update -
https://gerrit.openbmc.org/c/openbmc/docs/+/64917
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/64914
Add test_health_metric_collection gtest for unit testing.
Change-Id: Ia0b9fbc6bec4850735c7eb74dcd5c40fc47c568c
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/test/meson.build b/test/meson.build
index f240bc0..c4f8993 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -54,3 +54,23 @@
include_directories: '../',
)
)
+
+test(
+ 'test_health_metric_collection',
+ executable(
+ 'test_health_metric_collection',
+ 'test_health_metric_collection.cpp',
+ '../health_metric_collection.cpp',
+ '../health_metric.cpp',
+ '../health_metric_config.cpp',
+ '../health_utils.cpp',
+ dependencies: [
+ gtest_dep,
+ gmock_dep,
+ phosphor_logging_dep,
+ phosphor_dbus_interfaces_dep,
+ sdbusplus_dep
+ ],
+ include_directories: '../',
+ )
+)
diff --git a/test/test_health_metric_collection.cpp b/test/test_health_metric_collection.cpp
new file mode 100644
index 0000000..2f4b1b9
--- /dev/null
+++ b/test/test_health_metric_collection.cpp
@@ -0,0 +1,160 @@
+#include "health_metric_collection.hpp"
+
+#include <sdbusplus/test/sdbus_mock.hpp>
+#include <xyz/openbmc_project/Metric/Value/server.hpp>
+
+#include <gtest/gtest.h>
+
+namespace ConfigIntf = phosphor::health::metric::config;
+namespace MetricIntf = phosphor::health::metric;
+namespace CollectionIntf = phosphor::health::metric::collection;
+
+using PathInterface =
+ sdbusplus::common::xyz::openbmc_project::metric::Value::namespace_path;
+using ThresholdIntf =
+ sdbusplus::server::xyz::openbmc_project::common::Threshold;
+using ::testing::Invoke;
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::StrEq;
+
+class HealthMetricCollectionTest : public ::testing::Test
+{
+ public:
+ sdbusplus::SdBusMock sdbusMock;
+ sdbusplus::bus::bus bus = sdbusplus::get_mocked_new(&sdbusMock);
+
+ static constexpr auto busName = "xyz.openbmc_project.test.HealthMon";
+ static constexpr auto objPath = "/xyz/openbmc_project/sdbusplus/test";
+ const std::string valueInterface =
+ sdbusplus::common::xyz::openbmc_project::metric::Value::interface;
+ const std::string thresholdInterface =
+ sdbusplus::common::xyz::openbmc_project::common::Threshold::interface;
+ ConfigIntf::HealthMetric::map_t configs;
+
+ void SetUp() override
+ {
+ sdbusplus::server::manager_t objManager(bus, objPath);
+ bus.request_name(busName);
+
+ configs = ConfigIntf::getHealthMetricConfigs();
+ EXPECT_THAT(configs.size(), testing::Ge(1));
+ // Update the health metric window size to 1 and path for test purposes
+ for (auto& [key, values] : configs)
+ {
+ for (auto& config : values)
+ {
+ config.windowSize = 1;
+ if (key == MetricIntf::Type::storage &&
+ config.subType == MetricIntf::SubType::storageReadWrite)
+ {
+ config.path = "/tmp";
+ }
+ }
+ }
+ }
+
+ void updateThreshold(double value)
+ {
+ for (auto& [key, values] : configs)
+ {
+ for (auto& config : values)
+ {
+ for (auto& threshold : config.thresholds)
+ {
+ threshold.second.value = value;
+ }
+ }
+ }
+ }
+
+ void createCollection()
+ {
+ std::map<MetricIntf::Type,
+ std::unique_ptr<CollectionIntf::HealthMetricCollection>>
+ collections;
+ MetricIntf::paths_t bmcPaths = {};
+ for (const auto& [type, collectionConfig] : configs)
+ {
+ collections[type] =
+ std::make_unique<CollectionIntf::HealthMetricCollection>(
+ bus, type, collectionConfig, bmcPaths);
+ collections[type]->read();
+ }
+ }
+};
+
+TEST_F(HealthMetricCollectionTest, TestCreation)
+{
+ // Change threshold value to 100 to avoid threshold assertion
+ updateThreshold(100);
+
+ EXPECT_CALL(sdbusMock,
+ sd_bus_emit_properties_changed_strv(
+ IsNull(), NotNull(), StrEq(valueInterface), NotNull()))
+ .WillRepeatedly(Invoke(
+ [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
+ [[maybe_unused]] const char* interface, const char** names) {
+ // Test no signal generation for metric init properties
+ const std::set<std::string> metricInitProperties = {"MaxValue",
+ "MinValue", "Unit"};
+ EXPECT_THAT(metricInitProperties,
+ testing::Not(testing::Contains(names[0])));
+ // Test signal generated for Value property set
+ const std::set<std::string> metricSetProperties = {"Value"};
+ EXPECT_THAT(metricSetProperties, testing::Contains(names[0]));
+ return 0;
+ }));
+
+ EXPECT_CALL(sdbusMock,
+ sd_bus_emit_properties_changed_strv(
+ IsNull(), NotNull(), StrEq(thresholdInterface), NotNull()))
+ .WillRepeatedly(Invoke(
+ [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
+ [[maybe_unused]] const char* interface, const char** names) {
+ // Test no signal generation for threshold init properties
+ const std::set<std::string> thresholdProperties = {"Value", "Asserted"};
+ EXPECT_THAT(thresholdProperties,
+ testing::Not(testing::Contains(names[0])));
+ return 0;
+ }));
+
+ createCollection();
+}
+
+TEST_F(HealthMetricCollectionTest, TestThresholdAsserted)
+{
+ // Change threshold value to 0 to trigger threshold assertion
+ updateThreshold(0);
+
+ // Test metric value property change
+ EXPECT_CALL(sdbusMock,
+ sd_bus_emit_properties_changed_strv(
+ IsNull(), NotNull(), StrEq(valueInterface), NotNull()))
+ .WillRepeatedly(Invoke(
+ [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
+ [[maybe_unused]] const char* interface, const char** names) {
+ EXPECT_THAT("Value", StrEq(names[0]));
+ return 0;
+ }));
+
+ // Test threshold asserted property change
+ EXPECT_CALL(sdbusMock,
+ sd_bus_emit_properties_changed_strv(
+ IsNull(), NotNull(), StrEq(thresholdInterface), NotNull()))
+ .WillRepeatedly(Invoke(
+ [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
+ [[maybe_unused]] const char* interface, const char** names) {
+ EXPECT_THAT("Asserted", StrEq(names[0]));
+ return 0;
+ }));
+
+ // Test AssertionChanged signal generation
+ EXPECT_CALL(sdbusMock,
+ sd_bus_message_new_signal(IsNull(), NotNull(), NotNull(),
+ StrEq(thresholdInterface),
+ StrEq("AssertionChanged")))
+ .Times(11);
+
+ createCollection();
+}