From 647e5f8936b683b6ca511b967fcb35f2cd1cf463 Mon Sep 17 00:00:00 2001 From: Ashod Nakashian Date: Sun, 30 Apr 2017 21:54:38 -0400 Subject: [PATCH] wsd: unittest to reproduce rendering issue in Calc The following scenario causes rendering failure where blank tiles are returned. 1. Load doc where the cursor is saved to a top cell. 2. Page down (typically several 100th row). 3. Load a new view to the same doc (do nothing else). 4. In the first view up-arrow to move cursor and invalidate. 5. New tile is rendered incorrectly. Change-Id: I06c7627d1b74d9e3be3e83d9d9a09cb5479ba660 Reviewed-on: https://gerrit.libreoffice.org/37129 Reviewed-by: Ashod Nakashian Tested-by: Ashod Nakashian --- test/helpers.hpp | 27 ++++++++++++++++++++++++++ test/httpwstest.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/test/helpers.hpp b/test/helpers.hpp index 70bf6e4c8..1b00b2e32 100644 --- a/test/helpers.hpp +++ b/test/helpers.hpp @@ -540,6 +540,33 @@ inline void sendText(std::shared_ptr& socket, const std::string& } } +inline std::vector getTileAndSave(std::shared_ptr& socket, + const std::string& req, + const std::string& filename, + const std::string& testname) +{ + std::cerr << testname << "Requesting: " << req << std::endl; + sendTextFrame(socket, req, testname); + + const auto tile = getResponseMessage(socket, "tile:", testname); + std::cerr << testname << " Tile PNG size: " << tile.size() << std::endl; + + const std::string firstLine = LOOLProtocol::getFirstLine(tile); + std::vector res(tile.begin() + firstLine.size() + 1, tile.end()); + std::stringstream streamRes; + std::copy(res.begin(), res.end(), std::ostream_iterator(streamRes)); + + if (!filename.empty()) + { + std::fstream outStream(filename, std::ios::out); + outStream.write(res.data(), res.size()); + outStream.close(); + std::cerr << testname << "Saved [" << firstLine << "] to [" << filename << "]" << std::endl; + } + + return res; +} + } #endif diff --git a/test/httpwstest.cpp b/test/httpwstest.cpp index 917a41dd3..e348a4293 100644 --- a/test/httpwstest.cpp +++ b/test/httpwstest.cpp @@ -92,6 +92,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture // CPPUNIT_TEST(testEditAnnotationWriter); // FIXME CPPUNIT_TEST(testInsertAnnotationCalc); CPPUNIT_TEST(testCalcEditRendering); + CPPUNIT_TEST(testCalcRenderAfterNewView); CPPUNIT_TEST(testFontList); CPPUNIT_TEST(testStateUnoCommandWriter); CPPUNIT_TEST(testStateUnoCommandCalc); @@ -146,6 +147,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture void testEditAnnotationWriter(); void testInsertAnnotationCalc(); void testCalcEditRendering(); + void testCalcRenderAfterNewView(); void testFontList(); void testStateUnoCommandWriter(); void testStateUnoCommandCalc(); @@ -1767,6 +1769,50 @@ void HTTPWSTest::testCalcEditRendering() } } +/// When a second view is loaded to a Calc doc, +/// the first stops rendering correctly. +/// This only happens at high rows. +void HTTPWSTest::testCalcRenderAfterNewView() +{ + const auto testname = "calcRenderAfterNewView "; + + // Load a doc with the cursor saved at a top row. + std::string documentPath, documentURL; + getDocumentPathAndURL("empty.ods", documentPath, documentURL, testname); + + auto socket = loadDocAndGetSocket(_uri, documentURL, testname); + + // Page Down until we get to the bottom of the doc. + for (int i = 0; i < 40; ++i) + { + sendTextFrame(socket, "key type=input char=0 key=1031", testname); + } + + // Wait for status due to doc resize. + assertResponseString(socket, "status:", testname); + + const auto req = "tilecombine part=0 width=256 height=256 tileposx=0 tileposy=253440 tilewidth=3840 tileheight=3840"; + + // Get tile. + const std::vector tile1 = getTileAndSave(socket, req, "/tmp/calc_render_orig.png", testname); + + + // Connect second client, which will load at the top. + std::cerr << testname << "Connecting second client." << std::endl; + auto socket2 = loadDocAndGetSocket(_uri, documentURL, testname); + + + // Up one row on the first view to trigger the bug. + std::cerr << testname << "Up." << std::endl; + sendTextFrame(socket, "key type=input char=0 key=1025", testname); + assertResponseString(socket, "invalidatetiles:", testname); // Up invalidates. + + // Get same tile again. + const std::vector tile2 = getTileAndSave(socket, req, "/tmp/calc_render_sec.png", testname); + + CPPUNIT_ASSERT(tile1 == tile2); +} + std::string HTTPWSTest::getFontList(const std::string& message) { Poco::JSON::Parser parser;