Add Lad::Options::collectorLogLevel 64/44064/48 accepted/tizen_common accepted/tizen/3.0/common/20161114.110018 accepted/tizen/common/20161014.103138 accepted/tizen/unified/20170313.190432 submit/tizen/20161014.065203 submit/tizen_3.0_common/20161104.104000 submit/tizen_unified/20170313.195099 tizen_4.0.m1_release
authorOskar Świtalski <o.switalski@samsung.com>
Thu, 16 Jul 2015 11:01:00 +0000 (13:01 +0200)
committerOskar Świtalski <o.switalski@samsung.com>
Mon, 21 Dec 2015 10:32:38 +0000 (11:32 +0100)
Adds possibility to change log level of logs sent to collectors.
Test: Run nice-lad-tests

Change-Id: I95b5f238fac3bd935ae96417f4c8ea3d71825649
Signed-off-by: Oskar Świtalski <o.switalski@samsung.com>
17 files changed:
conf/nice_lad.conf.in
src/CMakeLists.txt
src/Lad/BaseCollectorLogLevelSetter.h [new file with mode: 0644]
src/Lad/CollectorLogLevelSetter.cpp [new file with mode: 0644]
src/Lad/CollectorLogLevelSetter.h [new file with mode: 0644]
src/Lad/CommandlineProcessor.cpp [new file with mode: 0644]
src/Lad/CommandlineProcessor.h [new file with mode: 0644]
src/Lad/DataCollector.cpp [new file with mode: 0644]
src/Lad/DataCollector.h
src/Lad/SyslogDataCollector.cpp
src/Lad/SyslogDataCollector.h
src/Systemd/DataCollector.cpp
src/Systemd/DataCollector.h
src/main.cpp
tests/BaseCommandlineTest.h [new file with mode: 0644]
tests/CMakeLists.txt
tests/Lad/process_command_line.cpp [new file with mode: 0644]

index 2d35464..50dfd04 100644 (file)
@@ -1,4 +1,10 @@
+# This file controls the configuration of the nice-lad plugin.
+# It simply takes events and writes them to a syslog or journald.
+# This plugin can take 1 argument, the -l LOG_LEVEL, where possible
+# log levels are defined in syslog(3).
+
 active = yes
 direction = out
 path = @SBIN_DIR@/nice-lad
 type = always
+# args = -l LOG_INFO
index 09ed58a..ababe7e 100644 (file)
@@ -14,6 +14,7 @@
 #
 # @file        src/CMakeLists.txt
 # @author      Aleksander Zdyb <a.zdyb@samsung.com>
+# @author      Oskar Świtalski <o.switalski@samsung.com>
 #
 
 OPTION(WITH_SECURITY_MANAGER "Use Security Manager to obtain resource groups" OFF)
@@ -34,7 +35,7 @@ IF(WITH_SECURITY_MANAGER)
     ADD_DEFINITIONS("-DWITH_SECURITY_MANAGER")
 ENDIF(WITH_SECURITY_MANAGER)
 
-FIND_PACKAGE(Boost 1.57 REQUIRED)
+FIND_PACKAGE(Boost 1.57 REQUIRED program_options)
 
 PKG_CHECK_MODULES(audit
     REQUIRED
@@ -66,6 +67,9 @@ SET(SOURCE_FILES
     Audit/SyscallRuleData.cpp
     Lad/AuditEventHandler.cpp
     Lad/AuditRulesPopulator.cpp
+    Lad/CollectorLogLevelSetter.cpp
+    Lad/CommandlineProcessor.cpp
+    Lad/DataCollector.cpp
     Lad/Options.cpp
     Log/log.cpp
     Utils/Feed.cpp
diff --git a/src/Lad/BaseCollectorLogLevelSetter.h b/src/Lad/BaseCollectorLogLevelSetter.h
new file mode 100644 (file)
index 0000000..e1e4198
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/BaseCollectorLogLevelSetter.h
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Declaration of abstract class for setting collector log level
+ */
+
+#ifndef SRC_LAD_BASECOLLECTORLOGLEVELSETTER_H
+#define SRC_LAD_BASECOLLECTORLOGLEVELSETTER_H
+
+namespace Lad {
+
+class BaseCollectorLogLevelSetter {
+public:
+    virtual void changeLevel(int logLevel) = 0;
+};
+
+} /* namespace Lad */
+
+#endif // SRC_LAD_BASECOLLECTORLOGLEVELSETTER_H
diff --git a/src/Lad/CollectorLogLevelSetter.cpp b/src/Lad/CollectorLogLevelSetter.cpp
new file mode 100644 (file)
index 0000000..fb89dfa
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/CollectorLogLevelSetter.cpp
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Definition of class for setting collector log level
+ */
+
+#include "CollectorLogLevelSetter.h"
+#include "DataCollector.h"
+
+namespace Lad {
+
+void CollectorLogLevelSetter::changeLevel(int logLevel) {
+    Lad::DataCollector::setCollectorLogLevel(logLevel);
+}
+
+} /* namespace Lad */
diff --git a/src/Lad/CollectorLogLevelSetter.h b/src/Lad/CollectorLogLevelSetter.h
new file mode 100644 (file)
index 0000000..8fd7dbe
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/CollectorLogLevelSetter.h
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Declaration of class for setting collector log level
+ */
+
+#ifndef SRC_LAD_COLLECTORLOGLEVELSETTER_H
+#define SRC_LAD_COLLECTORLOGLEVELSETTER_H
+
+#include "BaseCollectorLogLevelSetter.h"
+
+namespace Lad {
+
+class CollectorLogLevelSetter : public BaseCollectorLogLevelSetter {
+public:
+    void changeLevel(int logLevel) override;
+};
+
+} /* namespace Lad */
+
+#endif // SRC_LAD_COLLECTORLOGLEVELSETTER_H
diff --git a/src/Lad/CommandlineProcessor.cpp b/src/Lad/CommandlineProcessor.cpp
new file mode 100644 (file)
index 0000000..122a70d
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/CommandlineProcessor.cpp
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Definition of CommandlineProcessor class
+ */
+
+#include <map>
+#include <string>
+#include <syslog.h>
+#include <vector>
+
+#include <boost/any.hpp>
+#include <boost/program_options.hpp>
+
+#include "CommandlineProcessor.h"
+
+namespace Lad {
+
+namespace Options {
+
+namespace {
+
+const std::map<std::string, int> levelMap = { { "LOG_EMERG", LOG_EMERG },
+                                              { "LOG_ALERT", LOG_ALERT },
+                                              { "LOG_CRIT", LOG_CRIT },
+                                              { "LOG_ERR", LOG_ERR },
+                                              { "LOG_WARNING", LOG_WARNING },
+                                              { "LOG_NOTICE", LOG_NOTICE },
+                                              { "LOG_INFO", LOG_INFO },
+                                              { "LOG_DEBUG", LOG_DEBUG } };
+
+} /* namespace */
+
+/**
+ * @brief called by Boost::program_options to validate and parse collector log level to int
+ */
+void validate(boost::any &v, const std::vector<std::string> &values, CollectorLevel *, int) {
+    namespace po = boost::program_options;
+
+    po::validators::check_first_occurrence(v);
+    const std::string &s = po::validators::get_single_string(values);
+
+    auto iter = levelMap.find(s);
+    if (iter != levelMap.end())
+        v = boost::any(CollectorLevel{std::get<1>(*iter)});
+    else
+        throw po::validation_error(po::validation_error::invalid_option_value);
+}
+
+CommandlineProcessor::CommandlineProcessor(int argc, char * const *argv) : m_argc(argc),
+    m_argv(argv) {}
+
+ExitType CommandlineProcessor::process(BaseCollectorLogLevelSetter &setter) {
+    namespace po = boost::program_options;
+
+    try {
+        po::options_description desc("Allowed options");
+        desc.add_options()
+                ("help,h", "produce help message")
+                ("collector-log-level,l", po::value<CollectorLevel>()->value_name("LOG_LEVEL"),
+                 "set collector log level, possible values are: \n"
+                 "LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, "
+                 "LOG_INFO (default), LOG_DEBUG"
+                 )
+                ;
+        po::variables_map vm;
+        po::store(parse_command_line(m_argc, m_argv, desc), vm);
+        notify(vm);
+
+        if (vm.count("help")) {
+            *m_out << desc << std::endl;
+            return ExitType::HELP;
+        }
+
+        if (vm.count("collector-log-level")) {
+            setter.changeLevel(vm["collector-log-level"].as<CollectorLevel>());
+        }
+    } catch (const po::error &e) {
+        *m_err << e.what() << std::endl;
+        return ExitType::USAGE;
+    }
+
+    return ExitType::NO_EXIT;
+}
+
+void CommandlineProcessor::setOutputStream(std::ostream *out) {
+    m_out = out;
+}
+
+void CommandlineProcessor::setErrorStream(std::ostream *err) {
+    m_err = err;
+}
+
+} /* namespace Options */
+
+} /* namespace Lad */
diff --git a/src/Lad/CommandlineProcessor.h b/src/Lad/CommandlineProcessor.h
new file mode 100644 (file)
index 0000000..248feb9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/CommandlineProcessor.h
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Declaration of CommandlineProcessor class
+ */
+
+#ifndef SRC_LAD_COMMANDLINEPROCESSOR_H
+#define SRC_LAD_COMMANDLINEPROCESSOR_H
+
+#include <iostream>
+#include <ostream>
+
+#include <Lad/BaseCollectorLogLevelSetter.h>
+
+namespace Lad {
+
+namespace Options {
+
+enum class ExitType {
+    NO_EXIT,
+    HELP,
+    USAGE,
+};
+
+struct CollectorLevel {
+    operator int() const {
+        return m_level;
+    }
+    int m_level;
+};
+
+class CommandlineProcessor {
+public:
+    CommandlineProcessor(int argc, char * const *argv);
+    ExitType process(BaseCollectorLogLevelSetter &setter);
+
+    void setOutputStream(std::ostream *out);
+    void setErrorStream(std::ostream *err);
+private:
+    int m_argc;
+    char * const *m_argv;
+    std::ostream *m_out = &std::cout;
+    std::ostream *m_err = &std::cerr;
+};
+
+} /* namespace Options */
+
+} /* namespace Lad */
+
+#endif // SRC_LAD_COMMANDLINEPROCESSOR_H
diff --git a/src/Lad/DataCollector.cpp b/src/Lad/DataCollector.cpp
new file mode 100644 (file)
index 0000000..db5598b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        src/Lad/DataCollector.cpp
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Definition of abstract class for sending logs to log collector
+ */
+
+#include <syslog.h>
+
+#include "DataCollector.h"
+
+int Lad::DataCollector::s_collectorLogLevel = LOG_INFO;
+
+void Lad::DataCollector::setCollectorLogLevel(int collectorLogLevel) {
+    s_collectorLogLevel = collectorLogLevel;
+}
index d79d24b..f32d31f 100644 (file)
@@ -16,7 +16,9 @@
 /**
  * @file        src/Lad/DataCollector.h
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
  * @version     1.0
+ * @brief       Declaration of abstract class for sending logs to log collector
  */
 
 #ifndef SRC_LAD_DATACOLLECTOR_H
@@ -30,6 +32,10 @@ class DataCollector {
 public:
     virtual ~DataCollector() = default;
     virtual void log(const std::string &logMessage) = 0;
+
+    static void setCollectorLogLevel(int collectorLogLevel);
+protected:
+    static int s_collectorLogLevel;
 };
 
 } /* namespace Lad */
index 99f61a5..bec342b 100644 (file)
@@ -16,7 +16,9 @@
 /**
  * @file        src/Lad/SyslogDataCollector.cpp
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
  * @version     1.0
+ * @brief       Definition of class for sending logs to syslog
  */
 
 #include <syslog.h>
@@ -26,7 +28,7 @@
 namespace Lad {
 
 void SyslogDataCollector::log(const std::string &logMessage) {
-    syslog(LOG_INFO, "%s", logMessage.c_str());
+    syslog(s_collectorLogLevel, "%s", logMessage.c_str());
 }
 
 } /* namespace Lad */
index 600bcca..0ab3d1b 100644 (file)
@@ -17,6 +17,7 @@
  * @file        src/Lad/SyslogDataCollector.h
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
  * @version     1.0
+ * @brief       Declaration of class for sending logs to syslog
  */
 
 #ifndef SRC_LAD_SYSLOGDATACOLLECTOR_H
@@ -30,7 +31,7 @@ class SyslogDataCollector : public DataCollector {
 public:
     virtual ~SyslogDataCollector() = default;
 
-    virtual void log(const std::string &logMessage);
+    void log(const std::string &logMessage) override;
 };
 
 } /* namespace Lad */
index d69df9c..abdb283 100644 (file)
@@ -16,7 +16,9 @@
 /**
  * @file        src/Systemd/DataCollector.cpp
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
  * @version     1.0
+ * @brief       Definition of class for sending logs to journald
  */
 
 #include <systemd/sd-journal.h>
@@ -26,7 +28,7 @@
 namespace Systemd {
 
 void DataCollector::log(const std::string &logMessage) {
-    sd_journal_print(LOG_INFO, "%s", logMessage.c_str());
+    sd_journal_print(s_collectorLogLevel, "%s", logMessage.c_str());
 }
 
 
index 209dc57..5720bca 100644 (file)
@@ -17,6 +17,7 @@
  * @file        src/Systemd/DataCollector.h
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
  * @version     1.0
+ * @brief       Declaration of class for sending logs to journald
  */
 
 #ifndef SRC_SYSTEMD_DATACOLLECTOR_H
@@ -31,7 +32,7 @@ public:
     using Lad::DataCollector::DataCollector;
     virtual ~DataCollector() = default;
 
-    virtual void log(const std::string &logMessage);
+    void log(const std::string &logMessage) override;
 };
 
 } /* namespace Systemd */
index f9c4578..2f6e853 100644 (file)
@@ -16,7 +16,9 @@
 /**
  * @file        src/main.cpp
  * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
  * @version     1.0
+ * @brief       Main file for nice-lad
  */
 
 #include <csignal>
@@ -30,6 +32,8 @@
 #include <Audit/Parser.h>
 #include <Lad/AuditEventHandler.h>
 #include <Lad/AuditRulesPopulator.h>
+#include <Lad/CollectorLogLevelSetter.h>
+#include <Lad/CommandlineProcessor.h>
 #include <Lad/Options.h>
 #include <Log/log.h>
 #include <Utils/Feed.h>
@@ -45,6 +49,21 @@ int main(int argc, char **argv) {
     LOGI("Starting nice-lad");
 
     try {
+        Lad::CollectorLogLevelSetter collectorLogLevelSetter;
+        Lad::Options::CommandlineProcessor commandlineProcessor(argc, argv);
+
+        auto processCommandLineReturn = commandlineProcessor.process(collectorLogLevelSetter);
+
+        switch (processCommandLineReturn) {
+        case Lad::Options::ExitType::HELP:
+            return EXIT_SUCCESS;
+        case Lad::Options::ExitType::USAGE:
+            LOGE("Improper use of command line options (Terminating)");
+            return EXIT_FAILURE;
+        default:
+            break;
+        }
+
         Audit::AuditWrapper auditApi;
         Audit::AuparseSourceFeedWrapper auparseApi;
         Audit::Parser auParser(auparseApi);
@@ -84,7 +103,7 @@ int main(int argc, char **argv) {
 
         LOGD("nice-lad up and ready");
 
-       feed.start();
+        feed.start();
     } catch (const std::exception &ex) {
         LOGC(ex.what() << " (Terminating)");
         return EXIT_FAILURE;
diff --git a/tests/BaseCommandlineTest.h b/tests/BaseCommandlineTest.h
new file mode 100644 (file)
index 0000000..674a37d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        tests/BaseCommandlineTest.h
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @author      Pawel Wieczorek <p.wieczorek2@samsung.com>
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Base fixture for tests of commandline parsers
+ */
+
+#ifndef TESTS_BASECOMMANDLINETEST_H
+#define TESTS_BASECOMMANDLINETEST_H
+
+#include <cstdlib>
+#include <cstring>
+#include <new>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+class BaseCommandlineTest : public ::testing::Test {
+public:
+    typedef std::vector<std::string> Args;
+
+    void prepare_argv(const Args &args) {
+        destroy_argv();
+
+        m_argc = args.size();
+        m_argv = new char*[m_argc]();
+
+        for (auto i = 0; i < m_argc; ++i) {
+            m_argv[i] = strdup(args.at(i).c_str());
+            if (m_argv[i] == nullptr)
+                throw std::bad_alloc();
+        }
+    }
+
+    int argc(void) const {
+        return m_argc;
+    }
+
+    char * const *argv(void) const {
+        return m_argv;
+    }
+
+protected:
+    void TearDown(void) override {
+        destroy_argv();
+    }
+
+    void destroy_argv(void) {
+        for (auto i = 0; i < m_argc; ++i) {
+            free(m_argv[i]);
+        }
+        delete[] m_argv;
+
+        m_argc = 0;
+        m_argv = nullptr;
+    }
+
+    int m_argc = 0;
+    char **m_argv = nullptr;
+};
+
+#endif /* TESTS_BASECOMMANDLINETEST_H_ */
index 2da5db9..563ba68 100644 (file)
 #
 # @file        tests/CMakeLists.txt
 # @author      Aleksander Zdyb <a.zdyb@samsung.com>
+# @author      Oskar Świtalski <o.switalski@samsung.com>
 #
 
-FIND_PACKAGE(Boost 1.57 REQUIRED)
+FIND_PACKAGE(Boost 1.57 REQUIRED program_options)
 
 FIND_PACKAGE(Threads REQUIRED) # Required by gmock
 
@@ -30,13 +31,14 @@ IF(NOT gmock_FOUND)
     )
 ENDIF(NOT gmock_FOUND)
 
-SET(LAD_SRC_DIR ../src)
+SET(LAD_SRC_DIR ${PROJECT_SOURCE_DIR}/src)
 
 INCLUDE_DIRECTORIES(
     ${audit_INCLUDE_DIRS}
     ${Boost_INCLUDE_DIRS}
     ${gmock_INCLUDE_DIRS}
     ${LAD_SRC_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}
 )
 
 SET(SOURCE_FILES
@@ -45,6 +47,7 @@ SET(SOURCE_FILES
     Audit/parser.cpp
     Audit/syscall_rule_data.cpp
     Lad/audit_event_handler.cpp
+    Lad/process_command_line.cpp
     SecurityManager/data_provider.cpp
     Utils/with_message_exception.cpp
 
@@ -52,6 +55,11 @@ SET(SOURCE_FILES
     ${LAD_SRC_DIR}/Audit/Parser.cpp
     ${LAD_SRC_DIR}/Audit/SyscallRuleData.cpp
     ${LAD_SRC_DIR}/Lad/AuditEventHandler.cpp
+    ${LAD_SRC_DIR}/Lad/CommandlineProcessor.cpp
+    ${LAD_SRC_DIR}/Lad/DataCollector.cpp
+    ${LAD_SRC_DIR}/Lad/DummyDataProvider.cpp
+    ${LAD_SRC_DIR}/Lad/Options.cpp
+    ${LAD_SRC_DIR}/Lad/SyslogDataCollector.cpp
     ${LAD_SRC_DIR}/Log/log.cpp
     ${LAD_SRC_DIR}/SecurityManager/DataProvider.cpp
 )
@@ -63,10 +71,12 @@ IF(gmock_FOUND)
         ${CMAKE_THREAD_LIBS_INIT}
         ${gmock_LDFLAGS}
         ${gmock_LIBRARIES}
+        ${Boost_LIBRARIES}
     )
 ELSE(gmock_FOUND)
     TARGET_LINK_LIBRARIES(${TARGET_NICE_LAD_TESTS}
         ${CMAKE_THREAD_LIBS_INIT}
+        ${Boost_LIBRARIES}
         gmock gtest
     )
 ENDIF(gmock_FOUND)
diff --git a/tests/Lad/process_command_line.cpp b/tests/Lad/process_command_line.cpp
new file mode 100644 (file)
index 0000000..e6c1002
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        tests/Lad/process_command_line.cpp
+ * @author      Oskar Świtalski <o.switalski@samsung.com>
+ * @version     1.0
+ * @brief       Tests for CommandlineProcessor class
+ */
+
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <syslog.h>
+#include <vector>
+
+#include <boost/any.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <BaseCommandlineTest.h>
+#include <Lad/BaseCollectorLogLevelSetter.h>
+#include <Lad/CommandlineProcessor.h>
+
+namespace {
+    std::map<std::string, int> levelMap = { { "LOG_EMERG", LOG_EMERG },
+                                            { "LOG_ALERT", LOG_ALERT },
+                                            { "LOG_CRIT", LOG_CRIT },
+                                            { "LOG_ERR", LOG_ERR },
+                                            { "LOG_WARNING", LOG_WARNING },
+                                            { "LOG_NOTICE", LOG_NOTICE },
+                                            { "LOG_INFO", LOG_INFO },
+                                            { "LOG_DEBUG", LOG_DEBUG } };
+
+    const char *help_not_printed = "help message was not printed";
+    const char *error_not_printed = "error message was not printed";
+    const char *printed_to_output_stream = "should not print to output stream";
+    const char *printed_to_error_stream = "should not print to error stream";
+
+    const char *file_path = "./nice-lad";
+    const char *long_log_level_option = "--collector-log-level";
+    const char *log_level_option = "-l";
+    const char *long_help_option = "--help";
+    const char *help_option = "-h";
+    const char *unknown_log_level_option = "unknown_log_level";
+    const char *unrecognized_option = "--unrecognized_option";
+} /* namespace anonymous */
+
+class FakeCollectorLogLevelSetter : public Lad::BaseCollectorLogLevelSetter {
+public:
+    MOCK_METHOD1(changeLevel, void(int level));
+};
+
+class CommandLineProcessingTest : public BaseCommandlineTest {
+public:
+    /**
+      * @brief Process cmd line option, check if error msg was printed, log level was not changed
+      * and USAGE was returned
+      */
+    void failingTest() {
+        FakeCollectorLogLevelSetter logLevelSetter;
+        Lad::Options::CommandlineProcessor processor(argc(), argv());
+        processor.setErrorStream(&m_err);
+        processor.setOutputStream(&m_out);
+        ASSERT_EQ(Lad::Options::ExitType::USAGE, processor.process(logLevelSetter));
+        ASSERT_EQ(0, m_out.rdbuf()->in_avail()) << printed_to_output_stream;
+        ASSERT_LT(0, m_err.rdbuf()->in_avail()) << error_not_printed;
+    }
+
+    /**
+      * @brief Process cmd line option, check if help msg was printed, log level was not changed
+      * and HELP was returned
+      */
+    void helpMsgTest() {
+        FakeCollectorLogLevelSetter logLevelSetter;
+        Lad::Options::CommandlineProcessor processor(argc(), argv());
+        processor.setErrorStream(&m_err);
+        processor.setOutputStream(&m_out);
+        ASSERT_EQ(Lad::Options::ExitType::HELP, processor.process(logLevelSetter));
+        ASSERT_LT(0, m_out.rdbuf()->in_avail()) << help_not_printed;
+        ASSERT_EQ(0, m_err.rdbuf()->in_avail()) << printed_to_error_stream;
+    }
+
+    /**
+      * @brief Process cmd line option, check if nothing was printed, log level was correctly
+      * changed and NO_EXIT was returned
+      */
+    void changeTest(int expectedLogLevel) {
+        FakeCollectorLogLevelSetter logLevelSetter;
+        Lad::Options::CommandlineProcessor processor(argc(), argv());
+        processor.setErrorStream(&m_err);
+        processor.setOutputStream(&m_out);
+        EXPECT_CALL(logLevelSetter, changeLevel(expectedLogLevel));
+        ASSERT_EQ(Lad::Options::ExitType::NO_EXIT, processor.process(logLevelSetter));
+        ASSERT_EQ(0, m_out.rdbuf()->in_avail()) << printed_to_output_stream;
+        ASSERT_EQ(0, m_err.rdbuf()->in_avail()) << printed_to_error_stream;
+    }
+
+    /**
+     * Process cmd line options, check if nothing was printed, log level was not changed and
+     * NO_EXIT was returned
+     */
+    void noChangeTest() {
+        FakeCollectorLogLevelSetter logLevelSetter;
+        Lad::Options::CommandlineProcessor processor(argc(), argv());
+        processor.setErrorStream(&m_err);
+        processor.setOutputStream(&m_out);
+        ASSERT_EQ(Lad::Options::ExitType::NO_EXIT,
+                  processor.process(logLevelSetter));
+        ASSERT_EQ(0, m_out.rdbuf()->in_avail()) << printed_to_output_stream;
+        ASSERT_EQ(0, m_err.rdbuf()->in_avail()) << printed_to_error_stream;
+    }
+
+protected:
+    void TearDown() override {
+        clearStreams();
+        BaseCommandlineTest::TearDown();
+    }
+
+    void clearStreams() {
+        m_out.clear();
+        m_out.str("");
+
+        m_err.clear();
+        m_err.str("");
+    }
+
+    std::stringstream m_out;
+    std::stringstream m_err;
+};
+
+/**
+ * @brief Test processCommandline with all correct arguments for -l option
+ * @test Scenario:
+ * - pass -l option with valid log level value
+ */
+TEST_F(CommandLineProcessingTest, validate_function) {
+    for (auto &levelPair : levelMap) {
+        SCOPED_TRACE("level = \"" + std::get<0>(levelPair) + "\"");
+        prepare_argv({ file_path, log_level_option, std::get<0>(levelPair)});
+        changeTest(std::get<1>(levelPair));
+        clearStreams();
+        destroy_argv();
+    }
+}
+
+/**
+ * @brief Test processCommandline with empty options
+ * @test Scenario:
+ * - pass nothing to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, empty_options) {
+    prepare_argv({ file_path });
+    noChangeTest();
+}
+
+/**
+ * @brief Test processCommandline with unrecognized option
+ * @test Scenario:
+ * - pass unrecognized option to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, unrecognized_option) {
+    prepare_argv({ file_path, unrecognized_option });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with no argument for -l option
+ * @test Scenario:
+ * - pass for -l option with no argument
+ */
+TEST_F(CommandLineProcessingTest, empty_log_level_option) {
+    prepare_argv({ file_path, log_level_option });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with invalid argument for -l option
+ * @test Scenario:
+ * - pass "-l unknown_log_level_option" to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, unknown_log_level_option) {
+    prepare_argv({ file_path, log_level_option, unknown_log_level_option });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with -h option
+ * @test Scenario:
+ * - pass "-h" to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, help_option) {
+    prepare_argv({ file_path, help_option });
+    helpMsgTest();
+}
+
+/**
+ * @brief Test processCommandline with --help option
+ * @test Scenario:
+ * - pass "--help" to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, long_help_option) {
+    prepare_argv({ file_path, long_help_option });
+    helpMsgTest();
+}
+
+/**
+ * @brief Test processCommandline with multiple -l specified
+ * @test Scenario:
+ * - pass multiple correct log levels to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, multiple_collector_log_level_option) {
+    prepare_argv({ file_path, log_level_option, "LOG_INFO", log_level_option, "LOG_DEBUG" });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with all correct arguments for --collector-log-level option
+ * @test Scenario:
+ * - pass --collector-log-level option with valid log level value
+ */
+TEST_F(CommandLineProcessingTest, validate_function_long) {
+    for (auto &levelPair : levelMap) {
+        SCOPED_TRACE("level = \"" + std::get<0>(levelPair) + "\"");
+        prepare_argv({ file_path, long_log_level_option, std::get<0>(levelPair)});
+        changeTest(std::get<1>(levelPair));
+        clearStreams();
+        destroy_argv();
+    }
+}
+
+/**
+ * @brief Test processCommandline with no argument for --collector-log-level option
+ * @test Scenario:
+ * - pass for --collector-log-level option with no argument
+ */
+TEST_F(CommandLineProcessingTest, empty_collector_log_level_option) {
+    prepare_argv({ file_path, long_log_level_option });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with invalid argument for --collector-log-level option
+ * @test Scenario:
+ * - pass "--collector-log-level unknown_log_level" to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, unknown_collector_log_level_option) {
+    prepare_argv({ file_path, long_log_level_option, unknown_log_level_option });
+    failingTest();
+}
+
+/**
+ * @brief Test processCommandline with multiple --collector-log-level specified
+ * @test Scenario:
+ * - pass multiple correct log levels to processCommandline
+ */
+TEST_F(CommandLineProcessingTest, multiple_collector_long_log_level_option) {
+    prepare_argv({ file_path, long_log_level_option, "LOG_INFO", long_log_level_option,
+                   "LOG_DEBUG" });
+    failingTest();
+}