/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. */ #pragma once #include #include #include #include #include #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 }; static const std::string testResultAsString(TestResult res) { switch (res) { case TestResult::Failed: return "Failed"; case TestResult::Ok: return "Ok"; case TestResult::TimedOut: return "TimedOut"; } assert(!"Unknown TestResult entry."); return std::to_string(static_cast(res)); } /// 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 > & /* 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& /*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; } static std::string getUnitLibPath() { return std::string(UnitLibPath); } private: void setHandle(void *dlHandle) { _dlHandle = dlHandle; } static UnitBase *linkAndCreateUnit(UnitType type, const std::string& unitLibPath); void *_dlHandle; static char *UnitLibPath; bool _setRetValue; int _retValue; int _timeoutMilliSeconds; 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(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& /* storage */) { return false; } /// Child sent a message virtual bool filterChildMessage(const std::vector& /* 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::shared_ptr> &tile); // ---------------- 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; } /// hook and allow through clipboard authentication virtual bool filterClipboardAuth(const std::string & /* serverId */, const std::string &/* tag */) { 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); #if !MOBILEAPP && !defined(KIT_IN_PROCESS) assert(Global->_type == UnitType::Kit); #endif return *static_cast(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(WebSocketHandler *, std::string &/* message */ ) { return false; } /// LOKit (and some synthetic internal) callbacks virtual bool filterLoKitCallback(const int /* type */, const std::string& /* payload */) { return false; } /// Allow a custom LibreOfficeKit wrapper virtual LibreOfficeKit *lok_init(const char * /* instdir */, const char * /* userdir */) { return nullptr; } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */