add a test for joining doc and disconnecting
a normal case, where user#2 joins the document successfully and then their connection closes; where the remaining client gets the notification that there is only one client in the session. an abnormal case, failing test currently disabled, where user#2 joins the document, "load url" is launched, but the connection is immediately dropped; the other client gets a notification that a user has joined to make it a 2 user session, but no notification that the user has dropped. Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com> Change-Id: I8271fb3d4def917acdff0fae6a3a52b5d02ef7afpull/8972/head
parent
8b558a2372
commit
a6b3961c50
|
@ -86,6 +86,7 @@ all_la_unit_tests = \
|
|||
unit-prefork.la \
|
||||
unit-bad-doc-load.la \
|
||||
unit-hosting.la \
|
||||
unit-join-disconnect.la \
|
||||
unit-timeout.la \
|
||||
unit-base.la
|
||||
# unit-admin.la
|
||||
|
@ -211,6 +212,8 @@ unit_copy_paste_la_LIBADD = $(CPPUNIT_LIBS)
|
|||
unit_copy_paste_writer_la_SOURCES = UnitCopyPasteWriter.cpp
|
||||
unit_copy_paste_writer_la_LIBADD = $(CPPUNIT_LIBS)
|
||||
unit_convert_la_SOURCES = UnitConvert.cpp
|
||||
unit_join_disconnect_la_SOURCES = UnitJoinDisconnect.cpp
|
||||
unit_join_disconnect_la_LIBADD = $(CPPUNIT_LIBS)
|
||||
unit_timeout_la_SOURCES = UnitTimeout.cpp
|
||||
unit_timeout_la_LIBADD = $(CPPUNIT_LIBS)
|
||||
unit_prefork_la_SOURCES = UnitPrefork.cpp
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* Copyright the Collabora Online contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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 "lokassert.hpp"
|
||||
#include "Unit.hpp"
|
||||
#include <WopiTestServer.hpp>
|
||||
#include <Log.hpp>
|
||||
#include <helpers.hpp>
|
||||
#include <wsd/ClientSession.hpp>
|
||||
|
||||
#include <Poco/Net/HTTPRequest.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
/// This is to test that dropping connection is seen as leaving the document
|
||||
class SecondJoinQuit : public WopiTestServer
|
||||
{
|
||||
STATE_ENUM(Phase, LoadUser1, WaitUser1Loaded, User1Loaded, LoadUser2, WaitUser2Loaded, User2Loaded, DropUser2, ModifyDoc, Done) _phase;
|
||||
|
||||
bool _earlyQuit;
|
||||
|
||||
std::size_t _checkFileInfoCount;
|
||||
std::size_t _viewCount;
|
||||
std::size_t _viewsActive;
|
||||
|
||||
public:
|
||||
SecondJoinQuit(const std::string& name, bool earlyQuit)
|
||||
: WopiTestServer(name)
|
||||
, _phase(Phase::LoadUser1)
|
||||
, _earlyQuit(earlyQuit)
|
||||
, _checkFileInfoCount(0)
|
||||
, _viewCount(0)
|
||||
, _viewsActive(0)
|
||||
{
|
||||
}
|
||||
|
||||
void configCheckFileInfo(const Poco::Net::HTTPRequest& /*request*/,
|
||||
Poco::JSON::Object::Ptr& fileInfo) override
|
||||
{
|
||||
const bool firstView = _checkFileInfoCount++ == 0;
|
||||
|
||||
LOG_TST("CheckFileInfo: " << (firstView ? "User#1" : "User#2"));
|
||||
|
||||
fileInfo->set("UserCanWrite", "true");
|
||||
}
|
||||
|
||||
bool onFilterSendWebSocketMessage(const char* data, const std::size_t len,
|
||||
const WSOpCode /* code */, const bool /* flush */,
|
||||
int& /*unitReturn*/) override
|
||||
{
|
||||
const std::string message(data, len);
|
||||
|
||||
if (message.starts_with("viewinfo:"))
|
||||
{
|
||||
Poco::JSON::Parser parser0;
|
||||
Poco::JSON::Array::Ptr array = parser0.parse(message.substr(9)).extract<Poco::JSON::Array::Ptr>();
|
||||
_viewsActive = array->size();
|
||||
if (_phase == Phase::Done && _viewsActive == 1)
|
||||
passTest("View disconnection seen");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void onDocBrokerViewLoaded(const std::string&,
|
||||
const std::shared_ptr<ClientSession>& session) override
|
||||
{
|
||||
LOG_TST("View #" << _viewCount + 1 << " [" << session->getName() << "] loaded");
|
||||
|
||||
++_viewCount;
|
||||
|
||||
if (_viewCount == 1 && _phase == Phase::WaitUser1Loaded)
|
||||
TRANSITION_STATE(_phase, Phase::User1Loaded);
|
||||
|
||||
if (_viewCount == 2 && _phase == Phase::WaitUser2Loaded)
|
||||
TRANSITION_STATE(_phase, Phase::User2Loaded);
|
||||
}
|
||||
|
||||
void invokeWSDTest() override
|
||||
{
|
||||
switch (_phase)
|
||||
{
|
||||
case Phase::LoadUser1:
|
||||
{
|
||||
// Always transition before issuing commands.
|
||||
TRANSITION_STATE(_phase, Phase::WaitUser1Loaded);
|
||||
|
||||
LOG_TST("Creating first connection");
|
||||
initWebsocket("/wopi/files/0?access_token=anything");
|
||||
|
||||
LOG_TST("Loading first view");
|
||||
WSD_CMD_BY_CONNECTION_INDEX(0, "load url=" + getWopiSrc());
|
||||
break;
|
||||
}
|
||||
case Phase::User1Loaded:
|
||||
{
|
||||
TRANSITION_STATE(_phase, Phase::LoadUser2);
|
||||
break;
|
||||
}
|
||||
case Phase::LoadUser2:
|
||||
{
|
||||
if (!_earlyQuit)
|
||||
{
|
||||
// normal case, user 2 loads then then quits after
|
||||
// they have joined
|
||||
TRANSITION_STATE(_phase, Phase::WaitUser2Loaded);
|
||||
}
|
||||
else
|
||||
{
|
||||
// abnormal case, user 2 loses connection right
|
||||
// after launching their load
|
||||
TRANSITION_STATE(_phase, Phase::DropUser2);
|
||||
}
|
||||
|
||||
LOG_TST("Creating second connection");
|
||||
addWebSocket();
|
||||
|
||||
LOG_TST("Loading second view");
|
||||
WSD_CMD_BY_CONNECTION_INDEX(1, "load url=" + getWopiSrc());
|
||||
break;
|
||||
}
|
||||
case Phase::User2Loaded:
|
||||
{
|
||||
TRANSITION_STATE(_phase, Phase::DropUser2);
|
||||
break;
|
||||
}
|
||||
case Phase::DropUser2:
|
||||
{
|
||||
TRANSITION_STATE(_phase, Phase::ModifyDoc);
|
||||
|
||||
LOG_TST("Disconnecting first view right after load start");
|
||||
deleteSocketAt(1);
|
||||
break;
|
||||
}
|
||||
case Phase::ModifyDoc:
|
||||
{
|
||||
TRANSITION_STATE(_phase, Phase::Done);
|
||||
|
||||
// Modify the document.
|
||||
LOG_TST("Modifying");
|
||||
WSD_CMD_BY_CONNECTION_INDEX(0, "key type=input char=97 key=0");
|
||||
WSD_CMD_BY_CONNECTION_INDEX(0, "key type=up char=0 key=512");
|
||||
break;
|
||||
}
|
||||
case Phase::WaitUser1Loaded:
|
||||
case Phase::WaitUser2Loaded:
|
||||
case Phase::Done:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SecondJoinQuitNormal : public SecondJoinQuit
|
||||
{
|
||||
public:
|
||||
SecondJoinQuitNormal()
|
||||
: SecondJoinQuit("SecondJoinQuitNormal", false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
UnitBase** unit_create_wsd_multi(void)
|
||||
{
|
||||
return new UnitBase* [2]
|
||||
{
|
||||
new SecondJoinQuitNormal(), nullptr
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* In this case, we are currently failing.
|
||||
|
||||
We have one user connected, the 2nd user join, and immediately drop
|
||||
connection after "load" is dispatched. While in the normal case we wait
|
||||
until the 2nd user join has completed, and then close the connection.
|
||||
|
||||
In both cases we receive:
|
||||
|
||||
ToClient-007: Send: [viewinfo: [{"id":4,...},
|
||||
{"id":5,...}]]| common/Session.cpp:62
|
||||
|
||||
so two users are seen as joined, but in the 2nd case we don't get a
|
||||
follow up indicating that the 2nd user has dropped.
|
||||
*/
|
||||
class SecondJoinQuitEarly : public SecondJoinQuit
|
||||
{
|
||||
public:
|
||||
SecondJoinQuitEarly()
|
||||
: SecondJoinQuit("SecondJoinQuitNormal", true)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
UnitBase** unit_create_wsd_multi(void)
|
||||
{
|
||||
return new UnitBase* [3]
|
||||
{
|
||||
new SecondJoinQuitNormal(), new SecondJoinQuitEarly(), nullptr
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
Loading…
Reference in New Issue