[Libreoffice-commits] online.git: loolwsd/LOOLForKit.cpp loolwsd/LOOLWSD.cpp loolwsd/Makefile.am loolwsd/Storage.cpp loolwsd/test loolwsd/Unit.cpp loolwsd/Unit.hpp

Michael Meeks michael.meeks at collabora.com
Sat Apr 9 17:17:38 UTC 2016


 loolwsd/LOOLForKit.cpp       |   19 +++++++
 loolwsd/LOOLWSD.cpp          |   17 ++++---
 loolwsd/Makefile.am          |    2 
 loolwsd/Storage.cpp          |    2 
 loolwsd/Unit.cpp             |   93 +++++++++++++++++++++++++++++---------
 loolwsd/Unit.hpp             |  103 ++++++++++++++++++++++++++++++-------------
 loolwsd/test/UnitPrefork.cpp |    4 -
 loolwsd/test/UnitStorage.cpp |    8 +--
 loolwsd/test/UnitTimeout.cpp |   20 +++++++-
 9 files changed, 197 insertions(+), 71 deletions(-)

New commits:
commit b308792801f18eabfb6a62e3cbd2f59e38faa23c
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Sat Apr 9 17:30:48 2016 +0100

    Add infrastructure to inject test pieces into loolforkit.

diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp
index e6f6c15..5529bc7 100644
--- a/loolwsd/LOOLForKit.cpp
+++ b/loolwsd/LOOLForKit.cpp
@@ -31,6 +31,7 @@
 #include "IoUtil.hpp"
 #include "LOOLKit.hpp"
 #include "Util.hpp"
+#include "Unit.hpp"
 #include "ChildProcessSession.hpp"
 
 using Poco::Path;
@@ -40,6 +41,7 @@ using Poco::Thread;
 using Poco::Timestamp;
 using Poco::Util::Application;
 
+static std::string UnitTestLibrary;
 static std::atomic<unsigned> ForkCounter( 0 );
 
 static int pipeFd = -1;
@@ -181,6 +183,11 @@ int main(int argc, char** argv)
             eq = std::strchr(cmd, '=');
             ClientPortNumber = std::stoll(std::string(eq+1));
         }
+        else if (std::strstr(cmd, "--unitlib=") == cmd)
+        {
+            eq = std::strchr(cmd, '=');
+            UnitTestLibrary = std::string(eq+1);
+        }
     }
 
     if (loSubPath.empty() || sysTemplate.empty() ||
@@ -190,6 +197,13 @@ int main(int argc, char** argv)
         return 1;
     }
 
+    if (!UnitBase::init(UnitBase::UnitType::TYPE_KIT,
+                        UnitTestLibrary))
+    {
+        Log::error("Failed to load kit unit test library");
+        return Application::EXIT_USAGE;
+    }
+
     if (!std::getenv("LD_BIND_NOW"))
         Log::info("Note: LD_BIND_NOW is not set.");
 
@@ -256,8 +270,11 @@ int main(int argc, char** argv)
 
     close(pipeFd);
 
+    int returnValue = Application::EXIT_OK;
+    UnitKit::get().returnValue(returnValue);
+
     Log::info("ForKit process finished.");
-    return Application::EXIT_OK;
+    return returnValue;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index b8becd1..b70d110 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -165,7 +165,7 @@ static void preForkChildren()
 {
     std::unique_lock<std::mutex> lock(newChildrenMutex);
     int numPreSpawn = LOOLWSD::NumPreSpawnedChildren;
-    UnitHooks::get().preSpawnCount(numPreSpawn);
+    UnitWSD::get().preSpawnCount(numPreSpawn);
     forkChildren(numPreSpawn);
 }
 
@@ -676,7 +676,7 @@ public:
             newChildren.emplace_back(std::make_shared<ChildProcess>(pid, ws));
             Log::info("Have " + std::to_string(newChildren.size()) + " children.");
             newChildrenCV.notify_one();
-            UnitHooks::get().newChild();
+            UnitWSD::get().newChild();
             return;
         }
 
@@ -1231,6 +1231,8 @@ Process::PID LOOLWSD::createForKit()
     args.push_back("--lotemplate=" + LoTemplate);
     args.push_back("--childroot=" + ChildRoot);
     args.push_back("--clientport=" + std::to_string(ClientPortNumber));
+    if (UnitWSD::get().hasKitHooks())
+        args.push_back("--unitlib=" + UnitTestLibrary);
 
     const std::string forKitPath = Path(Application::instance().commandPath()).parent().toString() + "loolforkit";
 
@@ -1252,9 +1254,10 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
         return Application::EXIT_USAGE;
     }
 
-    if (!UnitHooks::init(UnitTestLibrary))
+    if (!UnitWSD::init(UnitWSD::UnitType::TYPE_WSD,
+                         UnitTestLibrary))
     {
-        Log::error("Failed to load unit test library");
+        Log::error("Failed to load wsd unit test library");
         return Application::EXIT_USAGE;
     }
 #ifdef ENABLE_SSL
@@ -1416,7 +1419,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     int status = 0;
     while (!TerminationFlag && !LOOLWSD::DoTest)
     {
-        UnitHooks::get().invokeTest();
+        UnitWSD::get().invokeTest();
 
         const pid_t pid = waitpid(forKitPid, &status, WUNTRACED | WNOHANG);
         if (pid > 0)
@@ -1570,12 +1573,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     Log::info("Process [loolwsd] finished.");
 
     int returnValue = Application::EXIT_OK;
-    UnitHooks::get().returnValue(returnValue);
+    UnitWSD::get().returnValue(returnValue);
 
     return returnValue;
 }
 
-void UnitHooks::testHandleRequest(TestRequest type, UnitHTTPServerRequest& request, UnitHTTPServerResponse& response)
+void UnitWSD::testHandleRequest(TestRequest type, UnitHTTPServerRequest& request, UnitHTTPServerResponse& response)
 {
     switch (type)
     {
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index 943331c..c35b39c 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -15,6 +15,7 @@ shared_sources = ChildProcessSession.cpp \
                  LOOLProtocol.cpp \
                  LOOLSession.cpp \
                  MessageQueue.cpp \
+		 Unit.cpp \
                  Util.cpp
 
 loolwsd_SOURCES = Admin.cpp \
@@ -25,7 +26,6 @@ loolwsd_SOURCES = Admin.cpp \
                   MasterProcessSession.cpp \
                   Storage.cpp \
                   TileCache.cpp \
-		  Unit.cpp \
                   $(shared_sources)
 
 noinst_PROGRAMS = connect \
diff --git a/loolwsd/Storage.cpp b/loolwsd/Storage.cpp
index 849148c..1d17599 100644
--- a/loolwsd/Storage.cpp
+++ b/loolwsd/Storage.cpp
@@ -56,7 +56,7 @@ std::unique_ptr<StorageBase> StorageBase::create(const std::string& jailRoot, co
 {
     std::unique_ptr<StorageBase> storage;
 
-    if (UnitHooks::get().createStorage(jailRoot, jailPath, uri, storage))
+    if (UnitWSD::get().createStorage(jailRoot, jailPath, uri, storage))
         Log::info("Storage load hooked");
     else if (uri.isRelative() || uri.getScheme() == "file")
     {
diff --git a/loolwsd/Unit.cpp b/loolwsd/Unit.cpp
index abafa12..1c4f5fa 100644
--- a/loolwsd/Unit.cpp
+++ b/loolwsd/Unit.cpp
@@ -16,11 +16,11 @@
 #include <Poco/Thread.h>
 #include <Poco/Util/Application.h>
 
-UnitHooks *UnitHooks::_global = nullptr;
+UnitBase *UnitBase::_global = nullptr;
 
 static Poco::Thread TimeoutThread("unit timeout");
 
-UnitHooks *UnitHooks::linkAndCreateUnit(const std::string &unitLibPath)
+UnitBase *UnitBase::linkAndCreateUnit(UnitType type, const std::string &unitLibPath)
 {
     void *dlHandle = dlopen(unitLibPath.c_str(), RTLD_GLOBAL|RTLD_NOW);
     if (!dlHandle)
@@ -29,14 +29,24 @@ UnitHooks *UnitHooks::linkAndCreateUnit(const std::string &unitLibPath)
         return NULL;
     }
 
+    const char *symbol = NULL;
+    switch (type)
+    {
+        case TYPE_WSD:
+            symbol = "unit_create_wsd";
+            break;
+        case TYPE_KIT:
+            symbol = "unit_create_kit";
+            break;
+    }
     CreateUnitHooksFunction* createHooks;
-    createHooks = (CreateUnitHooksFunction *)dlsym(dlHandle, CREATE_UNIT_HOOKS_SYMBOL);
+    createHooks = reinterpret_cast<CreateUnitHooksFunction *>(dlsym(dlHandle, symbol));
     if (!createHooks)
     {
-        Log::error("No " CREATE_UNIT_HOOKS_SYMBOL " symbol in " + unitLibPath);
+        Log::error("No " + std::string(symbol) + " symbol in " + unitLibPath);
         return NULL;
     }
-    UnitHooks *pHooks = createHooks();
+    UnitBase *pHooks = createHooks();
 
     if (pHooks)
         pHooks->setHandle(dlHandle);
@@ -44,40 +54,62 @@ UnitHooks *UnitHooks::linkAndCreateUnit(const std::string &unitLibPath)
     return pHooks;
 }
 
-bool UnitHooks::init(const std::string &unitLibPath)
+bool UnitBase::init(UnitType type, const std::string &unitLibPath)
 {
+    assert(!_global);
     if (!unitLibPath.empty())
     {
-        _global = linkAndCreateUnit(unitLibPath);
-        TimeoutThread.startFunc([](){
-                TimeoutThread.trySleep(_global->_timeoutMilliSeconds);
-                if (!_global->_timeoutShutdown)
-                {
-                    Log::error("Timeout");
-                    _global->timeout();
-                }
-            });
+        _global = linkAndCreateUnit(type, unitLibPath);
+        if (_global)
+        {
+            TimeoutThread.startFunc([](){
+                    TimeoutThread.trySleep(_global->_timeoutMilliSeconds);
+                    if (!_global->_timeoutShutdown)
+                    {
+                        Log::error("Timeout");
+                        _global->timeout();
+                    }
+                });
+        }
     }
     else
-        _global = new UnitHooks();
+    {
+        switch (type)
+        {
+        case TYPE_WSD:
+            _global = new UnitWSD();
+            break;
+        case TYPE_KIT:
+            _global = new UnitKit();
+            break;
+        default:
+            assert(false);
+            break;
+        }
+    }
+
+    if (_global)
+        _global->_type = type;
 
     return _global != NULL;
 }
 
-void UnitHooks::setTimeout(int timeoutMilliSeconds)
+void UnitBase::setTimeout(int timeoutMilliSeconds)
 {
     assert(!TimeoutThread.isRunning());
     _timeoutMilliSeconds = timeoutMilliSeconds;
 }
 
-UnitHooks::UnitHooks()
+UnitBase::UnitBase()
     : _dlHandle(NULL),
+      _setRetValue(false),
+      _retValue(0),
       _timeoutMilliSeconds(30 * 1000),
       _timeoutShutdown(false)
 {
 }
 
-UnitHooks::~UnitHooks()
+UnitBase::~UnitBase()
 {
 // FIXME: we should really clean-up properly.
 //    if (_dlHandle)
@@ -85,7 +117,24 @@ UnitHooks::~UnitHooks()
     _dlHandle = NULL;
 }
 
-void UnitHooks::exitTest(TestResult result)
+UnitWSD::UnitWSD()
+    : _hasKitHooks(false)
+{
+}
+
+UnitWSD::~UnitWSD()
+{
+}
+
+UnitKit::UnitKit()
+{
+}
+
+UnitKit::~UnitKit()
+{
+}
+
+void UnitBase::exitTest(TestResult result)
 {
     _setRetValue = true;
     _retValue = result == TestResult::TEST_OK ?
@@ -94,12 +143,12 @@ void UnitHooks::exitTest(TestResult result)
     TerminationFlag = true;
 }
 
-void UnitHooks::timeout()
+void UnitBase::timeout()
 {
     exitTest(TestResult::TEST_TIMED_OUT);
 }
 
-void UnitHooks::returnValue(int &retValue)
+void UnitBase::returnValue(int &retValue)
 {
     if (_setRetValue)
         retValue = _retValue;
diff --git a/loolwsd/Unit.hpp b/loolwsd/Unit.hpp
index 0a16d34..7e11a33 100644
--- a/loolwsd/Unit.hpp
+++ b/loolwsd/Unit.hpp
@@ -12,55 +12,88 @@
 #include <string>
 #include <memory>
 #include <atomic>
+#include <assert.h>
 
-class UnitHooks;
+class UnitBase;
+class UnitWSD;
+class UnitKit;
 class UnitTimeout;
 class UnitHTTPServerRequest;
 class UnitHTTPServerResponse;
 
 class StorageBase;
 
-#define CREATE_UNIT_HOOKS_SYMBOL "unit_create"
-typedef UnitHooks *(CreateUnitHooksFunction)();
-extern "C" { UnitHooks *unit_create(void); }
+typedef UnitBase *(CreateUnitHooksFunction)();
+extern "C" { UnitBase *unit_create_wsd(void); }
+extern "C" { UnitBase *unit_create_kit(void); }
 
-/// Derive your unit test / hooks from me.
-class UnitHooks
+/// Derive your WSD unit test / hooks from me.
+class UnitBase
 {
     friend UnitTimeout;
+    friend UnitWSD;
+    friend UnitKit;
 
-    void *_dlHandle;
-    bool _setRetValue;
-    int  _retValue;
-    int  _timeoutMilliSeconds;
-    std::atomic<bool> _timeoutShutdown;
-    static UnitHooks *_global;
-
-    void setHandle(void *dlHandle) { _dlHandle = dlHandle; }
-    static UnitHooks *linkAndCreateUnit(const std::string &unitLibPath);
 protected:
-
     // ---------------- Helper API ----------------
-
     /// After this time we invoke 'timeout' default 30 seconds
     void setTimeout(int timeoutMilliSeconds);
 
+    /// If the test times out this gets invoked, the default just exits.
+    virtual void timeout();
+
     enum TestResult { TEST_FAILED, TEST_OK, TEST_TIMED_OUT };
-    /// Encourages loolwsd to exit with this value (unless hooked)
+
+    /// Encourages the process to exit with this value (unless hooked)
     void exitTest(TestResult result);
 
+             UnitBase();
+    virtual ~UnitBase();
+
+public:
+    enum UnitType { TYPE_WSD, TYPE_KIT };
+    /// Load unit test hook shared library from this path
+    static bool init(UnitType type, const std::string &unitLibPath);
+
+    /// Tweak the return value from the process.
+	virtual void returnValue(int & /* retValue */);
+
+private:
+    void setHandle(void *dlHandle) { _dlHandle = dlHandle; }
+    static UnitBase *linkAndCreateUnit(UnitType type, const std::string &unitLibPath);
+
+    void *_dlHandle;
+    bool _setRetValue;
+    int  _retValue;
+    int  _timeoutMilliSeconds;
+    std::atomic<bool> _timeoutShutdown;
+    static UnitBase *_global;
+    UnitType _type;
+};
+
+/// Derive your WSD unit test / hooks from me.
+class UnitWSD : public UnitBase
+{
+    bool _hasKitHooks;
+public:
+             UnitWSD();
+    virtual ~UnitWSD();
+
+	static UnitWSD &get()
+    {
+        assert (_global && _global->_type == UnitType::TYPE_WSD);
+        return *static_cast<UnitWSD *>(_global);
+    }
+
     enum TestRequest { TEST_REQ_CLIENT, TEST_REQ_PRISONER };
     /// Simulate an incoming request
     void testHandleRequest(TestRequest type,
                            UnitHTTPServerRequest& request,
                            UnitHTTPServerResponse& response);
-
-public:
-             UnitHooks();
-    virtual ~UnitHooks();
-	static UnitHooks &get() { return *_global; }
-    /// Load unit test hook shared library from this path
-    static bool init(const std::string &unitLibPath);
+    /// Do we have hooks for the Kit too
+    bool hasKitHooks() { return _hasKitHooks; }
+    /// set in your unit if you want to be injected into the kit too.
+    void setHasKitHooks(bool hasHooks) { _hasKitHooks = hasHooks; }
 
     // ---------------- Hooks ----------------
 
@@ -68,17 +101,27 @@ public:
     virtual void invokeTest() {}
     /// Tweak the count of pre-spawned kits.
 	virtual void preSpawnCount(int & /* numPrefork */) {}
-    /// Tweak the return value from LOOLWSD.
-	virtual void returnValue(int & /* retValue */);
     /// When a new child kit process reports
     virtual void newChild() {}
-    /// If the test times out this gets invoked, default exits.
-    virtual void timeout();
     /// Intercept createStorage
     virtual bool createStorage(const std::string& /* jailRoot */,
                                const std::string& /* jailPath */,
                                const Poco::URI& /* uri */,
-                               std::unique_ptr<StorageBase> & /*rStorage */) { return false; }
+                               std::unique_ptr<StorageBase> & /*rStorage */)
+        { return false; }
+};
+
+/// Derive your Kit unit test / hooks from me.
+class UnitKit : public UnitBase
+{
+public:
+             UnitKit();
+    virtual ~UnitKit();
+	static UnitKit &get()
+    {
+        assert (_global && _global->_type == UnitType::TYPE_KIT);
+        return *static_cast<UnitKit *>(_global);
+    }
 };
 
 #endif
diff --git a/loolwsd/test/UnitPrefork.cpp b/loolwsd/test/UnitPrefork.cpp
index 4133468..6094b0c 100644
--- a/loolwsd/test/UnitPrefork.cpp
+++ b/loolwsd/test/UnitPrefork.cpp
@@ -18,7 +18,7 @@
 #include <Poco/Timestamp.h>
 using Poco::Timestamp;
 
-class UnitPrefork : public UnitHooks
+class UnitPrefork : public UnitWSD
 {
     int _numStarted;
     const int _numToPrefork;
@@ -48,7 +48,7 @@ public:
     }
 };
 
-UnitHooks *unit_create(void)
+UnitBase *unit_create_wsd(void)
 {
     return new UnitPrefork();
 }
diff --git a/loolwsd/test/UnitStorage.cpp b/loolwsd/test/UnitStorage.cpp
index 91989f4..eba5f74 100644
--- a/loolwsd/test/UnitStorage.cpp
+++ b/loolwsd/test/UnitStorage.cpp
@@ -16,7 +16,7 @@
 #include "Unit.hpp"
 #include "UnitHTTP.hpp"
 
-class UnitStorage : public UnitHooks
+class UnitStorage : public UnitWSD
 {
 public:
     virtual bool createStorage(const std::string& /* jailRoot */,
@@ -33,12 +33,12 @@ public:
         exitTest(TestResult::TEST_OK);
         UnitHTTPServerResponse response;
         UnitHTTPServerRequest request(response, std::string(CHILD_URI));
-        UnitHooks::testHandleRequest(TestRequest::TEST_REQ_PRISONER,
-                                    request, response);
+        UnitWSD::testHandleRequest(TestRequest::TEST_REQ_PRISONER,
+                                   request, response);
     }
 };
 
-UnitHooks *unit_create(void)
+UnitBase *unit_create_wsd(void)
 {
     return new UnitStorage();
 }
diff --git a/loolwsd/test/UnitTimeout.cpp b/loolwsd/test/UnitTimeout.cpp
index 7c400b5..f29bf73 100644
--- a/loolwsd/test/UnitTimeout.cpp
+++ b/loolwsd/test/UnitTimeout.cpp
@@ -19,7 +19,7 @@
 #include <Poco/Util/Application.h>
 using Poco::Timestamp;
 
-class UnitTimeout : public UnitHooks
+class UnitTimeout : public UnitWSD
 {
     std::atomic<bool> _timedOut;
 public:
@@ -31,7 +31,7 @@ public:
     virtual void timeout() override
     {
         _timedOut = true;
-        UnitHooks::timeout();
+        UnitBase::timeout();
     }
 	virtual void returnValue(int & retValue) override
     {
@@ -48,10 +48,24 @@ public:
             retValue = Poco::Util::Application::EXIT_OK;
         }
     }
+
+    // sanity check the non-unit-test paths
+    static void testDefaultKits()
+    {
+        bool madeWSD = init(UnitType::TYPE_WSD, std::string());
+        assert(madeWSD);
+        delete UnitBase::_global;
+        UnitBase::_global = NULL;
+        bool madeKit = init(UnitType::TYPE_KIT, std::string());
+        assert(madeKit);
+        delete UnitBase::_global;
+        UnitBase::_global = NULL;
+    }
 };
 
-UnitHooks *unit_create(void)
+UnitBase *unit_create_wsd(void)
 {
+    UnitTimeout::testDefaultKits();
     return new UnitTimeout();
 }
 


More information about the Libreoffice-commits mailing list