mirror of https://github.com/qTox/qTox.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
9.7 KiB
329 lines
9.7 KiB
/* |
|
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/icoregroupmessagesender.h" |
|
#include "src/model/group.h" |
|
#include "src/model/groupmessagedispatcher.h" |
|
#include "src/model/message.h" |
|
#include "src/persistence/settings.h" |
|
#include "src/persistence/igroupsettings.h" |
|
#include "src/model/interface.h" |
|
|
|
#include <QObject> |
|
#include <QtTest/QtTest> |
|
|
|
#include <set> |
|
#include <deque> |
|
|
|
|
|
class MockGroupMessageSender : public ICoreGroupMessageSender |
|
{ |
|
public: |
|
void sendGroupAction(int groupId, const QString& action) override |
|
{ |
|
numSentActions++; |
|
} |
|
|
|
void sendGroupMessage(int groupId, const QString& message) override |
|
{ |
|
numSentMessages++; |
|
} |
|
|
|
size_t numSentActions = 0; |
|
size_t numSentMessages = 0; |
|
}; |
|
|
|
/** |
|
* Mock 1 peer at group number 0 |
|
*/ |
|
class MockGroupQuery : public ICoreGroupQuery |
|
{ |
|
public: |
|
GroupId getGroupPersistentId(uint32_t groupNumber) const override |
|
{ |
|
return GroupId(0); |
|
} |
|
|
|
uint32_t getGroupNumberPeers(int groupId) const override |
|
{ |
|
if (emptyGroup) { |
|
return 1; |
|
} |
|
|
|
return 2; |
|
} |
|
|
|
QString getGroupPeerName(int groupId, int peerId) const override |
|
{ |
|
return QString("peer") + peerId; |
|
} |
|
|
|
ToxPk getGroupPeerPk(int groupId, int peerId) const override |
|
{ |
|
uint8_t id[TOX_PUBLIC_KEY_SIZE] = {static_cast<uint8_t>(peerId)}; |
|
return ToxPk(id); |
|
} |
|
|
|
QStringList getGroupPeerNames(int groupId) const override |
|
{ |
|
if (emptyGroup) { |
|
return QStringList({QString("me")}); |
|
} |
|
return QStringList({QString("me"), QString("other")}); |
|
} |
|
|
|
bool getGroupAvEnabled(int groupId) const override |
|
{ |
|
return false; |
|
} |
|
|
|
void setAsEmptyGroup() |
|
{ |
|
emptyGroup = true; |
|
} |
|
|
|
void setAsFunctionalGroup() |
|
{ |
|
emptyGroup = false; |
|
} |
|
|
|
private: |
|
bool emptyGroup = false; |
|
}; |
|
|
|
class MockCoreIdHandler : public ICoreIdHandler |
|
{ |
|
public: |
|
ToxId getSelfId() const override |
|
{ |
|
std::terminate(); |
|
return ToxId(); |
|
} |
|
|
|
ToxPk getSelfPublicKey() const override |
|
{ |
|
static uint8_t id[TOX_PUBLIC_KEY_SIZE] = {0}; |
|
return ToxPk(id); |
|
} |
|
|
|
QString getUsername() const override |
|
{ |
|
return "me"; |
|
} |
|
}; |
|
|
|
class MockGroupSettings : public QObject, public IGroupSettings |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
QStringList getBlackList() const override |
|
{ |
|
return blacklist; |
|
} |
|
|
|
void setBlackList(const QStringList& blist) override |
|
{ |
|
blacklist = blist; |
|
} |
|
|
|
bool getGroupAlwaysNotify() const override |
|
{ |
|
return false; |
|
} |
|
|
|
void setGroupAlwaysNotify(bool newValue) override {} |
|
SIGNAL_IMPL(MockGroupSettings, blackListChanged, QStringList const& blist) |
|
|
|
bool getShowGroupJoinLeaveMessages() const override { return true; }; |
|
void setShowGroupJoinLeaveMessages(bool newValue) override {}; |
|
SIGNAL_IMPL(MockGroupSettings, showGroupJoinLeaveMessagesChanged, bool show) |
|
|
|
private: |
|
QStringList blacklist; |
|
}; |
|
|
|
class TestGroupMessageDispatcher : public QObject |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
TestGroupMessageDispatcher(); |
|
|
|
private slots: |
|
void init(); |
|
void testSignals(); |
|
void testMessageSending(); |
|
void testEmptyGroup(); |
|
void testSelfReceive(); |
|
void testBlacklist(); |
|
|
|
void onMessageSent(DispatchedMessageId id, Message message) |
|
{ |
|
auto it = outgoingMessages.find(id); |
|
QVERIFY(it == outgoingMessages.end()); |
|
outgoingMessages.emplace(id); |
|
sentMessages.push_back(std::move(message)); |
|
} |
|
|
|
void onMessageComplete(DispatchedMessageId id) |
|
{ |
|
auto it = outgoingMessages.find(id); |
|
QVERIFY(it != outgoingMessages.end()); |
|
outgoingMessages.erase(it); |
|
} |
|
|
|
void onMessageReceived(const ToxPk& sender, Message message) |
|
{ |
|
receivedMessages.push_back(std::move(message)); |
|
} |
|
|
|
private: |
|
// All unique_ptrs to make construction/init() easier to manage |
|
std::unique_ptr<MockGroupSettings> groupSettings; |
|
std::unique_ptr<MockGroupQuery> groupQuery; |
|
std::unique_ptr<MockCoreIdHandler> coreIdHandler; |
|
std::unique_ptr<Group> g; |
|
std::unique_ptr<MockGroupMessageSender> messageSender; |
|
std::unique_ptr<MessageProcessor::SharedParams> sharedProcessorParams; |
|
std::unique_ptr<MessageProcessor> messageProcessor; |
|
std::unique_ptr<GroupMessageDispatcher> groupMessageDispatcher; |
|
std::set<DispatchedMessageId> outgoingMessages; |
|
std::deque<Message> sentMessages; |
|
std::deque<Message> receivedMessages; |
|
}; |
|
|
|
TestGroupMessageDispatcher::TestGroupMessageDispatcher() {} |
|
|
|
/** |
|
* @brief Test initialization. Resets all members to initial state |
|
*/ |
|
void TestGroupMessageDispatcher::init() |
|
{ |
|
groupSettings = std::unique_ptr<MockGroupSettings>(new MockGroupSettings()); |
|
groupQuery = std::unique_ptr<MockGroupQuery>(new MockGroupQuery()); |
|
coreIdHandler = std::unique_ptr<MockCoreIdHandler>(new MockCoreIdHandler()); |
|
g = std::unique_ptr<Group>( |
|
new Group(0, GroupId(0), "TestGroup", false, "me", *groupQuery, *coreIdHandler)); |
|
messageSender = std::unique_ptr<MockGroupMessageSender>(new MockGroupMessageSender()); |
|
sharedProcessorParams = |
|
std::unique_ptr<MessageProcessor::SharedParams>(new MessageProcessor::SharedParams()); |
|
messageProcessor = std::unique_ptr<MessageProcessor>(new MessageProcessor(*sharedProcessorParams)); |
|
groupMessageDispatcher = std::unique_ptr<GroupMessageDispatcher>( |
|
new GroupMessageDispatcher(*g, *messageProcessor, *coreIdHandler, *messageSender, |
|
*groupSettings)); |
|
|
|
connect(groupMessageDispatcher.get(), &GroupMessageDispatcher::messageSent, this, |
|
&TestGroupMessageDispatcher::onMessageSent); |
|
connect(groupMessageDispatcher.get(), &GroupMessageDispatcher::messageComplete, this, |
|
&TestGroupMessageDispatcher::onMessageComplete); |
|
connect(groupMessageDispatcher.get(), &GroupMessageDispatcher::messageReceived, this, |
|
&TestGroupMessageDispatcher::onMessageReceived); |
|
|
|
outgoingMessages = std::set<DispatchedMessageId>(); |
|
sentMessages = std::deque<Message>(); |
|
receivedMessages = std::deque<Message>(); |
|
} |
|
|
|
/** |
|
* @brief Tests that the signals emitted by the dispatcher are all emitted at the correct times |
|
*/ |
|
void TestGroupMessageDispatcher::testSignals() |
|
{ |
|
groupMessageDispatcher->sendMessage(false, "test"); |
|
|
|
// For groups we pair our sent and completed signals since we have no receiver reports |
|
QVERIFY(outgoingMessages.size() == 0); |
|
QVERIFY(!sentMessages.empty()); |
|
QVERIFY(sentMessages.front().isAction == false); |
|
QVERIFY(sentMessages.front().content == "test"); |
|
|
|
// If signals are emitted correctly we should have one message in our received message buffer |
|
QVERIFY(receivedMessages.empty()); |
|
groupMessageDispatcher->onMessageReceived(ToxPk(), false, "test2"); |
|
|
|
QVERIFY(!receivedMessages.empty()); |
|
QVERIFY(receivedMessages.front().isAction == false); |
|
QVERIFY(receivedMessages.front().content == "test2"); |
|
} |
|
|
|
/** |
|
* @brief Tests that sent messages actually go through to core |
|
*/ |
|
void TestGroupMessageDispatcher::testMessageSending() |
|
{ |
|
groupMessageDispatcher->sendMessage(false, "Test"); |
|
|
|
QVERIFY(messageSender->numSentMessages == 1); |
|
QVERIFY(messageSender->numSentActions == 0); |
|
|
|
groupMessageDispatcher->sendMessage(true, "Test"); |
|
|
|
QVERIFY(messageSender->numSentMessages == 1); |
|
QVERIFY(messageSender->numSentActions == 1); |
|
} |
|
|
|
/** |
|
* @brief Tests that if we are the only member in a group we do _not_ send messages to core. Toxcore |
|
* isn't too happy if we send messages and we're the only one in the group |
|
*/ |
|
void TestGroupMessageDispatcher::testEmptyGroup() |
|
{ |
|
groupQuery->setAsEmptyGroup(); |
|
g->regeneratePeerList(); |
|
|
|
groupMessageDispatcher->sendMessage(false, "Test"); |
|
groupMessageDispatcher->sendMessage(true, "Test"); |
|
|
|
QVERIFY(messageSender->numSentMessages == 0); |
|
QVERIFY(messageSender->numSentActions == 0); |
|
} |
|
|
|
/** |
|
* @brief Tests that we do not emit any signals if we receive a message from ourself. Toxcore will send us back messages we sent |
|
*/ |
|
void TestGroupMessageDispatcher::testSelfReceive() |
|
{ |
|
uint8_t selfId[TOX_PUBLIC_KEY_SIZE] = {0}; |
|
groupMessageDispatcher->onMessageReceived(ToxPk(selfId), false, "Test"); |
|
QVERIFY(receivedMessages.size() == 0); |
|
|
|
uint8_t id[TOX_PUBLIC_KEY_SIZE] = {1}; |
|
groupMessageDispatcher->onMessageReceived(ToxPk(id), false, "Test"); |
|
QVERIFY(receivedMessages.size() == 1); |
|
} |
|
|
|
/** |
|
* @brief Tests that messages from blacklisted peers do not get propogated from the dispatcher |
|
*/ |
|
void TestGroupMessageDispatcher::testBlacklist() |
|
{ |
|
uint8_t id[TOX_PUBLIC_KEY_SIZE] = {1}; |
|
auto otherPk = ToxPk(id); |
|
groupMessageDispatcher->onMessageReceived(otherPk, false, "Test"); |
|
QVERIFY(receivedMessages.size() == 1); |
|
|
|
groupSettings->setBlackList({otherPk.toString()}); |
|
groupMessageDispatcher->onMessageReceived(otherPk, false, "Test"); |
|
QVERIFY(receivedMessages.size() == 1); |
|
} |
|
|
|
// Cannot be guiless due to a settings instance in GroupMessageDispatcher |
|
QTEST_GUILESS_MAIN(TestGroupMessageDispatcher) |
|
#include "groupmessagedispatcher_test.moc"
|
|
|