[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