Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the Log tool #4

Merged
merged 2 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if( DEFINED PROJECT_NAME )
endif()

project( tools
VERSION 0.1.0
VERSION 0.2.0
LANGUAGES CXX
)

Expand Down
2 changes: 2 additions & 0 deletions cmake/unit_testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ endfunction()
#######################################################################
# Unit testing directories
#######################################################################

add_subdirectory( src/tools/Log/test )
132 changes: 132 additions & 0 deletions src/tools/Log.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#ifndef NJOY_TOOLS_LOG
#define NJOY_TOOLS_LOG

// system includes

// other includes
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"

namespace njoy {
namespace tools {

/**
* @brief A singleton logger for njoy components
*/
class Log {

static auto initialize_logger() {

auto instance = spdlog::stdout_color_st( "njoy" );
instance->set_pattern( "[%^%l%$] %v" );
#ifndef NDEBUG
instance->set_level( spdlog::level::debug );
#endif
return instance;
}

static auto& logger() {

static auto instance = initialize_logger();
return instance;
}

/* constructors */
Log() {}; // private to avoid creation of Log instances

public:

Log( const Log& ) = delete;
void operator=( const Log& ) = delete;

/**
* @brief Direct the logger output to the given file
*/
static void add_sink( const std::string& filename ) {

auto sink_ptr = std::make_shared< spdlog::sinks::basic_file_sink_st >( filename );
sink_ptr->set_pattern( "[%^%l%$] %v" );
logger()->sinks().push_back( sink_ptr );
}

/**
* @brief Flush the logger
*/
static void flush() {

logger()->flush();
}

/**
* @brief Print a message at the info level
*
* For example:
*
* int value = 10;
* utility::Log::info( "Some message with a value {}", value );
*/
template< typename... Args >
static void info( Args... args ) {

logger()->info( std::forward< Args >( args )... );
}

/**
* @brief Print a message at the warning level
*
* For example:
*
* int value = 10;
* utility::Log::warning( "Some message with a value {}", value );
*/
template< typename... Args >
static void warning( Args... args ) {

logger()->warn( std::forward< Args >( args )... );
}

/**
* @brief Print a message at the error level
*
* For example:
*
* int value = 10;
* utility::Log::info( "Some message with a value {}", value );
*/
template< typename... Args >
static void error( Args... args ) {

logger()->error( std::forward< Args >( args )... );
}

/**
* @brief Print a message at the debug level
*
* This only prints when NDEBUG is defined when compiling this code.
*
* For example:
*
* int value = 10;
* utility::Log::debug( "Some message with a value {}", value );
*/
#ifdef NDEBUG
template< typename... Args >
static void debug( Args... ) {}
#else
template< typename... Args >
static void debug( Args... args ) {

logger()->debug( std::forward< Args >( args )... );
}
#endif
};

} // tools namespace

/* type alias - for backwards compatibility reasons */
using Log = tools::Log;

} // njoy namespace

#endif
1 change: 1 addition & 0 deletions src/tools/Log/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_cpp_test( Log Log.test.cpp )
57 changes: 57 additions & 0 deletions src/tools/Log/test/Log.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// include Catch2
#include <catch2/catch_test_macros.hpp>

// what we are testing
#include "tools/Log.hpp"

// other includes
#include <fstream>
#include <sstream>
#include <filesystem>

// convenience typedefs
using namespace njoy::tools;

std::string getContent( std::string filename ) {

std::stringstream ss;
std::ifstream fs( filename, std::ifstream::in );
ss << fs.rdbuf();
return ss.str();
}

SCENARIO( "Log" ) {

GIVEN( "a file name" ) {

std::string filename = "output.txt";
std::filesystem::remove( filename ); // ensure the file is not there

WHEN( "the Log redirects to a file" ) {

Log::add_sink( filename );

THEN( "the file contains the log after flushing" ) {

Log::error( "Some error occurred" );
Log::warning( "Some warning was issued" );
Log::info( "Some info was printed" );
Log::debug( "Some debug info was given" );
Log::flush();

std::string content = getContent( filename );

#ifdef NDEBUG
CHECK( "[error] Some error occurred\n"
"[warning] Some warning was issued\n"
"[info] Some info was printed\n" == content );
#else
CHECK( "[error] Some error occurred\n"
"[warning] Some warning was issued\n"
"[info] Some info was printed\n"
"[debug] Some debug info was given\n" == content );
#endif
} // THEN
} // WHEN
} // GIVEN
} // SCENARIO