Parcourir la 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 il y a 10 ans
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/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 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 <exceptions/exceptions.h>
 #include <log/logger_support.h>
 #include <log/logger_support.h>
 #include <log/logger_manager.h>
 #include <log/logger_manager.h>
-//#include <dhcpsrv/cfgmgr.h>
 #include <iostream>
 #include <iostream>
 
 
 using namespace std;
 using namespace std;
@@ -27,23 +26,23 @@ namespace lfc {
 
 
 /// @brief Defines the application name, it may be used to locate
 /// @brief Defines the application name, it may be used to locate
 /// configuration data and appears in log statements.
 /// 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.
 /// @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;
     std::cerr << "created lfc" << std::endl;
 }
 }
 
 
-lfc::~lfc() {
+lfcController::~lfcController() {
     std::cerr << "destroyed lfc" << std::endl;
     std::cerr << "destroyed lfc" << std::endl;
 }
 }
 
 
 void
 void
-lfc::launch(int argc, char* argv[], const bool test_mode) {
+lfcController::launch(int argc, char* argv[], const bool test_mode) {
   try {
   try {
     parseArgs(argc, argv);
     parseArgs(argc, argv);
   } catch (const InvalidUsage& ex) {
   } catch (const InvalidUsage& ex) {
@@ -55,30 +54,30 @@ lfc::launch(int argc, char* argv[], const bool test_mode) {
 }
 }
 
 
 void
 void
-lfc::parseArgs(int argc, char* argv[])
+lfcController::parseArgs(int argc, char* argv[])
 {
 {
     int ch;
     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) {
         switch (ch) {
 	case '4':
 	case '4':
             // Process DHCPv4 lease files.
             // Process DHCPv4 lease files.
-            dhcp_version_ = 4;
+            protocol_version_ = 4;
             break;
             break;
 
 
 	case '6':
 	case '6':
             // Process DHCPv6 lease files.
             // Process DHCPv6 lease files.
-            dhcp_version_ = 6;
+            protocol_version_ = 6;
             break;
             break;
 
 
 	case 'v':
 	case 'v':
             // Print just Kea vesion and exit.
             // Print just Kea vesion and exit.
-	  //            std::cout << getVersion(false) << std::endl;
+	    std::cout << getVersion(false) << std::endl;
             exit(EXIT_SUCCESS);
             exit(EXIT_SUCCESS);
 
 
 	case 'V':
 	case 'V':
             // Print extended  Kea vesion and exit.
             // Print extended  Kea vesion and exit.
-	  //std::cout << getVersion(true) << std::endl;
+	    std::cout << getVersion(true) << std::endl;
             exit(EXIT_SUCCESS);
             exit(EXIT_SUCCESS);
 
 
 	case 'd':
 	case 'd':
@@ -110,6 +109,14 @@ lfc::parseArgs(int argc, char* argv[])
 	    output_file_ = optarg;
 	    output_file_ = optarg;
 	    break;
 	    break;
 
 
+	case 'f':
+	    // Output file name.
+	    if (optarg == NULL) {
+	        isc_throw(InvalidUsage, "Finish file name missing");
+	    }
+	    finish_file_ = optarg;
+	    break;
+
 	case 'c':
 	case 'c':
 	    // Previous file name.
 	    // Previous file name.
 	    if (optarg == NULL) {
 	    if (optarg == NULL) {
@@ -128,7 +135,7 @@ lfc::parseArgs(int argc, char* argv[])
         isc_throw(InvalidUsage, "Extraneous parameters.");
         isc_throw(InvalidUsage, "Extraneous parameters.");
     }
     }
 
 
-    if (dhcp_version_ == 0) {
+    if (protocol_version_ == 0) {
         isc_throw(InvalidUsage, "DHCP version required");
         isc_throw(InvalidUsage, "DHCP version required");
     }
     }
 
 
@@ -144,43 +151,57 @@ lfc::parseArgs(int argc, char* argv[])
         isc_throw(InvalidUsage, "Output file not specified");	
         isc_throw(InvalidUsage, "Output file not specified");	
     }
     }
 
 
+    if (finish_file_.empty()) {
+        isc_throw(InvalidUsage, "Finish file not specified");	
+    }
+
     if (config_file_.empty()) {
     if (config_file_.empty()) {
         isc_throw(InvalidUsage, "Config file not specified");	
         isc_throw(InvalidUsage, "Config file not specified");	
     }
     }
 
 
     // If verbose is set echo the input information
     // If verbose is set echo the input information
     if (verbose_ == true) {
     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
 	        << "Previous lease file: " << previous_file_ << std::endl
 	        << "Copy lease file:     " << copy_file_ << std::endl
 	        << "Copy lease file:     " << copy_file_ << std::endl
 	        << "Output lease file:   " << output_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
 void
-lfc::pidDelete()
+lfcController::pidDelete(const std::string & pid_file)
 {
 {
 }
 }
 
 
 void
 void
-lfc::usage(const std::string & text)
+lfcController::usage(const std::string & text)
 {
 {
     if (text != "") {
     if (text != "") {
         std::cerr << "Usage error: " << text << std::endl;
         std::cerr << "Usage error: " << text << std::endl;
     }
     }
 
 
     std::cerr << "Usage: " << lfc_bin_name_ << 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
               << "   -4 or -6 clean a set of v4 or v6 lease files" << std::endl
               << "   -p <file>: previous lease file" << std::endl
               << "   -p <file>: previous lease file" << std::endl
               << "   -i <file>: copy of lease file" << std::endl
               << "   -i <file>: copy of lease file" << std::endl
               << "   -o <file>: output lease file" << std::endl
               << "   -o <file>: output lease file" << std::endl
+              << "   -f <file>: finish file" << std::endl
               << "   -c <file>: configuration file" << std::endl
               << "   -c <file>: configuration file" << std::endl
               << "   -v: print version number and exit" << std::endl
               << "   -v: print version number and exit" << std::endl
               << "   -V: print extended version inforamtion 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::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::lfc
 }; // namespace isc
 }; // 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;
 //class lfcBase;
 //typedef boost::shared_ptr<lfcBase> lfcBasePtr;
 //typedef boost::shared_ptr<lfcBase> lfcBasePtr;
 
 
-class lfc {
+class lfcController {
 public:
 public:
     /// @brief Defines the application name, it may be used to locate
     /// @brief Defines the application name, it may be used to locate
     /// configuration data and appears in log statements.
     /// configuration data and appears in log statements.
@@ -43,10 +43,10 @@ public:
     static const char* lfc_bin_name_;
     static const char* lfc_bin_name_;
 
 
     /// @brief Constructor
     /// @brief Constructor
-    lfc();
+    lfcController();
 
 
     /// @brief Destructor
     /// @brief Destructor
-    ~lfc();
+    ~lfcController();
 
 
     /// @brief Acts as the primary entry point to start execution
     /// @brief Acts as the primary entry point to start execution
     /// of the process.  Provides the control logic:
     /// of the process.  Provides the control logic:
@@ -63,26 +63,94 @@ public:
     /// step taken after the process has been launched.
     /// step taken after the process has been launched.
     void parseArgs(int argc, char* argv[]);
     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
     /// @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.
     /// @param text is a string message which will preceded the usage text.
     /// This is intended to be used for specific usage violation messages.
     /// This is intended to be used for specific usage violation messages.
     void usage(const std::string& text);
     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:
 private:
-    int dhcp_version_;
+    int protocol_version_;
     bool verbose_;
     bool verbose_;
     std::string config_file_;
     std::string config_file_;
     std::string previous_file_;
     std::string previous_file_;
     std::string copy_file_;
     std::string copy_file_;
     std::string output_file_;
     std::string output_file_;
+    std::string finish_file_;
+    std::string pid_file_;
 };
 };
 
 
 }; // namespace isc:lfc
 }; // namespace isc:lfc

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

@@ -31,16 +31,13 @@ using namespace std;
 /// errors, EXIT_FAILURE otherwise.
 /// errors, EXIT_FAILURE otherwise.
 int main(int argc, char* argv[]) {
 int main(int argc, char* argv[]) {
     int ret = EXIT_SUCCESS;
     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.
     // Launch the controller passing in command line arguments.
     // Exit program with the controller's return code.
     // Exit program with the controller's return code.
     try  {
     try  {
         // 'false' value disables test mode.
         // 'false' value disables test mode.
-        lfc.launch(argc, argv, false);
+        lfcController.launch(argc, argv, false);
     } catch (const isc::Exception& ex) {
     } catch (const isc::Exception& ex) {
         std::cerr << "Service failed:" << ex.what() << std::endl;
         std::cerr << "Service failed:" << ex.what() << std::endl;
         ret = EXIT_FAILURE;
         ret = EXIT_FAILURE;

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

@@ -1,8 +1,8 @@
 SHTESTS =
 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
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 check-local:
@@ -24,7 +24,7 @@ AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
 
 
 CLEANFILES = $(builddir)/interfaces.txt $(builddir)/logger_lockfile
 CLEANFILES = $(builddir)/interfaces.txt $(builddir)/logger_lockfile
 
 
-DISTCLEANFILES = lfc_process_tests.sh
+DISTCLEANFILES = 
 
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
 if USE_CLANGPP
 if USE_CLANGPP
@@ -44,12 +44,13 @@ if HAVE_GTEST
 
 
 TESTS += lfc_unittests
 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_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 lfc_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 lfc_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 lfc_unittests_LDADD = $(GTEST_LDADD)
 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/exceptions/libkea-exceptions.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 lfc_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.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);
+}