diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2021-11-26 08:19:58 +0100 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2021-11-26 08:19:58 +0100 |
| commit | f70495a48646e54272783b4b709aca0396cb85f8 (patch) | |
| tree | 5e63b1f57582b3f025f1008034e4b066db0c32a6 /test | |
| parent | 9c26f52e0942e3ddc8fe90fad5da871324c66f08 (diff) | |
Create daemon module and use it from server
Need to run setup() after forking, otherwise each TaskRunner created
in setup() will dead-lock at exit as there are now two copies of
each of them but not of the threads causing the destructors to lock.
This made setup a little bit more complicated as it has to forward
the log and status to parent process but I turned out quite nice.
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_daemon.cc | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/test/test_daemon.cc b/test/test_daemon.cc new file mode 100644 index 0000000..04ba105 --- /dev/null +++ b/test/test_daemon.cc @@ -0,0 +1,146 @@ +#include "common.hh" + +#include "daemon.hh" +#include "logger.hh" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <memory> + +namespace { + +class MockDaemon : public Daemon { +public: + MOCK_METHOD(bool, setup, (Logger*), (override)); + MOCK_METHOD(bool, run, (), (override)); +}; + +class MockLogger : public Logger { +public: + void err(char const* format, ...) override { + va_list args; + va_start(args, format); + vlog("err", format, args); + va_end(args); + } + + void warn(char const* format, ...) override { + va_list args; + va_start(args, format); + vlog("warn", format, args); + va_end(args); + } + + void info(char const* format, ...) override { + va_list args; + va_start(args, format); + vlog("info", format, args); + va_end(args); + } + + void dbg(char const* format, ...) override { + va_list args; + va_start(args, format); + vlog("dbg", format, args); + va_end(args); + } + + void vlog(std::string level, char const* format, va_list args) { + if (strcmp(format, "%s") == 0) { + log(level, va_arg(args, char const*)); + } else if (strcmp(format, "%.*s") == 0) { + auto len = va_arg(args, int); + auto ptr = va_arg(args, char const*); + log(level, std::string(ptr, len)); + } else { + log(level, format); + } + } + + MOCK_METHOD(void, log, (std::string, std::string)); +}; + +class TestDaemon : public Daemon { +public: + bool setup(Logger*) override { + return false; + } + + bool run() override { + return false; + } +}; + +class FailSetupDaemon : public TestDaemon { +public: + explicit FailSetupDaemon(std::string error) + : error_(std::move(error)) {} + + bool setup(Logger* logger) override { + logger->err("%s", error_.c_str()); + return false; + } + +private: + std::string error_; +}; + +class SuccessSetupDaemon : public TestDaemon { +public: + explicit SuccessSetupDaemon(std::string success) + : success_(std::move(success)) {} + + bool setup(Logger* logger) override { + logger->info("%s", success_.c_str()); + return true; + } + +private: + std::string success_; +}; + +} // namespace + +TEST(daemon, run_in_foreground_setup_fail) { + auto daemon = std::make_unique<MockDaemon>(); + auto logger = Logger::create_null(); + EXPECT_CALL(*daemon, setup(logger.get())) + .WillOnce(testing::Return(false)); + EXPECT_FALSE(Daemon::run_in_foreground(logger.get(), std::move(daemon))); +} + +TEST(daemon, run_in_foreground_run_fail) { + auto daemon = std::make_unique<MockDaemon>(); + auto logger = Logger::create_null(); + EXPECT_CALL(*daemon, setup(logger.get())) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*daemon, run()) + .WillOnce(testing::Return(false)); + EXPECT_FALSE(Daemon::run_in_foreground(logger.get(), std::move(daemon))); +} + +TEST(daemon, run_in_foreground_run_success) { + auto daemon = std::make_unique<MockDaemon>(); + auto logger = Logger::create_null(); + EXPECT_CALL(*daemon, setup(logger.get())) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*daemon, run()) + .WillOnce(testing::Return(true)); + EXPECT_TRUE(Daemon::run_in_foreground(logger.get(), std::move(daemon))); +} + +TEST(daemon, fork_in_background_setup_fail) { + auto daemon = std::make_unique<FailSetupDaemon>("Something failed"); + MockLogger logger; + testing::Mock::AllowLeak(&logger); // Forking copies the mock. + EXPECT_CALL(logger, log("err", "Something failed")); + EXPECT_FALSE(Daemon::fork_in_background(&logger, std::move(daemon))); +} + +TEST(daemon, fork_in_background_run_fail) { + auto daemon = std::make_unique<SuccessSetupDaemon>("All good"); + MockLogger logger; + testing::Mock::AllowLeak(&logger); // Forking copies the mock. + EXPECT_CALL(logger, log("info", "All good")); + EXPECT_TRUE(Daemon::fork_in_background(&logger, std::move(daemon))); +} |
