Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
eb34eb97
Commit
eb34eb97
authored
Jan 06, 2017
by
Dominik Charousset
Committed by
Marian Triebe
Apr 23, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Redesign terminal color API to support Windows
parent
42ab04ea
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
295 additions
and
204 deletions
+295
-204
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+1
-1
libcaf_core/caf/all.hpp
libcaf_core/caf/all.hpp
+1
-0
libcaf_core/caf/term.hpp
libcaf_core/caf/term.hpp
+36
-11
libcaf_core/src/logger.cpp
libcaf_core/src/logger.cpp
+7
-7
libcaf_core/src/term.cpp
libcaf_core/src/term.cpp
+142
-0
libcaf_test/caf/test/unit_test.hpp
libcaf_test/caf/test/unit_test.hpp
+50
-74
libcaf_test/caf/test/unit_test_impl.hpp
libcaf_test/caf/test/unit_test_impl.hpp
+58
-111
No files found.
libcaf_core/CMakeLists.txt
View file @
eb34eb97
...
...
@@ -34,7 +34,6 @@ set (LIBCAF_CORE_SRCS
src/behavior_impl.cpp
src/blocking_actor.cpp
src/blocking_behavior.cpp
src/color.cpp
src/concatenated_tuple.cpp
src/config_option.cpp
src/continue_helper.cpp
...
...
@@ -89,6 +88,7 @@ set (LIBCAF_CORE_SRCS
src/sync_request_bouncer.cpp
src/stringification_inspector.cpp
src/test_coordinator.cpp
src/term.cpp
src/timestamp.cpp
src/try_match.cpp
src/type_erased_value.cpp
...
...
libcaf_core/caf/all.hpp
View file @
eb34eb97
...
...
@@ -27,6 +27,7 @@
#include "caf/send.hpp"
#include "caf/skip.hpp"
#include "caf/unit.hpp"
#include "caf/term.hpp"
#include "caf/actor.hpp"
#include "caf/after.hpp"
#include "caf/error.hpp"
...
...
libcaf_core/caf/
color
.hpp
→
libcaf_core/caf/
term
.hpp
View file @
eb34eb97
...
...
@@ -17,30 +17,55 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_
COLOR
_HPP
#define CAF_
COLOR
_HPP
#ifndef CAF_
TERM
_HPP
#define CAF_
TERM
_HPP
namespace
caf
{
#include <iosfwd>
enum
color_face
{
normal
,
bold
};
namespace
caf
{
enum
color_value
{
/// Terminal color and font face options.
enum
class
term
{
/// Resets the color to the default color and the font weight to normal.
reset
,
/// Like `reset` but also prints a newline.
reset_endl
,
/// Sets the terminal color to black.
black
,
/// Sets the terminal color to red.
red
,
/// Sets the terminal color to green.
green
,
/// Sets the terminal color to yellow.
yellow
,
/// Sets the terminal color to blue.
blue
,
/// Sets the terminal color to magenta.
magenta
,
/// Sets the terminal color to cyan.
cyan
,
white
/// Sets the terminal color to white.
white
,
/// Sets the terminal color to black and the font weight to bold.
bold_black
,
/// Sets the terminal color to red and the font weight to bold.
bold_red
,
/// Sets the terminal color to green and the font weight to bold.
bold_green
,
/// Sets the terminal color to yellow and the font weight to bold.
bold_yellow
,
/// Sets the terminal color to blue and the font weight to bold.
bold_blue
,
/// Sets the terminal color to magenta and the font weight to bold.
bold_magenta
,
/// Sets the terminal color to cyan and the font weight to bold.
bold_cyan
,
/// Sets the terminal color to white and the font weight to bold.
bold_white
};
const
char
*
color
(
color_value
value
,
color_face
face
=
normal
);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
term
x
);
}
// namespace caf
#endif // CAF_
COLOR
_HPP
#endif // CAF_
TERM
_HPP
libcaf_core/src/logger.cpp
View file @
eb34eb97
...
...
@@ -35,7 +35,7 @@
#include "caf/string_algorithms.hpp"
#include "caf/
color
.hpp"
#include "caf/
term
.hpp"
#include "caf/locks.hpp"
#include "caf/timestamp.hpp"
#include "caf/actor_proxy.hpp"
...
...
@@ -424,22 +424,22 @@ void logger::run() {
default:
break
;
case
CAF_LOG_LEVEL_ERROR
:
std
::
clog
<<
color
(
red
)
;
std
::
clog
<<
term
::
red
;
;
break
;
case
CAF_LOG_LEVEL_WARNING
:
std
::
clog
<<
color
(
yellow
)
;
std
::
clog
<<
term
::
yellow
;
break
;
case
CAF_LOG_LEVEL_INFO
:
std
::
clog
<<
color
(
green
)
;
std
::
clog
<<
term
::
green
;
break
;
case
CAF_LOG_LEVEL_DEBUG
:
std
::
clog
<<
color
(
cyan
)
;
std
::
clog
<<
term
::
cyan
;
break
;
case
CAF_LOG_LEVEL_TRACE
:
std
::
clog
<<
color
(
blue
)
;
std
::
clog
<<
term
::
blue
;
break
;
}
std
::
clog
<<
ptr
->
msg
<<
color
(
reset
)
<<
std
::
endl
;
std
::
clog
<<
ptr
->
msg
<<
term
::
reset
<<
std
::
endl
;
}
}
if
(
file
)
{
...
...
libcaf_core/src/
color
.cpp
→
libcaf_core/src/
term
.cpp
View file @
eb34eb97
...
...
@@ -17,29 +17,126 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/color.hpp"
#include "caf/term.hpp"
#include <iostream>
#include "caf/config.hpp"
#ifdef CAF_WINDOWS
#include <io.h>
#include <windows.h>
#else
#include <stdio.h>
#include <unistd.h>
#endif
namespace
caf
{
const
char
*
color
(
color_value
value
,
color_face
face
)
{
#ifdef CAF_MSVC
return
""
;
#else
const
char
*
colors
[
9
][
2
]
=
{
{
"
\033
[0m"
,
"
\033
[0m"
},
// reset
{
"
\033
[30m"
,
"
\033
[1m
\033
[30m"
},
// black
{
"
\033
[31m"
,
"
\033
[1m
\033
[31m"
},
// red
{
"
\033
[32m"
,
"
\033
[1m
\033
[32m"
},
// green
{
"
\033
[33m"
,
"
\033
[1m
\033
[33m"
},
// yellow
{
"
\033
[34m"
,
"
\033
[1m
\033
[34m"
},
// blue
{
"
\033
[35m"
,
"
\033
[1m
\033
[35m"
},
// magenta
{
"
\033
[36m"
,
"
\033
[1m
\033
[36m"
},
// cyan
{
"
\033
[37m"
,
"
\033
[1m
\033
[37m"
}
// white
};
return
colors
[
static_cast
<
size_t
>
(
value
)][
static_cast
<
size_t
>
(
face
)];
namespace
{
#ifdef CAF_WINDOWS
// windows terminals do no support bold fonts
constexpr
int
win_black
=
0
;
constexpr
int
win_red
=
FOREGROUND_INTENSITY
|
FOREGROUND_RED
;
constexpr
int
win_green
=
FOREGROUND_INTENSITY
|
FOREGROUND_GREEN
;
constexpr
int
win_blue
=
FOREGROUND_INTENSITY
|
FOREGROUND_BLUE
;
constexpr
int
win_yellow
=
win_red
|
win_green
;
constexpr
int
win_magenta
=
win_red
|
win_blue
;
constexpr
int
win_cyan
=
win_green
|
win_blue
;
constexpr
int
win_white
=
win_red
|
win_cyan
;
int
tty_codes
[]
=
{
-
1
,
// reset
-
2
,
// reset_endl
win_black
,
// black
win_red
,
// red
win_green
,
// green
win_yellow
,
// yellow
win_blue
,
// blue
win_magenta
,
// magenta
win_cyan
,
// cyan
win_white
,
// white
win_black
,
// bold black
win_red
,
// bold red
win_green
,
// bold green
win_yellow
,
// bold yellow
win_blue
,
// bold blue
win_magenta
,
// bold magenta
win_cyan
,
// bold cyan
win_white
// bold white
};
void
set_term_color
(
std
::
ostream
&
out
,
int
c
)
{
static
WORD
default_color
=
0xFFFF
;
auto
hdl
=
GetStdHandle
(
&
out
==
&
std
::
cout
?
STD_OUTPUT_HANDLE
:
STD_ERROR_HANDLE
);
if
(
default_color
==
0xFFFF
)
{
CONSOLE_SCREEN_BUFFER_INFO
info
;
if
(
!
GetConsoleScreenBufferInfo
(
hdl
,
&
info
))
return
;
default_color
=
info
.
wAttributes
;
}
// always pick background from the default color
auto
x
=
c
<
0
?
default_color
:
static_cast
<
WORD
>
((
0xF0
&
default_color
)
|
(
0x0F
&
c
));
SetConsoleTextAttribute
(
hdl
,
x
);
if
(
c
==
-
2
)
out
<<
'\n'
;
}
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#define ISATTY_FUN ::_isatty
#else // POSIX-compatible terminals
const
char
*
tty_codes
[]
=
{
"
\033
[0m"
,
// reset
"
\033
[0m
\n
"
,
// reset_endl
"
\033
[30m"
,
// black
"
\033
[31m"
,
// red
"
\033
[32m"
,
// green
"
\033
[33m"
,
// yellow
"
\033
[34m"
,
// blue
"
\033
[35m"
,
// magenta
"
\033
[36m"
,
// cyan
"
\033
[37m"
,
// white
"
\033
[1m
\033
[30m"
,
// bold_black
"
\033
[1m
\033
[31m"
,
// bold_red
"
\033
[1m
\033
[32m"
,
// bold_green
"
\033
[1m
\033
[33m"
,
// bold_yellow
"
\033
[1m
\033
[34m"
,
// bold_blue
"
\033
[1m
\033
[35m"
,
// bold_magenta
"
\033
[1m
\033
[36m"
,
// bold_cyan
"
\033
[1m
\033
[37m"
// bold_white
};
void
set_term_color
(
std
::
ostream
&
out
,
const
char
*
x
)
{
out
<<
x
;
}
#define ISATTY_FUN ::isatty
#endif
bool
is_tty
(
const
std
::
ostream
&
out
)
{
if
(
&
out
==
&
std
::
cout
)
return
ISATTY_FUN
(
STDOUT_FILENO
)
!=
0
;
if
(
&
out
==
&
std
::
cerr
||
&
out
==
&
std
::
clog
)
return
ISATTY_FUN
(
STDERR_FILENO
)
!=
0
;
return
false
;
}
}
// namespace <anonymous>
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
term
x
)
{
if
(
is_tty
(
out
))
set_term_color
(
out
,
tty_codes
[
static_cast
<
size_t
>
(
x
)]);
return
out
;
}
}
// namespace caf
libcaf_test/caf/test/unit_test.hpp
View file @
eb34eb97
...
...
@@ -32,7 +32,7 @@
#include <iostream>
#include "caf/fwd.hpp"
#include "caf/
color
.hpp"
#include "caf/
term
.hpp"
#include "caf/optional.hpp"
#include "caf/deep_to_string.hpp"
...
...
@@ -81,9 +81,9 @@ public:
size_t
expected_failures
()
const
;
void
pass
(
const
std
::
string
&
msg
);
void
pass
();
void
fail
(
const
std
::
string
&
msg
,
bool
expected
);
void
fail
(
bool
expected
);
const
std
::
string
&
name
()
const
;
...
...
@@ -141,20 +141,30 @@ public:
massive
=
4
};
static
bool
init
(
int
lvl_cons
,
int
lvl_file
,
const
std
::
string
&
logfile
);
static
logger
&
instance
();
template
<
class
T
>
void
log
(
level
lvl
,
const
T
&
x
)
{
if
(
lvl
<=
level_console_
)
{
*
console_
<<
x
;
}
if
(
lvl
<=
level_file_
)
{
file_
<<
x
;
}
}
/// Output stream for logging purposes.
class
stream
{
public:
stream
(
logger
&
l
,
level
lvl
);
stream
(
logger
&
parent
,
level
lvl
);
stream
(
stream
&&
)
;
stream
(
const
stream
&
)
=
default
;
template
<
class
T
>
typename
std
::
enable_if
<
!
std
::
is_same
<
T
,
char
*>::
value
,
stream
&
>::
type
operator
<<
(
const
T
&
x
)
{
buf_
<<
x
;
stream
&
operator
<<
(
const
T
&
x
)
{
parent_
.
log
(
lvl_
,
x
);
return
*
this
;
}
...
...
@@ -165,53 +175,26 @@ public:
return
*
this
<<
*
x
;
}
stream
&
operator
<<
(
const
char
&
c
);
stream
&
operator
<<
(
const
char
*
cstr
);
stream
&
operator
<<
(
const
std
::
string
&
x
);
std
::
string
str
()
const
;
private:
void
flush
();
logger
&
logger_
;
level
level_
;
std
::
ostringstream
buf_
;
std
::
string
str_
;
logger
&
parent_
;
level
lvl_
;
};
static
bool
init
(
int
lvl_cons
,
int
lvl_file
,
const
std
::
string
&
logfile
);
static
logger
&
instance
();
template
<
class
T
>
void
log
(
level
lvl
,
const
T
&
x
)
{
if
(
lvl
<=
level_console_
)
{
std
::
lock_guard
<
std
::
mutex
>
io_guard
{
console_mtx_
};
console_
<<
x
;
}
if
(
lvl
<=
level_file_
)
{
std
::
lock_guard
<
std
::
mutex
>
io_guard
{
file_mtx_
};
file_
<<
x
;
}
}
stream
error
();
stream
info
();
stream
verbose
();
stream
massive
();
void
disable_colors
();
private:
logger
();
level
level_console_
;
level
level_file_
;
std
::
ostream
&
console_
;
std
::
ostream
*
console_
;
std
::
ofstream
file_
;
std
::
mutex
console_mtx_
;
std
::
mutex
file_mtx_
;
std
::
ostringstream
dummy_
;
};
/// Drives unit test execution.
...
...
@@ -270,10 +253,6 @@ public:
const
std
::
string
&
tests_str
,
const
std
::
string
&
not_tests_str
);
/// Retrieves a UNIX terminal color code or an empty string based on the
/// color configuration of the engine.
static
const
char
*
color
(
color_value
v
,
color_face
t
=
normal
);
static
const
char
*
last_check_file
();
static
void
last_check_file
(
const
char
*
file
);
...
...
@@ -327,7 +306,7 @@ template <class T>
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
showable_base
<
T
>&
x
)
{
auto
str
=
caf
::
deep_to_string
(
x
.
value
);
if
(
str
==
"<unprintable>"
)
out
<<
engine
::
color
(
blue
)
<<
"<unprintable>"
<<
engine
::
color
(
reset
)
;
out
<<
term
::
blue
<<
"<unprintable>"
<<
term
::
reset
;
else
out
<<
str
;
return
out
;
...
...
@@ -360,22 +339,22 @@ template <class T, class U>
bool
check
(
test
*
parent
,
const
char
*
file
,
size_t
line
,
const
char
*
expr
,
bool
should_fail
,
bool
result
,
const
T
&
x
,
const
U
&
y
)
{
std
::
stringstream
ss
;
auto
out
=
logger
::
instance
().
massive
()
;
if
(
result
)
{
ss
<<
engine
::
color
(
green
)
<<
"** "
<<
engine
::
color
(
blue
)
<<
file
<<
engine
::
color
(
yellow
)
<<
":"
<<
engine
::
color
(
blue
)
<<
line
<<
fill
(
line
)
<<
engine
::
color
(
reset
)
<<
expr
;
parent
->
pass
(
ss
.
str
()
);
out
<<
term
::
green
<<
"** "
<<
term
::
blue
<<
file
<<
term
::
yellow
<<
":"
<<
term
::
blue
<<
line
<<
fill
(
line
)
<<
term
::
reset
<<
expr
<<
'\n'
;
parent
->
pass
();
}
else
{
ss
<<
engine
::
color
(
red
)
<<
"!!
"
<<
engine
::
color
(
blue
)
<<
file
<<
engine
::
color
(
yellow
)
<<
":"
<<
engine
::
color
(
blue
)
<<
line
<<
fill
(
line
)
<<
engine
::
color
(
reset
)
<<
expr
<<
engine
::
color
(
magenta
)
<<
" ("
<<
engine
::
color
(
red
)
<<
show
(
x
)
<<
engine
::
color
(
magenta
)
<<
" !! "
<<
engine
::
color
(
red
)
<<
show
(
y
)
<<
engine
::
color
(
magenta
)
<<
')'
<<
engine
::
color
(
reset
)
;
parent
->
fail
(
s
s
.
str
(),
s
hould_fail
);
out
<<
term
::
red
<<
"!!
"
<<
term
::
blue
<<
file
<<
term
::
yellow
<<
":"
<<
term
::
blue
<<
line
<<
fill
(
line
)
<<
term
::
reset
<<
expr
<<
term
::
magenta
<<
" ("
<<
term
::
red
<<
show
(
x
)
<<
term
::
magenta
<<
" !! "
<<
term
::
red
<<
show
(
y
)
<<
term
::
magenta
<<
')'
<<
term
::
reset_endl
;
parent
->
fail
(
should_fail
);
}
return
result
;
}
...
...
@@ -388,10 +367,9 @@ bool check(test* parent, const char *file, size_t line,
using
caf_test_case_auto_fixture
=
caf
::
test
::
dummy_fixture
;
#define CAF_TEST_PRINT(level, msg, colorcode) \
(::caf::test::logger::instance(). level () \
<< ::caf::test::engine::color(::caf:: colorcode ) \
<< " -> " << ::caf::test::engine::color(::caf::reset) << msg \
<< " [line " << __LINE__ << "]\n")
(::caf::test::logger::instance().level() \
<< ::caf::term:: colorcode << " -> " << ::caf::term::reset << msg \
<< " [line " << __LINE__ << "]\n")
#define CAF_TEST_PRINT_ERROR(msg) CAF_TEST_PRINT(info, msg, red)
#define CAF_TEST_PRINT_INFO(msg) CAF_TEST_PRINT(info, msg, yellow)
...
...
@@ -416,12 +394,11 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture;
#define CAF_ERROR(msg) \
do { \
auto CAF_UNIQUE(__str) = CAF_TEST_PRINT_ERROR(msg).str(); \
::caf::test::detail::remove_trailing_spaces(CAF_UNIQUE(__str)); \
::caf::test::engine::current_test()->fail(CAF_UNIQUE(__str), false); \
CAF_TEST_PRINT_ERROR(msg); \
::caf::test::engine::current_test()->fail(false); \
::caf::test::engine::last_check_file(__FILE__); \
::caf::test::engine::last_check_line(__LINE__); \
} while(false)
} while
(false)
#define CAF_CHECK(...) \
do { \
...
...
@@ -467,9 +444,8 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture;
#define CAF_FAIL(msg) \
do { \
auto CAF_UNIQUE(__str) = CAF_TEST_PRINT_ERROR(msg).str(); \
::caf::test::detail::remove_trailing_spaces(CAF_UNIQUE(__str)); \
::caf::test::engine::current_test()->fail(CAF_UNIQUE(__str), false); \
CAF_TEST_PRINT_ERROR(msg); \
::caf::test::engine::current_test()->fail(false); \
::caf::test::detail::requirement_failed("test failure"); \
} while (false)
...
...
libcaf_test/caf/test/unit_test_impl.hpp
View file @
eb34eb97
...
...
@@ -108,17 +108,14 @@ size_t test::expected_failures() const {
return
expected_failures_
;
}
void
test
::
pass
(
const
std
::
string
&
msg
)
{
void
test
::
pass
()
{
++
good_
;
::
caf
::
test
::
logger
::
instance
().
massive
()
<<
" "
<<
msg
<<
'\n'
;
}
void
test
::
fail
(
const
std
::
string
&
msg
,
bool
expected
)
{
void
test
::
fail
(
bool
expected
)
{
++
bad_
;
::
caf
::
test
::
logger
::
instance
().
massive
()
<<
" "
<<
msg
<<
'\n'
;
if
(
expected
)
{
if
(
expected
)
++
expected_failures_
;
}
}
const
std
::
string
&
test
::
name
()
const
{
...
...
@@ -129,11 +126,11 @@ namespace detail {
[[
noreturn
]]
void
requirement_failed
(
const
std
::
string
&
msg
)
{
auto
&
log
=
logger
::
instance
();
log
.
error
()
<<
engine
::
color
(
red
)
<<
" REQUIRED: "
<<
msg
<<
engine
::
color
(
reset
)
<<
'\n'
<<
" "
<<
engine
::
color
(
blue
)
<<
engine
::
last_check_file
()
<<
engine
::
color
(
yellow
)
<<
":"
<<
engine
::
color
(
cyan
)
<<
engine
::
last_check_line
()
<<
engine
::
color
(
reset
)
log
.
error
()
<<
term
::
red
<<
" REQUIRED: "
<<
msg
<<
term
::
reset
<<
'\n'
<<
" "
<<
term
::
blue
<<
engine
::
last_check_file
()
<<
term
::
yellow
<<
":"
<<
term
::
cyan
<<
engine
::
last_check_line
()
<<
term
::
reset
<<
detail
::
fill
(
engine
::
last_check_line
())
<<
"had last successful check"
<<
'\n'
;
abort
();
...
...
@@ -155,75 +152,31 @@ void remove_trailing_spaces(std::string& x) {
bool
check
(
test
*
parent
,
const
char
*
file
,
size_t
line
,
const
char
*
expr
,
bool
should_fail
,
bool
result
)
{
std
::
stringstream
ss
;
auto
out
=
logger
::
instance
().
massive
()
;
if
(
result
)
{
ss
<<
engine
::
color
(
green
)
<<
"** "
<<
engine
::
color
(
blue
)
<<
file
<<
engine
::
color
(
yellow
)
<<
":"
<<
engine
::
color
(
blue
)
<<
line
<<
fill
(
line
)
<<
engine
::
color
(
reset
)
<<
expr
;
parent
->
pass
(
ss
.
str
()
);
out
<<
term
::
green
<<
"** "
<<
term
::
blue
<<
file
<<
term
::
yellow
<<
":"
<<
term
::
blue
<<
line
<<
fill
(
line
)
<<
term
::
reset
<<
expr
;
parent
->
pass
();
}
else
{
ss
<<
engine
::
color
(
red
)
<<
"!!
"
<<
engine
::
color
(
blue
)
<<
file
<<
engine
::
color
(
yellow
)
<<
":"
<<
engine
::
color
(
blue
)
<<
line
<<
fill
(
line
)
<<
engine
::
color
(
reset
)
<<
expr
;
parent
->
fail
(
s
s
.
str
(),
s
hould_fail
);
out
<<
term
::
red
<<
"!!
"
<<
term
::
blue
<<
file
<<
term
::
yellow
<<
":"
<<
term
::
blue
<<
line
<<
fill
(
line
)
<<
term
::
reset
<<
expr
;
parent
->
fail
(
should_fail
);
}
return
result
;
}
}
// namespace detail
logger
::
stream
::
stream
(
logger
&
l
,
level
lvl
)
:
logger_
(
l
),
level_
(
lvl
)
{
logger
::
stream
::
stream
(
logger
&
parent
,
logger
::
level
lvl
)
:
parent_
(
parent
),
lvl_
(
lvl
)
{
// nop
}
logger
::
stream
::
stream
(
stream
&&
other
)
:
logger_
(
other
.
logger_
)
,
level_
(
other
.
level_
)
{
// ostringstream does have swap since C++11... but not in GCC 4.8.4
buf_
.
str
(
other
.
buf_
.
str
());
}
logger
::
stream
&
logger
::
stream
::
operator
<<
(
const
char
&
c
)
{
buf_
<<
c
;
if
(
c
==
'\n'
)
{
flush
();
}
return
*
this
;
}
logger
::
stream
&
logger
::
stream
::
operator
<<
(
const
char
*
cstr
)
{
if
(
*
cstr
==
'\0'
)
{
return
*
this
;
}
buf_
<<
cstr
;
if
(
cstr
[
std
::
strlen
(
cstr
)
-
1
]
==
'\n'
)
{
flush
();
}
return
*
this
;
}
logger
::
stream
&
logger
::
stream
::
operator
<<
(
const
std
::
string
&
x
)
{
if
(
x
.
empty
())
return
*
this
;
buf_
<<
x
;
if
(
x
.
back
()
==
'\n'
)
flush
();
return
*
this
;
}
std
::
string
logger
::
stream
::
str
()
const
{
return
str_
;
}
void
logger
::
stream
::
flush
()
{
auto
x
=
buf_
.
str
();
buf_
.
str
(
""
);
logger_
.
log
(
level_
,
x
);
str_
+=
x
;
}
bool
logger
::
init
(
int
lvl_cons
,
int
lvl_file
,
const
std
::
string
&
logfile
)
{
instance
().
level_console_
=
static_cast
<
level
>
(
lvl_cons
);
instance
().
level_file_
=
static_cast
<
level
>
(
lvl_file
);
...
...
@@ -255,10 +208,19 @@ logger::stream logger::massive() {
return
stream
{
*
this
,
level
::
massive
};
}
void
logger
::
disable_colors
()
{
// Disable colors by piping all writes through dummy_.
// Since dummy_ is not a TTY, colors are turned off implicitly.
dummy_
.
copyfmt
(
std
::
cerr
);
dummy_
.
clear
(
std
::
cerr
.
rdstate
());
dummy_
.
basic_ios
<
char
>::
rdbuf
(
std
::
cerr
.
rdbuf
());
console_
=
&
dummy_
;
}
logger
::
logger
()
:
level_console_
(
level
::
error
),
level_file_
(
level
::
error
),
console_
(
std
::
cerr
)
{
console_
(
&
std
::
cerr
)
{
// nop
}
...
...
@@ -320,6 +282,8 @@ bool engine::run(bool colorize,
return
false
;
}
auto
&
log
=
logger
::
instance
();
if
(
!
colorize
)
log
.
disable_colors
();
std
::
chrono
::
microseconds
runtime
{
0
};
size_t
total_suites
=
0
;
size_t
total_tests
=
0
;
...
...
@@ -385,11 +349,11 @@ bool engine::run(bool colorize,
instance
().
current_test_
=
t
.
get
();
++
tests_ran
;
if
(
!
displayed_header
)
{
log
.
verbose
()
<<
color
(
yellow
)
<<
bar
<<
'\n'
<<
pad
<<
suite_name
<<
'\n'
<<
bar
<<
color
(
reset
)
<<
"
\n\n
"
;
log
.
verbose
()
<<
term
::
yellow
<<
bar
<<
'\n'
<<
pad
<<
suite_name
<<
'\n'
<<
bar
<<
term
::
reset
<<
"
\n\n
"
;
displayed_header
=
true
;
}
log
.
verbose
()
<<
color
(
yellow
)
<<
"- "
<<
color
(
reset
)
<<
t
->
name
()
log
.
verbose
()
<<
term
::
yellow
<<
"- "
<<
term
::
reset
<<
t
->
name
()
<<
'\n'
;
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
watchdog
::
start
(
max_runtime
());
...
...
@@ -405,17 +369,17 @@ bool engine::run(bool colorize,
total_good
+=
good
;
total_bad
+=
bad
;
total_bad_expected
+=
t
->
expected_failures
();
log
.
verbose
()
<<
color
(
yellow
)
<<
" -> "
<<
color
(
cyan
)
<<
good
+
bad
<<
color
(
reset
)
<<
" check"
<<
(
good
+
bad
>
1
?
"s "
:
" "
)
<<
"took "
<<
color
(
cyan
)
<<
render
(
elapsed
)
<<
color
(
reset
)
<<
'\n'
;
log
.
verbose
()
<<
term
::
yellow
<<
" -> "
<<
term
::
cyan
<<
good
+
bad
<<
term
::
reset
<<
" check"
<<
(
good
+
bad
>
1
?
"s "
:
" "
)
<<
"took "
<<
term
::
cyan
<<
render
(
elapsed
)
<<
term
::
reset
<<
'\n'
;
if
(
bad
>
0
)
{
// concat suite name + test name
failed_tests
.
emplace_back
(
p
.
first
);
failed_tests
.
back
()
+=
":"
;
failed_tests
.
back
()
+=
t
->
name
();
log
.
verbose
()
<<
" ("
<<
color
(
green
)
<<
good
<<
color
(
reset
)
<<
'/'
<<
color
(
red
)
<<
bad
<<
color
(
reset
)
<<
")"
<<
'\n'
;
log
.
verbose
()
<<
" ("
<<
term
::
green
<<
good
<<
term
::
reset
<<
'/'
<<
term
::
red
<<
bad
<<
term
::
reset
<<
")"
<<
'\n'
;
}
else
{
log
.
verbose
()
<<
'\n'
;
}
...
...
@@ -437,40 +401,36 @@ bool engine::run(bool colorize,
auto
title
=
std
::
string
{
"summary"
};
auto
pad
=
std
::
string
((
bar
.
size
()
-
title
.
size
())
/
2
,
' '
);
auto
indent
=
std
::
string
(
24
,
' '
);
log
.
info
()
<<
color
(
cyan
)
<<
bar
<<
'\n'
<<
pad
<<
title
<<
'\n'
<<
bar
<<
color
(
reset
)
<<
"
\n\n
"
<<
indent
<<
"suites: "
<<
color
(
yellow
)
<<
total_suites
<<
color
(
reset
)
<<
'\n'
<<
indent
<<
"tests: "
<<
color
(
yellow
)
<<
total_tests
<<
color
(
reset
)
<<
'\n'
<<
indent
<<
"checks: "
<<
color
(
yellow
)
<<
total_good
+
total_bad
<<
color
(
reset
)
;
log
.
info
()
<<
term
::
cyan
<<
bar
<<
'\n'
<<
pad
<<
title
<<
'\n'
<<
bar
<<
term
::
reset
<<
"
\n\n
"
<<
indent
<<
"suites: "
<<
term
::
yellow
<<
total_suites
<<
term
::
reset
<<
'\n'
<<
indent
<<
"tests: "
<<
term
::
yellow
<<
total_tests
<<
term
::
reset
<<
'\n'
<<
indent
<<
"checks: "
<<
term
::
yellow
<<
total_good
+
total_bad
<<
term
::
reset
;
if
(
total_bad
>
0
)
{
log
.
info
()
<<
" ("
<<
color
(
green
)
<<
total_good
<<
color
(
reset
)
<<
'/'
<<
color
(
red
)
<<
total_bad
<<
color
(
reset
)
<<
")"
;
log
.
info
()
<<
" ("
<<
term
::
green
<<
total_good
<<
term
::
reset
<<
'/'
<<
term
::
red
<<
total_bad
<<
term
::
reset
<<
")"
;
if
(
total_bad_expected
>
0
)
{
log
.
info
()
<<
' '
<<
color
(
cyan
)
<<
total_bad_expected
<<
color
(
reset
)
<<
' '
<<
term
::
cyan
<<
total_bad_expected
<<
term
::
reset
<<
" failures expected"
;
}
}
log
.
info
()
<<
'\n'
<<
indent
<<
"time: "
<<
color
(
yellow
)
<<
render
(
runtime
)
<<
'\n'
<<
color
(
reset
)
<<
indent
log
.
info
()
<<
'\n'
<<
indent
<<
"time: "
<<
term
::
yellow
<<
render
(
runtime
)
<<
'\n'
<<
term
::
reset
<<
indent
<<
"success: "
<<
(
total_bad
==
total_bad_expected
?
color
(
green
)
:
color
(
red
)
)
<<
percent_good
<<
"%"
<<
color
(
reset
)
<<
"
\n\n
"
;
<<
(
total_bad
==
total_bad_expected
?
term
::
green
:
term
::
red
)
<<
percent_good
<<
"%"
<<
term
::
reset
<<
"
\n\n
"
;
if
(
!
failed_tests
.
empty
())
{
log
.
info
()
<<
indent
<<
"failed tests:"
<<
'\n'
;
for
(
auto
&
name
:
failed_tests
)
log
.
info
()
<<
indent
<<
"- "
<<
name
<<
'\n'
;
log
.
info
()
<<
'\n'
;
}
log
.
info
()
<<
color
(
cyan
)
<<
bar
<<
color
(
reset
)
<<
'\n'
;
log
.
info
()
<<
term
::
cyan
<<
bar
<<
term
::
reset
<<
'\n'
;
return
total_bad
==
total_bad_expected
;
}
const
char
*
engine
::
color
(
color_value
v
,
color_face
t
)
{
return
instance
().
colorize_
?
caf
::
color
(
v
,
t
)
:
""
;
}
const
char
*
engine
::
last_check_file
()
{
return
instance
().
check_file_
;
}
...
...
@@ -583,20 +543,7 @@ int main(int argc, char** argv) {
<<
res
.
helptext
<<
std
::
endl
;
return
1
;
}
# ifdef CAF_WINDOWS
constexpr
bool
colorize
=
false
;
# else
auto
color_support
=
[]()
->
bool
{
if
(
isatty
(
0
)
==
0
)
return
false
;
char
ttybuf
[
50
];
if
(
ttyname_r
(
0
,
ttybuf
,
sizeof
(
ttybuf
))
!=
0
)
return
false
;
char
prefix
[]
=
"/dev/tty"
;
return
strncmp
(
prefix
,
ttybuf
,
sizeof
(
prefix
)
-
1
)
==
0
;
};
auto
colorize
=
color_support
();
# endif
auto
colorize
=
res
.
opts
.
count
(
"no-colors"
)
==
0
;
std
::
vector
<
char
*>
args
;
if
(
divider
<
argc
)
{
// make a new args vector that contains argv[0] and all remaining args
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment