Restructured tests and matured Logger a lil bit, now LoggerBase

This commit is contained in:
NaifBanana 2026-01-26 11:19:44 -06:00
parent f8a8813b3e
commit 3b828a34ff
11 changed files with 127 additions and 92 deletions

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(NBEngine VERSION 0.1.0 LANGUAGES C CXX) project(NBEngine VERSION 0.1.0 LANGUAGES C CXX)
cmake_policy(SET CMP0135 NEW)
if(CMAKE_BUILD_TYPE STREQUAL "Release") if(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "Targeting Release build") message(STATUS "Targeting Release build")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ./release) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ./release)
@ -33,6 +35,7 @@ set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
if(NB_BUILD_TESTS) if(NB_BUILD_TESTS)
message(STATUS "Building tests") message(STATUS "Building tests")
enable_testing()
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
gtest gtest

View File

@ -7,6 +7,7 @@
#include <ostream> #include <ostream>
#include <thread> #include <thread>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "Processes.hpp" #include "Processes.hpp"
#include "ThreadSafeQueue.hpp" #include "ThreadSafeQueue.hpp"
@ -30,14 +31,23 @@ struct LogEvent{
typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&); typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&);
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap; typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
template<typename LoggerName> template<typename LoggerName, typename ST=std::ostream>
class Logger { class LoggerBase {
public: public:
using Type = LoggerName; using Type = LoggerName;
using StreamType = ST;
Logger(std::ostream& stream) : _ostream(&stream) {} LoggerBase(StreamType& stream) : _ostreams({&stream}) {}
LoggerBase(const LoggerBase&) = delete;
LoggerBase(LoggerBase&&) = delete;
bool isRunning() const { LoggerBase& operator=(const LoggerBase&) = delete;
~LoggerBase() {
stop();
}
bool isRunning() const noexcept {
return _running && bool(_runningThread); return _running && bool(_runningThread);
} }
@ -46,9 +56,10 @@ public:
} }
bool run() { bool run() {
auto this_type = static_cast<Type*>(this);
if (!isRunning()) { if (!isRunning()) {
_running = true;
_runningThread = std::make_shared<std::thread>([&]{ _runningThread = std::make_shared<std::thread>([&]{
auto this_type = static_cast<Type*>(this);
while(this_type->isRunning()) { while(this_type->isRunning()) {
this_type->flush(); this_type->flush();
} }
@ -57,7 +68,7 @@ public:
return isRunning(); return isRunning();
} }
bool stop() { bool stop() noexcept {
if (isRunning()) { if (isRunning()) {
_running = false; _running = false;
_runningThread->join(); _runningThread->join();
@ -74,7 +85,7 @@ public:
return *event; return *event;
} }
void flush() { void flush() noexcept {
while(_queue.size()) { while(_queue.size()) {
pop(); pop();
} }
@ -93,33 +104,38 @@ public:
lvl, lvl,
msg, msg,
std::this_thread::get_id(), std::this_thread::get_id(),
get_pid(), GetPID(),
}); });
} }
template <size_t N>
void log(char const(&msg) [N], const uint8_t& lvl) {
static_cast<Type*>(this)->log(std::string(msg), lvl);
}
void log(const std::exception& err, const uint8_t& lvl) { void log(const std::exception& err, const uint8_t& lvl) {
_queue.push(LogEvent{ _queue.push(LogEvent{
std::chrono::system_clock::now(), std::chrono::system_clock::now(),
lvl, lvl,
err.what(), err.what(),
std::this_thread::get_id(), std::this_thread::get_id(),
get_pid(), GetPID(),
}); });
} }
void msg(const std::string& msg, const uint8_t& lvl=0x00) { void msg(const std::string& msg, const uint8_t& lvl=0x00) {
static_cast<Type>(this)->log(msg, lvl); static_cast<Type*>(this)->log(msg, lvl);
} }
void warn(const std::string& msg, const uint8_t& lvl=0x01) { void warn(const std::string& msg, const uint8_t& lvl=0x01) {
static_cast<Type>(this)->log(msg, lvl); static_cast<Type*>(this)->log(msg, lvl);
} }
void warn(const std::exception& err, const uint8_t lvl=0x01) { void warn(const std::exception& err, const uint8_t lvl=0x01) {
static_cast<Type>(this)->log(err, lvl); static_cast<Type*>(this)->log(err, lvl);
} }
void error(const std::string& msg, const uint8_t lvl=0xFF) { void error(const std::string& msg, const uint8_t lvl=0xFF) {
static_cast<Type>(this)->log(msg, lvl); static_cast<Type*>(this)->log(msg, lvl);
} }
void error(const std::exception& err, const uint8_t lvl=0xFF) { void error(const std::exception& err, const uint8_t lvl=0xFF) {
static_cast<Type*>(this)->log(err, lvl); static_cast<Type*>(this)->log(err, lvl);
@ -129,18 +145,18 @@ protected:
void process(const LogEvent&); void process(const LogEvent&);
ThreadsafeQueue<LogEvent> _queue; ThreadsafeQueue<LogEvent> _queue;
std::ostream* const _ostream; std::vector<StreamType*> const _ostreams;
std::atomic<bool> _running; std::atomic<bool> _running;
std::shared_ptr<std::thread> _runningThread = nullptr; std::shared_ptr<std::thread> _runningThread = nullptr;
}; };
class BasicLogger : public Logger<BasicLogger> { class BasicLogger : public LoggerBase<BasicLogger> {
public: public:
using Base = Logger<BasicLogger>; using Base = LoggerBase<BasicLogger>;
BasicLogger(std::ostream& stream) : Base(stream) {} BasicLogger(std::ostream& stream) : Base(stream) {}
virtual void process(const LogEvent& event) { virtual void process(const LogEvent& event) {
*_ostream << event.msg << "\n"; *_ostreams[0] << event.msg << "\n";
} }
}; };

View File

@ -6,7 +6,7 @@
namespace nb { namespace nb {
uint64_t get_pid(); uint64_t GetPID();
} // namespace nb } // namespace nb

21
engine/NBCore/Types.hpp Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#ifndef _NB_CORE_TYPES
#define _NB_CORE_TYPES
namespace nb {
template<typename T>
T swapEndian(const T& val) {
T ret;
const int size = sizeof(T);
auto retLoc = static_cast<void*>(&ret);
auto valLoc = static_cast<const void*>(&val);
for (int i = 0; i < size; ++i) {
memcpy(retLoc+i, valLoc+(size-i-1), 1);
}
return ret;
}
} // namespace nb
#endif // _NB_CORE_TYPES

View File

@ -7,15 +7,13 @@
#endif // _TARGET_LINUX #endif // _TARGET_LINUX
#include "Processes.hpp" #include "Processes.hpp"
#include "Types.hpp"
namespace nb { namespace nb {
#ifdef _TARGET_WINDOWS #ifdef _TARGET_WINDOWS
uint64_t get_pid() { uint64_t GetPID() {
const auto pid_w = GetCurrentProcessId(); return GetCurrentProcessId();
uint64_t ret;
memcpy(&ret, &pid_w, sizeof(pid_w));
return ret;
} }
#endif // _TARGET_WINDOWS #endif // _TARGET_WINDOWS

View File

@ -1,5 +1,16 @@
cmake_minimum_required(VERSION 3.26.0) cmake_minimum_required(VERSION 3.26.0)
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX) project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
add_subdirectory(./ErrorTest) include(GoogleTest)
add_subdirectory(./ProcessTest)
if (NB_BUILD_TESTS)
add_executable(TestCore
testErrors.cpp
testProcesses.cpp
)
target_link_libraries(TestCore
NBCore
GTest::gtest_main
)
gtest_discover_tests(TestCore)
endif()

View File

@ -1,5 +0,0 @@
cmake_minimum_required(VERSION 3.26.0)
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
add_executable(ErrorTest main.cpp)
target_link_libraries(ErrorTest NBCore)

View File

@ -1,54 +0,0 @@
#define CODE_ERROR_LOCATIONS
#include "Errors.hpp"
#include <iostream>
#include "Logger.hpp"
using namespace nb;
class TestError : public ErrorBase<TestError> {
public:
using ErrorBase<TestError>::ErrorBase;
enum ErrorCodes : unsigned int {
A, B, C, D
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
const std::string TestError::type="TestError";
const ErrorCodeMap TestError::ErrorMessages{
{TestError::ErrorCodes::A, "Hey!"},
{TestError::ErrorCodes::B, "How"},
{TestError::ErrorCodes::C, "You"},
{TestError::ErrorCodes::D, "Doin"}
};
int main() {
try {
try {
try {
try {
THROW(TestError, TestError::ErrorCodes::D);
} catch (const std::exception& e){
THROW(TestError, TestError::ErrorCodes::C, e);
}
} catch(const std::exception& e) {
THROW(TestError, TestError::ErrorCodes::B, e);
}
} catch(const std::exception& e) {
THROW(TestError, TestError::ErrorCodes::A, e);
}
} catch(const std::exception& e) {
// THROW(Error, Error::ErrorCodes::UNDEFINED, e);
BasicLogger log(std::cout);
std::cout << "Logger is starting: " << log.run() << std::endl;
std::cout << "Logger is running: " << log.isRunning() << std::endl;
log.error(e);
log.stop();
std::cout << "Logger is running: " << log.isRunning() << std::endl;
}
return 0;
}

View File

@ -1,5 +0,0 @@
cmake_minimum_required(VERSION 3.26.0)
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
add_executable(ProcessTest main.cpp)
target_link_libraries(ProcessTest NBCore)

View File

@ -0,0 +1,45 @@
#define CODE_ERROR_LOCATIONS
#include "Errors.hpp"
#include <gtest/gtest.h>
#include <iostream>
#include "Logger.hpp"
using namespace nb;
class TestError : public ErrorBase<TestError> {
public:
using ErrorBase<TestError>::ErrorBase;
enum ErrorCodes : unsigned int {
A, B, C, D
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
const std::string TestError::type="TestError";
const ErrorCodeMap TestError::ErrorMessages{
{TestError::ErrorCodes::A, "Hey!"},
{TestError::ErrorCodes::B, "How"},
{TestError::ErrorCodes::C, "You"},
{TestError::ErrorCodes::D, "Doin"}
};
class TestLogger : public nb::LoggerBase<TestLogger> {
public:
using Base = LoggerBase<TestLogger>;
using Base::Base;
virtual void process(const LogEvent& event) {
*_ostreams[0] << event.pid << " : " << event.msg << std::endl;
}
};
TEST(ErrorTest, Test) {
EXPECT_EQ(1, 1);
TestLogger log(std::cout);
ASSERT_TRUE(log.run());
log.msg("Hey!");
}

View File

@ -1,17 +1,22 @@
#define CODE_ERROR_LOCATIONS #define CODE_ERROR_LOCATIONS
#include <gtest/gtest.h>
#include <iostream> #include <iostream>
#include "Processes.hpp" #include "Processes.hpp"
#include <Windows.h> #include <Windows.h>
int main() { TEST(ProcessesTest, GetPID) {
ASSERT_EQ(nb::GetPID(), GetCurrentProcessId());
}
std::cout << "nb::get_pid() -> " << nb::get_pid() << std::endl; /* int main() {
std::cout << "nb::GetPID() -> " << nb::GetPID() << std::endl;
#ifdef _TARGET_WINDOWS #ifdef _TARGET_WINDOWS
std::cout << "GetCurrentProcessId() -> " << GetCurrentProcessId() << std::endl; std::cout << "GetCurrentProcessId() -> " << GetCurrentProcessId() << std::endl;
#endif // _TARGET_WINDOWS #endif // _TARGET_WINDOWS
return 0; return 0;
} } */