66ac62429c
Remove significant complexity; if we need it later lets do it more simply serializing when we start / finish a session. Turn off caching for mobile - possibly should kill for single-user too. Change-Id: I5ea56088ddbb61f22fe7920f8c9ac7440cb3296a
1540 lines
61 KiB
C++
1540 lines
61 KiB
C++
/* -*- 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/.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <Poco/Net/AcceptCertificateHandler.h>
|
|
#include <Poco/Net/InvalidCertificateHandler.h>
|
|
#include <Poco/Net/SSLManager.h>
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include <Common.hpp>
|
|
#include <Protocol.hpp>
|
|
#include <LOOLWebSocket.hpp>
|
|
#include <MessageQueue.hpp>
|
|
#include <Png.hpp>
|
|
#include <TileCache.hpp>
|
|
#include <Unit.hpp>
|
|
#include <Util.hpp>
|
|
|
|
#include <countloolkits.hpp>
|
|
#include <helpers.hpp>
|
|
#include <test.hpp>
|
|
#include <sstream>
|
|
|
|
using namespace helpers;
|
|
|
|
namespace CPPUNIT_NS
|
|
{
|
|
template<>
|
|
struct assertion_traits<std::vector<char>>
|
|
{
|
|
static bool equal(const std::vector<char>& x, const std::vector<char>& y)
|
|
{
|
|
return x == y;
|
|
}
|
|
|
|
static std::string toString(const std::vector<char>& x)
|
|
{
|
|
const std::string text = '"' + (!x.empty() ? std::string(x.data(), x.size()) : "<empty>") + '"';
|
|
return text;
|
|
}
|
|
};
|
|
}
|
|
|
|
/// TileCache unit-tests.
|
|
class TileCacheTests : public CPPUNIT_NS::TestFixture
|
|
{
|
|
const Poco::URI _uri;
|
|
Poco::Net::HTTPResponse _response;
|
|
|
|
CPPUNIT_TEST_SUITE(TileCacheTests);
|
|
|
|
CPPUNIT_TEST(testSimple);
|
|
CPPUNIT_TEST(testSimpleCombine);
|
|
CPPUNIT_TEST(testCancelTiles);
|
|
// unstable
|
|
// CPPUNIT_TEST(testCancelTilesMultiView);
|
|
CPPUNIT_TEST(testDisconnectMultiView);
|
|
CPPUNIT_TEST(testUnresponsiveClient);
|
|
CPPUNIT_TEST(testImpressTiles);
|
|
CPPUNIT_TEST(testClientPartImpress);
|
|
CPPUNIT_TEST(testClientPartCalc);
|
|
// FIXME CPPUNIT_TEST(testTilesRenderedJustOnce);
|
|
// CPPUNIT_TEST(testTilesRenderedJustOnceMultiClient); // always fails, seems complicated to fix
|
|
#if ENABLE_DEBUG
|
|
CPPUNIT_TEST(testSimultaneousTilesRenderedJustOnce);
|
|
#endif
|
|
CPPUNIT_TEST(testLoad12ods);
|
|
CPPUNIT_TEST(testTileInvalidateWriter);
|
|
CPPUNIT_TEST(testTileInvalidateWriterPage);
|
|
CPPUNIT_TEST(testTileInvalidateCalc);
|
|
// temporarily disable
|
|
//CPPUNIT_TEST(testTileInvalidatePartCalc);
|
|
//CPPUNIT_TEST(testTileInvalidatePartImpress);
|
|
CPPUNIT_TEST(testTileRequestByInvalidation);
|
|
CPPUNIT_TEST(testTileRequestByZoom);
|
|
CPPUNIT_TEST(testTileWireIDHandling);
|
|
CPPUNIT_TEST(testTileProcessed);
|
|
CPPUNIT_TEST(testTileInvalidatedOutside);
|
|
CPPUNIT_TEST(testTileBeingRenderedHandling);
|
|
CPPUNIT_TEST(testWireIDFilteringOnWSDSide);
|
|
CPPUNIT_TEST(testLimitTileVersionsOnFly);
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
void testSimple();
|
|
void testSimpleCombine();
|
|
void testCancelTiles();
|
|
void testCancelTilesMultiView();
|
|
void testDisconnectMultiView();
|
|
void testUnresponsiveClient();
|
|
void testImpressTiles();
|
|
void testClientPartImpress();
|
|
void testClientPartCalc();
|
|
void testTilesRenderedJustOnce();
|
|
void testTilesRenderedJustOnceMultiClient();
|
|
void testSimultaneousTilesRenderedJustOnce();
|
|
void testLoad12ods();
|
|
void testTileInvalidateWriter();
|
|
void testTileInvalidateWriterPage();
|
|
void testWriterAnyKey();
|
|
void testTileInvalidateCalc();
|
|
void testTileInvalidatePartCalc();
|
|
void testTileInvalidatePartImpress();
|
|
void testTileRequestByInvalidation();
|
|
void testTileRequestByZoom();
|
|
void testTileWireIDHandling();
|
|
void testTileProcessed();
|
|
void testTileInvalidatedOutside();
|
|
void testTileBeingRenderedHandling();
|
|
void testWireIDFilteringOnWSDSide();
|
|
void testLimitTileVersionsOnFly();
|
|
|
|
void checkTiles(std::shared_ptr<LOOLWebSocket>& socket,
|
|
const std::string& type,
|
|
const std::string& name = "checkTiles ");
|
|
|
|
void requestTiles(std::shared_ptr<LOOLWebSocket>& socket,
|
|
const int part,
|
|
const int docWidth,
|
|
const int docHeight,
|
|
const std::string& name = "requestTiles ");
|
|
|
|
void checkBlackTiles(std::shared_ptr<LOOLWebSocket>& socket,
|
|
const int part,
|
|
const int docWidth,
|
|
const int docHeight,
|
|
const std::string& name = "checkBlackTiles ");
|
|
|
|
void checkBlackTile(std::stringstream& tile);
|
|
|
|
public:
|
|
TileCacheTests()
|
|
: _uri(helpers::getTestServerURI())
|
|
{
|
|
#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(nullptr, invalidCertHandler, sslContext);
|
|
#endif
|
|
}
|
|
|
|
#if ENABLE_SSL
|
|
~TileCacheTests()
|
|
{
|
|
Poco::Net::uninitializeSSL();
|
|
}
|
|
#endif
|
|
|
|
void setUp()
|
|
{
|
|
resetTestStartTime();
|
|
testCountHowManyLoolkits();
|
|
resetTestStartTime();
|
|
}
|
|
|
|
void tearDown()
|
|
{
|
|
resetTestStartTime();
|
|
testNoExtraLoolKitsLeft();
|
|
resetTestStartTime();
|
|
}
|
|
};
|
|
|
|
void TileCacheTests::testSimple()
|
|
{
|
|
if (isStandalone())
|
|
{
|
|
if (!UnitWSD::init(UnitWSD::UnitType::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());
|
|
|
|
int part = 0;
|
|
int width = 256;
|
|
int height = 256;
|
|
int tilePosX = 0;
|
|
int tilePosY = 0;
|
|
int tileWidth = 3840;
|
|
int tileHeight = 3840;
|
|
TileDesc tile(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight, -1, 0, -1, false);
|
|
|
|
// No Cache
|
|
TileCache::Tile tileData = tc.lookupTile(tile);
|
|
CPPUNIT_ASSERT_MESSAGE("found tile when none was expected", !tileData);
|
|
|
|
// Cache Tile
|
|
const int size = 1024;
|
|
const std::vector<char> data = genRandomData(size);
|
|
tc.saveTileAndNotify(tile, data.data(), size);
|
|
|
|
// Find Tile
|
|
tileData = tc.lookupTile(tile);
|
|
CPPUNIT_ASSERT_MESSAGE("tile not found when expected", tileData);
|
|
CPPUNIT_ASSERT_MESSAGE("cached tile corrupted", data == *tileData);
|
|
|
|
// Invalidate Tiles
|
|
tc.invalidateTiles("invalidatetiles: EMPTY");
|
|
|
|
// No Cache
|
|
tileData = tc.lookupTile(tile);
|
|
CPPUNIT_ASSERT_MESSAGE("found tile when none was expected", !tileData);
|
|
}
|
|
|
|
void TileCacheTests::testSimpleCombine()
|
|
{
|
|
const char* testname = "simpleCombine ";
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("hello.odt", documentPath, documentURL, testname);
|
|
|
|
// First.
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, "simpleCombine-1 ");
|
|
|
|
sendTextFrame(socket1, "tilecombine part=0 width=256 height=256 tileposx=0,3840 tileposy=0,0 tilewidth=3840 tileheight=3840");
|
|
|
|
std::vector<char> tile1a = getResponseMessage(socket1, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile1a.empty());
|
|
std::vector<char> tile1b = getResponseMessage(socket1, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile1b.empty());
|
|
sendTextFrame(socket1, "tilecombine part=0 width=256 height=256 tileposx=0,3840 tileposy=0,0 tilewidth=3840 tileheight=3840");
|
|
|
|
tile1a = getResponseMessage(socket1, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile1a.empty());
|
|
tile1b = getResponseMessage(socket1, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile1b.empty());
|
|
|
|
// Second.
|
|
std::cerr << "Connecting second client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, "simpleCombine-2 ", true);
|
|
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840 tileposy=0,0 tilewidth=3840 tileheight=3840");
|
|
|
|
std::vector<char> tile2a = getResponseMessage(socket2, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile2a.empty());
|
|
std::vector<char> tile2b = getResponseMessage(socket2, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("did not receive a tile: message as expected", !tile2b.empty());
|
|
}
|
|
|
|
void TileCacheTests::testCancelTiles()
|
|
{
|
|
const char* testName = "cancelTiles ";
|
|
|
|
// The tile response can race past the canceltiles,
|
|
// so be forgiving to avoid spurious failures.
|
|
const size_t repeat = 4;
|
|
for (size_t i = 1; i <= repeat; ++i)
|
|
{
|
|
std::cerr << "cancelTiles try #" << i << std::endl;
|
|
|
|
// Wait to clear previous sessions.
|
|
countLoolKitProcesses(InitialLoolKitCount);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("setclientpart.ods", _uri, testName);
|
|
|
|
// Request a huge tile, and cancel immediately.
|
|
sendTextFrame(socket, "tilecombine part=0 width=2560 height=2560 tileposx=0 tileposy=0 tilewidth=38400 tileheight=38400");
|
|
sendTextFrame(socket, "canceltiles");
|
|
|
|
const auto res = getResponseString(socket, "tile:", testName, 1000);
|
|
if (res.empty())
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (i == repeat)
|
|
{
|
|
CPPUNIT_ASSERT_MESSAGE("Did not expect getting message [" + res + "].", res.empty());
|
|
}
|
|
|
|
std::cerr << "Unexpected: [" << res << "]" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testCancelTilesMultiView()
|
|
{
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("setclientpart.ods", documentPath, documentURL, "cancelTilesMultiView ");
|
|
|
|
// The tile response can race past the canceltiles,
|
|
// so be forgiving to avoid spurious failures.
|
|
const size_t repeat = 4;
|
|
for (size_t j = 1; j <= repeat; ++j)
|
|
{
|
|
std::cerr << "cancelTilesMultiView try #" << j << std::endl;
|
|
|
|
// Wait to clear previous sessions.
|
|
countLoolKitProcesses(InitialLoolKitCount);
|
|
|
|
// Request a huge tile, and cancel immediately.
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, "cancelTilesMultiView-1 ");
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, "cancelTilesMultiView-2 ", true);
|
|
|
|
sendTextFrame(socket1, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,11520,0,3840,7680,11520 tileposy=0,0,0,0,3840,3840,3840,3840 tilewidth=3840 tileheight=3840", "cancelTilesMultiView-1 ");
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,0 tileposy=0,0,0,22520 tilewidth=3840 tileheight=3840", "cancelTilesMultiView-2 ");
|
|
|
|
sendTextFrame(socket1, "canceltiles");
|
|
const auto res1 = getResponseString(socket1, "tile:", "cancelTilesMultiView-1 ", 500);
|
|
if (!res1.empty())
|
|
{
|
|
if (j == repeat)
|
|
{
|
|
CPPUNIT_ASSERT_MESSAGE("Did not expect getting message [" + res1 + "].", res1.empty());
|
|
}
|
|
|
|
std::cerr << "Unexpected: [" << res1 << "]" << std::endl;
|
|
continue;
|
|
}
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
getTileMessage(*socket2, "cancelTilesMultiView-2 ");
|
|
}
|
|
|
|
// Should never get more than 4 tiles on socket2.
|
|
// Though in practice we get the rendering result from socket1's request and ours.
|
|
// This happens because we currently always send back tiles even if they are of old version
|
|
// because we want to be responsive, since we've rendered them anyway.
|
|
const auto res2 = getResponseString(socket2, "tile:", "cancelTilesMultiView-2 ", 500);
|
|
if (!res2.empty())
|
|
{
|
|
if (j == repeat)
|
|
{
|
|
CPPUNIT_ASSERT_MESSAGE("Did not expect getting message [" + res2 + "].", res1.empty());
|
|
}
|
|
|
|
std::cerr << "Unexpected: [" << res2 << "]" << std::endl;
|
|
continue;
|
|
}
|
|
|
|
if (res1.empty() && res2.empty())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testDisconnectMultiView()
|
|
{
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("setclientpart.ods", documentPath, documentURL, "disconnectMultiView ");
|
|
|
|
const size_t repeat = 4;
|
|
for (size_t j = 1; j <= repeat; ++j)
|
|
{
|
|
std::cerr << "disconnectMultiView try #" << j << std::endl;
|
|
|
|
// Wait to clear previous sessions.
|
|
countLoolKitProcesses(InitialLoolKitCount);
|
|
|
|
// Request a huge tile, and cancel immediately.
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, "disconnectMultiView-1 ");
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, "disconnectMultiView-2 ", true);
|
|
|
|
sendTextFrame(socket1, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,11520,0,3840,7680,11520 tileposy=0,0,0,0,3840,3840,3840,3840 tilewidth=3840 tileheight=3840", "cancelTilesMultiView-1 ");
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,0 tileposy=0,0,0,22520 tilewidth=3840 tileheight=3840", "cancelTilesMultiView-2 ");
|
|
|
|
socket1->shutdown();
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
getTileMessage(*socket2, "disconnectMultiView-2 ");
|
|
}
|
|
|
|
// Should never get more than 4 tiles on socket2.
|
|
getResponseString(socket2, "tile:", "disconnectMultiView-2 ", 500);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testUnresponsiveClient()
|
|
{
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("hello.odt", documentPath, documentURL, "unresponsiveClient ");
|
|
|
|
std::cerr << "Connecting first client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, "unresponsiveClient-1 ");
|
|
|
|
std::cerr << "Connecting second client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, "unresponsiveClient-2 ");
|
|
|
|
// Pathologically request tiles and fail to read (say slow connection).
|
|
// Meanwhile, verify that others can get all tiles fine.
|
|
// TODO: Track memory consumption to verify we don't buffer too much.
|
|
|
|
std::ostringstream oss;
|
|
for (int i = 0; i < 1000; ++i)
|
|
{
|
|
oss << Util::encodeId(Util::rng::getNext(), 6);
|
|
}
|
|
|
|
const std::string documentContents = oss.str();
|
|
for (int x = 0; x < 8; ++x)
|
|
{
|
|
// Invalidate to force re-rendering.
|
|
sendTextFrame(socket2, "uno .uno:SelectAll");
|
|
sendTextFrame(socket2, "uno .uno:Delete");
|
|
assertResponseString(socket2, "invalidatetiles:", "client2 ");
|
|
sendTextFrame(socket2, "paste mimetype=text/html\n" + documentContents);
|
|
assertResponseString(socket2, "invalidatetiles:", "client2 ");
|
|
|
|
// Ask for tiles and don't read!
|
|
sendTextFrame(socket1, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,11520,0,3840,7680,11520 tileposy=0,0,0,0,3840,3840,3840,3840 tilewidth=3840 tileheight=3840");
|
|
|
|
// Verify that we get all 8 tiles.
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680,11520,0,3840,7680,11520 tileposy=0,0,0,0,3840,3840,3840,3840 tilewidth=3840 tileheight=3840");
|
|
for (int i = 0; i < 8; ++i)
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket2, "tile:", "client2 ");
|
|
CPPUNIT_ASSERT_MESSAGE("Did not receive tile #" + std::to_string(i+1) + " of 8: message as expected", !tile.empty());
|
|
}
|
|
/// Send canceltiles message to clear tiles-on-fly list, otherwise wsd waits for tileprocessed messages
|
|
sendTextFrame(socket2, "canceltiles");
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testImpressTiles()
|
|
{
|
|
try
|
|
{
|
|
const std::string testName = "impressTiles ";
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("setclientpart.odp", _uri, testName);
|
|
|
|
sendTextFrame(socket, "tile part=0 width=180 height=135 tileposx=0 tileposy=0 tilewidth=15875 tileheight=11906 id=0", testName);
|
|
getTileMessage(*socket, testName);
|
|
}
|
|
catch (const Poco::Exception& exc)
|
|
{
|
|
CPPUNIT_FAIL(exc.displayText());
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testClientPartImpress()
|
|
{
|
|
try
|
|
{
|
|
const std::string testName = "clientPartImpress ";
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("setclientpart.odp", _uri, testName);
|
|
|
|
checkTiles(socket, "presentation", testName);
|
|
|
|
socket->shutdown();
|
|
}
|
|
catch (const Poco::Exception& exc)
|
|
{
|
|
CPPUNIT_FAIL(exc.displayText());
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testClientPartCalc()
|
|
{
|
|
try
|
|
{
|
|
const std::string testName = "clientPartCalc ";
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("setclientpart.ods", _uri, testName);
|
|
|
|
checkTiles(socket, "spreadsheet", testName);
|
|
|
|
socket->shutdown();
|
|
}
|
|
catch (const Poco::Exception& exc)
|
|
{
|
|
CPPUNIT_FAIL(exc.displayText());
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testTilesRenderedJustOnce()
|
|
{
|
|
const char* testname = "tilesRenderdJustOnce ";
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("with_comment.odt", _uri, testname);
|
|
|
|
assertResponseString(socket, "statechanged: .uno:AcceptTrackedChange=", testname);
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
// Get initial rendercount.
|
|
sendTextFrame(socket, "ping", testname);
|
|
const auto ping1 = assertResponseString(socket, "pong", testname);
|
|
int renderCount1 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping1, "rendercount", renderCount1));
|
|
CPPUNIT_ASSERT_EQUAL(i * 3, renderCount1);
|
|
|
|
// Modify.
|
|
sendText(socket, "a", testname);
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// Get 3 tiles.
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname);
|
|
assertResponseString(socket, "tile:", testname);
|
|
assertResponseString(socket, "tile:", testname);
|
|
assertResponseString(socket, "tile:", testname);
|
|
|
|
// Get new rendercount.
|
|
sendTextFrame(socket, "ping", testname);
|
|
const auto ping2 = assertResponseString(socket, "pong", testname);
|
|
int renderCount2 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping2, "rendercount", renderCount2));
|
|
CPPUNIT_ASSERT_EQUAL((i+1) * 3, renderCount2);
|
|
|
|
// Get same 3 tiles.
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname);
|
|
const auto tile1 = assertResponseString(socket, "tile:", testname);
|
|
std::string renderId1;
|
|
LOOLProtocol::getTokenStringFromMessage(tile1, "renderid", renderId1);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId1);
|
|
|
|
const auto tile2 = assertResponseString(socket, "tile:", testname);
|
|
std::string renderId2;
|
|
LOOLProtocol::getTokenStringFromMessage(tile2, "renderid", renderId2);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId2);
|
|
|
|
const auto tile3 = assertResponseString(socket, "tile:", testname);
|
|
std::string renderId3;
|
|
LOOLProtocol::getTokenStringFromMessage(tile3, "renderid", renderId3);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId3);
|
|
|
|
// Get new rendercount.
|
|
sendTextFrame(socket, "ping", testname);
|
|
const auto ping3 = assertResponseString(socket, "pong", testname);
|
|
int renderCount3 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping3, "rendercount", renderCount3));
|
|
CPPUNIT_ASSERT_EQUAL(renderCount2, renderCount3);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testTilesRenderedJustOnceMultiClient()
|
|
{
|
|
const std::string testname = "tilesRenderdJustOnceMultiClient";
|
|
const auto testname1 = testname + "-1 ";
|
|
const auto testname2 = testname + "-2 ";
|
|
const auto testname3 = testname + "-3 ";
|
|
const auto testname4 = testname + "-4 ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("with_comment.odt", documentPath, documentURL, testname);
|
|
|
|
std::cerr << "Connecting first client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname1);
|
|
std::cerr << "Connecting second client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, testname2);
|
|
std::cerr << "Connecting third client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket3 = loadDocAndGetSocket(_uri, documentURL, testname3);
|
|
std::cerr << "Connecting fourth client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket4 = loadDocAndGetSocket(_uri, documentURL, "tilesRenderdJustOnce-4 ");
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
// No tiles at this point.
|
|
assertNotInResponse(socket, "tile:", testname1);
|
|
assertNotInResponse(socket2, "tile:", testname2);
|
|
assertNotInResponse(socket3, "tile:", testname3);
|
|
assertNotInResponse(socket4, "tile:", testname4);
|
|
|
|
// Get initial rendercount.
|
|
sendTextFrame(socket, "ping", testname1);
|
|
const auto ping1 = assertResponseString(socket, "pong", testname1);
|
|
int renderCount1 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping1, "rendercount", renderCount1));
|
|
CPPUNIT_ASSERT_EQUAL(i * 3, renderCount1);
|
|
|
|
// Modify.
|
|
sendText(socket, "a", testname1);
|
|
assertResponseString(socket, "invalidatetiles:", testname1);
|
|
|
|
// Get 3 tiles.
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname1);
|
|
assertResponseString(socket, "tile:", testname1);
|
|
assertResponseString(socket, "tile:", testname1);
|
|
assertResponseString(socket, "tile:", testname1);
|
|
|
|
assertResponseString(socket2, "invalidatetiles:", testname2);
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname2);
|
|
assertResponseString(socket2, "tile:", testname2);
|
|
assertResponseString(socket2, "tile:", testname2);
|
|
assertResponseString(socket2, "tile:", testname2);
|
|
|
|
assertResponseString(socket3, "invalidatetiles:", testname3);
|
|
sendTextFrame(socket3, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname3);
|
|
assertResponseString(socket3, "tile:", testname3);
|
|
assertResponseString(socket3, "tile:", testname3);
|
|
assertResponseString(socket3, "tile:", testname3);
|
|
|
|
assertResponseString(socket4, "invalidatetiles:", testname4);
|
|
sendTextFrame(socket4, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname4);
|
|
assertResponseString(socket4, "tile:", testname4);
|
|
assertResponseString(socket4, "tile:", testname4);
|
|
assertResponseString(socket4, "tile:", testname4);
|
|
|
|
// Get new rendercount.
|
|
sendTextFrame(socket, "ping", testname1);
|
|
const auto ping2 = assertResponseString(socket, "pong", testname1);
|
|
int renderCount2 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping2, "rendercount", renderCount2));
|
|
CPPUNIT_ASSERT_EQUAL((i+1) * 3, renderCount2);
|
|
|
|
// Get same 3 tiles.
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840", testname1);
|
|
const auto tile1 = assertResponseString(socket, "tile:", testname1);
|
|
std::string renderId1;
|
|
LOOLProtocol::getTokenStringFromMessage(tile1, "renderid", renderId1);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId1);
|
|
|
|
const auto tile2 = assertResponseString(socket, "tile:", testname1);
|
|
std::string renderId2;
|
|
LOOLProtocol::getTokenStringFromMessage(tile2, "renderid", renderId2);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId2);
|
|
|
|
const auto tile3 = assertResponseString(socket, "tile:", testname1);
|
|
std::string renderId3;
|
|
LOOLProtocol::getTokenStringFromMessage(tile3, "renderid", renderId3);
|
|
CPPUNIT_ASSERT_EQUAL(std::string("cached"), renderId3);
|
|
|
|
// Get new rendercount.
|
|
sendTextFrame(socket, "ping", testname1);
|
|
const auto ping3 = assertResponseString(socket, "pong", testname1);
|
|
int renderCount3 = 0;
|
|
CPPUNIT_ASSERT(LOOLProtocol::getTokenIntegerFromMessage(ping3, "rendercount", renderCount3));
|
|
CPPUNIT_ASSERT_EQUAL(renderCount2, renderCount3);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testSimultaneousTilesRenderedJustOnce()
|
|
{
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("hello.odt", documentPath, documentURL, "simultaneousTilesrenderedJustOnce ");
|
|
|
|
std::cerr << "Connecting first client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, "simultaneousTilesRenderdJustOnce-1 ");
|
|
std::cerr << "Connecting second client." << std::endl;
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, "simultaneousTilesRenderdJustOnce-2 ");
|
|
|
|
// Wait for the invalidatetile events to pass, otherwise they
|
|
// remove our tile subscription.
|
|
assertResponseString(socket1, "statechanged:", "client1 ");
|
|
assertResponseString(socket2, "statechanged:", "client2 ");
|
|
|
|
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");
|
|
|
|
const auto response1 = assertResponseString(socket1, "tile:", "client1 ");
|
|
const auto response2 = assertResponseString(socket2, "tile:", "client2 ");
|
|
|
|
if (!response1.empty() && !response2.empty())
|
|
{
|
|
std::string renderId1;
|
|
LOOLProtocol::getTokenStringFromMessage(response1, "renderid", renderId1);
|
|
std::string renderId2;
|
|
LOOLProtocol::getTokenStringFromMessage(response2, "renderid", renderId2);
|
|
|
|
CPPUNIT_ASSERT(renderId1 == renderId2 ||
|
|
(renderId1 == "cached" && renderId2 != "cached") ||
|
|
(renderId1 != "cached" && renderId2 == "cached"));
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testLoad12ods()
|
|
{
|
|
try
|
|
{
|
|
const char* testname = "load12ods ";
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("load12.ods", _uri, testname);
|
|
|
|
int docSheet = -1;
|
|
int docSheets = 0;
|
|
int docHeight = 0;
|
|
int docWidth = 0;
|
|
int docViewId = -1;
|
|
|
|
// check document size
|
|
sendTextFrame(socket, "status");
|
|
|
|
const auto response = assertResponseString(socket, "status:", testname);
|
|
parseDocSize(response.substr(7), "spreadsheet", docSheet, docSheets, docWidth, docHeight, docViewId);
|
|
|
|
checkBlackTiles(socket, docSheet, docWidth, docWidth, testname);
|
|
}
|
|
catch (const Poco::Exception& exc)
|
|
{
|
|
CPPUNIT_FAIL(exc.displayText());
|
|
}
|
|
catch (...)
|
|
{
|
|
CPPUNIT_FAIL("Unexpected exception thrown during ods load");
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::checkBlackTile(std::stringstream& tile)
|
|
{
|
|
png_uint_32 height = 0;
|
|
png_uint_32 width = 0;
|
|
png_uint_32 rowBytes = 0;
|
|
|
|
std::vector<png_bytep> rows = Png::decodePNG(tile, height, width, rowBytes);
|
|
|
|
png_uint_32 black = 0;
|
|
for (png_uint_32 itRow = 0; itRow < height; ++itRow)
|
|
{
|
|
png_uint_32 itCol = 0;
|
|
while (itCol <= rowBytes)
|
|
{
|
|
png_byte R = rows[itRow][itCol + 0];
|
|
png_byte G = rows[itRow][itCol + 1];
|
|
png_byte B = rows[itRow][itCol + 2];
|
|
//png_byte A = rows[itRow][itCol + 3];
|
|
if (R == 0x00 && G == 0x00 && B == 0x00)
|
|
{
|
|
++black;
|
|
}
|
|
|
|
itCol += 4;
|
|
}
|
|
}
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("The tile is 100% black", black != height * width);
|
|
assert(height * width != 0);
|
|
CPPUNIT_ASSERT_MESSAGE("The tile is 90% black", (black * 100) / (height * width) < 90);
|
|
}
|
|
|
|
void TileCacheTests::checkBlackTiles(std::shared_ptr<LOOLWebSocket>& socket, const int /*part*/, const int /*docWidth*/, const int /*docHeight*/, const std::string& name)
|
|
{
|
|
// Check the last row of tiles to verify that the tiles
|
|
// render correctly and there are no black tiles.
|
|
// Current cap of table size ends at 257280 twips (for load12.ods),
|
|
// otherwise 2035200 should be rendered successfully.
|
|
const char* req = "tile part=0 width=256 height=256 tileposx=0 tileposy=253440 tilewidth=3840 tileheight=3840";
|
|
sendTextFrame(socket, req);
|
|
|
|
const std::vector<char> tile = getResponseMessage(socket, "tile:", name);
|
|
if (!tile.size())
|
|
{
|
|
CPPUNIT_FAIL("No tile returned to checkBlackTiles - failed load ?");
|
|
return;
|
|
}
|
|
|
|
const std::string firstLine = LOOLProtocol::getFirstLine(tile);
|
|
|
|
#if 0
|
|
std::fstream outStream("/tmp/black.png", std::ios::out);
|
|
outStream.write(tile.data() + firstLine.size() + 1, tile.size() - firstLine.size() - 1);
|
|
outStream.close();
|
|
#endif
|
|
|
|
std::stringstream streamTile;
|
|
std::copy(tile.begin() + firstLine.size() + 1, tile.end(), std::ostream_iterator<char>(streamTile));
|
|
checkBlackTile(streamTile);
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidateWriter()
|
|
{
|
|
const char* testname = "tileInvalidateWriter ";
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
std::string text = "Test. Now go 3 \"Enters\":\n\n\nNow after the enters, goes this text";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skNone, testname); // Send ordinary characters and wait for response -> one tile invalidation for each
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
|
|
text = "\n\n\n";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skCtrl, testname); // Send 3 Ctrl+Enter -> 3 new pages
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
|
|
text = "abcde";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skNone, testname);
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
|
|
// While extra invalidates are not desirable, they are inevitable at the moment.
|
|
//CPPUNIT_ASSERT_MESSAGE("received unexpected invalidatetiles: message", getResponseMessage(socket, "invalidatetiles:").empty());
|
|
|
|
// TODO: implement a random-sequence "monkey test"
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidateWriterPage()
|
|
{
|
|
const char* testname = "tileInvalidateWriterPage ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
sendChar(socket, '\n', skCtrl, testname); // Send Ctrl+Enter (page break).
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
sendTextFrame(socket, "uno .uno:InsertTable { \"Columns\": { \"type\": \"long\",\"value\": 3 }, \"Rows\": { \"type\": \"long\",\"value\": 2 }}", testname);
|
|
|
|
const auto res = assertResponseString(socket, "invalidatetiles:", testname);
|
|
int part = -1;
|
|
CPPUNIT_ASSERT_MESSAGE("No part# in invalidatetiles message.",
|
|
LOOLProtocol::getTokenIntegerFromMessage(res, "part", part));
|
|
CPPUNIT_ASSERT_EQUAL(1, part);
|
|
}
|
|
|
|
// This isn't yet used
|
|
void TileCacheTests::testWriterAnyKey()
|
|
{
|
|
const char* testname = "writerAnyKey ";
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Now test "usual" keycodes (TODO: whole 32-bit range)
|
|
for (int i=0; i<0x1000; ++i)
|
|
{
|
|
std::stringstream ss("Keycode ");
|
|
ss << i;
|
|
std::string s = ss.str();
|
|
std::stringstream fn("saveas url=");
|
|
fn << documentURL << i << ".odt format= options=";
|
|
std::string f = fn.str();
|
|
|
|
const int istart = 474;
|
|
sendText(socket, "\n"+s+"\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i, testname);
|
|
sendKeyEvent(socket, "up", 0, i, testname);
|
|
sendText(socket, "\nEnd "+s+"\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Shift:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skShift, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skShift, testname);
|
|
sendText(socket, "\nEnd "+s+" With Shift\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Ctrl:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skCtrl, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skCtrl, testname);
|
|
sendText(socket, "\nEnd "+s+" With Ctrl\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Alt:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skAlt, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skAlt, testname);
|
|
sendText(socket, "\nEnd "+s+" With Alt\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Shift+Ctrl:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skShift|skCtrl, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skShift|skCtrl, testname);
|
|
sendText(socket, "\nEnd "+s+" With Shift+Ctrl\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Shift+Alt:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skShift|skAlt, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skShift|skAlt, testname);
|
|
sendText(socket, "\nEnd "+s+" With Shift+Alt\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Ctrl+Alt:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skCtrl|skAlt, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skCtrl|skAlt, testname);
|
|
sendText(socket, "\nEnd "+s+" With Ctrl+Alt\n", testname);
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
sendText(socket, "\n"+s+" With Shift+Ctrl+Alt:\n", testname);
|
|
sendKeyEvent(socket, "input", 0, i|skShift|skCtrl|skAlt, testname);
|
|
sendKeyEvent(socket, "up", 0, i|skShift|skCtrl|skAlt, testname);
|
|
sendText(socket, "\nEnd "+s+" With Shift+Ctrl+Alt\n", testname);
|
|
|
|
if (i>=istart)
|
|
sendTextFrame(socket, f);
|
|
|
|
// This is to allow server to process the input, and check that everything is still OK
|
|
sendTextFrame(socket, "status", testname);
|
|
getResponseMessage(socket, "status:", testname);
|
|
}
|
|
// sendTextFrame(socket, "saveas url=file:///tmp/emptyempty.odt format= options=");
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidateCalc()
|
|
{
|
|
const std::string testname = "tileInvalidateCalc ";
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket("empty.ods", _uri, testname);
|
|
|
|
std::string text = "Test. Now go 3 \"Enters\": Now after the enters, goes this text";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skNone, testname); // Send ordinary characters -> one tile invalidation for each
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
|
|
std::cerr << "Sending enters" << std::endl;
|
|
text = "\n\n\n";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skCtrl, testname); // Send 3 Ctrl+Enter -> 3 new pages; I see 3 tiles invalidated for each
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
|
|
text = "abcde";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket, ch, skNone, testname);
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidatePartCalc()
|
|
{
|
|
const std::string filename = "setclientpart.ods";
|
|
const std::string testname = "tileInvalidatePartCalc";
|
|
const std::string testname1 = testname + "-1 ";
|
|
const std::string testname2 = testname + "-2 ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL(filename, documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, testname1);
|
|
|
|
sendTextFrame(socket1, "setclientpart part=2", testname1);
|
|
assertResponseString(socket1, "setpart:", testname1);
|
|
sendTextFrame(socket1, "mouse type=buttondown x=1500 y=1500 count=1 buttons=1 modifier=0", testname1);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, testname2);
|
|
sendTextFrame(socket2, "setclientpart part=5", testname2);
|
|
assertResponseString(socket2, "setpart:", testname2);
|
|
sendTextFrame(socket2, "mouse type=buttondown x=1500 y=1500 count=1 buttons=1 modifier=0", testname2);
|
|
|
|
static const std::string text = "Some test";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket1, ch, skNone, testname);
|
|
sendChar(socket2, ch, skNone, testname);
|
|
|
|
const auto response1 = assertResponseString(socket1, "invalidatetiles:", testname1);
|
|
int value1;
|
|
LOOLProtocol::getTokenIntegerFromMessage(response1, "part", value1);
|
|
CPPUNIT_ASSERT_EQUAL(2, value1);
|
|
|
|
const auto response2 = assertResponseString(socket2, "invalidatetiles:", testname2);
|
|
int value2;
|
|
LOOLProtocol::getTokenIntegerFromMessage(response2, "part", value2);
|
|
CPPUNIT_ASSERT_EQUAL(5, value2);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidatePartImpress()
|
|
{
|
|
const std::string filename = "setclientpart.odp";
|
|
const std::string testname = "tileInvalidatePartImpress";
|
|
const std::string testname1 = testname + "-1 ";
|
|
const std::string testname2 = testname + "-2 ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL(filename, documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, testname1);
|
|
|
|
sendTextFrame(socket1, "setclientpart part=2", testname1);
|
|
assertResponseString(socket1, "setpart:", testname1);
|
|
sendTextFrame(socket1, "mouse type=buttondown x=1500 y=1500 count=1 buttons=1 modifier=0", testname1);
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, testname2);
|
|
sendTextFrame(socket2, "setclientpart part=5", testname2);
|
|
assertResponseString(socket2, "setpart:", testname2);
|
|
sendTextFrame(socket2, "mouse type=buttondown x=1500 y=1500 count=1 buttons=1 modifier=0", testname2);
|
|
|
|
// This should be short, as in odp the font is large and we leave the page otherwise.
|
|
static const std::string text = "Some test";
|
|
for (char ch : text)
|
|
{
|
|
sendChar(socket1, ch, skNone, testname);
|
|
sendChar(socket2, ch, skNone, testname);
|
|
|
|
const auto response1 = assertResponseString(socket1, "invalidatetiles:", testname1);
|
|
int value1;
|
|
LOOLProtocol::getTokenIntegerFromMessage(response1, "part", value1);
|
|
CPPUNIT_ASSERT_EQUAL(2, value1);
|
|
|
|
const auto response2 = assertResponseString(socket2, "invalidatetiles:", testname2);
|
|
int value2;
|
|
LOOLProtocol::getTokenIntegerFromMessage(response2, "part", value2);
|
|
CPPUNIT_ASSERT_EQUAL(5, value2);
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::checkTiles(std::shared_ptr<LOOLWebSocket>& socket, const std::string& docType, const std::string& name)
|
|
{
|
|
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;
|
|
|
|
// check total slides 10
|
|
sendTextFrame(socket, "status", name);
|
|
const auto response = assertResponseString(socket, "status:", name);
|
|
{
|
|
std::string line;
|
|
std::istringstream istr(response.substr(8));
|
|
std::getline(istr, line);
|
|
|
|
Poco::StringTokenizer tokens(line, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), tokens.count());
|
|
|
|
// Expected format is something like 'type= parts= current= width= height='.
|
|
const std::string 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")
|
|
{
|
|
// request tiles
|
|
std::cerr << "Requesting Impress tiles." << std::endl;
|
|
requestTiles(socket, currentPart, docWidth, docHeight, name);
|
|
}
|
|
|
|
// random setclientpart
|
|
std::srand(std::time(nullptr));
|
|
std::vector<int> vParts = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
|
std::random_shuffle(vParts.begin(), vParts.end());
|
|
int requests = 0;
|
|
for (int it : vParts)
|
|
{
|
|
if (currentPart != it)
|
|
{
|
|
// change part
|
|
const std::string text = Poco::format("setclientpart part=%d", it);
|
|
sendTextFrame(socket, text, name);
|
|
// Wait for the change to take effect otherwise we get invalidatetile
|
|
// which removes our next tile request subscription (expecting us to
|
|
// issue a new tile request as a response, which a real client would do).
|
|
assertResponseString(socket, "setpart:", name);
|
|
|
|
requestTiles(socket, it, docWidth, docHeight, name);
|
|
|
|
if (++requests >= 3)
|
|
{
|
|
// No need to test all parts.
|
|
break;
|
|
}
|
|
}
|
|
|
|
currentPart = it;
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::requestTiles(std::shared_ptr<LOOLWebSocket>& socket, const int part, const int docWidth, const int docHeight, const std::string& name)
|
|
{
|
|
// 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, name);
|
|
tile = assertResponseString(socket, "tile:", name);
|
|
// 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::testTileRequestByInvalidation()
|
|
{
|
|
const char* testname = "tileRequestByInvalidation ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// 1. use case: invalidation without having a valid visible area in wsd
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// Since we did not set client visible area wsd won't send tile
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("Not expected tile message arrived!", tile.empty());
|
|
|
|
// 2. use case: invalidation of one tile inside the client visible area
|
|
// Now set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-4005 y=0 width=50490 height=72300");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840");
|
|
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// Then sends the new tile which was invalidated inside the visible area
|
|
assertResponseString(socket, "tile:", testname);
|
|
}
|
|
|
|
void TileCacheTests::testTileRequestByZoom()
|
|
{
|
|
// By zoom the client requests all the tile of the visible area
|
|
// Server should push all these tiles to the network, so tiles-on-fly should be bigger than this count
|
|
|
|
const char* testname = "testTileRequestByZoom ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-2662 y=0 width=16000 height=9875");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3200 tiletwipheight=3200");
|
|
|
|
// Request all tile of the visible area (it happens by zoom)
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3200,6400,9600,12800,0,3200,6400,9600,12800,0,3200,6400,9600,12800,0,3200,6400,9600,12800 tileposy=0,0,0,0,0,3200,3200,3200,3200,3200,6400,6400,6400,6400,6400,9600,9600,9600,9600,9600 tilewidth=3200 tileheight=3200");
|
|
|
|
// Check that we get all the tiles without we send back the tileprocessed message
|
|
for (int i = 0; i < 20; ++i)
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("Did not get tile as expected!", !tile.empty());
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testTileWireIDHandling()
|
|
{
|
|
const char* testname = "testTileWireIDHandling ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-4005 y=0 width=50490 height=72300");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840");
|
|
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// For the first input wsd will send all invalidated tiles
|
|
int arrivedTiles = 0;
|
|
bool gotTile = false;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("We expect two tiles at least!", arrivedTiles > 1);
|
|
|
|
// Type an other character
|
|
sendChar(socket, 'x', skNone, testname);
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// For the second input wsd will send one tile, since some of them are indentical
|
|
arrivedTiles = 0;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, arrivedTiles);
|
|
}
|
|
|
|
void TileCacheTests::testTileProcessed()
|
|
{
|
|
// Test whether tileprocessed message removes the tiles from the internal tiles-on-fly list
|
|
const char* testname = "testTileProcessed ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-2662 y=0 width=10000 height=9000");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3200 tiletwipheight=3200");
|
|
|
|
// Request a lots of tiles (more than wsd can send once)
|
|
sendTextFrame(socket, "tilecombine part=0 width=256 height=256 tileposx=0,3200,6400,9600,12800,0,3200,6400,9600,12800,0,3200,6400,9600,12800,0,3200,6400,9600,12800,0,3200,6400,9600,12800 tileposy=0,0,0,0,0,3200,3200,3200,3200,3200,6400,6400,6400,6400,6400,9600,9600,9600,9600,9600,12800,12800,12800,12800,12800 tilewidth=3200 tileheight=3200");
|
|
|
|
std::vector<std::string> tileIDs;
|
|
int arrivedTile = 0;
|
|
bool gotTile = false;
|
|
do
|
|
{
|
|
std::string tile = getResponseString(socket, "tile:", testname);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
{
|
|
++arrivedTile;
|
|
|
|
// Store tileID, so we can send it back
|
|
Poco::StringTokenizer tokens(tile, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
std::string tileID = tokens[1].substr(std::string("part=").size()) + ":" +
|
|
tokens[4].substr(std::string("tileposx=").size()) + ":" +
|
|
tokens[5].substr(std::string("tileposy=").size()) + ":" +
|
|
tokens[6].substr(std::string("tileWidth=").size()) + ":" +
|
|
tokens[7].substr(std::string("tileHeight=").size());
|
|
tileIDs.push_back(tileID);
|
|
}
|
|
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("We expect two tiles at least!", arrivedTile > 1);
|
|
CPPUNIT_ASSERT_MESSAGE("We expect that wsd can't send all the tiles!", arrivedTile < 25);
|
|
|
|
for(std::string& tileID : tileIDs)
|
|
{
|
|
sendTextFrame(socket, "tileprocessed tile=" + tileID);
|
|
}
|
|
|
|
// Now we can get the remaining tiles
|
|
int arrivedTile2 = 0;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTile2;
|
|
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("We expect one tile at least!", arrivedTile2 > 1);
|
|
}
|
|
|
|
void TileCacheTests::testTileInvalidatedOutside()
|
|
{
|
|
// Test whether wsd sends us the tiles which are hanging out the visible area
|
|
const char* testname = "testTileInvalidatedOutside ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Type one character to trigger invalidation and get the invalidation rectangle
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
std::string sInvalidate = assertResponseString(socket, "invalidatetiles:", testname);
|
|
Poco::StringTokenizer tokens(sInvalidate, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
int y = std::stoi(tokens[3].substr(std::string("y=").size()));
|
|
int height = std::stoi(tokens[5].substr(std::string("height=").size()));
|
|
|
|
|
|
// Set client visible area to make it not having intersection with the invalidate rectangle, but having shared tiles
|
|
std::ostringstream oss;
|
|
oss << "clientvisiblearea x=0 y=" << (y + height + 100) << " width=50490 height=72300";
|
|
sendTextFrame(socket, oss.str());
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840");
|
|
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// Since the invalidation rectangle is outside the visible area
|
|
// wsd does not send a new tile even if some of the invalidated tiles
|
|
// are partly visible.
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
CPPUNIT_ASSERT_MESSAGE("Not expected tile message arrived!", tile.empty());
|
|
}
|
|
|
|
void TileCacheTests::testTileBeingRenderedHandling()
|
|
{
|
|
// The issue here was that we requested the tile of the same tile twice
|
|
// and so sometimes we got the same tile message twice from wsd.
|
|
const char* testname = "testTileBeingRenderedHandling ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-2662 y=0 width=16000 height=9875");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3200 tiletwipheight=3200");
|
|
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
// For the first input wsd will send all invalidated tiles
|
|
int arrivedTiles = 0;
|
|
bool gotTile = false;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("We expect two tiles at least!", arrivedTiles > 1);
|
|
|
|
// For the later inputs wsd will send one tile, since other ones are indentical
|
|
for(int i = 0; i < 5; ++i)
|
|
{
|
|
// Type an other character
|
|
sendChar(socket, 'x', skNone, testname);
|
|
assertResponseString(socket, "invalidatetiles:", testname);
|
|
|
|
arrivedTiles = 0;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname, 500);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, arrivedTiles);
|
|
|
|
sendTextFrame(socket, "tileprocessed tile=0:0:0:3200:3200");
|
|
}
|
|
}
|
|
|
|
void TileCacheTests::testWireIDFilteringOnWSDSide()
|
|
{
|
|
const char* testname = "testWireIDFilteringOnWSDSide ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket1 = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
// Set the client visible area
|
|
sendTextFrame(socket1, "clientvisiblearea x=-4005 y=0 width=50490 height=72300");
|
|
sendTextFrame(socket1, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840");
|
|
|
|
std::shared_ptr<LOOLWebSocket> socket2 = loadDocAndGetSocket(_uri, documentURL, testname, true);
|
|
// Set the client visible area
|
|
sendTextFrame(socket1, "clientvisiblearea x=-4005 y=0 width=50490 height=72300");
|
|
sendTextFrame(socket1, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3840 tiletwipheight=3840");
|
|
|
|
//1. First make the first client to trigger the kit to filter out tiles based on identical wireIDs
|
|
|
|
// Type one character to trigger invalidation
|
|
sendChar(socket1, 'x', skNone, testname);
|
|
|
|
// First wsd forwards the invalidation
|
|
assertResponseString(socket1, "invalidatetiles:", testname);
|
|
|
|
// For the first input wsd will send all invalidated tiles
|
|
int arrivedTiles = 0;
|
|
bool gotTile = false;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket1, "tile:", testname, 5000);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_MESSAGE("We expect two tiles at least!", arrivedTiles > 1);
|
|
|
|
// Type an other character
|
|
sendChar(socket1, 'x', skNone, testname);
|
|
assertResponseString(socket1, "invalidatetiles:", testname);
|
|
|
|
// For the second input wsd will send one tile, since other tiles are indentical
|
|
arrivedTiles = 0;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket1, "tile:", testname, 1000);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, arrivedTiles);
|
|
|
|
//2. Now request the same tiles by the other client (e.g. scroll to the same view)
|
|
|
|
sendTextFrame(socket2, "tilecombine part=0 width=256 height=256 tileposx=0,3840,7680 tileposy=0,0,0 tilewidth=3840 tileheight=3840");
|
|
|
|
// We expect three tiles sent to the second client
|
|
arrivedTiles = 0;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket2, "tile:", testname, 1000);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3, arrivedTiles);
|
|
|
|
// wsd should not send tiles messages for the first client
|
|
std::vector<char> tile = getResponseMessage(socket1, "tile:", testname, 1000);
|
|
CPPUNIT_ASSERT_MESSAGE("Not expected tile message arrived!", tile.empty());
|
|
}
|
|
|
|
void TileCacheTests::testLimitTileVersionsOnFly()
|
|
{
|
|
// We have an upper limit (2) for the versions of the same tile wsd send out
|
|
// without getting the tileprocessed message for the first tile message.
|
|
const char* testname = "testLimitTileVersionsOnFly ";
|
|
|
|
std::string documentPath, documentURL;
|
|
getDocumentPathAndURL("empty.odt", documentPath, documentURL, testname);
|
|
std::shared_ptr<LOOLWebSocket> socket = loadDocAndGetSocket(_uri, documentURL, testname);
|
|
|
|
// Set the client visible area
|
|
sendTextFrame(socket, "clientvisiblearea x=-2662 y=0 width=16000 height=9875");
|
|
sendTextFrame(socket, "clientzoom tilepixelwidth=256 tilepixelheight=256 tiletwipwidth=3200 tiletwipheight=3200");
|
|
|
|
// Type one character to trigger sending tiles
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// Handle all tiles send by wsd
|
|
bool getTileResp = false;
|
|
do
|
|
{
|
|
std::string tile = getResponseString(socket, "tile:", testname, 1000);
|
|
getTileResp = !tile.empty();
|
|
} while(getTileResp);
|
|
|
|
// Type an other character to trigger sending tiles
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
// Handle all tiles sent by wsd
|
|
do
|
|
{
|
|
std::string tile = getResponseString(socket, "tile:", testname, 1000);
|
|
getTileResp = !tile.empty();
|
|
} while(getTileResp);
|
|
|
|
// For the third invalidation wsd does not send the new tile since
|
|
// two versions of the same tile were already sent.
|
|
sendChar(socket, 'x', skNone, testname);
|
|
|
|
std::vector<char> tile1 = getResponseMessage(socket, "tile:", testname, 1000);
|
|
CPPUNIT_ASSERT_MESSAGE("Not expected tile message arrived!", tile1.empty());
|
|
|
|
// When the next tileprocessed message arrive with correct tileID
|
|
// wsd sends the delayed tile
|
|
sendTextFrame(socket, "tileprocessed tile=0:0:0:3200:3200");
|
|
|
|
int arrivedTiles = 0;
|
|
bool gotTile = false;
|
|
do
|
|
{
|
|
std::vector<char> tile = getResponseMessage(socket, "tile:", testname, 1000);
|
|
gotTile = !tile.empty();
|
|
if(gotTile)
|
|
++arrivedTiles;
|
|
} while(gotTile);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, arrivedTiles);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(TileCacheTests);
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|