1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/test/persistence/offlinemsgengine_test.cpp

195 lines
6.2 KiB
C++
Raw Normal View History

/*
Copyright © 2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#include "src/core/core.h"
#include "src/model/friend.h"
#include "src/model/status.h"
#include "src/persistence/offlinemsgengine.h"
#include <QtTest/QtTest>
struct MockFriendMessageSender : public QObject, public ICoreFriendMessageSender
{
Q_OBJECT
public:
MockFriendMessageSender(Friend* f)
chore: Various code cleanups. * Reorder class data members and/or constructor initialisers to match, reducing confusion about when members will be initialised. * Remove (most) unused variables. Not removed: some global variables with `TODO(sudden6)` on them for using them in the future. I don't know how far into the future sudden6 wants to use them, so I left them there for now. * Distinguish different bootstrap nodes in the logs by index in the bootstrap node list. Originally, we used to log the address/port of the node we're bootstrapping to. This was removed out of privacy concerns (even though the bootstrap nodes are public). This made the logs much less useful when debugging why the client isn't connecting. Having indices makes it easier to see that different nodes are being selected, and makes it possible to determine which node was selected. * Explicitly cast unused results of Tox API functions to `void` when all we want is to know whether the function succeeds or not. * Don't try to `#include <unistd.h>` on Windows. It does not exist on MSVC. * Remove extra `;` after function definitions. * Remove reference indirection of QJsonValueRef, since a copy of that ref (small pointer-like object) has to be made anyway when iterating over QJsonArrays. * Make some file-scope global state `static`. * Use `nullptr` instead of `NULL`. * Add `#if DESKTOP_NOTIFICATIONS` around the code that implements desktop notifications, so it becomes a bit easier to compile everything with a single compiler command - useful for manually running static analysers. * Fix an error on MSVC where `disconnect` is looked up to be a non-static member function and the `this` capture is missing. * Consistently use `struct` and `class` tags for types. * Use references in ranged-for where it reduces copies. * Move private static data members out of the Style class and into file-local scope. There is no need for them to be in the class. Also marked them `const` where possible. * Removed unused lambda capture. * Ensure qTox can compile under NDEBUG with `-Wunused-variable` by inlining the unused variable into the `assert` that was its only target. * Minor reformatting in core_test.cpp.
2020-04-16 23:59:29 +08:00
: f(f){}
bool sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt) override
{
return false;
}
bool sendMessage(uint32_t friendId, const QString& message, ReceiptNum& receipt) override
{
if (Status::isOnline(f->getStatus())) {
receipt.get() = receiptNum++;
if (!dropReceipts) {
msgs.push_back(message);
emit receiptReceived(receipt);
}
numMessagesSent++;
} else {
numMessagesFailed++;
}
return Status::isOnline(f->getStatus());
}
signals:
void receiptReceived(ReceiptNum receipt);
public:
Friend* f;
bool dropReceipts = false;
size_t numMessagesSent = 0;
size_t numMessagesFailed = 0;
int receiptNum = 0;
std::vector<QString> msgs;
};
class TestOfflineMsgEngine : public QObject
{
Q_OBJECT
private slots:
void testReceiptResolution();
void testOfflineFriend();
void testSentUnsentCoordination();
void testCallback();
};
class OfflineMsgEngineFixture
{
public:
OfflineMsgEngineFixture()
: f(0, ToxPk(QByteArray(32, 0)))
, friendMessageSender(&f)
, offlineMsgEngine(&f, &friendMessageSender)
{
f.setStatus(Status::Status::Online);
QObject::connect(&friendMessageSender, &MockFriendMessageSender::receiptReceived,
&offlineMsgEngine, &OfflineMsgEngine::onReceiptReceived);
}
Friend f;
MockFriendMessageSender friendMessageSender;
OfflineMsgEngine offlineMsgEngine;
};
void completionFn() {}
void TestOfflineMsgEngine::testReceiptResolution()
{
OfflineMsgEngineFixture fixture;
Message msg{false, QString(), QDateTime()};
ReceiptNum receipt;
fixture.friendMessageSender.sendMessage(0, msg.content, receipt);
fixture.offlineMsgEngine.addSentMessage(receipt, msg, completionFn);
// We should have no offline messages to deliver if we resolved our receipt
// correctly
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
QVERIFY(fixture.friendMessageSender.numMessagesSent == 1);
// If we drop receipts we should keep trying to send messages every time we
// "deliverOfflineMsgs"
fixture.friendMessageSender.dropReceipts = true;
fixture.friendMessageSender.sendMessage(0, msg.content, receipt);
fixture.offlineMsgEngine.addSentMessage(receipt, msg, completionFn);
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
QVERIFY(fixture.friendMessageSender.numMessagesSent == 5);
// And once we stop dropping and try one more time we should run out of
// messages to send again
fixture.friendMessageSender.dropReceipts = false;
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
fixture.offlineMsgEngine.deliverOfflineMsgs();
QVERIFY(fixture.friendMessageSender.numMessagesSent == 6);
}
void TestOfflineMsgEngine::testOfflineFriend()
{
OfflineMsgEngineFixture fixture;
Message msg{false, QString(), QDateTime()};
fixture.f.setStatus(Status::Status::Offline);
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.f.setStatus(Status::Status::Online);
fixture.offlineMsgEngine.deliverOfflineMsgs();
QVERIFY(fixture.friendMessageSender.numMessagesFailed == 0);
QVERIFY(fixture.friendMessageSender.numMessagesSent == 5);
}
void TestOfflineMsgEngine::testSentUnsentCoordination()
{
OfflineMsgEngineFixture fixture;
Message msg{false, QString("a"), QDateTime()};
ReceiptNum receipt;
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
msg.content = "b";
fixture.friendMessageSender.dropReceipts = true;
fixture.friendMessageSender.sendMessage(0, msg.content, receipt);
fixture.friendMessageSender.dropReceipts = false;
fixture.offlineMsgEngine.addSentMessage(receipt, msg, completionFn);
msg.content = "c";
fixture.offlineMsgEngine.addUnsentMessage(msg, completionFn);
fixture.offlineMsgEngine.deliverOfflineMsgs();
auto expectedResponseOrder = std::vector<QString>{"a", "b", "c"};
QVERIFY(fixture.friendMessageSender.msgs == expectedResponseOrder);
}
void TestOfflineMsgEngine::testCallback()
{
OfflineMsgEngineFixture fixture;
size_t numCallbacks = 0;
auto callback = [&numCallbacks] { numCallbacks++; };
Message msg{false, QString(), QDateTime()};
ReceiptNum receipt;
fixture.friendMessageSender.sendMessage(0, msg.content, receipt);
fixture.offlineMsgEngine.addSentMessage(receipt, msg, callback);
fixture.offlineMsgEngine.addUnsentMessage(msg, callback);
fixture.offlineMsgEngine.deliverOfflineMsgs();
QVERIFY(numCallbacks == 2);
}
QTEST_GUILESS_MAIN(TestOfflineMsgEngine)
#include "offlinemsgengine_test.moc"