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

View File

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

View File

@ -6,7 +6,7 @@
namespace nb {
uint64_t get_pid();
uint64_t GetPID();
} // 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
#include "Processes.hpp"
#include "Types.hpp"
namespace nb {
#ifdef _TARGET_WINDOWS
uint64_t get_pid() {
const auto pid_w = GetCurrentProcessId();
uint64_t ret;
memcpy(&ret, &pid_w, sizeof(pid_w));
return ret;
uint64_t GetPID() {
return GetCurrentProcessId();
}
#endif // _TARGET_WINDOWS

View File

@ -1,5 +1,16 @@
cmake_minimum_required(VERSION 3.26.0)
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
add_subdirectory(./ErrorTest)
add_subdirectory(./ProcessTest)
include(GoogleTest)
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
#include <gtest/gtest.h>
#include <iostream>
#include "Processes.hpp"
#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
std::cout << "GetCurrentProcessId() -> " << GetCurrentProcessId() << std::endl;
#endif // _TARGET_WINDOWS
return 0;
}
} */