Added unit tests (catch based)

This commit is contained in:
gabime 2015-05-15 20:30:37 +03:00
parent 056352cf42
commit 2f81e54568
10 changed files with 9832 additions and 0 deletions

12
tests/Makefile Normal file
View File

@ -0,0 +1,12 @@
CXX ?= g++
CXXFLAGS = -D_WIN32_WINNT=0x600 -march=native -Wall -Wextra -Wshadow -pedantic -std=c++11 -pthread -Wl,--no-as-needed -I../include
all: %.cpp
$(CXX) $^ -o tests $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
clean:
rm -f tests *.o logs/*
rebuild: clean all

9427
tests/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

136
tests/file_log.cpp Normal file
View File

@ -0,0 +1,136 @@
#include "includes.h"
static std::string file_contents(const std::string& filename)
{
std::ifstream ifs(filename);
if (!ifs)
throw std::exception("Failed open file ");
return std::string((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
}
static std::size_t count_lines(const std::string& filename)
{
std::ifstream ifs(filename);
if (!ifs)
throw std::exception("Failed open file ");
std::string line;
size_t counter = 0;
while(std::getline(ifs, line))
counter++;
return counter;
}
std::ifstream::pos_type filesize(const std::string& filename)
{
std::ifstream ifs(filename, std::ifstream::ate | std::ifstream::binary);
if (!ifs)
throw std::exception("Failed open file ");
return ifs.tellg();
}
static void delete_logs()
{
spdlog::drop_all();
#ifdef _WIN32
system("del /F /Q logs\\*");
#else
system("rm -f logs/*");
#endif
}
TEST_CASE("simple_file_logger", "[simple_logger]]")
{
delete_logs();
std::string filename = "logs/simple_log.txt";
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename);
REQUIRE_THROWS_AS(
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger2", filename);
, spdlog::spdlog_ex);
logger->set_pattern("%v");
logger->info("Test message {}", 1);
logger->info("Test message {}", 2);
logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n"));
REQUIRE(count_lines(filename) == 2);
}
TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
{
delete_logs();
std::string basename = "logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, 1024, 0, true);
for (int i = 0; i < 10; ++i)
logger->info("Test message {}", i);
auto filename = basename + ".txt";
REQUIRE(count_lines(filename) == 10);
for (int i = 0; i < 1000; i++)
logger->info("Test message {}", i);
}
TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
{
delete_logs();
std::string basename = "logs/rotating_log";
auto logger = spdlog::rotating_logger_mt("logger", basename, 1024, 1, false);
for (int i = 0; i < 10; ++i)
logger->info("Test message {}", i);
logger->flush();
auto filename = basename + ".txt";
REQUIRE(count_lines(filename) == 10);
for (int i = 0; i < 1000; i++)
logger->info("Test message {}", i);
logger->flush();
REQUIRE(filesize(filename) <= 1024);
auto filename1 = basename + ".1.txt";
REQUIRE(filesize(filename1) <= 1024);
}
TEST_CASE("daily_logger", "[daily_logger]]")
{
delete_logs();
//calculate filename (time based)
std::string basename = "logs/daily_log";
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.txt", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
auto logger = spdlog::daily_logger_mt("logger", basename, 0, 0, true);
for (int i = 0; i < 10; ++i)
logger->info("Test message {}", i);
auto filename = w.str();
REQUIRE(count_lines(filename) == 10);
}

87
tests/format.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "includes.h"
template<class T>
std::string log_info(const T& what, spdlog::level::level_enum logger_level = spdlog::level::info) {
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("oss", oss_sink);
oss_logger.set_level(logger_level);
oss_logger.set_pattern("%v");
oss_logger.info() << what;
//strip last eol and return the logged string
auto eol_size = strlen(spdlog::details::os::eol());
return oss.str().substr(0, oss.str().length() - eol_size);
}
//User defined class with operator<<
struct some_logged_class
{
some_logged_class(const std::string val) :value(val) {};
std::string value;
};
std::ostream& operator<<(std::ostream& os, const some_logged_class& c) {
return os << c.value;
}
TEST_CASE("basic_logging ", "[basic_logging]") {
//const char
REQUIRE(log_info("Hello") == "Hello");
REQUIRE(log_info("") == "");
//std::string
REQUIRE(log_info(std::string("Hello")) == "Hello");
REQUIRE(log_info(std::string()) == std::string());
//Numbers
REQUIRE(log_info(5) == "5");
REQUIRE(log_info(5.6) == "5.6");
//User defined class
REQUIRE(log_info(some_logged_class("some_val")) == "some_val");
}
TEST_CASE("log_levels", "[log_levels]")
{
REQUIRE(log_info("Hello", spdlog::level::err) == "");
REQUIRE(log_info("Hello", spdlog::level::critical) == "");
REQUIRE(log_info("Hello", spdlog::level::emerg) == "");
REQUIRE(log_info("Hello", spdlog::level::alert) == "");
REQUIRE(log_info("Hello", spdlog::level::info) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::debug) == "Hello");
REQUIRE(log_info("Hello", spdlog::level::trace) == "Hello");
}
TEST_CASE("invalid_format", "[format]")
{
using namespace spdlog::sinks;
spdlog::logger null_logger("null_logger", std::make_shared<null_sink_st>());
REQUIRE_THROWS_AS(
null_logger.info("{} {}", "first"),
spdlog::spdlog_ex);
REQUIRE_THROWS_AS(
null_logger.info("{0:f}", "aads"),
spdlog::spdlog_ex);
REQUIRE_THROWS_AS(
null_logger.info("{0:kk}", 123),
spdlog::spdlog_ex);
}

10
tests/includes.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdio>
#include <fstream>
#include <string>
#include <ostream>
#include <chrono>
#include "catch.hpp"
#include "../include/spdlog/spdlog.h"
#include "../include/spdlog/sinks/null_sink.h"

View File

2
tests/main.cpp Normal file
View File

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

53
tests/registry.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "includes.h"
static const char *logger_name = "null_logger";
TEST_CASE("register_drop", "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(logger_name);
REQUIRE(spdlog::get(logger_name)!=nullptr);
//Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(logger_name), spdlog::spdlog_ex);
}
TEST_CASE("explicit register" "[registry]")
{
spdlog::drop_all();
auto logger = std::make_shared<spdlog::logger>(logger_name, std::make_shared<spdlog::sinks::null_sink_st>());
spdlog::register_logger(logger);
REQUIRE(spdlog::get(logger_name) != nullptr);
//Throw if registring existing name
REQUIRE_THROWS_AS(spdlog::create<spdlog::sinks::null_sink_mt>(logger_name), spdlog::spdlog_ex);
}
TEST_CASE("drop" "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(logger_name);
spdlog::drop(logger_name);
REQUIRE_FALSE(spdlog::get(logger_name));
}
TEST_CASE("drop_all" "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(logger_name);
spdlog::create<spdlog::sinks::null_sink_mt>("name2");
spdlog::drop_all();
REQUIRE_FALSE(spdlog::get(logger_name));
REQUIRE_FALSE(spdlog::get("name2"));
}
TEST_CASE("drop non existing" "[registry]")
{
spdlog::drop_all();
spdlog::create<spdlog::sinks::null_sink_mt>(logger_name);
spdlog::drop("some_name");
REQUIRE_FALSE(spdlog::get("some_name"));
REQUIRE(spdlog::get(logger_name));
spdlog::drop_all();
}

89
tests/tests.vcxproj Normal file
View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="file_log.cpp" />
<ClCompile Include="format.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="registry.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="catch.hpp" />
<ClInclude Include="includes.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1274FDEC-109A-45DF-8AEC-E3334C3A925F}</ProjectGuid>
<RootNamespace>tests</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)</OutDir>
<IntDir>$(ProjectDir)\$(Configuration-obj)\</IntDir>
<TargetName>$(ProjectName)-debug</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)</OutDir>
<IntDir>$(ProjectDir)\$(Configuration)-obj\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Headers">
<UniqueIdentifier>{9e4e82c2-35fe-4707-a66a-5cc069b44224}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="catch.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="includes.h">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
</Project>