blob: fc998449e66ebfe1ae2916e39f1308407d4d46aa [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <base/containers/contains.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/json/json_string_value_serializer.h>
#include <base/json/values_util.h>
#include <base/rand_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include "shill/logging.h"
#include "shill/scope_logger.h"
#include <gtest/gtest.h>
namespace shill {
class LoggingTest : public testing::Test {
protected:
LoggingTest() = default;
void SetUp() override {
logger_ = ScopeLogger::GetInstance();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
path_ = temp_dir_.GetPath().Append(shill::kLogOverrideFile);
initial_level_ = logging::GetMinLogLevel();
ASSERT_EQ(-initial_level_, logger_->verbose_level());
}
void TearDown() override {
logger_->EnableScopesByName(initial_scopes_);
logging::SetMinLogLevel(initial_level_);
logger_->set_verbose_level(-initial_level_);
}
void ResetDefaultLogging() {
logger_->EnableScopesByName({});
logging::SetMinLogLevel(0);
logger_->set_verbose_level(0);
}
void ExpectDefaulLogging() {
EXPECT_TRUE(logger_->GetEnabledScopeNames().empty());
EXPECT_EQ(logging::GetMinLogLevel(), 0);
EXPECT_EQ(logger_->verbose_level(), 0);
}
void TestInvalidInput(const std::string& content) {
EXPECT_TRUE(base::WriteFile(path_, content));
EXPECT_FALSE(ApplyOverrideLogConfig(path_));
EXPECT_FALSE(base::PathExists(path_));
}
ScopeLogger* logger_;
base::ScopedTempDir temp_dir_;
base::FilePath path_;
int initial_level_;
std::string initial_scopes_;
};
TEST_F(LoggingTest, OverrideLogConfig) {
int level = -3;
std::string scopes{"device+service+wifi"};
logger_->EnableScopesByName(scopes);
logging::SetMinLogLevel(level);
logger_->set_verbose_level(-level);
auto enabled_scopes = logger_->GetEnabledScopeNames();
EXPECT_FALSE(enabled_scopes.empty());
EXPECT_TRUE(PersistOverrideLogConfig(path_, /*enabled=*/true));
// Reset logging and try to restore from config file.
ResetDefaultLogging();
EXPECT_TRUE(ApplyOverrideLogConfig(path_));
EXPECT_EQ(enabled_scopes, logger_->GetEnabledScopeNames());
EXPECT_EQ(level, logging::GetMinLogLevel());
EXPECT_EQ(-level, logger_->verbose_level());
// Now reset logging defaults, remove the log config file and try to restore.
ResetDefaultLogging();
EXPECT_TRUE(PersistOverrideLogConfig(path_, /*enabled=*/false));
EXPECT_FALSE(base::PathExists(path_));
EXPECT_FALSE(ApplyOverrideLogConfig(path_));
ExpectDefaulLogging();
}
TEST_F(LoggingTest, OverrideLogConfig_InvalidJson) {
std::string file_content = "an+invalid+json+format";
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_WrongType) {
std::string file_content = R"(["not", "a", "dictionary"])";
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_NoTime) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
log_config.Set("log-level", 1);
log_config.Set("log-scopes", "device");
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_InvalidTime) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
log_config.Set("log-level", -2);
log_config.Set("log-scopes", "wifi");
log_config.Set("start-time", "garbage");
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_TooOld) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
log_config.Set("log-level", -3);
log_config.Set("log-scopes", "service");
// Valid time stamp but older than 3 days.
auto start = base::Time::Now() - base::Days(4);
log_config.Set("start-time", TimeToValue(start));
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_TooNew) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
log_config.Set("log-level", -3);
log_config.Set("log-scopes", "service");
// Valid time stamp but in the future.
auto start = base::Time::Now() + base::Hours(2);
log_config.Set("start-time", TimeToValue(start));
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_NoLevel) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
auto start = base::Time::Now();
log_config.Set("start-time", TimeToValue(start));
log_config.Set("log-scopes", "wifi");
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_NoScopes) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
auto start = base::Time::Now();
log_config.Set("start-time", TimeToValue(start));
log_config.Set("log-level", -1);
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_InvalidLevel) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
auto start = base::Time::Now();
log_config.Set("start-time", TimeToValue(start));
log_config.Set("log-scopes", "wifi");
log_config.Set("log-level", "failure");
json.Serialize(log_config);
TestInvalidInput(file_content);
}
TEST_F(LoggingTest, OverrideLogConfig_InvalidScopes) {
std::string file_content;
JSONStringValueSerializer json(&file_content);
base::Value::Dict log_config;
auto start = base::Time::Now();
log_config.Set("start-time", TimeToValue(start));
log_config.Set("log-level", -2);
log_config.Set("log-scopes", 3.14);
json.Serialize(log_config);
TestInvalidInput(file_content);
}
} // namespace shill