Changed dbus add report interface
- metric parameters now take single sensor instead of list
- added interface support for new operation types
Tested:
- All telemetry tests are passing.
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: Id3a41c48e81a287e7d205ae1c747daa36d4cdb29
diff --git a/src/interfaces/metric.hpp b/src/interfaces/metric.hpp
index 5a960a4..deb3ed6 100644
--- a/src/interfaces/metric.hpp
+++ b/src/interfaces/metric.hpp
@@ -16,7 +16,7 @@
virtual ~Metric() = default;
virtual void initialize() = 0;
- virtual const std::vector<MetricValue>& getReadings() const = 0;
+ virtual const MetricValue& getReading() const = 0;
virtual LabeledMetricParameters dumpConfiguration() const = 0;
};
diff --git a/src/interfaces/types.hpp b/src/interfaces/types.hpp
index 3cc069e..a5ed0db 100644
--- a/src/interfaces/types.hpp
+++ b/src/interfaces/types.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "operation_type.hpp"
#include "utils/labeled_tuple.hpp"
#include "utils/tstring.hpp"
@@ -11,17 +12,17 @@
#include <vector>
using ReadingParameters =
- std::vector<std::tuple<std::vector<sdbusplus::message::object_path>,
- std::string, std::string, std::string>>;
+ std::vector<std::tuple<sdbusplus::message::object_path, std::string,
+ std::string, std::string>>;
using LabeledSensorParameters =
utils::LabeledTuple<std::tuple<std::string, std::string>,
utils::tstring::Service, utils::tstring::Path>;
using LabeledMetricParameters =
- utils::LabeledTuple<std::tuple<std::vector<LabeledSensorParameters>,
- std::string, std::string, std::string>,
- utils::tstring::SensorPaths,
+ utils::LabeledTuple<std::tuple<LabeledSensorParameters, OperationType,
+ std::string, std::string>,
+ utils::tstring::SensorPath,
utils::tstring::OperationType, utils::tstring::Id,
utils::tstring::MetricMetadata>;
diff --git a/src/metric.cpp b/src/metric.cpp
index b12f3a6..2a73536 100644
--- a/src/metric.cpp
+++ b/src/metric.cpp
@@ -5,58 +5,52 @@
#include <algorithm>
-Metric::Metric(std::vector<std::shared_ptr<interfaces::Sensor>> sensors,
- std::string operationType, std::string id,
+Metric::Metric(std::shared_ptr<interfaces::Sensor> sensor,
+ OperationType operationType, std::string id,
std::string metadata) :
- sensors(std::move(sensors)),
- operationType(std::move(operationType)), id(std::move(id)),
- metadata(std::move(metadata))
+ sensor(std::move(sensor)),
+ operationType(std::move(operationType)), reading{std::move(id),
+ std::move(metadata), 0.,
+ 0u}
{}
void Metric::initialize()
{
- readings = std::vector<MetricValue>(sensors.size(),
- MetricValue{id, metadata, 0., 0u});
-
- for (auto& sensor : sensors)
- {
- sensor->registerForUpdates(weak_from_this());
- }
+ sensor->registerForUpdates(weak_from_this());
}
-const std::vector<MetricValue>& Metric::getReadings() const
+const MetricValue& Metric::getReading() const
{
- return readings;
+ return reading;
}
-void Metric::sensorUpdated(interfaces::Sensor& sensor, uint64_t timestamp)
+void Metric::sensorUpdated(interfaces::Sensor& notifier, uint64_t timestamp)
{
- MetricValue& mv = findMetric(sensor);
+ MetricValue& mv = findMetric(notifier);
mv.timestamp = timestamp;
}
-void Metric::sensorUpdated(interfaces::Sensor& sensor, uint64_t timestamp,
+void Metric::sensorUpdated(interfaces::Sensor& notifier, uint64_t timestamp,
double value)
{
- MetricValue& mv = findMetric(sensor);
+ MetricValue& mv = findMetric(notifier);
mv.timestamp = timestamp;
mv.value = value;
}
-MetricValue& Metric::findMetric(interfaces::Sensor& sensor)
+MetricValue& Metric::findMetric(interfaces::Sensor& notifier)
{
- auto it =
- std::find_if(sensors.begin(), sensors.end(),
- [&sensor](const auto& s) { return s.get() == &sensor; });
- auto index = std::distance(sensors.begin(), it);
- return readings.at(index);
+ if (sensor.get() != ¬ifier)
+ {
+ throw std::out_of_range("unknown sensor");
+ }
+ return reading;
}
LabeledMetricParameters Metric::dumpConfiguration() const
{
- auto sensorPaths = utils::transform(sensors, [](const auto& sensor) {
- return LabeledSensorParameters(sensor->id().service, sensor->id().path);
- });
- return LabeledMetricParameters(std::move(sensorPaths), operationType, id,
- metadata);
+ auto sensorPath =
+ LabeledSensorParameters(sensor->id().service, sensor->id().path);
+ return LabeledMetricParameters(std::move(sensorPath), operationType,
+ reading.id, reading.metadata);
}
diff --git a/src/metric.hpp b/src/metric.hpp
index 39f525c..aab4d15 100644
--- a/src/metric.hpp
+++ b/src/metric.hpp
@@ -10,11 +10,11 @@
public std::enable_shared_from_this<Metric>
{
public:
- Metric(std::vector<std::shared_ptr<interfaces::Sensor>> sensors,
- std::string operationType, std::string id, std::string metadata);
+ Metric(std::shared_ptr<interfaces::Sensor> sensor,
+ OperationType operationType, std::string id, std::string metadata);
void initialize() override;
- const std::vector<MetricValue>& getReadings() const override;
+ const MetricValue& getReading() const override;
void sensorUpdated(interfaces::Sensor&, uint64_t) override;
void sensorUpdated(interfaces::Sensor&, uint64_t, double value) override;
LabeledMetricParameters dumpConfiguration() const override;
@@ -22,9 +22,7 @@
private:
MetricValue& findMetric(interfaces::Sensor&);
- std::vector<std::shared_ptr<interfaces::Sensor>> sensors;
- std::string operationType;
- std::string id;
- std::string metadata;
- std::vector<MetricValue> readings;
+ std::shared_ptr<interfaces::Sensor> sensor;
+ OperationType operationType;
+ MetricValue reading;
};
diff --git a/src/operation_type.hpp b/src/operation_type.hpp
new file mode 100644
index 0000000..a4f085c
--- /dev/null
+++ b/src/operation_type.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "utils/conversion.hpp"
+
+#include <array>
+#include <cstdint>
+#include <string_view>
+
+enum class OperationType : uint32_t
+{
+ single,
+ max,
+ min,
+ avg,
+ sum
+};
+
+namespace utils
+{
+
+constexpr std::array<std::pair<std::string_view, OperationType>, 5>
+ convDataOperationType = {
+ {std::make_pair<std::string_view, OperationType>("SINGLE",
+ OperationType::single),
+ std::make_pair<std::string_view, OperationType>("MAX",
+ OperationType::max),
+ std::make_pair<std::string_view, OperationType>("MIN",
+ OperationType::min),
+ std::make_pair<std::string_view, OperationType>("AVG",
+ OperationType::avg),
+ std::make_pair<std::string_view, OperationType>("SUM",
+ OperationType::sum)}};
+
+inline OperationType
+ toOperationType(std::underlying_type_t<OperationType> value)
+{
+ return toEnum<OperationType, OperationType::single, OperationType::sum>(
+ value);
+}
+
+inline OperationType stringToOperationType(const std::string& value)
+{
+ return stringToEnum(convDataOperationType, value);
+}
+
+inline std::string enumToString(OperationType value)
+{
+ return std::string(enumToString(convDataOperationType, value));
+}
+
+} // namespace utils
diff --git a/src/report.cpp b/src/report.cpp
index 59028f4..77189c1 100644
--- a/src/report.cpp
+++ b/src/report.cpp
@@ -143,23 +143,14 @@
void Report::updateReadings()
{
- auto numElements = std::accumulate(
- metrics.begin(), metrics.end(), 0u, [](auto sum, const auto& metric) {
- return sum + metric->getReadings().size();
- });
+ std::tuple_element_t<1, Readings> readingsCache(metrics.size());
- std::tuple_element_t<1, Readings> readingsCache(numElements);
-
- auto it = readingsCache.begin();
-
- for (const auto& metric : metrics)
- {
- for (const auto& reading : metric->getReadings())
- {
- *(it++) = std::make_tuple(reading.id, reading.metadata,
- reading.value, reading.timestamp);
- }
- }
+ std::transform(std::begin(metrics), std::end(metrics),
+ std::begin(readingsCache), [](const auto& metric) {
+ const auto& reading = metric->getReading();
+ return std::make_tuple(reading.id, reading.metadata,
+ reading.value, reading.timestamp);
+ });
std::get<0>(readings) = std::time(0);
std::get<1>(readings) = std::move(readingsCache);
diff --git a/src/report.hpp b/src/report.hpp
index 2f470d3..97afe03 100644
--- a/src/report.hpp
+++ b/src/report.hpp
@@ -75,5 +75,5 @@
"/xyz/openbmc_project/Telemetry/Reports/";
static constexpr const char* deleteIfaceName =
"xyz.openbmc_project.Object.Delete";
- static constexpr size_t reportVersion = 2;
+ static constexpr size_t reportVersion = 3;
};
diff --git a/src/report_factory.cpp b/src/report_factory.cpp
index 2cd5da3..9dfdbb0 100644
--- a/src/report_factory.cpp
+++ b/src/report_factory.cpp
@@ -3,6 +3,7 @@
#include "metric.hpp"
#include "report.hpp"
#include "sensor.hpp"
+#include "utils/conversion.hpp"
#include "utils/dbus_mapper.hpp"
#include "utils/transform.hpp"
@@ -41,7 +42,7 @@
[this](const LabeledMetricParameters& param)
-> std::shared_ptr<interfaces::Metric> {
return std::make_shared<Metric>(
- getSensors(param.at_index<0>()), param.at_index<1>(),
+ getSensor(param.at_index<0>()), param.at_index<1>(),
param.at_index<2>(), param.at_index<3>());
});
@@ -51,19 +52,14 @@
reportManager, reportStorage, std::move(metrics));
}
-std::vector<std::shared_ptr<interfaces::Sensor>> ReportFactory::getSensors(
- const std::vector<LabeledSensorParameters>& sensorPaths) const
+std::shared_ptr<interfaces::Sensor>
+ ReportFactory::getSensor(const LabeledSensorParameters& sensorPath) const
{
- return utils::transform(sensorPaths,
- [this](const LabeledSensorParameters& param)
- -> std::shared_ptr<interfaces::Sensor> {
- using namespace utils::tstring;
+ using namespace utils::tstring;
- return sensorCache.makeSensor<Sensor>(
- param.at_label<Service>(),
- param.at_label<Path>(),
- bus->get_io_context(), bus);
- });
+ return sensorCache.makeSensor<Sensor>(sensorPath.at_label<Service>(),
+ sensorPath.at_label<Path>(),
+ bus->get_io_context(), bus);
}
std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
@@ -73,24 +69,22 @@
auto tree = utils::getSubTreeSensors(yield, bus);
return utils::transform(metricParams, [&tree](const auto& item) {
- std::vector<LabeledSensorParameters> sensors;
+ const auto& [sensorPath, operationType, id, metadata] = item;
- for (const auto& sensorPath : std::get<0>(item))
+ auto it = std::find_if(
+ tree.begin(), tree.end(),
+ [&sensorPath](const auto& v) { return v.first == sensorPath; });
+
+ if (it != tree.end() && it->second.size() == 1)
{
- auto it = std::find_if(
- tree.begin(), tree.end(),
- [&sensorPath](const auto& v) { return v.first == sensorPath; });
-
- if (it != tree.end())
- {
- for (const auto& [service, ifaces] : it->second)
- {
- sensors.emplace_back(service, sensorPath);
- }
- }
+ const auto& [service, ifaces] = it->second.front();
+ return LabeledMetricParameters(
+ LabeledSensorParameters(service, sensorPath),
+ utils::stringToOperationType(operationType), id, metadata);
}
- return LabeledMetricParameters(std::move(sensors), std::get<1>(item),
- std::get<2>(item), std::get<3>(item));
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::invalid_argument),
+ "Could not find service for provided sensors");
});
}
diff --git a/src/report_factory.hpp b/src/report_factory.hpp
index 6d90902..550eb81 100644
--- a/src/report_factory.hpp
+++ b/src/report_factory.hpp
@@ -34,8 +34,8 @@
const override;
private:
- std::vector<std::shared_ptr<interfaces::Sensor>> getSensors(
- const std::vector<LabeledSensorParameters>& sensorPaths) const;
+ std::shared_ptr<interfaces::Sensor>
+ getSensor(const LabeledSensorParameters& sensorPath) const;
std::vector<LabeledMetricParameters>
convertMetricParams(boost::asio::yield_context& yield,
const ReadingParameters& metricParams) const;
diff --git a/src/report_manager.cpp b/src/report_manager.cpp
index 1d3e47b..9ea6026 100644
--- a/src/report_manager.cpp
+++ b/src/report_manager.cpp
@@ -2,6 +2,7 @@
#include "interfaces/types.hpp"
#include "report.hpp"
+#include "utils/conversion.hpp"
#include "utils/transform.hpp"
#include <phosphor-logging/log.hpp>
@@ -92,22 +93,26 @@
static_cast<int>(std::errc::invalid_argument), "Invalid interval");
}
- for (const auto& param : readingParams)
- {
- const auto& sensors = std::get<0>(param);
- if (sensors.size() != 1)
- {
- throw sdbusplus::exception::SdBusError(
- static_cast<int>(std::errc::not_supported),
- "Only single sensor per metric is allowed");
- }
- }
if (readingParams.size() > maxReadingParams)
+
{
throw sdbusplus::exception::SdBusError(
static_cast<int>(std::errc::argument_list_too_long),
"Too many reading parameters");
}
+
+ try
+ {
+ for (const auto& item : readingParams)
+ {
+ utils::stringToOperationType(std::get<1>(item));
+ }
+ }
+ catch (const std::exception& e)
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::invalid_argument), e.what());
+ }
}
interfaces::Report& ReportManager::addReport(
@@ -136,12 +141,10 @@
using namespace utils::tstring;
return ReadingParameters::value_type(
- utils::transform(param.at_index<0>(),
- [](const LabeledSensorParameters& p) {
- return sdbusplus::message::object_path(
- p.at_label<Path>());
- }),
- param.at_index<1>(), param.at_index<2>(), param.at_index<3>());
+ sdbusplus::message::object_path(
+ param.at_index<0>().at_label<Path>()),
+ utils::enumToString(param.at_index<1>()), param.at_index<2>(),
+ param.at_index<3>());
});
verifyAddReport(reportName, reportingType, interval, metricParams);
diff --git a/src/utils/conversion.hpp b/src/utils/conversion.hpp
index 7db4be8..5e8ef81 100644
--- a/src/utils/conversion.hpp
+++ b/src/utils/conversion.hpp
@@ -1,18 +1,57 @@
#pragma once
+#include <algorithm>
+#include <array>
#include <stdexcept>
+#include <string>
namespace utils
{
template <class T, T first, T last>
-inline T toEnum(int x)
+inline T toEnum(std::underlying_type_t<T> x)
{
- if (x < static_cast<decltype(x)>(first) ||
- x > static_cast<decltype(x)>(last))
+ if (x < static_cast<std::underlying_type_t<T>>(first) ||
+ x > static_cast<std::underlying_type_t<T>>(last))
{
throw std::out_of_range("Value is not in range of enum");
}
return static_cast<T>(x);
}
+
+template <class T>
+inline std::underlying_type_t<T> toUnderlying(T value)
+{
+ return static_cast<std::underlying_type_t<T>>(value);
+}
+
+template <class T, size_t N>
+inline T stringToEnum(const std::array<std::pair<std::string_view, T>, N>& data,
+ const std::string& value)
+{
+ auto it = std::find_if(
+ std::begin(data), std::end(data),
+ [&value](const auto& item) { return item.first == value; });
+ if (it == std::end(data))
+ {
+ throw std::out_of_range("Value is not in range of enum");
+ }
+ return it->second;
+}
+
+template <class T, size_t N>
+inline std::string_view
+ enumToString(const std::array<std::pair<std::string_view, T>, N>& data,
+ T value)
+{
+ auto it = std::find_if(
+ std::begin(data), std::end(data),
+ [value](const auto& item) { return item.second == value; });
+ if (it == std::end(data))
+ {
+ throw std::out_of_range("Value is not in range of enum");
+ }
+ return it->first;
+}
+
} // namespace utils
diff --git a/src/utils/tstring.hpp b/src/utils/tstring.hpp
index f0a401f..a8d3e90 100644
--- a/src/utils/tstring.hpp
+++ b/src/utils/tstring.hpp
@@ -16,11 +16,11 @@
}
};
-struct SensorPaths
+struct SensorPath
{
static std::string str()
{
- return "sensorPaths";
+ return "sensorPath";
}
};
diff --git a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp b/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
index 3666a62..9a46d0c 100644
--- a/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
+++ b/tests/src/helpers/interfaces/labeled_reading_parameter_helpers.hpp
@@ -15,8 +15,8 @@
using testing::PrintToString;
(*os) << "{ ";
- (*os) << utils::tstring::SensorPaths::str() << ": "
- << PrintToString(o.at_label<utils::tstring::SensorPaths>()) << ", ";
+ (*os) << utils::tstring::SensorPath::str() << ": "
+ << PrintToString(o.at_label<utils::tstring::SensorPath>()) << ", ";
(*os) << utils::tstring::OperationType::str() << ": "
<< PrintToString(o.at_label<utils::tstring::OperationType>()) << ", ";
(*os) << utils::tstring::Id::str() << ": "
@@ -26,4 +26,4 @@
(*os) << " }";
}
-} // namespace utils
\ No newline at end of file
+} // namespace utils
diff --git a/tests/src/mocks/metric_mock.hpp b/tests/src/mocks/metric_mock.hpp
index 98bad87..2f31f1e 100644
--- a/tests/src/mocks/metric_mock.hpp
+++ b/tests/src/mocks/metric_mock.hpp
@@ -11,13 +11,12 @@
{
using namespace testing;
- ON_CALL(*this, getReadings())
- .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>()));
+ ON_CALL(*this, getReading())
+ .WillByDefault(ReturnRefOfCopy(MetricValue()));
}
MOCK_METHOD(void, initialize, (), (override));
- MOCK_METHOD(const std::vector<MetricValue>&, getReadings, (),
- (const, override));
+ MOCK_METHOD(const MetricValue&, getReading, (), (const, override));
MOCK_METHOD(LabeledMetricParameters, dumpConfiguration, (),
(const, override));
};
diff --git a/tests/src/params/report_params.hpp b/tests/src/params/report_params.hpp
index fa1340c..25422bc 100644
--- a/tests/src/params/report_params.hpp
+++ b/tests/src/params/report_params.hpp
@@ -84,12 +84,12 @@
ReadingParameters readingParametersProperty = {
{{sdbusplus::message::object_path(
"/xyz/openbmc_project/sensors/power/p1")},
- "SINGLE",
+ utils::enumToString(OperationType::single),
"MetricId1",
"Metadata1"},
{{sdbusplus::message::object_path(
"/xyz/openbmc_project/sensors/power/p2")},
- "SINGLE",
+ utils::enumToString(OperationType::single),
"MetricId2",
"Metadata2"}};
};
diff --git a/tests/src/params/trigger_params.hpp b/tests/src/params/trigger_params.hpp
index 464c68b..9aed64d 100644
--- a/tests/src/params/trigger_params.hpp
+++ b/tests/src/params/trigger_params.hpp
@@ -2,6 +2,8 @@
#include "interfaces/trigger_types.hpp"
+#include <sdbusplus/message.hpp>
+
#include <chrono>
#include <utility>
diff --git a/tests/src/test_conversion.cpp b/tests/src/test_conversion.cpp
index e3984ca..f24592f 100644
--- a/tests/src/test_conversion.cpp
+++ b/tests/src/test_conversion.cpp
@@ -4,7 +4,7 @@
using namespace testing;
-class TestEnum : public Test
+class TestConversion : public Test
{
public:
enum class Enum
@@ -18,16 +18,63 @@
{
return utils::toEnum<Enum, Enum::zero, Enum::two>(x);
}
+
+ Enum stringToEnum(const std::string& value)
+ {
+ return utils::stringToEnum(convDataEnum, value);
+ }
+
+ std::string enumToString(Enum value)
+ {
+ return std::string(utils::enumToString(convDataEnum, value));
+ }
+
+ static constexpr std::array<std::pair<std::string_view, Enum>, 3>
+ convDataEnum = {
+ {std::make_pair<std::string_view, Enum>("zero", Enum::zero),
+ std::make_pair<std::string_view, Enum>("one", Enum::one),
+ std::make_pair<std::string_view, Enum>("two", Enum::two)}};
};
-TEST_F(TestEnum, passValueInRangeExpectToGetValidOutput)
+TEST_F(TestConversion, passValueInRangeExpectToGetValidOutput)
{
EXPECT_EQ(toEnum(0), Enum::zero);
EXPECT_EQ(toEnum(2), Enum::two);
}
-TEST_F(TestEnum, passInvalidValueExpectToThrowOutOfRangeException)
+TEST_F(TestConversion, passInvalidValueExpectToThrowOutOfRangeException)
{
EXPECT_THROW(toEnum(-1), std::out_of_range);
EXPECT_THROW(toEnum(3), std::out_of_range);
}
+
+TEST_F(TestConversion, convertsToUnderlyingType)
+{
+ EXPECT_THAT(utils::toUnderlying(Enum::one), Eq(1));
+ EXPECT_THAT(utils::toUnderlying(Enum::two), Eq(2));
+ EXPECT_THAT(utils::toUnderlying(Enum::zero), Eq(0));
+}
+
+TEST_F(TestConversion, convertsEnumToString)
+{
+ EXPECT_THAT(enumToString(Enum::one), Eq("one"));
+ EXPECT_THAT(enumToString(Enum::two), Eq("two"));
+ EXPECT_THAT(enumToString(Enum::zero), Eq("zero"));
+}
+
+TEST_F(TestConversion, convertsStringToEnum)
+{
+ EXPECT_THAT(stringToEnum("one"), Eq(Enum::one));
+ EXPECT_THAT(stringToEnum("two"), Eq(Enum::two));
+ EXPECT_THAT(stringToEnum("zero"), Eq(Enum::zero));
+}
+
+TEST_F(TestConversion, enumToStringThrowsWhenUknownEnumPassed)
+{
+ EXPECT_THROW(enumToString(static_cast<Enum>(77)), std::out_of_range);
+}
+
+TEST_F(TestConversion, stringToEnumThrowsWhenUknownStringPassed)
+{
+ EXPECT_THROW(stringToEnum("four"), std::out_of_range);
+}
diff --git a/tests/src/test_metric.cpp b/tests/src/test_metric.cpp
index 22fc97b..e91750d 100644
--- a/tests/src/test_metric.cpp
+++ b/tests/src/test_metric.cpp
@@ -2,130 +2,111 @@
#include "metric.hpp"
#include "mocks/sensor_mock.hpp"
#include "utils/conv_container.hpp"
+#include "utils/conversion.hpp"
+#include "utils/tstring.hpp"
#include <gmock/gmock.h>
using namespace testing;
+namespace tstring = utils::tstring;
using Timestamp = uint64_t;
class TestMetric : public Test
{
public:
- std::vector<std::shared_ptr<SensorMock>> sensorMocks = {
- std::make_shared<NiceMock<SensorMock>>(),
- std::make_shared<NiceMock<SensorMock>>(),
- std::make_shared<NiceMock<SensorMock>>()};
+ std::shared_ptr<SensorMock> sensorMock =
+ std::make_shared<NiceMock<SensorMock>>();
std::shared_ptr<Metric> sut = std::make_shared<Metric>(
- utils::convContainer<std::shared_ptr<interfaces::Sensor>>(sensorMocks),
- "op", "id", "metadata");
+ sensorMock, OperationType::avg, "id", "metadata");
};
TEST_F(TestMetric, subscribesForSensorDuringInitialization)
{
- for (auto& sensor : sensorMocks)
+ EXPECT_CALL(*sensorMock,
+ registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
+ return a0.lock().get() == sut;
+ })));
+
+ sut->initialize();
+}
+
+TEST_F(TestMetric, containsEmptyReadingAfterCreated)
+{
+ ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
+}
+
+class TestMetricAfterInitialization : public TestMetric
+{
+ public:
+ TestMetricAfterInitialization()
{
- EXPECT_CALL(*sensor,
- registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
- return a0.lock().get() == sut;
- })));
+ sut->initialize();
}
+};
- sut->initialize();
+TEST_F(TestMetricAfterInitialization, containsEmptyReading)
+{
+ ASSERT_THAT(sut->getReading(), MetricValue({"id", "metadata", 0., 0u}));
}
-TEST_F(TestMetric, containsNoReadingsWhenNotInitialized)
+TEST_F(TestMetricAfterInitialization, updatesMetricValuesOnSensorUpdate)
{
- ASSERT_THAT(sut->getReadings(), ElementsAre());
+ sut->sensorUpdated(*sensorMock, Timestamp{18}, 31.2);
+
+ ASSERT_THAT(sut->getReading(),
+ Eq(MetricValue{"id", "metadata", 31.2, 18u}));
}
-TEST_F(TestMetric, containsEmptyReadingsAfterInitialize)
+TEST_F(TestMetricAfterInitialization,
+ throwsWhenUpdateIsPerformedOnUnknownSensor)
{
- sut->initialize();
-
- ASSERT_THAT(sut->getReadings(),
- ElementsAre(MetricValue{"id", "metadata", 0., 0u},
- MetricValue{"id", "metadata", 0., 0u},
- MetricValue{"id", "metadata", 0., 0u}));
-}
-
-TEST_F(TestMetric, throwsWhenUpdateIsPerformedWhenNotInitialized)
-{
- EXPECT_THROW(sut->sensorUpdated(*sensorMocks[0], Timestamp{10}),
- std::out_of_range);
- EXPECT_THROW(sut->sensorUpdated(*sensorMocks[1], Timestamp{10}, 20.0),
- std::out_of_range);
-}
-
-TEST_F(TestMetric, updatesMetricValuesOnSensorUpdate)
-{
- sut->initialize();
-
- sut->sensorUpdated(*sensorMocks[2], Timestamp{18}, 31.0);
- sut->sensorUpdated(*sensorMocks[0], Timestamp{21});
-
- ASSERT_THAT(sut->getReadings(),
- ElementsAre(MetricValue{"id", "metadata", 0., 21u},
- MetricValue{"id", "metadata", 0., 0u},
- MetricValue{"id", "metadata", 31., 18u}));
-}
-
-TEST_F(TestMetric, throwsWhenUpdateIsPerformedOnUnknownSensor)
-{
- sut->initialize();
-
auto sensor = std::make_shared<StrictMock<SensorMock>>();
EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}), std::out_of_range);
EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}, 20.0),
std::out_of_range);
}
-TEST_F(TestMetric, containsIdInConfigurationDump)
+TEST_F(TestMetricAfterInitialization, containsIdInConfigurationDump)
{
const auto conf = sut->dumpConfiguration();
EXPECT_THAT(conf.at_label<utils::tstring::Id>(), Eq("id"));
- EXPECT_THAT(conf.to_json().at("id"), Eq(nlohmann::json("id")));
+ EXPECT_THAT(conf.to_json().at(tstring::Id::str()),
+ Eq(nlohmann::json("id")));
}
-TEST_F(TestMetric, containsOpInJsonDump)
+TEST_F(TestMetricAfterInitialization, containsOpInJsonDump)
{
const auto conf = sut->dumpConfiguration();
- EXPECT_THAT(conf.at_label<utils::tstring::OperationType>(), Eq("op"));
- EXPECT_THAT(conf.to_json().at("operationType"), Eq(nlohmann::json("op")));
+ EXPECT_THAT(conf.at_label<utils::tstring::OperationType>(),
+ Eq(OperationType::avg));
+ EXPECT_THAT(conf.to_json().at(tstring::OperationType::str()),
+ Eq(nlohmann::json(utils::toUnderlying(OperationType::avg))));
}
-TEST_F(TestMetric, containsMetadataInJsonDump)
+TEST_F(TestMetricAfterInitialization, containsMetadataInJsonDump)
{
const auto conf = sut->dumpConfiguration();
EXPECT_THAT(conf.at_label<utils::tstring::MetricMetadata>(),
Eq("metadata"));
- EXPECT_THAT(conf.to_json().at("metricMetadata"),
+ EXPECT_THAT(conf.to_json().at(tstring::MetricMetadata::str()),
Eq(nlohmann::json("metadata")));
}
-TEST_F(TestMetric, containsSensorPathsInJsonDump)
+TEST_F(TestMetricAfterInitialization, containsSensorPathInJsonDump)
{
- for (size_t i = 0; i < sensorMocks.size(); ++i)
- {
- const auto no = std::to_string(i);
- ON_CALL(*sensorMocks[i], id())
- .WillByDefault(
- Return(SensorMock::makeId("service" + no, "path" + no)));
- }
+ ON_CALL(*sensorMock, id())
+ .WillByDefault(Return(SensorMock::makeId("service1", "path1")));
const auto conf = sut->dumpConfiguration();
- EXPECT_THAT(conf.at_label<utils::tstring::SensorPaths>(),
- ElementsAre(LabeledSensorParameters("service0", "path0"),
- LabeledSensorParameters("service1", "path1"),
- LabeledSensorParameters("service2", "path2")));
+ EXPECT_THAT(conf.at_label<utils::tstring::SensorPath>(),
+ Eq(LabeledSensorParameters("service1", "path1")));
EXPECT_THAT(
- conf.to_json().at("sensorPaths"),
- Eq(nlohmann::json({{{"service", "service0"}, {"path", "path0"}},
- {{"service", "service1"}, {"path", "path1"}},
- {{"service", "service2"}, {"path", "path2"}}})));
+ conf.to_json().at(tstring::SensorPath::str()),
+ Eq(nlohmann::json({{"service", "service1"}, {"path", "path1"}})));
}
diff --git a/tests/src/test_report.cpp b/tests/src/test_report.cpp
index f6c4ee7..5378f48 100644
--- a/tests/src/test_report.cpp
+++ b/tests/src/test_report.cpp
@@ -8,12 +8,14 @@
#include "report_manager.hpp"
#include "utils/conv_container.hpp"
#include "utils/set_exception.hpp"
+#include "utils/tstring.hpp"
#include <sdbusplus/exception.hpp>
using namespace testing;
using namespace std::literals::string_literals;
using namespace std::chrono_literals;
+namespace tstring = utils::tstring;
class TestReport : public Test
{
@@ -33,13 +35,13 @@
TestReport()
{
- ON_CALL(*metricMocks[0], getReadings())
- .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>(
- {MetricValue{"a", "b", 17.1, 114},
- MetricValue{"aaa", "bbb", 21.7, 100}})));
- ON_CALL(*metricMocks[1], getReadings())
- .WillByDefault(ReturnRefOfCopy(
- std::vector<MetricValue>({MetricValue{"aa", "bb", 42.0, 74}})));
+ ON_CALL(*metricMocks[0], getReading())
+ .WillByDefault(ReturnRefOfCopy(MetricValue{"a", "b", 17.1, 114}));
+ ON_CALL(*metricMocks[1], getReading())
+ .WillByDefault(ReturnRefOfCopy(MetricValue{"aa", "bb", 42.0, 74}));
+ ON_CALL(*metricMocks[2], getReading())
+ .WillByDefault(
+ ReturnRefOfCopy(MetricValue{"aaa", "bbb", 100.7, 21}));
for (size_t i = 0; i < metricMocks.size(); ++i)
{
@@ -47,11 +49,11 @@
auto id = std::to_string(i);
- auto sensorParameters = std::vector<LabeledSensorParameters>(
- {LabeledSensorParameters("service"s + id, "path"s + id)});
- auto metricParameters =
- LabeledMetricParameters(std::move(sensorParameters), "op"s + id,
- "id"s + id, "metadata"s + id);
+ auto sensorParameters =
+ LabeledSensorParameters("service"s + id, "path"s + id);
+ auto metricParameters = LabeledMetricParameters(
+ std::move(sensorParameters), utils::toOperationType(i),
+ "id"s + id, "metadata"s + id);
ON_CALL(*metricMocks[i], dumpConfiguration())
.WillByDefault(Return(std::move(metricParameters)));
@@ -241,35 +243,35 @@
INSTANTIATE_TEST_SUITE_P(
_, TestReportStore,
- Values(
- std::make_pair("Version"s, nlohmann::json(2)),
- std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
- std::make_pair("ReportingType",
- nlohmann::json(ReportParams().reportingType())),
- std::make_pair("EmitsReadingsUpdate",
- nlohmann::json(ReportParams().emitReadingUpdate())),
- std::make_pair(
- "LogToMetricReportsCollection",
- nlohmann::json(ReportParams().logToMetricReportCollection())),
- std::make_pair("Interval",
- nlohmann::json(ReportParams().interval().count())),
- std::make_pair(
- "ReadingParameters",
- nlohmann::json({{{"sensorPaths",
- {{{"service", "service0"}, {"path", "path0"}}}},
- {"operationType", "op0"},
- {"id", "id0"},
- {"metricMetadata", "metadata0"}},
- {{"sensorPaths",
- {{{"service", "service1"}, {"path", "path1"}}}},
- {"operationType", "op1"},
- {"id", "id1"},
- {"metricMetadata", "metadata1"}},
- {{"sensorPaths",
- {{{"service", "service2"}, {"path", "path2"}}}},
- {"operationType", "op2"},
- {"id", "id2"},
- {"metricMetadata", "metadata2"}}}))));
+ Values(std::make_pair("Version"s, nlohmann::json(3)),
+ std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
+ std::make_pair("ReportingType",
+ nlohmann::json(ReportParams().reportingType())),
+ std::make_pair("EmitsReadingsUpdate",
+ nlohmann::json(ReportParams().emitReadingUpdate())),
+ std::make_pair(
+ "LogToMetricReportsCollection",
+ nlohmann::json(ReportParams().logToMetricReportCollection())),
+ std::make_pair("Interval",
+ nlohmann::json(ReportParams().interval().count())),
+ std::make_pair(
+ "ReadingParameters",
+ nlohmann::json(
+ {{{tstring::SensorPath::str(),
+ {{"service", "service0"}, {"path", "path0"}}},
+ {tstring::OperationType::str(), OperationType::single},
+ {tstring::Id::str(), "id0"},
+ {tstring::MetricMetadata::str(), "metadata0"}},
+ {{tstring::SensorPath::str(),
+ {{"service", "service1"}, {"path", "path1"}}},
+ {tstring::OperationType::str(), OperationType::max},
+ {tstring::Id::str(), "id1"},
+ {tstring::MetricMetadata::str(), "metadata1"}},
+ {{tstring::SensorPath::str(),
+ {{"service", "service2"}, {"path", "path2"}}},
+ {tstring::OperationType::str(), OperationType::min},
+ {tstring::Id::str(), "id2"},
+ {tstring::MetricMetadata::str(), "metadata2"}}}))));
TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
{
@@ -416,8 +418,8 @@
EXPECT_THAT(readings,
ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
- std::make_tuple("aaa"s, "bbb"s, 21.7, 100u),
- std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
+ std::make_tuple("aa"s, "bb"s, 42.0, 74u),
+ std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
}
class TestReportNonOnRequestType :
@@ -493,8 +495,8 @@
EXPECT_THAT(readings,
ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
- std::make_tuple("aaa"s, "bbb"s, 21.7, 100u),
- std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
+ std::make_tuple("aa"s, "bb"s, 42.0, 74u),
+ std::make_tuple("aaa"s, "bbb"s, 100.7, 21u)));
}
class TestReportInitialization : public TestReport
diff --git a/tests/src/test_report_manager.cpp b/tests/src/test_report_manager.cpp
index 30628d6..65e48f4 100644
--- a/tests/src/test_report_manager.cpp
+++ b/tests/src/test_report_manager.cpp
@@ -5,9 +5,11 @@
#include "params/report_params.hpp"
#include "report.hpp"
#include "report_manager.hpp"
+#include "utils/conversion.hpp"
#include "utils/transform.hpp"
using namespace testing;
+using namespace std::string_literals;
using namespace std::chrono_literals;
class TestReportManager : public Test
@@ -246,6 +248,37 @@
sut->updateReport("NotAReport");
}
+class TestReportManagerWithAggregationOperationType :
+ public TestReportManager,
+ public WithParamInterface<OperationType>
+{
+ public:
+ OperationType operationType = GetParam();
+};
+
+INSTANTIATE_TEST_SUITE_P(_, TestReportManagerWithAggregationOperationType,
+ Values(OperationType::single, OperationType::max,
+ OperationType::min, OperationType::avg,
+ OperationType::sum));
+
+TEST_P(TestReportManagerWithAggregationOperationType,
+ addReportWithDifferentOperationTypes)
+{
+ reportParams.readingParameters(
+ {{{sdbusplus::message::object_path(
+ "/xyz/openbmc_project/sensors/power/p1")},
+ utils::enumToString(operationType),
+ "MetricId1",
+ "Metadata1"}});
+
+ reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
+ .WillOnce(Return(ByMove(std::move(reportMockPtr))));
+
+ auto [ec, path] = addReport(reportParams);
+ EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
+ EXPECT_THAT(path, Eq("/"s + reportParams.reportName()));
+}
+
class TestReportManagerStorage : public TestReportManager
{
public:
@@ -272,12 +305,9 @@
{
return utils::transform(params, [](const auto& item) {
return LabeledMetricParameters(
- utils::transform(std::get<0>(item),
- [](const auto& elem) {
- return LabeledSensorParameters("service",
- elem);
- }),
- std::get<1>(item), std::get<2>(item), std::get<3>(item));
+ LabeledSensorParameters("service", std::get<0>(item)),
+ utils::stringToOperationType(std::get<1>(item)),
+ std::get<2>(item), std::get<3>(item));
});
}