blob: 84018b3f97092889d742f70041044e86ffa96077 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/api/logging.h"
#include <string>
#include <vector>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "gtest/gtest.h"
#include "platform/impl/logging.h"
#include "platform/impl/logging_test.h"
#include "util/osp_logging.h"
namespace openscreen {
class LoggingTest : public ::testing::Test {
public:
LoggingTest() {}
void SetUp() {
previous_log_level = GetLogLevel();
SetLogLevel(LogLevel::kInfo);
SetLogBufferForTest(&log_messages);
}
void TearDown() {
SetLogLevel(previous_log_level);
SetLogBufferForTest(nullptr);
DisableBreakForTest(nullptr);
}
protected:
void DisableBreak() { DisableBreakForTest(&break_was_called); }
void ExpectLog(LogLevel level, absl::string_view message) {
const char* level_string = "";
switch (level) {
case LogLevel::kVerbose:
level_string = "VERBOSE";
break;
case LogLevel::kInfo:
level_string = "INFO";
break;
case LogLevel::kWarning:
level_string = "WARNING";
break;
case LogLevel::kError:
level_string = "ERROR";
break;
case LogLevel::kFatal:
level_string = "FATAL";
break;
}
expected_messages.push_back({level_string, std::string(message)});
}
void VerifyNoLogs() { EXPECT_TRUE(log_messages.empty()); }
void VerifyLogs() {
ASSERT_EQ(expected_messages.size(), log_messages.size());
auto expected_it = expected_messages.begin();
auto actual_it = log_messages.begin();
// NOTE: This is somewhat brittle; it relies on details of how
// logging_posix.cc formats log messages.
while (expected_it != expected_messages.end()) {
EXPECT_TRUE(
absl::StartsWith(*actual_it, absl::StrCat("[", expected_it->level)));
EXPECT_TRUE(absl::EndsWith(
*actual_it, absl::StrCat("] ", expected_it->message, "\n")));
actual_it++;
expected_it++;
}
expected_messages.clear();
log_messages.clear();
}
void ExpectBreakAndClear() {
EXPECT_TRUE(break_was_called);
break_was_called = false;
}
void ExpectDebugBreakAndClear() {
#if OSP_DCHECK_IS_ON()
EXPECT_TRUE(break_was_called);
break_was_called = false;
#else
EXPECT_FALSE(break_was_called);
#endif // OSP_DCHECK_IS_ON()
}
private:
struct LogMessage {
std::string level;
std::string message;
};
std::vector<std::string> log_messages;
std::vector<LogMessage> expected_messages;
bool break_was_called = false;
LogLevel previous_log_level = LogLevel::kWarning;
};
TEST_F(LoggingTest, UnconditionalLogging) {
SetLogLevel(LogLevel::kVerbose);
ExpectLog(LogLevel::kVerbose, "Verbose");
ExpectLog(LogLevel::kInfo, "Info");
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
OSP_VLOG << "Verbose";
OSP_LOG_INFO << "Info";
OSP_LOG_WARN << "Warning";
OSP_LOG_ERROR << "Error";
VerifyLogs();
SetLogLevel(LogLevel::kWarning);
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
OSP_VLOG << "Verbose";
OSP_LOG_INFO << "Info";
OSP_LOG_WARN << "Warning";
OSP_LOG_ERROR << "Error";
VerifyLogs();
}
TEST_F(LoggingTest, ConditionalLogging) {
SetLogLevel(LogLevel::kVerbose);
ExpectLog(LogLevel::kVerbose, "Verbose");
ExpectLog(LogLevel::kInfo, "Info");
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
OSP_VLOG_IF(true) << "Verbose";
OSP_LOG_IF(INFO, true) << "Info";
OSP_LOG_IF(WARN, true) << "Warning";
OSP_LOG_IF(ERROR, true) << "Error";
VerifyLogs();
OSP_VLOG_IF(false) << "Verbose";
OSP_LOG_IF(INFO, false) << "Info";
OSP_LOG_IF(WARN, false) << "Warning";
OSP_LOG_IF(ERROR, false) << "Error";
VerifyNoLogs();
}
TEST_F(LoggingTest, DebugUnconditionalLogging) {
SetLogLevel(LogLevel::kVerbose);
OSP_DVLOG << "Verbose";
OSP_DLOG_INFO << "Info";
OSP_DLOG_WARN << "Warning";
OSP_DLOG_ERROR << "Error";
#if OSP_DCHECK_IS_ON()
ExpectLog(LogLevel::kVerbose, "Verbose");
ExpectLog(LogLevel::kInfo, "Info");
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
VerifyLogs();
#else
VerifyNoLogs();
#endif // OSP_DCHECK_IS_ON()
SetLogLevel(LogLevel::kWarning);
OSP_DVLOG << "Verbose";
OSP_DLOG_INFO << "Info";
OSP_DLOG_WARN << "Warning";
OSP_DLOG_ERROR << "Error";
#if OSP_DCHECK_IS_ON()
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
VerifyLogs();
#else
VerifyNoLogs();
#endif // OSP_DCHECK_IS_ON()
}
TEST_F(LoggingTest, DebugConditionalLogging) {
SetLogLevel(LogLevel::kVerbose);
OSP_DVLOG_IF(true) << "Verbose";
OSP_DLOG_IF(INFO, true) << "Info";
OSP_DLOG_IF(WARN, true) << "Warning";
OSP_DLOG_IF(ERROR, true) << "Error";
#if OSP_DCHECK_IS_ON()
ExpectLog(LogLevel::kVerbose, "Verbose");
ExpectLog(LogLevel::kInfo, "Info");
ExpectLog(LogLevel::kWarning, "Warning");
ExpectLog(LogLevel::kError, "Error");
VerifyLogs();
#else
VerifyNoLogs();
#endif // OSP_DCHECK_IS_ON()
OSP_DVLOG_IF(false) << "Verbose";
OSP_DLOG_IF(INFO, false) << "Info";
OSP_DLOG_IF(WARN, false) << "Warning";
OSP_DLOG_IF(ERROR, false) << "Error";
VerifyNoLogs();
}
TEST_F(LoggingTest, CheckAndLogFatal) {
DisableBreak();
ExpectLog(LogLevel::kFatal, "OSP_CHECK(false) failed: ");
OSP_CHECK(false);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) == (2)) failed: 1 vs. 2: ");
OSP_CHECK_EQ(1, 2);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) != (1)) failed: 1 vs. 1: ");
OSP_CHECK_NE(1, 1);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((2) < (1)) failed: 2 vs. 1: ");
OSP_CHECK_LT(2, 1);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((2) <= (1)) failed: 2 vs. 1: ");
OSP_CHECK_LE(2, 1);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) > (2)) failed: 1 vs. 2: ");
OSP_CHECK_GT(1, 2);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) >= (2)) failed: 1 vs. 2: ");
OSP_CHECK_GE(1, 2);
ExpectBreakAndClear();
ExpectLog(LogLevel::kFatal, "Fatal");
OSP_LOG_FATAL << "Fatal";
ExpectBreakAndClear();
VerifyLogs();
}
TEST_F(LoggingTest, DCheckAndDLogFatal) {
DisableBreak();
ExpectLog(LogLevel::kFatal, "OSP_CHECK(false) failed: ");
OSP_DCHECK(false);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) == (2)) failed: 1 vs. 2: ");
OSP_DCHECK_EQ(1, 2);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) != (1)) failed: 1 vs. 1: ");
OSP_DCHECK_NE(1, 1);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((2) < (1)) failed: 2 vs. 1: ");
OSP_DCHECK_LT(2, 1);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((2) <= (1)) failed: 2 vs. 1: ");
OSP_DCHECK_LE(2, 1);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) > (2)) failed: 1 vs. 2: ");
OSP_DCHECK_GT(1, 2);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "OSP_CHECK((1) >= (2)) failed: 1 vs. 2: ");
OSP_DCHECK_GE(1, 2);
ExpectDebugBreakAndClear();
ExpectLog(LogLevel::kFatal, "Fatal");
OSP_DLOG_FATAL << "Fatal";
ExpectDebugBreakAndClear();
#if OSP_DCHECK_IS_ON()
VerifyLogs();
#else
VerifyNoLogs();
#endif // OSP_DCHECK_IS_ON()
}
TEST_F(LoggingTest, OspUnimplemented) {
// Default is to log once per process if the level >= kWarning.
SetLogLevel(LogLevel::kWarning);
ExpectLog(LogLevel::kWarning, "TestBody: UNIMPLEMENTED() hit.");
for (int i = 0; i < 2; i++) {
OSP_UNIMPLEMENTED();
}
VerifyLogs();
// Setting the level to kVerbose logs every time.
SetLogLevel(LogLevel::kVerbose);
std::string message("TestBody: UNIMPLEMENTED() hit.");
ExpectLog(LogLevel::kVerbose, message);
ExpectLog(LogLevel::kVerbose, message);
for (int i = 0; i < 2; i++) {
OSP_UNIMPLEMENTED();
}
VerifyLogs();
}
TEST_F(LoggingTest, OspNotReached) {
DisableBreak();
ExpectLog(LogLevel::kFatal, "TestBody: NOTREACHED() hit.");
OSP_NOTREACHED();
VerifyLogs();
ExpectBreakAndClear();
}
} // namespace openscreen