1 #include "dbus_environment.hpp" 2 #include "mocks/json_storage_mock.hpp" 3 #include "mocks/report_factory_mock.hpp" 4 #include "params/report_params.hpp" 5 #include "report.hpp" 6 #include "report_manager.hpp" 7 #include "utils/transform.hpp" 8 9 using namespace testing; 10 using namespace std::chrono_literals; 11 12 class TestReportManager : public Test 13 { 14 public: 15 ReportParams reportParams; 16 17 std::unique_ptr<ReportFactoryMock> reportFactoryMockPtr = 18 std::make_unique<StrictMock<ReportFactoryMock>>(); 19 ReportFactoryMock& reportFactoryMock = *reportFactoryMockPtr; 20 21 std::unique_ptr<StorageMock> storageMockPtr = 22 std::make_unique<NiceMock<StorageMock>>(); 23 StorageMock& storageMock = *storageMockPtr; 24 25 std::unique_ptr<ReportManager> sut; 26 27 MockFunction<void(std::string)> checkPoint; 28 29 void SetUp() override 30 { 31 sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr), 32 std::move(storageMockPtr), 33 DbusEnvironment::getObjServer()); 34 } 35 36 void TearDown() override 37 { 38 DbusEnvironment::synchronizeIoc(); 39 } 40 41 std::pair<boost::system::error_code, std::string> 42 addReport(const ReportParams& params) 43 { 44 std::promise<std::pair<boost::system::error_code, std::string>> 45 addReportPromise; 46 DbusEnvironment::getBus()->async_method_call( 47 [&addReportPromise](boost::system::error_code ec, 48 const std::string& path) { 49 addReportPromise.set_value({ec, path}); 50 }, 51 DbusEnvironment::serviceName(), ReportManager::reportManagerPath, 52 ReportManager::reportManagerIfaceName, "AddReport", 53 params.reportName(), params.reportingType(), 54 params.emitReadingUpdate(), params.logToMetricReportCollection(), 55 static_cast<uint64_t>(params.interval().count()), 56 params.readingParameters()); 57 return DbusEnvironment::waitForFuture(addReportPromise.get_future()); 58 } 59 60 template <class T> 61 static T getProperty(std::string property) 62 { 63 std::promise<T> propertyPromise; 64 sdbusplus::asio::getProperty<T>( 65 *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), 66 ReportManager::reportManagerPath, 67 ReportManager::reportManagerIfaceName, property, 68 [&propertyPromise](boost::system::error_code ec) { 69 EXPECT_THAT(static_cast<bool>(ec), ::testing::Eq(false)); 70 propertyPromise.set_value(T{}); 71 }, 72 [&propertyPromise](T t) { propertyPromise.set_value(t); }); 73 return DbusEnvironment::waitForFuture(propertyPromise.get_future()); 74 } 75 }; 76 77 TEST_F(TestReportManager, minInterval) 78 { 79 EXPECT_THAT(getProperty<uint64_t>("MinInterval"), 80 Eq(static_cast<uint64_t>(ReportManager::minInterval.count()))); 81 } 82 83 TEST_F(TestReportManager, maxReports) 84 { 85 EXPECT_THAT(getProperty<uint32_t>("MaxReports"), 86 Eq(ReportManager::maxReports)); 87 } 88 89 TEST_F(TestReportManager, addReport) 90 { 91 auto reportMockPtr = 92 std::make_unique<NiceMock<ReportMock>>(reportParams.reportName()); 93 auto& reportMock = *reportMockPtr; 94 95 EXPECT_CALL(reportFactoryMock, 96 make(_, reportParams.reportName(), reportParams.reportingType(), 97 reportParams.emitReadingUpdate(), 98 reportParams.logToMetricReportCollection(), 99 reportParams.interval(), reportParams.readingParameters(), 100 Ref(*sut), Ref(storageMock))) 101 .WillOnce(Return(ByMove(std::move(reportMockPtr)))); 102 103 auto [ec, path] = addReport(reportParams); 104 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 105 EXPECT_THAT(path, Eq(reportMock.getPath())); 106 } 107 108 TEST_F(TestReportManager, DISABLED_failToAddReportTwice) 109 { 110 EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _)); 111 112 addReport(reportParams); 113 114 auto [ec, path] = addReport(reportParams); 115 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists)); 116 EXPECT_THAT(path, Eq(std::string())); 117 } 118 119 TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidInterval) 120 { 121 EXPECT_CALL(reportFactoryMock, make).Times(0); 122 123 reportParams.interval(reportParams.interval() - 1ms); 124 125 auto [ec, path] = addReport(reportParams); 126 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument)); 127 EXPECT_THAT(path, Eq(std::string())); 128 } 129 130 TEST_F(TestReportManager, DISABLED_failToAddReportWhenMaxReportIsReached) 131 { 132 EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _)) 133 .Times(ReportManager::maxReports); 134 135 for (size_t i = 0; i < ReportManager::maxReports; i++) 136 { 137 reportParams.reportName(reportParams.reportName() + std::to_string(i)); 138 139 auto [ec, path] = addReport(reportParams); 140 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 141 } 142 143 reportParams.reportName(reportParams.reportName() + 144 std::to_string(ReportManager::maxReports)); 145 auto [ec, path] = addReport(reportParams); 146 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open)); 147 EXPECT_THAT(path, Eq(std::string())); 148 } 149 150 TEST_F(TestReportManager, removeReport) 151 { 152 auto reportMockPtr = 153 std::make_unique<NiceMock<ReportMock>>(reportParams.reportName()); 154 auto& reportMock = *reportMockPtr; 155 156 { 157 InSequence seq; 158 EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _)) 159 .WillOnce(Return(ByMove(std::move(reportMockPtr)))); 160 EXPECT_CALL(reportMock, Die()); 161 EXPECT_CALL(checkPoint, Call("end")); 162 } 163 164 addReport(reportParams); 165 sut->removeReport(&reportMock); 166 checkPoint.Call("end"); 167 } 168 169 TEST_F(TestReportManager, removingReportThatIsNotInContainerHasNoEffect) 170 { 171 auto reportMockPtr = 172 std::make_unique<NiceMock<ReportMock>>(reportParams.reportName()); 173 auto& reportMock = *reportMockPtr; 174 175 { 176 InSequence seq; 177 EXPECT_CALL(checkPoint, Call("end")); 178 EXPECT_CALL(reportMock, Die()); 179 } 180 181 sut->removeReport(&reportMock); 182 checkPoint.Call("end"); 183 } 184 185 TEST_F(TestReportManager, removingSameReportTwiceHasNoSideEffect) 186 { 187 auto reportMockPtr = 188 std::make_unique<NiceMock<ReportMock>>(reportParams.reportName()); 189 auto& reportMock = *reportMockPtr; 190 191 { 192 InSequence seq; 193 EXPECT_CALL(reportFactoryMock, 194 make(_, reportParams.reportName(), _, _, _, _, _, _, _)) 195 .WillOnce(Return(ByMove(std::move(reportMockPtr)))); 196 EXPECT_CALL(reportMock, Die()); 197 EXPECT_CALL(checkPoint, Call("end")); 198 } 199 200 addReport(reportParams); 201 sut->removeReport(&reportMock); 202 sut->removeReport(&reportMock); 203 checkPoint.Call("end"); 204 } 205 206 class TestReportManagerStorage : public TestReportManager 207 { 208 public: 209 using FilePath = interfaces::JsonStorage::FilePath; 210 using DirectoryPath = interfaces::JsonStorage::DirectoryPath; 211 212 void SetUp() override 213 { 214 ON_CALL(storageMock, list()) 215 .WillByDefault(Return(std::vector<FilePath>{FilePath("report1")})); 216 ON_CALL(storageMock, load(FilePath("report1"))) 217 .WillByDefault(Return(data)); 218 } 219 220 void makeReportManager() 221 { 222 sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr), 223 std::move(storageMockPtr), 224 DbusEnvironment::getObjServer()); 225 } 226 227 nlohmann::json data = nlohmann::json{ 228 {"Version", Report::reportVersion}, 229 {"Name", reportParams.reportName()}, 230 {"ReportingType", reportParams.reportingType()}, 231 {"EmitsReadingsUpdate", reportParams.emitReadingUpdate()}, 232 {"LogToMetricReportsCollection", 233 reportParams.logToMetricReportCollection()}, 234 {"Interval", reportParams.interval().count()}, 235 {"ReadingParameters", 236 utils::transform(reportParams.readingParameters(), 237 [](const auto& item) { 238 return LabeledReadingParameter::to_json(item); 239 })}}; 240 }; 241 242 TEST_F(TestReportManagerStorage, reportManagerCtorAddReportFromStorage) 243 { 244 EXPECT_CALL(reportFactoryMock, 245 make(_, reportParams.reportName(), reportParams.reportingType(), 246 reportParams.emitReadingUpdate(), 247 reportParams.logToMetricReportCollection(), 248 reportParams.interval(), reportParams.readingParameters(), 249 _, Ref(storageMock))); 250 251 makeReportManager(); 252 } 253 254 TEST_F(TestReportManagerStorage, 255 reportManagerCtorRemoveFileIfVersionDoesNotMatch) 256 { 257 data["Version"] = Report::reportVersion - 1; 258 259 ON_CALL(storageMock, load(FilePath("report1"))).WillByDefault(Return(data)); 260 EXPECT_CALL(storageMock, remove(FilePath("report1"))); 261 262 makeReportManager(); 263 } 264 265 TEST_F(TestReportManagerStorage, 266 reportManagerCtorRemoveFileIfIntervalHasWrongType) 267 { 268 data["Interval"] = "1000"; 269 270 ON_CALL(storageMock, load(FilePath("report1"))).WillByDefault(Return(data)); 271 EXPECT_CALL(storageMock, remove(FilePath("report1"))); 272 273 makeReportManager(); 274 } 275