/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * 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 #include #include #include #include #include #include #include #include #include namespace { std::string getFontList(const std::string& message, const std::string& testname) { Poco::JSON::Parser parser; const Poco::Dynamic::Var result = parser.parse(message); const auto& command = result.extract(); std::string text = command->get("commandName").toString(); LOK_ASSERT_EQUAL(std::string(".uno:CharFontName"), text); text = command->get("commandValues").toString(); return text; } } /// Test suite for closing, etc. class UnitClose : public UnitWSD { TestResult testCloseAfterClose(); TestResult testFontList(); TestResult testGraphicInvalidate(); TestResult testAlertAllUsers(); public: UnitClose(); void invokeWSDTest() override; }; UnitBase::TestResult UnitClose::testCloseAfterClose() { try { TST_LOG("Connecting and loading."); Poco::URI uri(helpers::getTestServerURI()); std::shared_ptr socketPoll = std::make_shared("ClosePoll"); socketPoll->startThread(); std::shared_ptr socket = helpers::loadDocAndGetSession(socketPoll, "hello.odt", uri, testname); // send normal socket shutdown TST_LOG("Disconnecting gracefully."); socket->asyncShutdown(); // 5 seconds timeout LOK_ASSERT_MESSAGE("Expected successful disconnection of the WebSocket", socket->waitForDisconnection(std::chrono::seconds(5))); // Verify that we get back a close frame. LOK_ASSERT_EQUAL(static_cast(Poco::Net::WebSocket::FRAME_OP_CLOSE), (socket->lastFlags() & Poco::Net::WebSocket::FRAME_OP_BITMASK)); } catch (const Poco::Exception& exc) { LOK_ASSERT_FAIL(exc.displayText()); } return TestResult::Ok; } UnitBase::TestResult UnitClose::testFontList() { try { // Load a document Poco::URI uri(helpers::getTestServerURI()); std::shared_ptr socketPoll = std::make_shared("ClosePoll"); socketPoll->startThread(); std::shared_ptr socket = helpers::loadDocAndGetSession(socketPoll, "setclientpart.odp", uri, testname); helpers::sendTextFrame(socket, "commandvalues command=.uno:CharFontName", testname); const std::vector response = helpers::getResponseMessage(socket, "commandvalues:", testname); LOK_ASSERT_MESSAGE("did not receive a commandvalues: message as expected", !response.empty()); std::stringstream streamResponse; std::copy(response.begin() + std::string("commandvalues:").length() + 1, response.end(), std::ostream_iterator(streamResponse)); LOK_ASSERT(!getFontList(streamResponse.str(), testname).empty()); } catch (const Poco::Exception& exc) { LOK_ASSERT_FAIL(exc.displayText()); } return TestResult::Ok; } UnitBase::TestResult UnitClose::testGraphicInvalidate() { try { // Load a document. Poco::URI uri(helpers::getTestServerURI()); std::shared_ptr socketPoll = std::make_shared("ClosePoll"); socketPoll->startThread(); std::shared_ptr socket = helpers::loadDocAndGetSession(socketPoll, "shape.ods", uri, testname); // Send click message helpers::sendTextFrame( socket, "mouse type=buttondown x=1035 y=400 count=1 buttons=1 modifier=0", testname); helpers::sendTextFrame( socket, "mouse type=buttonup x=1035 y=400 count=1 buttons=1 modifier=0", testname); helpers::getResponseString(socket, "graphicselection:", testname); // Drag & drop graphic helpers::sendTextFrame( socket, "mouse type=buttondown x=1035 y=400 count=1 buttons=1 modifier=0", testname); helpers::sendTextFrame(socket, "mouse type=move x=1035 y=450 count=1 buttons=1 modifier=0", testname); helpers::sendTextFrame( socket, "mouse type=buttonup x=1035 y=450 count=1 buttons=1 modifier=0", testname); const auto message = helpers::getResponseString(socket, "invalidatetiles:", testname); LOK_ASSERT_MESSAGE("Drag & Drop graphic invalidate all tiles", message.find("EMPTY") == std::string::npos); } catch (const Poco::Exception& exc) { LOK_ASSERT_FAIL(exc.displayText()); } return TestResult::Ok; } UnitBase::TestResult UnitClose::testAlertAllUsers() { // Load two documents, each in two sessions. Tell one session to fake a disk full // situation. Expect to get the corresponding error back in all sessions. static_assert(MAX_DOCUMENTS >= 2, "MAX_DOCUMENTS must be at least 2"); try { Poco::URI uri(helpers::getTestServerURI()); std::shared_ptr socketPoll = std::make_shared("ClosePoll"); socketPoll->startThread(); std::shared_ptr socket[4]; socket[0] = helpers::loadDocAndGetSession(socketPoll, "hello.odt", uri, testname); socket[1] = helpers::loadDocAndGetSession(socketPoll, "Example.odt", uri, testname); // Simulate disk full. helpers::sendTextFrame(socket[0], "uno .uno:fakeDiskFull", testname); // Assert that both clients get the error. for (int i = 0; i < 2; i++) { const std::string response = helpers::assertResponseString(socket[i], "error:", testname); StringVector tokens(StringVector::tokenize(response.substr(6), ' ')); std::string cmd; COOLProtocol::getTokenString(tokens, "cmd", cmd); LOK_ASSERT_EQUAL(std::string("internal"), cmd); std::string kind; COOLProtocol::getTokenString(tokens, "kind", kind); LOK_ASSERT_EQUAL(std::string("diskfull"), kind); } } catch (const Poco::Exception& exc) { LOK_ASSERT_FAIL(exc.displayText()); } return TestResult::Ok; } UnitClose::UnitClose() : UnitWSD("UnitClose") { constexpr std::chrono::minutes timeout_minutes(2); setTimeout(timeout_minutes); } void UnitClose::invokeWSDTest() { UnitBase::TestResult result = testCloseAfterClose(); if (result != TestResult::Ok) exitTest(result); result = testFontList(); if (result != TestResult::Ok) exitTest(result); result = testGraphicInvalidate(); if (result != TestResult::Ok) exitTest(result); result = testAlertAllUsers(); if (result != TestResult::Ok) exitTest(result); exitTest(TestResult::Ok); } UnitBase* unit_create_wsd(void) { return new UnitClose(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */