[mapguide-commits] r9202 - sandbox/jng/cmdline/Server/src/Core

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed Jun 7 08:32:57 PDT 2017


Author: jng
Date: 2017-06-07 08:32:57 -0700 (Wed, 07 Jun 2017)
New Revision: 9202

Added:
   sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.cpp
   sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.h
   sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.cpp
   sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.h
   sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.cpp
   sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.h
   sandbox/jng/cmdline/Server/src/Core/TestCommand.cpp
   sandbox/jng/cmdline/Server/src/Core/TestCommand.h
   sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.cpp
   sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.h
Modified:
   sandbox/jng/cmdline/Server/src/Core/Makefile.am
   sandbox/jng/cmdline/Server/src/Core/Server.cpp
   sandbox/jng/cmdline/Server/src/Core/Server.h
   sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj
   sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj.filters
   sandbox/jng/cmdline/Server/src/Core/ServerCoreBuild.cpp
Log:
With the introduction of these new interactive commands, it has become clear that in order for this to be more maintainable and easily extendible in the future (ie. if we add more commands), then we should have a command pattern in place to avoid a giant if/else block in MgServer::svc()

This commit does exactly that. It adds a new abstract MgServerInteractiveCommand class, from which we have the following subclasses:

 - MgTestCommand: For "mgserver test"
 - MgTestFdoCommand: For "mgserver testfdo"
 - MgLoadPackageCommand: For "mgserver loadpackage"
 - MgSetPwdCommand: For "mgserver setpwd"

In MgServer::ParseArgs(), we now set the appropriate command pointer and in MgServer::svc() we now check for a set command pointer, which if set we instruct it to Execute() and capture its return code. Otherwise we proceed with normal service (or interactive) startup.

Added: sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.cpp	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,70 @@
+#include "LoadPackageCommand.h"
+
+MgLoadPackageCommand::MgLoadPackageCommand(CREFSTRING locale, CREFSTRING path)
+    : MgServerInteractiveCommand()
+{
+    m_locale = locale;
+    m_path = path;
+}
+
+MgLoadPackageCommand::~MgLoadPackageCommand()
+{
+
+}
+
+INT32 MgLoadPackageCommand::Execute()
+{
+    INT32 nResult = 0;
+    try
+    {
+        if (MgFileUtil::IsFile(m_path))
+        {
+            // Let the site manager know that the check servers background thread needs to stop
+            MgSiteManager* siteManager = MgSiteManager::GetInstance();
+            siteManager->StopCheckServersThread();
+
+            // Set the user information for the current thread to be administrator.
+            //
+            // This is server-local, so no authentication is done. The MgServiceManager just needs to know the user when
+            // services are requested.
+            Ptr<MgUserInformation> adminUserInfo = new MgUserInformation(MgUser::Administrator, L"");
+            MgUserInformation::SetCurrentUserInfo(adminUserInfo);
+
+            MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+            Ptr<MgResourceService> resSvc = dynamic_cast<MgResourceService*>(serviceManager->RequestService(MgServiceType::ResourceService));
+            if (NULL == (MgResourceService*)resSvc)
+            {
+                throw new MgServiceNotAvailableException(L"MgLoadPackageCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+            }
+
+            Ptr<MgByteSource> bs = new MgByteSource(m_path);
+            Ptr<MgByteReader> br = bs->GetReader();
+
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Loading package file: %W...\n\n"), m_path.c_str()));
+            resSvc->ApplyResourcePackage(br);
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Package loaded.\n")));
+        }
+        else
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Package file not found: %W\n\n"), m_path.c_str()));
+
+            nResult = -1;
+        }
+    }
+    catch (MgException* e)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(m_locale).c_str()));
+        SAFE_RELEASE(e);
+
+        nResult = -1;
+    }
+    catch (...)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
+
+        nResult = -1;
+    }
+
+    return nResult;
+}

Added: sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.h	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/LoadPackageCommand.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,19 @@
+#ifndef LOAD_PACKAGE_COMMAND_H
+#define LOAD_PACKAGE_COMMAND_H
+
+#include "MapGuideCommon.h"
+#include "ServerInteractiveCommand.h"
+
+class MgLoadPackageCommand : public MgServerInteractiveCommand
+{
+public:
+    MgLoadPackageCommand(CREFSTRING locale, CREFSTRING path);
+    virtual ~MgLoadPackageCommand();
+    virtual INT32 Execute();
+
+private:
+    STRING m_locale;
+    STRING m_path;
+};
+
+#endif

Modified: sandbox/jng/cmdline/Server/src/Core/Makefile.am
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/Makefile.am	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/Makefile.am	2017-06-07 15:32:57 UTC (rev 9202)
@@ -56,6 +56,7 @@
   EventTimerManager.cpp \
   FeatureServiceCacheTimeLimitEventHandler.cpp \
   main.cpp \
+  LoadPackageCommand.cpp \
   OperationThread.cpp \
   PerformanceLoggingEventHandler.cpp \
   RepositoryCheckpointEventHandler.cpp \
@@ -63,10 +64,14 @@
   ResourceServiceCacheTimeLimitEventHandler.cpp \
   Server.cpp \
   ServerFactory.cpp \
+  ServerInteractiveCommand.cpp \
   ServiceHandlerFactory.cpp \
   ServiceRegistrationEventHandler.cpp \
   SessionTimeoutEventHandler.cpp \
+  SetPwdCommand.cpp \
   SignalHandler.cpp \
+  TestCommand.cpp \
+  TestFdoCommand.cpp \
   TimedEvent.cpp \
   TimedEventHandler.cpp
 
@@ -78,6 +83,7 @@
   EventTimer.h \
   EventTimerManager.h \
   FeatureServiceCacheTimeLimitEventHandler.h \
+  LoadPackageCommand.h \
   OperationThread.h \
   PerformanceLoggingEventHandler.h \
   RepositoryCheckpointEventHandler.h \
@@ -85,9 +91,13 @@
   ResourceServiceCacheTimeLimitEventHandler.h \
   Server.h \
   ServiceHandlerFactory.h \
+  ServerInteractiveCommand.h \
   ServiceRegistrationEventHandler.h \
   SessionTimeoutEventHandler.h \
+  SetPwdCommand.h \
   SignalHandler.h \
+  TestCommand.h \
+  TestFdoCommand.h \
   TimedEvent.h \
   TimedEventHandler.h
 

Modified: sandbox/jng/cmdline/Server/src/Core/Server.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/Server.cpp	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/Server.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -38,6 +38,11 @@
 #include "Renderer.h"
 #include "MappingUtil.h"
 
+#include "LoadPackageCommand.h"
+#include "SetPwdCommand.h"
+#include "TestCommand.h"
+#include "TestFdoCommand.h"
+
 #ifdef _DEBUG
 void DebugOutput(const ACE_TCHAR* format, ...)
 {
@@ -77,13 +82,12 @@
     ACE_DEBUG ((LM_DEBUG, ACE_TEXT("ACE_WIN64 NOT DEFINED\n")));
 #endif
 
-    reactor(ACE_Reactor::instance());
-
-    m_bTestMode = false;
     m_bTestFdo = false;
-    m_bLoadPackage = false;
-    m_bSetPwd = false;
+    m_bTestMode = false;
 
+    reactor(ACE_Reactor::instance());
+    m_command.reset(NULL);
+
 #ifdef _DEBUG
     m_nClientRequestLimit = -1;   // -1 = No limit. DEBUG ONLY
 #endif
@@ -225,68 +229,75 @@
         if((ACE_OS::strcasecmp(parameter, MG_WCHAR_TO_TCHAR(MgResources::ServerCmdTest)) == 0) ||
            (ACE_OS::strcasecmp(parameter, MG_WCHAR_TO_TCHAR(MgResources::ServerCmdTestMode)) == 0))
         {
+            MgServerManager* pServerManager = MgServerManager::GetInstance();
+
             // Test mode
             m_bTestMode = true;
-            m_strTestFileName = L"";    // Default to no output filename
-            m_strTestName = MgResources::ServerCmdTestDefaultTests;     // Default to all of the tests
+            STRING outputFile = L"";    // Default to no output filename
+            STRING subSuite = MgResources::ServerCmdTestDefaultTests;     // Default to all of the tests
 
             // If there is a 2nd parameter it is the test to run
             if(argc > 2)
             {
-                m_strTestName = MG_TCHAR_TO_WCHAR(argv[2]);
+                subSuite = MG_TCHAR_TO_WCHAR(argv[2]);
             }
 
             // If there is a 3rd parameter it is the output filename
             if(argc > 3)
             {
-                m_strTestFileName = MG_TCHAR_TO_WCHAR(argv[3]);
+                outputFile = MG_TCHAR_TO_WCHAR(argv[3]);
             }
+
+            m_command.reset(new MgTestCommand(pServerManager->GetDefaultMessageLocale(), subSuite, outputFile));
         }
         else if(ACE_OS::strcasecmp(parameter, MG_WCHAR_TO_TCHAR(MgResources::ServerCmdTestFdo)) == 0)
         {
+            MgServerManager* pServerManager = MgServerManager::GetInstance();
+
             // Test FDO
             m_bTestFdo = true;
+            STRING outputFile = L"";
 
             // If there is a 2nd parameter it is the output filename
             if(argc > 2)
             {
-                m_strTestFileName = MG_TCHAR_TO_WCHAR(argv[2]);
+                outputFile = MG_TCHAR_TO_WCHAR(argv[2]);
             }
-            else
-            {
-                m_strTestFileName = L"";
-            }
+
+            m_command.reset(new MgTestFdoCommand(pServerManager->GetDefaultMessageLocale(), outputFile));
         }
         else if (ACE_OS::strcasecmp(parameter, MG_WCHAR_TO_TCHAR(MgResources::ServerCmdLoadPackage)) == 0)
         {
+            MgServerManager* pServerManager = MgServerManager::GetInstance();
+
             // Package loading mode
-            m_bLoadPackage = true;
+            STRING packagePath = L"";
 
             // If there is a 2nd parameter it is the package filename
             if (argc > 2)
             {
-                m_strPackageFilePath = MG_TCHAR_TO_WCHAR(argv[2]);
+                packagePath = MG_TCHAR_TO_WCHAR(argv[2]);
             }
-            else
-            {
-                m_strPackageFilePath = L"";
-            }
+
+            m_command.reset(new MgLoadPackageCommand(pServerManager->GetDefaultMessageLocale(), packagePath));
         }
         else if (ACE_OS::strcasecmp(parameter, MG_WCHAR_TO_TCHAR(MgResources::ServerCmdSetPwd)) == 0)
         {
-            // Password changing mode
-            m_bSetPwd = true;
+            MgServerManager* pServerManager = MgServerManager::GetInstance();
 
-            m_strUser = L"";
-            m_strPassword = L"";
+            // Password changing mode
+            STRING strUser = L"";
+            STRING strPassword = L"";
             if (argc > 2)
             {
-                m_strUser = MG_TCHAR_TO_WCHAR(argv[2]);
+                strUser = MG_TCHAR_TO_WCHAR(argv[2]);
             }
             if (argc > 3)
             {
-                m_strPassword = MG_TCHAR_TO_WCHAR(argv[3]);
+                strPassword = MG_TCHAR_TO_WCHAR(argv[3]);
             }
+
+            m_command.reset(new MgSetPwdCommand(pServerManager->GetDefaultMessageLocale(), strUser, strPassword));
         }
         delete[] parameter;
     }
@@ -305,336 +316,10 @@
 
     MgServerManager* pServerManager = MgServerManager::GetInstance();
 
-    if(m_bTestMode)
+    if (m_command.get()) //An interactive command was set, run it
     {
-        // Run the test cases
-
-        typedef int (*EXECUTE)(CREFSTRING, CREFSTRING);
-
-        MG_LOG_TRACE_ENTRY(L"MgServer::svc() - Running the server unit tests.");
-        ACE_DEBUG((LM_INFO, ACE_TEXT("Preparing to run the unit tests...\n\n")));
-
-        try
-        {
-            // Let the site manager know that the check servers background thread needs to stop
-            MgSiteManager* siteManager = MgSiteManager::GetInstance();
-            siteManager->StopCheckServersThread();
-
-            // Change the log file names to use the unit test names because we don't want to replace the existing log files
-            MgLogManager* pLogManager = MgLogManager::GetInstance();
-            STRING filename;
-
-            filename = L"Test" + MgLogManager::DefaultAccessLogFileName;
-            pLogManager->SetAccessLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultAdminLogFileName;
-            pLogManager->SetAdminLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultAuthenticationLogFileName;
-            pLogManager->SetAuthenticationLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultErrorLogFileName;
-            pLogManager->SetErrorLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultSessionLogFileName;
-            pLogManager->SetSessionLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultTraceLogFileName;
-            pLogManager->SetTraceLogFileName(filename);
-
-            EXECUTE execute = NULL;
-
-        #ifdef _WIN32
-            HMODULE hlib = NULL;
-            #ifdef _DEBUG // load debug dll
-            STRING library = L"MgUnitTestingd.dll";
-            hlib = LoadLibrary(library.c_str());
-            #else // Load Release dll
-            STRING library = L"MgUnitTesting.dll";
-            hlib = LoadLibrary(library.c_str());
-            #endif
-
-            if (hlib != NULL)
-            {
-                execute = (EXECUTE)GetProcAddress(hlib, "Execute");
-            }
-            else
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %W\n"), library.c_str()));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-        #else
-            string library = "libMgUnitTesting.so";
-            void* hlib = dlopen(library.c_str(), RTLD_NOW);
-
-            if (hlib != NULL)
-            {
-                execute = (EXECUTE)dlsym(hlib, "Execute");
-            }
-            else
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %s\n"), library.c_str()));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-        #endif // _WIN32
-            if (execute != NULL)
-            {
-                nResult = (*execute)(m_strTestFileName, m_strTestName);
-
-                // The build script does not work with negative return codes, which is what is returned on a failure from CPPUnit.
-                // Therefore, we change the -1 result to a positive 1 to indicate to the build script that an error occurred.
-                if(nResult < 0)
-                {
-                    nResult = -(nResult);
-                }
-            }
-            else
-            {
-                // Failed to retrieve function
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot locate 'Execute' procedure address inside library.\n")));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-
-            ACE_DEBUG((LM_INFO, ACE_TEXT("Finished running the unit tests.\n\n")));
-        }
-        catch (MgException* e)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the unit tests.\n")));
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(pServerManager->GetDefaultMessageLocale()).c_str()));
-            SAFE_RELEASE(e);
-
-            nResult = -1;
-        }
-        catch (...)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the unit tests.\n")));
-
-            nResult = -1;
-        }
+        nResult = m_command->Execute();
     }
-    else if(m_bTestFdo)
-    {
-        // Run the FDO test cases
-
-        typedef int (*EXECUTE)(CREFSTRING);
-
-        MG_LOG_TRACE_ENTRY(L"MgServer::svc() - Running the FDO unit tests.");
-        ACE_DEBUG((LM_INFO, ACE_TEXT("Preparing to run the FDO unit tests...\n\n")));
-
-        try
-        {
-            // Let the site manager know that the check servers background thread needs to stop
-            MgSiteManager* siteManager = MgSiteManager::GetInstance();
-            siteManager->StopCheckServersThread();
-
-            // Change the log file names to use the unit test names because we don't want to replace the existing log files
-            MgLogManager* pLogManager = MgLogManager::GetInstance();
-            STRING filename;
-
-            filename = L"Test" + MgLogManager::DefaultAccessLogFileName;
-            pLogManager->SetAccessLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultAdminLogFileName;
-            pLogManager->SetAdminLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultAuthenticationLogFileName;
-            pLogManager->SetAuthenticationLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultErrorLogFileName;
-            pLogManager->SetErrorLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultSessionLogFileName;
-            pLogManager->SetSessionLogFileName(filename);
-
-            filename = L"Test" + MgLogManager::DefaultTraceLogFileName;
-            pLogManager->SetTraceLogFileName(filename);
-
-            EXECUTE execute = NULL;
-
-        #ifdef _WIN32
-            HMODULE hlib = NULL;
-            #ifdef _DEBUG // load debug dll
-            STRING library = L"MgFdoUnitTestingd.dll";
-            hlib = LoadLibrary(library.c_str());
-            #else // Load Release dll
-            STRING library = L"MgFdoUnitTesting.dll";
-            hlib = LoadLibrary(library.c_str());
-            #endif
-
-            if (hlib != NULL)
-            {
-                execute = (EXECUTE)GetProcAddress(hlib, "Execute");
-            }
-            else
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %W\n"), library.c_str()));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-        #else
-            string library = "libMgFdoUnitTesting.so";
-            void* hlib = dlopen(library.c_str(), RTLD_NOW);
-
-            if (hlib != NULL)
-            {
-                execute = (EXECUTE)dlsym(hlib, "Execute");
-            }
-            else
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %s\n"), library.c_str()));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-        #endif // _WIN32
-            if (execute != NULL)
-            {
-                nResult = (*execute)(m_strTestFileName);
-
-                // The build script does not work with negative return codes, which is what is returned on a failure from CPPUnit.
-                // Therefore, we change the -1 result to a positive 1 to indicate to the build script that an error occurred.
-                if(nResult < 0)
-                {
-                    nResult = -(nResult);
-                }
-            }
-            else
-            {
-                // Failed to retrieve function
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot locate 'Execute' procedure address inside library.\n")));
-                throw new MgUnclassifiedException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-
-            ACE_DEBUG((LM_INFO, ACE_TEXT("Finished running the FDO unit tests.\n")));
-        }
-        catch (MgException* e)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the FDO unit tests.\n")));
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(pServerManager->GetDefaultMessageLocale()).c_str()));
-            SAFE_RELEASE(e);
-
-            nResult = -1;
-        }
-        catch (...)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the FDO unit tests.\n")));
-
-            nResult = -1;
-        }
-    }
-    else if (m_bLoadPackage)
-    {
-        try 
-        {
-            if (MgFileUtil::IsFile(m_strPackageFilePath))
-            {
-                // Let the site manager know that the check servers background thread needs to stop
-                MgSiteManager* siteManager = MgSiteManager::GetInstance();
-                siteManager->StopCheckServersThread();
-
-                // Set the user information for the current thread to be administrator.
-                //
-                // This is server-local, so no authentication is done. The MgServiceManager just needs to know the user when
-                // services are requested.
-                Ptr<MgUserInformation> adminUserInfo = new MgUserInformation(MgUser::Administrator, L"");
-                MgUserInformation::SetCurrentUserInfo(adminUserInfo);
-
-                MgServiceManager* serviceManager = MgServiceManager::GetInstance();
-                Ptr<MgResourceService> resSvc = dynamic_cast<MgResourceService*>(serviceManager->RequestService(MgServiceType::ResourceService));
-                if (NULL == (MgResourceService*)resSvc)
-                {
-                    throw new MgServiceNotAvailableException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-                }
-
-                Ptr<MgByteSource> bs = new MgByteSource(m_strPackageFilePath);
-                Ptr<MgByteReader> br = bs->GetReader();
-
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Loading package file: %W...\n\n"), m_strPackageFilePath.c_str()));
-                resSvc->ApplyResourcePackage(br);
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Package loaded.\n")));
-            }
-            else
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("Package file not found: %W\n\n"), m_strPackageFilePath.c_str()));
-
-                nResult = -1;
-            }
-        }
-        catch (MgException* e)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(pServerManager->GetDefaultMessageLocale()).c_str()));
-            SAFE_RELEASE(e);
-
-            nResult = -1;
-        }
-        catch (...)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
-
-            nResult = -1;
-        }
-    }
-    else if (m_bSetPwd)
-    {
-        try
-        {
-            // Let the site manager know that the check servers background thread needs to stop
-            MgSiteManager* siteManager = MgSiteManager::GetInstance();
-            siteManager->StopCheckServersThread();
-
-            // Set the user information for the current thread to be administrator.
-            //
-            // This is server-local, so no authentication is done. The MgServiceManager just needs to know the user when
-            // services are requested.
-            Ptr<MgUserInformation> adminUserInfo = new MgUserInformation(MgUser::Administrator, L"");
-            MgUserInformation::SetCurrentUserInfo(adminUserInfo);
-
-            MgServiceManager* serviceManager = MgServiceManager::GetInstance();
-            Ptr<MgServerSiteService> pService = dynamic_cast<MgServerSiteService*>(serviceManager->RequestService(MgServiceType::SiteService));
-            if (NULL == (MgServerSiteService*)pService)
-            {
-                throw new MgServiceNotAvailableException(L"MgServer.svc", __LINE__, __WFILE__, NULL, L"", NULL);
-            }
-
-            if (m_strUser.empty()) //Need to have passed username
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("No username specified.\n")));
-                nResult = -1;
-            }
-            else if (m_strPassword.empty()) //Need to have passed pwd
-            {
-                ACE_DEBUG((LM_INFO, ACE_TEXT("No password specified.\n")));
-                nResult = -1;
-            }
-            else
-            {
-                //Anonymous has no password, so there's nothing to set
-                if (m_strUser == MgUser::Anonymous)
-                {
-                    ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot change password for Anonymous.\n")));
-                    nResult = -1;
-                }
-                else
-                {
-                    ACE_DEBUG((LM_INFO, ACE_TEXT("Changing password for user: %W...\n\n"), m_strUser.c_str()));
-                    pService->UpdateUser(m_strUser, L"", L"", m_strPassword, L"");
-                    ACE_DEBUG((LM_INFO, ACE_TEXT("Password changed.\n")));
-                }
-            }
-        }
-        catch (MgException* e)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(pServerManager->GetDefaultMessageLocale()).c_str()));
-            SAFE_RELEASE(e);
-
-            nResult = -1;
-        }
-        catch (...)
-        {
-            ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
-
-            nResult = -1;
-        }
-    }
     else
     {
         try

Modified: sandbox/jng/cmdline/Server/src/Core/Server.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/Server.h	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/Server.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -20,6 +20,7 @@
 
 #include "MapGuideCommon.h"
 #include "EventTimerManager.h"
+#include "ServerInteractiveCommand.h"
 
 #ifdef _WIN32
 #include "ace/NT_Service.h"
@@ -121,15 +122,9 @@
     ///////////////////////////////////////////////////////
     /// Member data
 private:
-    bool m_bSetPwd;
-    STRING m_strUser;
-    STRING m_strPassword;
-    bool m_bLoadPackage;
-    STRING m_strPackageFilePath;
+    std::auto_ptr<MgServerInteractiveCommand> m_command;
     bool m_bTestMode;
     bool m_bTestFdo;
-    STRING m_strTestFileName;
-    STRING m_strTestName;
 
 #ifdef _DEBUG
     INT32 m_nClientRequestLimit;        // DEBUG ONLY

Modified: sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj	2017-06-07 15:32:57 UTC (rev 9202)
@@ -249,6 +249,12 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="LoadPackageCommand.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
     <ClCompile Include="PerformanceLoggingEventHandler.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -273,6 +279,12 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="ServerInteractiveCommand.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
     <ClCompile Include="ServiceRegistrationEventHandler.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -285,6 +297,24 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="SetPwdCommand.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="TestFdoCommand.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="TestCommand.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
     <ClCompile Include="TimedEvent.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -348,12 +378,17 @@
     <ClInclude Include="EventTimer.h" />
     <ClInclude Include="EventTimerManager.h" />
     <ClInclude Include="FeatureServiceCacheTimeLimitEventHandler.h" />
+    <ClInclude Include="LoadPackageCommand.h" />
     <ClInclude Include="PerformanceLoggingEventHandler.h" />
     <ClInclude Include="RepositoryCheckpointEventHandler.h" />
     <ClInclude Include="ResourceChangeEventHandler.h" />
     <ClInclude Include="ResourceServiceCacheTimeLimitEventHandler.h" />
+    <ClInclude Include="ServerInteractiveCommand.h" />
     <ClInclude Include="ServiceRegistrationEventHandler.h" />
     <ClInclude Include="SessionTimeoutEventHandler.h" />
+    <ClInclude Include="SetPwdCommand.h" />
+    <ClInclude Include="TestCommand.h" />
+    <ClInclude Include="TestFdoCommand.h" />
     <ClInclude Include="TimedEvent.h" />
     <ClInclude Include="TimedEventHandler.h" />
     <ClInclude Include="ClientAcceptor.h" />

Modified: sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj.filters
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj.filters	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/ServerCore.vcxproj.filters	2017-06-07 15:32:57 UTC (rev 9202)
@@ -4,6 +4,9 @@
     <Filter Include="TimedEventHandlers">
       <UniqueIdentifier>{73580568-ac7b-4016-8439-2059bd65dc97}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Commands">
+      <UniqueIdentifier>{049d02ba-050a-40b1-a175-00a994d8cd91}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="ConnectionTimeoutEventHandler.cpp">
@@ -56,6 +59,19 @@
     <ClCompile Include="ResourceServiceCacheTimeLimitEventHandler.cpp">
       <Filter>TimedEventHandlers</Filter>
     </ClCompile>
+    <ClCompile Include="ServerInteractiveCommand.cpp" />
+    <ClCompile Include="LoadPackageCommand.cpp">
+      <Filter>Commands</Filter>
+    </ClCompile>
+    <ClCompile Include="SetPwdCommand.cpp">
+      <Filter>Commands</Filter>
+    </ClCompile>
+    <ClCompile Include="TestCommand.cpp">
+      <Filter>Commands</Filter>
+    </ClCompile>
+    <ClCompile Include="TestFdoCommand.cpp">
+      <Filter>Commands</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="ConnectionTimeoutEventHandler.h">
@@ -105,6 +121,19 @@
     <ClInclude Include="ResourceServiceCacheTimeLimitEventHandler.h">
       <Filter>TimedEventHandlers</Filter>
     </ClInclude>
+    <ClInclude Include="ServerInteractiveCommand.h" />
+    <ClInclude Include="LoadPackageCommand.h">
+      <Filter>Commands</Filter>
+    </ClInclude>
+    <ClInclude Include="SetPwdCommand.h">
+      <Filter>Commands</Filter>
+    </ClInclude>
+    <ClInclude Include="TestCommand.h">
+      <Filter>Commands</Filter>
+    </ClInclude>
+    <ClInclude Include="TestFdoCommand.h">
+      <Filter>Commands</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ServerCore.rc" />

Modified: sandbox/jng/cmdline/Server/src/Core/ServerCoreBuild.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/ServerCoreBuild.cpp	2017-06-07 13:51:00 UTC (rev 9201)
+++ sandbox/jng/cmdline/Server/src/Core/ServerCoreBuild.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -36,3 +36,10 @@
 #include "TimedEvent.cpp"
 #include "TimedEventHandler.cpp"
 #include "ServerFactory.cpp"
+
+// Commands
+#include "ServerInteractiveCommand.cpp"
+#include "TestCommand.cpp"
+#include "TestFdoCommand.cpp"
+#include "LoadPackageCommand.cpp"
+#include "SetPwdCommand.cpp"
\ No newline at end of file

Added: sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.cpp	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,12 @@
+#include "ServerInteractiveCommand.h"
+
+
+
+MgServerInteractiveCommand::MgServerInteractiveCommand()
+{
+}
+
+
+MgServerInteractiveCommand::~MgServerInteractiveCommand()
+{
+}

Added: sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.h	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/ServerInteractiveCommand.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,16 @@
+#ifndef SERVER_INTERACTIVE_COMMAND_H
+#define SERVER_INTERACTIVE_COMMAND_H
+
+// The base class of all interactive commands
+class MgServerInteractiveCommand
+{
+protected:
+    MgServerInteractiveCommand();
+
+public:
+    virtual ~MgServerInteractiveCommand();
+
+    virtual INT32 Execute() = 0;
+};
+
+#endif
\ No newline at end of file

Added: sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.cpp	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,81 @@
+#include "SetPwdCommand.h"
+
+MgSetPwdCommand::MgSetPwdCommand(CREFSTRING locale, CREFSTRING userName, CREFSTRING password)
+    : MgServerInteractiveCommand()
+{
+    m_locale = locale;
+    m_strUser = userName;
+    m_strPassword = password;
+}
+
+
+MgSetPwdCommand::~MgSetPwdCommand()
+{
+}
+
+INT32 MgSetPwdCommand::Execute()
+{
+    INT32 nResult = 0;
+    try
+    {
+        // Let the site manager know that the check servers background thread needs to stop
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        siteManager->StopCheckServersThread();
+
+        // Set the user information for the current thread to be administrator.
+        //
+        // This is server-local, so no authentication is done. The MgServiceManager just needs to know the user when
+        // services are requested.
+        Ptr<MgUserInformation> adminUserInfo = new MgUserInformation(MgUser::Administrator, L"");
+        MgUserInformation::SetCurrentUserInfo(adminUserInfo);
+
+        MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+        Ptr<MgServerSiteService> pService = dynamic_cast<MgServerSiteService*>(serviceManager->RequestService(MgServiceType::SiteService));
+        if (NULL == (MgServerSiteService*)pService)
+        {
+            throw new MgServiceNotAvailableException(L"MgSetPwdCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        if (m_strUser.empty()) //Need to have passed username
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("No username specified.\n")));
+            nResult = -1;
+        }
+        else if (m_strPassword.empty()) //Need to have passed pwd
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("No password specified.\n")));
+            nResult = -1;
+        }
+        else
+        {
+            //Anonymous has no password, so there's nothing to set
+            if (m_strUser == MgUser::Anonymous)
+            {
+                ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot change password for Anonymous.\n")));
+                nResult = -1;
+            }
+            else
+            {
+                ACE_DEBUG((LM_INFO, ACE_TEXT("Changing password for user: %W...\n\n"), m_strUser.c_str()));
+                pService->UpdateUser(m_strUser, L"", L"", m_strPassword, L"");
+                ACE_DEBUG((LM_INFO, ACE_TEXT("Password changed.\n")));
+            }
+        }
+    }
+    catch (MgException* e)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(m_locale).c_str()));
+        SAFE_RELEASE(e);
+
+        nResult = -1;
+    }
+    catch (...)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to load the specified package.\n")));
+
+        nResult = -1;
+    }
+
+    return nResult;
+}

Added: sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.h	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/SetPwdCommand.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,21 @@
+#ifndef SET_PWD_COMMAND_H
+#define SET_PWD_COMMAND_H
+
+#include "MapGuideCommon.h"
+#include "ServerInteractiveCommand.h"
+
+class MgSetPwdCommand : public MgServerInteractiveCommand
+{
+public:
+    MgSetPwdCommand(CREFSTRING locale, CREFSTRING userName, CREFSTRING password);
+    virtual ~MgSetPwdCommand();
+
+    virtual INT32 Execute();
+
+private:
+    STRING m_locale;
+    STRING m_strUser;
+    STRING m_strPassword;
+};
+
+#endif
\ No newline at end of file

Added: sandbox/jng/cmdline/Server/src/Core/TestCommand.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/TestCommand.cpp	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/TestCommand.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,126 @@
+#include "LogManager.h"
+#include "TestCommand.h"
+
+MgTestCommand::MgTestCommand(CREFSTRING locale, CREFSTRING subSuite, CREFSTRING outputFile)
+    : MgServerInteractiveCommand()
+{
+    m_locale = locale;
+    m_subSuite = subSuite;
+    m_outputFile = outputFile;
+}
+
+MgTestCommand::~MgTestCommand()
+{
+}
+
+INT32 MgTestCommand::Execute()
+{
+    INT32 nResult = 0;
+
+    // Run the test cases
+
+    typedef int(*EXECUTE)(CREFSTRING, CREFSTRING);
+
+    MG_LOG_TRACE_ENTRY(L"MgTestCommand::Execute() - Running the server unit tests.");
+    ACE_DEBUG((LM_INFO, ACE_TEXT("Preparing to run the unit tests...\n\n")));
+
+    try
+    {
+        // Let the site manager know that the check servers background thread needs to stop
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        siteManager->StopCheckServersThread();
+
+        // Change the log file names to use the unit test names because we don't want to replace the existing log files
+        MgLogManager* pLogManager = MgLogManager::GetInstance();
+        STRING filename;
+
+        filename = L"Test" + MgLogManager::DefaultAccessLogFileName;
+        pLogManager->SetAccessLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultAdminLogFileName;
+        pLogManager->SetAdminLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultAuthenticationLogFileName;
+        pLogManager->SetAuthenticationLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultErrorLogFileName;
+        pLogManager->SetErrorLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultSessionLogFileName;
+        pLogManager->SetSessionLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultTraceLogFileName;
+        pLogManager->SetTraceLogFileName(filename);
+
+        EXECUTE execute = NULL;
+
+#ifdef _WIN32
+        HMODULE hlib = NULL;
+#ifdef _DEBUG // load debug dll
+        STRING library = L"MgUnitTestingd.dll";
+        hlib = LoadLibrary(library.c_str());
+#else // Load Release dll
+        STRING library = L"MgUnitTesting.dll";
+        hlib = LoadLibrary(library.c_str());
+#endif
+
+        if (hlib != NULL)
+        {
+            execute = (EXECUTE)GetProcAddress(hlib, "Execute");
+        }
+        else
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %W\n"), library.c_str()));
+            throw new MgUnclassifiedException(L"MgTestCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+#else
+        string library = "libMgUnitTesting.so";
+        void* hlib = dlopen(library.c_str(), RTLD_NOW);
+
+        if (hlib != NULL)
+        {
+            execute = (EXECUTE)dlsym(hlib, "Execute");
+        }
+        else
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %s\n"), library.c_str()));
+            throw new MgUnclassifiedException(L"MgTestCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+#endif // _WIN32
+        if (execute != NULL)
+        {
+            nResult = (*execute)(m_outputFile, m_subSuite);
+
+            // The build script does not work with negative return codes, which is what is returned on a failure from CPPUnit.
+            // Therefore, we change the -1 result to a positive 1 to indicate to the build script that an error occurred.
+            if (nResult < 0)
+            {
+                nResult = -(nResult);
+            }
+        }
+        else
+        {
+            // Failed to retrieve function
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot locate 'Execute' procedure address inside library.\n")));
+            throw new MgUnclassifiedException(L"MgTestCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        ACE_DEBUG((LM_INFO, ACE_TEXT("Finished running the unit tests.\n\n")));
+    }
+    catch (MgException* e)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the unit tests.\n")));
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(m_locale).c_str()));
+        SAFE_RELEASE(e);
+
+        nResult = -1;
+    }
+    catch (...)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the unit tests.\n")));
+
+        nResult = -1;
+    }
+
+    return nResult;
+}
\ No newline at end of file

Added: sandbox/jng/cmdline/Server/src/Core/TestCommand.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/TestCommand.h	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/TestCommand.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,22 @@
+#ifndef TEST_COMMAND_H
+#define TEST_COMMAND_H
+
+#include "MapGuideCommon.h"
+#include "ServerInteractiveCommand.h"
+
+class MgTestCommand : public MgServerInteractiveCommand
+{
+public:
+    MgTestCommand(CREFSTRING locale, CREFSTRING subSuite, CREFSTRING outputFile);
+    virtual ~MgTestCommand();
+
+    virtual INT32 Execute();
+
+private:
+    STRING m_locale;
+    STRING m_subSuite;
+    STRING m_outputFile;
+};
+
+#endif
+

Added: sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.cpp
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.cpp	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.cpp	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,125 @@
+#include "LogManager.h"
+#include "TestFdoCommand.h"
+
+MgTestFdoCommand::MgTestFdoCommand(CREFSTRING locale, CREFSTRING outputFile)
+    : MgServerInteractiveCommand()
+{
+    m_locale = locale;
+    m_outputFile = outputFile;
+}
+
+MgTestFdoCommand::~MgTestFdoCommand()
+{
+}
+
+INT32 MgTestFdoCommand::Execute()
+{
+    INT32 nResult = 0;
+
+    // Run the FDO test cases
+
+    typedef int(*EXECUTE)(CREFSTRING);
+
+    MG_LOG_TRACE_ENTRY(L"MgTestFdoCommand::Execute() - Running the FDO unit tests.");
+    ACE_DEBUG((LM_INFO, ACE_TEXT("Preparing to run the FDO unit tests...\n\n")));
+
+    try
+    {
+        // Let the site manager know that the check servers background thread needs to stop
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        siteManager->StopCheckServersThread();
+
+        // Change the log file names to use the unit test names because we don't want to replace the existing log files
+        MgLogManager* pLogManager = MgLogManager::GetInstance();
+        STRING filename;
+
+        filename = L"Test" + MgLogManager::DefaultAccessLogFileName;
+        pLogManager->SetAccessLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultAdminLogFileName;
+        pLogManager->SetAdminLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultAuthenticationLogFileName;
+        pLogManager->SetAuthenticationLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultErrorLogFileName;
+        pLogManager->SetErrorLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultSessionLogFileName;
+        pLogManager->SetSessionLogFileName(filename);
+
+        filename = L"Test" + MgLogManager::DefaultTraceLogFileName;
+        pLogManager->SetTraceLogFileName(filename);
+
+        EXECUTE execute = NULL;
+
+#ifdef _WIN32
+        HMODULE hlib = NULL;
+#ifdef _DEBUG // load debug dll
+        STRING library = L"MgFdoUnitTestingd.dll";
+        hlib = LoadLibrary(library.c_str());
+#else // Load Release dll
+        STRING library = L"MgFdoUnitTesting.dll";
+        hlib = LoadLibrary(library.c_str());
+#endif
+
+        if (hlib != NULL)
+        {
+            execute = (EXECUTE)GetProcAddress(hlib, "Execute");
+        }
+        else
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %W\n"), library.c_str()));
+            throw new MgUnclassifiedException(L"MgTestFdoCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+#else
+        string library = "libMgFdoUnitTesting.so";
+        void* hlib = dlopen(library.c_str(), RTLD_NOW);
+
+        if (hlib != NULL)
+        {
+            execute = (EXECUTE)dlsym(hlib, "Execute");
+        }
+        else
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot open library: %s\n"), library.c_str()));
+            throw new MgUnclassifiedException(L"MgTestFdoCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+#endif // _WIN32
+        if (execute != NULL)
+        {
+            nResult = (*execute)(m_outputFile);
+
+            // The build script does not work with negative return codes, which is what is returned on a failure from CPPUnit.
+            // Therefore, we change the -1 result to a positive 1 to indicate to the build script that an error occurred.
+            if (nResult < 0)
+            {
+                nResult = -(nResult);
+            }
+        }
+        else
+        {
+            // Failed to retrieve function
+            ACE_DEBUG((LM_INFO, ACE_TEXT("Cannot locate 'Execute' procedure address inside library.\n")));
+            throw new MgUnclassifiedException(L"MgTestFdoCommand.Execute", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        ACE_DEBUG((LM_INFO, ACE_TEXT("Finished running the FDO unit tests.\n")));
+    }
+    catch (MgException* e)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the FDO unit tests.\n")));
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("%W\n"), e->GetStackTrace(m_locale).c_str()));
+        SAFE_RELEASE(e);
+
+        nResult = -1;
+    }
+    catch (...)
+    {
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unable to run all the FDO unit tests.\n")));
+
+        nResult = -1;
+    }
+
+    return nResult;
+}

Added: sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.h
===================================================================
--- sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.h	                        (rev 0)
+++ sandbox/jng/cmdline/Server/src/Core/TestFdoCommand.h	2017-06-07 15:32:57 UTC (rev 9202)
@@ -0,0 +1,20 @@
+#ifndef TEST_FDO_COMMAND_H
+#define TEST_FDO_COMMAND_H
+
+#include "MapGuideCommon.h"
+#include "ServerInteractiveCommand.h"
+
+class MgTestFdoCommand : public MgServerInteractiveCommand
+{
+public:
+    MgTestFdoCommand(CREFSTRING locale, CREFSTRING outputFile);
+    virtual ~MgTestFdoCommand();
+
+    virtual INT32 Execute();
+
+private:
+    STRING m_locale;
+    STRING m_outputFile;
+};
+
+#endif
\ No newline at end of file



More information about the mapguide-commits mailing list