Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
Log.ut.cpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2022 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#include "Log.hpp"
18
20
21#include <boost/test/unit_test.hpp>
22
23#include <cstring>
24#include <iomanip>
25#include <string_view>
26
27using namespace std;
28using namespace toolbox;
29
30namespace {
31namespace noformat {
32// Specific Log operator<< to allow non formatted writing.
33Log& operator<<(Log& log, std::string_view str)
34{
35 return log(str.data(), str.size());
36}
37} // namespace noformat
38
39template <typename T, typename U>
40struct Foo {
41 T first;
42 U second;
43};
44
45ostream& operator<<(ostream& os, const Foo<int, int>& val)
46{
47 return os << '(' << val.first << ',' << val.second << ')';
48}
49
50struct TestLogger final : Logger {
51 void do_write_log(WallTime /*ts*/, LogLevel level, int /*tid*/, LogMsgPtr&& msg,
52 size_t size) noexcept override
53 {
54 last_level = level;
55 last_msg.assign(static_cast<const char*>(msg.get()), size);
56 }
57 LogLevel last_level{};
58 string last_msg{};
59};
60
61} // namespace
62
64
66{
67 //NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
69 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::None), "NONE"), 0);
70 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Crit), "CRIT"), 0);
71 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Error), "ERROR"), 0);
72 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Warn), "WARN"), 0);
73 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Metric), "METRIC"), 0);
74 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Notice), "NOTICE"), 0);
75 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Info), "INFO"), 0);
76 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel::Debug), "DEBUG"), 0);
77 //NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
78 BOOST_CHECK_EQUAL(strcmp(log_label(LogLevel{99}), "DEBUG"), 0);
79}
80
82{
83 TestLogger tl;
84
85 auto prev_level = set_log_level(LogLevel::Info);
86 auto& prev_logger = set_logger(tl);
87 // clang-format off
88 const auto finally = make_finally([prev_level, &prev_logger]() noexcept {
91 });
92 // clang-format on
93
94 TOOLBOX_LOG(LogLevel::Info) << "test1: " << Foo<int, int>{10, 20};
95 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Info);
96 BOOST_CHECK_EQUAL(tl.last_msg, "test1: (10,20)");
97
98 TOOLBOX_CRIT << "test2: " << Foo<int, int>{10, 20};
99 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Crit);
100 BOOST_CHECK_EQUAL(tl.last_msg, "test2: (10,20)");
101
102 TOOLBOX_ERROR << "test3: " << Foo<int, int>{10, 20};
103 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Error);
104 BOOST_CHECK_EQUAL(tl.last_msg, "test3: (10,20)");
105
106 TOOLBOX_WARN << "test4: " << Foo<int, int>{10, 20};
107 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Warn);
108 BOOST_CHECK_EQUAL(tl.last_msg, "test4: (10,20)");
109
110 TOOLBOX_METRIC << "test5: " << Foo<int, int>{10, 20};
111 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Metric);
112 BOOST_CHECK_EQUAL(tl.last_msg, "test5: (10,20)");
113
114 TOOLBOX_NOTICE << "test6: " << Foo<int, int>{10, 20};
115 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Notice);
116 BOOST_CHECK_EQUAL(tl.last_msg, "test6: (10,20)");
117
118 TOOLBOX_INFO << "test7: " << Foo<int, int>{10, 20};
119 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Info);
120 BOOST_CHECK_EQUAL(tl.last_msg, "test7: (10,20)");
121
122 // This should not be logged.
123 TOOLBOX_DEBUG << "test8: " << Foo<int, int>{10, 20};
124 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Info);
125 BOOST_CHECK_EQUAL(tl.last_msg, "test7: (10,20)");
126
127 // This will log a non formatted string view, the formatting shows up on the next "formatable"
128 // parameter.
129 using namespace noformat;
130 TOOLBOX_LOG(LogLevel::Info) << setw(3) << setfill('*') << "test8: "sv << Foo<int, int>{10, 20};
131 BOOST_CHECK_EQUAL(tl.last_level, LogLevel::Info);
132 BOOST_CHECK_EQUAL(tl.last_msg, "test8: **(10,20)");
133}
134
#define TOOLBOX_METRIC
Definition Log.hpp:95
#define TOOLBOX_DEBUG
Definition Log.hpp:102
#define TOOLBOX_CRIT
Definition Log.hpp:92
#define TOOLBOX_WARN
Definition Log.hpp:94
#define TOOLBOX_NOTICE
Definition Log.hpp:96
#define TOOLBOX_INFO
Definition Log.hpp:97
#define TOOLBOX_ERROR
Definition Log.hpp:93
#define TOOLBOX_LOG(LEVEL)
Definition Log.hpp:89
BOOST_AUTO_TEST_CASE(LogLabelCase)
Definition Log.ut.cpp:65
BOOST_CHECK_EQUAL(v.size(), 10U)
STL namespace.
ostream & operator<<(ostream &os, PutPercentiles pp)
Definition Utility.cpp:96
const char * log_label(LogLevel level) noexcept
Return log label for given log level.
Definition Logger.cpp:155
Logger & set_logger(Logger &logger) noexcept
Set logger globally for all threads.
Definition Logger.cpp:175
WallClock::time_point WallTime
Definition Time.hpp:111
StoragePtr< MaxLogLine > LogMsgPtr
Definition Logger.hpp:51
LogLevel set_log_level(LogLevel level) noexcept
Set log level globally for all threads.
Definition Logger.cpp:165
auto make_finally(FnT fn) noexcept
Definition Finally.hpp:48
constexpr std::size_t size(const detail::Struct< detail::Member< TagsT, ValuesT >... > &s)
Definition Struct.hpp:98
constexpr auto bind() noexcept
Definition Slot.hpp:92