Commit 3046b7d8 authored by Krzysztof Nowicki's avatar Krzysztof Nowicki Committed by Laurent Montel
Browse files

Add initial server busy test



The EWS server uses a throttling mechanism to avoid abuse. This
mechanism can often engage when performing a full sync of a large
folder. This test aims at simulating this behaviour.

Initially a test case for the initial server connection is
implemented. Additional test cases will be added for occurence of this
error during different operations of the EWS resource.
Signed-off-by: Krzysztof Nowicki's avatarKrzysztof Nowicki <krissn@op.pl>
parent b45bedef
......@@ -33,4 +33,5 @@ add_subdirectory(unittests)
add_subdirectory(fakeserver)
if (KDEPIM_RUN_AKONADI_TEST)
add_akonadi_isolated_test_advanced(ewstest.cpp "${isolatestestcommon_RSRCS}" "isolatedtestcommon")
add_akonadi_isolated_test_advanced(serverbusytest.cpp "${isolatestestcommon_RSRCS}" "isolatedtestcommon")
endif()
......@@ -10,4 +10,7 @@
<file alias="unsubscribe">resources/unsubscribe.xq</file>
<file alias="getfolder-validateids">resources/getfolder-validateids.xq</file>
</qresource>
<qresource prefix="/xml">
<file alias="errorserverbusy">resources/errorserverbusy.xml</file>
</qresource>
</RCC>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:e="http://schemas.microsoft.com/exchange/services/2006/errors">
<soap:Header>
<t:ServerVersionInfo MajorVersion="15" MinorVersion="01" MajorBuildNumber="225" MinorBuildNumber="042" />
</soap:Header><soap:Body>
<soap:Fault>
<faultcode>t:ErrorServerBusy</faultcode>
<faultstring>The server cannot service this request right now. Try again later.</faultstring>
<detail>
<e:ResponseCode>ErrorServerBusy</e:ResponseCode>
<e:Message>The server cannot service this request right now. Try again later.</e:Message>
<t:MessageXml>
<t:Value Name="Policy">MaxConcurrency</t:Value>
<t:Value Name="MaxConcurrencyLimit">27</t:Value>
<t:Value Name="ErrorMessage">This operation exceeds the throttling budget for policy part 'MaxConcurrency', policy value '27', Budget type: 'Ews'. Suggested backoff time 0 ms.</t:Value>
</t:MessageXml>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
/*
Copyright (C) 2019 Krzysztof Nowicki <krissn@op.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <AkonadiCore/AgentInstanceCreateJob>
#include <AkonadiCore/AgentManager>
#include <AkonadiCore/CollectionFetchScope>
#include <AkonadiCore/Control>
#include <AkonadiCore/Monitor>
#include <AkonadiCore/SpecialCollectionAttribute>
#include <qtest_akonadi.h>
#include "ewsresourceinterface.h"
#include "ewssettings.h"
#include "ewswallet.h"
#include "fakeewsserverthread.h"
#include "isolatedtestbase.h"
#include "statemonitor.h"
class BasicTest : public IsolatedTestBase
{
Q_OBJECT
public:
explicit BasicTest(QObject *parent = nullptr);
~BasicTest() override;
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void busyInit();
private:
QScopedPointer<TestAgentInstance> mTestInstance;
};
QTEST_AKONADIMAIN(BasicTest)
using namespace Akonadi;
constexpr int DesiredStateTimeoutMs = 200000;
BasicTest::BasicTest(QObject *parent)
: IsolatedTestBase(parent)
{
}
BasicTest::~BasicTest()
{
}
void BasicTest::initTestCase()
{
init();
mTestInstance.reset(new TestAgentInstance(QStringLiteral("http://127.0.0.1:%1/EWS/Exchange.asmx").arg(mFakeServerThread->portNumber())));
QVERIFY(mTestInstance->isValid());
mTestInstance->resourceInterface().setInitialReconnectTimeout(2);
}
void BasicTest::cleanupTestCase()
{
cleanup();
}
void BasicTest::busyInit()
{
bool requestTriggered = false;
mFakeServerThread->setOverrideReplyCallback([&](const QString &, QXmlResultItems &, const QXmlNamePool &) {
requestTriggered = true;
return FakeEwsServer::DialogEntry::HttpResponse(IsolatedTestBase::loadResourceAsString(QStringLiteral(":/xml/errorserverbusy")), 200);
});
QEventLoop loop;
enum { InitialOffline, InitialOnline, BusyOffline, RetryOnline, RetryOffline } instanceState = InitialOffline;
connect(AgentManager::self(), &AgentManager::instanceOnline, this, [&](const AgentInstance &_instance, bool online) {
if (_instance.identifier() == mTestInstance->identifier()) {
switch (instanceState) {
case InitialOffline:
QVERIFY(online);
if (online) {
qDebug() << "Initial resource online state reached";
instanceState = InitialOnline;
}
break;
case InitialOnline:
if (!online && requestTriggered) {
qDebug() << "Resource state changed to offline after busy response";
instanceState = BusyOffline;
requestTriggered = false;
}
break;
case BusyOffline:
QVERIFY(online);
if (online) {
qDebug() << "Resource online after retry";
instanceState = RetryOnline;
}
break;
case RetryOnline:
if (!online) {
qDebug() << "Resource state changed to offline after busy response";
instanceState = RetryOffline;
loop.exit(0);
}
break;
default:
break;
}
}
});
QVERIFY(mTestInstance->setOnline(true, true));
QTimer timer;
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, this, [&]() {
qWarning() << "Timeout waiting for desired resource online state.";
loop.exit(1);
});
timer.start(DesiredStateTimeoutMs);
QCOMPARE(loop.exec(), 0);
}
#include "serverbusytest.moc"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment