]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[trac3664] Code updates and add unittests for parsing
authorShawn Routhier <sar@isc.org>
Wed, 21 Jan 2015 06:37:10 +0000 (22:37 -0800)
committerShawn Routhier <sar@isc.org>
Wed, 21 Jan 2015 06:37:10 +0000 (22:37 -0800)
Add the structure for doing unittests and add some tests
to exercise parseArgs().

Rename the class to lfcController to be more in line with
the coding spec.

src/bin/lfc/Makefile.am
src/bin/lfc/lfc.cc
src/bin/lfc/lfc.h
src/bin/lfc/main.cc
src/bin/lfc/tests/Makefile.am
src/bin/lfc/tests/lfc_controller_unittests.cc [new file with mode: 0644]
src/bin/lfc/tests/lfc_unittests.cc [new file with mode: 0644]

index 7c058018eb7d339620a1d4430dace1c9d286ddf3..c2926f6f39aff5a6e9077e3e0bd2d2e0c5930a07 100644 (file)
@@ -1,5 +1,4 @@
-#SUBDIRS = . tests
-SUBDIRS = .
+SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
index 3d5512ff2d0e20e58cc1c2cd66b1b12210e86423..cb031e21548f8aec9a0ecfea607aee04d2312f89 100644 (file)
@@ -17,7 +17,6 @@
 #include <exceptions/exceptions.h>
 #include <log/logger_support.h>
 #include <log/logger_manager.h>
-//#include <dhcpsrv/cfgmgr.h>
 #include <iostream>
 
 using namespace std;
@@ -27,23 +26,23 @@ namespace lfc {
 
 /// @brief Defines the application name, it may be used to locate
 /// configuration data and appears in log statements.
-const char* lfc::lfc_app_name_ = "DhcpLFC";
+const char* lfcController::lfc_app_name_ = "DhcpLFC";
 
 /// @brief Defines the executable name.
-const char*lfc::lfc_bin_name_ = "kea-lfc";
+const char* lfcController::lfc_bin_name_ = "kea-lfc";
 
-lfc::lfc()
-    : dhcp_version_(0), verbose_(false), config_file_(""),
-      previous_file_(""), copy_file_(""), output_file_("") {
+lfcController::lfcController()
+    : protocol_version_(0), verbose_(false), config_file_(""), previous_file_(""),
+      copy_file_(""), output_file_(""), finish_file_(""), pid_file_("./test_pid") {
     std::cerr << "created lfc" << std::endl;
 }
 
-lfc::~lfc() {
+lfcController::~lfcController() {
     std::cerr << "destroyed lfc" << std::endl;
 }
 
 void
-lfc::launch(int argc, char* argv[], const bool test_mode) {
+lfcController::launch(int argc, char* argv[], const bool test_mode) {
   try {
     parseArgs(argc, argv);
   } catch (const InvalidUsage& ex) {
@@ -55,30 +54,30 @@ lfc::launch(int argc, char* argv[], const bool test_mode) {
 }
 
 void
-lfc::parseArgs(int argc, char* argv[])
+lfcController::parseArgs(int argc, char* argv[])
 {
     int ch;
 
-    while ((ch = getopt(argc, argv, "46dvVp:i:o:c:")) != -1) {
+    while ((ch = getopt(argc, argv, "46dvVp:i:o:c:f:")) != -1) {
         switch (ch) {
        case '4':
             // Process DHCPv4 lease files.
-            dhcp_version_ = 4;
+            protocol_version_ = 4;
             break;
 
        case '6':
             // Process DHCPv6 lease files.
-            dhcp_version_ = 6;
+            protocol_version_ = 6;
             break;
 
        case 'v':
             // Print just Kea vesion and exit.
-         //            std::cout << getVersion(false) << std::endl;
+           std::cout << getVersion(false) << std::endl;
             exit(EXIT_SUCCESS);
 
        case 'V':
             // Print extended  Kea vesion and exit.
-         //std::cout << getVersion(true) << std::endl;
+           std::cout << getVersion(true) << std::endl;
             exit(EXIT_SUCCESS);
 
        case 'd':
@@ -110,6 +109,14 @@ lfc::parseArgs(int argc, char* argv[])
            output_file_ = optarg;
            break;
 
+       case 'f':
+           // Output file name.
+           if (optarg == NULL) {
+               isc_throw(InvalidUsage, "Finish file name missing");
+           }
+           finish_file_ = optarg;
+           break;
+
        case 'c':
            // Previous file name.
            if (optarg == NULL) {
@@ -128,7 +135,7 @@ lfc::parseArgs(int argc, char* argv[])
         isc_throw(InvalidUsage, "Extraneous parameters.");
     }
 
-    if (dhcp_version_ == 0) {
+    if (protocol_version_ == 0) {
         isc_throw(InvalidUsage, "DHCP version required");
     }
 
@@ -144,43 +151,57 @@ lfc::parseArgs(int argc, char* argv[])
         isc_throw(InvalidUsage, "Output file not specified");  
     }
 
+    if (finish_file_.empty()) {
+        isc_throw(InvalidUsage, "Finish file not specified");  
+    }
+
     if (config_file_.empty()) {
         isc_throw(InvalidUsage, "Config file not specified");  
     }
 
     // If verbose is set echo the input information
     if (verbose_ == true) {
-      std::cerr << "Protocol version:    " << dhcp_version_ << std::endl
+      std::cerr << "Protocol version:    " << protocol_version_ << std::endl
                << "Previous lease file: " << previous_file_ << std::endl
                << "Copy lease file:     " << copy_file_ << std::endl
                << "Output lease file:   " << output_file_ << std::endl
-               << "Config file:         " << config_file_ << std::endl;
+               << "Finishn file:        " << finish_file_ << std::endl
+               << "Config file:         " << config_file_ << std::endl
+               << "PID file:            " << pid_file_ << std::endl;
     }
 }
 
-void
-lfc::pidCheck()
+bool
+lfcController::pidCheck(const std::string & pid_file)
+{
+    return (false);
+}
+
+bool
+lfcController::pidWrite(const std::string & pid_file)
 {
+    return (true);
 }
 
 void
-lfc::pidDelete()
+lfcController::pidDelete(const std::string & pid_file)
 {
 }
 
 void
-lfc::usage(const std::string & text)
+lfcController::usage(const std::string & text)
 {
     if (text != "") {
         std::cerr << "Usage error: " << text << std::endl;
     }
 
     std::cerr << "Usage: " << lfc_bin_name_ << std::endl
-              << " [-4|-6] -p file -i file -o file -c file" << std::endl
+              << " [-4|-6] -p file -i file -o file -f file -c file" << std::endl
               << "   -4 or -6 clean a set of v4 or v6 lease files" << std::endl
               << "   -p <file>: previous lease file" << std::endl
               << "   -i <file>: copy of lease file" << std::endl
               << "   -o <file>: output lease file" << std::endl
+              << "   -f <file>: finish file" << std::endl
               << "   -c <file>: configuration file" << std::endl
               << "   -v: print version number and exit" << std::endl
               << "   -V: print extended version inforamtion and exit" << std::endl
@@ -188,21 +209,17 @@ lfc::usage(const std::string & text)
               << std::endl;
 }
 
+std::string
+lfcController::getVersion(bool extended) {
+    std::stringstream tmp;
+
+    tmp << VERSION;
+    if (extended) {
+        tmp << std::endl << EXTENDED_VERSION;
+    }
+
+    return (tmp.str());
+}
+
 }; // namespace isc::lfc
 }; // namespace isc
-
-//std::string
-//isc::dhcp::Daemon::getVersion(bool extended) {
-//    std::stringstream tmp;
-//
-//    tmp << VERSION;
-//    if (extended) {
-//        tmp << std::endl << EXTENDED_VERSION;
-//
-        // @todo print more details (is it Botan or OpenSSL build,
-        // with or without MySQL/Postgres? What compilation options were
-        // used? etc)
-//    }
-//
-//    return (tmp.str());
-//}
index 4f38e5468f4c1b3f3f29766c24f941df325b5f71..4c0deb46239c3925582f49a3980aeb313ee7218a 100644 (file)
@@ -32,7 +32,7 @@ public:
 //class lfcBase;
 //typedef boost::shared_ptr<lfcBase> lfcBasePtr;
 
-class lfc {
+class lfcController {
 public:
     /// @brief Defines the application name, it may be used to locate
     /// configuration data and appears in log statements.
@@ -43,10 +43,10 @@ public:
     static const char* lfc_bin_name_;
 
     /// @brief Constructor
-    lfc();
+    lfcController();
 
     /// @brief Destructor
-    ~lfc();
+    ~lfcController();
 
     /// @brief Acts as the primary entry point to start execution
     /// of the process.  Provides the control logic:
@@ -63,26 +63,94 @@ public:
     /// step taken after the process has been launched.
     void parseArgs(int argc, char* argv[]);
 
-    /// @brief Use the pid to determine if there is another instance
-    /// and create a pid file if we are alone.
-    void pidCheck();
+    /// @brief Use the pid file to determine if there is another instance
+    ///
+    /// @param pid_file is the name of the file which holds the pid to check
+    /// returns true if there is a process with that pid
+    bool pidCheck(const std::string & pid_file);
+
+    /// @brief Extract the pid and Write it out to the pid file
+    ///
+    /// @param pid_file is the name of the file in which to write the pid
+    /// returns true if the write was successful
+    bool pidWrite(const std::string & pid_file);
 
     /// @brief Get rid of the pid file we created earlier
-    void pidDelete();
+    void pidDelete(const std::string & pid_file);
 
-    /// #brief prints the program usage text to std error.
+    /// @brief Prints the program usage text to std error.
     ///
     /// @param text is a string message which will preceded the usage text.
     /// This is intended to be used for specific usage violation messages.
     void usage(const std::string& text);
 
+    /// @brief Gets the Kea version number for printing
+    ///
+    /// @param extended is a boolean indicating if the version string
+    /// should be short (false) or extended (true)
+    std::string getVersion(bool extended);
+
+    // The following are primarly for the test code and not expected
+    // to be used in normal situations
+
+    /// @brief Gets the protocol version of the leaes files
+    ///
+    /// @return Returns the value of the protocol version
+    int getProtocolVersion() {
+      return (protocol_version_);
+    }
+
+    /// @brief Gets the config file name
+    ///
+    /// @return Returns the name of the config file
+    std::string getConfigFile() const {
+        return (config_file_);
+    }
+
+    /// @brief Gets the prevous file name
+    ///
+    /// @return Returns the name of the previous file
+    std::string getPreviousFile() const {
+        return (previous_file_);
+    }
+
+    /// @brief Gets the copy file name
+    ///
+    /// @return Returns the name of the copy file
+    std::string getCopyFile() const {
+        return (copy_file_);
+    }
+
+    /// @brief Gets the output file name
+    ///
+    /// @return Returns the name of the output file
+    std::string getOutputFile() const {
+        return (output_file_);
+    }
+
+    /// @brief Gets the finish file name
+    ///
+    /// @return Returns the name of the finish file
+    std::string getFinishFile() const {
+        return (finish_file_);
+    }
+
+    /// @brief Gets the pid file name
+    ///
+    /// @return Returns the name of the pid file
+    std::string getPidFile() const {
+        return (pid_file_);
+    }
+
 private:
-    int dhcp_version_;
+    int protocol_version_;
     bool verbose_;
     std::string config_file_;
     std::string previous_file_;
     std::string copy_file_;
     std::string output_file_;
+    std::string finish_file_;
+    std::string pid_file_;
 };
 
 }; // namespace isc:lfc
index 9f1b4552859f9701bea11af1910ad3997ad25a5a..7328f945e73f224538376e10e40345854faa1fda 100644 (file)
@@ -31,16 +31,13 @@ using namespace std;
 /// errors, EXIT_FAILURE otherwise.
 int main(int argc, char* argv[]) {
     int ret = EXIT_SUCCESS;
-    lfc lfc;
-
-    // Instantiate/fetch the lfc application controller.
-    //    lfc& lfc = lfc::lfc();
+    lfcController lfcController;
 
     // Launch the controller passing in command line arguments.
     // Exit program with the controller's return code.
     try  {
         // 'false' value disables test mode.
-        lfc.launch(argc, argv, false);
+        lfcController.launch(argc, argv, false);
     } catch (const isc::Exception& ex) {
         std::cerr << "Service failed:" << ex.what() << std::endl;
         ret = EXIT_FAILURE;
index 42b0d5beff03611e64a523e22cd43480aa935523..23ea485887759ad3e153c3fa0f615a81daab7b37 100644 (file)
@@ -1,8 +1,8 @@
 SHTESTS =
 
-noinst_SCRIPTS = lfc_tests.sh
+noinst_SCRIPTS = 
 
-EXTRA_DIST  = lfc_tests.sh.in
+EXTRA_DIST  = 
 
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
@@ -24,7 +24,7 @@ AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
 
 CLEANFILES = $(builddir)/interfaces.txt $(builddir)/logger_lockfile
 
-DISTCLEANFILES = lfc_process_tests.sh
+DISTCLEANFILES = 
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
 if USE_CLANGPP
@@ -44,12 +44,13 @@ if HAVE_GTEST
 
 TESTS += lfc_unittests
 
-#lfc_unittests_SOURCES = d_test_stubs.cc d_test_stubs.h
+lfc_unittests_SOURCES = lfc_unittests.cc
+lfc_unittests_SOURCES += lfc_controller_unittests.cc
 
 lfc_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 lfc_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 lfc_unittests_LDADD = $(GTEST_LDADD)
-lfc_unittests_LDADD += $(top_builddir)/src/bin/d2/libd2.la
+lfc_unittests_LDADD += $(top_builddir)/src/bin/lfc/liblfc.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.la
diff --git a/src/bin/lfc/tests/lfc_controller_unittests.cc b/src/bin/lfc/tests/lfc_controller_unittests.cc
new file mode 100644 (file)
index 0000000..3069a2a
--- /dev/null
@@ -0,0 +1,158 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <log/logger_support.h>
+#include <gtest/gtest.h>
+#include <lfc/lfc.h>
+
+using namespace isc::lfc;
+using namespace std;
+
+TEST(lfcControllerTest, initialValues) {
+    lfcController lfcController;
+
+    // Verify that we start with everything empty
+    EXPECT_TRUE(lfcController.getProtocolVersion() == 0);
+    EXPECT_TRUE(lfcController.getConfigFile() == "");
+    EXPECT_TRUE(lfcController.getPreviousFile() == "");
+    EXPECT_TRUE(lfcController.getCopyFile() == "");
+    EXPECT_TRUE(lfcController.getOutputFile() == "");
+    EXPECT_TRUE(lfcController.getFinishFile() == "");
+    // Currently defaulting pid file for testing
+    // EXPECT_TRUE(lfcController.getPidFile() == "");
+}
+
+TEST(lfcControllerTest, fullCommandLine) {
+    lfcController lfcController;
+
+    // Verify that standard options can be parsed without error
+    char* argv[] = { const_cast<char*>("progName"),
+                    const_cast<char*>("-4"),
+                    const_cast<char*>("-p"),
+                    const_cast<char*>("previous"),
+                    const_cast<char*>("-i"),
+                    const_cast<char*>("copy"),
+                    const_cast<char*>("-o"),
+                    const_cast<char*>("output"),
+                    const_cast<char*>("-c"),
+                    const_cast<char*>("config"),
+                    const_cast<char*>("-f"),
+                    const_cast<char*>("finish") };
+    int argc = 12;
+
+    EXPECT_NO_THROW(lfcController.parseArgs(argc, argv));
+
+    // The parsed data
+    EXPECT_TRUE(lfcController.getProtocolVersion() == 4);
+    EXPECT_TRUE(lfcController.getConfigFile() == "config");
+    EXPECT_TRUE(lfcController.getPreviousFile() == "previous");
+    EXPECT_TRUE(lfcController.getCopyFile() == "copy");
+    EXPECT_TRUE(lfcController.getOutputFile() == "output");
+    EXPECT_TRUE(lfcController.getFinishFile() == "finish");
+}
+
+TEST(lfcControllerTest, notEnoughData) {
+    lfcController lfcController;
+
+    // The standard options we shall test what happens
+    // if we don't include all of them
+    char* argv[] = { const_cast<char*>("progName"),
+                    const_cast<char*>("-4"),
+                    const_cast<char*>("-p"),
+                    const_cast<char*>("previous"),
+                    const_cast<char*>("-i"),
+                    const_cast<char*>("copy"),
+                    const_cast<char*>("-o"),
+                    const_cast<char*>("output"),
+                    const_cast<char*>("-c"),
+                    const_cast<char*>("config"),
+                    const_cast<char*>("-f"),
+                    const_cast<char*>("finish") };
+    int argc = 1;
+
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 2;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 3;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 4;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 5;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 6;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 7;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 8;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 9;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 10;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+    argc = 11;
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+
+}
+
+TEST(lfcControllerTest, tooMuchData) {
+    lfcController lfcController;
+
+    // The standard options plus some others
+
+    char* argv[] = { const_cast<char*>("progName"),
+                    const_cast<char*>("-4"),
+                    const_cast<char*>("-p"),
+                    const_cast<char*>("previous"),
+                    const_cast<char*>("-i"),
+                    const_cast<char*>("copy"),
+                    const_cast<char*>("-o"),
+                    const_cast<char*>("output"),
+                    const_cast<char*>("-c"),
+                    const_cast<char*>("config"),
+                    const_cast<char*>("-f"),
+                    const_cast<char*>("finish"),
+                    const_cast<char*>("some"),
+                    const_cast<char*>("other"),
+                    const_cast<char*>("args"),              
+    };
+    int argc = 15;
+
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+}
+
+TEST(lfcControllerTest, someBadData) {
+    lfcController lfcController;
+
+    // The standard options plus some others
+
+    char* argv[] = { const_cast<char*>("progName"),
+                    const_cast<char*>("some"),
+                    const_cast<char*>("bad"),
+                    const_cast<char*>("args"),              
+    };
+    int argc = 4;
+
+    EXPECT_THROW(lfcController.parseArgs(argc, argv), InvalidUsage);
+}
+//-4 -p previous -i copy -o output -c config -f finish -d
diff --git a/src/bin/lfc/tests/lfc_unittests.cc b/src/bin/lfc/tests/lfc_unittests.cc
new file mode 100644 (file)
index 0000000..a2bb34b
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <log/logger_support.h>
+#include <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // See the documentation of the KEA_* environment variables in
+    // src/lib/log/README for info on how to tweak logging
+    isc::log::initLogger();
+
+    int result = RUN_ALL_TESTS();
+
+    return (result);
+}