PROBLEMS | 8 - common/Unit.cpp | 4 test/Makefile.am | 8 + test/UnitTyping.cpp | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/helpers.hpp | 6 - wsd/ClientSession.cpp | 19 +-- wsd/ClientSession.hpp | 3 wsd/LOOLWSD.cpp | 11 ++ wsd/LOOLWSD.hpp | 3 wsd/TileCache.cpp | 1 wsd/TileDesc.hpp | 8 + 11 files changed, 289 insertions(+), 29 deletions(-)
New commits: commit e1f3a6a38872165ff99e130cde03e994445ef0bd Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Feb 13 18:33:06 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Wed Feb 13 18:35:32 2019 +0100 Tweak problemms. Change-Id: I35d82dffba9f0e58ea70c782ee8ce7fcf8f9b314 diff --git a/PROBLEMS b/PROBLEMS index f220b85ec..cfe2a01b7 100644 --- a/PROBLEMS +++ b/PROBLEMS @@ -35,11 +35,9 @@ poll() calls to be without timeout. Or something similar, depending on case. -- Recursive mutexes are evil. In general, I think the consensus is - that recursive mutexes should be avoided. One should use them only - when absolutely necessary because the code-base is so complex that - one has no idea how it works. That was hopefully not the case when - recursive mutexes were introduced here? But probably it is by now... +- Recursive mutexes are evil. The last remaining instances should be + removed from the Kit/ChildSession.cppp as/when we move to a single + threaded Kit process. - Occasionally Control-C (SIGINT) doesn't shut down loolwsd. One has to kill it with SIGKILL. Which of course leaves all the chroot jails diff --git a/wsd/TileCache.cpp b/wsd/TileCache.cpp index b46d16044..65b1c5a41 100644 --- a/wsd/TileCache.cpp +++ b/wsd/TileCache.cpp @@ -33,7 +33,6 @@ #include "ClientSession.hpp" #include <Common.hpp> #include <Protocol.hpp> -#include "SenderQueue.hpp" #include <Unit.hpp> #include <Util.hpp> #include <common/FileUtil.hpp> commit 92cf5707cfa1a0a3e43b89a394c335a97b7d3164 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Feb 13 18:24:09 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Wed Feb 13 18:24:36 2019 +0100 Add calc / typing unit test. Change-Id: Ib62ad6e1a720bdfce41ed5520d7396e83c8f5a91 diff --git a/test/Makefile.am b/test/Makefile.am index c43e14dd6..7af9b467b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,7 +13,7 @@ AM_CXXFLAGS = $(CPPUNIT_CFLAGS) -DTDOC=\"$(top_srcdir)/test/data\" \ -I${top_srcdir}/common -I${top_srcdir}/net -I${top_srcdir}/wsd -I${top_srcdir}/kit noinst_LTLIBRARIES = \ - unit-convert.la \ + unit-convert.la unit-typing.la \ unit-timeout.la unit-prefork.la \ unit-storage.la unit-client.la \ unit-admin.la unit-tilecache.la \ @@ -89,6 +89,8 @@ unit_admin_la_SOURCES = UnitAdmin.cpp unit_admin_la_LIBADD = $(CPPUNIT_LIBS) unit_client_la_SOURCES = UnitClient.cpp ${test_all_source} unit_client_la_LIBADD = $(CPPUNIT_LIBS) +unit_typing_la_SOURCES = UnitTyping.cpp +unit_typing_la_LIBADD = $(CPPUNIT_LIBS) unit_convert_la_SOURCES = UnitConvert.cpp unit_timeout_la_SOURCES = UnitTimeout.cpp unit_prefork_la_SOURCES = UnitPrefork.cpp @@ -120,8 +122,8 @@ check-local: ./run_unit.sh --log-file test.log --trs-file test.trs # FIXME 2: unit-oob.la fails with symbol undefined: # UnitWSD::testHandleRequest(UnitWSD::TestRequest, UnitHTTPServerRequest&, UnitHTTPServerResponse&) , -TESTS = unit-convert.la unit-prefork.la unit-tilecache.la unit-timeout.la \ - unit-oauth.la unit-wopi.la unit-wopi-saveas.la \ +TESTS = unit-typing.la unit-convert.la unit-prefork.la unit-tilecache.la \ + unit-timeout.la unit-oauth.la unit-wopi.la unit-wopi-saveas.la \ unit-wopi-ownertermination.la unit-wopi-versionrestore.la \ unit-wopi-documentconflict.la # TESTS = unit-client.la diff --git a/test/UnitTyping.cpp b/test/UnitTyping.cpp new file mode 100644 index 000000000..b66fdb15b --- /dev/null +++ b/test/UnitTyping.cpp @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +// Runs client tests in their own thread inside a WSD process. + +#include <config.h> + +#include <Exceptions.hpp> +#include <Log.hpp> +#include <Unit.hpp> +#include <UnitHTTP.hpp> +#include <helpers.hpp> +#include <LOOLWSD.hpp> + +#include <wsd/TileDesc.hpp> + +using namespace ::helpers; + +// Inside the WSD process +class UnitTyping : public UnitWSD +{ + bool _workerStarted; + std::thread _worker; + +public: + UnitTyping() : + _workerStarted(false) + { + int timeout_minutes = 5; + setTimeout(timeout_minutes * 60 * 1000); + } + ~UnitTyping() + { + LOG_INF("Joining test worker thread\n"); + _worker.join(); + } + + bool filterAlertAllusers(const std::string & msg) override + { + std::cout << "Alert: " << msg << "\n"; + return false; + } + + + TestResult testWriterTyping() + { +// const char* testname = "writerMultiViewEdit "; + return TestResult::Ok; + } + + TestResult testCalcTyping() + { + const char* testname = "calcMultiViewEdit "; + std::string serverURL = LOOLWSD::getServerURL(); + const Poco::URI uri(serverURL); + + // Load a doc with the cursor saved at a top row. + std::string documentPath, documentURL; + helpers::getDocumentPathAndURL("empty.ods", documentPath, documentURL, testname); + + const int numRender = 2; + const int numTyping = 6; + const int numSocket = numRender + numTyping; + std::vector<std::shared_ptr<LOOLWebSocket>> sockets; + + LOG_TRC("Connecting first client to " << serverURL << " doc: " << documentURL); + sockets.push_back(helpers::loadDocAndGetSocket(uri, documentURL, testname)); + + for (int i = 1; i < numSocket; ++i) + { + LOG_TRC("Connecting client " << i); + std::shared_ptr<LOOLWebSocket> socket = helpers::loadDocAndGetSocket(uri, documentURL, testname); + sockets.push_back(socket); + for (int j = 0; j < i * 3; ++j) + { + // cursor down some multiple of times + sendTextFrame(socket, "key type=input char=0 key=1024", testname); + sendTextFrame(socket, "key type=up char=0 key=1024", testname); + assertResponseString(socket, "celladdress:", testname); + } + } + + int count = 100 * numTyping; + std::vector<std::string> messages[numTyping]; + + // setup. + for (int i = 0; i < numTyping; ++i) + { + messages[i].push_back("clientvisiblearea x=0 y=0 width=27960 height=5160"); + messages[i].push_back("clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840"); + messages[i].push_back("commandvalues command=.uno:ViewRowColumnHeaders?x=-15&y=3870&width=0&height=5160"); + messages[i].push_back("useractive"); + } + + // randonly queue 'a', 'b' etc. key-press / space to each socket. + std::mt19937 randMt(0); + for (int i = 0; i < count; ++i) + { + int which = i % numTyping; + std::vector<std::string> &msgs = messages[which]; + int chr = 97 + which; + int key = 512 + which * 2; + + bool bSpace = !(randMt() & 0300); // send a space + + msgs.push_back("key type=input char=" + std::to_string(chr) + " key=0"); + msgs.push_back("key type=up char=0 key=" + std::to_string(key)); + if (bSpace) + { + msgs.push_back("key type=input char=32 key=0"); + msgs.push_back("key type=up char=0 key=1284"); + } + } + + int waitMS = 5; + std::vector<std::thread> threads; + std::atomic<bool> started(false); + std::atomic<int> liveTyping(0); + + // First some rendering load + for (int i = 0; i < numRender; ++i) + threads.emplace_back([&,i] { + std::mt19937 randDev(numRender * 257); + std::shared_ptr<LOOLWebSocket> sock = sockets[numTyping + i]; + while (!started || liveTyping > 0) + { + std::ostringstream oss; + std::uniform_int_distribution<int> distribution(0,32); + oss << "tilecombine part=0 width=512 height=512" + << " tileposx=" << 3840*distribution(randDev) + << " tileposy=" << 3840*distribution(randDev) + << " tilewidth=7680 tileheight=7680"; + sendTextFrame(sock, oss.str(), testname); + + std::vector<char> tile = getResponseMessage(sock, "tile:", testname, 5 /* ms */); + + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + } + }); + + // Add some typing + for (int which = 0; which < numTyping; ++which) + { + threads.emplace_back([&,which] { + std::mt19937 randDev(which * 16); + std::shared_ptr<LOOLWebSocket> sock = sockets[which]; + liveTyping++; + started = true; + for (size_t i = 0; i < messages[which].size(); ++i) + { + std::string msg = messages[which][i]; + + std::uint_fast32_t num = randDev(); + if (!(num & 0x30)) + sendTextFrame(sock, "ping", testname); + + // suck and dump replies down + std::vector<char> tile = getResponseMessage(sock, "tile:", testname, waitMS /* ms */); + if (tile.size()) + { +// 1544818858022 INCOMING: tile: part=0 width=256 height=256 tileposx=15360 tileposy=38400 tilewidth=3840 tileheight=3840 oldwid=0 wid=232 ver=913 imgsize=1002 +// Socket.js:123 1544818858027 OUTGOING: tileprocessed tile=0:15360:38400:3840:3840 + TileDesc desc = TileDesc::parse(LOOLProtocol::tokenize(tile.data(), tile.size())); + sendTextFrame(sock, "tileprocessed tile=" + desc.generateID(), testname); + } + + if (!(num & 0x300)) // occasionally sleep some more - why not. + std::this_thread::sleep_for(std::chrono::milliseconds(waitMS*25)); + LOG_TRC("Send to " << which << " message " << msg); +// std::cout << "Send to " << which << " message " << msg << "\n"; + sendTextFrame(sock, msg, testname); + } + liveTyping--; + }); + } + + for (auto& thread : threads) + { + thread.join(); + } + + // complete the cells with some 'enters' + std::string results[numTyping]; + for (int i = 0; i < numTyping; ++i) + { + sendTextFrame(sockets[i], "key type=input char=13 key=0", testname); + sendTextFrame(sockets[i], "key type=up char=0 key=1280", testname); + + // extract their text + sendTextFrame(sockets[i], "uno .uno:SelectAll", testname); + sendTextFrame(sockets[i], "gettextselection mimetype=text/plain;charset=utf-8", testname); + + LOG_TRC("Waiting for test selection:"); + std::string result = getResponseString(sockets[i], "textselectioncontent:", testname, 20000 /* 20 secs */); + results[i] = result; + + char target = 'a'+i; + LOG_TRC("Result [" << i << "] target " << target << " is '" << result << "'"); + for (size_t j = sizeof("textselectioncontent:"); j < result.size(); ++j) + { + if (result[j] != ' ' && result[j] != target) + { + LOG_TRC("Text contains incorrect char[" << j << "] = '" << result[j] << "' not " << target << " '" << result << "'"); + if (result[j] != target) + return TestResult::Failed; + } + } + } + + return TestResult::Ok; + } + + TestResult testTyping() + { + TestResult res; + res = testWriterTyping(); + if (res != TestResult::Ok) + return res; +// res = testCalcTyping(); + return res; + } + + void invokeTest() override + { + // this method gets called every few seconds. + if (_workerStarted) + return; + _workerStarted = true; + + _worker = std::thread([this]{ + exitTest (testTyping()); + }); + } +}; + +UnitBase *unit_create_wsd(void) +{ + return new UnitTyping(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit af31537a2a9eee7ce0ef727d3bba46963a66ed6a Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Feb 13 18:23:37 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Wed Feb 13 18:24:36 2019 +0100 Expose tile-id generation to unit tests. Change-Id: Ie56967c82192f3983ac13d53fd73346f25e6c840 diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index fcd449744..3a6bf59dd 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -1060,8 +1060,7 @@ void ClientSession::enqueueSendMessage(const std::shared_ptr<Message>& data) { // Avoid sending tile if it has the same wireID as the previously sent tile tile.reset(new TileDesc(TileDesc::parse(data->firstLine()))); - const std::string tileID = generateTileID(*tile); - auto iter = _oldWireIds.find(tileID); + auto iter = _oldWireIds.find(tile->generateID()); if(iter != _oldWireIds.end() && tile->getWireId() != 0 && tile->getWireId() == iter->second) { LOG_INF("WSD filters out a tile with the same wireID: " << tile->serialize("tile:")); @@ -1110,7 +1109,7 @@ Authorization ClientSession::getAuthorization() const void ClientSession::addTileOnFly(const TileDesc& tile) { - _tilesOnFly.push_back({generateTileID(tile), std::chrono::steady_clock::now()}); + _tilesOnFly.push_back({tile.generateID(), std::chrono::steady_clock::now()}); } void ClientSession::clearTilesOnFly() @@ -1139,7 +1138,7 @@ void ClientSession::removeOutdatedTilesOnFly() size_t ClientSession::countIdenticalTilesOnFly(const TileDesc& tile) const { size_t count = 0; - std::string tileID = generateTileID(tile); + std::string tileID = tile.generateID(); for(auto& tileItem : _tilesOnFly) { if(tileItem.first == tileID) @@ -1283,7 +1282,7 @@ void ClientSession::handleTileInvalidation(const std::string& message, invalidTiles.emplace_back(part, _tileWidthPixel, _tileHeightPixel, j * _tileWidthTwips, i * _tileHeightTwips, _tileWidthTwips, _tileHeightTwips, -1, 0, -1, false); TileWireId oldWireId = 0; - auto iter = _oldWireIds.find(generateTileID(invalidTiles.back())); + auto iter = _oldWireIds.find(invalidTiles.back().generateID()); if(iter != _oldWireIds.end()) oldWireId = iter->second; @@ -1308,7 +1307,7 @@ void ClientSession::resetWireIdMap() void ClientSession::traceTileBySend(const TileDesc& tile, bool deduplicated) { - const std::string tileID = generateTileID(tile); + const std::string tileID = tile.generateID(); // Store wireId first auto iter = _oldWireIds.find(tileID); @@ -1367,12 +1366,4 @@ void ClientSession::clearTileSubscription() _tilesBeingRendered.clear(); } -std::string ClientSession::generateTileID(const TileDesc& tile) const -{ - std::ostringstream tileID; - tileID << tile.getPart() << ":" << tile.getTilePosX() << ":" << tile.getTilePosY() << ":" - << tile.getTileWidth() << ":" << tile.getTileHeight(); - return tileID.str(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp index b701e5568..948e1b202 100644 --- a/wsd/ClientSession.hpp +++ b/wsd/ClientSession.hpp @@ -170,9 +170,6 @@ private: void handleTileInvalidation(const std::string& message, const std::shared_ptr<DocumentBroker>& docBroker); - /// Generate a unique id for a tile - std::string generateTileID(const TileDesc& tile) const; - private: std::weak_ptr<DocumentBroker> _docBroker; diff --git a/wsd/TileDesc.hpp b/wsd/TileDesc.hpp index fa945df14..3a68040c8 100644 --- a/wsd/TileDesc.hpp +++ b/wsd/TileDesc.hpp @@ -225,6 +225,14 @@ public: return parse(LOOLProtocol::tokenize(message.data(), message.size())); } + std::string generateID() const + { + std::ostringstream tileID; + tileID << getPart() << ":" << getTilePosX() << ":" << getTilePosY() << ":" + << getTileWidth() << ":" << getTileHeight(); + return tileID.str(); + } + private: int _part; int _width; commit f98a7f05925da20a6a499a1d089a41678c017e17 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Feb 13 18:01:08 2019 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Wed Feb 13 18:24:36 2019 +0100 Improve unit test / SSL handling & detection. Change-Id: I6bd3116ac94d3d2c61e2ec543cb17896834ef2df diff --git a/common/Unit.cpp b/common/Unit.cpp index ae1c363a6..28dba3488 100644 --- a/common/Unit.cpp +++ b/common/Unit.cpp @@ -151,6 +151,8 @@ UnitWSD::~UnitWSD() { } +static bool isSSL = false; + void UnitWSD::configure(Poco::Util::LayeredConfiguration &config) { if (isUnitTesting()) @@ -163,6 +165,8 @@ void UnitWSD::configure(Poco::Util::LayeredConfiguration &config) config.setBool("logging.file[@enable]", false); } // else - a product run. + + isSSL = config.getBool("ssl.enable", true) && !config.getBool("ssl.termination", false); } void UnitWSD::lookupTile(int part, int width, int height, int tilePosX, int tilePosY, diff --git a/test/helpers.hpp b/test/helpers.hpp index 13b351762..bc4818d98 100644 --- a/test/helpers.hpp +++ b/test/helpers.hpp @@ -160,10 +160,10 @@ inline Poco::Net::HTTPClientSession* createSession(const Poco::URI& uri) { #if ENABLE_SSL - return new Poco::Net::HTTPSClientSession(uri.getHost(), uri.getPort()); -#else - return new Poco::Net::HTTPClientSession(uri.getHost(), uri.getPort()); + if (uri.getScheme() == "https") + return new Poco::Net::HTTPSClientSession(uri.getHost(), uri.getPort()); #endif + return new Poco::Net::HTTPClientSession(uri.getHost(), uri.getPort()); } inline diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index ba1d3f134..fccb86ef9 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -3063,6 +3063,17 @@ private: static LOOLWSDServer srv; +std::string LOOLWSD::getServerURL() +{ + std::ostringstream oss; + + oss << getLaunchBase(""); + oss << LOOLWSD::ServiceRoot; + oss << LOOLWSD_TEST_LOLEAFLET_UI; + + return oss.str(); +} + int LOOLWSD::innerMain() { #if !defined FUZZER && !MOBILEAPP diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp index a0a43910e..9303f789a 100644 --- a/wsd/LOOLWSD.hpp +++ b/wsd/LOOLWSD.hpp @@ -157,6 +157,9 @@ public: return AnonymizeUsernames ? Util::anonymize(username) : username; } + /// get correct server URL with protocol + port number for this running server + static std::string getServerURL(); + int innerMain(); protected: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits