forked from pz4kybsvg/Conception
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.5 KiB
183 lines
5.5 KiB
2 years ago
|
#include "drake/common/text_logging.h"
|
||
|
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <gmock/gmock.h>
|
||
|
#include <gtest/gtest.h>
|
||
|
|
||
|
// The BUILD.bazel rules must supply this flag. This test code is compiled and
|
||
|
// run twice -- once with spdlog, and once without.
|
||
|
#ifndef TEXT_LOGGING_TEST_SPDLOG
|
||
|
#error Missing a required definition to compile this test case.
|
||
|
#endif
|
||
|
|
||
|
// Check for the expected HAVE_SPDLOG value.
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
#ifndef HAVE_SPDLOG
|
||
|
#error Missing HAVE_SPDLOG.
|
||
|
#endif
|
||
|
#else
|
||
|
#ifdef HAVE_SPDLOG
|
||
|
#error Unwanted HAVE_SPDLOG.
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
namespace {
|
||
|
class Formattable {
|
||
|
public:
|
||
|
std::string to_string() const { return "OK"; }
|
||
|
};
|
||
|
} // namespace
|
||
|
|
||
|
DRAKE_FORMATTER_AS(, , Formattable, x, x.to_string())
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
using drake::logging::kHaveSpdlog;
|
||
|
|
||
|
// Call each API function and macro to ensure that all of them compile.
|
||
|
// These should all compile and run both with and without spdlog.
|
||
|
GTEST_TEST(TextLoggingTest, SmokeTestFormattable) {
|
||
|
Formattable obj;
|
||
|
drake::log()->trace("drake::log()->trace test: {} {}", "OK", obj);
|
||
|
drake::log()->debug("drake::log()->debug test: {} {}", "OK", obj);
|
||
|
drake::log()->info("drake::log()->info test: {} {}", "OK", obj);
|
||
|
drake::log()->warn("drake::log()->warn test: {} {}", "OK", obj);
|
||
|
drake::log()->error("drake::log()->error test: {} {}", "OK", obj);
|
||
|
drake::log()->critical("drake::log()->critical test: {} {}", "OK", obj);
|
||
|
DRAKE_LOGGER_TRACE("DRAKE_LOGGER_TRACE macro test: {}, {}",
|
||
|
"OK", obj);
|
||
|
DRAKE_LOGGER_DEBUG("DRAKE_LOGGER_DEBUG macro test: {}, {}",
|
||
|
"OK", obj);
|
||
|
}
|
||
|
|
||
|
// Check that floating point values format sensibly. We'll just test fmt
|
||
|
// directly, since we know that spdlog uses it internally.
|
||
|
GTEST_TEST(TextLoggingTest, FloatingPoint) {
|
||
|
EXPECT_EQ(fmt::format("{:#}", 1.0), "1.0");
|
||
|
// This number is particularly challenging.
|
||
|
EXPECT_EQ(fmt::format("{}", 0.009), "0.009");
|
||
|
}
|
||
|
|
||
|
// Check that the constexpr bool is set correctly.
|
||
|
GTEST_TEST(TextLoggingTest, ConstantTest) {
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
EXPECT_TRUE(kHaveSpdlog);
|
||
|
#else
|
||
|
EXPECT_FALSE(kHaveSpdlog);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// Check that the "warn once" idiom compiles and doesn't crash at runtime.
|
||
|
GTEST_TEST(TextLoggingTest, WarnOnceTest) {
|
||
|
static const drake::logging::Warn log_once(
|
||
|
"The log_once happened as expected.");
|
||
|
}
|
||
|
|
||
|
// Abuse gtest internals to verify that logging actually prints when enabled,
|
||
|
// and that the default level is INFO.
|
||
|
GTEST_TEST(TextLoggingTest, CaptureOutputTest) {
|
||
|
testing::internal::CaptureStderr();
|
||
|
drake::log()->trace("bad sentinel");
|
||
|
drake::log()->debug("bad sentinel");
|
||
|
drake::log()->info("good sentinel");
|
||
|
std::string output = testing::internal::GetCapturedStderr();
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
EXPECT_TRUE(output.find("good sentinel") != std::string::npos);
|
||
|
EXPECT_TRUE(output.find("bad sentinel") == std::string::npos);
|
||
|
#else
|
||
|
EXPECT_EQ(output, "");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// Verify that DRAKE_LOGGER macros succeed in avoiding evaluation of their
|
||
|
// arguments.
|
||
|
GTEST_TEST(TextLoggingTest, DrakeMacrosDontEvaluateArguments) {
|
||
|
int tracearg = 0, debugarg = 0;
|
||
|
|
||
|
// Shouldn't increment argument whether the macro expanded or not, since
|
||
|
// logging is off.
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
drake::log()->set_level(spdlog::level::off);
|
||
|
#endif
|
||
|
DRAKE_LOGGER_TRACE("tracearg={}", ++tracearg);
|
||
|
DRAKE_LOGGER_DEBUG("debugarg={}", ++debugarg);
|
||
|
EXPECT_EQ(tracearg, 0);
|
||
|
EXPECT_EQ(debugarg, 0);
|
||
|
tracearg = 0;
|
||
|
debugarg = 0;
|
||
|
|
||
|
// Should increment arg only if the macro expanded.
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
drake::log()->set_level(spdlog::level::trace);
|
||
|
#endif
|
||
|
DRAKE_LOGGER_TRACE("tracearg={}", ++tracearg);
|
||
|
DRAKE_LOGGER_DEBUG("debugarg={}", ++debugarg);
|
||
|
#ifndef NDEBUG
|
||
|
EXPECT_EQ(tracearg, kHaveSpdlog ? 1 : 0);
|
||
|
EXPECT_EQ(debugarg, kHaveSpdlog ? 1 : 0);
|
||
|
#else
|
||
|
EXPECT_EQ(tracearg, 0);
|
||
|
EXPECT_EQ(debugarg, 0);
|
||
|
#endif
|
||
|
tracearg = 0;
|
||
|
debugarg = 0;
|
||
|
|
||
|
// Only DEBUG should increment arg since trace is not enabled.
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
drake::log()->set_level(spdlog::level::debug);
|
||
|
#endif
|
||
|
DRAKE_LOGGER_TRACE("tracearg={}", ++tracearg);
|
||
|
DRAKE_LOGGER_DEBUG("debugarg={}", ++debugarg);
|
||
|
#ifndef NDEBUG
|
||
|
EXPECT_EQ(tracearg, 0);
|
||
|
EXPECT_EQ(debugarg, kHaveSpdlog ? 1 : 0);
|
||
|
#else
|
||
|
EXPECT_EQ(tracearg, 0);
|
||
|
EXPECT_EQ(debugarg, 0);
|
||
|
#endif
|
||
|
tracearg = 0;
|
||
|
debugarg = 0;
|
||
|
}
|
||
|
|
||
|
GTEST_TEST(TextLoggingTest, SetLogLevel) {
|
||
|
using drake::logging::set_log_level;
|
||
|
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
EXPECT_THROW(set_log_level("bad"), std::runtime_error);
|
||
|
const std::vector<std::string> levels = {
|
||
|
"trace", "debug", "info", "warn", "err", "critical", "off"};
|
||
|
const std::string first_level = set_log_level("unchanged");
|
||
|
std::string prev_level = "off";
|
||
|
set_log_level(prev_level);
|
||
|
for (const std::string& level : levels) {
|
||
|
EXPECT_EQ(set_log_level(level), prev_level);
|
||
|
prev_level = level;
|
||
|
}
|
||
|
set_log_level(first_level);
|
||
|
#else
|
||
|
ASSERT_EQ(drake::logging::set_log_level("anything really"), "");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
GTEST_TEST(TextLoggingTest, SetLogPattern) {
|
||
|
using drake::logging::set_log_pattern;
|
||
|
|
||
|
#if TEXT_LOGGING_TEST_SPDLOG
|
||
|
set_log_pattern("%v");
|
||
|
set_log_pattern("%+");
|
||
|
#else
|
||
|
set_log_pattern("anything really");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
} // anon namespace
|
||
|
|
||
|
// To enable compiling without depending on @spdlog, we need to provide our own
|
||
|
// main routine. The default drake_cc_googletest_main depends on @spdlog.
|
||
|
int main(int argc, char** argv) {
|
||
|
testing::InitGoogleTest(&argc, argv);
|
||
|
return RUN_ALL_TESTS();
|
||
|
}
|