mirror of https://github.com/qTox/qTox.git
20 changed files with 886 additions and 34 deletions
@ -0,0 +1,33 @@ |
|||||||
|
/*
|
||||||
|
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/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ICORE_GROUP_MESSAGE_SENDER_H |
||||||
|
#define ICORE_GROUP_MESSAGE_SENDER_H |
||||||
|
|
||||||
|
#include <QString> |
||||||
|
|
||||||
|
class ICoreGroupMessageSender |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~ICoreGroupMessageSender() = default; |
||||||
|
virtual void sendGroupAction(int groupId, const QString& message) = 0; |
||||||
|
virtual void sendGroupMessage(int groupId, const QString& message) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif /*ICORE_GROUP_MESSAGE_SENDER_H*/ |
@ -0,0 +1,44 @@ |
|||||||
|
/*
|
||||||
|
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||||
|
Copyright © 2014-2018 by The qTox Project Contributors |
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
This program is free 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/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ICORE_GROUP_QUERY_H |
||||||
|
#define ICORE_GROUP_QUERY_H |
||||||
|
|
||||||
|
#include "groupid.h" |
||||||
|
#include "toxpk.h" |
||||||
|
|
||||||
|
#include <QString> |
||||||
|
#include <QStringList> |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
class ICoreGroupQuery |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~ICoreGroupQuery() = default; |
||||||
|
virtual GroupId getGroupPersistentId(uint32_t groupNumber) const = 0; |
||||||
|
virtual uint32_t getGroupNumberPeers(int groupId) const = 0; |
||||||
|
virtual QString getGroupPeerName(int groupId, int peerId) const = 0; |
||||||
|
virtual ToxPk getGroupPeerPk(int groupId, int peerId) const = 0; |
||||||
|
virtual QStringList getGroupPeerNames(int groupId) const = 0; |
||||||
|
virtual bool getGroupAvEnabled(int groupId) const = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif /*ICORE_GROUP_QUERY_H*/ |
@ -0,0 +1,37 @@ |
|||||||
|
/*
|
||||||
|
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/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ICORE_ID_HANDLER_H |
||||||
|
#define ICORE_ID_HANDLER_H |
||||||
|
|
||||||
|
#include "toxid.h" |
||||||
|
#include "toxpk.h" |
||||||
|
|
||||||
|
class ICoreIdHandler |
||||||
|
{ |
||||||
|
|
||||||
|
public: |
||||||
|
virtual ~ICoreIdHandler() = default; |
||||||
|
virtual ToxId getSelfId() const = 0; |
||||||
|
virtual ToxPk getSelfPublicKey() const = 0; |
||||||
|
virtual QString getUsername() const = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif /*ICORE_ID_HANDLER_H*/ |
@ -0,0 +1,88 @@ |
|||||||
|
/*
|
||||||
|
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 "groupmessagedispatcher.h" |
||||||
|
#include "src/persistence/igroupsettings.h" |
||||||
|
|
||||||
|
#include <QtCore> |
||||||
|
|
||||||
|
GroupMessageDispatcher::GroupMessageDispatcher(Group& g_, MessageProcessor processor_, |
||||||
|
ICoreIdHandler& idHandler_, |
||||||
|
ICoreGroupMessageSender& messageSender_, |
||||||
|
const IGroupSettings& groupSettings_) |
||||||
|
: group(g_) |
||||||
|
, processor(processor_) |
||||||
|
, idHandler(idHandler_) |
||||||
|
, messageSender(messageSender_) |
||||||
|
, groupSettings(groupSettings_) |
||||||
|
{ |
||||||
|
processor.enableMentions(); |
||||||
|
} |
||||||
|
|
||||||
|
std::pair<DispatchedMessageId, DispatchedMessageId> |
||||||
|
GroupMessageDispatcher::sendMessage(bool isAction, QString const& content) |
||||||
|
{ |
||||||
|
const auto firstMessageId = nextMessageId; |
||||||
|
auto lastMessageId = firstMessageId; |
||||||
|
|
||||||
|
for (auto const& message : processor.processOutgoingMessage(isAction, content)) { |
||||||
|
auto messageId = nextMessageId++; |
||||||
|
lastMessageId = messageId; |
||||||
|
if (group.getPeersCount() != 1) { |
||||||
|
if (message.isAction) { |
||||||
|
messageSender.sendGroupAction(group.getId(), message.content); |
||||||
|
} else { |
||||||
|
messageSender.sendGroupMessage(group.getId(), message.content); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Emit both signals since we do not have receipts for groups
|
||||||
|
//
|
||||||
|
// NOTE: We could in theory keep track of our sent message and wait for
|
||||||
|
// toxcore to send it back to us to indicate a completed message, but
|
||||||
|
// this isn't necessarily the design of toxcore and associating the
|
||||||
|
// received message back would be difficult.
|
||||||
|
emit this->messageSent(messageId, message); |
||||||
|
emit this->messageComplete(messageId); |
||||||
|
} |
||||||
|
|
||||||
|
return std::make_pair(firstMessageId, lastMessageId); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes and dispatches received message from toxcore |
||||||
|
* @param[in] sender |
||||||
|
* @param[in] isAction True if is action |
||||||
|
* @param[in] content Message content |
||||||
|
*/ |
||||||
|
void GroupMessageDispatcher::onMessageReceived(const ToxPk& sender, bool isAction, QString const& content) |
||||||
|
{ |
||||||
|
bool isSelf = sender == idHandler.getSelfPublicKey(); |
||||||
|
|
||||||
|
if (isSelf) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (groupSettings.getBlackList().contains(sender.toString())) { |
||||||
|
qDebug() << "onGroupMessageReceived: Filtered:" << sender.toString(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
emit messageReceived(sender, processor.processIncomingMessage(isAction, content)); |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/*
|
||||||
|
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/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef GROUP_MESSAGE_DISPATCHER_H |
||||||
|
#define GROUP_MESSAGE_DISPATCHER_H |
||||||
|
|
||||||
|
#include "src/core/icoregroupmessagesender.h" |
||||||
|
#include "src/core/icoreidhandler.h" |
||||||
|
#include "src/model/group.h" |
||||||
|
#include "src/model/imessagedispatcher.h" |
||||||
|
#include "src/model/message.h" |
||||||
|
|
||||||
|
#include <QObject> |
||||||
|
#include <QString> |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
class IGroupSettings; |
||||||
|
|
||||||
|
class GroupMessageDispatcher : public IMessageDispatcher |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
GroupMessageDispatcher(Group& group, MessageProcessor processor, ICoreIdHandler& idHandler, |
||||||
|
ICoreGroupMessageSender& messageSender, |
||||||
|
const IGroupSettings& groupSettings); |
||||||
|
|
||||||
|
std::pair<DispatchedMessageId, DispatchedMessageId> sendMessage(bool isAction, |
||||||
|
QString const& content) override; |
||||||
|
void onMessageReceived(ToxPk const& sender, bool isAction, QString const& content); |
||||||
|
|
||||||
|
private: |
||||||
|
Group& group; |
||||||
|
MessageProcessor processor; |
||||||
|
ICoreIdHandler& idHandler; |
||||||
|
ICoreGroupMessageSender& messageSender; |
||||||
|
const IGroupSettings& groupSettings; |
||||||
|
DispatchedMessageId nextMessageId{0}; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif /* IMESSAGE_DISPATCHER_H */ |
@ -0,0 +1,35 @@ |
|||||||
|
/*
|
||||||
|
Copyright © 2014-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/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef IGROUP_SETTINGS_H |
||||||
|
#define IGROUP_SETTINGS_H |
||||||
|
|
||||||
|
#include <QStringList> |
||||||
|
|
||||||
|
class IGroupSettings |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~IGroupSettings() = default; |
||||||
|
virtual QStringList getBlackList() const = 0; |
||||||
|
virtual void setBlackList(const QStringList& blist) = 0; |
||||||
|
virtual bool getGroupAlwaysNotify() const = 0; |
||||||
|
virtual void setGroupAlwaysNotify(bool newValue) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif /*IGROUP_SETTINGS_H*/ |
@ -0,0 +1,300 @@ |
|||||||
|
#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 <QObject> |
||||||
|
#include <QtTest/QtTest> |
||||||
|
|
||||||
|
#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 IGroupSettings |
||||||
|
{ |
||||||
|
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 {} |
||||||
|
|
||||||
|
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" |
@ -0,0 +1,113 @@ |
|||||||
|
#include "src/model/message.h" |
||||||
|
|
||||||
|
#include <tox/tox.h> |
||||||
|
|
||||||
|
#include <QObject> |
||||||
|
#include <QtTest/QtTest> |
||||||
|
|
||||||
|
namespace { |
||||||
|
bool messageHasSelfMention(const Message& message) |
||||||
|
{ |
||||||
|
return std::any_of(message.metadata.begin(), message.metadata.end(), [](MessageMetadata meta) { |
||||||
|
return meta.type == MessageMetadataType::selfMention; |
||||||
|
}); |
||||||
|
} |
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class TestMessageProcessor : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
TestMessageProcessor(){}; |
||||||
|
|
||||||
|
private slots: |
||||||
|
void testSelfMention(); |
||||||
|
void testOutgoingMessage(); |
||||||
|
void testIncomingMessage(); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tests detection of username |
||||||
|
*/ |
||||||
|
void TestMessageProcessor::testSelfMention() |
||||||
|
{ |
||||||
|
MessageProcessor::SharedParams sharedParams; |
||||||
|
sharedParams.onUserNameSet("MyUserName"); |
||||||
|
|
||||||
|
auto messageProcessor = MessageProcessor(sharedParams); |
||||||
|
messageProcessor.enableMentions(); |
||||||
|
|
||||||
|
// Using my name should match
|
||||||
|
auto processedMessage = messageProcessor.processIncomingMessage(false, "MyUserName hi"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// Action messages should match too
|
||||||
|
processedMessage = messageProcessor.processIncomingMessage(true, "MyUserName hi"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// Too much text shouldn't match
|
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "MyUserName2"); |
||||||
|
QVERIFY(!messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// Unless it's a colon
|
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "MyUserName: test"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// Too little text shouldn't match
|
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "MyUser"); |
||||||
|
QVERIFY(!messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// The regex should be case insensitive
|
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "myusername hi"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// New user name changes should be detected
|
||||||
|
sharedParams.onUserNameSet("NewUserName"); |
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "NewUserName: hi"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
|
||||||
|
// Special characters should be removed
|
||||||
|
sharedParams.onUserNameSet("New\nUserName"); |
||||||
|
processedMessage = messageProcessor.processIncomingMessage(false, "NewUserName: hi"); |
||||||
|
QVERIFY(messageHasSelfMention(processedMessage)); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tests behavior of the processor for outgoing messages |
||||||
|
*/ |
||||||
|
void TestMessageProcessor::testOutgoingMessage() |
||||||
|
{ |
||||||
|
auto sharedParams = MessageProcessor::SharedParams(); |
||||||
|
auto messageProcessor = MessageProcessor(sharedParams); |
||||||
|
|
||||||
|
QString testStr; |
||||||
|
|
||||||
|
for (size_t i = 0; i < tox_max_message_length() + 50; ++i) { |
||||||
|
testStr += "a"; |
||||||
|
} |
||||||
|
|
||||||
|
auto messages = messageProcessor.processOutgoingMessage(false, testStr); |
||||||
|
|
||||||
|
// The message processor should split our messages
|
||||||
|
QVERIFY(messages.size() == 2); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tests behavior of the processor for incoming messages |
||||||
|
*/ |
||||||
|
void TestMessageProcessor::testIncomingMessage() |
||||||
|
{ |
||||||
|
// Nothing too special happening on the incoming side if we aren't looking for self mentions
|
||||||
|
auto sharedParams = MessageProcessor::SharedParams(); |
||||||
|
auto messageProcessor = MessageProcessor(sharedParams); |
||||||
|
auto message = messageProcessor.processIncomingMessage(false, "test"); |
||||||
|
|
||||||
|
QVERIFY(message.isAction == false); |
||||||
|
QVERIFY(message.content == "test"); |
||||||
|
QVERIFY(message.timestamp.isValid()); |
||||||
|
} |
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TestMessageProcessor) |
||||||
|
#include "messageprocessor_test.moc" |
Loading…
Reference in new issue