collabora-online/test/UnitSyntheticLok.cpp

252 lines
7.3 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* Copyright the Collabora Online contributors.
*
* SPDX-License-Identifier: MPL-2.0
*
* 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/.
*/
#include <config.h>
#include <Unit.hpp>
#include <Util.hpp>
#include <helpers.hpp>
#include <StringVector.hpp>
#include <WebSocketSession.hpp>
#include <test/testlog.hpp>
#include <test/lokassert.hpp>
#include <LibreOfficeKit/LibreOfficeKit.hxx>
#include <string>
#include <thread>
namespace {
void *memdup(const void *ptr, size_t size)
{
auto p = malloc(size);
memcpy(p, ptr, size);
return p;
}
}
/// Save torture testcase.
class UnitSyntheticLok : public UnitWSD
{
void loadAndSynthesize(const std::string& name, const std::string& docName);
public:
UnitSyntheticLok();
void invokeWSDTest() override;
};
void UnitSyntheticLok::loadAndSynthesize(
const std::string& name, const std::string& docName)
{
auto timeout = std::chrono::seconds(10);
std::string documentPath, documentURL;
helpers::getDocumentPathAndURL(docName, documentPath, documentURL, name);
TST_LOG("Starting test on " << documentURL << ' ' << documentPath);
std::shared_ptr<SocketPoll> poll = std::make_shared<SocketPoll>("WebSocketPoll");
poll->startThread();
Poco::URI uri(helpers::getTestServerURI());
auto wsSession = helpers::loadDocAndGetSession(poll, docName, uri, testname);
std::vector<char> message
= wsSession->waitForMessage("status:", timeout, name);
const std::string status = COOLProtocol::getFirstLine(message);
// Kit will signal success through unitresult: to wsd in its own time.
}
UnitSyntheticLok::UnitSyntheticLok()
: UnitWSD("UnitSyntheticLok")
{
setHasKitHooks();
// Double of the default.
constexpr std::chrono::minutes timeout_minutes(1);
setTimeout(timeout_minutes);
}
void UnitSyntheticLok::invokeWSDTest()
{
const auto name = "syntheticLok";
static bool started = false;
if (!started)
{
started = true;
loadAndSynthesize(name, "empty.ods");
}
// wait for result from the Kit process
}
class UnitKitSyntheticLok;
UnitKitSyntheticLok *GlobalUnitKit;
// Inside the forkit & kit processes
class UnitKitSyntheticLok : public UnitKit
{
public:
LibreOfficeKit *_kit;
// Original and overridden vtables
LibreOfficeKitClass *_kitClass;
LibreOfficeKitClass *_kitClassClean;
// Original and overridden vtables
LibreOfficeKitDocumentClass *_docClass;
LibreOfficeKitDocumentClass *_docClassClean;
// Polling replacement
LibreOfficeKitPollCallback _pollCallback;
LibreOfficeKitWakeCallback _wakeCallback;
void* _pollData;
LibreOfficeKitCallback _docCallback;
void *_docCallbackData;
bool isDocumentCreated() const { return _docCallback != nullptr; }
UnitKitSyntheticLok()
: UnitKit("SyntheticLok")
, _kit(nullptr)
, _kitClass(nullptr)
, _kitClassClean(nullptr)
, _docClass(nullptr)
, _docClassClean(nullptr)
, _pollCallback(nullptr)
, _wakeCallback(nullptr)
, _pollData(nullptr)
, _docCallback(nullptr)
, _docCallbackData(nullptr)
{
TST_LOG("SyntheticLOK kit bootstrap\n");
setTimeout(std::chrono::hours(1));
GlobalUnitKit = this;
}
virtual LibreOfficeKit *lok_init(
const char *instdir, const char *userdir,
LokHookFunction2 fn) override;
void postLOKDocumentEvent(int nType, const char* pPayload)
{
assert(_docCallback);
_docCallback(nType, pPayload, _docCallbackData);
}
bool prePollCallback(int /* timeoutUs */)
{
return true;
}
virtual void doTest()
{
if (isDocumentCreated())
{
TST_LOG("Send test event");
postLOKDocumentEvent(LOK_CALLBACK_CELL_CURSOR, "EMPTY");
exitTest(TestResult::Ok);
}
}
};
extern "C" {
int syn_pollCallback(void* /* pData */, int timeoutUs)
{
assert(GlobalUnitKit);
bool finished = UnitKit::get().isFinished();
if (!finished && timeoutUs > 1000) // post initial setup we hope
GlobalUnitKit->doTest();
if (GlobalUnitKit->prePollCallback(timeoutUs))
return GlobalUnitKit->_pollCallback(GlobalUnitKit->_pollData, timeoutUs);
return 0;
}
void syn_wakeCallback(void* /* pData */)
{
assert(GlobalUnitKit);
GlobalUnitKit->_wakeCallback(GlobalUnitKit->_pollData);
}
void syn_registerCallback (LibreOfficeKitDocument* pThis,
LibreOfficeKitCallback pCallback,
void* pData)
{
assert(GlobalUnitKit);
GlobalUnitKit->_docCallback = pCallback;
GlobalUnitKit->_docCallbackData = pData;
GlobalUnitKit->_docClassClean->registerCallback(pThis, pCallback, pData);
}
LibreOfficeKitDocument* syn_documentLoadWithOptions (LibreOfficeKit* pThis,
const char* pURL,
const char* pOptions)
{
assert(GlobalUnitKit);
// chain to parent
LibreOfficeKitDocument *doc = GlobalUnitKit->_kitClassClean->documentLoadWithOptions(pThis, pURL, pOptions);
GlobalUnitKit->_docClass = reinterpret_cast<LibreOfficeKitDocumentClass *>(memdup(doc->pClass, doc->pClass->nSize));
GlobalUnitKit->_docClassClean = reinterpret_cast<LibreOfficeKitDocumentClass *>(memdup(doc->pClass, doc->pClass->nSize));
doc->pClass = GlobalUnitKit->_docClass;
GlobalUnitKit->_docClass->registerCallback = syn_registerCallback;
return doc;
}
void syn_runLoop (LibreOfficeKit* pThis,
LibreOfficeKitPollCallback pPollCallback,
LibreOfficeKitWakeCallback pWakeCallback,
void* pData)
{
assert(GlobalUnitKit);
GlobalUnitKit->_pollCallback = pPollCallback;
GlobalUnitKit->_wakeCallback = pWakeCallback;
GlobalUnitKit->_pollData = pData;
GlobalUnitKit->_kitClassClean->runLoop(pThis, syn_pollCallback, syn_wakeCallback, pData);
}
};
LibreOfficeKit *UnitKitSyntheticLok::lok_init(const char *instdir,
const char *userdir,
LokHookFunction2 fn)
{
// Let the parent have a go
_kit = fn(instdir, userdir);
if (!_kit || !_kit->pClass)
LOK_ASSERT_FAIL("Failed to get kit initialized");
_kitClass = reinterpret_cast<LibreOfficeKitClass *>(memdup(_kit->pClass, _kit->pClass->nSize));
_kitClassClean = reinterpret_cast<LibreOfficeKitClass *>(memdup(_kit->pClass, _kit->pClass->nSize));
// switch to our vtable
_kit->pClass = _kitClass;
_kitClass->runLoop = syn_runLoop;
_kitClass->documentLoadWithOptions = syn_documentLoadWithOptions;
return _kit;
}
UnitBase* unit_create_wsd(void) { return new UnitSyntheticLok(); }
UnitBase *unit_create_kit(void) { return new UnitKitSyntheticLok(); }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */