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