Browse Source

[trac3664] Code updates and add unittests for parsing

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.
Shawn Routhier 10 years ago
parent
commit
6bb231d222

+ 1 - 2
src/bin/lfc/Makefile.am

@@ -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

+ 55 - 38
src/bin/lfc/lfc.cc

@@ -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());
-//}

+ 77 - 9
src/bin/lfc/lfc.h

@@ -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

+ 2 - 5
src/bin/lfc/main.cc

@@ -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;

+ 6 - 5
src/bin/lfc/tests/Makefile.am

@@ -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

+ 158 - 0
src/bin/lfc/tests/lfc_controller_unittests.cc

@@ -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

+ 30 - 0
src/bin/lfc/tests/lfc_unittests.cc

@@ -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);
+}