xref: /openbmc/telemetry/tests/src/test_metric.cpp (revision dcc4e1936173a93251a02066432bc2bcbc386240)
1 #include "helpers.hpp"
2 #include "metric.hpp"
3 #include "mocks/sensor_mock.hpp"
4 #include "params/metric_params.hpp"
5 #include "utils/conv_container.hpp"
6 #include "utils/conversion.hpp"
7 #include "utils/tstring.hpp"
8 
9 #include <gmock/gmock.h>
10 
11 using namespace testing;
12 using namespace std::chrono_literals;
13 
14 namespace tstring = utils::tstring;
15 
16 using Timestamp = uint64_t;
17 
18 class TestMetric : public Test
19 {
20   public:
21     static std::vector<std::shared_ptr<SensorMock>>
22         makeSensorMocks(size_t amount)
23     {
24         std::vector<std::shared_ptr<SensorMock>> result;
25         for (size_t i = 0; i < amount; ++i)
26         {
27             result.emplace_back(std::make_shared<NiceMock<SensorMock>>());
28         }
29         return result;
30     }
31 
32     std::shared_ptr<Metric> makeSut(const MetricParams& p)
33     {
34         return std::make_shared<Metric>(
35             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
36                 sensorMocks),
37             p.operationType(), p.id(), p.metadata(), p.collectionTimeScope(),
38             p.collectionDuration());
39     }
40 
41     MetricParams params =
42         MetricParams()
43             .id("id")
44             .metadata("metadata")
45             .operationType(OperationType::avg)
46             .collectionTimeScope(CollectionTimeScope::interval)
47             .collectionDuration(CollectionDuration(42ms));
48     std::vector<std::shared_ptr<SensorMock>> sensorMocks = makeSensorMocks(1u);
49     std::shared_ptr<Metric> sut;
50 };
51 
52 TEST_F(TestMetric, subscribesForSensorDuringInitialization)
53 {
54     sut = makeSut(params);
55 
56     EXPECT_CALL(*sensorMocks.front(),
57                 registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
58                     return a0.lock().get() == sut;
59                 })));
60 
61     sut->initialize();
62 }
63 
64 TEST_F(TestMetric, containsEmptyReadingAfterCreated)
65 {
66     sut = makeSut(params);
67 
68     ASSERT_THAT(sut->getReadings(),
69                 ElementsAre(MetricValue({"id", "metadata", 0., 0u})));
70 }
71 
72 TEST_F(TestMetric, parsesSensorMetadata)
73 {
74     nlohmann::json metadata;
75     metadata["MetricProperties"] = {"sensor1", "sensor2"};
76 
77     sensorMocks = makeSensorMocks(2);
78     sut = makeSut(params.metadata(metadata.dump()));
79 
80     EXPECT_THAT(sut->getReadings(),
81                 ElementsAre(MetricValue{"id", "sensor1", 0., 0u},
82                             MetricValue{"id", "sensor2", 0., 0u}));
83 }
84 
85 TEST_F(TestMetric, parsesSensorMetadataWhenMoreMetadataThanSensors)
86 {
87     nlohmann::json metadata;
88     metadata["MetricProperties"] = {"sensor1", "sensor2"};
89 
90     sensorMocks = makeSensorMocks(1);
91     sut = makeSut(params.metadata(metadata.dump()));
92 
93     EXPECT_THAT(sut->getReadings(),
94                 ElementsAre(MetricValue{"id", metadata.dump(), 0., 0u}));
95 }
96 
97 TEST_F(TestMetric, parsesSensorMetadataWhenMoreSensorsThanMetadata)
98 {
99     nlohmann::json metadata;
100     metadata["MetricProperties"] = {"sensor1"};
101 
102     sensorMocks = makeSensorMocks(2);
103     sut = makeSut(params.metadata(metadata.dump()));
104 
105     EXPECT_THAT(sut->getReadings(),
106                 ElementsAre(MetricValue{"id", metadata.dump(), 0., 0u},
107                             MetricValue{"id", metadata.dump(), 0., 0u}));
108 }
109 
110 class TestMetricAfterInitialization : public TestMetric
111 {
112   public:
113     void SetUp() override
114     {
115         sut = makeSut(params);
116         sut->initialize();
117     }
118 };
119 
120 TEST_F(TestMetricAfterInitialization, containsEmptyReading)
121 {
122     ASSERT_THAT(sut->getReadings(),
123                 ElementsAre(MetricValue({"id", "metadata", 0., 0u})));
124 }
125 
126 TEST_F(TestMetricAfterInitialization, updatesMetricValuesOnSensorUpdate)
127 {
128     sut->sensorUpdated(*sensorMocks.front(), Timestamp{18}, 31.2);
129 
130     ASSERT_THAT(sut->getReadings(),
131                 ElementsAre(MetricValue{"id", "metadata", 31.2, 18u}));
132 }
133 
134 TEST_F(TestMetricAfterInitialization,
135        throwsWhenUpdateIsPerformedOnUnknownSensor)
136 {
137     auto sensor = std::make_shared<StrictMock<SensorMock>>();
138     EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}), std::out_of_range);
139     EXPECT_THROW(sut->sensorUpdated(*sensor, Timestamp{10}, 20.0),
140                  std::out_of_range);
141 }
142 
143 TEST_F(TestMetricAfterInitialization, dumpsConfiguration)
144 {
145     namespace ts = utils::tstring;
146 
147     ON_CALL(*sensorMocks.front(), id())
148         .WillByDefault(Return(SensorMock::makeId("service1", "path1")));
149 
150     const auto conf = sut->dumpConfiguration();
151 
152     LabeledMetricParameters expected = {};
153     expected.at_label<ts::Id>() = "id";
154     expected.at_label<ts::MetricMetadata>() = "metadata";
155     expected.at_label<ts::OperationType>() = OperationType::avg;
156     expected.at_label<ts::CollectionTimeScope>() =
157         CollectionTimeScope::interval;
158     expected.at_label<ts::CollectionDuration>() = CollectionDuration(42ms);
159     expected.at_label<ts::SensorPath>() = {
160         LabeledSensorParameters("service1", "path1")};
161 
162     EXPECT_THAT(conf, Eq(expected));
163 }
164