[Libreoffice-commits] online.git: loolwsd/test
Henry Castro
hcastro at collabora.com
Thu Apr 21 01:15:26 UTC 2016
loolwsd/test/Makefile.am | 2
loolwsd/test/httpcrashtest.cpp | 294 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 295 insertions(+), 1 deletion(-)
New commits:
commit 11fbb33b5694dae57cbb29801cc63f072d5e6f61
Author: Henry Castro <hcastro at collabora.com>
Date: Wed Apr 20 21:14:51 2016 -0400
loolwsd: test: simulate lokit crash test
diff --git a/loolwsd/test/Makefile.am b/loolwsd/test/Makefile.am
index 98d3f3f..d5ec9b9 100644
--- a/loolwsd/test/Makefile.am
+++ b/loolwsd/test/Makefile.am
@@ -14,7 +14,7 @@ AM_LDFLAGS = -module $(MAGIC_TO_FORCE_SHLIB_CREATION)
AM_CPPFLAGS = -pthread -I$(top_srcdir)
test_CPPFLAGS = -DTDOC=\"$(top_srcdir)/test/data\"
-test_SOURCES = WhiteBoxTests.cpp httpposttest.cpp httpwstest.cpp test.cpp ../LOOLProtocol.cpp
+test_SOURCES = WhiteBoxTests.cpp httpposttest.cpp httpwstest.cpp httpcrashtest.cpp test.cpp ../LOOLProtocol.cpp
test_LDADD = $(CPPUNIT_LIBS)
# unit test modules:
diff --git a/loolwsd/test/httpcrashtest.cpp b/loolwsd/test/httpcrashtest.cpp
new file mode 100644
index 0000000..63d2c87
--- /dev/null
+++ b/loolwsd/test/httpcrashtest.cpp
@@ -0,0 +1,294 @@
+/* -*- 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/DirectoryIterator.h>
+#include <Poco/Dynamic/Var.h>
+#include <Poco/FileStream.h>
+#include <Poco/JSON/JSON.h>
+#include <Poco/JSON/Parser.h>
+#include <Poco/Net/AcceptCertificateHandler.h>
+#include <Poco/Net/HTTPClientSession.h>
+#include <Poco/Net/HTTPRequest.h>
+#include <Poco/Net/HTTPResponse.h>
+#include <Poco/Net/HTTPSClientSession.h>
+#include <Poco/Net/InvalidCertificateHandler.h>
+#include <Poco/Net/NetException.h>
+#include <Poco/Net/PrivateKeyPassphraseHandler.h>
+#include <Poco/Net/SSLManager.h>
+#include <Poco/Net/Socket.h>
+#include <Poco/Net/WebSocket.h>
+#include <Poco/Path.h>
+#include <Poco/StreamCopier.h>
+#include <Poco/StringTokenizer.h>
+#include <Poco/Thread.h>
+#include <Poco/URI.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <Common.hpp>
+#include <UserMessages.hpp>
+#include <Util.hpp>
+#include <LOOLProtocol.hpp>
+
+/// Tests the HTTP WebSocket API of loolwsd. The server has to be started manually before running this test.
+class HTTPCrashTest : public CPPUNIT_NS::TestFixture
+{
+ const Poco::URI _uri;
+ Poco::Net::HTTPResponse _response;
+
+ CPPUNIT_TEST_SUITE(HTTPCrashTest);
+
+ CPPUNIT_TEST(testCrashKit);
+
+ CPPUNIT_TEST_SUITE_END();
+
+ void testCrashKit();
+
+ static
+ void sendTextFrame(Poco::Net::WebSocket& socket, const std::string& string);
+
+ static
+ bool isDocumentLoaded(Poco::Net::WebSocket& socket);
+
+ std::shared_ptr<Poco::Net::WebSocket>
+ connectLOKit(Poco::Net::HTTPRequest& request,
+ Poco::Net::HTTPResponse& response);
+
+public:
+ HTTPCrashTest()
+#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 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
+ ~HTTPCrashTest()
+ {
+ Poco::Net::uninitializeSSL();
+ }
+#endif
+
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+};
+
+void HTTPCrashTest::testCrashKit()
+{
+ try
+ {
+ int bytes;
+ int flags;
+ char buffer[READ_BUFFER_SIZE];
+
+ // Load a document and get its status.
+ const std::string documentPath = Util::getTempFilePath(TDOC, "hello.odt");
+ const std::string documentURL = "file://" + Poco::Path(documentPath).makeAbsolute().toString();
+
+ Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
+ Poco::Net::WebSocket socket = *connectLOKit(request, _response);
+
+ sendTextFrame(socket, "load url=" + documentURL);
+ sendTextFrame(socket, "status");
+ CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket));
+
+ // simulate crash all lokit process
+ for (auto it = Poco::DirectoryIterator(std::string("/proc")); it != Poco::DirectoryIterator(); ++it)
+ {
+ try
+ {
+ Poco::Path procEntry = it.path();
+ const std::string& fileName = procEntry.getFileName();
+ int pid;
+ std::size_t endPos = 0;
+ try
+ {
+ pid = std::stoi(fileName, &endPos);
+ }
+ catch (const std::invalid_argument&)
+ {
+ pid = 0;
+ }
+ if (pid > 1 && endPos == fileName.length())
+ {
+ const std::string killLOKit = "kill -9 " + std::to_string(pid);
+ Poco::FileInputStream stat(procEntry.toString() + "/stat");
+ std::string statString;
+ Poco::StreamCopier::copyToString(stat, statString);
+ Poco::StringTokenizer tokens(statString, " ");
+ if (tokens.count() > 3 && tokens[1] == "(loolkit)")
+ {
+ std::system(killLOKit.c_str());
+ }
+ }
+ }
+ catch (const Poco::Exception&)
+ {
+ }
+ }
+
+ // 5 seconds timeout
+ socket.setReceiveTimeout(5000000);
+
+ // receive close frame handshake
+ do
+ {
+ bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+ }
+ while ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
+
+ // respond close frame
+ socket.shutdown();
+ // no more messages is received.
+ bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+ std::string received(buffer);
+ CPPUNIT_ASSERT_EQUAL(0, bytes);
+ CPPUNIT_ASSERT_EQUAL(0, flags);
+ }
+ catch (const Poco::Exception& exc)
+ {
+ CPPUNIT_FAIL(exc.displayText());
+ }
+}
+
+void HTTPCrashTest::sendTextFrame(Poco::Net::WebSocket& socket, const std::string& string)
+{
+ socket.sendFrame(string.data(), string.size());
+}
+
+bool HTTPCrashTest::isDocumentLoaded(Poco::Net::WebSocket& ws)
+{
+ bool isLoaded = false;
+ try
+ {
+ int flags;
+ int bytes;
+ int retries = 30;
+ const Poco::Timespan waitTime(1000000);
+
+ ws.setReceiveTimeout(0);
+ std::cout << "==> isDocumentLoaded\n";
+ do
+ {
+ char buffer[READ_BUFFER_SIZE];
+
+ if (ws.poll(waitTime, Poco::Net::Socket::SELECT_READ))
+ {
+ bytes = ws.receiveFrame(buffer, sizeof(buffer), flags);
+ std::cout << "Got " << bytes << " bytes, flags: " << std::hex << flags << std::dec << '\n';
+ if (bytes > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE)
+ {
+ std::cout << "Received message: " << LOOLProtocol::getAbbreviatedMessage(buffer, bytes) << '\n';
+ const std::string line = LOOLProtocol::getFirstLine(buffer, bytes);
+ const std::string prefixIndicator = "statusindicatorfinish:";
+ const std::string prefixStatus = "status:";
+ if (line.find(prefixIndicator) == 0 || line.find(prefixStatus) == 0)
+ {
+ isLoaded = true;
+ 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);
+ }
+ catch (const Poco::Net::WebSocketException& exc)
+ {
+ std::cout << exc.message();
+ }
+
+ return isLoaded;
+}
+
+// Connecting to a Kit process is managed by document broker, that it does several
+// jobs to establish the bridge connection between the Client and Kit process,
+// The result, it is mostly time outs to get messages in the unit test and it could fail.
+// connectLOKit ensures the websocket is connected to a kit process.
+
+std::shared_ptr<Poco::Net::WebSocket>
+HTTPCrashTest::connectLOKit(Poco::Net::HTTPRequest& request,
+ Poco::Net::HTTPResponse& response)
+{
+ int flags;
+ int received = 0;
+ int retries = 3;
+ bool ready = false;
+ char buffer[READ_BUFFER_SIZE];
+ const std::string success("ready");
+ std::shared_ptr<Poco::Net::WebSocket> ws;
+
+ do
+ {
+#if ENABLE_SSL
+ Poco::Net::HTTPSClientSession session(_uri.getHost(), _uri.getPort());
+#else
+ Poco::Net::HTTPClientSession session(_uri.getHost(), _uri.getPort());
+#endif
+ ws = std::make_shared<Poco::Net::WebSocket>(session, request, response);
+
+ do
+ {
+ try
+ {
+ received = ws->receiveFrame(buffer, sizeof(buffer), flags);
+ if (received > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE)
+ {
+ const std::string message = LOOLProtocol::getFirstLine(buffer, received);
+ std::cerr << message << std::endl;
+ if (message.find(success) != std::string::npos)
+ {
+ ready = true;
+ break;
+ }
+ }
+ }
+ catch (const Poco::TimeoutException& exc)
+ {
+ std::cout << exc.displayText();
+ }
+ catch(...)
+ {
+ throw;
+ }
+ }
+ while (received > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
+ }
+ while (retries-- && !ready);
+
+ if (!ready)
+ throw Poco::Net::WebSocketException("Failed to connect to lokit process", Poco::Net::WebSocket::WS_ENDPOINT_GOING_AWAY);
+
+ return ws;
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HTTPCrashTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list