libreoffice-online/test/integration-http-server.cpp
Ashod Nakashian 25dee367d4 wsd: load the convert-to doc in callback
Since this a fake session that doesn't
have a client socket, we push the
messages directly into the ClientSession.
But since the DocBroker poll thread will
probably not be ready by then, there
is no child process and the other
document bits needed to load (or indeed
process any client messages).

So we defer all the fake messages in
a poll callback to insure they are done
in the correct order.

Change-Id: Id81dc4288b305829149e6e9c81d0f7da719c59ad
Reviewed-on: https://gerrit.libreoffice.org/35712
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2017-03-26 05:11:30 +00:00

268 lines
9.3 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/FilePartSource.h>
#include <Poco/Net/HTMLForm.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/PrivateKeyPassphraseHandler.h>
#include <Poco/Net/SSLManager.h>
#include <Poco/RegularExpression.h>
#include <Poco/StreamCopier.h>
#include <Poco/URI.h>
#include <cppunit/extensions/HelperMacros.h>
#include <Common.hpp>
#include "common/FileUtil.hpp"
#include <Util.hpp>
#include "countloolkits.hpp"
#include "helpers.hpp"
/// Tests the HTTP GET API of loolwsd.
class HTTPServerTest : public CPPUNIT_NS::TestFixture
{
const Poco::URI _uri;
CPPUNIT_TEST_SUITE(HTTPServerTest);
CPPUNIT_TEST(testDiscovery);
CPPUNIT_TEST(testLoleafletGet);
CPPUNIT_TEST(testLoleafletPost);
CPPUNIT_TEST(testScriptsAndLinksGet);
CPPUNIT_TEST(testScriptsAndLinksPost);
CPPUNIT_TEST(testConvertTo);
CPPUNIT_TEST_SUITE_END();
void testDiscovery();
void testLoleafletGet();
void testLoleafletPost();
void testScriptsAndLinksGet();
void testScriptsAndLinksPost();
void testConvertTo();
public:
HTTPServerTest()
: _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
}
~HTTPServerTest()
{
#if ENABLE_SSL
Poco::Net::uninitializeSSL();
#endif
}
void setUp()
{
testCountHowManyLoolkits();
}
void tearDown()
{
testNoExtraLoolKitsLeft();
}
};
void HTTPServerTest::testDiscovery()
{
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, "/hosting/discovery");
session->sendRequest(request);
Poco::Net::HTTPResponse response;
session->receiveResponse(response);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, response.getStatus());
CPPUNIT_ASSERT_EQUAL(std::string("text/xml"), response.getContentType());
}
void HTTPServerTest::testLoleafletGet()
{
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, "/loleaflet/dist/loleaflet.html?access_token=111111111");
Poco::Net::HTMLForm param(request);
session->sendRequest(request);
Poco::Net::HTTPResponse response;
std::istream& rs = session->receiveResponse(response);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, response.getStatus());
CPPUNIT_ASSERT_EQUAL(std::string("text/html"), response.getContentType());
std::string html;
Poco::StreamCopier::copyToString(rs, html);
CPPUNIT_ASSERT(html.find(param["access_token"]) != std::string::npos);
CPPUNIT_ASSERT(html.find(_uri.getHost()) != std::string::npos);
CPPUNIT_ASSERT(html.find(std::string(LOOLWSD_VERSION_HASH)) != std::string::npos);
}
void HTTPServerTest::testLoleafletPost()
{
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/loleaflet/dist/loleaflet.html");
Poco::Net::HTMLForm form;
form.set("access_token", "2222222222");
form.prepareSubmit(request);
std::ostream& ostr = session->sendRequest(request);
form.write(ostr);
Poco::Net::HTTPResponse response;
std::istream& rs = session->receiveResponse(response);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, response.getStatus());
std::string html;
Poco::StreamCopier::copyToString(rs, html);
CPPUNIT_ASSERT(html.find(form["access_token"]) != std::string::npos);
CPPUNIT_ASSERT(html.find(_uri.getHost()) != std::string::npos);
}
namespace
{
void assertHTTPFilesExist(const Poco::URI& uri, Poco::RegularExpression& expr, const std::string& html, const std::string& mimetype = std::string())
{
Poco::RegularExpression::MatchVec matches;
bool found = false;
for (int offset = 0; expr.match(html, offset, matches) > 0; offset = static_cast<int>(matches[0].offset + matches[0].length))
{
found = true;
CPPUNIT_ASSERT_EQUAL(2, (int)matches.size());
Poco::URI uriScript(html.substr(matches[1].offset, matches[1].length));
if (uriScript.getHost().empty())
{
std::string scriptString(uriScript.toString());
// ignore the branding bits, it's not an error when they aren't present.
if (scriptString.find("/branding.") != std::string::npos)
continue;
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(uri));
Poco::Net::HTTPRequest requestScript(Poco::Net::HTTPRequest::HTTP_GET, scriptString);
session->sendRequest(requestScript);
Poco::Net::HTTPResponse responseScript;
session->receiveResponse(responseScript);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, responseScript.getStatus());
if (!mimetype.empty())
CPPUNIT_ASSERT_EQUAL(mimetype, responseScript.getContentType());
}
}
CPPUNIT_ASSERT_MESSAGE("No match found", found);
}
}
void HTTPServerTest::testScriptsAndLinksGet()
{
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, "/loleaflet/dist/loleaflet.html");
session->sendRequest(request);
Poco::Net::HTTPResponse response;
std::istream& rs = session->receiveResponse(response);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, response.getStatus());
std::string html;
Poco::StreamCopier::copyToString(rs, html);
Poco::RegularExpression script("<script.*?src=\"(.*?)\"");
assertHTTPFilesExist(_uri, script, html, "application/javascript");
Poco::RegularExpression link("<link.*?href=\"(.*?)\"");
assertHTTPFilesExist(_uri, link, html);
}
void HTTPServerTest::testScriptsAndLinksPost()
{
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/loleaflet/dist/loleaflet.html");
std::string body;
request.setContentLength((int) body.length());
session->sendRequest(request) << body;
Poco::Net::HTTPResponse response;
std::istream& rs = session->receiveResponse(response);
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTP_OK, response.getStatus());
std::string html;
Poco::StreamCopier::copyToString(rs, html);
Poco::RegularExpression script("<script.*?src=\"(.*?)\"");
assertHTTPFilesExist(_uri, script, html, "application/javascript");
Poco::RegularExpression link("<link.*?href=\"(.*?)\"");
assertHTTPFilesExist(_uri, link, html);
}
void HTTPServerTest::testConvertTo()
{
const auto srcPath = FileUtil::getTempFilePath(TDOC, "hello.odt", "convertTo_");
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
session->setTimeout(Poco::Timespan(2, 0)); // 2 seconds.
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/lool/convert-to");
Poco::Net::HTMLForm form;
form.setEncoding(Poco::Net::HTMLForm::ENCODING_MULTIPART);
form.set("format", "txt");
form.addPart("data", new Poco::Net::FilePartSource(srcPath));
form.prepareSubmit(request);
// If this results in a Poco::Net::ConnectionRefusedException, loolwsd is not running.
form.write(session->sendRequest(request));
Poco::Net::HTTPResponse response;
std::stringstream actualStream;
// receiveResponse() resulted in a Poco::Net::NoMessageException.
std::istream& responseStream = session->receiveResponse(response);
Poco::StreamCopier::copyStream(responseStream, actualStream);
std::ifstream fileStream(TDOC "/hello.txt");
std::stringstream expectedStream;
expectedStream << fileStream.rdbuf();
// Remove the temp files.
FileUtil::removeFile(srcPath);
// In some cases the result is prefixed with (the UTF-8 encoding of) the Unicode BOM
// (U+FEFF). Skip that.
std::string actualString = actualStream.str();
if (actualString.size() > 3 && actualString[0] == '\xEF' && actualString[1] == '\xBB' && actualString[2] == '\xBF')
actualString = actualString.substr(3);
CPPUNIT_ASSERT_EQUAL(expectedStream.str(), actualString);
}
CPPUNIT_TEST_SUITE_REGISTRATION(HTTPServerTest);
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */