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