/* Copyright 2013 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #include "mongo/platform/basic.h" #include "mongo/bson/util/builder.h" #include "mongo/db/server_options.h" #include "mongo/db/server_options_helpers.h" #include "mongo/logger/logger.h" #include "mongo/unittest/unittest.h" #include "mongo/util/options_parser/environment.h" #include "mongo/util/options_parser/option_section.h" #include "mongo/util/options_parser/options_parser.h" namespace { using mongo::ErrorCodes; using mongo::Status; namespace moe = mongo::optionenvironment; class OptionsParserTester : public moe::OptionsParser { public: Status readConfigFile(const std::string& filename, std::string* config) { if (filename != _filename) { ::mongo::StringBuilder sb; sb << "Parser using filename: " << filename << " which does not match expected filename: " << _filename; return Status(ErrorCodes::InternalError, sb.str()); } *config = _config; return Status::OK(); } void setConfig(const std::string& filename, const std::string& config) { _filename = filename; _config = config; } private: std::string _filename; std::string _config; }; TEST(Verbosity, Default) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); // Make sure the log level didn't change since we didn't specify any verbose options ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Info()); } TEST(Verbosity, CommandLineImplicit) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--verbose"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 1; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, CommandLineString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--verbose"); argv.push_back("vvvv"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 4; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, CommandLineStringDisguisedLongForm) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("-verbose"); argv.push_back("vvvv"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 4; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, CommandLineEmptyString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--verbose"); argv.push_back(""); std::map env_map; ASSERT_NOT_OK(parser.run(options, argv, env_map, &environment)); } TEST(Verbosity, CommandLineBadString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--verbose"); argv.push_back("beloud"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_NOT_OK(::mongo::validateServerOptions(environment)); } TEST(Verbosity, CommandLineBadStringOnlyDash) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("-"); std::map env_map; ASSERT_NOT_OK(parser.run(options, argv, env_map, &environment)); } TEST(Verbosity, CommandLineBadStringOnlyTwoDashes) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--"); std::map env_map; ASSERT_OK(parser.run(options, argv, env_map, &environment)); } TEST(Verbosity, INIConfigString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.ini"); std::map env_map; parser.setConfig("config.ini", "verbose=vvvv"); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 4; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, INIConfigBadString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.ini"); std::map env_map; parser.setConfig("config.ini", "verbose=beloud"); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_NOT_OK(::mongo::validateServerOptions(environment)); } TEST(Verbosity, INIConfigEmptyString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.ini"); std::map env_map; parser.setConfig("config.ini", "verbose="); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 0; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, JSONConfigString) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.json"); std::map env_map; parser.setConfig("config.json", "{ \"systemLog.verbosity\" : 4 }"); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 4; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, MultipleSourcesMultipleOptions) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.json"); argv.push_back("--verbose"); argv.push_back("vvv"); std::map env_map; parser.setConfig("config.json", "{ \"systemLog.verbosity\" : 4 }"); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); int verbosity = 3; ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); } TEST(Verbosity, YAMLConfigStringLogComponent) { OptionsParserTester parser; moe::Environment environment; moe::OptionSection options; // Reset the log level before we test ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogSeverity::Info()); // Log level for Storage will be cleared by config file value. ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity( ::mongo::logger::LogComponent::kStorage, ::mongo::logger::LogSeverity::Debug(1)); ASSERT_OK(::mongo::addGeneralServerOptions(&options)); std::vector argv; argv.push_back("binaryname"); argv.push_back("--config"); argv.push_back("config.yaml"); std::map env_map; parser.setConfig("config.yaml", "systemLog:\n" " verbosity: 4\n" " component:\n" " accessControl:\n" " verbosity: 0\n" " storage:\n" " verbosity: -1\n" " journal:\n" " verbosity: 2\n"); ASSERT_OK(parser.run(options, argv, env_map, &environment)); ASSERT_OK(::mongo::validateServerOptions(environment)); ASSERT_OK(::mongo::canonicalizeServerOptions(&environment)); ASSERT_OK(::mongo::storeServerOptions(environment, argv)); // Verify component log levels using global log domain. int verbosity = 4; // Default ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity(), ::mongo::logger::LogSeverity::Debug(verbosity)); ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity( ::mongo::logger::LogComponent::kDefault), ::mongo::logger::LogSeverity::Debug(verbosity)); // AccessControl ASSERT_TRUE(::mongo::logger::globalLogDomain()->hasMinimumLogSeverity( ::mongo::logger::LogComponent::kAccessControl)); ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity( ::mongo::logger::LogComponent::kAccessControl), ::mongo::logger::LogSeverity::Log()); // Query - not mentioned in configuration. should match default. ASSERT_FALSE(::mongo::logger::globalLogDomain()->hasMinimumLogSeverity( ::mongo::logger::LogComponent::kStorage)); ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity( ::mongo::logger::LogComponent::kStorage), ::mongo::logger::LogSeverity::Debug(verbosity)); // Storage - cleared by -1 value in configuration. should match default. ASSERT_FALSE(::mongo::logger::globalLogDomain()->hasMinimumLogSeverity( ::mongo::logger::LogComponent::kStorage)); ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity( ::mongo::logger::LogComponent::kStorage), ::mongo::logger::LogSeverity::Debug(verbosity)); // Journaling - explicitly set to 2 in configuration. ASSERT_TRUE(::mongo::logger::globalLogDomain()->hasMinimumLogSeverity( ::mongo::logger::LogComponent::kJournal)); ASSERT_EQUALS(::mongo::logger::globalLogDomain()->getMinimumLogSeverity( ::mongo::logger::LogComponent::kJournal), ::mongo::logger::LogSeverity::Debug(2)); } } // unnamed namespace