M module-services/service-time/tests/CMakeLists.txt => module-services/service-time/tests/CMakeLists.txt +2 -0
@@ 30,4 30,6 @@ add_gtest_executable(
service-time
INCLUDE
$<TARGET_PROPERTY:service-time,INCLUDE_DIRECTORIES>
+ DEFS
+ COMMON_ALARM_OPERATIONS_TEST
)
M module-services/service-time/tests/tests-AlarmOperations.cpp => module-services/service-time/tests/tests-AlarmOperations.cpp +11 -4
@@ 16,6 16,7 @@ class MockAlarmHandler : public alarms::AlarmHandler
MOCK_METHOD(bool, handle, (const AlarmEventRecord &record), ());
MOCK_METHOD(bool, handleOff, (const AlarmEventRecord &record), ());
};
+
class MockAlarmEventsRepository : public alarms::AbstractAlarmEventsRepository
{
public:
@@ 111,12 112,18 @@ alarms::IAlarmOperations::OnUpdateAlarmProcessed universalBoolCallback = [](bool
class AlarmOperationsFixture : public ::testing::Test
{
protected:
- auto getMockedAlarmOperations(std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
- {
- return std::make_unique<alarms::AlarmOperationsCommon>(std::move(alarmRepo), timeInjector);
- }
+ std::unique_ptr<alarms::IAlarmOperations> getMockedAlarmOperations(
+ std::unique_ptr<MockAlarmEventsRepository> &alarmRepo);
};
+#if defined COMMON_ALARM_OPERATIONS_TEST
+std::unique_ptr<alarms::IAlarmOperations> AlarmOperationsFixture::getMockedAlarmOperations(
+ std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
+{
+ return std::make_unique<alarms::AlarmOperationsCommon>(std::move(alarmRepo), timeInjector);
+}
+#endif
+
constexpr auto defName = "";
constexpr auto defDuration = 60;
constexpr auto defAllDay = false;
M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +1 -1
@@ 68,7 68,7 @@ int main()
systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
systemServices.emplace_back(sys::CreatorFor<ServiceAudio>());
systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
- systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>());
+ systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>(alarms::AlarmOperationsFactory{}));
systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>());
systemServices.emplace_back(sys::CreatorFor<service::gui::ServiceGUI>());
M products/BellHybrid/services/CMakeLists.txt => products/BellHybrid/services/CMakeLists.txt +2 -0
@@ 1,3 1,5 @@
+module_is_test_entity(bell-services)
+
add_subdirectory(appmgr)
add_subdirectory(evtmgr)
add_subdirectory(db)
M products/BellHybrid/services/time/AlarmOperations.cpp => products/BellHybrid/services/time/AlarmOperations.cpp +19 -19
@@ 9,7 9,7 @@ namespace alarms
{
namespace
{
- class MockedPreWakeUpSettingsProvider : public PreWakeUpSettingsProvider
+ class FakePreWakeUpSettingsProvider : public PreWakeUpSettingsProvider
{
public:
auto getChimeSettings() -> Settings override
@@ 29,7 29,7 @@ namespace alarms
std::unique_ptr<AbstractAlarmEventsRepository> &&alarmEventsRepo,
IAlarmOperations::GetCurrentTime getCurrentTimeCallback) const
{
- auto settingsProvider = std::make_unique<MockedPreWakeUpSettingsProvider>();
+ auto settingsProvider = std::make_unique<FakePreWakeUpSettingsProvider>();
auto alarmOperations = std::make_unique<AlarmOperations>(
std::move(alarmEventsRepo), getCurrentTimeCallback, std::move(settingsProvider));
alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::PreWakeUpChime,
@@ 43,16 43,16 @@ namespace alarms
GetCurrentTime getCurrentTimeCallback,
std::unique_ptr<PreWakeUpSettingsProvider> &&settingsProvider)
: AlarmOperationsCommon{std::move(alarmEventsRepo), std::move(getCurrentTimeCallback)},
- settingsProvider{std::move(settingsProvider)}
+ preWakeUp(std::move(settingsProvider))
{}
void AlarmOperations::minuteUpdated(TimePoint now)
{
AlarmOperationsCommon::minuteUpdated(now);
- processPreWakeUpEvents(now);
+ processPreWakeUp(now);
}
- void AlarmOperations::processPreWakeUpEvents(TimePoint now)
+ void AlarmOperations::processPreWakeUp(TimePoint now)
{
if (nextSingleEvents.empty()) {
return;
@@ 63,30 63,30 @@ namespace alarms
return;
}
- PreWakeUpHandler handler{settingsProvider.get()};
- preWakeUp(nextEvent, handler.handle(now, nextEvent));
- }
-
- void AlarmOperations::preWakeUp(const SingleEventRecord &event, PreWakeUpHandler::Result handleResult)
- {
- if (!handleResult.timeForChime && !handleResult.timeForFrontlight) {
+ const auto decision = preWakeUp.decide(now, nextEvent);
+ if (!decision.timeForChime && !decision.timeForFrontlight) {
return;
}
+ handlePreWakeUp(nextEvent, decision);
+ }
+ void AlarmOperations::handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision)
+ {
if (auto alarmEventPtr = std::dynamic_pointer_cast<AlarmEventRecord>(event.parent); alarmEventPtr) {
- if (handleResult.timeForChime) {
+ if (decision.timeForChime) {
handleAlarmEvent(alarmEventPtr, alarms::AlarmType::PreWakeUpChime, true);
}
- if (handleResult.timeForFrontlight) {
+ if (decision.timeForFrontlight) {
handleAlarmEvent(alarmEventPtr, alarms::AlarmType::PreWakeUpFrontlight, true);
}
}
}
- PreWakeUpHandler::PreWakeUpHandler(PreWakeUpSettingsProvider *settingsProvider) : settingsProvider{settingsProvider}
+ PreWakeUp::PreWakeUp(std::unique_ptr<PreWakeUpSettingsProvider> &&settingsProvider)
+ : settingsProvider{std::move(settingsProvider)}
{}
- auto PreWakeUpHandler::handle(TimePoint now, const SingleEventRecord &event) -> Result
+ auto PreWakeUp::decide(TimePoint now, const SingleEventRecord &event) -> Decision
{
const auto chimeSettings = settingsProvider->getChimeSettings();
const auto frontlightSettings = settingsProvider->getFrontlightSettings();
@@ 95,9 95,9 @@ namespace alarms
return {isTimeForChime, isTimeForFrontlight};
}
- auto PreWakeUpHandler::isTimeForPreWakeUp(TimePoint now,
- const SingleEventRecord &event,
- PreWakeUpSettingsProvider::Settings settings) -> bool
+ auto PreWakeUp::isTimeForPreWakeUp(TimePoint now,
+ const SingleEventRecord &event,
+ PreWakeUpSettingsProvider::Settings settings) -> bool
{
const auto expectedAlarmStart = std::chrono::floor<std::chrono::minutes>(now) + settings.timeBeforeAlarm;
return settings.enabled && std::chrono::floor<std::chrono::minutes>(event.startDate) == expectedAlarmStart;
M products/BellHybrid/services/time/CMakeLists.txt => products/BellHybrid/services/time/CMakeLists.txt +4 -0
@@ 22,3 22,7 @@ target_link_libraries(bell-time
PUBLIC
service-time
)
+
+if (${ENABLE_TESTS})
+ add_subdirectory(tests)
+endif ()
M products/BellHybrid/services/time/include/time/AlarmOperations.hpp => products/BellHybrid/services/time/include/time/AlarmOperations.hpp +8 -8
@@ 30,24 30,24 @@ namespace alarms
virtual auto getFrontlightSettings() -> Settings = 0;
};
- class PreWakeUpHandler
+ class PreWakeUp
{
public:
- struct Result
+ struct Decision
{
bool timeForChime;
bool timeForFrontlight;
};
- explicit PreWakeUpHandler(PreWakeUpSettingsProvider *settingsProvider);
- auto handle(TimePoint now, const SingleEventRecord &event) -> Result;
+ explicit PreWakeUp(std::unique_ptr<PreWakeUpSettingsProvider> &&settingsProvider);
+ auto decide(TimePoint now, const SingleEventRecord &event) -> Decision;
private:
auto isTimeForPreWakeUp(TimePoint now,
const SingleEventRecord &event,
PreWakeUpSettingsProvider::Settings settings) -> bool;
- PreWakeUpSettingsProvider *settingsProvider;
+ std::unique_ptr<PreWakeUpSettingsProvider> settingsProvider;
};
class AlarmOperations : public AlarmOperationsCommon
@@ 58,11 58,11 @@ namespace alarms
std::unique_ptr<PreWakeUpSettingsProvider> &&settingsProvider);
void minuteUpdated(TimePoint now) override;
+ void processPreWakeUp(TimePoint now);
private:
- void processPreWakeUpEvents(TimePoint now);
- void preWakeUp(const SingleEventRecord &event, PreWakeUpHandler::Result handleResult);
+ void handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision);
- std::unique_ptr<PreWakeUpSettingsProvider> settingsProvider;
+ PreWakeUp preWakeUp;
};
} // namespace alarms
A products/BellHybrid/services/time/tests/CMakeLists.txt => products/BellHybrid/services/time/tests/CMakeLists.txt +12 -0
@@ 0,0 1,12 @@
+add_gtest_executable(
+ NAME
+ service-time-bell-alarm-operations
+ SRCS
+ test-BellAlarmOperations.cpp
+ LIBS
+ module-sys
+ bell::time
+ INCLUDE
+ $<TARGET_PROPERTY:bell::time,INCLUDE_DIRECTORIES>
+ $<TARGET_PROPERTY:service-time,SOURCE_DIR>
+)
A products/BellHybrid/services/time/tests/test-BellAlarmOperations.cpp => products/BellHybrid/services/time/tests/test-BellAlarmOperations.cpp +236 -0
@@ 0,0 1,236 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <AlarmOperations.hpp>
+#include <module-db/Interface/AlarmEventRecord.hpp>
+
+#include <products/BellHybrid/services/time/include/time/AlarmOperations.hpp>
+
+#include <gtest/gtest.h>
+
+// Included a .cpp file with AlarmOperations tests for the common part (the base class' implementation).
+// It needs to be built into this test in order to test the possible regression introduced by
+// the Bell-specific AlarmOperations class.
+// Generally, this should not be solved this way in other cases.
+#include <service-time/tests/tests-AlarmOperations.cpp>
+
+namespace
+{
+ class MockedPreWakeUpSettingsProvider : public alarms::PreWakeUpSettingsProvider
+ {
+ public:
+ void setChimeSettings(bool enabled, std::chrono::minutes minutes)
+ {
+ chimeSettings = Settings{enabled, minutes};
+ }
+
+ void setFrontlightSettings(bool enabled, std::chrono::minutes minutes)
+ {
+ frontlightSettings = Settings{enabled, minutes};
+ }
+
+ auto getChimeSettings() -> Settings override
+ {
+ return chimeSettings;
+ }
+
+ auto getFrontlightSettings() -> Settings override
+ {
+ return frontlightSettings;
+ }
+
+ private:
+ Settings chimeSettings{true, std::chrono::minutes{5}};
+ Settings frontlightSettings{true, std::chrono::minutes{2}};
+ };
+
+ std::unique_ptr<alarms::IAlarmOperations> getMockedAlarmOperations(
+ std::unique_ptr<MockAlarmEventsRepository> &alarmRepo,
+ std::unique_ptr<alarms::PreWakeUpSettingsProvider> &&settingsProvider)
+ {
+ return std::make_unique<alarms::AlarmOperations>(
+ std::move(alarmRepo), timeInjector, std::move(settingsProvider));
+ }
+} // namespace
+
+// This function replaces the `getMockedAlarmOperations` function from `service-time/tests/tests-AlarmOperations.cpp`
+std::unique_ptr<alarms::IAlarmOperations> AlarmOperationsFixture::getMockedAlarmOperations(
+ std::unique_ptr<MockAlarmEventsRepository> &alarmRepo)
+{
+ return ::getMockedAlarmOperations(alarmRepo, std::make_unique<MockedPreWakeUpSettingsProvider>());
+}
+
+TEST(PreWakeUp, TooEarlyForPreWakeUp)
+{
+ alarms::PreWakeUp preWakeUp(std::make_unique<MockedPreWakeUpSettingsProvider>());
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:06:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_FALSE(decision.timeForChime);
+ ASSERT_FALSE(decision.timeForFrontlight);
+}
+
+TEST(PreWakeUp, TimeToPlayChime)
+{
+ alarms::PreWakeUp preWakeUp(std::make_unique<MockedPreWakeUpSettingsProvider>());
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:05:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_TRUE(decision.timeForChime);
+ ASSERT_FALSE(decision.timeForFrontlight);
+}
+
+TEST(PreWakeUp, TimeToPlayChimeButDisabled)
+{
+ auto settingsProvider = std::make_unique<MockedPreWakeUpSettingsProvider>();
+ settingsProvider->setChimeSettings(false, std::chrono::minutes::zero());
+ alarms::PreWakeUp preWakeUp(std::move(settingsProvider));
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:05:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_FALSE(decision.timeForChime);
+ ASSERT_FALSE(decision.timeForFrontlight);
+}
+
+TEST(PreWakeUp, TimeToLightFrontlight)
+{
+ alarms::PreWakeUp preWakeUp(std::make_unique<MockedPreWakeUpSettingsProvider>());
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:02:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_FALSE(decision.timeForChime);
+ ASSERT_TRUE(decision.timeForFrontlight);
+}
+
+TEST(PreWakeUp, TimeToLightFrontlightButDisabled)
+{
+ auto settingsProvider = std::make_unique<MockedPreWakeUpSettingsProvider>();
+ settingsProvider->setFrontlightSettings(false, std::chrono::minutes::zero());
+ alarms::PreWakeUp preWakeUp(std::move(settingsProvider));
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:02:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_FALSE(decision.timeForChime);
+ ASSERT_FALSE(decision.timeForFrontlight);
+}
+
+TEST(PreWakeUp, TimePointIsNotRoundedToFullMinute)
+{
+ alarms::PreWakeUp preWakeUp(std::make_unique<MockedPreWakeUpSettingsProvider>());
+ auto event = AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 05:05:01"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze);
+ const auto nextEvent = event.getNextSingleEvent(TimePointFromString("2022-11-11 05:00:00"));
+ EXPECT_TRUE(static_cast<EventInfo>(nextEvent).isValid());
+
+ const auto decision = preWakeUp.decide(timeInjector(), nextEvent);
+ ASSERT_TRUE(decision.timeForChime);
+ ASSERT_FALSE(decision.timeForFrontlight);
+}
+
+class BellAlarmOperationsFixture : public ::testing::Test
+{
+ protected:
+ void SetUp() override
+ {
+ auto alarmRepoMock = std::make_unique<MockAlarmEventsRepository>();
+ alarmRepoMock->nextRecords.push_back(AlarmEventRecord(1,
+ defName,
+ TimePointFromString("2022-11-11 09:00:00"),
+ defDuration,
+ defAllDay,
+ defRRule,
+ defMusic,
+ defEnabled,
+ defSnooze));
+ chimeHandler = std::make_shared<MockAlarmHandler>();
+ frontlightHandler = std::make_shared<MockAlarmHandler>();
+
+ alarmOperations =
+ ::getMockedAlarmOperations(alarmRepoMock, std::make_unique<MockedPreWakeUpSettingsProvider>());
+ alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::PreWakeUpChime, chimeHandler);
+ alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::PreWakeUpFrontlight, frontlightHandler);
+ alarmOperations->updateEventsCache(TimePointFromString("2022-11-11 08:00:00"));
+ }
+
+ std::unique_ptr<alarms::IAlarmOperations> alarmOperations;
+ std::shared_ptr<MockAlarmHandler> chimeHandler;
+ std::shared_ptr<MockAlarmHandler> frontlightHandler;
+};
+
+TEST_F(BellAlarmOperationsFixture, PreWakeUp_TooEarlyToHandle)
+{
+ EXPECT_CALL(*chimeHandler, handle(testing::_)).Times(0);
+ EXPECT_CALL(*frontlightHandler, handle(testing::_)).Times(0);
+ alarmOperations->minuteUpdated(TimePointFromString("2022-11-11 08:54:00"));
+}
+
+TEST_F(BellAlarmOperationsFixture, PreWakeUp_TimeToPlayChime)
+{
+ EXPECT_CALL(*chimeHandler, handle(testing::_)).Times(1);
+ EXPECT_CALL(*frontlightHandler, handle(testing::_)).Times(0);
+ alarmOperations->minuteUpdated(TimePointFromString("2022-11-11 08:55:00"));
+}
+
+TEST_F(BellAlarmOperationsFixture, PreWakeUp_TimeToLightFrontlight)
+{
+ EXPECT_CALL(*chimeHandler, handle(testing::_)).Times(0);
+ EXPECT_CALL(*frontlightHandler, handle(testing::_)).Times(1);
+ alarmOperations->minuteUpdated(TimePointFromString("2022-11-11 08:58:00"));
+}