Add flag aliasing, logger/flag tests

This commit is contained in:
Teddy Reed 2015-02-17 01:36:20 -07:00
parent fc64965c68
commit 1f8dacec3c
23 changed files with 418 additions and 159 deletions

View File

@ -12,6 +12,8 @@
#include <map>
#include <boost/lexical_cast.hpp>
#define STRIP_FLAG_HELP 1
#include <gflags/gflags.h>
@ -19,6 +21,16 @@
#define GFLAGS_NAMESPACE google
namespace boost {
/// We define a lexical_cast template for boolean for Gflags boolean string
/// values.
template <>
bool lexical_cast<bool, std::string>(const std::string& arg);
template <>
std::string lexical_cast<std::string, bool>(const bool& b);
}
namespace osquery {
struct FlagDetail {
@ -39,7 +51,7 @@ struct FlagInfo {
* @brief A small tracking wrapper for options, binary flags.
*
* The osquery-specific gflags-like options define macro `FLAG` uses a Flag
& instance to track the options data.
* instance to track the options data.
*/
class Flag {
public:
@ -51,9 +63,9 @@ class Flag {
*
* @return A mostly needless flag instance.
*/
static int create(const std::string& name, FlagDetail flag);
static int create(const std::string& name, const FlagDetail& flag);
/// Create a glags alias to name, using the Flag::getValue accessor.
/// Create a Gflags alias to name, using the Flag::getValue accessor.
static int createAlias(const std::string& alias, const std::string& name);
static Flag& instance() {
@ -106,16 +118,18 @@ class Flag {
*/
static std::string getValue(const std::string& name);
template <typename T>
static T getValue(const std::string& name) {
T intermediate;
return intermediate;
}
/*
* @brief Get the type as a string of an osquery flag.
*
* @param name the flag name.
*/
static std::string getType(const std::string& name);
/*
* @brief Print help-style output to stdout for a given flag set.
*
* @param shell_only Only print shell flags.
* @param shell Only print shell flags.
* @param external Only print external flags (from extensions).
*/
static void printFlags(bool shell = false, bool external = false);
@ -123,6 +137,34 @@ class Flag {
std::map<std::string, FlagDetail> flags_;
std::map<std::string, std::string> aliases_;
};
/**
* @brief Helper accessor/assignment alias class to support deprecated flags.
*
* This templated class wraps Flag::updateValue and Flag::getValue to 'alias'
* a deprecated flag name as the updated name. The helper macro FLAG_ALIAS
* will create a global variable instances of this wrapper using the same
* Gflags naming scheme to prevent collisions and support existing callsites.
*/
template <typename T>
class FlagAlias {
public:
FlagAlias& operator=(T const& v) {
Flag::updateValue(name_, boost::lexical_cast<std::string>(v));
return *this;
}
operator T() const { return boost::lexical_cast<T>(Flag::getValue(name_)); }
FlagAlias(const std::string& alias,
const std::string& type,
const std::string& name,
T* storage)
: name_(name) {}
private:
std::string name_;
};
}
/*
@ -143,11 +185,10 @@ class Flag {
#define SHELL_FLAG(t, n, v, d) OSQUERY_FLAG(t, n, v, d, true, false)
#define EXTENSION_FLAG(t, n, v, d) OSQUERY_FLAG(t, n, v, d, false, true)
#define FLAG_ALIAS(t, n, a) \
DEFINE_##t(a, FLAGS_##n); \
#define FLAG_ALIAS(t, a, n) \
FlagAlias<t> FLAGS_##a(#a, #t, #n, &FLAGS_##n); \
namespace flags { \
static GFLAGS_NAMESPACE::FlagRegisterer oflag_##a( \
#a, #t, #a, #a, &FLAGS_##n, &FLAGS_##n); \
const int flag_alias_##a = Flag::createAlias(#a, #n); \
}
#define DEFINE_osquery_flag(t, n, v, d) FLAG(t, n, v, d)
#define DEFINE_shell_flag(t, n, v, d) SHELL_FLAG(t, n, v, d)

View File

@ -104,7 +104,7 @@ class LoggerPlugin : public Plugin {
* has been loaded (which may include additional CLI flag-options).
*
* All of these actions may have generated VERBOSE, INFO, WARNING, or ERROR
* logs. The internal logging facility is, glog, collects these intermediate
* logs. The internal logging facility, Glog, collects these intermediate
* status logs and a customized log sink buffers them until the active
* osquery logger's `init` method is called.
*
@ -144,7 +144,7 @@ class LoggerPlugin : public Plugin {
void initStatusLogger(const std::string& name);
/**
* @brief Initialize the osquery Logger facility by dump the buffered status
* @brief Initialize the osquery Logger facility by dumping the buffered status
* logs and configurating status log forwarding.
*
* initLogger will disable the `BufferedLogSink` facility, dump any status logs

View File

@ -28,10 +28,7 @@ typedef std::map<std::string, std::vector<std::string> > EventFileMap_t;
namespace osquery {
DEFINE_osquery_flag(string,
config_plugin,
"filesystem",
"Config type (plugin)");
FLAG(string, config_plugin, "filesystem", "Config type (plugin)");
// This lock is used to protect the entirety of the OSqueryConfig struct
// Is should be used when ever accessing the structs members, reading or

View File

@ -21,10 +21,7 @@ using osquery::Status;
namespace osquery {
DEFINE_osquery_flag(string,
config_path,
"/var/osquery/osquery.conf",
"Path to config file");
FLAG(string, config_path, "/var/osquery/osquery.conf", "Path to config file");
class FilesystemConfigPlugin : public ConfigPlugin {
public:

View File

@ -22,9 +22,10 @@ ADD_OSQUERY_LIBRARY(TRUE osquery_test_util
test_util.cpp
)
ADD_OSQUERY_TEST(TRUE flags_tests flags_tests.cpp)
ADD_OSQUERY_TEST(TRUE hash_test hash_tests.cpp)
ADD_OSQUERY_TEST(TRUE status_test status_tests.cpp)
ADD_OSQUERY_TEST(TRUE tables_tests tables_tests.cpp)
ADD_OSQUERY_TEST(TRUE test_util_tests test_util_tests.cpp)
ADD_OSQUERY_TEST(TRUE text_tests text_tests.cpp)
ADD_OSQUERY_TEST(TRUE conversions_tests conversions_tests.cpp)
ADD_OSQUERY_TEST(TRUE conversions_tests conversions_tests.cpp)

View File

@ -10,9 +10,26 @@
#include <osquery/flags.h>
namespace boost {
template <>
bool lexical_cast<bool, std::string>(const std::string& arg) {
std::istringstream ss(arg);
bool b;
ss >> std::boolalpha >> b;
return b;
}
template <>
std::string lexical_cast<std::string, bool>(const bool& b) {
std::ostringstream ss;
ss << std::boolalpha << b;
return ss.str();
}
}
namespace osquery {
int Flag::create(const std::string& name, FlagDetail flag) {
int Flag::create(const std::string& name, const FlagDetail& flag) {
instance().flags_.insert(std::make_pair(name, flag));
return 0;
}
@ -47,6 +64,14 @@ std::string Flag::getValue(const std::string& name) {
return current_value;
}
std::string Flag::getType(const std::string& name) {
GFLAGS_NAMESPACE::CommandLineFlagInfo info;
if (!GFLAGS_NAMESPACE::GetCommandLineFlagInfo(name.c_str(), &info)) {
return "";
}
return info.type;
}
Status Flag::updateValue(const std::string& name, const std::string& value) {
GFLAGS_NAMESPACE::SetCommandLineOption(name.c_str(), value.c_str());
return Status(0, "OK");
@ -62,8 +87,12 @@ std::map<std::string, FlagInfo> Flag::flags() {
// This flag info was not defined within osquery.
continue;
}
// Set the flag info from the internal info kept by Gflags, except for
// the stored description. Gflag keeps an "unknown" value if the flag
// was declared without a definition.
flags[flag.name] = {flag.type,
flag.description,
instance().flags_.at(flag.name).description,
flag.default_value,
flag.current_value,
instance().flags_.at(flag.name)};

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include <gtest/gtest.h>
#include <osquery/core.h>
#include <osquery/flags.h>
#include <osquery/logger.h>
namespace osquery {
DECLARE_string(test_string_flag);
class FlagsTests : public testing::Test {
public:
FlagsTests() {}
void SetUp() {}
};
FLAG(string, test_string_flag, "TEST STRING", "TEST DESCRIPTION");
TEST_F(FlagsTests, test_set_get) {
// Test the core gflags functionality.
EXPECT_EQ(FLAGS_test_string_flag, "TEST STRING");
// Check that the gflags flag name was recorded in the osquery flag tracker.
auto all_flags = Flag::flags();
EXPECT_EQ(all_flags.count("test_string_flag"), 1);
// Update the value of the flag, and access through the osquery wrapper.
FLAGS_test_string_flag = "NEW TEST STRING";
EXPECT_EQ(Flag::getValue("test_string_flag"), "NEW TEST STRING");
}
TEST_F(FlagsTests, test_defaults) {
// Make sure the flag value was not reset.
EXPECT_EQ(FLAGS_test_string_flag, "NEW TEST STRING");
// Now test that the default value is tracked.
EXPECT_FALSE(Flag::isDefault("test_string_flag"));
// Check the default value accessor.
std::string default_value;
auto status = Flag::getDefaultValue("test_mistake", default_value);
EXPECT_FALSE(status.ok());
status = Flag::getDefaultValue("test_string_flag", default_value);
EXPECT_TRUE(status.ok());
EXPECT_EQ(default_value, "TEST STRING");
}
TEST_F(FlagsTests, test_details) {
// Make sure flag details are tracked correctly.
auto all_flags = Flag::flags();
auto flag_info = all_flags["test_string_flag"];
EXPECT_EQ(flag_info.type, "string");
EXPECT_EQ(flag_info.description, "TEST DESCRIPTION");
EXPECT_EQ(flag_info.default_value, "TEST STRING");
EXPECT_EQ(flag_info.value, "NEW TEST STRING");
EXPECT_EQ(flag_info.detail.shell, false);
EXPECT_EQ(flag_info.detail.external, false);
}
SHELL_FLAG(bool, shell_only, true, "TEST SHELL DESCRIPTION");
EXTENSION_FLAG(bool, extension_only, true, "TEST EXTENSION DESCRIPTION");
TEST_F(FlagsTests, test_flag_detail_types) {
EXPECT_TRUE(FLAGS_shell_only);
EXPECT_TRUE(FLAGS_extension_only);
auto all_flags = Flag::flags();
EXPECT_TRUE(all_flags["shell_only"].detail.shell);
EXPECT_TRUE(all_flags["extension_only"].detail.external);
}
FLAG_ALIAS(bool, shell_only_alias, shell_only);
TEST_F(FlagsTests, test_aliases) {
EXPECT_TRUE(FLAGS_shell_only_alias);
FLAGS_shell_only = false;
EXPECT_FALSE(FLAGS_shell_only);
EXPECT_FALSE(FLAGS_shell_only_alias);
}
FLAG(int32, test_int32, 1, "none");
FLAG_ALIAS(google::int32, test_int32_alias, test_int32);
FLAG(int64, test_int64, (int64_t)1 << 34, "none");
FLAG_ALIAS(google::int64, test_int64_alias, test_int64);
FLAG(double, test_double, 4.2, "none");
FLAG_ALIAS(double, test_double_alias, test_double);
FLAG(string, test_string, "test", "none");
FLAG_ALIAS(std::string, test_string_alias, test_string);
TEST_F(FlagsTests, test_alias_types) {
// Test int32 lexical casting both ways.
EXPECT_EQ(FLAGS_test_int32_alias, 1);
FLAGS_test_int32_alias = 2;
EXPECT_EQ(FLAGS_test_int32, 2);
FLAGS_test_int32 = 3;
EXPECT_EQ(FLAGS_test_int32_alias, 3);
EXPECT_TRUE(FLAGS_test_int32_alias > 0);
EXPECT_EQ(FLAGS_test_int64_alias, (int64_t)1 << 34);
FLAGS_test_int64_alias = (int64_t)1 << 35;
EXPECT_EQ(FLAGS_test_int64, (int64_t)1 << 35);
FLAGS_test_int64 = (int64_t)1 << 36;
EXPECT_EQ(FLAGS_test_int64_alias, (int64_t)1 << 36);
EXPECT_TRUE(FLAGS_test_int64_alias > 0);
EXPECT_EQ(FLAGS_test_double_alias, 4.2);
FLAGS_test_double_alias = 2.4;
EXPECT_EQ(FLAGS_test_double, 2.4);
FLAGS_test_double = 22.44;
EXPECT_EQ(FLAGS_test_double_alias, 22.44);
EXPECT_TRUE(FLAGS_test_double_alias > 0);
// Compile-time type checking will not compare typename T to const char*
std::string value = FLAGS_test_string_alias;
EXPECT_EQ(value, "test");
FLAGS_test_string_alias = "test2";
EXPECT_EQ(FLAGS_test_string, "test2");
FLAGS_test_string = "test3";
// Test both the copy and assignment constructor aliases.
value = FLAGS_test_string_alias;
auto value2 = (std::string)FLAGS_test_string_alias;
EXPECT_EQ(value, "test3");
}
}
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -25,14 +25,11 @@ const std::string kDescription =
"relational database";
const std::string kEpilog = "osquery project page <http://osquery.io>.";
DEFINE_osquery_flag(bool,
config_check,
false,
"Check the format of an osquery config");
FLAG(bool, config_check, false, "Check the format of an osquery config");
#ifndef __APPLE__
namespace osquery {
DEFINE_osquery_flag(bool, daemonize, false, "Run as daemon (osqueryd only)");
FLAG(bool, daemonize, false, "Run as daemon (osqueryd only)");
}
#endif

View File

@ -35,16 +35,13 @@ namespace fs = boost::filesystem;
namespace osquery {
/// The path to the pidfile for osqueryd
DEFINE_osquery_flag(string,
pidfile,
"/var/osquery/osqueryd.pidfile",
"The path to the pidfile for osqueryd");
FLAG(string,
pidfile,
"/var/osquery/osqueryd.pidfile",
"The path to the pidfile for osqueryd");
/// Should the daemon force unload previously-running osqueryd daemons.
DEFINE_osquery_flag(bool,
force,
false,
"Force osqueryd to kill previously-running daemons");
FLAG(bool, force, false, "Force osqueryd to kill previously-running daemons");
std::string getHostname() {
char hostname[256]; // Linux max should be 64.

View File

@ -41,16 +41,12 @@ const std::map<WatchdogLimitType, std::vector<size_t> > kWatchdogLimits = {
// How often to poll for performance limit violations.
{INTERVAL, {3, 3, 3}}, };
DEFINE_osquery_flag(
int32,
watchdog_level,
1,
"Performance limit level (0=loose, 1=normal, 2=restrictive)");
FLAG(int32,
watchdog_level,
1,
"Performance limit level (0=loose, 1=normal, 2=restrictive)");
DEFINE_osquery_flag(bool,
disable_watchdog,
false,
"Disable userland watchdog process");
FLAG(bool, disable_watchdog, false, "Disable userland watchdog process");
bool Watcher::ok() {
::sleep(getWorkerLimit(INTERVAL));

View File

@ -32,15 +32,15 @@ const std::string kEvents = "events";
const std::vector<std::string> kDomains = {kConfigurations, kQueries, kEvents};
DEFINE_osquery_flag(string,
db_path,
"/var/osquery/osquery.db",
"If using a disk-based backing store, specify a path");
FLAG(string,
db_path,
"/var/osquery/osquery.db",
"If using a disk-based backing store, specify a path");
DEFINE_osquery_flag(bool,
use_in_memory_database,
false,
"Keep osquery backing-store in memory");
FLAG(bool,
use_in_memory_database,
false,
"Keep osquery backing-store in memory");
/////////////////////////////////////////////////////////////////////////////
// constructors and destructors

View File

@ -4108,43 +4108,37 @@ static char *cmdline_option_value(int argc, char **argv, int i) {
namespace osquery {
/// Define flags used by the shell. They are parsed by the drop-in shell.
DEFINE_shell_flag(bool, bail, false, "stop after hitting an error");
DEFINE_shell_flag(bool, batch, false, "force batch I/O");
DEFINE_shell_flag(bool, column, false, "set output mode to 'column'");
DEFINE_shell_flag(string, cmd, "", "run \"COMMAND\" before reading stdin");
DEFINE_shell_flag(bool, csv, false, "set output mode to 'csv'");
DEFINE_shell_flag(bool, json, false, "set output mode to 'json'");
DEFINE_shell_flag(bool, echo, false, "print commands before execution");
DEFINE_shell_flag(string, init, "", "read/process named file");
DEFINE_shell_flag(bool, header, true, "turn headers on or off");
DEFINE_shell_flag(bool, html, false, "set output mode to HTML");
DEFINE_shell_flag(bool, interactive, false, "force interactive I/O");
DEFINE_shell_flag(bool, line, false, "set output mode to 'line'");
DEFINE_shell_flag(bool, list, false, "set output mode to 'list'");
DEFINE_shell_flag(int64, mmap, 0, "default mmap size set to N");
DEFINE_shell_flag(string,
nullvalue,
"",
"set text string for NULL values. Default ''");
DEFINE_shell_flag(string,
separator,
"|",
"set output field separator. Default: '|'");
DEFINE_shell_flag(bool,
stats,
false,
"print memory stats before each finalize");
DEFINE_shell_flag(string, vfs, "", "use NAME as the default VFS");
SHELL_FLAG(bool, bail, false, "stop after hitting an error");
SHELL_FLAG(bool, batch, false, "force batch I/O");
SHELL_FLAG(bool, column, false, "set output mode to 'column'");
SHELL_FLAG(string, cmd, "", "run \"COMMAND\" before reading stdin");
SHELL_FLAG(bool, csv, false, "set output mode to 'csv'");
SHELL_FLAG(bool, json, false, "set output mode to 'json'");
SHELL_FLAG(bool, echo, false, "print commands before execution");
SHELL_FLAG(string, init, "", "read/process named file");
SHELL_FLAG(bool, header, true, "turn headers on or off");
SHELL_FLAG(bool, html, false, "set output mode to HTML");
SHELL_FLAG(bool, interactive, false, "force interactive I/O");
SHELL_FLAG(bool, line, false, "set output mode to 'line'");
SHELL_FLAG(bool, list, false, "set output mode to 'list'");
SHELL_FLAG(int64, mmap, 0, "default mmap size set to N");
SHELL_FLAG(string,
nullvalue,
"",
"set text string for NULL values. Default ''");
SHELL_FLAG(string, separator, "|", "set output field separator. Default: '|'");
SHELL_FLAG(bool, stats, false, "print memory stats before each finalize");
SHELL_FLAG(string, vfs, "", "use NAME as the default VFS");
/// Optional flags enabled at compile time.
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
DEFINE_shell_flag(int64, heap, 0, "Size of heap for memsys3 or memsys5");
SHELL_FLAG(int64, heap, 0, "Size of heap for memsys3 or memsys5");
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
DEFINE_shell_flag(bool, multiplex, false, "enable the multiplexor VFS");
SHELL_FLAG(bool, multiplex, false, "enable the multiplexor VFS");
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
DEFINE_shell_flag(bool, vfstrace, false, "enable tracing of all VFS calls");
SHELL_FLAG(bool, vfstrace, false, "enable tracing of all VFS calls");
#endif
int launchIntoShell(int argc, char **argv) {

View File

@ -21,10 +21,7 @@ using namespace apache::thrift::concurrency;
namespace osquery {
/// The worker_threads define the default thread pool size.
DEFINE_osquery_flag(int32,
worker_threads,
4,
"Number of work dispatch threads");
FLAG(int32, worker_threads, 4, "Number of work dispatch threads");
void interruptableSleep(size_t milli) {
boost::this_thread::sleep(boost::posix_time::milliseconds(milli));

View File

@ -22,15 +22,15 @@ namespace pt = boost::property_tree;
namespace osquery {
DEFINE_osquery_flag(int32,
distributed_get_queries_retries,
3,
"Times to retry retrieving distributed queries");
FLAG(int32,
distributed_get_queries_retries,
3,
"Times to retry retrieving distributed queries");
DEFINE_osquery_flag(int32,
distributed_write_results_retries,
3,
"Times to retry writing distributed query results");
FLAG(int32,
distributed_write_results_retries,
3,
"Times to retry writing distributed query results");
Status MockDistributedProvider::getQueriesJSON(std::string& query_json) {
query_json = queriesJSON_;

View File

@ -26,15 +26,9 @@ namespace osquery {
/// Helper cooloff (ms) macro to prevent thread failure thrashing.
#define EVENTS_COOLOFF 20
DEFINE_osquery_flag(bool,
disable_events,
false,
"Disable osquery events pubsub");
FLAG(bool, disable_events, false, "Disable osquery events pubsub");
DEFINE_osquery_flag(int32,
events_expiry,
86000,
"Timeout to expire event pubsub results");
FLAG(int32, events_expiry, 86000, "Timeout to expire event pubsub results");
const std::vector<size_t> kEventTimeLists = {
1 * 60 * 60, // 1 hour

View File

@ -28,12 +28,12 @@ using namespace osquery::extensions;
namespace osquery {
DEFINE_osquery_flag(bool, disable_extensions, false, "Disable extension API");
FLAG(bool, disable_extensions, false, "Disable extension API");
DEFINE_osquery_flag(string,
extensions_socket,
"/var/osquery/osquery.em",
"Path to the extensions UNIX domain socket")
FLAG(string,
extensions_socket,
"/var/osquery/osquery.em",
"Path to the extensions UNIX domain socket")
namespace extensions {

View File

@ -22,10 +22,7 @@ namespace pt = boost::property_tree;
namespace osquery {
// run this benchmark with --iterations=9001 to parse over 9000 property lists
DEFINE_osquery_flag(int32,
plist_iterations,
100,
"Iterations to execute plist benchmark");
FLAG(int32, plist_iterations, 100, "Iterations to execute plist benchmark");
class PlistBenchmark : public testing::Test {};

View File

@ -25,10 +25,7 @@ namespace osquery {
const std::string kLinuxMemPath = "/dev/mem";
DEFINE_osquery_flag(bool,
disable_memory,
false,
"Disable physical memory reads");
FLAG(bool, disable_memory, false, "Disable physical memory reads");
Status readMem(int fd, size_t base, size_t length, uint8_t* buffer) {
if (lseek(fd, base, SEEK_SET) == -1) {

View File

@ -21,23 +21,15 @@ namespace pt = boost::property_tree;
namespace osquery {
/// `logger` defines the default log receiver plugin name.
DEFINE_osquery_flag(string,
logger_plugin,
"filesystem",
"The default logger plugin");
FLAG(bool, verbose, false, "Enable verbose informational messages");
FLAG_ALIAS(bool, verbose_debug, verbose);
FLAG_ALIAS(bool, debug, verbose);
DEFINE_osquery_flag(bool,
log_result_events,
true,
"Log scheduled results as events");
FLAG(bool, disable_logging, false, "Disable ERROR/INFO logging");
DEFINE_osquery_flag(bool,
verbose, // debug, verbose_debug
false,
"Enable verbose informational messages");
FLAG(string, logger_plugin, "filesystem", "The default logger plugin");
DEFINE_osquery_flag(bool, disable_logging, false, "Disable ERROR/INFO logging");
FLAG(bool, log_result_events, true, "Log scheduled results as events");
/**
* @brief A custom Glog log sink for forwarding or buffering status logs.

View File

@ -11,33 +11,126 @@
#include <gtest/gtest.h>
#include <osquery/core.h>
#include <osquery/flags.h>
#include <osquery/logger.h>
namespace osquery {
DECLARE_string(logger_plugin);
class LoggerTests : public testing::Test {
public:
LoggerTests() { Registry::setUp(); }
LoggerTests() {}
void SetUp() {
log_lines.clear();
status_messages.clear();
statuses_logged = 0;
last_status = {O_INFO, "", -1, ""};
}
// Track lines emitted to logString
static std::vector<std::string> log_lines;
// Track the results of init
static StatusLogLine last_status;
static std::vector<std::string> status_messages;
// Count calls to logStatus
static int statuses_logged;
};
std::vector<std::string> LoggerTests::log_lines;
StatusLogLine LoggerTests::last_status;
std::vector<std::string> LoggerTests::status_messages;
int LoggerTests::statuses_logged = 0;
class TestLoggerPlugin : public LoggerPlugin {
public:
TestLoggerPlugin() {}
Status logString(const std::string& s) { return Status(0, s); }
Status logString(const std::string& s) {
LoggerTests::log_lines.push_back(s);
return Status(0, s);
}
Status init(const std::string& name, const std::vector<StatusLogLine>& log) {
for (const auto& status : log) {
LoggerTests::status_messages.push_back(status.message);
}
if (log.size() > 0) {
LoggerTests::last_status = log.back();
}
if (name == "RETURN_FAILURE") {
return Status(1, "OK");
} else {
return Status(0, "OK");
}
}
Status logStatus(const std::vector<StatusLogLine>& log) {
++LoggerTests::statuses_logged;
return Status(0, "OK");
}
virtual ~TestLoggerPlugin() {}
};
TEST_F(LoggerTests, test_plugin) {
Registry::add<TestLoggerPlugin>("logger", "test");
Registry::setUp();
auto s = Registry::call("logger", "test", {{"string", "foobar"}});
EXPECT_EQ(s.ok(), true);
EXPECT_TRUE(s.ok());
EXPECT_EQ(LoggerTests::log_lines.back(), "foobar");
}
TEST_F(LoggerTests, test_logger_init) {
// Expect the logger to have been registered from the first test.
EXPECT_TRUE(Registry::exists("logger", "test"));
FLAGS_logger_plugin = "test";
initStatusLogger("logger_test");
// This will be printed to stdout.
LOG(WARNING) << "Logger test is generating a warning status (1)";
initLogger("logger_test");
// The warning message will have been buffered and sent to the active logger
// which is test.
EXPECT_EQ(LoggerTests::status_messages.size(), 1);
// The logStatus API should NOT have been called. It will only be used if
// (1) The active logger's init returns success within initLogger and
// (2) for status logs generated after initLogger is called.
EXPECT_EQ(LoggerTests::statuses_logged, 0);
}
TEST_F(LoggerTests, test_logger_log_status) {
// This will be printed to stdout.
LOG(WARNING) << "Logger test is generating a warning status (2)";
// The second warning status will be sent to the logger plugin.
EXPECT_EQ(LoggerTests::statuses_logged, 1);
}
TEST_F(LoggerTests, test_logger_variations) {
// Init the logger for a second time, this should only be done for testing.
// This time we'll trigger the init method to fail and prevent additional
// status messages from trigger logStatus.
initLogger("RETURN_FAILURE");
// This will be printed to stdout.
LOG(WARNING) << "Logger test is generating a warning status (3)";
// Since the initLogger call triggered a failed init, meaning the logger
// does NOT handle Glog logs, there will be no statuses logged.
EXPECT_EQ(LoggerTests::statuses_logged, 0);
}
}
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
osquery::initOsquery(argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -18,16 +18,13 @@
namespace osquery {
DEFINE_osquery_flag(string,
active_scribe_category,
"osquery",
"The path of the scribe category to be used if scribe "
"logging is enabled.");
FLAG(string,
active_scribe_category,
"osquery",
"The path of the scribe category to be used if scribe "
"logging is enabled.");
DEFINE_osquery_flag(bool,
dev_machine,
false,
"Set to true if the machine is a dev machine.");
FLAG(bool, dev_machine, false, "Set to true if the machine is a dev machine.");
class ScribeLoggerPlugin : public LoggerPlugin {
public:

View File

@ -19,10 +19,11 @@ namespace fs = boost::filesystem;
namespace osquery {
DEFINE_osquery_flag(string,
logger_path, // osquery_log_dir
"/var/log/osquery/",
"Directory path for ERROR/WARN/INFO and results logging");
FLAG(string,
logger_path,
"/var/log/osquery/",
"Directory path for ERROR/WARN/INFO and results logging");
FLAG_ALIAS(std::string, osquery_log_dir, logger_path);
const std::string kFilesystemLoggerFilename = "osqueryd.results.log";

View File

@ -22,15 +22,12 @@
namespace osquery {
DEFINE_osquery_flag(string,
host_identifier,
"hostname",
"Field used to identify the host running osqueryd");
FLAG(string,
host_identifier,
"hostname",
"Field used to identify the host running osqueryd");
DEFINE_osquery_flag(int32,
schedule_splay_percent,
10,
"Percent to splay config times");
FLAG(int32, schedule_splay_percent, 10, "Percent to splay config times");
Status getHostIdentifier(std::string& ident) {
std::shared_ptr<DBHandle> db;