loolwsd/TileCache.cpp | 19 +- loolwsd/test/TileCacheTests.cpp | 340 ++++++++++++++++++++++++++++++++++++++-- loolwsd/test/httpwstest.cpp | 291 ---------------------------------- 3 files changed, 340 insertions(+), 310 deletions(-)
New commits: commit 25a8b71dbb4bab5fb211905a733d3543a61667b8 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Tue May 3 23:31:12 2016 -0400 loolwsd: hoist invariant message out of loop Change-Id: I9319518a4bbba9c24ba5c0132d89ad6a793247e8 Reviewed-on: https://gerrit.libreoffice.org/24643 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp index edd88a7..3d71105 100644 --- a/loolwsd/TileCache.cpp +++ b/loolwsd/TileCache.cpp @@ -338,7 +338,15 @@ void TileCache::notifyAndRemoveSubscribers(int part, int width, int height, int if (!tileBeingRendered) return; - Log::debug("Sending tile message also to subscribers"); + const std::string message("tile " + " part=" + std::to_string(part) + + " width=" + std::to_string(width) + + " height=" + std::to_string(height) + + " tileposx=" + std::to_string(tilePosX) + + " tileposy=" + std::to_string(tilePosY) + + " tilewidth=" + std::to_string(tileWidth) + + " tileheight=" + std::to_string(tileHeight)); + Log::debug("Sending tile message to subscribers: " + message); for (const auto& i: tileBeingRendered->_subscribers) { @@ -353,15 +361,6 @@ void TileCache::notifyAndRemoveSubscribers(int part, int width, int height, int // mandatory parts of the message. if (queue) { - const std::string message("tile " - " part=" + std::to_string(part) + - " width=" + std::to_string(width) + - " height=" + std::to_string(height) + - " tileposx=" + std::to_string(tilePosX) + - " tileposy=" + std::to_string(tilePosY) + - " tilewidth=" + std::to_string(tileWidth) + - " tileheight=" + std::to_string(tileHeight) + - "\n"); queue->put(message); } } commit cdb5f9c2da6b918e04d1156958eb281285f1faec Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Tue May 3 19:28:39 2016 -0400 loolwsd: moved tile tests to TileCacheTests.cpp Change-Id: I6bc681772104615b79bbe3a21ccaead01abde4dd Reviewed-on: https://gerrit.libreoffice.org/24642 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/test/TileCacheTests.cpp b/loolwsd/test/TileCacheTests.cpp index 8667efb..a20c82f 100644 --- a/loolwsd/test/TileCacheTests.cpp +++ b/loolwsd/test/TileCacheTests.cpp @@ -9,22 +9,51 @@ #include "config.h" +#include <Poco/Net/WebSocket.h> #include <cppunit/extensions/HelperMacros.h> #include <TileCache.hpp> -#include "Unit.hpp" -#include "Util.hpp" + +#include <Common.hpp> +#include <Unit.hpp> +#include <Util.hpp> +#include <LOOLProtocol.hpp> +#include "helpers.hpp" + +using namespace helpers; /// TileCache unit-tests. class TileCacheTests : public CPPUNIT_NS::TestFixture { + const Poco::URI _uri; + Poco::Net::HTTPResponse _response; + CPPUNIT_TEST_SUITE(TileCacheTests); - CPPUNIT_TEST(test); + CPPUNIT_TEST(testSimple); + CPPUNIT_TEST(testClientPartImpress); + CPPUNIT_TEST(testClientPartCalc); +#if ENABLE_DEBUG + CPPUNIT_TEST(testSimultaneousTilesRenderedJustOnce); +#endif CPPUNIT_TEST_SUITE_END(); - void test(); + void testSimple(); + void testClientPartImpress(); + void testClientPartCalc(); + void testSimultaneousTilesRenderedJustOnce(); + + void checkTiles(Poco::Net::WebSocket& socket, + const std::string& type); + + void requestTiles(Poco::Net::WebSocket& socket, + const int part, + const int docWidth, + const int docHeight); + + void getTileMessage(Poco::Net::WebSocket& ws, + std::string& tile); static std::vector<char> genRandomData(const size_t size) @@ -57,16 +86,37 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture public: TileCacheTests() +#if ENABLE_SSL + : _uri("https://127.0.0.1:" + std::to_string(DEFAULT_CLIENT_PORT_NUMBER)) +#else + : _uri("http://127.0.0.1:" + std::to_string(DEFAULT_CLIENT_PORT_NUMBER)) +#endif { - if (!UnitWSD::init(UnitWSD::UnitType::TYPE_WSD, "")) - { - throw std::runtime_error("Failed to load wsd unit test library."); - } +#if ENABLE_SSL + Poco::Net::initializeSSL(); + // Just accept the certificate anyway for testing purposes + Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> invalidCertHandler = new Poco::Net::AcceptCertificateHandler(false); + Poco::Net::Context::Params sslParams; + Poco::Net::Context::Ptr sslContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, sslParams); + Poco::Net::SSLManager::instance().initializeClient(0, invalidCertHandler, sslContext); +#endif + } + +#if ENABLE_SSL + ~TileCacheTests() + { + Poco::Net::uninitializeSSL(); } +#endif }; -void TileCacheTests::test() +void TileCacheTests::testSimple() { + if (!UnitWSD::init(UnitWSD::UnitType::TYPE_WSD, "")) + { + throw std::runtime_error("Failed to load wsd unit test library."); + } + // Create TileCache and pretend the file was modified as recently as // now, so it discards the cached data. TileCache tc("doc.ods", Poco::Timestamp(), "/tmp/tile_cache_tests"); @@ -102,6 +152,278 @@ void TileCacheTests::test() CPPUNIT_ASSERT_MESSAGE("found tile when none was expected", !file); } +void TileCacheTests::testClientPartImpress() +{ + try + { + // Load a document + std::string documentPath, documentURL; + getDocumentPathAndURL("setclientpart.odp", documentPath, documentURL); + + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); + Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response); + + sendTextFrame(socket, "load url=" + documentURL); + CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket)); + + checkTiles(socket, "presentation"); + + socket.shutdown(); + Util::removeFile(documentPath); + } + catch (const Poco::Exception& exc) + { + CPPUNIT_FAIL(exc.displayText()); + } +} + +void TileCacheTests::testClientPartCalc() +{ + try + { + // Load a document + std::string documentPath, documentURL; + getDocumentPathAndURL("setclientpart.ods", documentPath, documentURL); + + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); + Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response); + + sendTextFrame(socket, "load url=" + documentURL); + CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket)); + + checkTiles(socket, "spreadsheet"); + + socket.shutdown(); + Util::removeFile(documentPath); + } + catch (const Poco::Exception& exc) + { + CPPUNIT_FAIL(exc.displayText()); + } +} + +void TileCacheTests::testSimultaneousTilesRenderedJustOnce() +{ + std::string documentPath, documentURL; + getDocumentPathAndURL("hello.odt", documentPath, documentURL); + + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); + Poco::Net::WebSocket socket1 = *connectLOKit(_uri, request, _response); + sendTextFrame(socket1, "load url=" + documentURL); + + Poco::Net::WebSocket socket2 = *connectLOKit(_uri, request, _response); + sendTextFrame(socket2, "load url=" + documentURL); + + sendTextFrame(socket1, "tile part=42 width=400 height=400 tileposx=1000 tileposy=2000 tilewidth=3000 tileheight=3000"); + sendTextFrame(socket2, "tile part=42 width=400 height=400 tileposx=1000 tileposy=2000 tilewidth=3000 tileheight=3000"); + + std::string response1; + getResponseMessage(socket1, "tile:", response1, true); + CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !response1.empty()); + + std::string response2; + getResponseMessage(socket2, "tile:", response2, true); + CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !response2.empty()); + + if (!response1.empty() && !response2.empty()) + { + Poco::StringTokenizer tokens1(response1, " "); + std::string renderId1; + LOOLProtocol::getTokenString(tokens1, "renderid", renderId1); + Poco::StringTokenizer tokens2(response2, " "); + std::string renderId2; + LOOLProtocol::getTokenString(tokens2, "renderid", renderId2); + + CPPUNIT_ASSERT(renderId1 == renderId2 || + (renderId1 == "cached" && renderId2 != "cached") || + (renderId1 != "cached" && renderId2 == "cached")); + } + + socket1.shutdown(); + socket2.shutdown(); +} + +void TileCacheTests::checkTiles(Poco::Net::WebSocket& socket, const std::string& docType) +{ + const std::string current = "current="; + const std::string height = "height="; + const std::string parts = "parts="; + const std::string type = "type="; + const std::string width = "width="; + + int currentPart = -1; + int totalParts = 0; + int docHeight = 0; + int docWidth = 0; + + std::string response; + std::string text; + + // check total slides 10 + getResponseMessage(socket, "status:", response, false); + CPPUNIT_ASSERT_MESSAGE("did not receive a status: message as expected", !response.empty()); + { + std::cout << "status: " << response << std::endl; + Poco::StringTokenizer tokens(response, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), tokens.count()); + + // Expected format is something like 'type= parts= current= width= height='. + text = tokens[0].substr(type.size()); + totalParts = std::stoi(tokens[1].substr(parts.size())); + currentPart = std::stoi(tokens[2].substr(current.size())); + docWidth = std::stoi(tokens[3].substr(width.size())); + docHeight = std::stoi(tokens[4].substr(height.size())); + CPPUNIT_ASSERT_EQUAL(docType, text); + CPPUNIT_ASSERT_EQUAL(10, totalParts); + CPPUNIT_ASSERT(currentPart > -1); + CPPUNIT_ASSERT(docWidth > 0); + CPPUNIT_ASSERT(docHeight > 0); + } + + if (docType == "presentation") + { + // first full invalidation + getResponseMessage(socket, "invalidatetiles:", response, true); + CPPUNIT_ASSERT_MESSAGE("did not receive a invalidatetiles: message as expected", !response.empty()); + { + Poco::StringTokenizer tokens(response, ":", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + CPPUNIT_ASSERT_EQUAL(std::string("EMPTY"), tokens[0]); + } + + // request tiles + requestTiles(socket, currentPart, docWidth, docHeight); + } + + // random setclientpart + std::srand(std::time(0)); + std::vector<int> vParts = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::random_shuffle (vParts.begin(), vParts.end()); + for (auto it : vParts) + { + if (currentPart != it) + { + // change part + text = Poco::format("setclientpart part=%d", it); + std::cout << text << std::endl; + sendTextFrame(socket, text); + + // get full invalidation + getResponseMessage(socket, "invalidatetiles:", response, true); + CPPUNIT_ASSERT_MESSAGE("did not receive a invalidatetiles: message as expected", !response.empty()); + { + Poco::StringTokenizer tokens(response, ":", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + CPPUNIT_ASSERT_EQUAL(std::string("EMPTY"), tokens[0]); + } + requestTiles(socket, it, docWidth, docHeight); + } + currentPart = it; + } +} + +void TileCacheTests::requestTiles(Poco::Net::WebSocket& socket, const int part, const int docWidth, const int docHeight) +{ + // twips + const int tileSize = 3840; + // pixel + const int pixTileSize = 256; + + int rows; + int cols; + int tileX; + int tileY; + int tileWidth; + int tileHeight; + + std::string text; + std::string tile; + + rows = docHeight / tileSize; + cols = docWidth / tileSize; + + // Note: this code tests tile requests in the wrong way. + + // This code does NOT match what was the idea how the LOOL protocol should/could be used. The + // intent was never that the protocol would need to be, or should be, used in a strict + // request/reply fashion. If a client needs n tiles, it should just send the requests, one after + // another. There is no need to do n roundtrips. A client should all the time be reading + // incoming messages, and handle incoming tiles as appropriate. There should be no expectation + // that tiles arrive at the client in the same order that they were requested. + + // But, whatever. + + for (int itRow = 0; itRow < rows; ++itRow) + { + for (int itCol = 0; itCol < cols; ++itCol) + { + tileWidth = tileSize; + tileHeight = tileSize; + tileX = tileSize * itCol; + tileY = tileSize * itRow; + text = Poco::format("tile part=%d width=%d height=%d tileposx=%d tileposy=%d tilewidth=%d tileheight=%d", + part, pixTileSize, pixTileSize, tileX, tileY, tileWidth, tileHeight); + + sendTextFrame(socket, text); + getTileMessage(socket, tile); + // expected tile: part= width= height= tileposx= tileposy= tilewidth= tileheight= + Poco::StringTokenizer tokens(tile, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + CPPUNIT_ASSERT_EQUAL(std::string("tile:"), tokens[0]); + CPPUNIT_ASSERT_EQUAL(part, std::stoi(tokens[1].substr(std::string("part=").size()))); + CPPUNIT_ASSERT_EQUAL(pixTileSize, std::stoi(tokens[2].substr(std::string("width=").size()))); + CPPUNIT_ASSERT_EQUAL(pixTileSize, std::stoi(tokens[3].substr(std::string("height=").size()))); + CPPUNIT_ASSERT_EQUAL(tileX, std::stoi(tokens[4].substr(std::string("tileposx=").size()))); + CPPUNIT_ASSERT_EQUAL(tileY, std::stoi(tokens[5].substr(std::string("tileposy=").size()))); + CPPUNIT_ASSERT_EQUAL(tileWidth, std::stoi(tokens[6].substr(std::string("tileWidth=").size()))); + CPPUNIT_ASSERT_EQUAL(tileHeight, std::stoi(tokens[7].substr(std::string("tileHeight=").size()))); + } + } +} + +void TileCacheTests::getTileMessage(Poco::Net::WebSocket& ws, std::string& tile) +{ + int flags; + int bytes; + int size = 0; + int retries = 10; + const Poco::Timespan waitTime(1000000); + + ws.setReceiveTimeout(0); + std::cout << "==> getTileMessage\n"; + tile.clear(); + do + { + std::vector<char> payload(READ_BUFFER_SIZE * 100); + if (retries > 0 && ws.poll(waitTime, Poco::Net::Socket::SELECT_READ)) + { + bytes = ws.receiveFrame(payload.data(), payload.capacity(), flags); + payload.resize(bytes > 0 ? bytes : 0); + std::cout << "Got " << bytes << " bytes, flags: " << std::bitset<8>(flags) << '\n'; + if (bytes > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE) + { + tile = LOOLProtocol::getFirstLine(payload.data(), bytes); + std::cout << "message: " << tile << '\n'; + Poco::StringTokenizer tokens(tile, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + if (tokens.count() == 2 && + tokens[0] == "nextmessage:" && + LOOLProtocol::getTokenInteger(tokens[1], "size", size) && + size > 0) + { + payload.resize(size); + bytes = ws.receiveFrame(payload.data(), size, flags); + tile = LOOLProtocol::getFirstLine(payload.data(), bytes); + break; + } + } + retries = 10; + } + else + { + std::cout << "Timeout\n"; + --retries; + } + } + while (retries > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE); +} + CPPUNIT_TEST_SUITE_REGISTRATION(TileCacheTests); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/test/httpwstest.cpp b/loolwsd/test/httpwstest.cpp index 082ecdb..10dc8a6 100644 --- a/loolwsd/test/httpwstest.cpp +++ b/loolwsd/test/httpwstest.cpp @@ -77,11 +77,6 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testPasswordProtectedDocumentWithCorrectPasswordAgain); CPPUNIT_TEST(testInsertDelete); CPPUNIT_TEST(testEditLock); - CPPUNIT_TEST(testClientPartImpress); - CPPUNIT_TEST(testClientPartCalc); -#if ENABLE_DEBUG - CPPUNIT_TEST(testSimultaneousTilesRenderedJustOnce); -#endif // This should be the last test: CPPUNIT_TEST(testNoExtraLoolKitsLeft); @@ -106,25 +101,11 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture void testPasswordProtectedDocumentWithCorrectPassword(); void testPasswordProtectedDocumentWithCorrectPasswordAgain(); void testInsertDelete(); - void testClientPartImpress(); - void testClientPartCalc(); - void testSimultaneousTilesRenderedJustOnce(); void testNoExtraLoolKitsLeft(); void testEditLock(); void loadDoc(const std::string& documentURL); - void checkTiles(Poco::Net::WebSocket& socket, - const std::string& type); - - void requestTiles(Poco::Net::WebSocket& socket, - const int part, - const int docWidth, - const int docHeight); - - void getTileMessage(Poco::Net::WebSocket& ws, - std::string& tile); - void getPartHashCodes(const std::string response, std::vector<std::string>& parts); @@ -1007,97 +988,6 @@ void HTTPWSTest::testInsertDelete() } } -void HTTPWSTest::testClientPartImpress() -{ - try - { - // Load a document - std::string documentPath, documentURL; - getDocumentPathAndURL("setclientpart.odp", documentPath, documentURL); - - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); - Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response); - - sendTextFrame(socket, "load url=" + documentURL); - CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket)); - - checkTiles(socket, "presentation"); - - socket.shutdown(); - Util::removeFile(documentPath); - } - catch (const Poco::Exception& exc) - { - CPPUNIT_FAIL(exc.displayText()); - } -} - -void HTTPWSTest::testClientPartCalc() -{ - try - { - // Load a document - std::string documentPath, documentURL; - getDocumentPathAndURL("setclientpart.ods", documentPath, documentURL); - - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); - Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response); - - sendTextFrame(socket, "load url=" + documentURL); - CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket)); - - checkTiles(socket, "spreadsheet"); - - socket.shutdown(); - Util::removeFile(documentPath); - } - catch (const Poco::Exception& exc) - { - CPPUNIT_FAIL(exc.displayText()); - } -} - -void HTTPWSTest::testSimultaneousTilesRenderedJustOnce() -{ - std::string documentPath, documentURL; - getDocumentPathAndURL("hello.odt", documentPath, documentURL); - - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL); - Poco::Net::WebSocket socket1 = *connectLOKit(_uri, request, _response); - sendTextFrame(socket1, "load url=" + documentURL); - - Poco::Net::WebSocket socket2 = *connectLOKit(_uri, request, _response); - sendTextFrame(socket2, "load url=" + documentURL); - - sendTextFrame(socket1, "tile part=42 width=400 height=400 tileposx=1000 tileposy=2000 tilewidth=3000 tileheight=3000"); - sendTextFrame(socket2, "tile part=42 width=400 height=400 tileposx=1000 tileposy=2000 tilewidth=3000 tileheight=3000"); - - std::string response1; - getResponseMessage(socket1, "tile:", response1, true); - CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !response1.empty()); - - std::string response2; - getResponseMessage(socket2, "tile:", response2, true); - CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !response2.empty()); - - if (!response1.empty() && !response2.empty()) - { - Poco::StringTokenizer tokens1(response1, " "); - std::string renderId1; - LOOLProtocol::getTokenString(tokens1, "renderid", renderId1); - Poco::StringTokenizer tokens2(response2, " "); - std::string renderId2; - LOOLProtocol::getTokenString(tokens2, "renderid", renderId2); - - CPPUNIT_ASSERT(renderId1 == renderId2 || - (renderId1 == "cached" && renderId2 != "cached") || - (renderId1 != "cached" && renderId2 == "cached")); - } - - socket1.shutdown(); - socket2.shutdown(); -} - void HTTPWSTest::testEditLock() { const std::string documentPath = Util::getTempFilePath(TDOC, "hello.odt"); @@ -1222,187 +1112,6 @@ void HTTPWSTest::testNoExtraLoolKitsLeft() CPPUNIT_ASSERT_EQUAL(_initialLoolKitCount, countNow); } -void HTTPWSTest::checkTiles(Poco::Net::WebSocket& socket, const std::string& docType) -{ - const std::string current = "current="; - const std::string height = "height="; - const std::string parts = "parts="; - const std::string type = "type="; - const std::string width = "width="; - - int currentPart = -1; - int totalParts = 0; - int docHeight = 0; - int docWidth = 0; - - std::string response; - std::string text; - - // check total slides 10 - getResponseMessage(socket, "status:", response, false); - CPPUNIT_ASSERT_MESSAGE("did not receive a status: message as expected", !response.empty()); - { - std::cout << "status: " << response << std::endl; - Poco::StringTokenizer tokens(response, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), tokens.count()); - - // Expected format is something like 'type= parts= current= width= height='. - text = tokens[0].substr(type.size()); - totalParts = std::stoi(tokens[1].substr(parts.size())); - currentPart = std::stoi(tokens[2].substr(current.size())); - docWidth = std::stoi(tokens[3].substr(width.size())); - docHeight = std::stoi(tokens[4].substr(height.size())); - CPPUNIT_ASSERT_EQUAL(docType, text); - CPPUNIT_ASSERT_EQUAL(10, totalParts); - CPPUNIT_ASSERT(currentPart > -1); - CPPUNIT_ASSERT(docWidth > 0); - CPPUNIT_ASSERT(docHeight > 0); - } - - if (docType == "presentation") - { - // first full invalidation - getResponseMessage(socket, "invalidatetiles:", response, true); - CPPUNIT_ASSERT_MESSAGE("did not receive a invalidatetiles: message as expected", !response.empty()); - { - Poco::StringTokenizer tokens(response, ":", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); - CPPUNIT_ASSERT_EQUAL(std::string("EMPTY"), tokens[0]); - } - - // request tiles - requestTiles(socket, currentPart, docWidth, docHeight); - } - - // random setclientpart - std::srand(std::time(0)); - std::vector<int> vParts = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::random_shuffle (vParts.begin(), vParts.end()); - for (auto it : vParts) - { - if (currentPart != it) - { - // change part - text = Poco::format("setclientpart part=%d", it); - std::cout << text << std::endl; - sendTextFrame(socket, text); - - // get full invalidation - getResponseMessage(socket, "invalidatetiles:", response, true); - CPPUNIT_ASSERT_MESSAGE("did not receive a invalidatetiles: message as expected", !response.empty()); - { - Poco::StringTokenizer tokens(response, ":", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); - CPPUNIT_ASSERT_EQUAL(std::string("EMPTY"), tokens[0]); - } - requestTiles(socket, it, docWidth, docHeight); - } - currentPart = it; - } -} - -void HTTPWSTest::requestTiles(Poco::Net::WebSocket& socket, const int part, const int docWidth, const int docHeight) -{ - // twips - const int tileSize = 3840; - // pixel - const int pixTileSize = 256; - - int rows; - int cols; - int tileX; - int tileY; - int tileWidth; - int tileHeight; - - std::string text; - std::string tile; - - rows = docHeight / tileSize; - cols = docWidth / tileSize; - - // Note: this code tests tile requests in the wrong way. - - // This code does NOT match what was the idea how the LOOL protocol should/could be used. The - // intent was never that the protocol would need to be, or should be, used in a strict - // request/reply fashion. If a client needs n tiles, it should just send the requests, one after - // another. There is no need to do n roundtrips. A client should all the time be reading - // incoming messages, and handle incoming tiles as appropriate. There should be no expectation - // that tiles arrive at the client in the same order that they were requested. - - // But, whatever. - - for (int itRow = 0; itRow < rows; ++itRow) - { - for (int itCol = 0; itCol < cols; ++itCol) - { - tileWidth = tileSize; - tileHeight = tileSize; - tileX = tileSize * itCol; - tileY = tileSize * itRow; - text = Poco::format("tile part=%d width=%d height=%d tileposx=%d tileposy=%d tilewidth=%d tileheight=%d", - part, pixTileSize, pixTileSize, tileX, tileY, tileWidth, tileHeight); - - sendTextFrame(socket, text); - getTileMessage(socket, tile); - // expected tile: part= width= height= tileposx= tileposy= tilewidth= tileheight= - Poco::StringTokenizer tokens(tile, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); - CPPUNIT_ASSERT_EQUAL(std::string("tile:"), tokens[0]); - CPPUNIT_ASSERT_EQUAL(part, std::stoi(tokens[1].substr(std::string("part=").size()))); - CPPUNIT_ASSERT_EQUAL(pixTileSize, std::stoi(tokens[2].substr(std::string("width=").size()))); - CPPUNIT_ASSERT_EQUAL(pixTileSize, std::stoi(tokens[3].substr(std::string("height=").size()))); - CPPUNIT_ASSERT_EQUAL(tileX, std::stoi(tokens[4].substr(std::string("tileposx=").size()))); - CPPUNIT_ASSERT_EQUAL(tileY, std::stoi(tokens[5].substr(std::string("tileposy=").size()))); - CPPUNIT_ASSERT_EQUAL(tileWidth, std::stoi(tokens[6].substr(std::string("tileWidth=").size()))); - CPPUNIT_ASSERT_EQUAL(tileHeight, std::stoi(tokens[7].substr(std::string("tileHeight=").size()))); - } - } -} - -void HTTPWSTest::getTileMessage(Poco::Net::WebSocket& ws, std::string& tile) -{ - int flags; - int bytes; - int size = 0; - int retries = 10; - const Poco::Timespan waitTime(1000000); - - ws.setReceiveTimeout(0); - std::cout << "==> getTileMessage\n"; - tile.clear(); - do - { - std::vector<char> payload(READ_BUFFER_SIZE * 100); - if (retries > 0 && ws.poll(waitTime, Poco::Net::Socket::SELECT_READ)) - { - bytes = ws.receiveFrame(payload.data(), payload.capacity(), flags); - payload.resize(bytes > 0 ? bytes : 0); - std::cout << "Got " << bytes << " bytes, flags: " << std::bitset<8>(flags) << '\n'; - if (bytes > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE) - { - tile = LOOLProtocol::getFirstLine(payload.data(), bytes); - std::cout << "message: " << tile << '\n'; - Poco::StringTokenizer tokens(tile, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); - if (tokens.count() == 2 && - tokens[0] == "nextmessage:" && - LOOLProtocol::getTokenInteger(tokens[1], "size", size) && - size > 0) - { - payload.resize(size); - bytes = ws.receiveFrame(payload.data(), size, flags); - tile = LOOLProtocol::getFirstLine(payload.data(), bytes); - break; - } - } - retries = 10; - } - else - { - std::cout << "Timeout\n"; - --retries; - } - } - while (retries > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE); -} - void HTTPWSTest::getPartHashCodes(const std::string response, std::vector<std::string>& parts) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits