Compare commits
10 Commits
d0f0955c47
...
c2fb269d40
Author | SHA1 | Date | |
---|---|---|---|
c2fb269d40 | |||
8a783c87a4 | |||
281f70adb4 | |||
a3043963da | |||
aa73fb50a5 | |||
782171268a | |||
1aa14f541e | |||
295bb7c5f0 | |||
32fc72824b | |||
e6d9d2205d |
@ -17,6 +17,7 @@ target_sources(nf7_core
|
|||||||
luajit/lambda.hh
|
luajit/lambda.hh
|
||||||
luajit/thread.hh
|
luajit/thread.hh
|
||||||
clock.hh
|
clock.hh
|
||||||
|
logger.hh
|
||||||
version.hh
|
version.hh
|
||||||
)
|
)
|
||||||
|
|
||||||
|
29
core/logger.hh
Normal file
29
core/logger.hh
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "iface/common/exception.hh"
|
||||||
|
#include "iface/subsys/logger.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace nf7::core {
|
||||||
|
|
||||||
|
class NullLogger : public subsys::Logger {
|
||||||
|
public:
|
||||||
|
static const std::shared_ptr<NullLogger>& instance()
|
||||||
|
try {
|
||||||
|
static const auto kInstance = std::make_shared<NullLogger>();
|
||||||
|
return kInstance;
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
throw Exception {"memory shortage"};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
NullLogger() noexcept : subsys::Logger("nf7::core::NullLogger") { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Push(const Item&) noexcept override { }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nf7::core
|
@ -14,13 +14,10 @@
|
|||||||
|
|
||||||
#include "iface/common/exception.hh"
|
#include "iface/common/exception.hh"
|
||||||
#include "iface/common/task.hh"
|
#include "iface/common/task.hh"
|
||||||
#include "iface/subsys/clock.hh"
|
|
||||||
#include "iface/subsys/concurrency.hh"
|
#include "iface/subsys/concurrency.hh"
|
||||||
#include "iface/subsys/parallelism.hh"
|
#include "iface/subsys/parallelism.hh"
|
||||||
#include "iface/env.hh"
|
#include "iface/env.hh"
|
||||||
|
|
||||||
#include "core/clock.hh"
|
|
||||||
|
|
||||||
namespace nf7::core::luajit::test {
|
namespace nf7::core::luajit::test {
|
||||||
|
|
||||||
class ContextFixture : public ::testing::TestWithParam<Context::Kind> {
|
class ContextFixture : public ::testing::TestWithParam<Context::Kind> {
|
||||||
@ -97,7 +94,6 @@ class ContextFixture : public ::testing::TestWithParam<Context::Kind> {
|
|||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
syncq_ = std::make_shared<SimpleTaskQueue<SyncTask>>();
|
syncq_ = std::make_shared<SimpleTaskQueue<SyncTask>>();
|
||||||
asyncq_ = std::make_shared<SimpleTaskQueue<AsyncTask>>();
|
asyncq_ = std::make_shared<SimpleTaskQueue<AsyncTask>>();
|
||||||
clock_ = std::make_shared<Clock>();
|
|
||||||
|
|
||||||
env_.emplace(SimpleEnv::FactoryMap {
|
env_.emplace(SimpleEnv::FactoryMap {
|
||||||
{
|
{
|
||||||
@ -112,11 +108,6 @@ class ContextFixture : public ::testing::TestWithParam<Context::Kind> {
|
|||||||
WrappedTaskQueue<subsys::Parallelism>>(asyncq_);
|
WrappedTaskQueue<subsys::Parallelism>>(asyncq_);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
typeid(subsys::Clock), [this](auto&) {
|
|
||||||
return clock_;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
typeid(Context), [this](auto& env) {
|
typeid(Context), [this](auto& env) {
|
||||||
return Context::Create(env, GetParam());
|
return Context::Create(env, GetParam());
|
||||||
@ -156,7 +147,6 @@ class ContextFixture : public ::testing::TestWithParam<Context::Kind> {
|
|||||||
protected:
|
protected:
|
||||||
std::shared_ptr<SimpleTaskQueue<SyncTask>> syncq_;
|
std::shared_ptr<SimpleTaskQueue<SyncTask>> syncq_;
|
||||||
std::shared_ptr<SimpleTaskQueue<AsyncTask>> asyncq_;
|
std::shared_ptr<SimpleTaskQueue<AsyncTask>> asyncq_;
|
||||||
std::shared_ptr<Clock> clock_;
|
|
||||||
std::optional<SimpleEnv> env_;
|
std::optional<SimpleEnv> env_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -30,6 +30,10 @@ class Lambda::Thread : public luajit::Thread {
|
|||||||
}
|
}
|
||||||
void onAborted(TaskContext& lua) noexcept override {
|
void onAborted(TaskContext& lua) noexcept override {
|
||||||
if (auto la = la_.lock()) {
|
if (auto la = la_.lock()) {
|
||||||
|
if (auto logger = la->logger_) {
|
||||||
|
const auto msg = lua_tostring(*lua, -1);
|
||||||
|
logger->Error(msg);
|
||||||
|
}
|
||||||
++la->abort_count_;
|
++la->abort_count_;
|
||||||
TryResume(lua, la);
|
TryResume(lua, la);
|
||||||
}
|
}
|
||||||
@ -138,9 +142,14 @@ void Lambda::PushLuaContextObject(TaskContext& lua) noexcept {
|
|||||||
|
|
||||||
lua_pushcfunction(*lua, [](auto L) {
|
lua_pushcfunction(*lua, [](auto L) {
|
||||||
const auto la = self(L);
|
const auto la = self(L);
|
||||||
|
if (nullptr == la->clock_) {
|
||||||
|
return luaL_error(L, "clock is not installed in the environment");
|
||||||
|
}
|
||||||
|
|
||||||
const auto wla = std::weak_ptr<Lambda> {la};
|
const auto wla = std::weak_ptr<Lambda> {la};
|
||||||
const auto dur = luaL_checkinteger(L, 2);
|
const auto dur = luaL_checkinteger(L, 2);
|
||||||
const auto after = la->clock_->now() + dur * 1ms;
|
const auto after = la->clock_->now() + dur * 1ms;
|
||||||
|
|
||||||
la->lua_->Push(Task {after, [wla](auto& lua) {
|
la->lua_->Push(Task {after, [wla](auto& lua) {
|
||||||
if (auto la = wla.lock()) {
|
if (auto la = wla.lock()) {
|
||||||
assert(la->thread_);
|
assert(la->thread_);
|
||||||
@ -150,6 +159,32 @@ void Lambda::PushLuaContextObject(TaskContext& lua) noexcept {
|
|||||||
return lua_yield(L, 0);
|
return lua_yield(L, 0);
|
||||||
});
|
});
|
||||||
lua_setfield(*lua, -2, "sleep");
|
lua_setfield(*lua, -2, "sleep");
|
||||||
|
|
||||||
|
static const auto logFunc = []<subsys::Logger::Level lv>(auto L) {
|
||||||
|
const auto la = self(L);
|
||||||
|
const auto contents = luaL_checkstring(L, 2);
|
||||||
|
la->logger_->Push(subsys::Logger::Item {lv, contents});
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
lua_pushcfunction(*lua, [](auto L) {
|
||||||
|
return logFunc.operator()<subsys::Logger::kTrace>(L);
|
||||||
|
});
|
||||||
|
lua_setfield(*lua, -2, "trace");
|
||||||
|
|
||||||
|
lua_pushcfunction(*lua, [](auto L) {
|
||||||
|
return logFunc.operator()<subsys::Logger::kInfo>(L);
|
||||||
|
});
|
||||||
|
lua_setfield(*lua, -2, "info");
|
||||||
|
|
||||||
|
lua_pushcfunction(*lua, [](auto L) {
|
||||||
|
return logFunc.operator()<subsys::Logger::kWarn>(L);
|
||||||
|
});
|
||||||
|
lua_setfield(*lua, -2, "warn");
|
||||||
|
|
||||||
|
lua_pushcfunction(*lua, [](auto L) {
|
||||||
|
return logFunc.operator()<subsys::Logger::kError>(L);
|
||||||
|
});
|
||||||
|
lua_setfield(*lua, -2, "error");
|
||||||
}
|
}
|
||||||
lua_setfield(*lua, -2, "__index");
|
lua_setfield(*lua, -2, "__index");
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,13 @@
|
|||||||
|
|
||||||
#include "iface/subsys/clock.hh"
|
#include "iface/subsys/clock.hh"
|
||||||
#include "iface/subsys/concurrency.hh"
|
#include "iface/subsys/concurrency.hh"
|
||||||
|
#include "iface/subsys/logger.hh"
|
||||||
#include "iface/env.hh"
|
#include "iface/env.hh"
|
||||||
#include "iface/lambda.hh"
|
#include "iface/lambda.hh"
|
||||||
|
|
||||||
#include "core/luajit/context.hh"
|
#include "core/luajit/context.hh"
|
||||||
#include "core/luajit/thread.hh"
|
#include "core/luajit/thread.hh"
|
||||||
|
#include "core/logger.hh"
|
||||||
|
|
||||||
namespace nf7::core::luajit {
|
namespace nf7::core::luajit {
|
||||||
|
|
||||||
@ -23,8 +25,9 @@ class Lambda :
|
|||||||
public:
|
public:
|
||||||
explicit Lambda(nf7::Env& env, const std::shared_ptr<luajit::Value>& func)
|
explicit Lambda(nf7::Env& env, const std::shared_ptr<luajit::Value>& func)
|
||||||
: LambdaBase(),
|
: LambdaBase(),
|
||||||
clock_(env.Get<subsys::Clock>()),
|
clock_(env.GetOr<subsys::Clock>()),
|
||||||
concurrency_(env.Get<subsys::Concurrency>()),
|
concurrency_(env.Get<subsys::Concurrency>()),
|
||||||
|
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())),
|
||||||
lua_(env.Get<luajit::Context>()),
|
lua_(env.Get<luajit::Context>()),
|
||||||
func_(func) { }
|
func_(func) { }
|
||||||
|
|
||||||
@ -43,6 +46,7 @@ class Lambda :
|
|||||||
private:
|
private:
|
||||||
const std::shared_ptr<subsys::Clock> clock_;
|
const std::shared_ptr<subsys::Clock> clock_;
|
||||||
const std::shared_ptr<subsys::Concurrency> concurrency_;
|
const std::shared_ptr<subsys::Concurrency> concurrency_;
|
||||||
|
const std::shared_ptr<subsys::Logger> logger_;
|
||||||
|
|
||||||
const std::shared_ptr<Context> lua_;
|
const std::shared_ptr<Context> lua_;
|
||||||
const std::shared_ptr<Value> func_;
|
const std::shared_ptr<Value> func_;
|
||||||
|
@ -6,9 +6,13 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "iface/subsys/clock.hh"
|
||||||
|
|
||||||
#include "core/luajit/context.hh"
|
#include "core/luajit/context.hh"
|
||||||
|
#include "core/clock.hh"
|
||||||
|
|
||||||
#include "iface/common/observer_test.hh"
|
#include "iface/common/observer_test.hh"
|
||||||
|
#include "iface/subsys/logger_test.hh"
|
||||||
|
|
||||||
#include "core/luajit/context_test.hh"
|
#include "core/luajit/context_test.hh"
|
||||||
|
|
||||||
@ -36,10 +40,15 @@ class LuaJIT_Lambda : public nf7::core::luajit::test::ContextFixture {
|
|||||||
void Expect(const char* script,
|
void Expect(const char* script,
|
||||||
const std::vector<nf7::Value>& in,
|
const std::vector<nf7::Value>& in,
|
||||||
uint32_t expectExit = 1, uint32_t expectAbort = 0,
|
uint32_t expectExit = 1, uint32_t expectAbort = 0,
|
||||||
const std::vector<nf7::Value>& out = {}) {
|
const std::vector<nf7::Value>& out = {},
|
||||||
|
nf7::Env* env = nullptr) {
|
||||||
|
if (nullptr == env) {
|
||||||
|
env = &*env_;
|
||||||
|
}
|
||||||
|
|
||||||
auto func = Compile(script);
|
auto func = Compile(script);
|
||||||
|
|
||||||
auto sut = std::make_shared<nf7::core::luajit::Lambda>(*env_, func);
|
auto sut = std::make_shared<nf7::core::luajit::Lambda>(*env, func);
|
||||||
for (const auto& v : in) {
|
for (const auto& v : in) {
|
||||||
sut->taker()->Take(v);
|
sut->taker()->Take(v);
|
||||||
}
|
}
|
||||||
@ -133,20 +142,71 @@ TEST_P(LuaJIT_Lambda, CtxMultiSend) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(LuaJIT_Lambda, CtxSleep) {
|
TEST_P(LuaJIT_Lambda, CtxSleep) {
|
||||||
clock_->Tick();
|
const auto clock = std::make_shared<nf7::core::Clock>();
|
||||||
const auto begin = clock_->now();
|
nf7::SimpleEnv env {{
|
||||||
|
{typeid(nf7::subsys::Clock), [&](auto&) { return clock; }},
|
||||||
|
}, *env_};
|
||||||
|
|
||||||
|
clock->Tick();
|
||||||
|
const auto begin = clock->now();
|
||||||
|
|
||||||
Expect(
|
Expect(
|
||||||
"local ctx = ...\nctx:sleep(100)",
|
"local ctx = ...\nctx:sleep(100)",
|
||||||
{nf7::Value {}},
|
{nf7::Value {}},
|
||||||
1, 0);
|
1, 0,
|
||||||
|
{},
|
||||||
|
&env);
|
||||||
|
|
||||||
clock_->Tick();
|
clock->Tick();
|
||||||
const auto end = clock_->now();
|
const auto end = clock->now();
|
||||||
|
|
||||||
EXPECT_GE(end-begin, 100ms);
|
EXPECT_GE(end-begin, 100ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(LuaJIT_Lambda, CtxSleepWithoutClock) {
|
||||||
|
Expect(
|
||||||
|
"local ctx = ...\nctx:sleep(100)",
|
||||||
|
{nf7::Value {}},
|
||||||
|
0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(LuaJIT_Lambda, CtxLogging) {
|
||||||
|
const auto logger = std::make_shared<nf7::subsys::test::LoggerMock>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*logger, Push)
|
||||||
|
.WillOnce([](auto& item) {
|
||||||
|
EXPECT_EQ(item.level(), nf7::subsys::Logger::kTrace);
|
||||||
|
EXPECT_EQ(item.contents(), "this is trace");
|
||||||
|
})
|
||||||
|
.WillOnce([](auto& item) {
|
||||||
|
EXPECT_EQ(item.level(), nf7::subsys::Logger::kInfo);
|
||||||
|
EXPECT_EQ(item.contents(), "this is info");
|
||||||
|
})
|
||||||
|
.WillOnce([](auto& item) {
|
||||||
|
EXPECT_EQ(item.level(), nf7::subsys::Logger::kWarn);
|
||||||
|
EXPECT_EQ(item.contents(), "this is warn");
|
||||||
|
})
|
||||||
|
.WillOnce([](auto& item) {
|
||||||
|
EXPECT_EQ(item.level(), nf7::subsys::Logger::kError);
|
||||||
|
EXPECT_EQ(item.contents(), "this is error");
|
||||||
|
});
|
||||||
|
|
||||||
|
nf7::SimpleEnv env {{
|
||||||
|
{typeid(nf7::subsys::Logger), [&](auto&) { return logger; }},
|
||||||
|
}, *env_};
|
||||||
|
|
||||||
|
Expect(
|
||||||
|
"local ctx = ...\n"
|
||||||
|
"ctx:trace(\"this is trace\")\n"
|
||||||
|
"ctx:info(\"this is info\")\n"
|
||||||
|
"ctx:warn(\"this is warn\")\n"
|
||||||
|
"ctx:error(\"this is error\")",
|
||||||
|
{nf7::Value {}},
|
||||||
|
1, 0,
|
||||||
|
{},
|
||||||
|
&env);
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
SyncOrAsync, LuaJIT_Lambda,
|
SyncOrAsync, LuaJIT_Lambda,
|
||||||
testing::Values(
|
testing::Values(
|
||||||
|
@ -21,6 +21,7 @@ target_sources(nf7_iface
|
|||||||
data/interface.hh
|
data/interface.hh
|
||||||
subsys/concurrency.hh
|
subsys/concurrency.hh
|
||||||
subsys/interface.hh
|
subsys/interface.hh
|
||||||
|
subsys/logger.hh
|
||||||
subsys/parallelism.hh
|
subsys/parallelism.hh
|
||||||
env.hh
|
env.hh
|
||||||
file.hh
|
file.hh
|
||||||
@ -40,6 +41,7 @@ target_sources(nf7_iface_test
|
|||||||
common/task_test.cc
|
common/task_test.cc
|
||||||
common/task_test.hh
|
common/task_test.hh
|
||||||
common/value_test.cc
|
common/value_test.cc
|
||||||
|
subsys/logger_test.hh
|
||||||
lambda_test.cc
|
lambda_test.cc
|
||||||
lambda_test.hh
|
lambda_test.hh
|
||||||
)
|
)
|
||||||
|
@ -64,6 +64,25 @@ class Container {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
class NullContainer : public Container<I> {
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<NullContainer> instance()
|
||||||
|
try {
|
||||||
|
static const auto kInstance = std::make_shared<NullContainer>();
|
||||||
|
return kInstance;
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
throw Exception {"memory shortage"};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
NullContainer() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::shared_ptr<I> Get(std::type_index) override { return nullptr; }
|
||||||
|
bool installed(std::type_index) const noexcept override { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
class SimpleContainer : public Container<I> {
|
class SimpleContainer : public Container<I> {
|
||||||
public:
|
public:
|
||||||
@ -95,8 +114,9 @@ class SimpleContainer : public Container<I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SimpleContainer() = delete;
|
SimpleContainer() = delete;
|
||||||
explicit SimpleContainer(FactoryMap&& factories) noexcept
|
SimpleContainer(FactoryMap&& factories,
|
||||||
: factories_(std::move(factories)) { }
|
Container<I>& fb = *NullContainer<I>::instance()) noexcept
|
||||||
|
: fallback_(fb), factories_(std::move(factories)) { }
|
||||||
|
|
||||||
std::shared_ptr<I> Get(std::type_index idx) override {
|
std::shared_ptr<I> Get(std::type_index idx) override {
|
||||||
const auto obj_itr = objs_.find(idx);
|
const auto obj_itr = objs_.find(idx);
|
||||||
@ -122,11 +142,11 @@ class SimpleContainer : public Container<I> {
|
|||||||
throw Exception {"memory shortage"};
|
throw Exception {"memory shortage"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return fallback_.Get(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool installed(std::type_index idx) const noexcept override {
|
bool installed(std::type_index idx) const noexcept override {
|
||||||
return factories_.contains(idx);
|
return factories_.contains(idx) || fallback_.installed(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Container<I>::Get;
|
using Container<I>::Get;
|
||||||
@ -134,6 +154,8 @@ class SimpleContainer : public Container<I> {
|
|||||||
using Container<I>::installed;
|
using Container<I>::installed;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Container<I>& fallback_;
|
||||||
|
|
||||||
FactoryMap factories_;
|
FactoryMap factories_;
|
||||||
ObjectMap objs_;
|
ObjectMap objs_;
|
||||||
|
|
||||||
|
@ -66,6 +66,28 @@ TEST(SimpleContainer, CheckInstalled) {
|
|||||||
EXPECT_FALSE(sut.installed<IB>());
|
EXPECT_FALSE(sut.installed<IB>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SimpleContainer, FetchWithFallback) {
|
||||||
|
SUT fb {{
|
||||||
|
SUT::MakePair<IA, A>(),
|
||||||
|
}};
|
||||||
|
SUT sut {{}, fb};
|
||||||
|
auto ptr = sut.Get<IA>();
|
||||||
|
EXPECT_TRUE(std::dynamic_pointer_cast<A>(ptr));
|
||||||
|
}
|
||||||
|
TEST(SimpleContainer, FetchUnknownWithFallback) {
|
||||||
|
SUT fb {{}};
|
||||||
|
SUT sut {{}, fb};
|
||||||
|
EXPECT_THROW(sut.Get<IA>(), nf7::Exception);
|
||||||
|
}
|
||||||
|
TEST(SimpleContainer, CheckInstalledWithFallback) {
|
||||||
|
SUT fb {{
|
||||||
|
SUT::MakePair<IA, A>(),
|
||||||
|
}};
|
||||||
|
SUT sut {{}, fb};
|
||||||
|
EXPECT_TRUE(sut.installed<IA>());
|
||||||
|
EXPECT_FALSE(sut.installed<IB>());
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
TEST(SimpleContainer, DeathByFetchRecursive) {
|
TEST(SimpleContainer, DeathByFetchRecursive) {
|
||||||
SUT sut {{
|
SUT sut {{
|
||||||
|
80
iface/subsys/logger.hh
Normal file
80
iface/subsys/logger.hh
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <source_location>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "iface/subsys/interface.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace nf7::subsys {
|
||||||
|
|
||||||
|
class Logger : public Interface {
|
||||||
|
public:
|
||||||
|
using SrcLoc = std::source_location;
|
||||||
|
|
||||||
|
enum Level {
|
||||||
|
kTrace,
|
||||||
|
kInfo,
|
||||||
|
kWarn,
|
||||||
|
kError,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Item final {
|
||||||
|
public:
|
||||||
|
Item() = delete;
|
||||||
|
Item(Level level,
|
||||||
|
std::string_view contents,
|
||||||
|
std::source_location srcloc = std::source_location::current()) noexcept
|
||||||
|
: level_(level), contents_(contents), srcloc_(srcloc) { }
|
||||||
|
|
||||||
|
Item(const Item&) = default;
|
||||||
|
Item(Item&&) = default;
|
||||||
|
Item& operator=(const Item&) = default;
|
||||||
|
Item& operator=(Item&&) = default;
|
||||||
|
|
||||||
|
Level level() const noexcept { return level_; }
|
||||||
|
const std::string& contents() const noexcept { return contents_; }
|
||||||
|
const std::source_location& srcloc() const noexcept { return srcloc_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Level level_;
|
||||||
|
std::string contents_;
|
||||||
|
std::source_location srcloc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Interface::Interface;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// THREAD-SAFE
|
||||||
|
virtual void Push(const Item&) noexcept = 0;
|
||||||
|
|
||||||
|
// THREAD-SAFE
|
||||||
|
void Trace(std::string_view contents,
|
||||||
|
SrcLoc srcloc = SrcLoc::current()) noexcept {
|
||||||
|
Push(Item {kTrace, contents, srcloc});
|
||||||
|
}
|
||||||
|
|
||||||
|
// THREAD-SAFE
|
||||||
|
void Info(std::string_view contents,
|
||||||
|
SrcLoc srcloc = SrcLoc::current()) noexcept {
|
||||||
|
Push(Item {kInfo, contents, srcloc});
|
||||||
|
}
|
||||||
|
|
||||||
|
// THREAD-SAFE
|
||||||
|
void Warn(std::string_view contents,
|
||||||
|
SrcLoc srcloc = SrcLoc::current()) noexcept {
|
||||||
|
Push(Item {kWarn, contents, srcloc});
|
||||||
|
}
|
||||||
|
|
||||||
|
// THREAD-SAFE
|
||||||
|
void Error(std::string_view contents,
|
||||||
|
SrcLoc srcloc = SrcLoc::current()) noexcept {
|
||||||
|
Push(Item {kError, contents, srcloc});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace nf7::subsys
|
19
iface/subsys/logger_test.hh
Normal file
19
iface/subsys/logger_test.hh
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "iface/subsys/logger.hh"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace nf7::subsys::test {
|
||||||
|
|
||||||
|
class LoggerMock : public Logger {
|
||||||
|
public:
|
||||||
|
explicit LoggerMock(const char* name = "LoggerMock") noexcept
|
||||||
|
: Logger(name) {}
|
||||||
|
|
||||||
|
MOCK_METHOD(void, Push, (const Item&), (noexcept));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nf7::subsys::test
|
Loading…
x
Reference in New Issue
Block a user