95eb849217
Re-think the plumbing between the different parts of the C++ Online code. Do try to have it work more like in real Online on all but the lowest socket level. Except that we don't have multiple processes, but threads inside the same process. And instead of using actual system sockets for WebSocket traffic between the threads, we use our own FakeSocket things, with no WebSocket framing of messages. Reduce the amount of #ifdef MOBILEAPP a bit also by compiling in the UnitFoo things. Hardcode that so that no unit testing is ever attempted, though. We don't try to dlopen any library. Corresponding changes in the app Objective-C code. Plus fixes and functionality improvements. Now it gets so far that the JavaScript code thinks it has the document tiles presented, and doesn't crash. But it hangs occasionally. And all tiles show up blank. Anyway, progress. Change-Id: I769497c9a46ddb74984bc7af36d132b7b43895d4
294 lines
8.6 KiB
C++
294 lines
8.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
#ifndef INCLUDED_UNIT_HPP
|
|
#define INCLUDED_UNIT_HPP
|
|
|
|
#include <atomic>
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include <LOOLWebSocket.hpp>
|
|
#include "net/Socket.hpp"
|
|
|
|
class UnitBase;
|
|
class UnitWSD;
|
|
class UnitKit;
|
|
class UnitTimeout;
|
|
class UnitHTTPServerRequest;
|
|
class UnitHTTPServerResponse;
|
|
|
|
class WebSocketHandler;
|
|
|
|
// Forward declaration to avoid pulling the world here.
|
|
namespace Poco
|
|
{
|
|
class MemoryInputStream;
|
|
|
|
namespace Net
|
|
{
|
|
class HTTPServerRequest;
|
|
class HTTPServerResponse;
|
|
}
|
|
|
|
namespace Util
|
|
{
|
|
class LayeredConfiguration;
|
|
}
|
|
}
|
|
|
|
class Session;
|
|
class StorageBase;
|
|
|
|
typedef UnitBase *(CreateUnitHooksFunction)();
|
|
extern "C" { UnitBase *unit_create_wsd(void); }
|
|
extern "C" { UnitBase *unit_create_kit(void); }
|
|
extern "C" { typedef struct _LibreOfficeKit LibreOfficeKit; }
|
|
|
|
/// Derive your WSD unit test / hooks from me.
|
|
class UnitBase
|
|
{
|
|
friend UnitTimeout;
|
|
friend UnitWSD;
|
|
friend UnitKit;
|
|
|
|
protected:
|
|
// ---------------- Helper API ----------------
|
|
/// After this time we invoke 'timeout' default 30 seconds
|
|
void setTimeout(int timeoutMilliSeconds);
|
|
|
|
enum class TestResult
|
|
{
|
|
Failed,
|
|
Ok,
|
|
TimedOut
|
|
};
|
|
|
|
/// Encourages the process to exit with this value (unless hooked)
|
|
void exitTest(TestResult result);
|
|
|
|
UnitBase();
|
|
virtual ~UnitBase();
|
|
|
|
public:
|
|
enum class UnitType
|
|
{
|
|
Wsd,
|
|
Kit
|
|
};
|
|
/// Load unit test hook shared library from this path
|
|
static bool init(UnitType type, const std::string& unitLibPath);
|
|
|
|
/// Do we have a unit test library hooking things & loaded
|
|
static bool isUnitTesting();
|
|
|
|
/// Tweak the return value from the process.
|
|
virtual void returnValue(int& /* retValue */);
|
|
|
|
/// Input message either for WSD or Kit
|
|
virtual bool filterSessionInput(Session *, const char */* buffer */,
|
|
int /* length */,
|
|
std::unique_ptr< std::vector<char> > & /* replace */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Message that is about to be sent via the websocket.
|
|
virtual bool filterSendMessage(const char* /* data */, const size_t /* len */, const WSOpCode /* code */, const bool /* flush */, int& /*unitReturn*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Hook the disk space check
|
|
virtual bool filterCheckDiskSpace(const std::string & /* path */,
|
|
bool & /* newResult */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Trap and filter alerting all users
|
|
virtual bool filterAlertAllusers(const std::string & /* msg */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Custom response to a http request.
|
|
virtual bool handleHttpRequest(const Poco::Net::HTTPRequest& /*request*/, Poco::MemoryInputStream& /*message*/,std::shared_ptr<StreamSocket>& /*socket*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// If the test times out this gets invoked, the default just exits.
|
|
virtual void timeout();
|
|
|
|
int getTimeoutMilliSeconds() const
|
|
{
|
|
return _timeoutMilliSeconds;
|
|
}
|
|
|
|
static UnitBase& get()
|
|
{
|
|
assert(Global);
|
|
return *Global;
|
|
}
|
|
|
|
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::Wsd);
|
|
return *static_cast<UnitWSD *>(Global);
|
|
}
|
|
|
|
enum class TestRequest
|
|
{
|
|
Client,
|
|
Prisoner
|
|
};
|
|
/// Simulate an incoming request
|
|
static void testHandleRequest(TestRequest type,
|
|
UnitHTTPServerRequest& request,
|
|
UnitHTTPServerResponse& response);
|
|
/// 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() { _hasKitHooks = true; }
|
|
|
|
// ---------------- WSD hooks ----------------
|
|
|
|
/// Manipulate and modify the configuration before any usage.
|
|
virtual void configure(Poco::Util::LayeredConfiguration& /* config */);
|
|
/// Main-loop reached, time for testing
|
|
virtual void invokeTest() {}
|
|
/// When a new child kit process reports
|
|
virtual void newChild(WebSocketHandler &/* socket */) {}
|
|
/// Intercept createStorage
|
|
virtual bool createStorage(const Poco::URI& /* uri */,
|
|
const std::string& /* jailRoot */,
|
|
const std::string& /* jailPath */,
|
|
std::unique_ptr<StorageBase>& /* storage */)
|
|
{
|
|
return false;
|
|
}
|
|
/// Intercept incoming requests, so unit tests can silently communicate
|
|
virtual bool filterHandleRequest(
|
|
TestRequest /* type */,
|
|
SocketDisposition & /* disposition */,
|
|
WebSocketHandler & /* handler */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Child sent a message
|
|
virtual bool filterChildMessage(const std::vector<char>& /* payload */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// ---------------- TileCache hooks ----------------
|
|
/// Called before the lookupTile call returns. Should always be called to fire events.
|
|
virtual void lookupTile(int part, int width, int height, int tilePosX, int tilePosY,
|
|
int tileWidth, int tileHeight, std::unique_ptr<std::fstream>& cacheFile);
|
|
|
|
// ---------------- DocumentBroker hooks ----------------
|
|
virtual bool filterLoad(const std::string& /* sessionId */,
|
|
const std::string& /* jailId */,
|
|
bool& /* result */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// To force the save operation being handled as auto-save from a unit test.
|
|
virtual bool isAutosave()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// ---------------- WSD events ----------------
|
|
virtual void onChildConnected(const int /* pid */, const std::string& /* sessionId */) {}
|
|
/// When admin notify message is sent
|
|
virtual void onAdminNotifyMessage(const std::string& /* message */) {}
|
|
/// When admin message is sent in response to a query
|
|
virtual void onAdminQueryMessage(const std::string& /* message */) {}
|
|
|
|
// ---------------- TileCache events ----------------
|
|
virtual void onTileCacheHit(int /*part*/, int /*width*/, int /*height*/,
|
|
int /*tilePosX*/, int /*tilePosY*/,
|
|
int /*tileWidth*/, int /*tileHeight*/) {}
|
|
virtual void onTileCacheMiss(int /*part*/, int /*width*/, int /*height*/,
|
|
int /*tilePosX*/, int /*tilePosY*/,
|
|
int /*tileWidth*/, int /*tileHeight*/) {}
|
|
virtual void onTileCacheSubscribe(int /*part*/, int /*width*/, int /*height*/,
|
|
int /*tilePosX*/, int /*tilePosY*/,
|
|
int /*tileWidth*/, int /*tileHeight*/) {}
|
|
};
|
|
|
|
/// Derive your Kit unit test / hooks from me.
|
|
class UnitKit : public UnitBase
|
|
{
|
|
public:
|
|
UnitKit();
|
|
virtual ~UnitKit();
|
|
static UnitKit& get()
|
|
{
|
|
assert(Global && Global->_type == UnitType::Kit);
|
|
return *static_cast<UnitKit *>(Global);
|
|
}
|
|
|
|
// ---------------- ForKit hooks ----------------
|
|
|
|
/// main-loop reached, time for testing
|
|
virtual void invokeForKitTest() {}
|
|
|
|
/// Post fork hook - just after we fork to init the child kit
|
|
virtual void launchedKit(int /* pid */) {}
|
|
|
|
// ---------------- Kit hooks ----------------
|
|
|
|
/// Post fork hook - just before we init the child kit
|
|
virtual void postFork() {}
|
|
|
|
/// Kit got a message
|
|
virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket>& /* ws */,
|
|
std::string& /* message */)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// Allow a custom LibreOfficeKit wrapper
|
|
virtual LibreOfficeKit *lok_init(const char * /* instdir */,
|
|
const char * /* userdir */)
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|