From 8a6d4b06f2291c363f3dea17837ed20893852453 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Wed, 9 Sep 2015 19:00:56 +0200 Subject: Cleanup repo with some directories --- src/libcommuni/tests/auto/auto.pri | 9 + src/libcommuni/tests/auto/auto.pro | 26 + src/libcommuni/tests/auto/irc/irc.pro | 7 + src/libcommuni/tests/auto/irc/tst_irc.cpp | 157 ++ src/libcommuni/tests/auto/ircbuffer/ircbuffer.pro | 7 + .../tests/auto/ircbuffer/tst_ircbuffer.cpp | 159 ++ .../tests/auto/ircbuffermodel/ircbuffermodel.pro | 11 + .../auto/ircbuffermodel/tst_ircbuffermodel.cpp | 1461 +++++++++++++++++ .../tests/auto/ircchannel/ircchannel.pro | 7 + .../tests/auto/ircchannel/tst_ircchannel.cpp | 79 + .../tests/auto/irccommand/irccommand.pro | 7 + .../tests/auto/irccommand/tst_irccommand.cpp | 529 ++++++ .../auto/irccommandparser/irccommandparser.pro | 7 + .../auto/irccommandparser/tst_irccommandparser.cpp | 442 +++++ .../tests/auto/irccompleter/irccompleter.pro | 8 + .../tests/auto/irccompleter/tst_irccompleter.cpp | 237 +++ .../tests/auto/ircconnection/ircconnection.pro | 11 + .../tests/auto/ircconnection/tst_ircconnection.cpp | 1721 ++++++++++++++++++++ .../tests/auto/irclagtimer/irclagtimer.pro | 8 + .../tests/auto/irclagtimer/tst_irclagtimer.cpp | 109 ++ .../tests/auto/ircmessage/ircmessage.pro | 7 + .../tests/auto/ircmessage/tst_ircmessage.cpp | 973 +++++++++++ .../tests/auto/ircnetwork/ircnetwork.pro | 8 + .../tests/auto/ircnetwork/tst_ircnetwork.cpp | 408 +++++ .../tests/auto/ircpalette/ircpalette.pro | 7 + .../tests/auto/ircpalette/tst_ircpalette.cpp | 102 ++ .../tests/auto/irctextformat/irctextformat.pro | 7 + .../tests/auto/irctextformat/tst_irctextformat.cpp | 192 +++ src/libcommuni/tests/auto/ircuser/ircuser.pro | 7 + src/libcommuni/tests/auto/ircuser/tst_ircuser.cpp | 86 + .../tests/auto/ircusermodel/ircusermodel.pro | 8 + .../tests/auto/ircusermodel/tst_ircusermodel.cpp | 1688 +++++++++++++++++++ src/libcommuni/tests/auto/shared/shared.pri | 16 + src/libcommuni/tests/auto/shared/tst_euirc.h | 47 + src/libcommuni/tests/auto/shared/tst_freenode.h | 94 ++ .../tests/auto/shared/tst_ircclientserver.cpp | 67 + .../tests/auto/shared/tst_ircclientserver.h | 50 + src/libcommuni/tests/auto/shared/tst_ircdata.cpp | 95 ++ src/libcommuni/tests/auto/shared/tst_ircdata.h | 32 + src/libcommuni/tests/auto/shared/tst_ircnet.h | 81 + 40 files changed, 8977 insertions(+) create mode 100644 src/libcommuni/tests/auto/auto.pri create mode 100644 src/libcommuni/tests/auto/auto.pro create mode 100644 src/libcommuni/tests/auto/irc/irc.pro create mode 100644 src/libcommuni/tests/auto/irc/tst_irc.cpp create mode 100644 src/libcommuni/tests/auto/ircbuffer/ircbuffer.pro create mode 100644 src/libcommuni/tests/auto/ircbuffer/tst_ircbuffer.cpp create mode 100644 src/libcommuni/tests/auto/ircbuffermodel/ircbuffermodel.pro create mode 100644 src/libcommuni/tests/auto/ircbuffermodel/tst_ircbuffermodel.cpp create mode 100644 src/libcommuni/tests/auto/ircchannel/ircchannel.pro create mode 100644 src/libcommuni/tests/auto/ircchannel/tst_ircchannel.cpp create mode 100644 src/libcommuni/tests/auto/irccommand/irccommand.pro create mode 100644 src/libcommuni/tests/auto/irccommand/tst_irccommand.cpp create mode 100644 src/libcommuni/tests/auto/irccommandparser/irccommandparser.pro create mode 100644 src/libcommuni/tests/auto/irccommandparser/tst_irccommandparser.cpp create mode 100644 src/libcommuni/tests/auto/irccompleter/irccompleter.pro create mode 100644 src/libcommuni/tests/auto/irccompleter/tst_irccompleter.cpp create mode 100644 src/libcommuni/tests/auto/ircconnection/ircconnection.pro create mode 100644 src/libcommuni/tests/auto/ircconnection/tst_ircconnection.cpp create mode 100644 src/libcommuni/tests/auto/irclagtimer/irclagtimer.pro create mode 100644 src/libcommuni/tests/auto/irclagtimer/tst_irclagtimer.cpp create mode 100644 src/libcommuni/tests/auto/ircmessage/ircmessage.pro create mode 100644 src/libcommuni/tests/auto/ircmessage/tst_ircmessage.cpp create mode 100644 src/libcommuni/tests/auto/ircnetwork/ircnetwork.pro create mode 100644 src/libcommuni/tests/auto/ircnetwork/tst_ircnetwork.cpp create mode 100644 src/libcommuni/tests/auto/ircpalette/ircpalette.pro create mode 100644 src/libcommuni/tests/auto/ircpalette/tst_ircpalette.cpp create mode 100644 src/libcommuni/tests/auto/irctextformat/irctextformat.pro create mode 100644 src/libcommuni/tests/auto/irctextformat/tst_irctextformat.cpp create mode 100644 src/libcommuni/tests/auto/ircuser/ircuser.pro create mode 100644 src/libcommuni/tests/auto/ircuser/tst_ircuser.cpp create mode 100644 src/libcommuni/tests/auto/ircusermodel/ircusermodel.pro create mode 100644 src/libcommuni/tests/auto/ircusermodel/tst_ircusermodel.cpp create mode 100644 src/libcommuni/tests/auto/shared/shared.pri create mode 100644 src/libcommuni/tests/auto/shared/tst_euirc.h create mode 100644 src/libcommuni/tests/auto/shared/tst_freenode.h create mode 100644 src/libcommuni/tests/auto/shared/tst_ircclientserver.cpp create mode 100644 src/libcommuni/tests/auto/shared/tst_ircclientserver.h create mode 100644 src/libcommuni/tests/auto/shared/tst_ircdata.cpp create mode 100644 src/libcommuni/tests/auto/shared/tst_ircdata.h create mode 100644 src/libcommuni/tests/auto/shared/tst_ircnet.h (limited to 'src/libcommuni/tests/auto') diff --git a/src/libcommuni/tests/auto/auto.pri b/src/libcommuni/tests/auto/auto.pri new file mode 100644 index 0000000..537efa0 --- /dev/null +++ b/src/libcommuni/tests/auto/auto.pri @@ -0,0 +1,9 @@ +###################################################################### +# Communi +###################################################################### + +QT = core network testlib +CONFIG += testcase +CONFIG -= app_bundle + +include(../tests.pri) diff --git a/src/libcommuni/tests/auto/auto.pro b/src/libcommuni/tests/auto/auto.pro new file mode 100644 index 0000000..e06d77c --- /dev/null +++ b/src/libcommuni/tests/auto/auto.pro @@ -0,0 +1,26 @@ +###################################################################### +# Communi +###################################################################### + +TEMPLATE = subdirs + +# IrcCore +SUBDIRS += irc +SUBDIRS += ircconnection +SUBDIRS += irccommand +SUBDIRS += ircmessage +SUBDIRS += ircnetwork + +# IrcModel +SUBDIRS += ircbuffer +SUBDIRS += ircbuffermodel +SUBDIRS += ircchannel +SUBDIRS += ircuser +SUBDIRS += ircusermodel + +# IrcUtil +SUBDIRS += irccommandparser +SUBDIRS += irccompleter +SUBDIRS += irclagtimer +SUBDIRS += ircpalette +SUBDIRS += irctextformat diff --git a/src/libcommuni/tests/auto/irc/irc.pro b/src/libcommuni/tests/auto/irc/irc.pro new file mode 100644 index 0000000..8270c47 --- /dev/null +++ b/src/libcommuni/tests/auto/irc/irc.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irc.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irc/tst_irc.cpp b/src/libcommuni/tests/auto/irc/tst_irc.cpp new file mode 100644 index 0000000..2a39f0b --- /dev/null +++ b/src/libcommuni/tests/auto/irc/tst_irc.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irc.h" +#include +#include + +class tst_Irc : public QObject +{ + Q_OBJECT + +private slots: + void testCreation(); + void testVersion(); + + void testCodeToString_data(); + void testCodeToString(); + + void testMetaObject(); + + void testPrefix_data(); + void testPrefix(); + + void testDebug(); +}; + +void tst_Irc::testCreation() +{ + Irc ircStatic; + Q_UNUSED(ircStatic); + + QScopedPointer ircDynamic(new Irc); + Q_UNUSED(ircDynamic); +} + +void tst_Irc::testVersion() +{ + QVERIFY(!Irc::version().isEmpty()); +} + +void tst_Irc::testCodeToString_data() +{ + QTest::addColumn("code"); + QTest::addColumn("str"); + + QTest::newRow("RPL_WELCOME") << 1 << QString("RPL_WELCOME"); + QTest::newRow("RPL_ISUPPORT") << 5 << QString("RPL_ISUPPORT"); + QTest::newRow("RPL_TOPIC") << 332 << QString("RPL_TOPIC"); + QTest::newRow("RPL_NAMREPLY") << 353 << QString("RPL_NAMREPLY"); + QTest::newRow("RPL_ENDOFNAMES") << 366 << QString("RPL_ENDOFNAMES"); + + QTest::newRow("ERR_NOSUCHNICK") << 401 << QString("ERR_NOSUCHNICK"); + QTest::newRow("ERR_NOSUCHCHANNEL") << 403 << QString("ERR_NOSUCHCHANNEL"); + QTest::newRow("ERR_NICKNAMEINUSE") << 433 << QString("ERR_NICKNAMEINUSE"); + QTest::newRow("ERR_OPERONLY") << 520 << QString("ERR_OPERONLY"); +} + +void tst_Irc::testCodeToString() +{ + QFETCH(int, code); + QFETCH(QString, str); + + QCOMPARE(Irc::codeToString(code), str); +} + +void tst_Irc::testMetaObject() +{ + Irc irc; + + QVERIFY(Irc::staticMetaObject.indexOfEnumerator("Code") != -1); + QVERIFY(Irc::staticMetaObject.indexOfEnumerator("Color") != -1); + QVERIFY(Irc::staticMetaObject.indexOfEnumerator("DataRole") != -1); + + QString ver; + QVERIFY(QMetaObject::invokeMethod(&irc, "version", Q_RETURN_ARG(QString, ver))); + QCOMPARE(ver, Irc::version()); + + QString str; + QVERIFY(QMetaObject::invokeMethod(&irc, "codeToString", Q_RETURN_ARG(QString, str), Q_ARG(int, Irc::RPL_ISUPPORT))); + QCOMPARE(str, Irc::codeToString(Irc::RPL_ISUPPORT)); +} + +void tst_Irc::testPrefix_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("prefix"); + QTest::addColumn("expectedNick"); + QTest::addColumn("expectedIdent"); + QTest::addColumn("expectedHost"); + + QTest::newRow("null") << false << QString() << QString() << QString() << QString(); + QTest::newRow("empty") << false << QString("") << QString("") << QString("") << QString(""); + QTest::newRow("trimmed") << true << QString(" n!u@h ") << QString("n") << QString("u") << QString("h"); + QTest::newRow("n!u@h") << true << QString("n!u@h") << QString("n") << QString("u") << QString("h"); + + QTest::newRow("n@h") << true << QString("n@h") << QString("n") << QString() << QString("h"); + QTest::newRow("n!u") << true << QString("n!u") << QString("n") << QString("u") << QString(); + QTest::newRow("!u@h") << false << QString("!u@h") << QString() << QString() << QString(); + QTest::newRow("n!@h") << false << QString("n!@h") << QString() << QString() << QString(); + QTest::newRow("n!u@") << false << QString("n!u@") << QString() << QString() << QString(); + + QTest::newRow("n !u@h") << false << QString("n !u@h") << QString() << QString() << QString(); + QTest::newRow("n! u@h") << false << QString("n! u@h") << QString() << QString() << QString(); + QTest::newRow("n!u @h") << false << QString("n!u @h") << QString() << QString() << QString(); + QTest::newRow("n!u@ h") << false << QString("n!u@ h") << QString() << QString() << QString(); + QTest::newRow("n ! u @ h") << false << QString("n ! u @ h") << QString() << QString() << QString(); +} + +void tst_Irc::testPrefix() +{ + QFETCH(bool, valid); + QFETCH(QString, prefix); + QFETCH(QString, expectedNick); + QFETCH(QString, expectedIdent); + QFETCH(QString, expectedHost); + + QString actualNick = Irc::nickFromPrefix(prefix); + QString actualIdent = Irc::identFromPrefix(prefix); + QString actualHost = Irc::hostFromPrefix(prefix); + + Q_UNUSED(valid); + QCOMPARE(expectedNick, actualNick); + QCOMPARE(expectedIdent, actualIdent); + QCOMPARE(expectedHost, actualHost); +} + +void tst_Irc::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << Irc::RPL_AWAY; + QCOMPARE(str.trimmed(), QString::fromLatin1("RPL_AWAY")); + str.clear(); + + dbg << Irc::NameRole; + QCOMPARE(str.trimmed(), QString::fromLatin1("NameRole")); + str.clear(); + + dbg << Irc::Brown; + QCOMPARE(str.trimmed(), QString::fromLatin1("Brown")); + str.clear(); + + dbg << Irc::SortByActivity; + QCOMPARE(str.trimmed(), QString::fromLatin1("SortByActivity")); + str.clear(); +} + +QTEST_MAIN(tst_Irc) + +#include "tst_irc.moc" diff --git a/src/libcommuni/tests/auto/ircbuffer/ircbuffer.pro b/src/libcommuni/tests/auto/ircbuffer/ircbuffer.pro new file mode 100644 index 0000000..1c0080c --- /dev/null +++ b/src/libcommuni/tests/auto/ircbuffer/ircbuffer.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircbuffer.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircbuffer/tst_ircbuffer.cpp b/src/libcommuni/tests/auto/ircbuffer/tst_ircbuffer.cpp new file mode 100644 index 0000000..1d124fb --- /dev/null +++ b/src/libcommuni/tests/auto/ircbuffer/tst_ircbuffer.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircbuffer.h" +#include "ircmessage.h" +#include +#include + +class tst_IrcBuffer : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testTitleNamePrefix(); + void testSticky(); + void testPersistent(); + void testReceive(); + void testDebug(); +}; + +void tst_IrcBuffer::testDefaults() +{ + IrcBuffer buffer; + QVERIFY(buffer.title().isEmpty()); + QVERIFY(buffer.name().isEmpty()); + QVERIFY(buffer.prefix().isEmpty()); + QVERIFY(!buffer.isChannel()); + QVERIFY(!buffer.toChannel()); + QVERIFY(!buffer.connection()); + QVERIFY(!buffer.network()); + QVERIFY(!buffer.model()); + QVERIFY(!buffer.isActive()); + QVERIFY(!buffer.isSticky()); + QVERIFY(!buffer.isPersistent()); +} + +void tst_IrcBuffer::testTitleNamePrefix() +{ + IrcBuffer buffer; + + QSignalSpy titleSpy(&buffer, SIGNAL(titleChanged(QString))); + QSignalSpy nameSpy(&buffer, SIGNAL(nameChanged(QString))); + QSignalSpy prefixSpy(&buffer, SIGNAL(prefixChanged(QString))); + QVERIFY(titleSpy.isValid()); + QVERIFY(nameSpy.isValid()); + QVERIFY(prefixSpy.isValid()); + + buffer.setName("name"); + QCOMPARE(buffer.title(), QString("name")); + QCOMPARE(buffer.name(), QString("name")); + QCOMPARE(buffer.prefix(), QString()); + QCOMPARE(titleSpy.count(), 1); + QCOMPARE(titleSpy.last().first().toString(), QString("name")); + QCOMPARE(nameSpy.count(), 1); + QCOMPARE(nameSpy.last().first().toString(), QString("name")); + QCOMPARE(prefixSpy.count(), 0); + + buffer.setPrefix("prefix"); + QCOMPARE(buffer.title(), QString("prefixname")); + QCOMPARE(buffer.name(), QString("name")); + QCOMPARE(buffer.prefix(), QString("prefix")); + QCOMPARE(titleSpy.count(), 2); + QCOMPARE(titleSpy.last().first().toString(), QString("prefixname")); + QCOMPARE(nameSpy.count(), 1); + QCOMPARE(prefixSpy.count(), 1); + QCOMPARE(prefixSpy.last().first().toString(), QString("prefix")); +} + +void tst_IrcBuffer::testSticky() +{ + IrcBuffer buffer; + QVERIFY(!buffer.isSticky()); + + QSignalSpy spy(&buffer, SIGNAL(stickyChanged(bool))); + QVERIFY(spy.isValid()); + + buffer.setSticky(true); + QVERIFY(buffer.isSticky()); + QCOMPARE(spy.count(), 1); + QVERIFY(spy.last().last().toBool()); + + buffer.setSticky(false); + QVERIFY(!buffer.isSticky()); + QCOMPARE(spy.count(), 2); + QVERIFY(!spy.last().last().toBool()); +} + +void tst_IrcBuffer::testPersistent() +{ + IrcBuffer buffer; + QVERIFY(!buffer.isPersistent()); + + QSignalSpy spy(&buffer, SIGNAL(persistentChanged(bool))); + QVERIFY(spy.isValid()); + + buffer.setPersistent(true); + QVERIFY(buffer.isPersistent()); + QCOMPARE(spy.count(), 1); + QVERIFY(spy.last().last().toBool()); + + buffer.setPersistent(false); + QVERIFY(!buffer.isPersistent()); + QCOMPARE(spy.count(), 2); + QVERIFY(!spy.last().last().toBool()); +} + +void tst_IrcBuffer::testReceive() +{ + Irc::registerMetaTypes(); + + IrcBuffer buffer; + + QSignalSpy spy(&buffer, SIGNAL(messageReceived(IrcMessage*))); + QVERIFY(spy.isValid()); + + buffer.receiveMessage(0); + QCOMPARE(spy.count(), 0); + + IrcMessage msg(0); + buffer.receiveMessage(&msg); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().at(0).value(), &msg); +} + +void tst_IrcBuffer::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcBuffer(0x0)")); + str.clear(); + + IrcBuffer buffer; + dbg << &buffer; + QVERIFY(QRegExp("IrcBuffer\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str)); + str.clear(); + + buffer.setObjectName("obj"); + dbg << &buffer; + QVERIFY(QRegExp("IrcBuffer\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str)); + str.clear(); + + buffer.setName("buf"); + dbg << &buffer; + QVERIFY(QRegExp("IrcBuffer\\(0x[0-9A-Fa-f]+, name=obj, title=buf\\) ").exactMatch(str)); + str.clear(); +} + +QTEST_MAIN(tst_IrcBuffer) + +#include "tst_ircbuffer.moc" diff --git a/src/libcommuni/tests/auto/ircbuffermodel/ircbuffermodel.pro b/src/libcommuni/tests/auto/ircbuffermodel/ircbuffermodel.pro new file mode 100644 index 0000000..16cf4c9 --- /dev/null +++ b/src/libcommuni/tests/auto/ircbuffermodel/ircbuffermodel.pro @@ -0,0 +1,11 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircbuffermodel.cpp + +# FakeQmlBufferModel::createXxx() +*g++*|*clang*:QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircbuffermodel/tst_ircbuffermodel.cpp b/src/libcommuni/tests/auto/ircbuffermodel/tst_ircbuffermodel.cpp new file mode 100644 index 0000000..60ec958 --- /dev/null +++ b/src/libcommuni/tests/auto/ircbuffermodel/tst_ircbuffermodel.cpp @@ -0,0 +1,1461 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircbuffermodel.h" +#include "ircconnection.h" +#include "ircchannel.h" +#include "ircbuffer.h" +#include +#include "tst_ircclientserver.h" +#include "tst_ircdata.h" + +class tst_IrcBufferModel : public tst_IrcClientServer +{ + Q_OBJECT + +public: + tst_IrcBufferModel(); + +private slots: + void testDefaults(); + void testBufferInit(); + void testAddRemove(); + void testSorting(); + void testClear(); + void testPersistent(); + void testPrototypes(); + void testChanges(); + void testActive(); + void testRoles(); + void testAIM(); + void testQML(); + void testWarnings(); +}; + +Q_DECLARE_METATYPE(QModelIndex) +tst_IrcBufferModel::tst_IrcBufferModel() +{ + Irc::registerMetaTypes(); + qRegisterMetaType(); + qRegisterMetaType("IrcBuffer*"); + qRegisterMetaType("IrcChannel*"); + qRegisterMetaType("IrcConnection*"); + qRegisterMetaType >("QList"); + qRegisterMetaType >("QList"); +} + +void tst_IrcBufferModel::testDefaults() +{ + IrcBufferModel model; + QCOMPARE(model.count(), 0); + QVERIFY(model.isEmpty()); + QCOMPARE(model.sortOrder(), Qt::AscendingOrder); + QCOMPARE(model.sortMethod(), Irc::SortByHand); + QVERIFY(model.channels().isEmpty()); + QCOMPARE(model.displayRole(), Irc::TitleRole); + QVERIFY(!model.isPersistent()); + QVERIFY(model.buffers().isEmpty()); + QVERIFY(!model.connection()); + QVERIFY(!model.network()); + QVERIFY(model.bufferPrototype()); + QVERIFY(model.channelPrototype()); +} + +void tst_IrcBufferModel::testBufferInit() +{ + IrcBufferModel model(connection); + model.setSortMethod(Irc::SortByTitle); + IrcBuffer* buffer1 = new IrcBuffer(&model); + buffer1->setName("1"); + model.add(buffer1); + IrcBuffer* buffer2 = new IrcBuffer(&model); + buffer2->setName("2"); + model.add(buffer2); +} + +void tst_IrcBufferModel::testAddRemove() +{ + IrcBufferModel model; + + QSignalSpy countSpy(&model, SIGNAL(countChanged(int))); + QSignalSpy emptySpy(&model, SIGNAL(emptyChanged(bool))); + QSignalSpy addedSpy(&model, SIGNAL(added(IrcBuffer*))); + QSignalSpy removedSpy(&model, SIGNAL(removed(IrcBuffer*))); + QSignalSpy aboutToBeAddedSpy(&model, SIGNAL(aboutToBeAdded(IrcBuffer*))); + QSignalSpy aboutToBeRemovedSpy(&model, SIGNAL(aboutToBeRemoved(IrcBuffer*))); + QSignalSpy buffersSpy(&model, SIGNAL(buffersChanged(QList))); + QSignalSpy channelsSpy(&model, SIGNAL(channelsChanged(QStringList))); + QVERIFY(countSpy.isValid()); + QVERIFY(emptySpy.isValid()); + QVERIFY(addedSpy.isValid()); + QVERIFY(removedSpy.isValid()); + QVERIFY(aboutToBeAddedSpy.isValid()); + QVERIFY(aboutToBeRemovedSpy.isValid()); + QVERIFY(buffersSpy.isValid()); + QVERIFY(channelsSpy.isValid()); + + // IrcBuffer* IrcBufferModel::add(const QString& title) + IrcBuffer* first = model.add("first"); + QCOMPARE(model.count(), 1); + QVERIFY(!model.isEmpty()); + QCOMPARE(model.get(0), first); + QCOMPARE(model.find("first"), first); + QCOMPARE(model.buffers(), QList() << first); + QVERIFY(model.contains("first")); + QCOMPARE(model.indexOf(first), 0); + QVERIFY(model.channels().isEmpty()); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(countSpy.last().last().toInt(), 1); + QCOMPARE(emptySpy.count(), 1); + QCOMPARE(emptySpy.last().last().toBool(), false); + QCOMPARE(aboutToBeAddedSpy.count(), 1); + QCOMPARE(aboutToBeAddedSpy.last().last().value(), first); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.last().last().value(), first); + QCOMPARE(buffersSpy.count(), 1); + QCOMPARE(buffersSpy.last().last().value >(), QList() << first); + QCOMPARE(channelsSpy.count(), 0); + + QModelIndex firstIdx = model.index(first); + QVERIFY(firstIdx.isValid()); + QCOMPARE(firstIdx.data(Irc::NameRole).toString(), QString("first")); + QCOMPARE(firstIdx.data(Irc::TitleRole).toString(), QString("first")); + QCOMPARE(firstIdx.data(Irc::PrefixRole).toString(), QString()); + QCOMPARE(firstIdx.data(Irc::BufferRole).value(), first); + QVERIFY(!firstIdx.data(Irc::ChannelRole).value()); + + // void IrcBufferModel::add(IrcBuffer* buffer) + IrcBuffer* second = new IrcBuffer(&model); + second->setName("second"); + model.add(second); + QCOMPARE(model.count(), 2); + QVERIFY(!model.isEmpty()); + QCOMPARE(model.get(1), second); + QCOMPARE(model.find("second"), second); + QCOMPARE(model.buffers(), QList() << first << second); + QVERIFY(model.contains("second")); + QCOMPARE(model.indexOf(second), 1); + QVERIFY(model.channels().isEmpty()); + + QCOMPARE(countSpy.count(), 2); + QCOMPARE(countSpy.last().last().toInt(), 2); + QCOMPARE(emptySpy.count(), 1); + QCOMPARE(aboutToBeAddedSpy.count(), 2); + QCOMPARE(aboutToBeAddedSpy.last().last().value(), second); + QCOMPARE(addedSpy.count(), 2); + QCOMPARE(addedSpy.last().last().value(), second); + QCOMPARE(buffersSpy.count(), 2); + QCOMPARE(buffersSpy.last().last().value >(), QList() << first << second); + QCOMPARE(channelsSpy.count(), 0); + + QModelIndex secondIdx = model.index(second); + QVERIFY(secondIdx.isValid()); + QCOMPARE(secondIdx.data(Irc::NameRole).toString(), QString("second")); + QCOMPARE(secondIdx.data(Irc::TitleRole).toString(), QString("second")); + QCOMPARE(secondIdx.data(Irc::PrefixRole).toString(), QString()); + QCOMPARE(secondIdx.data(Irc::BufferRole).value(), second); + QVERIFY(!secondIdx.data(Irc::ChannelRole).value()); + + // void IrcBufferModel::remove(IrcBuffer* buffer) + model.remove(second); + QCOMPARE(model.count(), 1); + QVERIFY(!model.isEmpty()); + QVERIFY(!model.find("second")); + QCOMPARE(model.buffers(), QList() << first); + QVERIFY(!model.contains("second")); + QVERIFY(model.channels().isEmpty()); + + QCOMPARE(countSpy.count(), 3); + QCOMPARE(countSpy.last().last().toInt(), 1); + QCOMPARE(emptySpy.count(), 1); + QCOMPARE(aboutToBeRemovedSpy.count(), 1); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(buffersSpy.count(), 3); + QCOMPARE(buffersSpy.last().last().value >(), QList() << first); + QCOMPARE(channelsSpy.count(), 0); + + // void IrcBufferModel::remove(const QString& title) + model.remove("first"); + QCOMPARE(model.count(), 0); + QVERIFY(model.isEmpty()); + QVERIFY(!model.find("first")); + QVERIFY(model.buffers().isEmpty()); + QVERIFY(!model.contains("first")); + QVERIFY(model.channels().isEmpty()); + + QCOMPARE(countSpy.count(), 4); + QCOMPARE(countSpy.last().last().toInt(), 0); + QCOMPARE(emptySpy.count(), 2); + QCOMPARE(emptySpy.last().last().toBool(), true); + QCOMPARE(aboutToBeRemovedSpy.count(), 2); + QCOMPARE(removedSpy.count(), 2); + QCOMPARE(buffersSpy.count(), 4); + QCOMPARE(buffersSpy.last().last().value >(), QList()); + QCOMPARE(channelsSpy.count(), 0); +} + +void tst_IrcBufferModel::testSorting() +{ + IrcBufferModel staticModel(connection); + IrcBufferModel dynamicModel(connection); + + connection->open(); + waitForOpened(); + waitForWritten(tst_IrcData::welcome()); + + IrcBuffer* b = staticModel.add("b"); + IrcBuffer* c = staticModel.add("#c"); + IrcBuffer* a = staticModel.add("#a"); + + QList buffers = QList() << b << c << a; + QCOMPARE(staticModel.buffers(), buffers); + + // IGNORE INVALID COLUMNS + staticModel.sort(-1, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + staticModel.sort(1, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY NAME - ASCENDING + buffers = QList() << a << b << c; + staticModel.setSortMethod(Irc::SortByName); + staticModel.sort(0, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY NAME - DESCENDING + buffers = QList() << c << b << a; + staticModel.setSortMethod(Irc::SortByName); + staticModel.sort(0, Qt::DescendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY TITLE - ASCENDING + buffers = QList() << a << c << b; + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY TITLE - DESCENDING + buffers = QList() << b << c << a; + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::DescendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY TITLE - ASCENDING & STICKY + c->setSticky(true); + buffers = QList() << c << a << b; + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + // STATIC - BY TITLE - ASCENDING & 2 STICKIES + b->setSticky(true); + buffers = QList() << c << b << a; + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::AscendingOrder); + QCOMPARE(staticModel.buffers(), buffers); + + b = dynamicModel.add("b"); + c = dynamicModel.add("#c"); + a = dynamicModel.add("#a"); + + // DYNAMIC - BY NAME - ASCENDING + buffers = QList() << a << b << c; + dynamicModel.setSortMethod(Irc::SortByName); + QCOMPARE(dynamicModel.buffers(), buffers); + + // DYNAMIC - BY TITLE - ASCENDING + buffers = QList() << a << c << b; + dynamicModel.setSortMethod(Irc::SortByTitle); + QCOMPARE(dynamicModel.buffers(), buffers); + + dynamicModel.setSortOrder(Qt::DescendingOrder); + + // DYNAMIC - BY NAME - DESCENDING + buffers = QList() << c << b << a; + dynamicModel.setSortMethod(Irc::SortByName); + QCOMPARE(dynamicModel.buffers(), buffers); + + // DYNAMIC - BY TITLE - DESCENDING + buffers = QList() << b << c << a; + dynamicModel.setSortMethod(Irc::SortByTitle); + QCOMPARE(dynamicModel.buffers(), buffers); + + // DO NOTHING + dynamicModel.sort(Irc::SortByHand); + QCOMPARE(dynamicModel.buffers(), buffers); +} + +void tst_IrcBufferModel::testClear() +{ + IrcBufferModel model(connection); + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + QPointer a = model.add("#a"); + QPointer b = model.add("#b"); + QPointer c = model.add("c"); + QPointer d = model.add("d"); + + QSignalSpy countSpy(&model, SIGNAL(countChanged(int))); + QSignalSpy buffersSpy(&model, SIGNAL(buffersChanged(QList))); + QSignalSpy channelsSpy(&model, SIGNAL(channelsChanged(QStringList))); + QSignalSpy modelAboutToBeResetSpy(&model, SIGNAL(modelAboutToBeReset())); + QSignalSpy modelResetSpy(&model, SIGNAL(modelReset())); + + QVERIFY(countSpy.isValid()); + QVERIFY(buffersSpy.isValid()); + QVERIFY(channelsSpy.isValid()); + QVERIFY(modelAboutToBeResetSpy.isValid()); + QVERIFY(modelResetSpy.isValid()); + + b->setPersistent(true); + d->setPersistent(true); + + // #a, #b*, c, d* + model.clear(); + + QCOMPARE(model.count(), 2); + QCOMPARE(model.buffers(), QList() << b << d); + QCOMPARE(model.channels(), QStringList() << "#b"); + + QCOMPARE(model.get(0), b.data()); + QCOMPARE(model.get(1), d.data()); + QVERIFY(!model.get(2)); + QVERIFY(!model.find("#a")); + QVERIFY(model.find("#b")); + QVERIFY(!model.find("c")); + QVERIFY(model.find("d")); + QVERIFY(!model.contains("#a")); + QVERIFY(model.contains("#b")); + QVERIFY(!model.contains("c")); + QVERIFY(model.contains("d")); + + QVERIFY(!a); + QVERIFY(b); + QVERIFY(!c); + QVERIFY(d); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(countSpy.last().at(0).toInt(), 2); + + QCOMPARE(buffersSpy.count(), 1); + QCOMPARE(buffersSpy.last().at(0).value >(), QList() << b << d); + + QCOMPARE(channelsSpy.count(), 1); + QCOMPARE(channelsSpy.last().at(0).toStringList(), QStringList() << "#b"); + + QCOMPARE(modelAboutToBeResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); + + b->setPersistent(false); + + countSpy.clear(); + buffersSpy.clear(); + channelsSpy.clear(); + modelAboutToBeResetSpy.clear(); + modelResetSpy.clear(); + + // #b, d* + model.clear(); + + QCOMPARE(model.count(), 1); + QCOMPARE(model.buffers(), QList() << d); + QCOMPARE(model.channels(), QStringList()); + + QCOMPARE(model.get(0), d.data()); + QVERIFY(!model.get(1)); + QVERIFY(!model.find("#b")); + QVERIFY(model.find("d")); + QVERIFY(!model.contains("#b")); + QVERIFY(model.contains("d")); + + QVERIFY(!b); + QVERIFY(d); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(countSpy.last().at(0).toInt(), 1); + + QCOMPARE(buffersSpy.count(), 1); + QCOMPARE(buffersSpy.last().at(0).value >(), QList() << d); + + QCOMPARE(channelsSpy.count(), 1); + QCOMPARE(channelsSpy.last().at(0).toStringList(), QStringList()); + + QCOMPARE(modelAboutToBeResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); + + d->setPersistent(false); + + countSpy.clear(); + buffersSpy.clear(); + channelsSpy.clear(); + modelAboutToBeResetSpy.clear(); + modelResetSpy.clear(); + + // d + model.clear(); + + QCOMPARE(model.count(), 0); + QCOMPARE(model.buffers(), QList()); + QCOMPARE(model.channels(), QStringList()); + + QVERIFY(!model.get(0)); + QVERIFY(!model.find("d")); + QVERIFY(!model.contains("d")); + + QVERIFY(!d); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(countSpy.last().at(0).toInt(), 0); + + QCOMPARE(buffersSpy.count(), 1); + QCOMPARE(buffersSpy.last().at(0).value >(), QList()); + + QCOMPARE(channelsSpy.count(), 0); + + QCOMPARE(modelAboutToBeResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); + + countSpy.clear(); + buffersSpy.clear(); + channelsSpy.clear(); + modelAboutToBeResetSpy.clear(); + modelResetSpy.clear(); + + // + model.clear(); + + QCOMPARE(countSpy.count(), 0); + QCOMPARE(buffersSpy.count(), 0); + QCOMPARE(channelsSpy.count(), 0); + QCOMPARE(modelAboutToBeResetSpy.count(), 0); + QCOMPARE(modelResetSpy.count(), 0); + + QPointer e = model.add("e"); + QPointer f = model.add("f"); + + e->setPersistent(true); + f->setPersistent(true); + + countSpy.clear(); + buffersSpy.clear(); + channelsSpy.clear(); + modelAboutToBeResetSpy.clear(); + modelResetSpy.clear(); + + // e*, f* + model.clear(); + + QVERIFY(e); + QVERIFY(f); + + QCOMPARE(countSpy.count(), 0); + QCOMPARE(buffersSpy.count(), 0); + QCOMPARE(channelsSpy.count(), 0); + QCOMPARE(modelAboutToBeResetSpy.count(), 0); + QCOMPARE(modelResetSpy.count(), 0); + + qDeleteAll(model.buffers()); + + QCOMPARE(model.count(), 0); + QCOMPARE(model.buffers(), QList()); + QCOMPARE(model.channels(), QStringList()); + + QVERIFY(!model.get(0)); + QVERIFY(!model.find("e")); + QVERIFY(!model.find("f")); + QVERIFY(!model.contains("e")); + QVERIFY(!model.contains("f")); + + QVERIFY(!e); + QVERIFY(!f); + + QCOMPARE(countSpy.count(), 2); + QCOMPARE(countSpy.at(0).at(0).toInt(), 1); + QCOMPARE(countSpy.at(1).at(0).toInt(), 0); + + QCOMPARE(buffersSpy.count(), 2); + QCOMPARE(buffersSpy.at(0).at(0).value >().count(), 1); + QCOMPARE(buffersSpy.at(1).at(0).value >(), QList()); + + QCOMPARE(channelsSpy.count(), 0); + + QCOMPARE(modelAboutToBeResetSpy.count(), 0); + QCOMPARE(modelResetSpy.count(), 0); +} + +void tst_IrcBufferModel::testPersistent() +{ + IrcBufferModel model(connection); + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#communi")); + QCOMPARE(model.count(), 1); + + QPointer channel = model.get(0)->toChannel(); + QVERIFY(channel); + + QVERIFY(!model.isPersistent()); + QVERIFY(!channel->isPersistent()); + QVERIFY(waitForWritten(":communi!communi@hidd.en PART :#communi")); + QVERIFY(model.isEmpty()); + QVERIFY(channel); // deleteLater()'d + QCoreApplication::sendPostedEvents(channel, QEvent::DeferredDelete); + QVERIFY(!channel); // deleteLater()'d + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#communi")); + QCOMPARE(model.count(), 1); + channel = model.get(0)->toChannel(); + QVERIFY(channel); + + model.setPersistent(true); + QVERIFY(model.isPersistent()); + QVERIFY(!channel->isPersistent()); + QVERIFY(waitForWritten(":communi!communi@hidd.en PART :#communi")); + QVERIFY(channel); + QCOMPARE(model.count(), 1); + + channel->setPersistent(true); + QVERIFY(model.isPersistent()); + QVERIFY(channel->isPersistent()); + QVERIFY(waitForWritten(":communi!communi@hidd.en PART :#communi")); + QVERIFY(channel); + QCOMPARE(model.count(), 1); + + model.setPersistent(false); + QVERIFY(!model.isPersistent()); + QVERIFY(channel->isPersistent()); + QVERIFY(waitForWritten(":communi!communi@hidd.en PART :#communi")); + QVERIFY(channel); + QCOMPARE(model.count(), 1); + + channel->setPersistent(false); + QVERIFY(!model.isPersistent()); + QVERIFY(!channel->isPersistent()); + QVERIFY(waitForWritten(":communi!communi@hidd.en PART :#communi")); + QVERIFY(model.isEmpty()); + QVERIFY(channel); // deleteLater()'d + QCoreApplication::sendPostedEvents(channel, QEvent::DeferredDelete); + QVERIFY(!channel); // deleteLater()'d +} + +void tst_IrcBufferModel::testPrototypes() +{ + IrcBufferModel model; + + QSignalSpy bufferProtoSpy(&model, SIGNAL(bufferPrototypeChanged(IrcBuffer*))); + QSignalSpy channelProtoSpy(&model, SIGNAL(channelPrototypeChanged(IrcChannel*))); + QVERIFY(bufferProtoSpy.isValid()); + QVERIFY(channelProtoSpy.isValid()); + + model.setBufferPrototype(0); + QVERIFY(model.bufferPrototype()); + QCOMPARE(bufferProtoSpy.count(), 1); + + model.setChannelPrototype(0); + QVERIFY(model.channelPrototype()); + QCOMPARE(channelProtoSpy.count(), 1); + + IrcBuffer* bufferProto = new IrcBuffer(&model); + model.setBufferPrototype(bufferProto); + QCOMPARE(model.bufferPrototype(), bufferProto); + QCOMPARE(bufferProtoSpy.count(), 2); + + IrcChannel* channelProto = new IrcChannel(&model); + model.setChannelPrototype(channelProto); + QCOMPARE(model.channelPrototype(), channelProto); + QCOMPARE(channelProtoSpy.count(), 2); +} + +void tst_IrcBufferModel::testChanges() +{ + IrcBufferModel bufferModel; + + // IrcBufferModel signals + QSignalSpy countChangedSpy(&bufferModel, SIGNAL(countChanged(int))); + QSignalSpy addedSpy(&bufferModel, SIGNAL(added(IrcBuffer*))); + QSignalSpy removedSpy(&bufferModel, SIGNAL(removed(IrcBuffer*))); + QSignalSpy aboutToBeAddedSpy(&bufferModel, SIGNAL(aboutToBeAdded(IrcBuffer*))); + QSignalSpy aboutToBeRemovedSpy(&bufferModel, SIGNAL(aboutToBeRemoved(IrcBuffer*))); + QSignalSpy buffersChangedSpy(&bufferModel, SIGNAL(buffersChanged(QList))); + QSignalSpy channelsChangedSpy(&bufferModel, SIGNAL(channelsChanged(QStringList))); + + QVERIFY(countChangedSpy.isValid()); + QVERIFY(addedSpy.isValid()); + QVERIFY(removedSpy.isValid()); + QVERIFY(aboutToBeAddedSpy.isValid()); + QVERIFY(aboutToBeRemovedSpy.isValid()); + QVERIFY(buffersChangedSpy.isValid()); + QVERIFY(channelsChangedSpy.isValid()); + + int countChangedCount = 0; + int aboutToBeAddedCount = 0, addedCount = 0; + int aboutToBeRemovedCount = 0, removedCount = 0; + int buffersChangedCount = 0; + int channelsChangedCount = 0; + + QSignalSpy connectionChangedSpy(&bufferModel, SIGNAL(connectionChanged(IrcConnection*))); + QSignalSpy networkChangedSpy(&bufferModel, SIGNAL(networkChanged(IrcNetwork*))); + QSignalSpy messageIgnoredSpy(&bufferModel, SIGNAL(messageIgnored(IrcMessage*))); + + QVERIFY(connectionChangedSpy.isValid()); + QVERIFY(networkChangedSpy.isValid()); + QVERIFY(messageIgnoredSpy.isValid()); + + int connectionChangedCount = 0; + int networkChangedCount = 0; + int messageIgnoredCount = 0; + + // relevant QAbstractItemModel signals + QSignalSpy dataChangedSpy(&bufferModel, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy layoutAboutToBeChangedSpy(&bufferModel, SIGNAL(layoutAboutToBeChanged())); + QSignalSpy layoutChangedSpy(&bufferModel, SIGNAL(layoutChanged())); + QSignalSpy rowsAboutToBeInsertedSpy(&bufferModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowsInsertedSpy(&bufferModel, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy rowsAboutToBeRemovedSpy(&bufferModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowsRemovedSpy(&bufferModel, SIGNAL(rowsRemoved(QModelIndex,int,int))); + + QVERIFY(dataChangedSpy.isValid()); + QVERIFY(layoutAboutToBeChangedSpy.isValid()); + QVERIFY(layoutChangedSpy.isValid()); + QVERIFY(rowsAboutToBeInsertedSpy.isValid()); + QVERIFY(rowsInsertedSpy.isValid()); + QVERIFY(rowsAboutToBeRemovedSpy.isValid()); + QVERIFY(rowsRemovedSpy.isValid()); + + int dataChangedCount = 0; + int layoutAboutToBeChangedCount = 0, layoutChangedCount = 0; + int rowsAboutToBeInsertedCount = 0, rowsInsertedCount = 0; + int rowsAboutToBeRemovedCount = 0, rowsRemovedCount = 0; + + bufferModel.setConnection(connection); + QCOMPARE(connectionChangedSpy.count(), ++connectionChangedCount); + QCOMPARE(networkChangedSpy.count(), ++networkChangedCount); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + messageIgnoredCount = tst_IrcData::welcome().split('\n').count(); // N lines + a combined motd msg + + QCOMPARE(bufferModel.count(), 0); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#communi")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QCOMPARE(bufferModel.count(), 1); + + QPointer communi = bufferModel.get(0)->toChannel(); + QVERIFY(communi); + QCOMPARE(communi->title(), QString("#communi")); + QCOMPARE(communi->name(), QString("communi")); + QCOMPARE(communi->prefix(), QString("#")); + + int previousIndex = -1; + + QList buffers = QList() << communi; + QStringList channels = QStringList() << "#communi"; + + int nextIndex = buffers.indexOf(communi); + + QCOMPARE(bufferModel.count(), buffers.count()); + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + QCOMPARE(bufferModel.channels(), channels); + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), communi.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), communi.data()); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), ++channelsChangedCount); + QCOMPARE(channelsChangedSpy.last().at(0).toStringList(), channels); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. NOTICE communi :fake...")); + QCOMPARE(messageIgnoredSpy.count(), ++messageIgnoredCount); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + QCOMPARE(countChangedSpy.count(), countChangedCount); + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + QCOMPARE(addedSpy.count(), addedCount); + QCOMPARE(buffersChangedSpy.count(), buffersChangedCount); + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. PRIVMSG communi :fake...")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QPointer ChanServ = bufferModel.get(1); + QVERIFY(ChanServ); + QCOMPARE(ChanServ->title(), QString("ChanServ")); + QCOMPARE(ChanServ->name(), QString("ChanServ")); + QCOMPARE(ChanServ->prefix(), QString()); + + previousIndex = -1; + + buffers = QList() << communi << ChanServ; + channels = QStringList() << "#communi"; + + nextIndex = buffers.indexOf(ChanServ); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + QCOMPARE(bufferModel.count(), buffers.count()); + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), ChanServ.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), ChanServ.data()); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. NOTICE communi :fake...")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + QCOMPARE(bufferModel.count(), buffers.count()); + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + QCOMPARE(addedSpy.count(), addedCount); + QCOMPARE(buffersChangedSpy.count(), buffersChangedCount); + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#freenode")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QPointer freenode = bufferModel.get(2)->toChannel(); + QVERIFY(freenode); + QCOMPARE(freenode->title(), QString("#freenode")); + QCOMPARE(freenode->name(), QString("freenode")); + QCOMPARE(freenode->prefix(), QString("#")); + + previousIndex = -1; + + buffers = QList() << communi << ChanServ << freenode; + channels = QStringList() << "#communi" << "#freenode"; + + nextIndex = buffers.indexOf(freenode); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), freenode.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), freenode.data()); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), ++channelsChangedCount); + QCOMPARE(channelsChangedSpy.last().at(0).toStringList(), channels); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + bufferModel.setSortMethod(Irc::SortByTitle); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + previousIndex = -1; + + // Irc::SortByTitle + buffers = QList() << communi << freenode << ChanServ; + channels = QStringList() << "#communi" << "#freenode"; + + nextIndex = -1; + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + bufferModel.setSortMethod(Irc::SortByName); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + bufferModel.setSortOrder(Qt::DescendingOrder); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + previousIndex = -1; + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << freenode << communi << ChanServ; + channels = QStringList() << "#communi" << "#freenode"; + + nextIndex = -1; + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QVERIFY(waitForWritten(":qtassistant!qtassistant@hidd.en PRIVMSG communi :hola")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QPointer qtassistant = bufferModel.get(0); + QVERIFY(qtassistant); + QCOMPARE(qtassistant->title(), QString("qtassistant")); + QCOMPARE(qtassistant->name(), QString("qtassistant")); + QCOMPARE(qtassistant->prefix(), QString()); + + previousIndex = -1; + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << qtassistant << freenode << communi << ChanServ; + channels = QStringList() << "#communi" << "#freenode"; + + nextIndex = buffers.indexOf(qtassistant); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), qtassistant.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), qtassistant.data()); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QSignalSpy titleChangedSpy(qtassistant, SIGNAL(titleChanged(QString))); + QSignalSpy nameChangedSpy(qtassistant, SIGNAL(nameChanged(QString))); + QSignalSpy prefixChangedSpy(qtassistant, SIGNAL(prefixChanged(QString))); + + QVERIFY(titleChangedSpy.isValid()); + QVERIFY(nameChangedSpy.isValid()); + QVERIFY(prefixChangedSpy.isValid()); + + int titleChangedCount = 0; + int nameChangedCount = 0; + int prefixChangedCount = 0; + + QVERIFY(waitForWritten(":qtassistant!qtassistant@hidd.en NICK assistant :hola")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QCOMPARE(qtassistant->title(), QString("assistant")); + QCOMPARE(qtassistant->name(), QString("assistant")); + QCOMPARE(qtassistant->prefix(), QString()); + + QCOMPARE(titleChangedSpy.count(), ++titleChangedCount); + QCOMPARE(nameChangedSpy.count(), ++nameChangedCount); + QCOMPARE(prefixChangedSpy.count(), prefixChangedCount); + + previousIndex = buffers.indexOf(qtassistant); + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << freenode << communi << ChanServ << qtassistant; // qtassistant=assistant + channels = QStringList() << "#communi" << "#freenode"; + + nextIndex = buffers.indexOf(qtassistant); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + + QCOMPARE(addedSpy.count(), addedCount); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + QModelIndex topLeft = dataChangedSpy.last().at(0).value(); + QModelIndex bottomRight = dataChangedSpy.last().at(0).value(); + QVERIFY(!topLeft.parent().isValid()); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), previousIndex); + QCOMPARE(topLeft.column(), 0); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QVERIFY(waitForWritten(":communi!communi@hidd.en PART #communi")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QVERIFY(communi); // deleteLater()'d + + QCOMPARE(aboutToBeRemovedSpy.count(), ++aboutToBeRemovedCount); + QCOMPARE(aboutToBeRemovedSpy.last().at(0).value(), communi.data()); + + QCOMPARE(removedSpy.count(), ++removedCount); + QCOMPARE(removedSpy.last().at(0).value(), communi.data()); + + previousIndex = buffers.indexOf(communi); + + QCoreApplication::sendPostedEvents(communi, QEvent::DeferredDelete); + QVERIFY(!communi); + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << freenode << ChanServ << qtassistant; // qtassistant=assistant + channels = QStringList() << "#freenode"; + + nextIndex = buffers.indexOf(communi); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + + QCOMPARE(addedSpy.count(), addedCount); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), ++channelsChangedCount); + QCOMPARE(channelsChangedSpy.last().at(0).toStringList(), channels); + + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + + waitForWritten(":moorcock.freenode.net 324 communi #freenode +s"); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + QCOMPARE(freenode->mode(), QString("+s")); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi KICK #freenode communi")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QVERIFY(freenode); // deleteLater()'d + + QCOMPARE(aboutToBeRemovedSpy.count(), ++aboutToBeRemovedCount); + QCOMPARE(aboutToBeRemovedSpy.last().at(0).value(), freenode.data()); + + QCOMPARE(removedSpy.count(), ++removedCount); + QCOMPARE(removedSpy.last().at(0).value(), freenode.data()); + + previousIndex = buffers.indexOf(freenode); + + QCoreApplication::sendPostedEvents(freenode, QEvent::DeferredDelete); + QVERIFY(!freenode); + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << ChanServ << qtassistant; // qtassistant=assistant + channels = QStringList(); + + nextIndex = buffers.indexOf(freenode); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + + QCOMPARE(addedSpy.count(), addedCount); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), ++channelsChangedCount); + QCOMPARE(channelsChangedSpy.last().at(0).toStringList(), channels); + + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + + QVERIFY(waitForWritten(":communi!communi@hidd.en PRIVMSG jpnurmi :echo")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + QPointer jpnurmi = bufferModel.get(0); + QVERIFY(jpnurmi); + QCOMPARE(jpnurmi->title(), QString("jpnurmi")); + QCOMPARE(jpnurmi->name(), QString("jpnurmi")); + QCOMPARE(jpnurmi->prefix(), QString()); + + previousIndex = -1; + + // Irc::SortByName, Qt::DescendingOrder + buffers = QList() << jpnurmi << ChanServ << qtassistant; // qtassistant=assistant + channels = QStringList(); + + nextIndex = buffers.indexOf(jpnurmi); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), buffers.count()); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), jpnurmi.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), jpnurmi.data()); + + QCOMPARE(buffersChangedSpy.count(), ++buffersChangedCount); + QCOMPARE(buffersChangedSpy.last().at(0).value >(), buffers); + + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), QModelIndex()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QVERIFY(waitForWritten(":communi!communi@hidd.en QUIT :bye")); + QCOMPARE(messageIgnoredSpy.count(), messageIgnoredCount); + + serverSocket->close(); + QVERIFY(clientSocket->waitForDisconnected(100)); + QVERIFY(!connection->isConnected()); + QVERIFY(!connection->isActive()); + + QCOMPARE(bufferModel.count(), buffers.count()); + QCOMPARE(bufferModel.buffers(), buffers); + QCOMPARE(bufferModel.channels(), channels); + + for (int i = 0; i < bufferModel.count(); ++i) { + QCOMPARE(bufferModel.get(i), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::BufferRole).value(), buffers.at(i)); + QCOMPARE(bufferModel.index(i).data(Irc::ChannelRole).value(), buffers.at(i)->toChannel()); + QVERIFY(!buffers.at(i)->isActive()); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + QCOMPARE(aboutToBeAddedSpy.count(), aboutToBeAddedCount); + QCOMPARE(addedSpy.count(), addedCount); + QCOMPARE(buffersChangedSpy.count(), buffersChangedCount); + QCOMPARE(channelsChangedSpy.count(), channelsChangedCount); + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); +} + +void tst_IrcBufferModel::testActive() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#communi")); + + IrcChannel* channel = bufferModel.get(0)->toChannel(); + IrcBuffer* query = bufferModel.add("qtassistant"); + + channel->setPersistent(true); + query->setPersistent(true); + + QSignalSpy channelActiveSpy(channel, SIGNAL(activeChanged(bool))); + QSignalSpy queryActiveSpy(query, SIGNAL(activeChanged(bool))); + QVERIFY(channelActiveSpy.isValid()); + QVERIFY(queryActiveSpy.isValid()); + int channelActiveCount = 0; + int queryActiveCount = 0; + + QVERIFY(channel->isActive()); + QVERIFY(query->isActive()); + + connection->close(); + + QVERIFY(!channel->isActive()); + QVERIFY(!query->isActive()); + + QCOMPARE(channelActiveSpy.count(), ++channelActiveCount); + QCOMPARE(queryActiveSpy.count(), ++queryActiveCount); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + QVERIFY(!channel->isActive()); + QVERIFY(query->isActive()); + + QCOMPARE(channelActiveSpy.count(), channelActiveCount); + QCOMPARE(queryActiveSpy.count(), ++queryActiveCount); + + QVERIFY(waitForWritten(":communi!communi@hidd.en JOIN :#communi")); + + QVERIFY(channel->isActive()); + QVERIFY(query->isActive()); + + QCOMPARE(channelActiveSpy.count(), ++channelActiveCount); + QCOMPARE(queryActiveSpy.count(), queryActiveCount); + + QVERIFY(waitForWritten(":communi!communi@hidd.en PART #communi")); + + QVERIFY(!channel->isActive()); + QVERIFY(query->isActive()); + + QCOMPARE(channelActiveSpy.count(), ++channelActiveCount); + QCOMPARE(queryActiveSpy.count(), queryActiveCount); + + connection->close(); + + QVERIFY(!channel->isActive()); + QVERIFY(!query->isActive()); + + QCOMPARE(channelActiveSpy.count(), channelActiveCount); + QCOMPARE(queryActiveSpy.count(), ++queryActiveCount); +} + +void tst_IrcBufferModel::testRoles() +{ + IrcBufferModel model; + QHash roles = model.roleNames(); + QCOMPARE(roles.take(Qt::DisplayRole), QByteArray("display")); + QCOMPARE(roles.take(Irc::BufferRole), QByteArray("buffer")); + QCOMPARE(roles.take(Irc::ChannelRole), QByteArray("channel")); + QCOMPARE(roles.take(Irc::NameRole), QByteArray("name")); + QCOMPARE(roles.take(Irc::PrefixRole), QByteArray("prefix")); + QCOMPARE(roles.take(Irc::TitleRole), QByteArray("title")); + QVERIFY(roles.isEmpty()); +} + +void tst_IrcBufferModel::testAIM() +{ + IrcBufferModel bufferModel(connection); + IrcBuffer* a = bufferModel.add("#a"); + IrcBuffer* b = bufferModel.add("#b"); + IrcBuffer* c = bufferModel.add("c"); + IrcBuffer* o = 0; + + QAbstractItemModel* aim = &bufferModel; + QModelIndex ai = aim->index(0, 0); + QModelIndex bi = aim->index(1, 0); + QModelIndex ci = aim->index(2, 0); + QModelIndex oi = aim->index(100, 100); + + QVERIFY(ai.isValid()); + QVERIFY(bi.isValid()); + QVERIFY(ci.isValid()); + QVERIFY(!oi.isValid()); + + QCOMPARE(aim->rowCount(QModelIndex()), 3); + QCOMPARE(aim->rowCount(ai), 0); + + QCOMPARE(aim->columnCount(QModelIndex()), 1); + QCOMPARE(aim->columnCount(ai), 0); + + QCOMPARE(bufferModel.index(a), ai); + QCOMPARE(bufferModel.index(b), bi); + QCOMPARE(bufferModel.index(c), ci); + QVERIFY(!bufferModel.index(o).isValid()); + + QCOMPARE(bufferModel.buffer(ai), a); + QCOMPARE(bufferModel.buffer(bi), b); + QCOMPARE(bufferModel.buffer(ci), c); + QVERIFY(!bufferModel.buffer(oi)); + + bufferModel.setDisplayRole(Irc::TitleRole); + QCOMPARE(aim->data(ai, Qt::DisplayRole).toString(), a->title()); + QCOMPARE(aim->data(bi, Qt::DisplayRole).toString(), b->title()); + QCOMPARE(aim->data(ci, Qt::DisplayRole).toString(), c->title()); + QVERIFY(aim->data(oi, Qt::DisplayRole).toString().isEmpty()); + + bufferModel.setDisplayRole(Irc::BufferRole); + QCOMPARE(aim->data(ai, Qt::DisplayRole).value(), a); + QCOMPARE(aim->data(bi, Qt::DisplayRole).value(), b); + QCOMPARE(aim->data(ci, Qt::DisplayRole).value(), c); + QVERIFY(!aim->data(oi, Qt::DisplayRole).value()); + + QCOMPARE(aim->data(ai, Irc::BufferRole).value(), a); + QCOMPARE(aim->data(bi, Irc::BufferRole).value(), b); + QCOMPARE(aim->data(ci, Irc::BufferRole).value(), c); + QVERIFY(!aim->data(oi, Irc::BufferRole).value()); + + QCOMPARE(aim->data(ai, Irc::ChannelRole).value(), a->toChannel()); + QCOMPARE(aim->data(bi, Irc::ChannelRole).value(), b->toChannel()); + QCOMPARE(aim->data(ci, Irc::ChannelRole).value(), c->toChannel()); + QVERIFY(!aim->data(oi, Irc::ChannelRole).value()); + + QCOMPARE(aim->data(ai, Irc::TitleRole).toString(), a->title()); + QCOMPARE(aim->data(bi, Irc::TitleRole).toString(), b->title()); + QCOMPARE(aim->data(ci, Irc::TitleRole).toString(), c->title()); + QVERIFY(aim->data(oi, Irc::TitleRole).toString().isEmpty()); + + QCOMPARE(aim->data(ai, Irc::NameRole).toString(), a->name()); + QCOMPARE(aim->data(bi, Irc::NameRole).toString(), b->name()); + QCOMPARE(aim->data(ci, Irc::NameRole).toString(), c->name()); + QVERIFY(aim->data(oi, Irc::NameRole).toString().isEmpty()); + + QVERIFY(aim->data(ai, Irc::PrefixRole).toString().isEmpty()); + QVERIFY(aim->data(bi, Irc::PrefixRole).toString().isEmpty()); + QVERIFY(aim->data(ci, Irc::PrefixRole).toString().isEmpty()); + QVERIFY(aim->data(oi, Irc::PrefixRole).toString().isEmpty()); +} + +class FakeQmlBufferModel : public IrcBufferModel +{ + Q_OBJECT + friend class tst_IrcBufferModel; + +public slots: + // -Wno-overloaded-virtual + QVariant createBuffer(const QVariant& title) + { + IrcBuffer* buffer = IrcBufferModel::createBuffer(title.toString()); + buffer->setObjectName("QML buffer"); + return QVariant::fromValue(buffer); + } + QVariant createChannel(const QVariant& title) + { + IrcChannel* channel = IrcBufferModel::createChannel(title.toString()); + channel->setObjectName("QML channel"); + return QVariant::fromValue(channel); + } +}; + +void tst_IrcBufferModel::testQML() +{ + FakeQmlBufferModel model; + model.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + QCOMPARE(model.add("buffer")->objectName(), QString("QML buffer")); + QCOMPARE(model.add("#channel")->objectName(), QString("QML channel")); +} + +void tst_IrcBufferModel::testWarnings() +{ + IrcBufferModel model(connection); + model.setConnection(connection); + + QTest::ignoreMessage(QtCriticalMsg, "IrcBufferModel::setConnection(): changing the connection on the fly is not supported."); + + IrcConnection another; + model.setConnection(&another); +} + +QTEST_MAIN(tst_IrcBufferModel) + +#include "tst_ircbuffermodel.moc" diff --git a/src/libcommuni/tests/auto/ircchannel/ircchannel.pro b/src/libcommuni/tests/auto/ircchannel/ircchannel.pro new file mode 100644 index 0000000..8f9b87b --- /dev/null +++ b/src/libcommuni/tests/auto/ircchannel/ircchannel.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircchannel.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircchannel/tst_ircchannel.cpp b/src/libcommuni/tests/auto/ircchannel/tst_ircchannel.cpp new file mode 100644 index 0000000..54fdf31 --- /dev/null +++ b/src/libcommuni/tests/auto/ircchannel/tst_ircchannel.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircchannel.h" +#include +#include + +class tst_IrcChannel : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testSignals(); + void testDebug(); +}; + +void tst_IrcChannel::testDefaults() +{ + IrcChannel channel; + QVERIFY(channel.title().isEmpty()); + QVERIFY(channel.name().isEmpty()); + QVERIFY(channel.prefix().isEmpty()); + QVERIFY(channel.isChannel()); + QVERIFY(channel.toChannel()); + QVERIFY(!channel.connection()); + QVERIFY(!channel.network()); + QVERIFY(!channel.model()); + QVERIFY(!channel.isActive()); + QVERIFY(!channel.isSticky()); + QVERIFY(!channel.isPersistent()); + QVERIFY(channel.mode().isEmpty()); + QVERIFY(channel.topic().isEmpty()); +} + +void tst_IrcChannel::testSignals() +{ + IrcChannel channel; + QSignalSpy modeSpy(&channel, SIGNAL(modeChanged(QString))); + QSignalSpy topicSpy(&channel, SIGNAL(topicChanged(QString))); + QVERIFY(modeSpy.isValid()); + QVERIFY(topicSpy.isValid()); +} + +void tst_IrcChannel::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcChannel(0x0)")); + str.clear(); + + IrcChannel channel; + dbg << &channel; + QVERIFY(QRegExp("IrcChannel\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str)); + str.clear(); + + channel.setObjectName("obj"); + dbg << &channel; + QVERIFY(QRegExp("IrcChannel\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str)); + str.clear(); + + channel.setPrefix("#"); + channel.setName("communi"); + dbg << &channel; + QVERIFY(QRegExp("IrcChannel\\(0x[0-9A-Fa-f]+, name=obj, title=#communi\\) ").exactMatch(str)); + str.clear(); +} + +QTEST_MAIN(tst_IrcChannel) + +#include "tst_ircchannel.moc" diff --git a/src/libcommuni/tests/auto/irccommand/irccommand.pro b/src/libcommuni/tests/auto/irccommand/irccommand.pro new file mode 100644 index 0000000..50a631e --- /dev/null +++ b/src/libcommuni/tests/auto/irccommand/irccommand.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irccommand.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irccommand/tst_irccommand.cpp b/src/libcommuni/tests/auto/irccommand/tst_irccommand.cpp new file mode 100644 index 0000000..563cacc --- /dev/null +++ b/src/libcommuni/tests/auto/irccommand/tst_irccommand.cpp @@ -0,0 +1,529 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irccommand.h" +#include "ircmessage.h" +#include "ircconnection.h" +#include +#include +#include +#include + +class tst_IrcCommand : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + + void testEncoding_data(); + void testEncoding(); + + void testConversion(); + + void testAdmin(); + void testAway(); + void testCapability(); + void testCtcpAction(); + void testCtcpReply(); + void testCtcpRequest(); + void testInfo(); + void testInvite(); + void testJoin(); + void testKick(); + void testKnock(); + void testList(); + void testMessage(); + void testMode(); + void testMotd(); + void testNames(); + void testNick(); + void testNotice(); + void testPart(); + void testPing(); + void testPong(); + void testQuit(); + void testQuote(); + void testStats(); + void testTime(); + void testTopic(); + void testTrace(); + void testUsers(); + void testVersion(); + void testWho(); + void testWhois(); + void testWhowas(); + + void testDebug(); +}; + +void tst_IrcCommand::testDefaults() +{ + IrcCommand cmd; + QVERIFY(cmd.parameters().isEmpty()); + QCOMPARE(cmd.type(), IrcCommand::Custom); + QCOMPARE(cmd.encoding(), QByteArray("UTF-8")); + + QTest::ignoreMessage(QtWarningMsg, "Reimplement IrcCommand::toString() for IrcCommand::Custom"); + QVERIFY(cmd.toString().isEmpty()); +} + +void tst_IrcCommand::testEncoding_data() +{ + QTest::addColumn("encoding"); + QTest::addColumn("actual"); + QTest::addColumn("supported"); + + QTest::newRow("null") << QByteArray() << QByteArray("UTF-8") << false; + QTest::newRow("empty") << QByteArray("") << QByteArray("UTF-8") << false; + QTest::newRow("space") << QByteArray(" ") << QByteArray("UTF-8") << false; + QTest::newRow("invalid") << QByteArray("invalid") << QByteArray("UTF-8") << false; + foreach (const QByteArray& codec, QTextCodec::availableCodecs()) + QTest::newRow(codec) << codec << codec << true; +} + +void tst_IrcCommand::testEncoding() +{ + QFETCH(QByteArray, encoding); + QFETCH(QByteArray, actual); + QFETCH(bool, supported); + + if (!supported) + QTest::ignoreMessage(QtWarningMsg, "IrcCommand::setEncoding(): unsupported encoding \"" + encoding + "\" "); + + IrcCommand cmd; + cmd.setEncoding(encoding); + QCOMPARE(cmd.encoding(), actual); +} + +void tst_IrcCommand::testConversion() +{ + QScopedPointer cmd(IrcCommand::createMessage("target", "foo bar")); + QVERIFY(cmd.data()); + QCOMPARE(cmd->type(), IrcCommand::Message); + + IrcConnection conn; + QScopedPointer msg(cmd->toMessage("prefix", &conn)); + QVERIFY(msg.data()); + + QCOMPARE(msg->type(), IrcMessage::Private); + QCOMPARE(msg->connection(), &conn); + QCOMPARE(msg->prefix(), QString("prefix")); + QCOMPARE(msg->property("target").toString(), QString("target")); + QCOMPARE(msg->property("content").toString(), QString("foo bar")); +} + +void tst_IrcCommand::testAdmin() +{ + QScopedPointer cmd(IrcCommand::createAdmin("server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Admin); + QVERIFY(cmd->toString().contains(QRegExp("\\bADMIN\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testAway() +{ + QScopedPointer cmd(IrcCommand::createAway("reason")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Away); + QVERIFY(cmd->toString().contains(QRegExp("\\bAWAY\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\breason\\b"))); +} + +void tst_IrcCommand::testCapability() +{ + QScopedPointer cmd1(IrcCommand::createCapability("sub", QString("cap"))); + QVERIFY(cmd1.data()); + + QCOMPARE(cmd1->type(), IrcCommand::Capability); + QVERIFY(cmd1->toString().contains(QRegExp("\\bCAP\\b"))); + QVERIFY(cmd1->toString().contains(QRegExp("\\bsub\\b"))); + QVERIFY(cmd1->toString().contains(QRegExp("\\bcap\\b"))); + + QScopedPointer cmd2(IrcCommand::createCapability("sub", QStringList() << "cap1" << "cap2")); + QVERIFY(cmd2.data()); + + QCOMPARE(cmd2->type(), IrcCommand::Capability); + QVERIFY(cmd2->toString().contains(QRegExp("\\bCAP\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bsub\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bcap1\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bcap2\\b"))); +} + +void tst_IrcCommand::testCtcpAction() +{ + QScopedPointer cmd(IrcCommand::createCtcpAction("tgt", "act")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::CtcpAction); + QVERIFY(cmd->toString().contains(QRegExp("\\bPRIVMSG\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bact\\b"))); + QCOMPARE(cmd->toString().count("\01"), 2); +} + +void tst_IrcCommand::testCtcpReply() +{ + QScopedPointer cmd(IrcCommand::createCtcpReply("tgt", "rpl")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::CtcpReply); + QVERIFY(cmd->toString().contains(QRegExp("\\bNOTICE\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\brpl\\b"))); + QCOMPARE(cmd->toString().count("\01"), 2); +} + +void tst_IrcCommand::testCtcpRequest() +{ + QScopedPointer cmd(IrcCommand::createCtcpRequest("tgt", "req")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::CtcpRequest); + QVERIFY(cmd->toString().contains(QRegExp("\\bPRIVMSG\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\breq\\b"))); + QCOMPARE(cmd->toString().count("\01"), 2); +} + +void tst_IrcCommand::testInfo() +{ + QScopedPointer cmd(IrcCommand::createInfo("server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Info); + QVERIFY(cmd->toString().contains(QRegExp("\\bINFO\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testInvite() +{ + QScopedPointer cmd(IrcCommand::createInvite("usr", "chan")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Invite); + QVERIFY(cmd->toString().contains(QRegExp("\\bINVITE\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\busr\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan\\b"))); +} + +void tst_IrcCommand::testJoin() +{ + QScopedPointer cmd1(IrcCommand::createJoin("chan")); + QVERIFY(cmd1.data()); + + QCOMPARE(cmd1->type(), IrcCommand::Join); + QVERIFY(cmd1->toString().contains(QRegExp("\\bJOIN\\b"))); + QVERIFY(cmd1->toString().contains(QRegExp("\\bchan\\b"))); + + QScopedPointer cmd2(IrcCommand::createJoin(QStringList() << "chan1" << "chan2")); + QVERIFY(cmd2.data()); + + QCOMPARE(cmd2->type(), IrcCommand::Join); + QVERIFY(cmd2->toString().contains(QRegExp("\\bJOIN\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan1\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan2\\b"))); +} + +void tst_IrcCommand::testKick() +{ + QScopedPointer cmd(IrcCommand::createKick("chan", "usr")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Kick); + QVERIFY(cmd->toString().contains(QRegExp("\\bKICK\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\busr\\b"))); +} + +void tst_IrcCommand::testKnock() +{ + QScopedPointer cmd(IrcCommand::createKnock("chan")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Knock); + QVERIFY(cmd->toString().contains(QRegExp("\\bKNOCK\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan\\b"))); +} + +void tst_IrcCommand::testList() +{ + QScopedPointer cmd(IrcCommand::createList(QStringList() << "chan1" << "chan2", "server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::List); + QVERIFY(cmd->toString().contains(QRegExp("\\bLIST\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan1\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan2\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testMessage() +{ + QScopedPointer cmd(IrcCommand::createMessage("tgt", "msg")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Message); + QVERIFY(cmd->toString().contains(QRegExp("\\bPRIVMSG\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmsg\\b"))); +} + +void tst_IrcCommand::testMode() +{ + QScopedPointer cmd(IrcCommand::createMode("tgt", "mode")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Mode); + QVERIFY(cmd->toString().contains(QRegExp("\\bMODE\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmode\\b"))); +} + +void tst_IrcCommand::testMotd() +{ + QScopedPointer cmd(IrcCommand::createMotd("server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Motd); + QVERIFY(cmd->toString().contains(QRegExp("\\bMOTD\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testNames() +{ + QScopedPointer cmd1(IrcCommand::createNames("chan")); + QVERIFY(cmd1.data()); + + QCOMPARE(cmd1->type(), IrcCommand::Names); + QVERIFY(cmd1->toString().contains(QRegExp("\\bNAMES\\b"))); + QVERIFY(cmd1->toString().contains(QRegExp("\\bchan\\b"))); + + QScopedPointer cmd2(IrcCommand::createNames(QStringList() << "chan1" << "chan2")); + QVERIFY(cmd2.data()); + + QCOMPARE(cmd2->type(), IrcCommand::Names); + QVERIFY(cmd2->toString().contains(QRegExp("\\bNAMES\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan1\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan2\\b"))); +} + +void tst_IrcCommand::testNick() +{ + QScopedPointer cmd(IrcCommand::createNick("nick")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Nick); + QVERIFY(cmd->toString().contains(QRegExp("\\bNICK\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bnick\\b"))); +} + +void tst_IrcCommand::testNotice() +{ + QScopedPointer cmd(IrcCommand::createNotice("tgt", "msg")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Notice); + QVERIFY(cmd->toString().contains(QRegExp("\\bNOTICE\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btgt\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmsg\\b"))); +} + +void tst_IrcCommand::testPart() +{ + QScopedPointer cmd1(IrcCommand::createPart("chan")); + QVERIFY(cmd1.data()); + + QCOMPARE(cmd1->type(), IrcCommand::Part); + QVERIFY(cmd1->toString().contains(QRegExp("\\bPART\\b"))); + QVERIFY(cmd1->toString().contains(QRegExp("\\bchan\\b"))); + + QScopedPointer cmd2(IrcCommand::createPart(QStringList() << "chan1" << "chan2")); + QVERIFY(cmd2.data()); + + QCOMPARE(cmd2->type(), IrcCommand::Part); + QVERIFY(cmd2->toString().contains(QRegExp("\\bPART\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan1\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bchan2\\b"))); +} + +void tst_IrcCommand::testPing() +{ + QScopedPointer cmd(IrcCommand::createPing("arg")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Ping); + QVERIFY(cmd->toString().contains(QRegExp("\\bPING\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\barg\\b"))); +} + +void tst_IrcCommand::testPong() +{ + QScopedPointer cmd(IrcCommand::createPong("arg")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Pong); + QVERIFY(cmd->toString().contains(QRegExp("\\bPONG\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\barg\\b"))); +} + +void tst_IrcCommand::testQuit() +{ + QScopedPointer cmd(IrcCommand::createQuit("reason")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Quit); + QVERIFY(cmd->toString().contains(QRegExp("\\bQUIT\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\breason\\b"))); +} + +void tst_IrcCommand::testQuote() +{ + QScopedPointer cmd1(IrcCommand::createQuote("CUSTOM")); + QVERIFY(cmd1.data()); + + QCOMPARE(cmd1->type(), IrcCommand::Quote); + QVERIFY(cmd1->toString().contains(QRegExp("\\bCUSTOM\\b"))); + + QScopedPointer cmd2(IrcCommand::createQuote(QStringList() << "FOO" << "BAR")); + QVERIFY(cmd2.data()); + + QCOMPARE(cmd2->type(), IrcCommand::Quote); + QVERIFY(cmd2->toString().contains(QRegExp("\\bFOO\\b"))); + QVERIFY(cmd2->toString().contains(QRegExp("\\bBAR\\b"))); +} + +void tst_IrcCommand::testStats() +{ + QScopedPointer cmd(IrcCommand::createStats("query", "server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Stats); + QVERIFY(cmd->toString().contains(QRegExp("\\bSTATS\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bquery\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testTime() +{ + QScopedPointer cmd(IrcCommand::createTime("server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Time); + QVERIFY(cmd->toString().contains(QRegExp("\\bTIME\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testTopic() +{ + QScopedPointer cmd(IrcCommand::createTopic("chan", "topic")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Topic); + QVERIFY(cmd->toString().contains(QRegExp("\\bTOPIC\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bchan\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btopic\\b"))); +} + +void tst_IrcCommand::testTrace() +{ + QScopedPointer cmd(IrcCommand::createTrace("target")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Trace); + QVERIFY(cmd->toString().contains(QRegExp("\\bTRACE\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\btarget\\b"))); +} + +void tst_IrcCommand::testUsers() +{ + QScopedPointer cmd(IrcCommand::createUsers("server")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Users); + QVERIFY(cmd->toString().contains(QRegExp("\\bUSERS\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bserver\\b"))); +} + +void tst_IrcCommand::testVersion() +{ + QScopedPointer cmd(IrcCommand::createVersion("user")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Version); + QVERIFY(cmd->toString().contains(QRegExp("\\bVERSION\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\buser\\b"))); +} + +void tst_IrcCommand::testWho() +{ + QScopedPointer cmd(IrcCommand::createWho("mask")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Who); + QVERIFY(cmd->toString().contains(QRegExp("\\bWHO\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmask\\b"))); +} + +void tst_IrcCommand::testWhois() +{ + QScopedPointer cmd(IrcCommand::createWhois("mask")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Whois); + QVERIFY(cmd->toString().contains(QRegExp("\\bWHOIS\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmask\\b"))); +} + +void tst_IrcCommand::testWhowas() +{ + QScopedPointer cmd(IrcCommand::createWhowas("mask")); + QVERIFY(cmd.data()); + + QCOMPARE(cmd->type(), IrcCommand::Whowas); + QVERIFY(cmd->toString().contains(QRegExp("\\bWHOWAS\\b"))); + QVERIFY(cmd->toString().contains(QRegExp("\\bmask\\b"))); +} + +void tst_IrcCommand::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcCommand(0x0)")); + str.clear(); + + IrcCommand command; + QTest::ignoreMessage(QtWarningMsg, "Reimplement IrcCommand::toString() for IrcCommand::Custom"); + dbg << &command; + QVERIFY(QRegExp("IrcCommand\\(0x[0-9A-Fa-f]+, type=Custom\\) ").exactMatch(str)); + str.clear(); + + command.setType(IrcCommand::Quit); + dbg << &command; + QVERIFY(QRegExp("IrcCommand\\(0x[0-9A-Fa-f]+, type=Quit, \"QUIT :\"\\) ").exactMatch(str)); + str.clear(); + + command.setObjectName("foo"); + dbg << &command; + QVERIFY(QRegExp("IrcCommand\\(0x[0-9A-Fa-f]+, name=foo, type=Quit, \"QUIT :\"\\) ").exactMatch(str)); + str.clear(); + + dbg << IrcCommand::Join; + QCOMPARE(str.trimmed(), QString::fromLatin1("Join")); + str.clear(); +} + +QTEST_MAIN(tst_IrcCommand) + +#include "tst_irccommand.moc" diff --git a/src/libcommuni/tests/auto/irccommandparser/irccommandparser.pro b/src/libcommuni/tests/auto/irccommandparser/irccommandparser.pro new file mode 100644 index 0000000..2fe0bc1 --- /dev/null +++ b/src/libcommuni/tests/auto/irccommandparser/irccommandparser.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irccommandparser.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irccommandparser/tst_irccommandparser.cpp b/src/libcommuni/tests/auto/irccommandparser/tst_irccommandparser.cpp new file mode 100644 index 0000000..6476f28 --- /dev/null +++ b/src/libcommuni/tests/auto/irccommandparser/tst_irccommandparser.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irccommandparser.h" +#include + +class tst_IrcCommandParser : public QObject +{ + Q_OBJECT + +private slots: + void testParse_data(); + void testParse(); + void testTriggers(); + void testTarget(); + void testChannels(); + void testCommands(); + void testClear(); + void testReset(); + void testAddRemove(); + void testSyntax_data(); + void testSyntax(); + void testTolerancy(); + void testCustom(); + void testWhitespace(); +}; + +void tst_IrcCommandParser::testParse_data() +{ + QTest::addColumn("target"); + QTest::addColumn("input"); + QTest::addColumn("output"); + + QTest::newRow("msg") << QString("#communi") << QString("Hello all!") << QString("PRIVMSG #communi :Hello all!"); + QTest::newRow("//msg") << QString("#communi") << QString("//msg test") << QString("PRIVMSG #communi :/msg test"); + QTest::newRow("/ /msg") << QString("#communi") << QString("/ /msg test") << QString("PRIVMSG #communi :/msg test"); + + QTest::newRow("join1") << QString("#communi") << QString("/JOIN") << QString(); + QTest::newRow("join2") << QString("#communi") << QString("/JOIN #chan") << QString("JOIN #chan"); + QTest::newRow("join3") << QString("#communi") << QString("/JOIN #chan secret") << QString("JOIN #chan secret"); + QTest::newRow("join4") << QString("#communi") << QString("/JOIN #chan too secret") << QString(); + + QTest::newRow("part1") << QString("#communi") << QString("/PART") << QString("PART #communi"); + QTest::newRow("part2") << QString("#communi") << QString("/PART #communi") << QString("PART #communi"); + QTest::newRow("part3") << QString("#communi") << QString("/PART #not-exist") << QString("PART #communi :#not-exist"); + QTest::newRow("part4") << QString("#communi") << QString("/PART hasta la vista") << QString("PART #communi :hasta la vista"); + QTest::newRow("part5") << QString("#communi") << QString("/PART #chan hasta la vista") << QString("PART #communi :#chan hasta la vista"); + + QTest::newRow("kick1") << QString("#communi") << QString("/KICK") << QString(); + QTest::newRow("kick2") << QString("#communi") << QString("/KICK #communi") << QString(); + QTest::newRow("kick3") << QString("#communi") << QString("/KICK jpnurmi") << QString("KICK #communi jpnurmi"); + QTest::newRow("kick4") << QString("jpnurmi") << QString("/KICK jpnurmi") << QString(); + QTest::newRow("kick5") << QString("#communi") << QString("/KICK #communi jpnurmi") << QString("KICK #communi jpnurmi"); + QTest::newRow("kick6") << QString("jpnurmi") << QString("/KICK jpnurmi jpnurmi") << QString(); + QTest::newRow("kick7") << QString("#communi") << QString("/KICK #communi jpnurmi hasta la vista") << QString("KICK #communi jpnurmi :hasta la vista"); + QTest::newRow("kick8") << QString("jpnurmi") << QString("/KICK jpnurmi jpnurmi hasta la vista") << QString(); + QTest::newRow("kick9") << QString("#communi") << QString("/KICK jpnurmi hasta la vista") << QString("KICK #communi jpnurmi :hasta la vista"); + + QTest::newRow("me1") << QString("jpnurmi") << QString("/ME") << QString(); + QTest::newRow("me2") << QString("#communi") << QString("/ME loves communi") << QString("PRIVMSG #communi :\1ACTION loves communi\1"); + QTest::newRow("me3") << QString("jpnurmi") << QString("/ME loves communi") << QString("PRIVMSG jpnurmi :\1ACTION loves communi\1"); + + QTest::newRow("action1") << QString("jpnurmi") << QString("/ACTION") << QString(); + QTest::newRow("action2") << QString("#communi") << QString("/ACTION #communi loves communi") << QString("PRIVMSG #communi :\1ACTION loves communi\1"); + QTest::newRow("action3") << QString("jpnurmi") << QString("/ACTION jpnurmi loves communi") << QString("PRIVMSG jpnurmi :\1ACTION loves communi\1"); + QTest::newRow("action4") << QString("jpnurmi") << QString("/ACTION #communi loves communi") << QString("PRIVMSG #communi :\1ACTION loves communi\1"); +} + +void tst_IrcCommandParser::testParse() +{ + QFETCH(QString, target); + QFETCH(QString, input); + QFETCH(QString, output); + + IrcCommandParser parser; + parser.setTolerant(true); + parser.setTriggers(QStringList("/")); + QCOMPARE(parser.triggers(), QStringList("/")); + + parser.addCommand(IrcCommand::Join, "JOIN <#channel> ()"); + parser.addCommand(IrcCommand::Part, "PART (<#channel>) ()"); + parser.addCommand(IrcCommand::Kick, "KICK (<#channel>) ()"); + parser.addCommand(IrcCommand::CtcpAction, "ME [target] "); + parser.addCommand(IrcCommand::CtcpAction, "ACTION "); + + parser.setTarget(target); + parser.setChannels(QStringList() << "#freenode" << "#communi"); + + IrcCommand* cmd = parser.parse(input); + QCOMPARE(cmd ? cmd->toString() : QString(), output); +} + +void tst_IrcCommandParser::testTriggers() +{ + IrcCommandParser parser; + parser.setTriggers(QStringList("/")); + parser.addCommand(IrcCommand::Join, "JOIN #channel"); + parser.setTarget("#target"); + + QSignalSpy triggerSpy(&parser, SIGNAL(triggersChanged(QStringList))); + QVERIFY(triggerSpy.isValid()); + + parser.setTriggers(QStringList("!")); + QCOMPARE(parser.triggers(), QStringList("!")); + QCOMPARE(triggerSpy.count(), 1); + QCOMPARE(triggerSpy.last().at(0).toStringList(), QStringList("!")); + + IrcCommand* cmd = parser.parse("!join #communi"); + QVERIFY(cmd); + QCOMPARE(cmd->type(), IrcCommand::Join); + QCOMPARE(cmd->toString(), QString("JOIN #communi")); + delete cmd; + + parser.setTriggers(QStringList()); + QCOMPARE(parser.triggers(), QStringList()); + QCOMPARE(triggerSpy.count(), 2); + QCOMPARE(triggerSpy.last().at(0).toStringList(), QStringList()); + + cmd = parser.parse("!join #communi"); + QVERIFY(!cmd); + + parser.setTolerant(true); + cmd = parser.parse("!join #communi"); + QCOMPARE(cmd->type(), IrcCommand::Message); + QCOMPARE(cmd->toString(), QString("PRIVMSG #target :!join #communi")); + delete cmd; + + QVERIFY(!parser.parse("")); +} + +void tst_IrcCommandParser::testTarget() +{ + IrcCommandParser parser; + QVERIFY(parser.target().isEmpty()); + + QSignalSpy targetSpy(&parser, SIGNAL(targetChanged(QString))); + QVERIFY(targetSpy.isValid()); + + parser.setTarget("#tgt"); + QCOMPARE(parser.target(), QString("#tgt")); + QCOMPARE(targetSpy.count(), 1); + QCOMPARE(targetSpy.last().at(0).toString(), QString("#tgt")); + + parser.setTarget("#tgt"); + QCOMPARE(targetSpy.count(), 1); + + parser.setTarget(QString()); + QCOMPARE(parser.target(), QString()); + QCOMPARE(targetSpy.count(), 2); + QCOMPARE(targetSpy.last().at(0).toString(), QString()); +} + +void tst_IrcCommandParser::testChannels() +{ + IrcCommandParser parser; + QVERIFY(parser.channels().isEmpty()); + + QSignalSpy channelSpy(&parser, SIGNAL(channelsChanged(QStringList))); + QVERIFY(channelSpy.isValid()); + + parser.setChannels(QStringList() << "#foo" << "#bar"); + QCOMPARE(parser.channels(), QStringList() << "#foo" << "#bar"); + QCOMPARE(channelSpy.count(), 1); + QCOMPARE(channelSpy.last().at(0).toStringList(), QStringList() << "#foo" << "#bar"); + + parser.setChannels(QStringList() << "#foo" << "#bar"); + QCOMPARE(parser.channels(), QStringList() << "#foo" << "#bar"); + QCOMPARE(channelSpy.count(), 1); + + parser.setChannels(QStringList()); + QCOMPARE(parser.channels(), QStringList()); + QCOMPARE(channelSpy.count(), 2); + QCOMPARE(channelSpy.last().at(0).toStringList(), QStringList()); +} + +void tst_IrcCommandParser::testCommands() +{ + IrcCommandParser parser; + + QSignalSpy commandSpy(&parser, SIGNAL(commandsChanged(QStringList))); + QVERIFY(commandSpy.isValid()); + + parser.addCommand(IrcCommand::Join, "JOIN <#channel> ()"); + parser.addCommand(IrcCommand::Part, "PART (<#channel>) ()"); + parser.addCommand(IrcCommand::Kick, "KICK (<#channel>) ()"); + parser.addCommand(IrcCommand::CtcpAction, "ME [target] "); + parser.addCommand(IrcCommand::CtcpAction, "ACTION "); + + QCOMPARE(parser.commands().count(), 5); + QCOMPARE(parser.commands(), QStringList() << "ACTION" << "JOIN" << "KICK" << "ME" << "PART"); + + QCOMPARE(commandSpy.count(), 5); + QCOMPARE(commandSpy.at(0).at(0).toStringList(), QStringList() << "JOIN"); + QCOMPARE(commandSpy.at(1).at(0).toStringList(), QStringList() << "JOIN" << "PART"); + QCOMPARE(commandSpy.at(2).at(0).toStringList(), QStringList() << "JOIN" << "KICK" << "PART"); + QCOMPARE(commandSpy.at(3).at(0).toStringList(), QStringList() << "JOIN" << "KICK" << "ME" << "PART"); + QCOMPARE(commandSpy.at(4).at(0).toStringList(), QStringList() << "ACTION" << "JOIN" << "KICK" << "ME" << "PART"); +} + +void tst_IrcCommandParser::testClear() +{ + IrcCommandParser parser; + parser.addCommand(IrcCommand::Join, "JOIN <#channel> ()"); + parser.addCommand(IrcCommand::Part, "PART (<#channel>) ()"); + parser.addCommand(IrcCommand::Kick, "KICK (<#channel>) ()"); + parser.addCommand(IrcCommand::CtcpAction, "ME [target] "); + parser.addCommand(IrcCommand::CtcpAction, "ACTION "); + QCOMPARE(parser.commands().count(), 5); + + QSignalSpy commandSpy(&parser, SIGNAL(commandsChanged(QStringList))); + QVERIFY(commandSpy.isValid()); + + parser.clear(); + QVERIFY(parser.commands().isEmpty()); + QCOMPARE(commandSpy.count(), 1); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList()); + + parser.clear(); + QVERIFY(parser.commands().isEmpty()); + QCOMPARE(commandSpy.count(), 1); +} + +void tst_IrcCommandParser::testReset() +{ + IrcCommandParser parser; + + QSignalSpy targetSpy(&parser, SIGNAL(targetChanged(QString))); + QVERIFY(targetSpy.isValid()); + + QSignalSpy channelSpy(&parser, SIGNAL(channelsChanged(QStringList))); + QVERIFY(channelSpy.isValid()); + + parser.setTarget("#tgt"); + QCOMPARE(targetSpy.count(), 1); + QCOMPARE(targetSpy.last().at(0).toString(), QString("#tgt")); + + parser.setChannels(QStringList() << "#foo" << "#bar"); + QCOMPARE(channelSpy.count(), 1); + QCOMPARE(channelSpy.last().at(0).toStringList(), QStringList() << "#foo" << "#bar"); + + parser.reset(); + + QCOMPARE(targetSpy.count(), 2); + QCOMPARE(targetSpy.last().at(0).toString(), QString()); + + QCOMPARE(channelSpy.count(), 2); + QCOMPARE(channelSpy.last().at(0).toStringList(), QStringList()); + + parser.reset(); + QCOMPARE(targetSpy.count(), 2); + QCOMPARE(channelSpy.count(), 2); +} + +void tst_IrcCommandParser::testAddRemove() +{ + IrcCommandParser parser; + QVERIFY(parser.commands().isEmpty()); + + QSignalSpy commandSpy(&parser, SIGNAL(commandsChanged(QStringList))); + QVERIFY(commandSpy.isValid()); + + parser.addCommand(IrcCommand::Join, "join <#channel> ()"); + QCOMPARE(parser.commands(), QStringList() << "JOIN"); + QCOMPARE(commandSpy.count(), 1); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "JOIN"); + + parser.addCommand(IrcCommand::Join, "join "); + QCOMPARE(parser.commands(), QStringList() << "JOIN"); + QCOMPARE(commandSpy.count(), 1); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "JOIN"); + + parser.addCommand(IrcCommand::Part, "Part (<#channel>) ()"); + QCOMPARE(parser.commands(), QStringList() << "JOIN" << "PART"); + QCOMPARE(commandSpy.count(), 2); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "JOIN" << "PART"); + + parser.addCommand(IrcCommand::Part, "PART "); + QCOMPARE(parser.commands(), QStringList() << "JOIN" << "PART"); + QCOMPARE(commandSpy.count(), 2); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "JOIN" << "PART"); + + parser.removeCommand(IrcCommand::Join); + QCOMPARE(parser.commands(), QStringList() << "PART"); + QCOMPARE(commandSpy.count(), 3); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "PART"); + + parser.removeCommand(IrcCommand::Part, "PART "); + QCOMPARE(parser.commands(), QStringList() << "PART"); + QCOMPARE(commandSpy.count(), 3); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList() << "PART"); + + parser.removeCommand(IrcCommand::Part, "Part (<#channel>) ()"); + QCOMPARE(parser.commands(), QStringList()); + QCOMPARE(commandSpy.count(), 4); + QCOMPARE(commandSpy.last().at(0).toStringList(), QStringList()); + QVERIFY(parser.commands().isEmpty()); +} + +void tst_IrcCommandParser::testSyntax_data() +{ + QTest::addColumn("command"); + QTest::addColumn("syntax"); + QTest::addColumn("details"); + QTest::addColumn("expected"); + + QTest::newRow("full") + << QString("foo") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::Full) + << QString("FOO [param] <#chan> () ()"); + + QTest::newRow("no target") + << QString("fOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoTarget) + << QString("FOO <#chan> () ()"); + + QTest::newRow("no ellipsis") + << QString("fOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoEllipsis) + << QString("FOO [param] <#chan> () ()"); + + QTest::newRow("no prefix") + << QString("fOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoPrefix) + << QString("FOO [param] () ()"); + + QTest::newRow("no parentheses") + << QString("Foo") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoParentheses) + << QString("FOO [param] <#chan> "); + + QTest::newRow("no brackets") + << QString("FOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoBrackets) + << QString("FOO param <#chan> () ()"); + + QTest::newRow("no angles") + << QString("FOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::NoAngles) + << QString("FOO [param] #chan (arg) (rest...)"); + + QTest::newRow("visual") + << QString("FOO") + << QString("FOO [param] <#chan> () ()") + << uint(IrcCommandParser::Visual) + << QString("FOO () ()"); +} + +void tst_IrcCommandParser::testSyntax() +{ + QFETCH(QString, command); + QFETCH(QString, syntax); + QFETCH(uint, details); + QFETCH(QString, expected); + + IrcCommandParser parser; + parser.addCommand(IrcCommand::Custom, syntax); + QString actual = parser.syntax(command, IrcCommandParser::Details(details)); + QCOMPARE(actual, expected); +} + +void tst_IrcCommandParser::testTolerancy() +{ + IrcCommandParser parser; + parser.setTriggers(QStringList("/")); + QVERIFY(!parser.isTolerant()); + + IrcCommand* cmd = parser.parse("/NS help"); + QVERIFY(!cmd); + + QSignalSpy tolerancySpy(&parser, SIGNAL(tolerancyChanged(bool))); + QVERIFY(tolerancySpy.isValid()); + + parser.setTolerant(true); + QVERIFY(parser.isTolerant()); + QCOMPARE(tolerancySpy.count(), 1); + QCOMPARE(tolerancySpy.last().at(0).toBool(), true); + + parser.setTolerant(true); + QVERIFY(parser.isTolerant()); + QCOMPARE(tolerancySpy.count(), 1); + + cmd = parser.parse("/NS help"); + QVERIFY(cmd); + QCOMPARE(cmd->type(), IrcCommand::Quote); + QCOMPARE(cmd->toString(), QString("NS help")); + + parser.setTolerant(false); + QVERIFY(!parser.isTolerant()); + QCOMPARE(tolerancySpy.count(), 2); + QCOMPARE(tolerancySpy.last().at(0).toBool(), false); +} + +void tst_IrcCommandParser::testCustom() +{ + IrcCommandParser parser; + parser.setTriggers(QStringList("/")); + + parser.addCommand(IrcCommand::Custom, "Hello "); + QCOMPARE(parser.commands(), QStringList() << "HELLO"); + QCOMPARE(parser.syntax("HELLO"), QString("HELLO ")); + + QVERIFY(!parser.parse("/hello")); + QVERIFY(!parser.parse("/hello foo")); + QVERIFY(!parser.parse("/hello foo bar")); + QVERIFY(!parser.parse("/hello foo bar foo baz")); + + IrcCommand* cmd = parser.parse("/hello foo bar baz"); + QVERIFY(cmd); + QCOMPARE(cmd->type(), IrcCommand::Custom); + QCOMPARE(cmd->parameters(), QStringList() << "HELLO" << "foo" << "bar" << "baz"); + delete cmd; +} + +void tst_IrcCommandParser::testWhitespace() +{ + IrcCommandParser parser; + parser.setTriggers(QStringList("/")); + parser.addCommand(IrcCommand::Custom, "TEST "); + + IrcCommand* cmd = parser.parse("/test foo bar baz"); + QVERIFY(cmd); + QCOMPARE(cmd->type(), IrcCommand::Custom); + QCOMPARE(cmd->parameters(), QStringList() << "TEST" << "foo bar baz"); + delete cmd; +} + +QTEST_MAIN(tst_IrcCommandParser) + +#include "tst_irccommandparser.moc" diff --git a/src/libcommuni/tests/auto/irccompleter/irccompleter.pro b/src/libcommuni/tests/auto/irccompleter/irccompleter.pro new file mode 100644 index 0000000..5d8306a --- /dev/null +++ b/src/libcommuni/tests/auto/irccompleter/irccompleter.pro @@ -0,0 +1,8 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irccompleter.cpp + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irccompleter/tst_irccompleter.cpp b/src/libcommuni/tests/auto/irccompleter/tst_irccompleter.cpp new file mode 100644 index 0000000..5eef644 --- /dev/null +++ b/src/libcommuni/tests/auto/irccompleter/tst_irccompleter.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irccompleter.h" +#include "ircbuffermodel.h" +#include "irccommandparser.h" +#include "ircchannel.h" +#include "ircbuffer.h" +#include +#include "tst_ircclientserver.h" +#include "tst_ircdata.h" + +class tst_IrcCompleter : public tst_IrcClientServer +{ + Q_OBJECT + +private slots: + void testSuffix(); + void testBuffer(); + void testParser(); + + void testCompletion_data(); + void testCompletion(); + + void testReset(); +}; + +void tst_IrcCompleter::testSuffix() +{ + IrcCompleter completer; + QCOMPARE(completer.suffix(), QString(":")); + QCOMPARE(completer.property("suffix").toString(), QString(":")); + + QSignalSpy spy(&completer, SIGNAL(suffixChanged(QString))); + QVERIFY(spy.isValid()); + + completer.setSuffix(","); + QCOMPARE(completer.suffix(), QString(",")); + QCOMPARE(completer.property("suffix").toString(), QString(",")); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().at(0).toString(), QString(",")); +} + +void tst_IrcCompleter::testBuffer() +{ + qRegisterMetaType("IrcBuffer*"); + + IrcCompleter completer; + QVERIFY(!completer.buffer()); + + QSignalSpy spy(&completer, SIGNAL(bufferChanged(IrcBuffer*))); + QVERIFY(spy.isValid()); + + IrcBuffer* buffer = new IrcBuffer(&completer); + completer.setBuffer(buffer); + QCOMPARE(completer.buffer(), buffer); + QCOMPARE(completer.property("buffer").value(), buffer); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().at(0).value(), buffer); + + completer.setBuffer(0); + QVERIFY(!completer.buffer()); + QCOMPARE(spy.count(), 2); + QVERIFY(!spy.last().at(0).value()); +} + +void tst_IrcCompleter::testParser() +{ + qRegisterMetaType("IrcCommandParser*"); + + IrcCompleter completer; + QVERIFY(!completer.parser()); + + QSignalSpy spy(&completer, SIGNAL(parserChanged(IrcCommandParser*))); + QVERIFY(spy.isValid()); + + IrcCommandParser* parser = new IrcCommandParser(&completer); + completer.setParser(parser); + QCOMPARE(completer.parser(), parser); + QCOMPARE(completer.property("parser").value(), parser); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().at(0).value(), parser); + + completer.setParser(0); + QVERIFY(!completer.parser()); + QCOMPARE(spy.count(), 2); + QVERIFY(!spy.last().at(0).value()); +} + +Q_DECLARE_METATYPE(QList) +void tst_IrcCompleter::testCompletion_data() +{ + QTest::addColumn("suffix"); + QTest::addColumn("text"); + QTest::addColumn("cursor"); + QTest::addColumn("completions"); + QTest::addColumn >("positions"); + + for (int i = -1; i <= 3; ++i) + QTest::newRow("/j @ " + QByteArray::number(i)) << QString() << "/j" << i << QStringList("/JOIN ") << (QList() << QString("/JOIN ").length()); + + QTest::newRow("/q #2") << QString() << "/q" << QString("/q").length() + << (QStringList() << "/QUERY " << "/QUIT ") + << (QList() << QString("/QUERY ").length() << QString("/QUIT ").length()); + + QTest::newRow("/QUERY q") << QString() << "/quer q " << QString("/quer").length() + << (QStringList("/QUERY q ")) + << (QList() << QString("/QUERY ").length()); + + QTest::newRow("/query q") << QString() << "/query q" << QString("/query q").length() + << (QStringList() << "/query quackgyver " << "/query quelx ") + << (QList() << QString("/query quackgyver ").length() << QString("/query quelx ").length()); + + QTest::newRow("buffers") << QString() << "q" << QString("q").length() + << (QStringList() << "quackgyver " << "quelx ") + << (QList() << QString("quackgyver ").length() << QString("quelx ").length()); + + QTest::newRow("repeat") << QString() << "qtassistant " << QString("qtassistant ").length() + << (QStringList() << "qtassistant " << "qtassistant ") + << (QList() << QString("qtassistant ").length() << QString("qtassistant ").length()); + + QStringList names1; + QStringList names2; + QList positions; + foreach (const QString& name, tst_IrcData::names()) { + if (name.startsWith("je", Qt::CaseInsensitive)) { + names1 += name + ": "; + names2 += name + ", "; + positions += name.length() + 2; + } + } + QTest::newRow("je...:") << ":" << "je" << 1 << names1 << positions; + QTest::newRow("je...,") << "," << "je" << 1 << names2 << positions; + + names1.clear(); + names2.clear(); + positions.clear(); + foreach (const QString& name, tst_IrcData::names()) { + if (name.startsWith("sa", Qt::CaseInsensitive)) { + names1 += "... " + name + " "; + positions += QString("... ").length() + name.length() + QString(" ").length(); + } + } + QTest::newRow("... sa") << QString() << "... sa" << QString("... ").length() << names1 << positions; + + QTest::newRow("spaces") << QString() << "/quit foo qt rest... " << QString("/quit foo qt ").length() + << QStringList("/quit foo qtassistant rest... ") + << (QList() << QString("/quit foo qtassistant ").length()); +} + +void tst_IrcCompleter::testCompletion() +{ + QFETCH(QString, suffix); + QFETCH(QString, text); + QFETCH(int, cursor); + QFETCH(QStringList, completions); + QFETCH(QList, positions); + + IrcBufferModel model(connection); + + connection->open(); + waitForOpened(); + waitForWritten(tst_IrcData::welcome()); + waitForWritten(tst_IrcData::join()); + + model.add("qout"); + model.add("qtassistant"); + + IrcCommandParser parser; + parser.setTriggers(QStringList("/")); + parser.addCommand(IrcCommand::Join, "JOIN <#channel> ()"); + parser.addCommand(IrcCommand::Part, "PART (<#channel>) ()"); + parser.addCommand(IrcCommand::Kick, "KICK (<#channel>) ()"); + parser.addCommand(IrcCommand::CtcpAction, "ME [target] "); + parser.addCommand(IrcCommand::CtcpAction, "ACTION "); + parser.addCommand(IrcCommand::Custom, "QUERY "); + parser.addCommand(IrcCommand::Quit, "QUIT ()"); + + IrcCompleter completer; + completer.setSuffix(suffix); + completer.setBuffer(model.get(0)); + completer.setParser(&parser); + + QSignalSpy spy(&completer, SIGNAL(completed(QString,int))); + QVERIFY(spy.isValid()); + + for (int i = 0; i < completions.count(); ++i) { + completer.complete(text, cursor); + QCOMPARE(spy.count(), i + 1); + QCOMPARE(spy.last().at(0).toString(), completions.at(i)); + QCOMPARE(spy.last().at(1).toInt(), positions.at(i)); + } +} + +void tst_IrcCompleter::testReset() +{ + IrcBufferModel model(connection); + connection->open(); + waitForOpened(); + waitForWritten(tst_IrcData::welcome()); + waitForWritten(tst_IrcData::join()); + IrcChannel* channel = model.get(0)->toChannel(); + QVERIFY(channel); + + IrcCompleter completer; + completer.setBuffer(channel); + + QSignalSpy spy(&completer, SIGNAL(completed(QString,int))); + QVERIFY(spy.isValid()); + + completer.complete("Guest", 5); + QCOMPARE(spy.count(), 1); + QString guest1 = spy.last().at(0).toString(); + QVERIFY(guest1.startsWith("Guest")); + + completer.complete("Guest", 5); + QCOMPARE(spy.count(), 2); + QString guest2 = spy.last().at(0).toString(); + QVERIFY(guest2.startsWith("Guest")); + QVERIFY(guest2 != guest1); + + completer.reset(); + completer.complete("Guest", 5); + QCOMPARE(spy.count(), 3); + QString guest3 = spy.last().at(0).toString(); + QCOMPARE(guest3, guest1); +} + +QTEST_MAIN(tst_IrcCompleter) + +#include "tst_irccompleter.moc" diff --git a/src/libcommuni/tests/auto/ircconnection/ircconnection.pro b/src/libcommuni/tests/auto/ircconnection/ircconnection.pro new file mode 100644 index 0000000..f505a2b --- /dev/null +++ b/src/libcommuni/tests/auto/ircconnection/ircconnection.pro @@ -0,0 +1,11 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircconnection.cpp + +# FakeQmlConnection::createCtcpReply() +*g++*|*clang*:QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircconnection/tst_ircconnection.cpp b/src/libcommuni/tests/auto/ircconnection/tst_ircconnection.cpp new file mode 100644 index 0000000..6f52b92 --- /dev/null +++ b/src/libcommuni/tests/auto/ircconnection/tst_ircconnection.cpp @@ -0,0 +1,1721 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irc.h" +#include "irccommand.h" +#include "ircprotocol.h" +#include "ircconnection.h" +#include "ircmessage.h" +#include "ircfilter.h" +#include +#include +#include +#include +#ifndef QT_NO_OPENSSL +#include +#endif + +#include "tst_ircdata.h" +#include "tst_ircclientserver.h" + +class FriendlyConnection : public IrcConnection +{ + friend class tst_IrcConnection; +}; + +class TestProtocol : public IrcProtocol +{ +public: + TestProtocol(IrcConnection* connection) : IrcProtocol(connection) + { + } + + virtual bool write(const QByteArray& data) + { + written = data; + return IrcProtocol::write(data); + } + + QByteArray written; +}; + +class tst_IrcConnection : public tst_IrcClientServer +{ + Q_OBJECT + +private slots: + void testDefaults(); + + void testHost_data(); + void testHost(); + + void testPort_data(); + void testPort(); + + void testUserName_data(); + void testUserName(); + + void testNickName_data(); + void testNickName(); + + void testRealName_data(); + void testRealName(); + + void testPassword_data(); + void testPassword(); + + void testDisplayName_data(); + void testDisplayName(); + + void testEncoding_data(); + void testEncoding(); + + void testSocket_data(); + void testSocket(); + + void testSecure(); + void testSasl(); + void testNoSasl(); + void testSsl(); + + void testOpen(); + void testEnabled(); + + void testStatus(); + void testConnection(); + void testMessages(); + void testMessageFlags(); + void testMessageBuilder(); + + void testSendCommand(); + void testSendData(); + + void testMessageFilter(); + void testCommandFilter(); + + void testDebug(); + void testWarnings(); + + void testCtcp(); +}; + +void tst_IrcConnection::testDefaults() +{ + IrcConnection connection; + QVERIFY(connection.host().isNull()); + QCOMPARE(connection.port(), 6667); + QVERIFY(connection.userName().isNull()); + QVERIFY(connection.nickName().isNull()); + QVERIFY(connection.realName().isNull()); + QVERIFY(connection.password().isNull()); + QVERIFY(connection.displayName().isNull()); + QCOMPARE(connection.encoding(), QByteArray("ISO-8859-15")); + QCOMPARE(connection.status(), IrcConnection::Inactive); + QVERIFY(!connection.isActive()); + QVERIFY(!connection.isConnected()); + QVERIFY(connection.isEnabled()); + QCOMPARE(connection.reconnectDelay(), 0); + QVERIFY(connection.socket()); + QVERIFY(!connection.isSecure()); + QVERIFY(connection.saslMechanism().isNull()); + QVERIFY(!IrcConnection::supportedSaslMechanisms().isEmpty()); + QVERIFY(connection.network()); +} + +void tst_IrcConnection::testHost_data() +{ + QTest::addColumn("host"); + + QTest::newRow("null") << QString(); + QTest::newRow("empty") << QString(""); + QTest::newRow("space") << QString(" "); + QTest::newRow("invalid") << QString("invalid"); + QTest::newRow("local") << QString("127.0.0.1"); +} + +void tst_IrcConnection::testHost() +{ + QFETCH(QString, host); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(hostChanged(QString))); + QVERIFY(spy.isValid()); + connection.setHost(host); + QCOMPARE(connection.host(), host); + QCOMPARE(spy.count(), !host.isEmpty() ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toString(), host); + + IrcConnection another(host); + QCOMPARE(another.host(), host); +} + +void tst_IrcConnection::testPort_data() +{ + QTest::addColumn("port"); + + QTest::newRow("-1") << -1; + QTest::newRow("0") << 0; + QTest::newRow("6666") << 6666; + QTest::newRow("6667") << 6667; + QTest::newRow("6668") << 6668; +} + +void tst_IrcConnection::testPort() +{ + QFETCH(int, port); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(portChanged(int))); + QVERIFY(spy.isValid()); + connection.setPort(port); + QCOMPARE(connection.port(), port); + QCOMPARE(spy.count(), port != 6667 ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toInt(), port); +} + +void tst_IrcConnection::testUserName_data() +{ + QTest::addColumn("name"); + QTest::addColumn("result"); + + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << QString("") << QString(""); + QTest::newRow("space") << QString(" ") << QString(""); + QTest::newRow("spaces") << QString(" foo bar ") << QString("foo"); +} + +void tst_IrcConnection::testUserName() +{ + QFETCH(QString, name); + QFETCH(QString, result); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(userNameChanged(QString))); + QVERIFY(spy.isValid()); + connection.setUserName(name); + QCOMPARE(connection.userName(), result); + QCOMPARE(spy.count(), !result.isEmpty() ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toString(), result); +} + +void tst_IrcConnection::testNickName_data() +{ + QTest::addColumn("name"); + QTest::addColumn("result"); + + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << QString("") << QString(""); + QTest::newRow("space") << QString(" ") << QString(""); + QTest::newRow("spaces") << QString(" foo bar ") << QString("foo"); +} + +void tst_IrcConnection::testNickName() +{ + QFETCH(QString, name); + QFETCH(QString, result); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(nickNameChanged(QString))); + QVERIFY(spy.isValid()); + connection.setNickName(name); + QCOMPARE(connection.nickName(), result); + QCOMPARE(spy.count(), !result.isEmpty() ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toString(), result); +} + +void tst_IrcConnection::testRealName_data() +{ + QTest::addColumn("name"); + QTest::addColumn("result"); + + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << QString("") << QString(""); + QTest::newRow("space") << QString(" ") << QString(" "); + QTest::newRow("spaces") << QString(" foo bar ") << QString(" foo bar "); +} + +void tst_IrcConnection::testRealName() +{ + QFETCH(QString, name); + QFETCH(QString, result); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(realNameChanged(QString))); + QVERIFY(spy.isValid()); + connection.setRealName(name); + QCOMPARE(connection.realName(), result); + QCOMPARE(spy.count(), !result.isEmpty() ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toString(), result); +} + +void tst_IrcConnection::testPassword_data() +{ + QTest::addColumn("passwd"); + QTest::addColumn("result"); + + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << QString("") << QString(""); + QTest::newRow("space") << QString(" ") << QString(" "); + QTest::newRow("spaces") << QString(" foo bar ") << QString(" foo bar "); +} + +void tst_IrcConnection::testPassword() +{ + QFETCH(QString, passwd); + QFETCH(QString, result); + + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(passwordChanged(QString))); + QVERIFY(spy.isValid()); + connection.setPassword(passwd); + QCOMPARE(connection.password(), result); + QCOMPARE(spy.count(), !result.isEmpty() ? 1 : 0); + if (!spy.isEmpty()) + QCOMPARE(spy.first().first().toString(), result); +} + +void tst_IrcConnection::testDisplayName_data() +{ + QTest::addColumn("host"); + QTest::addColumn("name"); + QTest::addColumn("result"); + + QTest::newRow("null") << QString() << QString() << QString(); + QTest::newRow("empty") << QString() << QString("") << QString(""); + QTest::newRow("space") << QString() << QString(" ") << QString(" "); + + QTest::newRow("host") << QString("host") << QString() << QString("host"); + QTest::newRow("name") << QString() << QString("name") << QString("name"); + QTest::newRow("explicit") << QString("host") << QString("name") << QString("name"); +} + +void tst_IrcConnection::testDisplayName() +{ + QFETCH(QString, host); + QFETCH(QString, name); + QFETCH(QString, result); + + IrcConnection connection; + connection.setHost(host); + connection.setDisplayName(name); + QCOMPARE(connection.displayName(), result); +} + +void tst_IrcConnection::testEncoding_data() +{ + QTest::addColumn("encoding"); + QTest::addColumn("actual"); + QTest::addColumn("supported"); + + QTest::newRow("null") << QByteArray() << QByteArray("ISO-8859-15") << false; + QTest::newRow("empty") << QByteArray("") << QByteArray("ISO-8859-15") << false; + QTest::newRow("space") << QByteArray(" ") << QByteArray("ISO-8859-15") << false; + QTest::newRow("invalid") << QByteArray("invalid") << QByteArray("ISO-8859-15") << false; + foreach (const QByteArray& codec, QTextCodec::availableCodecs()) + QTest::newRow(codec) << codec << codec << true; +} + +void tst_IrcConnection::testEncoding() +{ + QFETCH(QByteArray, encoding); + QFETCH(QByteArray, actual); + QFETCH(bool, supported); + + if (!supported) + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setEncoding(): unsupported encoding \"" + encoding + "\" "); + + IrcConnection connection; + connection.setEncoding(encoding); + QCOMPARE(connection.encoding(), actual); +} + +Q_DECLARE_METATYPE(QAbstractSocket*) +void tst_IrcConnection::testSocket_data() +{ + QTest::addColumn("socket"); + + QTest::newRow("null") << static_cast(0); + QTest::newRow("tcp") << static_cast(new QTcpSocket(this)); +#ifndef QT_NO_OPENSSL + QTest::newRow("ssl") << static_cast(new QSslSocket(this)); +#endif +} + +void tst_IrcConnection::testSocket() +{ + QFETCH(QAbstractSocket*, socket); + + IrcConnection connection; + connection.setSocket(socket); + QCOMPARE(connection.socket(), socket); + QCOMPARE(connection.isSecure(), socket && socket->inherits("QSslSocket")); +} + +void tst_IrcConnection::testSecure() +{ + IrcConnection connection; + QSignalSpy spy(&connection, SIGNAL(secureChanged(bool))); + QVERIFY(spy.isValid()); + QVERIFY(!connection.isSecure()); + +#ifdef QT_NO_OPENSSL + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setSecure(): the Qt build does not support SSL"); +#endif + + connection.setSecure(true); + +#ifndef QT_NO_OPENSSL + QVERIFY(connection.isSecure()); + QVERIFY(connection.socket()->inherits("QSslSocket")); + QCOMPARE(spy.count(), 1); + QVERIFY(spy.first().first().toBool()); +#else + QVERIFY(!connection.isSecure()); + QVERIFY(!connection.socket()->inherits("QSslSocket")); + QCOMPARE(spy.count(), 0); +#endif + + connection.setSecure(false); + QVERIFY(!connection.isSecure()); + QVERIFY(!connection.socket()->inherits("QSslSocket")); +#ifndef QT_NO_OPENSSL + QCOMPARE(spy.count(), 2); + QVERIFY(!spy.last().last().toBool()); +#else + QCOMPARE(spy.count(), 0); +#endif +} + +void tst_IrcConnection::testSasl() +{ + QVERIFY(!IrcConnection::supportedSaslMechanisms().contains("UNKNOWN")); + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setSaslMechanism(): unsupported mechanism: 'UNKNOWN'"); + connection->setSaslMechanism("UNKNOWN"); + QVERIFY(connection->saslMechanism().isEmpty()); + + IrcProtocol* protocol = static_cast(connection.data())->protocol(); + QVERIFY(protocol); + + QVERIFY(IrcConnection::supportedSaslMechanisms().contains("PLAIN")); + connection->setSaslMechanism("PLAIN"); + QCOMPARE(connection->saslMechanism(), QString("PLAIN")); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + QByteArray written = serverSocket->readAll(); + QVERIFY(written.contains("CAP LS")); + QVERIFY(written.contains("NICK nick")); + QVERIFY(!written.contains("PASS secret")); + QVERIFY(!written.contains("CAP REQ :sasl")); + + QVERIFY(waitForWritten(":irc.freenode.net CAP * LS :sasl")); + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + written = serverSocket->readAll(); + QVERIFY(!written.contains("CAP LS")); + QVERIFY(!written.contains("NICK nick")); + QVERIFY(!written.contains("PASS secret")); + QVERIFY(written.contains("CAP REQ :sasl")); + + // do not resume handshake too early + QCoreApplication::sendPostedEvents(protocol, QEvent::MetaCall); + QVERIFY(!clientSocket->waitForBytesWritten(1000)); + + QVERIFY(waitForWritten(":irc.freenode.net CAP user ACK :sasl")); + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + QVERIFY(serverSocket->readAll().contains("AUTHENTICATE PLAIN")); + + QVERIFY(waitForWritten("AUTHENTICATE +")); + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + + QByteArray response = serverSocket->readAll(); + int index = response.indexOf("AUTHENTICATE"); + QVERIFY(index != -1); + QByteArray secret = response.mid(index + 13); + index = secret.indexOf("\r\n"); + QVERIFY(index != -1); + secret.truncate(index + 1); + secret = QByteArray::fromBase64(secret); + QByteArray expected = connection->userName().toUtf8() + '\0' + + connection->userName().toUtf8() + '\0' + + connection->password().toUtf8(); + QCOMPARE(secret, expected); + + // resume handshake + QCoreApplication::sendPostedEvents(protocol, QEvent::MetaCall); + + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + QVERIFY(serverSocket->readAll().contains("CAP END")); + + // TODO: + QVERIFY(waitForWritten(":irc.freenode.net 900 user nick!user@host nick :You are now logged in as user.")); + QVERIFY(waitForWritten(":irc.freenode.net 903 user :SASL authentication successful")); + QVERIFY(waitForWritten(":irc.freenode.net 001 user :Welcome to the freenode Internet Relay Chat Network user")); +} + +void tst_IrcConnection::testNoSasl() +{ + QVERIFY(!IrcConnection::supportedSaslMechanisms().contains("UNKNOWN")); + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setSaslMechanism(): unsupported mechanism: 'UNKNOWN'"); + connection->setSaslMechanism("UNKNOWN"); + QVERIFY(connection->saslMechanism().isEmpty()); + + IrcProtocol* protocol = static_cast(connection.data())->protocol(); + QVERIFY(protocol); + + QVERIFY(IrcConnection::supportedSaslMechanisms().contains("PLAIN")); + connection->setSaslMechanism("PLAIN"); + QCOMPARE(connection->saslMechanism(), QString("PLAIN")); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + QByteArray written = serverSocket->readAll(); + QVERIFY(written.contains("CAP LS")); + QVERIFY(written.contains("NICK nick")); + QVERIFY(!written.contains("PASS secret")); + QVERIFY(!written.contains("CAP REQ :sasl")); + + QVERIFY(waitForWritten(":irc.freenode.net CAP * LS :no s-a-s-l here")); + QVERIFY(!clientSocket->waitForBytesWritten(1000)); + QVERIFY(!serverSocket->waitForReadyRead(1000)); + QVERIFY(serverSocket->readAll().isEmpty()); + + // resume handshake + QCoreApplication::sendPostedEvents(protocol, QEvent::MetaCall); + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + written = serverSocket->readAll(); + QVERIFY(written.contains("PASS secret")); + QVERIFY(written.contains("CAP END")); +} + +#ifndef QT_NO_OPENSSL +class SslSocket : public QSslSocket +{ + Q_OBJECT + +public: + SslSocket(QObject* parent) : QSslSocket(parent), clientEncryptionStarted(false) { } + bool clientEncryptionStarted; + +public slots: + void startClientEncryption() + { + clientEncryptionStarted = true; + QSslSocket::startClientEncryption(); + } +}; +#endif // !QT_NO_OPENSSL + +void tst_IrcConnection::testSsl() +{ +#ifndef QT_NO_OPENSSL + SslSocket* socket = new SslSocket(connection); + connection->setSocket(socket); + QCOMPARE(connection->socket(), socket); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(socket->clientEncryptionStarted); +#endif // !QT_NO_OPENSSL +} + +void tst_IrcConnection::testOpen() +{ + IrcConnection connection; + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::open(): host is empty!"); + connection.open(); + QCOMPARE(connection.status(), IrcConnection::Inactive); + + connection.setHost("irc.ser.ver"); + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::open(): userName is empty!"); + connection.open(); + QCOMPARE(connection.status(), IrcConnection::Inactive); + + connection.setUserName("user"); + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::open(): nickName is empty!"); + connection.open(); + QCOMPARE(connection.status(), IrcConnection::Inactive); + + connection.setNickName("nick"); + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::open(): realName is empty!"); + connection.open(); + QCOMPARE(connection.status(), IrcConnection::Inactive); + + connection.setRealName("real"); + connection.open(); + QVERIFY(connection.status() != IrcConnection::Inactive); + + connection.close(); + QCOMPARE(connection.status(), IrcConnection::Closed); + + connection.setEnabled(false); + connection.open(); + QCOMPARE(connection.status(), IrcConnection::Closed); +} + +void tst_IrcConnection::testEnabled() +{ + IrcConnection connection; + QVERIFY(connection.isEnabled()); + + QSignalSpy spy(&connection, SIGNAL(enabledChanged(bool))); + QVERIFY(spy.isValid()); + + connection.setEnabled(false); + QVERIFY(!connection.isEnabled()); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().at(0).toBool(), false); + + connection.setDisabled(true); + QVERIFY(!connection.isEnabled()); + QCOMPARE(spy.count(), 1); + + connection.setDisabled(false); + QVERIFY(connection.isEnabled()); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.last().at(0).toBool(), true); + + connection.setEnabled(true); + QVERIFY(connection.isEnabled()); + QCOMPARE(spy.count(), 2); +} + +void tst_IrcConnection::testStatus() +{ + Irc::registerMetaTypes(); + + QSignalSpy statusSpy(connection, SIGNAL(statusChanged(IrcConnection::Status))); + QSignalSpy connectingSpy(connection, SIGNAL(connecting())); + QSignalSpy connectedSpy(connection, SIGNAL(connected())); + QSignalSpy disconnectedSpy(connection, SIGNAL(disconnected())); + + QVERIFY(statusSpy.isValid()); + QVERIFY(connectingSpy.isValid()); + QVERIFY(connectedSpy.isValid()); + QVERIFY(disconnectedSpy.isValid()); + + int statusCount = 0; + int connectingCount = 0; + int connectedCount = 0; + int disconnectedCount = 0; + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connecting); + QCOMPARE(connectingSpy.count(), ++connectingCount); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QVERIFY(connection->isActive()); + QVERIFY(connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connected); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connected); + QCOMPARE(connectedSpy.count(), ++connectedCount); + + clientSocket->close(); + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closing); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Closing); + + connection->close(); + QVERIFY(!connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closed); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Closed); + QCOMPARE(disconnectedSpy.count(), ++disconnectedCount); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connecting); + QCOMPARE(connectingSpy.count(), ++connectingCount); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QVERIFY(connection->isActive()); + QVERIFY(connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connected); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connected); + QCOMPARE(connectedSpy.count(), ++connectedCount); + + // trigger an error + serverSocket->close(); + QVERIFY(clientSocket->waitForDisconnected(100)); + QVERIFY(!connection->isConnected()); + QVERIFY(!connection->isActive()); + + QCOMPARE(statusSpy.at(statusCount++).at(0).value(), IrcConnection::Error); + QCOMPARE(statusSpy.count(), statusCount); + + connection->close(); + QVERIFY(!connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closed); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Closed); + QCOMPARE(disconnectedSpy.count(), ++disconnectedCount); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connecting); + QCOMPARE(connectingSpy.count(), ++connectingCount); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QVERIFY(connection->isActive()); + QVERIFY(connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connected); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connected); + QCOMPARE(connectedSpy.count(), ++connectedCount); + + // trigger an error - automatic reconnect + connection->setReconnectDelay(1); + serverSocket->close(); + QVERIFY(clientSocket->waitForDisconnected(100)); + QVERIFY(!connection->isConnected()); + QVERIFY(!connection->isActive()); + + QCOMPARE(statusSpy.at(statusCount++).at(0).value(), IrcConnection::Error); + QCOMPARE(statusSpy.at(statusCount++).at(0).value(), IrcConnection::Waiting); + QCOMPARE(statusSpy.count(), statusCount); + + QEventLoop reconnectLoop; + QTimer::singleShot(2000, &reconnectLoop, SLOT(quit())); + connect(connection, SIGNAL(statusChanged(IrcConnection::Status)), &reconnectLoop, SLOT(quit())); + reconnectLoop.exec(); + + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + QCOMPARE(statusSpy.count(), ++statusCount); + QCOMPARE(statusSpy.last().at(0).value(), IrcConnection::Connecting); + + QVERIFY(waitForOpened()); + QCOMPARE(connectingSpy.count(), ++connectingCount); + + // trigger an error _after_ quit -> no automatic reconnect + connection->quit(); + serverSocket->close(); + QVERIFY(clientSocket->waitForDisconnected(100)); + QVERIFY(!connection->isConnected()); + QVERIFY(!connection->isActive()); + QCOMPARE(statusSpy.at(statusCount++).at(0).value(), IrcConnection::Closing); + QCOMPARE(statusSpy.at(statusCount++).at(0).value(), IrcConnection::Closed); + QCOMPARE(statusSpy.count(), statusCount); +} + +void tst_IrcConnection::testConnection() +{ + Irc::registerMetaTypes(); + + TestProtocol* protocol = new TestProtocol(connection); + FriendlyConnection* friendly = static_cast(connection.data()); + friendly->setProtocol(protocol); + QCOMPARE(friendly->protocol(), protocol); + QCOMPARE(protocol->connection(), connection.data()); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + + QVERIFY(waitForWritten(":irc.ser.ver 001 nick :Welcome to the Internet Relay Chat Network nick")); + QVERIFY(connection->isActive()); + QVERIFY(connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connected); + + connection->close(); + QVERIFY(!connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closed); + + // don't open when disabled + connection->setEnabled(false); + connection->open(); + QVERIFY(!connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closed); + + // re-enable + connection->setEnabled(true); + connection->open(); + QVERIFY(connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connecting); + + QVERIFY(waitForOpened()); + + protocol->written.clear(); + connection->network()->requestCapability("identify-msg"); + QVERIFY(protocol->written.contains("CAP REQ")); + QVERIFY(protocol->written.contains("identify-msg")); + + protocol->written.clear(); + connection->network()->requestCapabilities(QStringList() << "sasl" << "communi"); + QVERIFY(protocol->written.contains("CAP REQ")); + QVERIFY(protocol->written.contains("sasl")); + QVERIFY(protocol->written.contains("communi")); + + QVERIFY(waitForWritten(":irc.ser.ver 001 nick :Welcome to the Internet Relay Chat Network nick")); + QVERIFY(connection->isActive()); + QVERIFY(connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Connected); + + protocol->written.clear(); + connection->setNickName("communi"); + QVERIFY(protocol->written.contains("NICK")); + QVERIFY(protocol->written.contains("communi")); + + protocol->written.clear(); + connection->quit(); + QVERIFY(protocol->written.contains("QUIT")); + + connection->close(); + QVERIFY(!connection->isActive()); + QVERIFY(!connection->isConnected()); + QCOMPARE(connection->status(), IrcConnection::Closed); +} + +class NickChanger : public QObject +{ + Q_OBJECT + +public: + NickChanger(IrcConnection* connection) : QObject(connection) + { + connect(connection, SIGNAL(nickNameReserved(QString*)), SLOT(onNickNameReserved(QString*))); + } + + QString setAlternate; + QString passedAlternate; + +public slots: + void onNickNameReserved(QString* alternate) + { + Q_ASSERT(alternate); + passedAlternate = *alternate; + *alternate = setAlternate; + } +}; + +Q_DECLARE_METATYPE(QString*) +void tst_IrcConnection::testMessages() +{ + Irc::registerMetaTypes(); + qRegisterMetaType(); + + QSignalSpy messageSpy(connection, SIGNAL(messageReceived(IrcMessage*))); + QSignalSpy capabilityMessageSpy(connection, SIGNAL(capabilityMessageReceived(IrcCapabilityMessage*))); + QSignalSpy errorMessageSpy(connection, SIGNAL(errorMessageReceived(IrcErrorMessage*))); + QSignalSpy inviteMessageSpy(connection, SIGNAL(inviteMessageReceived(IrcInviteMessage*))); + QSignalSpy joinMessageSpy(connection, SIGNAL(joinMessageReceived(IrcJoinMessage*))); + QSignalSpy kickMessageSpy(connection, SIGNAL(kickMessageReceived(IrcKickMessage*))); + QSignalSpy modeMessageSpy(connection, SIGNAL(modeMessageReceived(IrcModeMessage*))); + QSignalSpy namesMessageSpy(connection, SIGNAL(namesMessageReceived(IrcNamesMessage*))); + QSignalSpy nickMessageSpy(connection, SIGNAL(nickMessageReceived(IrcNickMessage*))); + QSignalSpy noticeMessageSpy(connection, SIGNAL(noticeMessageReceived(IrcNoticeMessage*))); + QSignalSpy numericMessageSpy(connection, SIGNAL(numericMessageReceived(IrcNumericMessage*))); + QSignalSpy motdMessageSpy(connection, SIGNAL(motdMessageReceived(IrcMotdMessage*))); + QSignalSpy partMessageSpy(connection, SIGNAL(partMessageReceived(IrcPartMessage*))); + QSignalSpy pingMessageSpy(connection, SIGNAL(pingMessageReceived(IrcPingMessage*))); + QSignalSpy pongMessageSpy(connection, SIGNAL(pongMessageReceived(IrcPongMessage*))); + QSignalSpy privateMessageSpy(connection, SIGNAL(privateMessageReceived(IrcPrivateMessage*))); + QSignalSpy quitMessageSpy(connection, SIGNAL(quitMessageReceived(IrcQuitMessage*))); + QSignalSpy topicMessageSpy(connection, SIGNAL(topicMessageReceived(IrcTopicMessage*))); + QSignalSpy whoReplyMessageSpy(connection, SIGNAL(whoReplyMessageReceived(IrcWhoReplyMessage*))); + + QVERIFY(messageSpy.isValid()); + QVERIFY(capabilityMessageSpy.isValid()); + QVERIFY(errorMessageSpy.isValid()); + QVERIFY(inviteMessageSpy.isValid()); + QVERIFY(joinMessageSpy.isValid()); + QVERIFY(kickMessageSpy.isValid()); + QVERIFY(modeMessageSpy.isValid()); + QVERIFY(namesMessageSpy.isValid()); + QVERIFY(nickMessageSpy.isValid()); + QVERIFY(noticeMessageSpy.isValid()); + QVERIFY(numericMessageSpy.isValid()); + QVERIFY(motdMessageSpy.isValid()); + QVERIFY(partMessageSpy.isValid()); + QVERIFY(pingMessageSpy.isValid()); + QVERIFY(pongMessageSpy.isValid()); + QVERIFY(privateMessageSpy.isValid()); + QVERIFY(quitMessageSpy.isValid()); + QVERIFY(topicMessageSpy.isValid()); + QVERIFY(whoReplyMessageSpy.isValid()); + + int messageCount = 0; + int numericMessageCount = 0; + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(":moorcock.freenode.net CAP * LS :account-notify extended-join identify-msg multi-prefix sasl")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(capabilityMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":moorcock.freenode.net 001 communi :Welcome to the freenode Internet Relay Chat Network communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi EXTBAN=$,arxz WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 375 communi :- moorcock.freenode.net Message of the Day -")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 372 communi :- Welcome to moorcock.freenode.net in ...")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 376 communi :End of /MOTD command.")); + messageCount += 2; // RPL_ENDOFMOTD + IrcMotdMessage + QCOMPARE(messageSpy.count(), messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(motdMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN #freenode")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(joinMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":moorcock.freenode.net 332 communi #freenode :Welcome to #freenode | Staff are voiced; some may also be on /stats p -- feel free to /msg us at any time | FAQ: http://freenode.net/faq.shtml | Unwelcome queries? Use /mode your_nick +R to block them. | Channel guidelines: http://freenode.net/poundfreenode.shtml | Blog: http://blog.freenode.net | Please don't comment on spam/trolls.")); + messageCount += 2; // RPL_TOPIC & IrcTopicMessage + QCOMPARE(messageSpy.count(), messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(topicMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":moorcock.freenode.net 333 communi #freenode erry 1379357591")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 353 communi = #freenode :communi straterra absk007 pefn xlys Gromit TooCool Sambler gat0rs KarneAsada danis_963 Kiryx chrismeller deefloo black_male sxlnxdx bjork Kinny phobos_anomaly T13|sleeps JuxTApose Kolega2357 rorx techhelper1 hermatize Azimi iqualfragile fwilson skasturi mwallacesd mayday Guest76549 mcjohansen MangaKaDenza ARISTIDES ketas `- claptor ylluminate Cooky Brand3n cheater_1 Kirito digitaloktay Will| Iarfen abrotman smurfy Inaunt +mist Karol RougeR_")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 353 communi = #freenode :publickeating An_Ony_Moose michagogo Guest915` davidfg4 Ragnor s1lent_1 keee GingerGeek[Away] hibari derp S_T_A_N anonymuse asantoni road|runner LLckfan neoian2 aviancarrier nipples danieldaniel Pyrus Bry8Star shadowm_desktop furtardo rdymac TTSDA seaworthy Chiyo yscc Zombiebaron redpill f4cl3y Boohbah applebloom zorael kameloso^ Zetetic XAMPP wheels_up Cuppy-Cake mindlessjohnny Kymru mquin_ Rodja babilen kirin` David Affix jshyeung_ DarkAceZ karakedi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 366 communi #freenode :End of /NAMES list.")); + messageCount += 2; // RPL_ENDOFNAMES & IrcNamesMessage + QCOMPARE(messageSpy.count(), messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(namesMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. NOTICE communi :[#freenode] Welcome to #freenode. All network staff are voiced in here, but may not always be around - type /stats p to get a list of on call staff. Others may be hiding so do feel free to ping and /msg us at will! Also please read the channel guidelines at http://freenode.net/poundfreenode.shtml - thanks.")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(noticeMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":services. 328 communi #freenode :http://freenode.net/")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + + QVERIFY(waitForWritten("PING :moorcock.freenode.net")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(pingMessageSpy.count(), 1); + + QVERIFY(waitForWritten("PONG :moorcock.freenode.net")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(pongMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi INVITE Communi84194 :#communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(inviteMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":Communi84194!ident@host NICK :communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(nickMessageSpy.count(), 1); + + // own nick name changes + QSignalSpy nickNameChangedSpy(connection, SIGNAL(nickNameChanged(QString))); + QVERIFY(nickNameChangedSpy.isValid()); + QVERIFY(waitForWritten(":communi!user@host NICK :own")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(nickMessageSpy.count(), 2); + QCOMPARE(connection->nickName(), QString("own")); + QCOMPARE(nickNameChangedSpy.count(), 1); + QCOMPARE(nickNameChangedSpy.last().at(0).toString(), QString("own")); + + // nick in use + QString prevNick = connection->nickName(); + NickChanger changer(connection); + changer.setAlternate = "communi_"; + QSignalSpy nickNameReservedSpy(connection, SIGNAL(nickNameReserved(QString*))); + QVERIFY(nickNameReservedSpy.isValid()); + QVERIFY(waitForWritten(":moorcock.freenode.net 433 * communi :Nickname is already in use.")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(nickNameReservedSpy.count(), 1); + QCOMPARE(changer.passedAlternate, prevNick); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi MODE #communi +v communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(modeMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":moorcock.freenode.net 324 communi #communi +ms")); + messageCount += 2; // RPL_CHANNELMODEIS + IrcModeMessage + QCOMPARE(messageSpy.count(), messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(modeMessageSpy.count(), 2); + + QVERIFY(waitForWritten(":qtassistant!jpnurmi@qt/jpnurmi/bot/qtassistant PART #communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(partMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi PRIVMSG #communi :hello")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(privateMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi QUIT :Client Quit")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(quitMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":jpnurmi!jpnurmi@qt/jpnurmi KICK #communi communi")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(kickMessageSpy.count(), 1); + + QVERIFY(waitForWritten("ERROR :just testing...")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(errorMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":hobana.freenode.net 352 communi #communi ChanServ services. services. ChanServ H@ :0 Channel Services" )); + messageCount += 2; // RPL_WHOREPLY + IrcWhoReplyMessage + QCOMPARE(messageSpy.count(), messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(whoReplyMessageSpy.count(), 1); + + QVERIFY(waitForWritten(":hobana.freenode.net 315 communi #communi :End of /WHO list.")); + QCOMPARE(messageSpy.count(), ++messageCount); + QCOMPARE(numericMessageSpy.count(), ++numericMessageCount); + QCOMPARE(whoReplyMessageSpy.count(), 1); +} + +class MsgFilter : public QObject, public IrcMessageFilter +{ + Q_OBJECT + Q_INTERFACES(IrcMessageFilter) + +public: + MsgFilter() : count(0), type(IrcMessage::Unknown), flags(IrcMessage::None) + { + } + + bool messageFilter(IrcMessage* message) + { + ++count; + type = message->type(); + flags = message->flags(); + value = message->property(property); + return false; + } + +public: + int count; + QVariant value; + QByteArray property; + IrcMessage::Type type; + IrcMessage::Flags flags; +}; + +void tst_IrcConnection::testMessageFlags() +{ + connection->open(); + QVERIFY(waitForOpened()); + + int count = 0; + MsgFilter filter; + connection->installMessageFilter(&filter); + + QVERIFY(waitForWritten(":server CAP * LS :identify-msg")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Capability); + QCOMPARE(filter.flags, IrcMessage::None); + + QVERIFY(waitForWritten(":server CAP communi ACK :identify-msg")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Capability); + QCOMPARE(filter.flags, IrcMessage::None); + + QVERIFY(waitForWritten(":server 001 communi :Welcome...")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Numeric); + QCOMPARE(filter.flags, IrcMessage::None); + + QVERIFY(waitForWritten(":server 005 communi CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=fake KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Numeric); + QCOMPARE(filter.flags, IrcMessage::None); + + QVERIFY(waitForWritten(":server 005 communi CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Numeric); + QCOMPARE(filter.flags, IrcMessage::None); + + QVERIFY(waitForWritten(":server 005 communi EXTBAN=$,arxz WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Numeric); + QCOMPARE(filter.flags, IrcMessage::None); + + filter.property = "content"; + QVERIFY(waitForWritten(":communi!ident@host PRIVMSG #communi :hi all")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Private); + QCOMPARE(filter.flags, IrcMessage::Own); + QCOMPARE(filter.value.toString(), QString("hi all")); + + filter.property = "content"; + QVERIFY(waitForWritten(":jpnurmi!ident@host PRIVMSG #communi :+hello there, communi")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Private); + QCOMPARE(filter.flags, IrcMessage::Identified); + QCOMPARE(filter.value.toString(), QString("hello there, communi")); + + filter.property = "content"; + QVERIFY(waitForWritten(":Guest1234!ident@host PRIVMSG #communi :-hi communi")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Private); + QCOMPARE(filter.flags, IrcMessage::Unidentified); + QCOMPARE(filter.value.toString(), QString("hi communi")); + + filter.property = "content"; + QVERIFY(waitForWritten(":communi!ident@host NOTICE #communi :hi all")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Notice); + QCOMPARE(filter.flags, IrcMessage::Own); + QCOMPARE(filter.value.toString(), QString("hi all")); + + filter.property = "content"; + QVERIFY(waitForWritten(":jpnurmi!ident@host NOTICE #communi :+hello there, communi")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Notice); + QCOMPARE(filter.flags, IrcMessage::Identified); + QCOMPARE(filter.value.toString(), QString("hello there, communi")); + + filter.property = "content"; + QVERIFY(waitForWritten(":Guest1234!ident@host NOTICE #communi :-hi communi")); + QCOMPARE(filter.count, ++count); + QCOMPARE(filter.type, IrcMessage::Notice); + QCOMPARE(filter.flags, IrcMessage::Unidentified); + QCOMPARE(filter.value.toString(), QString("hi communi")); +} + +void tst_IrcConnection::testMessageBuilder() +{ + connection->open(); + QVERIFY(waitForOpened()); + + MsgFilter filter; + connection->installMessageFilter(&filter); + + QVERIFY(waitForWritten(":my.irc.ser.ver 001 communi :Welcome...")); + QVERIFY(waitForWritten(":my.irc.ser.ver 005 communi CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=fake KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server")); + QVERIFY(waitForWritten(":my.irc.ser.ver 005 communi CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server")); + QVERIFY(waitForWritten(":my.irc.ser.ver 005 communi EXTBAN=$,arxz WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server")); + + filter.property = "mask"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("#communi")); + + filter.property = "ident"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("~jpnurmi")); + + filter.property = "host"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("qt/jpnurmi")); + + filter.property = "server"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("his.irc.ser.ver")); + + filter.property = "nick"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("jpnurmi")); + + filter.property = "away"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toBool(), true); + + filter.property = "servOp"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toBool(), true); + + filter.property = "realName"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0 J-P Nurmi")); + QCOMPARE(filter.value.toString(), QString("J-P Nurmi")); + + filter.property = "realName"; + QVERIFY(waitForWritten(":my.irc.ser.ver 352 communi #communi ~jpnurmi qt/jpnurmi his.irc.ser.ver jpnurmi G*@ :0")); + QCOMPARE(filter.value.toString(), QString()); +} + +void tst_IrcConnection::testSendCommand() +{ + IrcConnection conn; + QVERIFY(!conn.sendCommand(0)); + QVERIFY(!conn.sendCommand(IrcCommand::createQuit())); + + TestProtocol* protocol = new TestProtocol(connection); + FriendlyConnection* friendly = static_cast(connection.data()); + friendly->setProtocol(protocol); + QCOMPARE(friendly->protocol(), protocol); + QCOMPARE(protocol->connection(), connection.data()); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(connection->sendCommand(IrcCommand::createQuit())); + QVERIFY(!connection->sendCommand(0)); + QVERIFY(protocol->written.contains("QUIT")); +} + +void tst_IrcConnection::testSendData() +{ + IrcConnection conn; + QVERIFY(!conn.sendData("QUIT")); + + TestProtocol* protocol = new TestProtocol(connection); + FriendlyConnection* friendly = static_cast(connection.data()); + friendly->setProtocol(protocol); + QCOMPARE(friendly->protocol(), protocol); + QCOMPARE(protocol->connection(), connection.data()); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(connection->sendData("QUIT")); + QVERIFY(protocol->written.contains("QUIT")); +} + +class TestFilter : public QObject, public IrcMessageFilter, public IrcCommandFilter +{ + Q_OBJECT + Q_INTERFACES(IrcMessageFilter IrcCommandFilter) + +public: + void clear() + { + commitSuicide = false; + messageFiltered = 0; + commandFiltered = 0; + messageFilterEnabled = false; + commandFilterEnabled = false; + } + + bool messageFilter(IrcMessage*) + { + ++messageFiltered; + if (commitSuicide) + delete this; + return messageFilterEnabled; + } + + bool commandFilter(IrcCommand*) + { + ++commandFiltered; + if (commitSuicide) + delete this; + return commandFilterEnabled; + } + + bool commitSuicide; + int messageFiltered; + int commandFiltered; + bool messageFilterEnabled; + bool commandFilterEnabled; +}; + +void tst_IrcConnection::testMessageFilter() +{ + Irc::registerMetaTypes(); + + QSignalSpy messageSpy(connection, SIGNAL(messageReceived(IrcMessage*))); + QVERIFY(messageSpy.isValid()); + int messageCount = 0; + + TestFilter filter1; + QScopedPointer filter2(new TestFilter); + QScopedPointer filter3(new TestFilter); + + filter1.clear(); filter2->clear(); filter3->clear(); + + connection->installMessageFilter(&filter1); + connection->installMessageFilter(filter2.data()); + connection->installMessageFilter(filter3.data()); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(":moorcock.freenode.net 001 communi :Welcome to the freenode Internet Relay Chat Network communi")); + QCOMPARE(filter1.messageFiltered, 1); + QCOMPARE(filter2->messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), ++messageCount); + + filter1.clear(); filter2->clear(); filter3->clear(); + filter3->messageFilterEnabled = true; + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server")); + QCOMPARE(filter1.messageFiltered, 0); + QCOMPARE(filter2->messageFiltered, 0); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), messageCount); + + filter1.clear(); filter2->clear(); filter3->clear(); + filter2->messageFilterEnabled = true; + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server")); + QCOMPARE(filter1.messageFiltered, 0); + QCOMPARE(filter2->messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), messageCount); + + filter1.clear(); filter2->clear(); filter3->clear(); + filter1.messageFilterEnabled = true; + + QVERIFY(waitForWritten(":moorcock.freenode.net 005 communi EXTBAN=$,arxz WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server")); + QCOMPARE(filter1.messageFiltered, 1); + QCOMPARE(filter2->messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), messageCount); + + filter1.clear(); filter2->clear(); filter3->clear(); + + QVERIFY(waitForWritten(":moorcock.freenode.net 375 communi :- moorcock.freenode.net Message of the Day -")); + QCOMPARE(filter1.messageFiltered, 1); + QCOMPARE(filter2->messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), ++messageCount); + + // a deleted filter gets removed + filter2.reset(); + filter1.clear(); filter3->clear(); + + QVERIFY(waitForWritten(":moorcock.freenode.net 372 communi :- Welcome to moorcock.freenode.net in ...")); + QCOMPARE(filter1.messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 1); + QCOMPARE(messageSpy.count(), ++messageCount); + + QVERIFY(waitForWritten(":moorcock.freenode.net 376 communi :End of /MOTD command.")); + messageCount += 2; // RPL_ENDOFMOTD + IrcMotdMessage + QCOMPARE(messageSpy.count(), messageCount); + + // double filters + connection->installMessageFilter(&filter1); + connection->installMessageFilter(filter3.data()); + filter1.clear(); filter3->clear(); + + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN #freenode")); + QCOMPARE(filter1.messageFiltered, 2); + QCOMPARE(filter3->messageFiltered, 2); + QCOMPARE(messageSpy.count(), ++messageCount); + + // remove & enable double filter + filter1.clear(); filter3->clear(); + filter1.messageFilterEnabled = true; + connection->removeMessageFilter(filter3.data()); + + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN #communi")); + QCOMPARE(filter1.messageFiltered, 1); + QCOMPARE(filter3->messageFiltered, 0); + QCOMPARE(messageSpy.count(), messageCount); + + // remove & delete + filter3.reset(); + filter1.clear(); + connection->removeMessageFilter(&filter1); + + QVERIFY(waitForWritten(":communi!~communi@hidd.en PART #communi")); + QCOMPARE(filter1.messageFiltered, 0); + QCOMPARE(messageSpy.count(), ++messageCount); + + // commit a suicide & filter + QPointer suicidal1 = new TestFilter; + connection->installMessageFilter(suicidal1); + suicidal1->clear(); + suicidal1->messageFilterEnabled = true; + suicidal1->commitSuicide = true; + + QVERIFY(waitForWritten(":communi!~communi@hidd.en PART #freenode")); + QCOMPARE(messageSpy.count(), messageCount); + QVERIFY(!suicidal1); + + // commit a suicide & don't filter + QPointer suicidal2 = new TestFilter; + connection->installMessageFilter(suicidal2); + suicidal2->clear(); + suicidal2->commitSuicide = true; + + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN #qt")); + QVERIFY(!suicidal2); +} + +void tst_IrcConnection::testCommandFilter() +{ + TestProtocol* protocol = new TestProtocol(connection); + FriendlyConnection* friendly = static_cast(connection.data()); + friendly->setProtocol(protocol); + QCOMPARE(friendly->protocol(), protocol); + QCOMPARE(protocol->connection(), connection.data()); + + TestFilter filter1; + QScopedPointer filter2(new TestFilter); + QScopedPointer filter3(new TestFilter); + + filter1.clear(); filter2->clear(); filter3->clear(); + + connection->installCommandFilter(&filter1); + connection->installCommandFilter(filter2.data()); + connection->installCommandFilter(filter3.data()); + + connection->open(); + QVERIFY(waitForOpened()); + + connection->sendCommand(IrcCommand::createJoin("#freenode")); + QCOMPARE(filter1.commandFiltered, 1); + QCOMPARE(filter2->commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(!protocol->written.isEmpty()); + + protocol->written.clear(); + filter1.clear(); filter2->clear(); filter3->clear(); + filter3->commandFilterEnabled = true; + + connection->sendCommand(IrcCommand::createJoin("#communi")); + QCOMPARE(filter1.commandFiltered, 0); + QCOMPARE(filter2->commandFiltered, 0); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(protocol->written.isEmpty()); + + protocol->written.clear(); + filter1.clear(); filter2->clear(); filter3->clear(); + filter2->commandFilterEnabled = true; + + connection->sendCommand(IrcCommand::createJoin("#qt")); + QCOMPARE(filter1.commandFiltered, 0); + QCOMPARE(filter2->commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(protocol->written.isEmpty()); + + protocol->written.clear(); + filter1.clear(); filter2->clear(); filter3->clear(); + filter1.commandFilterEnabled = true; + + connection->sendCommand(IrcCommand::createPart("#freenode")); + QCOMPARE(filter1.commandFiltered, 1); + QCOMPARE(filter2->commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(protocol->written.isEmpty()); + + protocol->written.clear(); + filter1.clear(); filter2->clear(); filter3->clear(); + + connection->sendCommand(IrcCommand::createPart("#communi")); + QCOMPARE(filter1.commandFiltered, 1); + QCOMPARE(filter2->commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(!protocol->written.isEmpty()); + + // a deleted filter gets removed + filter2.reset(); + filter1.clear(); filter3->clear(); + protocol->written.clear(); + + connection->sendCommand(IrcCommand::createPart("#qt")); + QCOMPARE(filter1.commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 1); + QVERIFY(!protocol->written.isEmpty()); + + // double filters + connection->installCommandFilter(&filter1); + connection->installCommandFilter(filter3.data()); + filter1.clear(); filter3->clear(); + protocol->written.clear(); + + connection->sendCommand(IrcCommand::createJoin("#freenode")); + QCOMPARE(filter1.commandFiltered, 2); + QCOMPARE(filter3->commandFiltered, 2); + QVERIFY(!protocol->written.isEmpty()); + + // remove & enable double filter + filter1.clear(); filter3->clear(); + filter1.commandFilterEnabled = true; + connection->removeCommandFilter(filter3.data()); + protocol->written.clear(); + + connection->sendCommand(IrcCommand::createJoin("#communi")); + QCOMPARE(filter1.commandFiltered, 1); + QCOMPARE(filter3->commandFiltered, 0); + QVERIFY(protocol->written.isEmpty()); + + // remove & delete + filter3.reset(); + filter1.clear(); + connection->removeCommandFilter(&filter1); + protocol->written.clear(); + + connection->sendCommand(IrcCommand::createJoin("#qt")); + QCOMPARE(filter1.commandFiltered, 0); + QVERIFY(!protocol->written.isEmpty()); + + // commit a suicide + QPointer suicidal = new TestFilter; + connection->installCommandFilter(suicidal); + suicidal->commitSuicide = true; + + connection->sendCommand(IrcCommand::createPart("#qt")); + QVERIFY(!suicidal); +} + +void tst_IrcConnection::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcConnection(0x0)")); + str.clear(); + + IrcConnection connection; + dbg << &connection; + QVERIFY(QRegExp("IrcConnection\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str)); + str.clear(); + + connection.setHost("irc.freenode.net"); + dbg << &connection; + QVERIFY(QRegExp("IrcConnection\\(0x[0-9A-Fa-f]+, irc.freenode.net\\) ").exactMatch(str)); + str.clear(); + + connection.setDisplayName("Freenode"); + dbg << &connection; + QVERIFY(QRegExp("IrcConnection\\(0x[0-9A-Fa-f]+, Freenode\\) ").exactMatch(str)); + str.clear(); + + dbg << IrcConnection::Connected; + QCOMPARE(str.trimmed(), QString::fromLatin1("Connected")); + str.clear(); +} + +void tst_IrcConnection::testWarnings() +{ + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(connection->isActive()); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setHost() has no effect until re-connect"); + connection->setHost("foo"); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setPort() has no effect until re-connect"); + connection->setPort(1234); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setUserName() has no effect until re-connect"); + connection->setUserName("foo"); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setRealName() has no effect until re-connect"); + connection->setRealName("foo"); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setPassword() has no effect until re-connect"); + connection->setPassword("foo"); + + QTest::ignoreMessage(QtWarningMsg, "IrcConnection::setSaslMechanism() has no effect until re-connect"); + connection->setSaslMechanism("PLAIN"); +} + +class FakeQmlConnection : public IrcConnection +{ + Q_OBJECT + friend class tst_IrcConnection; + +public slots: + // -Wno-overloaded-virtual + QVariant createCtcpReply(const QVariant& request) + { + return QVariant::fromValue(IrcConnection::createCtcpReply(request.value())); + } +}; + +void tst_IrcConnection::testCtcp() +{ + FriendlyConnection* friendly = static_cast(connection.data()); + + // PING + IrcMessage* msg = IrcMessage::fromData(":nick!user@host PRIVMSG communi :\1PING timestamp\1", connection); + QScopedPointer pingRequest(qobject_cast(msg)); + QVERIFY(pingRequest.data()); + + QScopedPointer pingReply(friendly->createCtcpReply(pingRequest.data())); + QVERIFY(pingReply.data()); + QCOMPARE(pingReply->type(), IrcCommand::CtcpReply); + QCOMPARE(pingReply->toString(), QString("NOTICE nick :\1PING timestamp\1")); + + // TIME + msg = IrcMessage::fromData(":nick!user@host PRIVMSG communi :\1TIME\1", connection); + QScopedPointer timeRequest(qobject_cast(msg)); + QVERIFY(timeRequest); + + QScopedPointer timeReply(friendly->createCtcpReply(timeRequest.data())); + QVERIFY(timeReply.data()); + QCOMPARE(timeReply->type(), IrcCommand::CtcpReply); + QCOMPARE(timeReply->toString(), QString("NOTICE nick :\1TIME %1\1").arg(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat))); + + // VERSION + msg = IrcMessage::fromData(":nick!user@host PRIVMSG communi :\1VERSION\1", connection); + QScopedPointer versionRequest(qobject_cast(msg)); + QVERIFY(versionRequest.data()); + + QScopedPointer versionReply(friendly->createCtcpReply(versionRequest.data())); + QVERIFY(versionReply.data()); + QCOMPARE(versionReply->type(), IrcCommand::CtcpReply); + QVERIFY(versionReply->toString().startsWith("NOTICE nick :\1VERSION ")); + QVERIFY(versionReply->toString().contains(Irc::version())); + QVERIFY(versionReply->toString().endsWith("\1")); + + // SOURCE + msg = IrcMessage::fromData(":nick!user@host PRIVMSG communi :\1SOURCE\1", connection); + QScopedPointer sourceRequest(qobject_cast(msg)); + QVERIFY(sourceRequest.data()); + + QScopedPointer sourceReply(friendly->createCtcpReply(sourceRequest.data())); + QVERIFY(sourceReply.data()); + QCOMPARE(sourceReply->type(), IrcCommand::CtcpReply); + QVERIFY(sourceReply->toString().startsWith("NOTICE nick :\1SOURCE ")); + QVERIFY(sourceReply->toString().contains("http://")); + QVERIFY(sourceReply->toString().endsWith("\1")); + + // CLIENTINFO + msg = IrcMessage::fromData(":nick!user@host PRIVMSG communi :\1CLIENTINFO\1", connection); + QScopedPointer infoRequest(qobject_cast(msg)); + QVERIFY(infoRequest.data()); + + QScopedPointer infoReply(friendly->createCtcpReply(infoRequest.data())); + QVERIFY(infoReply.data()); + QCOMPARE(infoReply->type(), IrcCommand::CtcpReply); + QVERIFY(infoReply->toString().startsWith("NOTICE nick :\1CLIENTINFO ")); + QVERIFY(infoReply->toString().contains("PING")); + QVERIFY(infoReply->toString().contains("TIME")); + QVERIFY(infoReply->toString().contains("VERSION")); + QVERIFY(infoReply->toString().contains("SOURCE")); + QVERIFY(infoReply->toString().endsWith("\1")); + + // QML compatibility + FakeQmlConnection qmlConnection; + qmlConnection.setUserName("user"); + qmlConnection.setNickName("nick"); + qmlConnection.setRealName("real"); + qmlConnection.setPassword("secret"); + qmlConnection.setHost("127.0.0.1"); + qmlConnection.setPort(server->serverPort()); + + TestProtocol* qmlProtocol = new TestProtocol(&qmlConnection); + qmlConnection.setProtocol(qmlProtocol); + qmlConnection.open(); + + QVERIFY(server->waitForNewConnection(200)); + QAbstractSocket* qmlServerSocket = server->nextPendingConnection(); + QVERIFY(qmlServerSocket); + QAbstractSocket* qmlClientSocket = qmlConnection.socket(); + QVERIFY(qmlClientSocket); + QVERIFY(qmlClientSocket->waitForConnected(200)); + + qmlProtocol->written.clear(); + qmlServerSocket->write(":nick!user@host PRIVMSG communi :\1PING qml\1\r\n"); + QVERIFY(qmlServerSocket->waitForBytesWritten(1000)); + QVERIFY(qmlClientSocket->waitForReadyRead(1000)); + QCOMPARE(qmlProtocol->written, QByteArray("NOTICE nick :\1PING qml\1")); + + connection->open(); + QVERIFY(waitForOpened()); + + TestProtocol* protocol = new TestProtocol(friendly); + friendly->setProtocol(protocol); + QCOMPARE(friendly->protocol(), protocol); + QCOMPARE(protocol->connection(), friendly); + + // PING + protocol->written.clear(); + QVERIFY(waitForWritten(":nick!user@host PRIVMSG communi :\1PING timestamp\1\r\n")); + QCOMPARE(protocol->written, QByteArray("NOTICE nick :\1PING timestamp\1")); + + // TIME + protocol->written.clear(); + QVERIFY(waitForWritten(":nick!user@host PRIVMSG communi :\1TIME\1\r\n")); + QVERIFY(protocol->written.startsWith("NOTICE nick :\1TIME ")); + QVERIFY(protocol->written.endsWith("\1")); + + // VERSION + protocol->written.clear(); + QVERIFY(waitForWritten(":nick!user@host PRIVMSG communi :\1VERSION\1\r\n")); + QVERIFY(protocol->written.startsWith("NOTICE nick :\1VERSION ")); + QVERIFY(protocol->written.contains(Irc::version().toUtf8())); + QVERIFY(protocol->written.endsWith("\1")); + + // SOURCE + protocol->written.clear(); + QVERIFY(waitForWritten(":nick!user@host PRIVMSG communi :\1SOURCE\1\r\n")); + QVERIFY(protocol->written.startsWith("NOTICE nick :\1SOURCE ")); + QVERIFY(protocol->written.contains("http://")); + QVERIFY(protocol->written.endsWith("\1")); + + // CLIENTINFO + protocol->written.clear(); + QVERIFY(waitForWritten(":nick!user@host PRIVMSG communi :\1CLIENTINFO\1\r\n")); + QVERIFY(protocol->written.startsWith("NOTICE nick :\1CLIENTINFO ")); + QVERIFY(protocol->written.contains("PING")); + QVERIFY(protocol->written.contains("TIME")); + QVERIFY(protocol->written.contains("VERSION")); + QVERIFY(protocol->written.contains("SOURCE")); + QVERIFY(protocol->written.endsWith("\1")); +} + +QTEST_MAIN(tst_IrcConnection) + +#include "tst_ircconnection.moc" diff --git a/src/libcommuni/tests/auto/irclagtimer/irclagtimer.pro b/src/libcommuni/tests/auto/irclagtimer/irclagtimer.pro new file mode 100644 index 0000000..bcaac4c --- /dev/null +++ b/src/libcommuni/tests/auto/irclagtimer/irclagtimer.pro @@ -0,0 +1,8 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irclagtimer.cpp + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irclagtimer/tst_irclagtimer.cpp b/src/libcommuni/tests/auto/irclagtimer/tst_irclagtimer.cpp new file mode 100644 index 0000000..3a69042 --- /dev/null +++ b/src/libcommuni/tests/auto/irclagtimer/tst_irclagtimer.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irclagtimer.h" +#include "ircconnection.h" +#include "tst_ircclientserver.h" +#include "tst_ircdata.h" +#include + +class tst_IrcLagTimer : public tst_IrcClientServer +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testInterval(); + void testConnection(); + void testLag(); +}; + +void tst_IrcLagTimer::testDefaults() +{ + IrcLagTimer timer; + QCOMPARE(timer.lag(), qint64(-1)); + QVERIFY(!timer.connection()); + QCOMPARE(timer.interval(), 60); +} + +void tst_IrcLagTimer::testInterval() +{ + IrcLagTimer timer; + timer.setInterval(INT_MIN); + QCOMPARE(timer.interval(), INT_MIN); + timer.setInterval(0); + QCOMPARE(timer.interval(), 0); + timer.setInterval(INT_MAX); + QCOMPARE(timer.interval(), INT_MAX); +} + +void tst_IrcLagTimer::testConnection() +{ + IrcLagTimer timer(connection); + QCOMPARE(timer.connection(), connection.data()); + timer.setConnection(0); + QVERIFY(!timer.connection()); + timer.setConnection(connection); + QCOMPARE(timer.connection(), connection.data()); +} + +void tst_IrcLagTimer::testLag() +{ +#if QT_VERSION >= 0x040700 + IrcLagTimer timer(connection); + + QSignalSpy lagSpy(&timer, SIGNAL(lagChanged(qint64))); + QVERIFY(lagSpy.isValid()); + int lagCount = 0; + + connection->open(); + QVERIFY(waitForOpened()); + + QCOMPARE(timer.lag(), -1ll); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + // cheat a bit to avoid waiting a 1s interval at minimum... + QMetaObject::invokeMethod(&timer, "_irc_pingServer"); + QVERIFY(clientSocket->waitForBytesWritten(1000)); + QVERIFY(serverSocket->waitForReadyRead(1000)); + + QRegExp rx("PING communi/(\\d+)"); + QString written = QString::fromUtf8(serverSocket->readAll()); + QVERIFY(rx.indexIn(written) != -1); + + waitForWritten(QString(":irc.ser.ver PONG communi communi/%1").arg(QDateTime::currentMSecsSinceEpoch() - 1234ll).toUtf8()); + QVERIFY(timer.lag() >= 1234ll); + QCOMPARE(lagSpy.count(), ++lagCount); + QVERIFY(lagSpy.last().at(0).toLongLong() >= 1234ll); + + timer.setConnection(0); + QCOMPARE(timer.lag(), -1ll); + QCOMPARE(lagSpy.count(), ++lagCount); + QCOMPARE(lagSpy.last().at(0).toLongLong(), -1ll); + + timer.setConnection(connection); + QCOMPARE(timer.lag(), -1ll); + QCOMPARE(lagSpy.count(), lagCount); + + waitForWritten(QString(":irc.ser.ver PONG communi communi/%1").arg(QDateTime::currentMSecsSinceEpoch() - 4321ll).toUtf8()); + QVERIFY(timer.lag() >= 4321ll); + QCOMPARE(lagSpy.count(), ++lagCount); + QVERIFY(lagSpy.last().at(0).toLongLong() >= 4321ll); + + connection->close(); + QCOMPARE(timer.lag(), -1ll); + QCOMPARE(lagSpy.count(), ++lagCount); + QCOMPARE(lagSpy.last().at(0).toLongLong(), -1ll); +#endif // QT_VERSION >= 0x040700 +} + +QTEST_MAIN(tst_IrcLagTimer) + +#include "tst_irclagtimer.moc" diff --git a/src/libcommuni/tests/auto/ircmessage/ircmessage.pro b/src/libcommuni/tests/auto/ircmessage/ircmessage.pro new file mode 100644 index 0000000..c13ba14 --- /dev/null +++ b/src/libcommuni/tests/auto/ircmessage/ircmessage.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircmessage.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircmessage/tst_ircmessage.cpp b/src/libcommuni/tests/auto/ircmessage/tst_ircmessage.cpp new file mode 100644 index 0000000..f96c50a --- /dev/null +++ b/src/libcommuni/tests/auto/ircmessage/tst_ircmessage.cpp @@ -0,0 +1,973 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircmessage.h" +#include "ircconnection.h" +#include "ircprotocol.h" +#include +#include +#include +#include + +#ifdef Q_OS_LINUX +#include "ircmessagedecoder_p.h" +#endif // Q_OS_LINUX + +class tst_IrcMessage : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + + void testPrefix_data(); + void testPrefix(); + + void testParameters_data(); + void testParameters(); + + void testFlags(); + + void testEncoding_data(); + void testEncoding(); + + void testDecoder_data(); + void testDecoder(); + + void testTags_data(); + void testTags(); + + void testCapabilityMessage_data(); + void testCapabilityMessage(); + void testErrorMessage_data(); + void testErrorMessage(); + void testInviteMessage_data(); + void testInviteMessage(); + void testJoinMessage_data(); + void testJoinMessage(); + void testKickMessage_data(); + void testKickMessage(); + void testNamesMessage(); + void testNickMessage_data(); + void testNickMessage(); + void testNoticeMessage_data(); + void testNoticeMessage(); + void testNumericMessage_data(); + void testNumericMessage(); + void testModeMessage_data(); + void testModeMessage(); + void testMotdMessage(); + void testPartMessage_data(); + void testPartMessage(); + void testPingMessage(); + void testPongMessage(); + void testPrivateMessage_data(); + void testPrivateMessage(); + void testQuitMessage_data(); + void testQuitMessage(); + void testTopicMessage_data(); + void testTopicMessage(); + void testWhoReplyMessage_data(); + void testWhoReplyMessage(); + + void testDebug(); +}; + +void tst_IrcMessage::testDefaults() +{ + IrcMessage msg(0); + QVERIFY(!msg.isValid()); + QVERIFY(!msg.connection()); + QCOMPARE(msg.type(), IrcMessage::Unknown); + QCOMPARE(msg.flags(), IrcMessage::None); + QCOMPARE(msg.encoding(), QByteArray("ISO-8859-15")); + QVERIFY(msg.prefix().isNull()); + QVERIFY(msg.nick().isNull()); + QVERIFY(msg.ident().isNull()); + QVERIFY(msg.host().isNull()); + QVERIFY(msg.command().isNull()); + QVERIFY(msg.parameters().isEmpty()); + QVERIFY(msg.toData().isEmpty()); +} + +void tst_IrcMessage::testPrefix_data() +{ + QTest::addColumn("prefix"); + QTest::addColumn("expected"); + QTest::addColumn("nick"); + QTest::addColumn("ident"); + QTest::addColumn("host"); + + QTest::newRow("null") << QString() << QString() << QString() << QString() << QString(); + QTest::newRow("empty") << QString("") << QString("") << QString() << QString() << QString(); + QTest::newRow("space") << QString(" ") << QString(" ") << QString() << QString() << QString(); + QTest::newRow("nick!ident@host") << QString("nick!ident@host") << QString("nick!ident@host") << QString("nick") << QString("ident") << QString("host"); +} + +void tst_IrcMessage::testPrefix() +{ + QFETCH(QString, prefix); + QFETCH(QString, expected); + QFETCH(QString, nick); + QFETCH(QString, ident); + QFETCH(QString, host); + + IrcMessage msg(0); + msg.setPrefix(prefix); + QCOMPARE(msg.prefix(), expected); + QCOMPARE(msg.nick(), nick); + QCOMPARE(msg.ident(), ident); + QCOMPARE(msg.host(), host); +} + +void tst_IrcMessage::testParameters_data() +{ + Irc::registerMetaTypes(); + + QTest::addColumn("prefix"); + QTest::addColumn("command"); + QTest::addColumn("params"); + QTest::addColumn("type"); + + QTest::newRow("null") << QString() << QString() << QStringList() << IrcMessage::Unknown; + QTest::newRow("message") << QString("nick!ident@host") << QString("PRIVMSG") << QStringList("p") << IrcMessage::Private; + QTest::newRow("notice") << QString("nick!ident@host") << QString("NOTICE") << QStringList("p") << IrcMessage::Notice; +} + +void tst_IrcMessage::testParameters() +{ + QFETCH(QString, prefix); + QFETCH(QString, command); + QFETCH(QStringList, params); + QFETCH(IrcMessage::Type, type); + + IrcConnection connection; + QScopedPointer message(IrcMessage::fromParameters(prefix, command, params, &connection)); + QCOMPARE(message->type(), type); + QCOMPARE(message->prefix(), prefix); + QCOMPARE(message->command(), command); + QCOMPARE(message->parameters(), params); +} + +void tst_IrcMessage::testFlags() +{ + IrcMessage msg(0); + msg.setPrefix("a!b@c"); + QCOMPARE(msg.flags(), IrcMessage::None); +} + +void tst_IrcMessage::testEncoding_data() +{ + QTest::addColumn("encoding"); + QTest::addColumn("actual"); + QTest::addColumn("supported"); + + QTest::newRow("null") << QByteArray() << QByteArray("ISO-8859-15") << false; + QTest::newRow("empty") << QByteArray("") << QByteArray("ISO-8859-15") << false; + QTest::newRow("space") << QByteArray(" ") << QByteArray("ISO-8859-15") << false; + QTest::newRow("invalid") << QByteArray("invalid") << QByteArray("ISO-8859-15") << false; + foreach (const QByteArray& codec, QTextCodec::availableCodecs()) + QTest::newRow(codec) << codec << codec << true; +} + +void tst_IrcMessage::testEncoding() +{ + QFETCH(QByteArray, encoding); + QFETCH(QByteArray, actual); + QFETCH(bool, supported); + + if (!supported) + QTest::ignoreMessage(QtWarningMsg, "IrcMessage::setEncoding(): unsupported encoding \"" + encoding + "\" "); + + IrcMessage msg(0); + msg.setEncoding(encoding); + QCOMPARE(msg.encoding(), actual); +} + +void tst_IrcMessage::testDecoder_data() +{ + QTest::addColumn("encoding"); + QTest::addColumn("base64"); + + QTest::newRow("windows-1251") << QByteArray("windows-1251") << QByteArray("7+Xt8eju7eXw4Owg7+7k5OXr/O375Q=="); + QTest::newRow("EUC-JP") << QByteArray("EUC-JP") << QByteArray("pKSkxKTHpOKkyaSzpMek4qGhpbml3qXbyMc="); + QTest::newRow("Shift-JIS") << QByteArray("Shift-JIS") << QByteArray("lbaOmoNSgVuDaJVcg1aDdINn"); + QTest::newRow("ISO-8859-15") << QByteArray("ISO-8859-15") << QByteArray("5Gl0aWVucORpduQ="); // TODO: QByteArray("5OQ="); +} + +void tst_IrcMessage::testDecoder() +{ + QFETCH(QByteArray, encoding); + QFETCH(QByteArray, base64); + +#ifdef Q_OS_LINUX + // others have problems with symbols (win) or private headers (osx frameworks) + IrcMessageDecoder decoder; + QString actual = decoder.decode(QByteArray::fromBase64(base64), encoding); + QString expected = QTextCodec::codecForName(encoding)->toUnicode(QByteArray::fromBase64(base64)); + QCOMPARE(actual, expected); +#endif // Q_OS_LINUX +} + +void tst_IrcMessage::testTags_data() +{ + QTest::addColumn("data"); + QTest::addColumn("tags"); + QTest::addColumn("prefix"); + QTest::addColumn("command"); + QTest::addColumn("target"); + QTest::addColumn("content"); + + QVariantMap tags; + tags.insert("aaa", "bbb"); + tags.insert("ccc", ""); + tags.insert("example.com/ddd", "eee"); + + QTest::newRow("example") << QByteArray("@aaa=bbb;ccc;example.com/ddd=eee :nick!ident@host.com PRIVMSG me :Hello") + << tags << "nick!ident@host.com" << "PRIVMSG" << "me" << "Hello"; +} + +void tst_IrcMessage::testTags() +{ + QFETCH(QByteArray, data); + QFETCH(QVariantMap, tags); + QFETCH(QString, prefix); + QFETCH(QString, command); + QFETCH(QString, target); + QFETCH(QString, content); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->tags(), tags); + QCOMPARE(message->prefix(), prefix); + QCOMPARE(message->command(), command); + QCOMPARE(message->property("target").toString(), target); + QCOMPARE(message->property("content").toString(), content); +} + +void tst_IrcMessage::testCapabilityMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("subCommand"); + QTest::addColumn("capabilities"); + + QTest::newRow("no prefix") << true << QByteArray("CAP") << QString() << QStringList(); + QTest::newRow("empty prefix") << false << QByteArray(": CAP") << QString() << QStringList(); + QTest::newRow("no params") << true << QByteArray(":server CAP") << QString() << QStringList(); + + QTest::newRow("ls") << true << QByteArray(":server CAP * LS :identify-msg sasl") << QString("LS") << (QStringList() << "identify-msg" << "sasl"); + QTest::newRow("ack") << true << QByteArray(":server CAP communi ACK :identify-msg") << QString("ACK") << (QStringList() << "identify-msg"); + QTest::newRow("nak") << true << QByteArray(":server CAP communi NAK :sasl") << QString("NAK") << (QStringList() << "sasl"); +} + +void tst_IrcMessage::testCapabilityMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, subCommand); + QFETCH(QStringList, capabilities); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Capability); + QCOMPARE(message->command(), QString("CAP")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("subCommand").toString(), subCommand); + QCOMPARE(message->property("capabilities").toStringList(), capabilities); + + IrcCapabilityMessage* capabilityMessage = qobject_cast(message); + QVERIFY(capabilityMessage); + QCOMPARE(capabilityMessage->isValid(), valid); + QCOMPARE(capabilityMessage->subCommand(), subCommand); + QCOMPARE(capabilityMessage->capabilities(), capabilities); +} + +void tst_IrcMessage::testErrorMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("error"); + + QTest::newRow("no prefix") << true << QByteArray("ERROR error1") << QString("error1"); + QTest::newRow("empty prefix") << false << QByteArray(": ERROR error1") << QString("error1"); + QTest::newRow("no params") << false << QByteArray(":server ERROR") << QString(); + QTest::newRow("all ok") << true << QByteArray(":server ERROR error1") << QString("error1"); +} + +void tst_IrcMessage::testErrorMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, error); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Error); + QCOMPARE(message->command(), QString("ERROR")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("error").toString(), error); + + IrcErrorMessage* errorMessage = qobject_cast(message); + QVERIFY(errorMessage); + QCOMPARE(errorMessage->isValid(), valid); + QCOMPARE(errorMessage->error(), error); +} + +void tst_IrcMessage::testInviteMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("user"); + QTest::addColumn("channel"); + + QTest::newRow("no prefix") << true << QByteArray("INVITE Wiz #Dust") << QString("Wiz") << QString("#Dust"); + QTest::newRow("empty prefix") << false << QByteArray(": INVITE Wiz #Dust") << QString("Wiz") << QString("#Dust"); + QTest::newRow("no params") << false << QByteArray(":Angel INVITE") << QString() << QString(); + QTest::newRow("no channel") << false << QByteArray(":Angel INVITE Wiz") << QString("Wiz") << QString(); + QTest::newRow("all ok") << true << QByteArray(":Angel INVITE Wiz #Dust") << QString("Wiz") << QString("#Dust"); +} + +void tst_IrcMessage::testInviteMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, channel); + QFETCH(QString, user); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Invite); + QCOMPARE(message->command(), QString("INVITE")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("channel").toString(), channel); + QCOMPARE(message->property("user").toString(), user); + + IrcInviteMessage* inviteMessage = qobject_cast(message); + QVERIFY(inviteMessage); + QCOMPARE(inviteMessage->isValid(), valid); + QCOMPARE(inviteMessage->channel(), channel); + QCOMPARE(inviteMessage->user(), user); +} + +void tst_IrcMessage::testJoinMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("channel"); + + QTest::newRow("no prefix") << true << QByteArray("JOIN #Twilight_zone") << QString("#Twilight_zone"); + QTest::newRow("empty prefix") << false << QByteArray(": JOIN #Twilight_zone") << QString("#Twilight_zone"); + QTest::newRow("no params") << false << QByteArray(":WiZ JOIN") << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ JOIN #Twilight_zone") << QString("#Twilight_zone"); +} + +void tst_IrcMessage::testJoinMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, channel); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Join); + QCOMPARE(message->command(), QString("JOIN")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("channel").toString(), channel); + + IrcJoinMessage* joinMessage = qobject_cast(message); + QVERIFY(joinMessage); + QCOMPARE(joinMessage->isValid(), valid); + QCOMPARE(joinMessage->channel(), channel); +} + +void tst_IrcMessage::testKickMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("channel"); + QTest::addColumn("user"); + QTest::addColumn("reason"); + + QTest::newRow("no prefix") << true << QByteArray("KICK #Finnish John") << QString("#Finnish") << QString("John") << QString(); + QTest::newRow("empty prefix") << false << QByteArray(": KICK #Finnish John") << QString("#Finnish") << QString("John") << QString(); + QTest::newRow("no params") << false << QByteArray(":WiZ KICK") << QString() << QString() << QString(); + QTest::newRow("no user") << false << QByteArray(":WiZ KICK #Finnish") << QString("#Finnish") << QString() << QString(); + QTest::newRow("no reason") << true << QByteArray(":WiZ KICK #Finnish John") << QString("#Finnish") << QString("John") << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ KICK #Finnish John :Another reason") << QString("#Finnish") << QString("John") << QString("Another reason"); +} + +void tst_IrcMessage::testKickMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, channel); + QFETCH(QString, user); + QFETCH(QString, reason); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Kick); + QCOMPARE(message->command(), QString("KICK")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("channel").toString(), channel); + QCOMPARE(message->property("user").toString(), user); + QCOMPARE(message->property("reason").toString(), reason); + + IrcKickMessage* kickMessage = qobject_cast(message); + QVERIFY(kickMessage); + QCOMPARE(kickMessage->isValid(), valid); + QCOMPARE(kickMessage->channel(), channel); + QCOMPARE(kickMessage->user(), user); + QCOMPARE(kickMessage->reason(), reason); +} + +void tst_IrcMessage::testNamesMessage() +{ + IrcConnection connection; + IrcNamesMessage message(&connection); + message.setPrefix("nick!ident@host"); + message.setParameters(QStringList() << "chan" << "usr1" << "usr2" << "usr3"); + QVERIFY(message.isValid()); + QCOMPARE(message.type(), IrcMessage::Names); + QCOMPARE(message.command(), QString("NAMES")); + QCOMPARE(message.channel(), QString("chan")); + QCOMPARE(message.names(), QStringList() << "usr1" << "usr2" << "usr3"); +} + +void tst_IrcMessage::testNickMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("oldNick"); + QTest::addColumn("newNick"); + + QTest::newRow("no prefix") << true << QByteArray("NICK Kilroy") << QString() << QString("Kilroy"); + QTest::newRow("empty prefix") << false << QByteArray(": NICK Kilroy") << QString() << QString("Kilroy"); + QTest::newRow("no params") << false << QByteArray(":WiZ NICK") << QString("WiZ") << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ NICK Kilroy") << QString("WiZ") << QString("Kilroy"); +} + +void tst_IrcMessage::testNickMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, oldNick); + QFETCH(QString, newNick); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Nick); + QCOMPARE(message->command(), QString("NICK")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("oldNick").toString(), oldNick); + QCOMPARE(message->property("newNick").toString(), newNick); + + IrcNickMessage* nickMessage = qobject_cast(message); + QVERIFY(nickMessage); + QCOMPARE(nickMessage->isValid(), valid); + QCOMPARE(nickMessage->oldNick(), oldNick); + QCOMPARE(nickMessage->newNick(), newNick); +} + +void tst_IrcMessage::testNoticeMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("target"); + QTest::addColumn("content"); + QTest::addColumn("priv"); + QTest::addColumn("reply"); + + QTest::newRow("no prefix") << true << QByteArray("NOTICE Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false; + QTest::newRow("empty prefix") << false << QByteArray(": NOTICE Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false; + QTest::newRow("no params") << false << QByteArray(":Angel NOTICE Wiz") << QString("Wiz") << QString() << false << false; + QTest::newRow("all ok") << true << QByteArray(":Angel NOTICE Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false; + QTest::newRow("private") << true << QByteArray(":Angel NOTICE communi :Hello are you receiving this message ?") << QString("communi") << QString("Hello are you receiving this message ?") << true << false; + QTest::newRow("reply") << true << QByteArray(":Angel NOTICE Wiz :\1Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << true; +} + +void tst_IrcMessage::testNoticeMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, target); + QFETCH(QString, content); + QFETCH(bool, priv); + QFETCH(bool, reply); + + IrcConnection connection; + connection.setNickName("communi"); + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Notice); + QCOMPARE(message->command(), QString("NOTICE")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("target").toString(), target); + QCOMPARE(message->property("content").toString(), content); + QCOMPARE(message->property("private").toBool(), priv); + QCOMPARE(message->property("reply").toBool(), reply); + + IrcNoticeMessage* noticeMessage = qobject_cast(message); + QVERIFY(noticeMessage); + QCOMPARE(noticeMessage->isValid(), valid); + QCOMPARE(noticeMessage->target(), target); + QCOMPARE(noticeMessage->content(), content); + QCOMPARE(noticeMessage->isPrivate(), priv); + QCOMPARE(noticeMessage->isReply(), reply); +} + +void tst_IrcMessage::testNumericMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("code"); + + QTest::newRow("no prefix") << true << QByteArray("123 Kilroy") << 123; + QTest::newRow("empty prefix") << false << QByteArray(": 123 Kilroy") << 123; + QTest::newRow("no params") << true << QByteArray(":WiZ 456") << 456; + QTest::newRow("all ok") << true << QByteArray(":WiZ 789 Kilroy") << 789; +} + +void tst_IrcMessage::testNumericMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(int, code); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Numeric); + QVERIFY(message->command().toInt() > 0); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("code").toInt(), code); + + IrcNumericMessage* numericMessage = qobject_cast(message); + QVERIFY(numericMessage); + QCOMPARE(numericMessage->isValid(), valid); + QCOMPARE(numericMessage->code(), code); +} + +void tst_IrcMessage::testModeMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("target"); + QTest::addColumn("mode"); + QTest::addColumn("argument"); + + QTest::newRow("no prefix") << true << QByteArray("MODE Kilroy -w") << QString("Kilroy") << QString("-w") << QString(); + QTest::newRow("empty prefix") << false << QByteArray(": MODE Kilroy -w") << QString("Kilroy") << QString("-w") << QString(); + QTest::newRow("no params") << false << QByteArray(":WiZ MODE Kilroy") << QString("Kilroy") << QString() << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ MODE Kilroy -w") << QString("Kilroy") << QString("-w") << QString(); + + QTest::newRow("1") << true << QByteArray(":WiZ MODE #Finnish +im") << QString("#Finnish") << QString("+im") << QString(); + QTest::newRow("2") << true << QByteArray(":Angel MODE #Finnish +o Kilroy") << QString("#Finnish") << QString("+o") << QString("Kilroy"); + QTest::newRow("3") << true << QByteArray(":Kilroy MODE #Finnish +v Wiz") << QString("#Finnish") << QString("+v") << QString("Wiz"); + QTest::newRow("4a") << true << QByteArray("MODE #Fins -s") << QString("#Fins") << QString("-s") << QString(); + QTest::newRow("4b") << false << QByteArray(": MODE #Fins -s") << QString("#Fins") << QString("-s") << QString(); + QTest::newRow("5") << true << QByteArray(":WiZ MODE #42 +k oulu") << QString("#42") << QString("+k") << QString("oulu"); + QTest::newRow("6a") << true << QByteArray("MODE #eu-opers +l 10") << QString("#eu-opers") << QString("+l") << QString("10"); + QTest::newRow("6b") << false << QByteArray(": MODE #eu-opers +l 10") << QString("#eu-opers") << QString("+l") << QString("10"); + QTest::newRow("7") << true << QByteArray(":nobody MODE &oulu +b") << QString("&oulu") << QString("+b") << QString(); + QTest::newRow("8") << true << QByteArray(":someone MODE &oulu +b *!*@*") << QString("&oulu") << QString("+b") << QString("*!*@*"); + QTest::newRow("9") << true << QByteArray(":anyone MODE &oulu +b *!*@*.edu") << QString("&oulu") << QString("+b") << QString("*!*@*.edu"); + QTest::newRow("10a") << true << QByteArray("MODE WiZ -w") << QString("WiZ") << QString("-w") << QString(); + QTest::newRow("10b") << false << QByteArray(": MODE WiZ -w") << QString("WiZ") << QString("-w") << QString(); + QTest::newRow("11") << true << QByteArray(":Angel MODE Angel +i") << QString("Angel") << QString("+i") << QString(); + QTest::newRow("12") << true << QByteArray(":WiZ MODE WiZ -o") << QString("WiZ") << QString("-o") << QString(); + + QTest::newRow("args") << true << QByteArray(":someone MODE #chan +lk 10 secret") << QString("#chan") << QString("+lk") << QString("10 secret"); +} + +void tst_IrcMessage::testModeMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, target); + QFETCH(QString, mode); + QFETCH(QString, argument); + + const QString arg = argument.split(" ", QString::SkipEmptyParts).value(0); + const QStringList args = argument.split(" ", QString::SkipEmptyParts); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Mode); + QCOMPARE(message->command(), QString("MODE")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("target").toString(), target); + QCOMPARE(message->property("mode").toString(), mode); + QCOMPARE(message->property("argument").toString(), arg); + QCOMPARE(message->property("arguments").toStringList(), args); + + IrcModeMessage* modeMessage = qobject_cast(message); + QVERIFY(modeMessage); + QCOMPARE(modeMessage->isValid(), valid); + QCOMPARE(modeMessage->target(), target); + QCOMPARE(modeMessage->mode(), mode); + QCOMPARE(modeMessage->argument(), arg); + QCOMPARE(modeMessage->arguments(), args); +} + +void tst_IrcMessage::testMotdMessage() +{ + IrcConnection connection; + IrcMotdMessage message(&connection); + message.setPrefix("nick!ident@host"); + QStringList params; + params += "user"; + params += ":server 375 user :- server Message of the Day"; + params += ":server 372 user :- Welcome..."; + params += ":server 376 user :End of /MOTD command"; + message.setParameters(params); + QVERIFY(message.isValid()); + QCOMPARE(message.type(), IrcMessage::Motd); + QCOMPARE(message.command(), QString("MOTD")); + QCOMPARE(message.lines(), QStringList(params.mid(1))); +} + +void tst_IrcMessage::testPartMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("channel"); + QTest::addColumn("reason"); + + QTest::newRow("no prefix") << true << QByteArray("PART #Twilight_zone") << QString("#Twilight_zone") << QString(); + QTest::newRow("empty prefix") << false << QByteArray(": PART #Twilight_zone") << QString("#Twilight_zone") << QString(); + QTest::newRow("no params") << false << QByteArray(":WiZ PART") << QString() << QString(); + QTest::newRow("no reason") << true << QByteArray(":WiZ PART #Twilight_zone") << QString("#Twilight_zone") << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ PART #Twilight_zone :Gone to have lunch") << QString("#Twilight_zone") << QString("Gone to have lunch"); +} + +void tst_IrcMessage::testPartMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, channel); + QFETCH(QString, reason); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Part); + QCOMPARE(message->command(), QString("PART")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("channel").toString(), channel); + QCOMPARE(message->property("reason").toString(), reason); + + IrcPartMessage* partMessage = qobject_cast(message); + QVERIFY(partMessage); + QCOMPARE(partMessage->isValid(), valid); + QCOMPARE(partMessage->channel(), channel); + QCOMPARE(partMessage->reason(), reason); +} + +void tst_IrcMessage::testPingMessage() +{ + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData("PING :arg", &connection); + QCOMPARE(message->type(), IrcMessage::Ping); + QCOMPARE(message->command(), QString("PING")); + QCOMPARE(message->property("command").toString(), QString("PING")); + QVERIFY(message->property("valid").toBool()); + QCOMPARE(message->property("argument").toString(), QString("arg")); + + IrcPingMessage* pingMessage = qobject_cast(message); + QVERIFY(pingMessage); + QVERIFY(pingMessage->isValid()); + QCOMPARE(pingMessage->argument(), QString("arg")); +} + +void tst_IrcMessage::testPongMessage() +{ + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData("PONG tgt :arg", &connection); + QCOMPARE(message->type(), IrcMessage::Pong); + QCOMPARE(message->command(), QString("PONG")); + QCOMPARE(message->property("command").toString(), QString("PONG")); + QVERIFY(message->property("valid").toBool()); + QCOMPARE(message->property("argument").toString(), QString("arg")); + + IrcPongMessage* pongMessage = qobject_cast(message); + QVERIFY(pongMessage); + QVERIFY(pongMessage->isValid()); + QCOMPARE(pongMessage->argument(), QString("arg")); +} + +void tst_IrcMessage::testPrivateMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("cap"); + QTest::addColumn("data"); + QTest::addColumn("target"); + QTest::addColumn("content"); + QTest::addColumn("priv"); + QTest::addColumn("action"); + QTest::addColumn("request"); + QTest::addColumn("flags"); + + QTest::newRow("no prefix") << true << QString() << QByteArray("PRIVMSG Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::None); + QTest::newRow("empty prefix") << false << QString() << QByteArray(": PRIVMSG Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::None); + QTest::newRow("no params") << false << QString() << QByteArray(":Angel PRIVMSG Wiz") << QString("Wiz") << QString() << false << false << false << static_cast(IrcMessage::None); + QTest::newRow("all ok") << true << QString() << QByteArray(":Angel PRIVMSG Wiz :Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::None); + QTest::newRow("private") << true << QString() << QByteArray(":Angel PRIVMSG communi :Hello are you receiving this message ?") << QString("communi") << QString("Hello are you receiving this message ?") << true << false << false << static_cast(IrcMessage::None); + QTest::newRow("action") << true << QString() << QByteArray(":Angel PRIVMSG Wiz :\1ACTION Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << true << false << static_cast(IrcMessage::None); + QTest::newRow("request") << true << QString() << QByteArray(":Angel PRIVMSG Wiz :\1Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << true << static_cast(IrcMessage::None); + + QTest::newRow("identified") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :+Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::Identified); + QTest::newRow("identified private") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG communi :+Hello are you receiving this message ?") << QString("communi") << QString("Hello are you receiving this message ?") << true << false << false << static_cast(IrcMessage::Identified); + QTest::newRow("identified action") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :+\1ACTION Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << true << false << static_cast(IrcMessage::Identified); + QTest::newRow("identified request") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :+\1Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << true << static_cast(IrcMessage::Identified); + + QTest::newRow("unidentified") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :-Hello are you receiving this message ?") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::Unidentified); + QTest::newRow("unidentified private") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG communi :-Hello are you receiving this message ?") << QString("communi") << QString("Hello are you receiving this message ?") << true << false << false << static_cast(IrcMessage::Unidentified); + QTest::newRow("unidentified action") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :-\1ACTION Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << true << false << static_cast(IrcMessage::Unidentified); + QTest::newRow("unidentified request") << true << QString("identify-msg") << QByteArray(":Angel PRIVMSG Wiz :-\1Hello are you receiving this message ?\1") << QString("Wiz") << QString("Hello are you receiving this message ?") << false << false << true << static_cast(IrcMessage::Unidentified); + + QTest::newRow("no-caps identified") << true << QString() << QByteArray(":Angel PRIVMSG Wiz :+Hello are you receiving this message ?") << QString("Wiz") << QString("+Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::None); + QTest::newRow("no-caps unidentified") << true << QString() << QByteArray(":Angel PRIVMSG Wiz :-Hello are you receiving this message ?") << QString("Wiz") << QString("-Hello are you receiving this message ?") << false << false << false << static_cast(IrcMessage::None); +} + +class TestProtocol : public IrcProtocol +{ +public: + TestProtocol(const QString& cap, IrcConnection* connection) : IrcProtocol(connection) + { + QSet caps; + caps.insert(cap); + setAvailableCapabilities(caps); + setActiveCapabilities(caps); + } +}; + +class FriendConnection : public IrcConnection +{ + friend class tst_IrcMessage; +}; + +void tst_IrcMessage::testPrivateMessage() +{ + QFETCH(bool, valid); + QFETCH(QString, cap); + QFETCH(QByteArray, data); + QFETCH(QString, target); + QFETCH(QString, content); + QFETCH(bool, priv); + QFETCH(bool, action); + QFETCH(bool, request); + QFETCH(uint, flags); + + IrcConnection connection; + connection.setNickName("communi"); + TestProtocol protocol(cap, &connection); + static_cast(&connection)->setProtocol(&protocol); + + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Private); + QCOMPARE(message->command(), QString("PRIVMSG")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("target").toString(), target); + QCOMPARE(message->property("content").toString(), content); + QCOMPARE(message->property("private").toBool(), priv); + QCOMPARE(message->property("action").toBool(), action); + QCOMPARE(message->property("request").toBool(), request); + QCOMPARE(message->property("flags").toUInt(), flags); + + IrcPrivateMessage* privateMessage = qobject_cast(message); + QVERIFY(privateMessage); + QCOMPARE(privateMessage->isValid(), valid); + QCOMPARE(privateMessage->target(), target); + QCOMPARE(privateMessage->content(), content); + QCOMPARE(privateMessage->isPrivate(), priv); + QCOMPARE(privateMessage->isAction(), action); + QCOMPARE(privateMessage->isRequest(), request); + QCOMPARE(static_cast(privateMessage->flags()), flags); +} + +void tst_IrcMessage::testQuitMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("reason"); + + QTest::newRow("no prefix") << true << QByteArray("QUIT :Gone to have lunch") << QString("Gone to have lunch"); + QTest::newRow("empty prefix") << false << QByteArray(": QUIT :Gone to have lunch") << QString("Gone to have lunch"); + QTest::newRow("no params") << true << QByteArray(":WiZ QUIT") << QString(); + QTest::newRow("all ok") << true << QByteArray(":WiZ QUIT :Gone to have lunch") << QString("Gone to have lunch"); +} + +void tst_IrcMessage::testQuitMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, reason); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Quit); + QCOMPARE(message->command(), QString("QUIT")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("reason").toString(), reason); + + IrcQuitMessage* quitMessage = qobject_cast(message); + QVERIFY(quitMessage); + QCOMPARE(quitMessage->isValid(), valid); + QCOMPARE(quitMessage->reason(), reason); +} + +void tst_IrcMessage::testTopicMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("data"); + QTest::addColumn("channel"); + QTest::addColumn("topic"); + QTest::addColumn("reply"); + + QTest::newRow("no prefix") << true << QByteArray("TOPIC #test") << QString("#test") << QString() << false; + QTest::newRow("empty prefix") << false << QByteArray(": TOPIC #test") << QString("#test") << QString() << false; + QTest::newRow("no params") << false << QByteArray(":WiZ TOPIC") << QString() << QString() << false; + QTest::newRow("no topic") << true << QByteArray(":WiZ TOPIC #test") << QString("#test") << QString() << false; + QTest::newRow("all ok") << true << QByteArray(":WiZ TOPIC #test :another topic") << QString("#test") << QString("another topic") << false; + // TODO: QTest::newRow("numeric") << true << QByteArray(":server 332 user #test :foo bar") << QString("#test") << QString("foo bar") << true; +} + +void tst_IrcMessage::testTopicMessage() +{ + QFETCH(bool, valid); + QFETCH(QByteArray, data); + QFETCH(QString, channel); + QFETCH(QString, topic); + QFETCH(bool, reply); + + IrcConnection connection; + IrcMessage* message = IrcMessage::fromData(data, &connection); + QCOMPARE(message->type(), IrcMessage::Topic); + QCOMPARE(message->command(), QString("TOPIC")); + QCOMPARE(message->property("valid").toBool(), valid); + QCOMPARE(message->property("channel").toString(), channel); + QCOMPARE(message->property("topic").toString(), topic); + QCOMPARE(message->property("reply").toBool(), reply); + + IrcTopicMessage* topicMessage = qobject_cast(message); + QVERIFY(topicMessage); + QCOMPARE(topicMessage->isValid(), valid); + QCOMPARE(topicMessage->channel(), channel); + QCOMPARE(topicMessage->topic(), topic); + QCOMPARE(topicMessage->isReply(), reply); +} + +void tst_IrcMessage::testWhoReplyMessage_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("prefix"); + QTest::addColumn("params"); + QTest::addColumn("mask"); + QTest::addColumn("server"); + QTest::addColumn("away"); + QTest::addColumn("servOp"); + QTest::addColumn("realName"); + + QTest::newRow("normal") << true << "nick!ident@host" + << (QStringList() << "#mask" << "irc.ser.ver" << "H@" << "real name") + << "#mask" << "irc.ser.ver" << false << false << "real name"; + + QTest::newRow("away") << true << "nick!ident@host" + << (QStringList() << "*" << "127.0.0.1" << "G@" << "real name") + << "*" << "127.0.0.1" << true << false << "real name"; + + QTest::newRow("serv op") << true << "nick!ident@host" + << (QStringList() << "*" << "127.0.0.1" << "H*@" << "real name") + << "*" << "127.0.0.1" << false << true << "real name"; + + QTest::newRow("no name") << true << "nick!ident@host" + << (QStringList() << "#mask" << "irc.ser.ver" << "H@" << "") + << "#mask" << "irc.ser.ver" << false << false << ""; +} + +void tst_IrcMessage::testWhoReplyMessage() +{ + QFETCH(bool, valid); + QFETCH(QString, prefix); + QFETCH(QStringList, params); + QFETCH(QString, mask); + QFETCH(QString, server); + QFETCH(bool, away); + QFETCH(bool, servOp); + QFETCH(QString, realName); + + IrcConnection connection; + IrcWhoReplyMessage message(&connection); + message.setPrefix(prefix); + message.setParameters(params); + QCOMPARE(message.isValid(), valid); + QCOMPARE(message.type(), IrcMessage::WhoReply); + // TODO: QCOMPARE(message.command(), QString::number(Irc::RPL_WHOREPLY)); + QCOMPARE(message.mask(), mask); + QCOMPARE(message.server(), server); + QCOMPARE(message.isAway(), away); + QCOMPARE(message.isServOp(), servOp); + QCOMPARE(message.realName(), realName); + + QCOMPARE(message.property("valid").toBool(), valid); + QCOMPARE(message.property("mask").toString(), mask); + QCOMPARE(message.property("server").toString(), server); + QCOMPARE(message.property("away").toBool(), away); + QCOMPARE(message.property("servOp").toBool(), servOp); + QCOMPARE(message.property("realName").toString(), realName); +} + +void tst_IrcMessage::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcMessage(0x0)")); + str.clear(); + + IrcMessage message(0); + dbg << &message; + QVERIFY(QRegExp("IrcMessage\\(0x[0-9A-Fa-f]+, flags=\\(None\\)\\) ").exactMatch(str)); + str.clear(); + + message.setObjectName("foo"); + dbg << &message; + QVERIFY(QRegExp("IrcMessage\\(0x[0-9A-Fa-f]+, name=foo, flags=\\(None\\)\\) ").exactMatch(str)); + str.clear(); + + message.setPrefix("nick!ident@host"); + dbg << &message; + QVERIFY(QRegExp("IrcMessage\\(0x[0-9A-Fa-f]+, name=foo, flags=\\(None\\), prefix=nick!ident@host\\) ").exactMatch(str)); + str.clear(); + + message.setCommand("COMMAND"); + dbg << &message; + QVERIFY(QRegExp("IrcMessage\\(0x[0-9A-Fa-f]+, name=foo, flags=\\(None\\), prefix=nick!ident@host, command=COMMAND\\) ").exactMatch(str)); + str.clear(); + + dbg << IrcMessage::Join; + QCOMPARE(str.trimmed(), QString::fromLatin1("Join")); + str.clear(); + + dbg << IrcMessage::Unidentified; + QCOMPARE(str.trimmed(), QString::fromLatin1("Unidentified")); + str.clear(); + + dbg << (IrcMessage::Own | IrcMessage::Identified | IrcMessage::Unidentified); + QCOMPARE(str.trimmed(), QString::fromLatin1("(Own|Identified|Unidentified)")); + str.clear(); + + dbg << IrcModeMessage::Channel; + QCOMPARE(str.trimmed(), QString::fromLatin1("Channel")); + str.clear(); +} + +QTEST_MAIN(tst_IrcMessage) + +#include "tst_ircmessage.moc" diff --git a/src/libcommuni/tests/auto/ircnetwork/ircnetwork.pro b/src/libcommuni/tests/auto/ircnetwork/ircnetwork.pro new file mode 100644 index 0000000..d4bebfb --- /dev/null +++ b/src/libcommuni/tests/auto/ircnetwork/ircnetwork.pro @@ -0,0 +1,8 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircnetwork.cpp + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircnetwork/tst_ircnetwork.cpp b/src/libcommuni/tests/auto/ircnetwork/tst_ircnetwork.cpp new file mode 100644 index 0000000..5237659 --- /dev/null +++ b/src/libcommuni/tests/auto/ircnetwork/tst_ircnetwork.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircnetwork.h" +#include "irccommand.h" +#include "ircconnection.h" +#include +#include +#include "tst_ircclientserver.h" +#include "tst_ircdata.h" +#ifdef Q_OS_LINUX +#include "ircnetwork_p.h" +#endif // Q_OS_LINUX + +class tst_IrcNetwork : public tst_IrcClientServer +{ + Q_OBJECT + +private slots: + void testDefaults(); + + void testInfo_data(); + void testInfo(); + + void testCapabilities_data(); + void testCapabilities(); + + void testDebug(); +}; + +void tst_IrcNetwork::testDefaults() +{ + IrcConnection connection; + IrcNetwork* network = connection.network(); + QVERIFY(!network->isInitialized()); + QVERIFY(network->name().isNull()); + QVERIFY(network->modes().isEmpty()); + QVERIFY(network->prefixes().isEmpty()); + QVERIFY(network->channelTypes().isEmpty()); + QVERIFY(network->availableCapabilities().isEmpty()); + QVERIFY(network->requestedCapabilities().isEmpty()); + QVERIFY(network->activeCapabilities().isEmpty()); +} + +void tst_IrcNetwork::testInfo_data() +{ + QTest::addColumn("welcome"); + QTest::addColumn("name"); + QTest::addColumn("modes"); + QTest::addColumn("prefixes"); + QTest::addColumn("channelTypes"); + + QTest::newRow("freenode") << tst_IrcData::welcome("freenode") << "freenode" << "ov" << "@+" << "#"; + QTest::newRow("ircnet") << tst_IrcData::welcome("ircnet") << "IRCNet" << "ov" << "@+" << "#&!+"; + QTest::newRow("euirc") << tst_IrcData::welcome("euirc") << "euIRCnet" << "qaohv" << "*!@%+" << "#&+"; +} + +void tst_IrcNetwork::testInfo() +{ + QFETCH(QByteArray, welcome); + QFETCH(QString, name); + QFETCH(QString, modes); + QFETCH(QString, prefixes); + QFETCH(QString, channelTypes); + + IrcNetwork* network = connection->network(); + + QSignalSpy initSpy(network, SIGNAL(initialized())); + QSignalSpy nameSpy(network, SIGNAL(nameChanged(QString))); + QSignalSpy modesSpy(network, SIGNAL(modesChanged(QStringList))); + QSignalSpy prefixesSpy(network, SIGNAL(prefixesChanged(QStringList))); + QSignalSpy channelTypesSpy(network, SIGNAL(channelTypesChanged(QStringList))); + + QVERIFY(initSpy.isValid()); + QVERIFY(nameSpy.isValid()); + QVERIFY(modesSpy.isValid()); + QVERIFY(prefixesSpy.isValid()); + QVERIFY(channelTypesSpy.isValid()); + + connection->open(); + QVERIFY(waitForOpened()); + QVERIFY(waitForWritten(welcome)); + + QVERIFY(network->isInitialized()); + + QCOMPARE(network->name(), name); + QCOMPARE(network->modes(), modes.split("", QString::SkipEmptyParts)); + QCOMPARE(network->prefixes(), prefixes.split("", QString::SkipEmptyParts)); + QCOMPARE(network->channelTypes(), channelTypes.split("", QString::SkipEmptyParts)); + + QCOMPARE(network->prefixes().count(), network->modes().count()); + for (int i = 0; i < network->prefixes().count(); ++i) { + QString prefix = network->prefixes().at(i); + QString mode = network->modes().at(i); + QCOMPARE(network->prefixToMode(prefix), mode); + QCOMPARE(network->modeToPrefix(mode), prefix); + } + + QVERIFY(!network->channelTypes().isEmpty()); + QVERIFY(!network->isChannel("foo")); + QVERIFY(network->isChannel(network->channelTypes().at(0) + "foo")); + + QVERIFY(!network->channelModes(IrcNetwork::TypeA).isEmpty()); + QVERIFY(!network->channelModes(IrcNetwork::TypeB).isEmpty()); + QVERIFY(!network->channelModes(IrcNetwork::TypeC).isEmpty()); + QVERIFY(!network->channelModes(IrcNetwork::TypeD).isEmpty()); + + if (welcome.contains("NICKLEN=")) + QVERIFY(network->numericLimit(IrcNetwork::NickLength) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::NickLength), -1); + if (welcome.contains("CHANNELLEN=")) + QVERIFY(network->numericLimit(IrcNetwork::ChannelLength) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::ChannelLength), -1); + if (welcome.contains("TOPICLEN=")) + QVERIFY(network->numericLimit(IrcNetwork::TopicLength) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::TopicLength), -1); + if (welcome.contains("KICKLEN=")) + QVERIFY(network->numericLimit(IrcNetwork::KickReasonLength) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::KickReasonLength), -1); + if (welcome.contains("AWAYLEN=")) + QVERIFY(network->numericLimit(IrcNetwork::AwayReasonLength) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::AwayReasonLength), -1); + if (welcome.contains("MODES=")) + QVERIFY(network->numericLimit(IrcNetwork::ModeCount) != -1); + else + QCOMPARE(network->numericLimit(IrcNetwork::ModeCount), -1); + + QCOMPARE(network->numericLimit(IrcNetwork::MessageLength), 512); // hard-coded :/ + + if (welcome.contains("MAXLIST=")) { + bool limited = false; + foreach (const QString& mode, network->modes()) + if (network->modeLimit(mode) != -1) + limited = true; + QVERIFY(limited); + } + + if (welcome.contains("CHANLIMIT=")) { + bool limited = false; + foreach (const QString& type, network->channelTypes()) + if (network->channelLimit(type) != -1) + limited = true; + QVERIFY(limited); + } + + if (welcome.contains("TARGMAX=")) { + bool limited = false; + IrcCommand command; + for (int i = IrcCommand::Admin; i <= IrcCommand::Whowas; ++i) { + if (i != IrcCommand::Custom) { + command.setType(static_cast(i)); + QString cmd = command.toString().split(" ", QString::SkipEmptyParts).value(0); + if (network->targetLimit(cmd) != -1) + limited = true; + } + } + QVERIFY(limited); + } + + QCOMPARE(initSpy.count(), 1); + QCOMPARE(nameSpy.count(), 1); + QCOMPARE(modesSpy.count(), 1); + QCOMPARE(prefixesSpy.count(), 1); + QCOMPARE(channelTypesSpy.count(), 1); + + QCOMPARE(nameSpy.first().first().toString(), name); + QCOMPARE(modesSpy.first().first().toStringList(), modes.split("", QString::SkipEmptyParts)); + QCOMPARE(prefixesSpy.first().first().toStringList(), prefixes.split("", QString::SkipEmptyParts)); + QCOMPARE(channelTypesSpy.first().first().toStringList(), channelTypes.split("", QString::SkipEmptyParts)); +} + +void tst_IrcNetwork::testCapabilities_data() +{ + QTest::addColumn("initialCaps"); + QTest::addColumn("requestedCaps"); + QTest::addColumn("ackedCaps"); + QTest::addColumn("nakedCaps"); + QTest::addColumn("listedCaps"); + QTest::addColumn("availableCaps"); + QTest::addColumn("activeCaps"); + + QTest::newRow("empty") << QString() + << QString() + << QString() + << QString() + << QString() + << QString() + << QString(); + + QTest::newRow("sasl") << QString("multi-prefix sasl identify-msg") // initial + << QString("sasl") // requested + << QString("sasl") // acked + << QString() // naked + << QString("sasl identify-msg multi-prefix") // listed + << QString("sasl identify-msg multi-prefix") // available + << QString("sasl"); // active + + QTest::newRow("unk") << QString("multi-prefix sasl identify-msg") // initial + << QString("unk") // requested + << QString() // acked + << QString("nak") // naked + << QString("multi-prefix sasl identify-msg") // listed + << QString("multi-prefix sasl identify-msg") // available + << QString(); // active + + QTest::newRow("nak all") << QString("multi-prefix sasl identify-msg") // initial + << QString("sasl identify-msg multi-prefix") // requested + << QString() // acked + << QString("sasl identify-msg multi-prefix") // naked + << QString("sasl identify-msg multi-prefix") // listed + << QString("sasl identify-msg multi-prefix") // available + << QString(); // active + + QTest::newRow("sticky") << QString("=sticky") // initial + << QString("sticky") // requested + << QString("=sticky") // acked + << QString() // naked + << QString() // listed + << QString("sticky") // available + << QString("sticky"); // active + + QTest::newRow("ackmod") << QString("~ackmod") // initial + << QString("ackmod") // requested + << QString("~ackmod") // acked + << QString() // naked + << QString() // listed + << QString("ackmod") // available + << QString("ackmod"); // active + + QTest::newRow("acksticky") << QString("~=acksticky") // initial + << QString("acksticky") // requested + << QString("=~acksticky") // acked + << QString() // naked + << QString() // listed + << QString("acksticky") // available + << QString("acksticky"); // active +} + +static bool equalCaps(const QString& left, const QString& right) +{ + return left.split(" ", QString::SkipEmptyParts).toSet() == right.split(" ", QString::SkipEmptyParts).toSet(); +} + +void tst_IrcNetwork::testCapabilities() +{ + QFETCH(QString, initialCaps); + QFETCH(QString, requestedCaps); + QFETCH(QString, ackedCaps); + QFETCH(QString, nakedCaps); + QFETCH(QString, listedCaps); + QFETCH(QString, availableCaps); + QFETCH(QString, activeCaps); + + IrcNetwork* network = connection->network(); + + QSignalSpy availableSpy(network, SIGNAL(availableCapabilitiesChanged(QStringList))); + QSignalSpy requestedSpy(network, SIGNAL(requestedCapabilitiesChanged(QStringList))); + QSignalSpy activeSpy(network, SIGNAL(activeCapabilitiesChanged(QStringList))); + QSignalSpy requestingSpy(network, SIGNAL(requestingCapabilities())); + + QVERIFY(availableSpy.isValid()); + QVERIFY(requestedSpy.isValid()); + QVERIFY(activeSpy.isValid()); + QVERIFY(requestingSpy.isValid()); + + int availableCount = 0; + int requestedCount = 0; + int activeCount = 0; + int requestingCount = 0; + + if (!requestedCaps.isEmpty()) { + network->setRequestedCapabilities(requestedCaps.split(" ", QString::SkipEmptyParts)); + ++requestedCount; + } + QCOMPARE(requestedSpy.count(), requestedCount); + + foreach (const QString& cap, availableCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(!network->hasCapability(cap)); + foreach (const QString& cap, activeCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(!network->isCapable(cap)); + + connection->open(); + QVERIFY(waitForOpened()); + + if (!initialCaps.isEmpty()) { + // typical ircd: "*", znc: "unknown-nick" + QVERIFY(waitForWritten(":irc.ser.ver CAP unknown-nick LS :" + initialCaps.toUtf8())); + ++availableCount; + ++requestingCount; + } + QCOMPARE(availableSpy.count(), availableCount); + QCOMPARE(requestingSpy.count(), requestingCount); + + foreach (const QString& cap, availableCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(network->hasCapability(cap)); + foreach (const QString& cap, activeCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(!network->isCapable(cap)); + + if (!ackedCaps.isEmpty()) { + QVERIFY(waitForWritten(":irc.ser.ver CAP jpnurmi ACK :" + ackedCaps.toUtf8())); + ++activeCount; + } + QCOMPARE(activeSpy.count(), activeCount); + + foreach (const QString& cap, availableCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(network->hasCapability(cap)); + foreach (const QString& cap, activeCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(network->isCapable(cap)); + + if (!nakedCaps.isEmpty()) + QVERIFY(waitForWritten(":irc.ser.ver CAP jpnurmi NAK :" + nakedCaps.toUtf8())); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + + if (!listedCaps.isEmpty()) { + QVERIFY(waitForWritten(":irc.ser.ver CAP jpnurmi LS :" + listedCaps.toUtf8())); + if (!equalCaps(listedCaps, initialCaps)) + ++availableCount; + } + QCOMPARE(availableSpy.count(), availableCount); + + QVERIFY(equalCaps(network->availableCapabilities().join(" "), availableCaps)); + QVERIFY(equalCaps(network->activeCapabilities().join(" "), activeCaps)); + QVERIFY(equalCaps(network->requestedCapabilities().join(" "), requestedCaps)); + + QCOMPARE(requestedSpy.count(), requestedCount); + QCOMPARE(requestingSpy.count(), requestingCount); + QCOMPARE(availableSpy.count(), availableCount); + QCOMPARE(activeSpy.count(), activeCount); + + foreach (const QString& cap, availableCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(network->hasCapability(cap)); + foreach (const QString& cap, activeCaps.split(" ", QString::SkipEmptyParts)) + QVERIFY(network->isCapable(cap)); + + // -> CLEAR + QString clearCaps; + foreach (const QString& cap, activeCaps.split(" ", QString::SkipEmptyParts)) + clearCaps += QString("-") + cap; + QVERIFY(waitForWritten(":irc.ser.ver CAP jpnurmi ACK :" + clearCaps.toUtf8())); + + if (!activeCaps.isEmpty()) + ++activeCount; + QCOMPARE(activeSpy.count(), activeCount); +} + +void tst_IrcNetwork::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcNetwork(0x0)")); + str.clear(); + + IrcConnection connection; + dbg << connection.network(); + QVERIFY(QRegExp("IrcNetwork\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str)); + str.clear(); + + connection.network()->setObjectName("obj"); + dbg << connection.network(); + QVERIFY(QRegExp("IrcNetwork\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str)); + str.clear(); + +#ifdef Q_OS_LINUX + // others have problems with symbols (win) or private headers (osx frameworks) + IrcNetworkPrivate::get(connection.network())->name = "net"; + dbg << connection.network(); + QVERIFY(QRegExp("IrcNetwork\\(0x[0-9A-Fa-f]+, name=obj, network=net\\) ").exactMatch(str)); + str.clear(); +#endif // Q_OS_LINUX + + dbg << IrcNetwork::MessageLength; + QCOMPARE(str.trimmed(), QString::fromLatin1("MessageLength")); + str.clear(); + + dbg << IrcNetwork::AllTypes; + QCOMPARE(str.trimmed(), QString::fromLatin1("AllTypes")); + str.clear(); + + dbg << (IrcNetwork::TypeA | IrcNetwork::TypeD); + QCOMPARE(str.trimmed(), QString::fromLatin1("(TypeA|TypeD)")); + str.clear(); + + dbg << (IrcNetwork::TypeB | IrcNetwork::TypeC); + QCOMPARE(str.trimmed(), QString::fromLatin1("(TypeB|TypeC)")); + str.clear(); + + dbg << (IrcNetwork::TypeA | IrcNetwork::TypeB | IrcNetwork::TypeC | IrcNetwork::TypeD); + QCOMPARE(str.trimmed(), QString::fromLatin1("(AllTypes)")); + str.clear(); +} + +QTEST_MAIN(tst_IrcNetwork) + +#include "tst_ircnetwork.moc" diff --git a/src/libcommuni/tests/auto/ircpalette/ircpalette.pro b/src/libcommuni/tests/auto/ircpalette/ircpalette.pro new file mode 100644 index 0000000..a31264d --- /dev/null +++ b/src/libcommuni/tests/auto/ircpalette/ircpalette.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircpalette.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircpalette/tst_ircpalette.cpp b/src/libcommuni/tests/auto/ircpalette/tst_ircpalette.cpp new file mode 100644 index 0000000..756b78d --- /dev/null +++ b/src/libcommuni/tests/auto/ircpalette/tst_ircpalette.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irc.h" +#include "ircpalette.h" +#include "irctextformat.h" +#include + +class tst_IrcPalette : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testColorNames(); + void testProperties_data(); + void testProperties(); +}; + +void tst_IrcPalette::testDefaults() +{ + IrcTextFormat format; + QVERIFY(format.palette()); + IrcPalette* palette = format.palette(); + QVERIFY(!palette->colorNames().isEmpty()); + for (int i = Irc::White; i <= Irc::LightGray; ++i) + QVERIFY(!palette->colorName(i).isEmpty()); + QCOMPARE(palette->colorName(-1, "fallback"), QString("fallback")); +} + +void tst_IrcPalette::testColorNames() +{ + IrcTextFormat format; + QVERIFY(format.palette()); + IrcPalette* palette = format.palette(); + QMap colorNames; + for (int i = -1; i <= 123; ++i) { + colorNames.insert(i, QString::number(i)); + palette->setColorName(i, QString::number(i)); + QCOMPARE(palette->colorName(i), QString::number(i)); + } + QCOMPARE(palette->colorNames(), colorNames); + + QMap dummies; + for (int i = 0; i < 100; i += 3) + dummies.insert(i, QString::number(i) + "-dummy"); + palette->setColorNames(dummies); + QCOMPARE(palette->colorNames(), dummies); +} + +void tst_IrcPalette::testProperties_data() +{ + QTest::addColumn("color"); + QTest::addColumn("prop"); + + QTest::newRow("white") << Irc::White << "white"; + QTest::newRow("black") << Irc::Black << "black"; + QTest::newRow("blue") << Irc::Blue << "blue"; + QTest::newRow("green") << Irc::Green << "green"; + QTest::newRow("red") << Irc::Red << "red"; + QTest::newRow("brown") << Irc::Brown << "brown"; + QTest::newRow("purple") << Irc::Purple << "purple"; + QTest::newRow("orange") << Irc::Orange << "orange"; + QTest::newRow("yellow") << Irc::Yellow << "yellow"; + QTest::newRow("lightGreen") << Irc::LightGreen << "lightGreen"; + QTest::newRow("cyan") << Irc::Cyan << "cyan"; + QTest::newRow("lightCyan") << Irc::LightCyan << "lightCyan"; + QTest::newRow("lightBlue") << Irc::LightBlue << "lightBlue"; + QTest::newRow("pink") << Irc::Pink << "pink"; + QTest::newRow("gray") << Irc::Gray << "gray"; + QTest::newRow("lightGray") << Irc::LightGray << "lightGray"; +} + +void tst_IrcPalette::testProperties() +{ + QFETCH(Irc::Color, color); + QFETCH(QString, prop); + + IrcTextFormat format; + QVERIFY(format.palette()); + IrcPalette* palette = format.palette(); + + QCOMPARE(palette->property(prop.toUtf8()).toString(), prop.toLower()); + + QVERIFY(palette->setProperty(prop.toUtf8(), QString("dummy"))); + QCOMPARE(palette->colorName(color), QString("dummy")); + QCOMPARE(palette->property(prop.toUtf8()).toString(), QString("dummy")); + + palette->setColorName(color, QString("dummier")); + QCOMPARE(palette->colorName(color), QString("dummier")); + QCOMPARE(palette->property(prop.toUtf8()).toString(), QString("dummier")); +} + +QTEST_MAIN(tst_IrcPalette) + +#include "tst_ircpalette.moc" diff --git a/src/libcommuni/tests/auto/irctextformat/irctextformat.pro b/src/libcommuni/tests/auto/irctextformat/irctextformat.pro new file mode 100644 index 0000000..3b90b66 --- /dev/null +++ b/src/libcommuni/tests/auto/irctextformat/irctextformat.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_irctextformat.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/irctextformat/tst_irctextformat.cpp b/src/libcommuni/tests/auto/irctextformat/tst_irctextformat.cpp new file mode 100644 index 0000000..377a438 --- /dev/null +++ b/src/libcommuni/tests/auto/irctextformat/tst_irctextformat.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "irc.h" +#include "irctextformat.h" +#include "ircpalette.h" +#include + +class tst_IrcTextFormat : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testPlainText_data(); + void testPlainText(); + void testHtml_data(); + void testHtml(); + void testUrls_data(); + void testUrls(); +}; + +void tst_IrcTextFormat::testDefaults() +{ + IrcTextFormat format; + QVERIFY(format.palette()); + QVERIFY(!format.urlPattern().isEmpty()); + QCOMPARE(format.spanFormat(), IrcTextFormat::SpanStyle); +} + +void tst_IrcTextFormat::testPlainText_data() +{ + QTest::addColumn("input"); + QTest::addColumn("output"); + + QTest::newRow("bold") << "\02bold\x0f" << "bold"; + QTest::newRow("line-through") << "\x13line-through\x0f" << "line-through"; + QTest::newRow("underline") << "\x15underline\x0f" << "underline"; + QTest::newRow("inverse") << "\x16inverse\x0f" << "inverse"; + QTest::newRow("italic") << "\x1ditalic\x0f" << "italic"; + QTest::newRow("underline") << "\x1funderline\x0f" << "underline"; + + IrcTextFormat format; + QVERIFY(format.palette()); + IrcPalette* palette = format.palette(); + for (int i = Irc::White; i <= Irc::LightGray; ++i) { + QString color = palette->colorName(i); + QTest::newRow(color.toUtf8()) << QString("\x03%1%2\x0f").arg(i).arg(color) << color; + } + + QTest::newRow("dummy \\x03") << "foo\x03 \02bold\x0f bar\x03" << "foo bold bar"; + QTest::newRow("extra \\x0f") << "foo\x0f \02bold\x0f bar\x0f" << "foo bold bar"; + QTest::newRow("background") << QString("foo \x03%1,%1red\x0f on \x03%1,%1red\x03 bar").arg(Irc::Red) << "foo red on red bar"; +} + +void tst_IrcTextFormat::testPlainText() +{ + QFETCH(QString, input); + QFETCH(QString, output); + + IrcTextFormat format; + QCOMPARE(format.toPlainText(input), output); + + format.parse(input); + QCOMPARE(format.plainText(), output); +} + +void tst_IrcTextFormat::testHtml_data() +{ + qRegisterMetaType(); + + QTest::addColumn("span"); + QTest::addColumn("input"); + QTest::addColumn("output"); + + QTest::newRow("style=bold") << IrcTextFormat::SpanStyle << "foo \02bold\x0f and \02bold\02 bar" << "foo bold and bold bar"; + QTest::newRow("class=bold") << IrcTextFormat::SpanClass << "foo \02bold\x0f and \02bold\02 bar" << "foo bold and bold bar"; + + QTest::newRow("style=line-through") << IrcTextFormat::SpanStyle << "foo \x13line\x0f and \x13through\x13 bar" << "foo line and through bar"; + QTest::newRow("class=line-through") << IrcTextFormat::SpanClass << "foo \x13line\x0f and \x13through\x13 bar" << "foo line and through bar"; + + QTest::newRow("style=underline1") << IrcTextFormat::SpanStyle << "foo \x15under\x0f and \x15line\x15 bar" << "foo under and line bar"; + + QTest::newRow("style=inverse") << IrcTextFormat::SpanStyle << "foo \x16inverse\x0f and \x16inverse\x16 bar" << "foo inverse and inverse bar"; + QTest::newRow("class=inverse") << IrcTextFormat::SpanClass << "foo \x16inverse\x0f and \x16inverse\x16 bar" << "foo inverse and inverse bar"; + + QTest::newRow("style=italic") << IrcTextFormat::SpanStyle << "foo \x1ditalic\x0f and \x1ditalic\x1d bar" << "foo italic and italic bar"; + QTest::newRow("class=italic") << IrcTextFormat::SpanClass << "foo \x1ditalic\x0f and \x1ditalic\x1d bar" << "foo italic and italic bar"; + + QTest::newRow("style=underline2") << IrcTextFormat::SpanStyle << "foo \x1funder\x0f and \x1fline\x1f bar" << "foo under and line bar"; + + IrcTextFormat format; + QVERIFY(format.palette()); + IrcPalette* palette = format.palette(); + for (int i = Irc::White; i <= Irc::LightGray; ++i) { + QString color = palette->colorName(i); + QTest::newRow(QString("style=%1").arg(color).toUtf8()) << IrcTextFormat::SpanStyle << QString("foo \x03%1%2\x0f and \x03%1%2\x03 bar").arg(i).arg(color) << QString("foo %1 and %1 bar").arg(color); + QTest::newRow(QString("class=%1").arg(color).toUtf8()) << IrcTextFormat::SpanClass << QString("foo \x03%1%2\x0f and \x03%1%2\x03 bar").arg(i).arg(color) << QString("foo %1 and %1 bar").arg(color); + } + + QTest::newRow("extra \\x0f") << IrcTextFormat::SpanStyle << "foo\x0f \02bold\x0f bar\x0f" << "foo bold bar"; + + QTest::newRow("style=background") << IrcTextFormat::SpanStyle << QString("foo \x03%1,%1red\x0f on \x03%1,%1red\x03 bar").arg(Irc::Red) << "foo red on red bar"; + QTest::newRow("class=background") << IrcTextFormat::SpanClass << QString("foo \x03%1,%1red\x0f on \x03%1,%1red\x03 bar").arg(Irc::Red) << "foo red on red bar"; +} + +void tst_IrcTextFormat::testHtml() +{ + QFETCH(IrcTextFormat::SpanFormat, span); + QFETCH(QString, input); + QFETCH(QString, output); + + IrcTextFormat format; + format.setSpanFormat(span); + QCOMPARE(format.toHtml(input), output); + + format.parse(input); + QCOMPARE(format.html(), output); +} + +Q_DECLARE_METATYPE(QList) +void tst_IrcTextFormat::testUrls_data() +{ + qRegisterMetaType >(); + + QTest::addColumn("pattern"); + QTest::addColumn("input"); + QTest::addColumn("output"); + QTest::addColumn >("urls"); + + QString defaultPattern = IrcTextFormat().urlPattern(); + + QTest::newRow("www.fi") << defaultPattern << "www.fi" << "www.fi" << (QList() << QUrl("http://www.fi")); + QTest::newRow("ftp.funet.fi") << defaultPattern << "ftp.funet.fi" << "ftp.funet.fi" << (QList() << QUrl("ftp://ftp.funet.fi")); + QTest::newRow("jpnurmi@gmail.com") << defaultPattern << "jpnurmi@gmail.com" << "jpnurmi@gmail.com" << (QList() << QUrl("mailto:jpnurmi@gmail.com")); + QTest::newRow("quote") << defaultPattern << "http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing" << "http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing" << (QList() << QUrl("http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing")); + QTest::newRow("percent") << defaultPattern << "http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing" << "http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing" << (QList() << QUrl("http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing")); + QTest::newRow("parentheses") << defaultPattern << "http://en.wikipedia.org/wiki/Qt_(software)" << "http://en.wikipedia.org/wiki/Qt_(software)" << (QList() << QUrl("http://en.wikipedia.org/wiki/Qt_(software)")); + QTest::newRow("hash & comma") << defaultPattern << "https://codereview.qt-project.org/#change,1" << "https://codereview.qt-project.org/#change,1" << (QList() << QUrl("https://codereview.qt-project.org/#change,1")); + QTest::newRow("equal & question & ampersand") << defaultPattern << "https://www.google.no/imghp?hl=en&tab=wi" << "https://www.google.no/imghp?hl=en&tab=wi" << (QList() << QUrl("https://www.google.no/imghp?hl=en&tab=wi")); + QTest::newRow("github commits") << defaultPattern << "https://github.com/communi/libcommuni/compare/ebf3c8ea47dc...19d66ddcb122" << "https://github.com/communi/libcommuni/compare/ebf3c8ea47dc...19d66ddcb122" << (QList() << QUrl("https://github.com/communi/libcommuni/compare/ebf3c8ea47dc...19d66ddcb122")); + QTest::newRow("multiple") << defaultPattern << "www.fi ftp.funet.fi jpnurmi@gmail.com" << "www.fi ftp.funet.fi jpnurmi@gmail.com" << (QList() << QUrl("http://www.fi") << QUrl("ftp://ftp.funet.fi") << QUrl("mailto:jpnurmi@gmail.com")); + QTest::newRow("empty pattern") << QString() << "www.fi ftp.funet.fi jpnurmi@gmail.com" << "www.fi ftp.funet.fi jpnurmi@gmail.com" << QList(); + + QTest::newRow("info") << defaultPattern + << QString("[freenode-info] if you're at a conference and other people are having trouble connecting, please mention it to staff: http://freenode.net/faq.shtml#gettinghelp") + << QString("[freenode-info] if you're at a conference and other people are having trouble connecting, please mention it to staff: http://freenode.net/faq.shtml#gettinghelp") + << (QList() << QUrl("http://freenode.net/faq.shtml#gettinghelp")); + QTest::newRow("topic") << defaultPattern + << QString("Communi 1.2.2 - IRC framework || Home: http://communi.github.com || Docs: http://communi.github.com/doc || MeeGo: http://store.ovi.com/content/219150") + << QString("Communi 1.2.2 - IRC framework || Home: http://communi.github.com || Docs: http://communi.github.com/doc || MeeGo: http://store.ovi.com/content/219150") + << (QList() << QUrl("http://communi.github.com") << QUrl("http://communi.github.com/doc") << QUrl("http://store.ovi.com/content/219150")); + QTest::newRow("commit") << defaultPattern + << QString("[communi-desktop] jpnurmi pushed 2 new commits to master: https://github.com/communi/communi-desktop/compare/257ca915a490...8832bfe8d0b8") + << QString("[communi-desktop] jpnurmi pushed 2 new commits to master: https://github.com/communi/communi-desktop/compare/257ca915a490...8832bfe8d0b8") + << (QList() << QUrl("https://github.com/communi/communi-desktop/compare/257ca915a490...8832bfe8d0b8")); + QTest::newRow("with protocol") << defaultPattern + << QString("aa http://www.fi bb ftp://ftp.funet.fi cc") + << QString("aa http://www.fi bb ftp://ftp.funet.fi cc") + << (QList() << QUrl("http://www.fi") << QUrl("ftp://ftp.funet.fi")); + QTest::newRow("without protocol") << defaultPattern + << QString("aa www.fi bb ftp.funet.fi cc jpnurmi@gmail.com dd") + << QString("aa www.fi bb ftp.funet.fi cc jpnurmi@gmail.com dd") + << (QList() << QUrl("http://www.fi") << QUrl("ftp://ftp.funet.fi") << QUrl("mailto:jpnurmi@gmail.com")); +} + +void tst_IrcTextFormat::testUrls() +{ + QFETCH(QString, pattern); + QFETCH(QString, input); + QFETCH(QString, output); + QFETCH(QList, urls); + + IrcTextFormat format; + format.setUrlPattern(pattern); + QCOMPARE(format.urlPattern(), pattern); + QCOMPARE(format.toHtml(input), output); + + format.parse(input); + QCOMPARE(format.html(), output); + QCOMPARE(format.urls(), urls); +} + +QTEST_MAIN(tst_IrcTextFormat) + +#include "tst_irctextformat.moc" diff --git a/src/libcommuni/tests/auto/ircuser/ircuser.pro b/src/libcommuni/tests/auto/ircuser/ircuser.pro new file mode 100644 index 0000000..b81617f --- /dev/null +++ b/src/libcommuni/tests/auto/ircuser/ircuser.pro @@ -0,0 +1,7 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircuser.cpp + +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircuser/tst_ircuser.cpp b/src/libcommuni/tests/auto/ircuser/tst_ircuser.cpp new file mode 100644 index 0000000..c575c14 --- /dev/null +++ b/src/libcommuni/tests/auto/ircuser/tst_ircuser.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircuser.h" +#include +#include +#ifdef Q_OS_LINUX +#include "ircuser_p.h" +#endif // Q_OS_LINUX + +class tst_IrcUser : public QObject +{ + Q_OBJECT + +private slots: + void testDefaults(); + void testSignals(); + void testDebug(); +}; + +void tst_IrcUser::testDefaults() +{ + IrcUser user; + QVERIFY(user.title().isEmpty()); + QVERIFY(user.name().isEmpty()); + QVERIFY(user.prefix().isEmpty()); + QVERIFY(user.mode().isEmpty()); + QVERIFY(!user.isServOp()); + QVERIFY(!user.isAway()); + QVERIFY(!user.channel()); +} + +void tst_IrcUser::testSignals() +{ + IrcUser user; + QSignalSpy titleSpy(&user, SIGNAL(titleChanged(QString))); + QSignalSpy nameSpy(&user, SIGNAL(nameChanged(QString))); + QSignalSpy prefixSpy(&user, SIGNAL(prefixChanged(QString))); + QSignalSpy modeSpy(&user, SIGNAL(modeChanged(QString))); + QSignalSpy servOpSpy(&user, SIGNAL(servOpChanged(bool))); + QSignalSpy awaySpy(&user, SIGNAL(awayChanged(bool))); + QVERIFY(titleSpy.isValid()); + QVERIFY(nameSpy.isValid()); + QVERIFY(prefixSpy.isValid()); + QVERIFY(modeSpy.isValid()); + QVERIFY(servOpSpy.isValid()); + QVERIFY(awaySpy.isValid()); +} + +void tst_IrcUser::testDebug() +{ + QString str; + QDebug dbg(&str); + + dbg << static_cast(0); + QCOMPARE(str.trimmed(), QString::fromLatin1("IrcUser(0x0)")); + str.clear(); + + IrcUser user; + dbg << &user; + QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str)); + str.clear(); + + user.setObjectName("obj"); + dbg << &user; + QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str)); + str.clear(); + +#ifdef Q_OS_LINUX + // others have problems with symbols (win) or private headers (osx frameworks) + IrcUserPrivate::get(&user)->setName("usr"); + dbg << &user; + QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj, user=usr\\) ").exactMatch(str)); + str.clear(); +#endif // Q_OS_LINUX +} + +QTEST_MAIN(tst_IrcUser) + +#include "tst_ircuser.moc" diff --git a/src/libcommuni/tests/auto/ircusermodel/ircusermodel.pro b/src/libcommuni/tests/auto/ircusermodel/ircusermodel.pro new file mode 100644 index 0000000..941d2ec --- /dev/null +++ b/src/libcommuni/tests/auto/ircusermodel/ircusermodel.pro @@ -0,0 +1,8 @@ +###################################################################### +# Communi +###################################################################### + +SOURCES += tst_ircusermodel.cpp + +include(../shared/shared.pri) +include(../auto.pri) diff --git a/src/libcommuni/tests/auto/ircusermodel/tst_ircusermodel.cpp b/src/libcommuni/tests/auto/ircusermodel/tst_ircusermodel.cpp new file mode 100644 index 0000000..20c1d5f --- /dev/null +++ b/src/libcommuni/tests/auto/ircusermodel/tst_ircusermodel.cpp @@ -0,0 +1,1688 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "ircusermodel.h" +#include "ircconnection.h" +#include "ircbuffermodel.h" +#include "ircchannel.h" +#include "ircuser.h" +#include "irc.h" + +#include "tst_ircdata.h" +#include "tst_ircclientserver.h" + +#include + +static bool caseInsensitiveLessThan(const QString& s1, const QString& s2) +{ + return s1.compare(s2, Qt::CaseInsensitive) < 0; +} + +static bool caseInsensitiveGreaterThan(const QString& s1, const QString& s2) +{ + return s1.compare(s2, Qt::CaseInsensitive) > 0; +} + +class tst_IrcUserModel : public tst_IrcClientServer +{ + Q_OBJECT + +public: + tst_IrcUserModel(); + +private slots: + void testDefaults(); + void testClear(); + void testSorting_data(); + void testSorting(); + void testActivity_freenode(); + void testActivity_ircnet(); + void testActivity_euirc(); + void testChanges(); + void testRoles(); + void testAIM(); + void testUser(); +}; + +Q_DECLARE_METATYPE(QModelIndex) +tst_IrcUserModel::tst_IrcUserModel() +{ + Irc::registerMetaTypes(); + qRegisterMetaType(); + qRegisterMetaType("IrcUser*"); + qRegisterMetaType("IrcChannel*"); + qRegisterMetaType >("QList"); +} + +void tst_IrcUserModel::testDefaults() +{ + IrcUserModel model; + QCOMPARE(model.count(), 0); + QVERIFY(model.isEmpty()); + QVERIFY(model.names().isEmpty()); + QVERIFY(model.users().isEmpty()); + QCOMPARE(model.displayRole(), Irc::TitleRole); + QVERIFY(!model.channel()); + QCOMPARE(model.sortMethod(), Irc::SortByHand); + QCOMPARE(model.sortOrder(), Qt::AscendingOrder); +} + +void tst_IrcUserModel::testClear() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QCOMPARE(bufferModel.count(), 0); + waitForWritten(":communi!communi@hidd.en JOIN :#channel"); + QCOMPARE(bufferModel.count(), 1); + + QPointer channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + + IrcUserModel userModel; + userModel.setChannel(channel); + waitForWritten(":irc.ser.ver 353 communi = #channel :a @b +c"); + waitForWritten(":irc.ser.ver 366 communi #channel :End of /NAMES list."); + QCOMPARE(userModel.count(), 3); + + QPointer a = userModel.find("a"); + QPointer b = userModel.find("b"); + QPointer c = userModel.find("c"); + + QVERIFY(a); + QVERIFY(b); + QVERIFY(c); + + QSignalSpy countSpy(&userModel, SIGNAL(countChanged(int))); + QSignalSpy emptySpy(&userModel, SIGNAL(emptyChanged(bool))); + QSignalSpy usersSpy(&userModel, SIGNAL(usersChanged(QList))); + QSignalSpy namesSpy(&userModel, SIGNAL(namesChanged(QStringList))); + QSignalSpy modelAboutToBeResetSpy(&userModel, SIGNAL(modelAboutToBeReset())); + QSignalSpy modelResetSpy(&userModel, SIGNAL(modelReset())); + + QVERIFY(countSpy.isValid()); + QVERIFY(emptySpy.isValid()); + QVERIFY(usersSpy.isValid()); + QVERIFY(namesSpy.isValid()); + QVERIFY(modelAboutToBeResetSpy.isValid()); + QVERIFY(modelResetSpy.isValid()); + + userModel.clear(); + + QCOMPARE(userModel.count(), 0); + QVERIFY(userModel.isEmpty()); + QCOMPARE(userModel.users(), QList()); + QCOMPARE(userModel.names(), QStringList()); + + QVERIFY(!userModel.get(0)); + QVERIFY(!userModel.find("a")); + QVERIFY(!userModel.find("b")); + QVERIFY(!userModel.find("c")); + QVERIFY(!userModel.contains("a")); + QVERIFY(!userModel.contains("b")); + QVERIFY(!userModel.contains("c")); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(countSpy.last().at(0).toInt(), 0); + + QCOMPARE(emptySpy.count(), 1); + QCOMPARE(emptySpy.last().at(0).toBool(), true); + + QCOMPARE(usersSpy.count(), 1); + QCOMPARE(usersSpy.last().at(0).value >(), QList()); + + QCOMPARE(namesSpy.count(), 1); + QCOMPARE(namesSpy.last().at(0).toStringList(), QStringList()); + + QCOMPARE(modelAboutToBeResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); + + QVERIFY(a); + QVERIFY(b); + QVERIFY(c); + + bufferModel.clear(); + + QVERIFY(!a); + QVERIFY(!b); + QVERIFY(!c); +} + +void tst_IrcUserModel::testSorting_data() +{ + QTest::addColumn("welcomeData"); + QTest::addColumn("joinData"); + QTest::addColumn("names"); + QTest::addColumn("admins"); + QTest::addColumn("ops"); + QTest::addColumn("halfops"); + QTest::addColumn("voices"); + + foreach (const QByteArray& key, tst_IrcData::keys()) { + QTest::newRow(key) + << tst_IrcData::welcome(key) + << tst_IrcData::join(key) + << tst_IrcData::names(key) + << tst_IrcData::admins(key) + << tst_IrcData::ops(key) + << tst_IrcData::halfops(key) + << tst_IrcData::voices(key); + } +} + +void tst_IrcUserModel::testSorting() +{ + QFETCH(QByteArray, welcomeData); + QFETCH(QByteArray, joinData); + QFETCH(QStringList, names); + QFETCH(QStringList, admins); + QFETCH(QStringList, ops); + QFETCH(QStringList, halfops); + QFETCH(QStringList, voices); + + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(welcomeData)); + QCOMPARE(bufferModel.count(), 0); + + QVERIFY(waitForWritten(joinData)); + + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + + IrcUserModel staticModel(channel); + QCOMPARE(staticModel.count(), names.count()); + for (int i = 0; i < staticModel.count(); ++i) { + IrcUser* user = staticModel.get(i); + QCOMPARE(user->name(), names.at(i)); + if (admins.contains(user->name())) { + QCOMPARE(user->mode(), QString("a")); + QCOMPARE(user->prefix(), QString("!")); + } else if (ops.contains(user->name())) { + QCOMPARE(user->mode(), QString("o")); + QCOMPARE(user->prefix(), QString("@")); + } else if (halfops.contains(user->name())) { + QCOMPARE(user->mode(), QString("h")); + QCOMPARE(user->prefix(), QString("%")); + } else if (voices.contains(user->name())) { + QCOMPARE(user->mode(), QString("v")); + QCOMPARE(user->prefix(), QString("+")); + } + } + + QStringList sorted = names; + qSort(sorted); + QCOMPARE(staticModel.names(), sorted); + + // IGNORE INVALID COLUMNS + staticModel.sort(-1, Qt::AscendingOrder); + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), names.at(i)); + + staticModel.sort(1, Qt::AscendingOrder); + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), names.at(i)); + + // STATIC - BY NAME - ASCENDING + staticModel.setSortMethod(Irc::SortByName); + staticModel.sort(0, Qt::AscendingOrder); + + QStringList nasc = names; + qSort(nasc.begin(), nasc.end(), caseInsensitiveLessThan); + + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), nasc.at(i)); + + // STATIC - BY NAME - DESCENDING + staticModel.setSortMethod(Irc::SortByName); + staticModel.sort(0, Qt::DescendingOrder); + + QStringList ndesc = names; + qSort(ndesc.begin(), ndesc.end(), caseInsensitiveGreaterThan); + + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), ndesc.at(i)); + + // STATIC - BY TITLE - ASCENDING + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::AscendingOrder); + + QStringList aasc = admins; + qSort(aasc.begin(), aasc.end(), caseInsensitiveLessThan); + + QStringList oasc = ops; + qSort(oasc.begin(), oasc.end(), caseInsensitiveLessThan); + + QStringList hasc = halfops; + qSort(hasc.begin(), hasc.end(), caseInsensitiveLessThan); + + QStringList vasc = voices; + qSort(vasc.begin(), vasc.end(), caseInsensitiveLessThan); + + QStringList tasc = aasc + oasc + hasc + vasc + nasc; + // remove duplicates + foreach (const QString& voice, voices) + tasc.removeAt(tasc.lastIndexOf(voice)); + foreach (const QString& halfop, halfops) + tasc.removeAt(tasc.lastIndexOf(halfop)); + foreach (const QString& op, ops) + tasc.removeAt(tasc.lastIndexOf(op)); + foreach (const QString& admin, admins) + tasc.removeAt(tasc.lastIndexOf(admin)); + + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), tasc.at(i)); + + // STATIC - BY TITLE - DESCENDING + staticModel.setSortMethod(Irc::SortByTitle); + staticModel.sort(0, Qt::DescendingOrder); + + QStringList adesc = admins; + qSort(adesc.begin(), adesc.end(), caseInsensitiveGreaterThan); + + QStringList odesc = ops; + qSort(odesc.begin(), odesc.end(), caseInsensitiveGreaterThan); + + QStringList hdesc = halfops; + qSort(hdesc.begin(), hdesc.end(), caseInsensitiveGreaterThan); + + QStringList vdesc = voices; + qSort(vdesc.begin(), vdesc.end(), caseInsensitiveGreaterThan); + + QStringList tdesc = ndesc + vdesc + hdesc + odesc + adesc; + // remove duplicates + foreach (const QString& voice, voices) + tdesc.removeAt(tdesc.indexOf(voice)); + foreach (const QString& halfop, halfops) + tdesc.removeAt(tdesc.indexOf(halfop)); + foreach (const QString& op, ops) + tdesc.removeAt(tdesc.indexOf(op)); + foreach (const QString& admin, admins) + tdesc.removeAt(tdesc.indexOf(admin)); + + for (int i = 0; i < staticModel.count(); ++i) + QCOMPARE(staticModel.get(i)->name(), tdesc.at(i)); + + // DYNAMIC - BY NAME, TITLE & ACTIVITY - ASCENDING + IrcUserModel dynamicModel(channel); + + dynamicModel.setSortMethod(Irc::SortByName); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), nasc.at(i)); + + dynamicModel.setSortMethod(Irc::SortByTitle); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), tasc.at(i)); + + dynamicModel.setSortMethod(Irc::SortByActivity); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), names.at(i)); + + // DYNAMIC - BY NAME, TITLE & ACTIVITY - DESCENDING + dynamicModel.setSortOrder(Qt::DescendingOrder); + + dynamicModel.setSortMethod(Irc::SortByName); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), ndesc.at(i)); + + dynamicModel.setSortMethod(Irc::SortByTitle); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), tdesc.at(i)); + + dynamicModel.setSortMethod(Irc::SortByActivity); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), names.at(names.count() - 1 - i)); + + // RESTORE USERS IN ASCENDING ORDER + dynamicModel.setSortOrder(Qt::AscendingOrder); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByName); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), nasc.at(i)); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByTitle); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), tasc.at(i)); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByActivity); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), names.at(i)); + + // RESTORE USERS IN DESCENDING ORDER + dynamicModel.setSortOrder(Qt::DescendingOrder); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByName); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), ndesc.at(i)); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByTitle); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), tdesc.at(i)); + + dynamicModel.setChannel(0); + dynamicModel.setSortMethod(Irc::SortByActivity); + dynamicModel.setChannel(channel); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), names.at(names.count() - 1 - i)); + + // DO NOTHING + dynamicModel.sort(Irc::SortByHand); + for (int i = 0; i < dynamicModel.count(); ++i) + QCOMPARE(dynamicModel.get(i)->name(), names.at(names.count() - 1 - i)); +} + +void tst_IrcUserModel::testActivity_freenode() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome("freenode"))); + QCOMPARE(bufferModel.count(), 0); + + QVERIFY(waitForWritten(tst_IrcData::join("freenode"))); + + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + + QStringList names = tst_IrcData::names("freenode"); + + IrcUserModel activityModel(channel); + activityModel.setSortMethod(Irc::SortByActivity); + + int count = names.count(); + + QVERIFY(waitForWritten(":smurfy!~smurfy@hidd.en PART #freenode")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("smurfy")); + + QVERIFY(waitForWritten(":ToApolytoXaos!~ToApolyto@hidd.en QUIT :Quit: Leaving")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("ToApolytoXaos")); + + QVERIFY(waitForWritten(":agsrv!~guest@hidd.en JOIN #freenode")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("agsrv")), 0); + + QVERIFY(waitForWritten(":Hello71!~Hello71@hidd.en PRIVMSG #freenode :straterra: there are many users on it")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("Hello71")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("straterra")), 1); + + QVERIFY(waitForWritten(":straterra!straterra@hidd.en PRIVMSG #freenode :what?")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("straterra")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("Hello71")), 1); + + QVERIFY(waitForWritten(":JuxTApose!~indigital@hidd.en NICK :JuxTApose_afk")); + QCOMPARE(activityModel.count(), count); + QVERIFY(!activityModel.contains("JuxTApose")); + QCOMPARE(activityModel.indexOf(activityModel.find("JuxTApose_afk")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("straterra")), 1); + QCOMPARE(activityModel.indexOf(activityModel.find("Hello71")), 2); + + QVERIFY(waitForWritten(":communi!communi@hidd.en PRIVMSG #freenode :+tomaw: ping")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("communi")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("tomaw")), 1); + + QVERIFY(waitForWritten(":Hello71!~Hello71@hidd.en NOTICE #freenode :just testing...")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("Hello71")), 0); +} + +void tst_IrcUserModel::testActivity_ircnet() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome("ircnet"))); + QCOMPARE(bufferModel.count(), 0); + + QVERIFY(waitForWritten(tst_IrcData::join("ircnet"))); + + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + + QStringList names = tst_IrcData::names("ircnet"); + + IrcUserModel activityModel(channel); + activityModel.setSortMethod(Irc::SortByActivity); + + int count = names.count(); + + QVERIFY(waitForWritten(":_box!~box@hidd.en QUIT :Broken pipe")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("_box")); + + QVERIFY(waitForWritten(":ip!~v6@hidd.en QUIT :Connection reset by peer")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("ip")); + + QVERIFY(waitForWritten(":[m]!m@hidd.en MODE #uptimed +b *!*x@does.matter.not*")); + QCOMPARE(activityModel.count(), count); + + QVERIFY(waitForWritten(":[m]!m@hidd.en KICK #uptimed \\x00 :lame exit sorry :P")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("\\x00")); + + QVERIFY(waitForWritten(":_box!~box@hidd.en JOIN :#uptimed")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("_box")), 0); + + QVERIFY(waitForWritten(":Voicer!mrozu@hidd.en MODE #uptimed +v _box")); + QCOMPARE(activityModel.count(), count); + + QVERIFY(waitForWritten(":t0r-!t0r@hidd.en PRIVMSG #uptimed :there is no sense for _box and ip to join the contest")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("t0r-")), 0); + + QVERIFY(waitForWritten(":ip!~v6@hidd.en JOIN :#uptimed")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("ip")), 0); + + QVERIFY(waitForWritten(":Voicer!mrozu@hidd.en MODE #uptimed +v ip")); + QCOMPARE(activityModel.count(), count); + + QVERIFY(waitForWritten(":[m]!m@hidd.en MODE #uptimed +b *!*v6@*.does.matter.not")); + QCOMPARE(activityModel.count(), count); + + QVERIFY(waitForWritten(":[m]!m@hidd.en KICK #uptimed ip :no reason")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("ip")); + + QVERIFY(waitForWritten(":t0r-!t0r@hidd.en PRIVMSG #uptimed :they are going down every second")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("t0r-")), 0); + + QVERIFY(waitForWritten(":t0r-!t0r@hidd.en PRIVMSG #uptimed :yeah")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("t0r-")), 0); + + QVERIFY(waitForWritten(":[m]!m@hidd.en MODE #uptimed -b *!*box@*.does.not.matter")); + QCOMPARE(activityModel.count(), count); + + QVERIFY(waitForWritten(":[m]!m@hidd.en KICK #uptimed _box :no reason")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("_box")); +} + +void tst_IrcUserModel::testActivity_euirc() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome("euirc"))); + QCOMPARE(bufferModel.count(), 0); + + QVERIFY(waitForWritten(tst_IrcData::join("euirc"))); + + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + + QStringList names = tst_IrcData::names("euirc"); + + IrcUserModel activityModel(channel); + activityModel.setSortMethod(Irc::SortByActivity); + + int count = names.count(); + + QVERIFY(waitForWritten(":Marko10_000!~marko@hidd.en JOIN :#euirc\n")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("Marko10_000")), 0); + + QVERIFY(waitForWritten(":Marko10_000!~marko@hidd.en NICK :Guest775\n")); + QCOMPARE(activityModel.count(), count); + QVERIFY(!activityModel.contains("Marko10_000")); + QCOMPARE(activityModel.indexOf(activityModel.find("Guest775")), 0); + + QVERIFY(waitForWritten(":Guest775!~marko@hidd.en QUIT :Quit: Verlassend\n")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("Guest775")); + + QVERIFY(waitForWritten(":Marko10_000!~marko@hidd.en JOIN :#euirc\n")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("Marko10_000")), 0); + + QVERIFY(waitForWritten(":Guest774!absk007@hidd.en QUIT :Quit: Good Bye. I Quit...\n")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("Guest774")); + + QVERIFY(waitForWritten(":absk007!absk007@hidd.en JOIN :#euirc\n")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("absk007")), 0); + + QVERIFY(waitForWritten(":charly6!~Miranda@hidd.en QUIT :Client exited\n")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("charly6")); + + QVERIFY(waitForWritten(":absk007!absk007@hidd.en NICK :Guest776\n")); + QCOMPARE(activityModel.count(), count); + QVERIFY(!activityModel.contains("absk007")); + QCOMPARE(activityModel.indexOf(activityModel.find("Guest776")), 0); + + QVERIFY(waitForWritten(":Tina-chan_onAir!~kvirc@hidd.en NICK :Tina-chan\n")); + QCOMPARE(activityModel.count(), count); + QVERIFY(!activityModel.contains("Tina-chan_onAir")); + QCOMPARE(activityModel.indexOf(activityModel.find("Tina-chan")), 0); + + QVERIFY(waitForWritten(":Guest776!absk007@hidd.en NICK :absk007\n")); + QCOMPARE(activityModel.count(), count); + QVERIFY(!activityModel.contains("Guest776")); + QCOMPARE(activityModel.indexOf(activityModel.find("absk007")), 0); + + QVERIFY(waitForWritten(":aleksandr!~aleksandr@hidd.en PRIVMSG #euirc :absk007, last warning. fix your client/script\n")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("aleksandr")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("absk007")), 1); + + QVERIFY(waitForWritten(":charly6!~Miranda@hidd.en JOIN :#euirc\n")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("charly6")), 0); + + QVERIFY(waitForWritten(":absk007!absk007@hidd.en PRIVMSG #euirc :aleksandr, what did i do this time?\n")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("absk007")), 0); + QCOMPARE(activityModel.indexOf(activityModel.find("aleksandr")), 1); + + QVERIFY(waitForWritten(":aleksandr!~aleksandr@hidd.en PRIVMSG #euirc :if you need help, join #opers\n")); + QCOMPARE(activityModel.count(), count); + QCOMPARE(activityModel.indexOf(activityModel.find("aleksandr")), 0); + + QVERIFY(waitForWritten(":charly6!~Miranda@hidd.en QUIT :Client exited\n")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("charly6")); + + QVERIFY(waitForWritten(":icefly!~icefly@hidd.en PART #euirc :Once you know what it is you want to be true, instinct is a very useful device for enabling you to know that it is\n")); + QCOMPARE(activityModel.count(), --count); + QVERIFY(!activityModel.contains("icefly")); + + QVERIFY(waitForWritten(":icefly!~icefly@hidd.en JOIN :#euirc\n")); + QCOMPARE(activityModel.count(), ++count); + QCOMPARE(activityModel.indexOf(activityModel.find("icefly")), 0); +} + +void tst_IrcUserModel::testChanges() +{ + IrcUserModel userModel; + + // IrcUserModel signals + QSignalSpy addedSpy(&userModel, SIGNAL(added(IrcUser*))); + QSignalSpy removedSpy(&userModel, SIGNAL(removed(IrcUser*))); + QSignalSpy aboutToBeAddedSpy(&userModel, SIGNAL(aboutToBeAdded(IrcUser*))); + QSignalSpy aboutToBeRemovedSpy(&userModel, SIGNAL(aboutToBeRemoved(IrcUser*))); + QSignalSpy countChangedSpy(&userModel, SIGNAL(countChanged(int))); + QSignalSpy namesChangedSpy(&userModel, SIGNAL(namesChanged(QStringList))); + QSignalSpy usersChangedSpy(&userModel, SIGNAL(usersChanged(QList))); + QSignalSpy channelChangedSpy(&userModel, SIGNAL(channelChanged(IrcChannel*))); + + QVERIFY(addedSpy.isValid()); + QVERIFY(removedSpy.isValid()); + QVERIFY(aboutToBeAddedSpy.isValid()); + QVERIFY(aboutToBeRemovedSpy.isValid()); + QVERIFY(countChangedSpy.isValid()); + QVERIFY(namesChangedSpy.isValid()); + QVERIFY(usersChangedSpy.isValid()); + QVERIFY(channelChangedSpy.isValid()); + + int aboutToBeAddedCount = 0, addedCount = 0; + int aboutToBeRemovedCount = 0, removedCount = 0; + int countChangedCount = 0; + int namesChangedCount = 0; + int usersChangedCount = 0; + int channelChangedCount = 0; + + // relevant QAbstractItemModel signals + QSignalSpy dataChangedSpy(&userModel, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy modelAboutToBeResetSpy(&userModel, SIGNAL(modelAboutToBeReset())); + QSignalSpy modelResetSpy(&userModel, SIGNAL(modelReset())); + QSignalSpy layoutAboutToBeChangedSpy(&userModel, SIGNAL(layoutAboutToBeChanged())); + QSignalSpy layoutChangedSpy(&userModel, SIGNAL(layoutChanged())); + QSignalSpy rowsAboutToBeInsertedSpy(&userModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowsInsertedSpy(&userModel, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy rowsAboutToBeRemovedSpy(&userModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowsRemovedSpy(&userModel, SIGNAL(rowsRemoved(QModelIndex,int,int))); + + QVERIFY(dataChangedSpy.isValid()); + QVERIFY(modelAboutToBeResetSpy.isValid()); + QVERIFY(modelResetSpy.isValid()); + QVERIFY(layoutAboutToBeChangedSpy.isValid()); + QVERIFY(layoutChangedSpy.isValid()); + QVERIFY(rowsAboutToBeInsertedSpy.isValid()); + QVERIFY(rowsInsertedSpy.isValid()); + QVERIFY(rowsAboutToBeRemovedSpy.isValid()); + QVERIFY(rowsRemovedSpy.isValid()); + + int dataChangedCount = 0; + int modelAboutToBeResetCount = 0, modelResetCount = 0; + int layoutAboutToBeChangedCount = 0, layoutChangedCount = 0; + int rowsAboutToBeInsertedCount = 0, rowsInsertedCount = 0; + int rowsAboutToBeRemovedCount = 0, rowsRemovedCount = 0; + + // ### setup #communi (5): communi @ChanServ +qtassistant Guest1234 +qout + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN :#communi")); + QVERIFY(waitForWritten(":irc.ifi.uio.no 353 communi = #communi :communi @ChanServ +qtassistant Guest1234 +qout")); + QVERIFY(waitForWritten(":irc.ifi.uio.no 366 communi #communi :End of NAMES list.")); + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + QCOMPARE(channel->title(), QString("#communi")); + + // ### ready to go! + userModel.setChannel(channel); + QCOMPARE(channelChangedSpy.count(), ++channelChangedCount); + QCOMPARE(channelChangedSpy.last().at(0).value(), channel); + QCOMPARE(modelAboutToBeResetSpy.count(), ++modelAboutToBeResetCount); + QCOMPARE(modelResetSpy.count(), ++modelResetCount); + + QStringList names = QStringList() << "communi" << "ChanServ" << "qtassistant" << "Guest1234" << "qout"; + QStringList titles = QStringList() << "communi" << "@ChanServ" << "+qtassistant" << "Guest1234" << "+qout"; + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + } + + QPointer communi = userModel.get(0); + QVERIFY(communi); + QCOMPARE(communi->name(), QString("communi")); + QCOMPARE(communi->mode(), QString()); + QCOMPARE(communi->prefix(), QString()); + + QPointer ChanServ = userModel.get(1); + QVERIFY(ChanServ); + QCOMPARE(ChanServ->name(), QString("ChanServ")); + QCOMPARE(ChanServ->mode(), QString("o")); + QCOMPARE(ChanServ->prefix(), QString("@")); + + QPointer qtassistant = userModel.get(2); + QVERIFY(qtassistant); + QCOMPARE(qtassistant->name(), QString("qtassistant")); + QCOMPARE(qtassistant->mode(), QString("v")); + QCOMPARE(qtassistant->prefix(), QString("+")); + + QPointer Guest1234 = userModel.get(3); + QVERIFY(Guest1234); + QCOMPARE(Guest1234->name(), QString("Guest1234")); + QCOMPARE(Guest1234->mode(), QString()); + QCOMPARE(Guest1234->prefix(), QString()); + + QPointer qout = userModel.get(4); + QVERIFY(qout); + QCOMPARE(qout->name(), QString("qout")); + QCOMPARE(qout->mode(), QString("v")); + QCOMPARE(qout->prefix(), QString("+")); + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), 5); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "Guest1234" << "communi" << "qout" << "qtassistant"); + + QList users = QList() << communi << ChanServ << qtassistant << Guest1234 << qout; + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + // ### trigger sort -> layout change + userModel.setSortMethod(Irc::SortByTitle); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi << Guest1234; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi" << "Guest1234"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi" << "Guest1234"; + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + // ### trigger sort -> layout change + userModel.setSortMethod(Irc::SortByName); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + // Irc::SortByName + users = QList() << ChanServ << communi << Guest1234 << qout << qtassistant; + names = QStringList() << "ChanServ" << "communi" << "Guest1234" << "qout" << "qtassistant"; + titles = QStringList() << "@ChanServ" << "communi" << "Guest1234" << "+qout" << "+qtassistant"; + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + // ### trigger model reset + userModel.setChannel(0); + QCOMPARE(channelChangedSpy.count(), ++channelChangedCount); + QCOMPARE(channelChangedSpy.last().at(0).value(), static_cast(0)); + QCOMPARE(modelAboutToBeResetSpy.count(), ++modelAboutToBeResetCount); + QCOMPARE(modelResetSpy.count(), ++modelResetCount); + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), 0); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList()); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), QList()); + + // ### empty model -> no layout change + userModel.setSortMethod(Irc::SortByActivity); + QCOMPARE(layoutAboutToBeChangedSpy.count(), layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), layoutChangedCount); + + // ### reset again + userModel.setChannel(channel); + QCOMPARE(modelAboutToBeResetSpy.count(), ++modelAboutToBeResetCount); + QCOMPARE(modelResetSpy.count(), ++modelResetCount); + + // Irc::SortByActivity + users = QList() << communi << ChanServ << qtassistant << Guest1234 << qout; + names = QStringList() << "communi" << "ChanServ" << "qtassistant" << "Guest1234" << "qout"; + titles = QStringList() << "communi" << "@ChanServ" << "+qtassistant" << "Guest1234" << "+qout"; + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), users.count()); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "Guest1234" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QSignalSpy guestTitleChangedSpy(Guest1234, SIGNAL(titleChanged(QString))); + QSignalSpy guestNameChangedSpy(Guest1234, SIGNAL(nameChanged(QString))); + QSignalSpy guestPrefixChangedSpy(Guest1234, SIGNAL(prefixChanged(QString))); + QSignalSpy guestModeChangedSpy(Guest1234, SIGNAL(modeChanged(QString))); + QVERIFY(guestTitleChangedSpy.isValid()); + QVERIFY(guestNameChangedSpy.isValid()); + QVERIFY(guestPrefixChangedSpy.isValid()); + QVERIFY(guestModeChangedSpy.isValid()); + + int guestTitleChangedCount = 0; + int guestNameChangedCount = 0; + int guestPrefixChangedCount = 0; + int guestModeChangedCount = 0; + + // ### sorted by activity -> trigger a change in names & users, count remains intact + QVERIFY(waitForWritten(":Guest1234!~Guest1234@hidd.en NICK :Guest5678")); + + QCOMPARE(Guest1234->name(), QString("Guest5678")); + QCOMPARE(Guest1234->title(), QString("Guest5678")); + + QCOMPARE(guestTitleChangedSpy.count(), ++guestTitleChangedCount); + QCOMPARE(guestTitleChangedSpy.last().at(0).toString(), QString("Guest5678")); + + QCOMPARE(guestNameChangedSpy.count(), ++guestNameChangedCount); + QCOMPARE(guestNameChangedSpy.last().at(0).toString(), QString("Guest5678")); + + QCOMPARE(guestPrefixChangedSpy.count(), guestPrefixChangedCount); + QCOMPARE(guestModeChangedSpy.count(), guestModeChangedCount); + + int previousIndex = users.indexOf(Guest1234); + + // Irc::SortByActivity + users = QList() << Guest1234 << communi << ChanServ << qtassistant << qout; + names = QStringList() << "Guest5678" << "communi" << "ChanServ" << "qtassistant" << "qout"; + titles = QStringList() << "Guest5678" << "communi" << "@ChanServ" << "+qtassistant" << "+qout"; + + int nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "Guest5678" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + QModelIndex topLeft = dataChangedSpy.last().at(0).value(); + QModelIndex bottomRight = dataChangedSpy.last().at(0).value(); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), previousIndex); + QCOMPARE(topLeft.column(), 0); + + // TODO: nick change AND activity promotion + // => would ideally still result to just one change... + rowsAboutToBeRemovedCount += 2; + rowsRemovedCount += 2; + rowsAboutToBeInsertedCount += 2; + rowsInsertedCount += 2; + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // ### trigger sort -> layout change + userModel.setSortMethod(Irc::SortByTitle); + QCOMPARE(layoutAboutToBeChangedSpy.count(), ++layoutAboutToBeChangedCount); + QCOMPARE(layoutChangedSpy.count(), ++layoutChangedCount); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi << Guest1234; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi" << "Guest5678"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi" << "Guest5678"; + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + // ### sorted by title -> trigger a change in names & users, count remains intact + QVERIFY(waitForWritten(":Guest5678!~Guest1234@hidd.en NICK :Guest1234")); + + QCOMPARE(Guest1234->name(), QString("Guest1234")); + QCOMPARE(Guest1234->title(), QString("Guest1234")); + + QCOMPARE(guestTitleChangedSpy.count(), ++guestTitleChangedCount); + QCOMPARE(guestTitleChangedSpy.last().at(0).toString(), QString("Guest1234")); + + QCOMPARE(guestNameChangedSpy.count(), ++guestNameChangedCount); + QCOMPARE(guestNameChangedSpy.last().at(0).toString(), QString("Guest1234")); + + QCOMPARE(guestPrefixChangedSpy.count(), guestPrefixChangedCount); + QCOMPARE(guestModeChangedSpy.count(), guestModeChangedCount); + + previousIndex = users.indexOf(Guest1234); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi << Guest1234; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi" << "Guest1234"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi" << "Guest1234"; + + nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "Guest1234" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), usersChangedCount); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + topLeft = dataChangedSpy.last().at(0).value(); + bottomRight = dataChangedSpy.last().at(1).value(); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), 4); + QCOMPARE(topLeft.column(), 0); + + // TODO: nick change without index change + // => would ideally result to merely a data change... + QCOMPARE(previousIndex, nextIndex); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // ### sorted by title -> trigger a change in users, count & names remain intact + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. MODE #communi +v Guest1234")); + + QCOMPARE(Guest1234->name(), QString("Guest1234")); + QCOMPARE(Guest1234->title(), QString("+Guest1234")); + QCOMPARE(Guest1234->prefix(), QString("+")); + QCOMPARE(Guest1234->mode(), QString("v")); + + QCOMPARE(guestTitleChangedSpy.count(), ++guestTitleChangedCount); + QCOMPARE(guestTitleChangedSpy.last().at(0).toString(), QString("+Guest1234")); + + QCOMPARE(guestNameChangedSpy.count(), guestNameChangedCount); + + QCOMPARE(guestPrefixChangedSpy.count(), ++guestPrefixChangedCount); + QCOMPARE(guestPrefixChangedSpy.last().at(0).toString(), QString("+")); + + QCOMPARE(guestModeChangedSpy.count(), ++guestModeChangedCount); + QCOMPARE(guestModeChangedSpy.last().at(0).toString(), QString("v")); + + previousIndex = users.indexOf(Guest1234); + + // Irc::SortByTitle + users = QList() << ChanServ << Guest1234 << qout << qtassistant << communi; + names = QStringList() << "ChanServ" << "Guest1234" << "qout" << "qtassistant" << "communi"; + titles = QStringList() << "@ChanServ" << "+Guest1234" << "+qout" << "+qtassistant" << "communi"; + + nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(namesChangedSpy.count(), namesChangedCount); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + topLeft = dataChangedSpy.last().at(0).value(); + bottomRight = dataChangedSpy.last().at(1).value(); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), previousIndex); + QCOMPARE(topLeft.column(), 0); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // ### sorted by title -> trigger a change in users, count & names remain intact + QVERIFY(waitForWritten(":ChanServ!ChanServ@services. MODE #communi -v Guest1234")); + + QCOMPARE(Guest1234->name(), QString("Guest1234")); + QCOMPARE(Guest1234->title(), QString("Guest1234")); + QCOMPARE(Guest1234->prefix(), QString()); + QCOMPARE(Guest1234->mode(), QString()); + + QCOMPARE(guestTitleChangedSpy.count(), ++guestTitleChangedCount); + QCOMPARE(guestTitleChangedSpy.last().at(0).toString(), QString("Guest1234")); + + QCOMPARE(guestNameChangedSpy.count(), guestNameChangedCount); + + QCOMPARE(guestPrefixChangedSpy.count(), ++guestPrefixChangedCount); + QCOMPARE(guestPrefixChangedSpy.last().at(0).toString(), QString()); + + QCOMPARE(guestModeChangedSpy.count(), ++guestModeChangedCount); + QCOMPARE(guestModeChangedSpy.last().at(0).toString(), QString()); + + previousIndex = users.indexOf(Guest1234); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi << Guest1234; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi" << "Guest1234"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi" << "Guest1234"; + + nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(namesChangedSpy.count(), namesChangedCount); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + topLeft = dataChangedSpy.last().at(0).value(); + bottomRight = dataChangedSpy.last().at(1).value(); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), previousIndex); + QCOMPARE(topLeft.column(), 0); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // ### sorted by title -> trigger a change in count, users & names + QVERIFY(waitForWritten(":Guest1234!~Guest1234@hidd.en PART #communi")); + + QVERIFY(Guest1234); // deleteLater()'d + + QCOMPARE(aboutToBeRemovedSpy.count(), ++aboutToBeRemovedCount); + QCOMPARE(aboutToBeRemovedSpy.last().at(0).value(), Guest1234.data()); + + QCOMPARE(removedSpy.count(), ++removedCount); + QCOMPARE(removedSpy.last().at(0).value(), Guest1234.data()); + + previousIndex = users.indexOf(Guest1234); + + QCoreApplication::sendPostedEvents(Guest1234, QEvent::DeferredDelete); + QVERIFY(!Guest1234); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi"; + + nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), users.count()); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + + // ### sorted by title -> trigger a change in count, users & names + QVERIFY(waitForWritten(":Guest1234!~Guest1234@hidd.en JOIN #communi")); + + Guest1234 = userModel.find("Guest1234"); + QVERIFY(Guest1234); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), Guest1234.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), Guest1234.data()); + + previousIndex = users.indexOf(Guest1234); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << communi << Guest1234; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "communi" << "Guest1234"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "communi" << "Guest1234"; + + nextIndex = users.indexOf(Guest1234); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), users.count()); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "ChanServ" << "Guest1234" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + QPointer Bot = Guest1234; + + QSignalSpy botTitleChangedSpy(Guest1234, SIGNAL(titleChanged(QString))); + QSignalSpy botNameChangedSpy(Guest1234, SIGNAL(nameChanged(QString))); + QSignalSpy botPrefixChangedSpy(Guest1234, SIGNAL(prefixChanged(QString))); + QSignalSpy botModeChangedSpy(Guest1234, SIGNAL(modeChanged(QString))); + QVERIFY(botTitleChangedSpy.isValid()); + QVERIFY(botNameChangedSpy.isValid()); + QVERIFY(botPrefixChangedSpy.isValid()); + QVERIFY(botModeChangedSpy.isValid()); + + int botTitleChangedCount = 0; + int botNameChangedCount = 0; + int botPrefixChangedCount = 0; + int botModeChangedCount = 0; + + // ### sorted by title -> trigger a change in users & names, count remains intact + QVERIFY(waitForWritten(":Guest1234!~Guest1234@hidd.en NICK :Bot")); + + QCOMPARE(Bot->name(), QString("Bot")); + QCOMPARE(Bot->title(), QString("Bot")); + + QCOMPARE(botTitleChangedSpy.count(), ++botTitleChangedCount); + QCOMPARE(botTitleChangedSpy.last().at(0).toString(), QString("Bot")); + + QCOMPARE(botNameChangedSpy.count(), ++botNameChangedCount); + QCOMPARE(botNameChangedSpy.last().at(0).toString(), QString("Bot")); + + QCOMPARE(botPrefixChangedSpy.count(), botPrefixChangedCount); + QCOMPARE(botModeChangedSpy.count(), botModeChangedCount); + + previousIndex = users.indexOf(Bot); + + // Irc::SortByTitle + users = QList() << ChanServ << qout << qtassistant << Bot << communi; + names = QStringList() << "ChanServ" << "qout" << "qtassistant" << "Bot" << "communi"; + titles = QStringList() << "@ChanServ" << "+qout" << "+qtassistant" << "Bot" << "communi"; + + nextIndex = users.indexOf(Bot); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "Bot" << "ChanServ" << "communi" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), ++dataChangedCount); + topLeft = dataChangedSpy.last().at(0).value(); + bottomRight = dataChangedSpy.last().at(0).value(); + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QVERIFY(topLeft == bottomRight); + QCOMPARE(topLeft.row(), previousIndex); + QCOMPARE(topLeft.column(), 0); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), ++rowsAboutToBeRemovedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsAboutToBeRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsRemovedSpy.count(), ++rowsRemovedCount); + QCOMPARE(rowsRemovedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsRemovedSpy.last().at(1).toInt(), previousIndex); + QCOMPARE(rowsRemovedSpy.last().at(2).toInt(), previousIndex); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // ### sorted by name, descending -> trigger a change in count, users & names + userModel.setSortOrder(Qt::DescendingOrder); + userModel.setSortMethod(Irc::SortByName); + QVERIFY(waitForWritten(":fake!fake@hidd.en JOIN #communi")); + + QPointer fake = userModel.find("fake"); + QVERIFY(fake); + + QCOMPARE(aboutToBeAddedSpy.count(), ++aboutToBeAddedCount); + QCOMPARE(aboutToBeAddedSpy.last().at(0).value(), fake.data()); + + QCOMPARE(addedSpy.count(), ++addedCount); + QCOMPARE(addedSpy.last().at(0).value(), fake.data()); + + previousIndex = users.indexOf(fake); + + // Irc::SortByName - descending + users = QList() << qtassistant << qout << fake << communi << ChanServ << Bot; + names = QStringList() << "qtassistant" << "qout" << "fake" << "communi" << "ChanServ" << "Bot"; + titles = QStringList() << "+qtassistant" << "+qout" << "fake" << "communi" << "@ChanServ" << "Bot"; + + nextIndex = users.indexOf(fake); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), ++countChangedCount); + QCOMPARE(countChangedSpy.last().at(0).toInt(), users.count()); + + QCOMPARE(namesChangedSpy.count(), ++namesChangedCount); + QCOMPARE(namesChangedSpy.last().at(0).toStringList(), QStringList() << "Bot" << "ChanServ" << "communi" << "fake" << "qout" << "qtassistant"); + + QCOMPARE(usersChangedSpy.count(), ++usersChangedCount); + QCOMPARE(usersChangedSpy.last().at(0).value >(), users); + + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + + QCOMPARE(rowsAboutToBeInsertedSpy.count(), ++rowsAboutToBeInsertedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsAboutToBeInsertedSpy.last().at(2).toInt(), nextIndex); + + QCOMPARE(rowsInsertedSpy.count(), ++rowsInsertedCount); + QCOMPARE(rowsInsertedSpy.last().at(0).value(), topLeft.parent()); + QCOMPARE(rowsInsertedSpy.last().at(1).toInt(), nextIndex); + QCOMPARE(rowsInsertedSpy.last().at(2).toInt(), nextIndex); + + // QUIT -> no changes + QVERIFY(waitForWritten(":communi!communi@hidd.en QUIT :bye")); + + QCOMPARE(userModel.count(), names.count()); + for (int i = 0; i < userModel.count(); ++i) { + QCOMPARE(userModel.get(i)->name(), names.at(i)); + QCOMPARE(userModel.get(i)->title(), titles.at(i)); + QCOMPARE(userModel.get(i), users.at(i)); + } + + QCOMPARE(countChangedSpy.count(), countChangedCount); + QCOMPARE(namesChangedSpy.count(), namesChangedCount); + QCOMPARE(usersChangedSpy.count(), usersChangedCount); + QCOMPARE(dataChangedSpy.count(), dataChangedCount); + QCOMPARE(rowsAboutToBeRemovedSpy.count(), rowsAboutToBeRemovedCount); + QCOMPARE(rowsRemovedSpy.count(), rowsRemovedCount); + QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsAboutToBeInsertedCount); + QCOMPARE(rowsInsertedSpy.count(), rowsInsertedCount); + QCOMPARE(modelAboutToBeResetSpy.count(), modelAboutToBeResetCount); + QCOMPARE(modelResetSpy.count(), modelResetCount); +} + +void tst_IrcUserModel::testRoles() +{ + IrcUserModel model; + QHash roles = model.roleNames(); + QCOMPARE(roles.take(Qt::DisplayRole), QByteArray("display")); + QCOMPARE(roles.take(Irc::UserRole), QByteArray("user")); + QCOMPARE(roles.take(Irc::NameRole), QByteArray("name")); + QCOMPARE(roles.take(Irc::PrefixRole), QByteArray("prefix")); + QCOMPARE(roles.take(Irc::ModeRole), QByteArray("mode")); + QCOMPARE(roles.take(Irc::TitleRole), QByteArray("title")); + QVERIFY(roles.isEmpty()); +} + +void tst_IrcUserModel::testAIM() +{ + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QCOMPARE(bufferModel.count(), 0); + waitForWritten(":communi!communi@hidd.en JOIN :#channel"); + QCOMPARE(bufferModel.count(), 1); + + IrcUserModel userModel(bufferModel.get(0)); + waitForWritten(":irc.ser.ver 353 communi = #channel :a @b +c"); + waitForWritten(":irc.ser.ver 366 communi #channel :End of /NAMES list."); + QCOMPARE(userModel.count(), 3); + + IrcUser* a = userModel.find("a"); + IrcUser* b = userModel.find("b"); + IrcUser* c = userModel.find("c"); + IrcUser* o = 0; + + QVERIFY(a); + QVERIFY(b); + QVERIFY(c); + + QAbstractItemModel* aim = &userModel; + QModelIndex ai = aim->index(0, 0); + QModelIndex bi = aim->index(1, 0); + QModelIndex ci = aim->index(2, 0); + QModelIndex oi = aim->index(100, 100); + + QVERIFY(ai.isValid()); + QVERIFY(bi.isValid()); + QVERIFY(ci.isValid()); + QVERIFY(!oi.isValid()); + + QCOMPARE(aim->rowCount(QModelIndex()), 3); + QCOMPARE(aim->rowCount(ai), 0); + + QCOMPARE(aim->columnCount(QModelIndex()), 1); + QCOMPARE(aim->columnCount(ai), 0); + + QCOMPARE(userModel.index(a), ai); + QCOMPARE(userModel.index(b), bi); + QCOMPARE(userModel.index(c), ci); + QVERIFY(!userModel.index(o).isValid()); + + QCOMPARE(userModel.user(ai), a); + QCOMPARE(userModel.user(bi), b); + QCOMPARE(userModel.user(ci), c); + QVERIFY(!userModel.user(oi)); + + userModel.setDisplayRole(Irc::TitleRole); + QCOMPARE(aim->data(ai, Qt::DisplayRole).toString(), a->title()); + QCOMPARE(aim->data(bi, Qt::DisplayRole).toString(), b->title()); + QCOMPARE(aim->data(ci, Qt::DisplayRole).toString(), c->title()); + QVERIFY(aim->data(oi, Qt::DisplayRole).toString().isEmpty()); + + userModel.setDisplayRole(Irc::UserRole); + QCOMPARE(aim->data(ai, Qt::DisplayRole).value(), a); + QCOMPARE(aim->data(bi, Qt::DisplayRole).value(), b); + QCOMPARE(aim->data(ci, Qt::DisplayRole).value(), c); + QVERIFY(!aim->data(oi, Qt::DisplayRole).value()); + + QCOMPARE(aim->data(ai, Irc::UserRole).value(), a); + QCOMPARE(aim->data(bi, Irc::UserRole).value(), b); + QCOMPARE(aim->data(ci, Irc::UserRole).value(), c); + QVERIFY(!aim->data(oi, Irc::UserRole).value()); + + QCOMPARE(aim->data(ai, Irc::TitleRole).toString(), a->title()); + QCOMPARE(aim->data(bi, Irc::TitleRole).toString(), b->title()); + QCOMPARE(aim->data(ci, Irc::TitleRole).toString(), c->title()); + QVERIFY(aim->data(oi, Irc::TitleRole).toString().isEmpty()); + + QCOMPARE(aim->data(ai, Irc::NameRole).toString(), a->name()); + QCOMPARE(aim->data(bi, Irc::NameRole).toString(), b->name()); + QCOMPARE(aim->data(ci, Irc::NameRole).toString(), c->name()); + QVERIFY(aim->data(oi, Irc::NameRole).toString().isEmpty()); + + QVERIFY(aim->data(ai, Irc::PrefixRole).toString().isEmpty()); + QCOMPARE(aim->data(bi, Irc::PrefixRole).toString(), QString("@")); + QCOMPARE(aim->data(ci, Irc::PrefixRole).toString(), QString("+")); + QVERIFY(aim->data(oi, Irc::PrefixRole).toString().isEmpty()); + + QVERIFY(aim->data(ai, Irc::ModeRole).toString().isEmpty()); + QCOMPARE(aim->data(bi, Irc::ModeRole).toString(), QString("o")); + QCOMPARE(aim->data(ci, Irc::ModeRole).toString(), QString("v")); + QVERIFY(aim->data(oi, Irc::ModeRole).toString().isEmpty()); +} + +void tst_IrcUserModel::testUser() +{ + IrcUserModel userModel; + + // ### setup #communi (5): communi @ChanServ +qtassistant Guest1234 +qout + IrcBufferModel bufferModel; + bufferModel.setConnection(connection); + + connection->open(); + QVERIFY(waitForOpened()); + + QVERIFY(waitForWritten(tst_IrcData::welcome())); + QVERIFY(waitForWritten(":communi!~communi@hidd.en JOIN :#communi")); + QVERIFY(waitForWritten(":irc.ifi.uio.no 353 communi = #communi :communi @ChanServ +qtassistant Guest1234 +qout")); + QVERIFY(waitForWritten(":irc.ifi.uio.no 366 communi #communi :End of NAMES list.")); + QCOMPARE(bufferModel.count(), 1); + IrcChannel* channel = bufferModel.get(0)->toChannel(); + QVERIFY(channel); + QCOMPARE(channel->title(), QString("#communi")); + + // ### ready to go! + userModel.setChannel(channel); + QCOMPARE(userModel.count(), 5); + + QPointer communi = userModel.get(0); + QVERIFY(communi); + QCOMPARE(communi->name(), QString("communi")); + QVERIFY(!communi->isAway()); + QVERIFY(!communi->isServOp()); + + QPointer ChanServ = userModel.get(1); + QVERIFY(ChanServ); + QCOMPARE(ChanServ->name(), QString("ChanServ")); + QVERIFY(!ChanServ->isAway()); + QVERIFY(!ChanServ->isServOp()); + + QPointer qtassistant = userModel.get(2); + QVERIFY(qtassistant); + QCOMPARE(qtassistant->name(), QString("qtassistant")); + QVERIFY(!qtassistant->isAway()); + QVERIFY(!qtassistant->isServOp()); + + QPointer Guest1234 = userModel.get(3); + QVERIFY(Guest1234); + QCOMPARE(Guest1234->name(), QString("Guest1234")); + QVERIFY(!Guest1234->isAway()); + QVERIFY(!Guest1234->isServOp()); + + QPointer qout = userModel.get(4); + QVERIFY(qout); + QCOMPARE(qout->name(), QString("qout")); + QVERIFY(!qout->isAway()); + QVERIFY(!qout->isServOp()); + + QSignalSpy communiAwaySpy(communi.data(), SIGNAL(awayChanged(bool))); + QSignalSpy ChanServAwaySpy(ChanServ.data(), SIGNAL(awayChanged(bool))); + QSignalSpy qtassistantAwaySpy(qtassistant.data(), SIGNAL(awayChanged(bool))); + QSignalSpy Guest1234AwaySpy(Guest1234.data(), SIGNAL(awayChanged(bool))); + QSignalSpy qoutAwaySpy(qout.data(), SIGNAL(awayChanged(bool))); + + QVERIFY(communiAwaySpy.isValid()); + QVERIFY(ChanServAwaySpy.isValid()); + QVERIFY(qtassistantAwaySpy.isValid()); + QVERIFY(Guest1234AwaySpy.isValid()); + QVERIFY(qoutAwaySpy.isValid()); + + QSignalSpy communiServOpSpy(communi.data(), SIGNAL(servOpChanged(bool))); + QSignalSpy ChanServServOpSpy(ChanServ.data(), SIGNAL(servOpChanged(bool))); + QSignalSpy qtassistantServOpSpy(qtassistant.data(), SIGNAL(servOpChanged(bool))); + QSignalSpy Guest1234ServOpSpy(Guest1234.data(), SIGNAL(servOpChanged(bool))); + QSignalSpy qoutServOpSpy(qout.data(), SIGNAL(servOpChanged(bool))); + + QVERIFY(communiServOpSpy.isValid()); + QVERIFY(ChanServServOpSpy.isValid()); + QVERIFY(qtassistantServOpSpy.isValid()); + QVERIFY(Guest1234ServOpSpy.isValid()); + QVERIFY(qoutServOpSpy.isValid()); + + // first round + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~communi hidd.en irc.ifi.uio.no communi H* :0 Communi")); + QVERIFY(!communi->isAway()); + QVERIFY(communi->isServOp()); + QCOMPARE(communiAwaySpy.count(), 0); + QCOMPARE(communiServOpSpy.count(), 1); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ChanServ services. irc.ifi.uio.no ChanServ H@ :0 ChanServ")); + QVERIFY(!ChanServ->isAway()); + QVERIFY(!ChanServ->isServOp()); + QCOMPARE(ChanServAwaySpy.count(), 0); + QCOMPARE(ChanServServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~qtassistant hidd.en irc.ifi.uio.no qtassistant G+ :0 Qt Assistant")); + QVERIFY(qtassistant->isAway()); + QVERIFY(!qtassistant->isServOp()); + QCOMPARE(qtassistantAwaySpy.count(), 1); + QCOMPARE(qtassistantServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~guest hidd.en irc.ifi.uio.no Guest1234 H :0 Just a guest...")); + QVERIFY(!Guest1234->isAway()); + QVERIFY(!Guest1234->isServOp()); + QCOMPARE(Guest1234AwaySpy.count(), 0); + QCOMPARE(Guest1234ServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~qout hidd.en irc.ifi.uio.no qout G+ :0")); + QVERIFY(qout->isAway()); + QVERIFY(!qout->isServOp()); + QCOMPARE(qoutAwaySpy.count(), 1); + QCOMPARE(qoutServOpSpy.count(), 0); + + // second round + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~communi hidd.en irc.ifi.uio.no communi G@ :0 Communi")); + QVERIFY(communi->isAway()); + QVERIFY(!communi->isServOp()); + QCOMPARE(communiAwaySpy.count(), 1); + QCOMPARE(communiServOpSpy.count(), 2); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ChanServ services. irc.ifi.uio.no ChanServ H@ :0 ChanServ")); + QVERIFY(!ChanServ->isAway()); + QVERIFY(!ChanServ->isServOp()); + QCOMPARE(ChanServAwaySpy.count(), 0); + QCOMPARE(ChanServServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~qtassistant hidd.en irc.ifi.uio.no qtassistant H+ :0 Qt Assistant")); + QVERIFY(!qtassistant->isAway()); + QVERIFY(!qtassistant->isServOp()); + QCOMPARE(qtassistantAwaySpy.count(), 2); + QCOMPARE(qtassistantServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~guest hidd.en irc.ifi.uio.no Guest1234 G :0 Just a guest...")); + QVERIFY(Guest1234->isAway()); + QVERIFY(!Guest1234->isServOp()); + QCOMPARE(Guest1234AwaySpy.count(), 1); + QCOMPARE(Guest1234ServOpSpy.count(), 0); + + QVERIFY(waitForWritten(":irc.ifi.uio.no 352 communi #communi ~qout hidd.en irc.ifi.uio.no qout G+ :0")); + QVERIFY(qout->isAway()); + QVERIFY(!qout->isServOp()); + QCOMPARE(qoutAwaySpy.count(), 1); + QCOMPARE(qoutServOpSpy.count(), 0); +} + +QTEST_MAIN(tst_IrcUserModel) + +#include "tst_ircusermodel.moc" diff --git a/src/libcommuni/tests/auto/shared/shared.pri b/src/libcommuni/tests/auto/shared/shared.pri new file mode 100644 index 0000000..1b7258b --- /dev/null +++ b/src/libcommuni/tests/auto/shared/shared.pri @@ -0,0 +1,16 @@ +###################################################################### +# Communi +###################################################################### + +DEPENDPATH += $$PWD +INCLUDEPATH += $$PWD + +HEADERS += $$PWD/tst_euirc.h +HEADERS += $$PWD/tst_freenode.h +HEADERS += $$PWD/tst_ircnet.h + +HEADERS += $$PWD/tst_ircdata.h +SOURCES += $$PWD/tst_ircdata.cpp + +HEADERS += $$PWD/tst_ircclientserver.h +SOURCES += $$PWD/tst_ircclientserver.cpp diff --git a/src/libcommuni/tests/auto/shared/tst_euirc.h b/src/libcommuni/tests/auto/shared/tst_euirc.h new file mode 100644 index 0000000..116e8a2 --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_euirc.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#ifndef TST_EUIRC_H +#define TST_EUIRC_H + +static const char* euirc_welcome = + ":irc.rbx.fr.euirc.net 001 communi :Welcome to the euIRCnet IRC Network communi!~communi@hidd.en\n" + ":irc.rbx.fr.euirc.net 002 communi :Your host is irc.rbx.fr.euirc.net, running version euIRCd 1.3.4-e544f33+debug\n" + ":irc.rbx.fr.euirc.net 003 communi :This server was created Mon Jul 08 2013 at 07:09:56 CEST\n" + ":irc.rbx.fr.euirc.net 004 communi irc.rbx.fr.euirc.net euIRCd 1.3.4-e544f33+debug oOiRwhsSaHANCrxjWqBZ1dtcpPUnTI vhoaqpsmtinrRQKVHOAYCNcSXUTxW5beIwklfLBuFM\n" + ":irc.rbx.fr.euirc.net 005 communi NETWORK=euIRCnet WATCH=128 SAFELIST PREFIX=(qaohv)*!@%+ CHANMODES=bewI,k,flBL,cimnprstxACHKNOQRiTSVWXY5 CHANTYPES=#&+ KICKLEN=307 KNOCK MAP MAXLIST=bewI:100 MODES=6 NICKLEN=30 SILENCE=5 TOPICLEN=307 AWAYLEN=307 WALLCHOPS CHANNELLEN=32 MAXCHANNELS=30 MAXTARGETS=20 INVEX=I EXCEPT=e :are available on this server\n" + ":irc.rbx.fr.euirc.net 005 communi STARTTLS :are available on this server\n" + ":irc.rbx.fr.euirc.net 251 communi :There are 14 users and 2768 invisible on 10 servers\n" + ":irc.rbx.fr.euirc.net 252 communi 24 :operator(s) online\n" + ":irc.rbx.fr.euirc.net 253 communi 1 :unknown connection(s)\n" + ":irc.rbx.fr.euirc.net 254 communi 1671 :channels formed\n" + ":irc.rbx.fr.euirc.net 255 communi :I have 1060 clients and 1 servers\n" + ":irc.rbx.fr.euirc.net 265 communi :Current Local Users: 1060 Max: 1221\n" + ":irc.rbx.fr.euirc.net 266 communi :Current Global Users: 2782 Max: 11082\n" + ":irc.rbx.fr.euirc.net 375 communi :- irc.rbx.fr.euirc.net Message of the Day -\n" + ":irc.rbx.fr.euirc.net 376 communi :End of /MOTD command\n"; + +static const char* euirc_join = + ":communi!~communi@hidd.en JOIN :#euirc\n" + ":irc.rbx.fr.euirc.net 332 communi #euirc :Welcome to euIRC || Problems? Join #opers || www.euirc.net || SSL and S/MIME authentication now available on all servers (port 6697) || euIRC meets facebook: www.facebook.com/euirc\n" + ":irc.rbx.fr.euirc.net 333 communi #euirc Renne 1370272649\n" + ":irc.rbx.fr.euirc.net 353 communi = #euirc :communi Guest774 burning_rabbit %aleksandr netsplit Jerry Brueggus charly6 HermiNe %brue Mercutio stephan48 NeinnHomer Luthandorius Technomagier |Baron| Laknu_ Polizist1 !alamar rhonabwy @Vampi Mayday @Road radic MorkiTorki PRoTaGoNiST Simik|ZzZZ @][flat][ statsbot7 !mensch holygoth firefly Kanibal Luchs xinator CR|Noah|Away MrWolf !specon CR|Dani %leni CR|Sven @Renne Revi Arovin pinGUUin Vampire666 gastgast_\n" + ":irc.rbx.fr.euirc.net 353 communi = #euirc :konqui Tina-chan_onAir picoFF @medice SLXViper !TC sb Kn0p3XX SlySing faZe Icedream Der_Orwischer Goggy g00fy Burle klaxa [Chaos|Krieger] Guest14697 Tehlak icefly Herr_Vorragend Ding Nothing4You Sven|Off Zarquod !jun|per scaba meister Hikaru-Shindo Alx Kinji-san Guest13553 !Chibisuke\n" + ":irc.rbx.fr.euirc.net 366 communi #euirc :End of /NAMES list.\n"; + +static const char* euirc_names = + "communi Guest774 burning_rabbit aleksandr netsplit Jerry Brueggus charly6 HermiNe brue Mercutio stephan48 NeinnHomer Luthandorius Technomagier |Baron| Laknu_ Polizist1 alamar rhonabwy Vampi Mayday Road radic MorkiTorki PRoTaGoNiST Simik|ZzZZ ][flat][ statsbot7 mensch holygoth firefly Kanibal Luchs xinator CR|Noah|Away MrWolf specon CR|Dani leni CR|Sven Renne Revi Arovin pinGUUin Vampire666 gastgast_ " + "konqui Tina-chan_onAir picoFF medice SLXViper TC sb Kn0p3XX SlySing faZe Icedream Der_Orwischer Goggy g00fy Burle klaxa [Chaos|Krieger] Guest14697 Tehlak icefly Herr_Vorragend Ding Nothing4You Sven|Off Zarquod jun|per scaba meister Hikaru-Shindo Alx Kinji-san Guest13553 Chibisuke"; + +static const char* euirc_admins = "alamar mensch specon TC jun|per Chibisuke"; +static const char* euirc_ops = "Vampi Road ][flat][ Renne medice"; +static const char* euirc_halfops = "aleksandr brue leni"; +static const char* euirc_voices = ""; + +#endif // TST_EUIRC_H diff --git a/src/libcommuni/tests/auto/shared/tst_freenode.h b/src/libcommuni/tests/auto/shared/tst_freenode.h new file mode 100644 index 0000000..345abeb --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_freenode.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#ifndef TST_FREENODE_H +#define TST_FREENODE_H + +static const char* freenode_welcome = + ":moorcock.freenode.net NOTICE * :*** Looking up your hostname...\r\n" + ":moorcock.freenode.net NOTICE * :*** Checking Ident\r\n" + ":moorcock.freenode.net NOTICE * :*** Found your hostname\r\n" + ":moorcock.freenode.net NOTICE * :*** No Ident response\r\n" + ":moorcock.freenode.net 001 communi :Welcome to the freenode Internet Relay Chat Network communi\r\n" + ":moorcock.freenode.net 002 communi :Your host is moorcock.freenode.net[50.22.136.18/6667], running version ircd-seven-1.1.3\r\n" + ":moorcock.freenode.net 003 communi :This server was created Mon Dec 31 2012 at 15:37:06 CST\r\n" + ":moorcock.freenode.net 004 communi moorcock.freenode.net ircd-seven-1.1.3 DOQRSZaghilopswz CFILMPQSbcefgijklmnopqrstvz bkloveqjfI\r\n" + ":moorcock.freenode.net 005 communi CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server\r\n" + ":moorcock.freenode.net 005 communi CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server\r\n" + ":moorcock.freenode.net 005 communi EXTBAN=$,arxz WHOX CLIENTVER=3.0 SAFELIST ELIST=CTU :are supported by this server\r\n" + ":moorcock.freenode.net 251 communi :There are 231 users and 88216 invisible on 29 servers\r\n" + ":moorcock.freenode.net 252 communi 36 :IRC Operators online\r\n" + ":moorcock.freenode.net 253 communi 12 :unknown connection(s)\r\n" + ":moorcock.freenode.net 254 communi 49792 :channels formed\r\n" + ":moorcock.freenode.net 255 communi :I have 4723 clients and 1 servers\r\n" + ":moorcock.freenode.net 265 communi 4723 7446 :Current local users 4723, max 7446\r\n" + ":moorcock.freenode.net 266 communi 88447 92550 :Current global users 88447, max 92550\r\n" + ":moorcock.freenode.net 250 communi :Highest connection count: 7447 (7446 clients) (1286042 connections received)\r\n" + ":moorcock.freenode.net 375 communi :- moorcock.freenode.net Message of the Day -\r\n" + ":moorcock.freenode.net 372 communi :- Welcome to moorcock.freenode.net in ...\r\n" + ":moorcock.freenode.net 376 communi :End of /MOTD command.\r\n"; + +static const char* freenode_join = + ":communi!~communi@hidd.en JOIN #freenode\r\n" + ":moorcock.freenode.net 332 communi #freenode :Welcome to #freenode | Staff are voiced; some may also be on /stats p -- feel free to /msg us at any time | FAQ: http://freenode.net/faq.shtml | Unwelcome queries? Use /mode your_nick +R to block them. | Channel guidelines: http://freenode.net/poundfreenode.shtml | Blog: http://blog.freenode.net | Please don't comment on spam/trolls.\r\n" + ":moorcock.freenode.net 333 communi #freenode erry 1379357591\r\n" + ":moorcock.freenode.net 353 communi = #freenode :communi straterra absk007 pefn xlys Gromit TooCool Sambler gat0rs KarneAsada danis_963 Kiryx chrismeller deefloo black_male sxlnxdx bjork Kinny phobos_anomaly T13|sleeps JuxTApose Kolega2357 rorx techhelper1 hermatize Azimi iqualfragile fwilson skasturi mwallacesd mayday Guest76549 mcjohansen MangaKaDenza ARISTIDES ketas `- claptor ylluminate Cooky Brand3n cheater_1 Kirito digitaloktay Will| Iarfen abrotman smurfy Inaunt +mist Karol RougeR_\r\n" + ":moorcock.freenode.net 353 communi = #freenode :publickeating An_Ony_Moose michagogo Guest915` davidfg4 Ragnor s1lent_1 keee GingerGeek[Away] hibari derp S_T_A_N anonymuse asantoni road|runner LLckfan neoian2 aviancarrier nipples danieldaniel Pyrus Bry8Star shadowm_desktop furtardo rdymac TTSDA seaworthy Chiyo yscc Zombiebaron redpill f4cl3y Boohbah applebloom zorael kameloso^ Zetetic XAMPP wheels_up Cuppy-Cake mindlessjohnny Kymru mquin_ Rodja babilen kirin` David Affix jshyeung_ DarkAceZ karakedi\r\n" + ":moorcock.freenode.net 353 communi = #freenode :jraglin AdriDJ ToApolytoXaos whaletechno jlf Ricardo__ TmvC Sigma00 Casmo breck7 Oldiesmann Rappy naomi thiras moli FRCorey_ iderik glebihan cool_name Dwade09 UniOn eMBee Samual johnnymoo_logsta darknyan mlk dyay xBytez hammond M2Ys4U kobain monoprotic MiLK_ Noldorin njm Nomado Alina-malina abchirk_ Johannes13_ scorche dreamfighter Lars_G DCMT TomyLobo King_Hual No_One fling Mike_H CoreISP djdoody fdd pipitas Subo1977 jef redarrow marcoecc bin_sh TReK\r\n" + ":moorcock.freenode.net 353 communi = #freenode :[MortiKi] traveller__ Catie DarkG HisaoNakai scounder alone Corycia rudyismydog ToBeFree mcalabrese micadeyeye_ Sembei candlejackson cobra-the-joker ElectricDuck fuzeman swoolley ali_h dungodung oleo brain8675 Jordach rdy4watever KillYourTV coffeee levine m4v dvu ty _nova jgeboski Olipro CheckDavid impulse150 Shadow` jarr0dsz an3k Sove daemon Sary t0rben monkeyjuice Blas alexa the_TORmentor Transfusion kensington Spaceghost wolfmitchell lubmil synick\r\n" + ":moorcock.freenode.net 353 communi = #freenode :bitnumus krassomat zerox kel39 basiclaser tristero blaxnake themill meznak chinkung DJJeff RBecker XDS2010_ iamblue_cloud excilan Ristovski +JamesTait DrJ pfffx d9b4bef9 Corvus` s0ckpuppet Guest73279 Fritz7 JBreit zinx KhashayaR p3lim_ krisha quackgyver salkaman j4jackj Guest86053 nmmm wiretapped lunchdump goose sam Zarthus jje sl3dge Vutral sins- weie_ +Myrtti _raymond_ KindOne youlysses Mizael jeffz` meet_praveen STalKer-X osxdude surfdue torako\r\n" + ":moorcock.freenode.net 353 communi = #freenode :niloc132_ connor_goodwolf \\mSg vemacs iViLe slobber zendeavor drbean Tonitrus Nightmare ssbr GorillaPatch TingPing +Pricey james41382 Chenguang Jyothis RansomTime zz_Enviious TakinOver chrisss404 Brando753 mduca SlashLife_ Fuchs DW-Drew Firzen__ Suprano duke johest_ infinem Birdman3131 tmtowtdi Guest61594 BearPerson GiGaHuRtZ Hausas sdamashek salamanderrake jwbirdsong themadhatter mahomet smeggysmeg +kloeri_ kameloso Simonn ryukafalz tigrmesh Borg\r\n" + ":moorcock.freenode.net 353 communi = #freenode :Kingdom RougeR Venusaur resistivecorpse rush2end destiny rylinaux gskellig Wonkaewt philip quelx hside tann bolt btcvixen joako pr0ggie Xiti` arpita_ Hewn Argus Shippo +Tabmow FrankZZ Olanzapin zhezhe swiatos Argure Cathy JKL1234- Elfix Suicide cali urkl laissez-f sig-wall Guest76477 Rix jok- Guest41925 Thehelpfulone Nimrod oscailt stalled anexus _val_ Luke-Jr Konomi German__ acanete knuth Wildblue` juser Reshesnik Saiban corelax brr JoeK DarkSkyes\r\n" + ":moorcock.freenode.net 353 communi = #freenode :BullShark Zhaofeng_Li vidplace7 aji APLU RiverRat jerome Bateau raSter^ chipster Vito PigFlu Sprocks evaldoxie Atlas petan javalover MobiusL yerodin Barras2 Barras Humbedooh Niichan SlicerDicer slax0r Brodeles Aurora tandoori Davey Culator|Away gtmanfred kPa ex0a contempt Xack ecks prawnsalad wirehack7 nyuszika7h around Kelsie CaHogan mrpeenut24 Mozart IceCraft LifeIspain andrex sloof thismat troybattey notori0us UbuPhillup lasers BlastHardcheese muskeg\r\n" + ":moorcock.freenode.net 353 communi = #freenode :archigos +jayne XJR-9 realazthat Geert ahf nim edk spb @ChanServ Azure +nhandler a3li edggeek zol Bigcheese stylus DrBash ingo ningrat zu +tomaw felipe QueenOfFrance dxrt Y_Ichiro sysdef Ju576 rwg [NOT|HERE] sili Snowolf Shnaw tapout Joori GriGore665 LoganCloud Osaka funtapaz MidnighToker codeM0nK3Y Zen kinlo +Corey raj c0ded Remco Vikrant_ xander chadi |L| Shockk nickg ajpiano guntbert funkyHat +erry Mkaysi meingtsla seaLne EvilBlueShark pdelvo Strog\r\n" + ":moorcock.freenode.net 353 communi = #freenode :geb Vlad Deathspawn mdan Zidonuke jjs999jjs Bry8Star4 inthecompanyof Motzfeldt jlouis mooky avelldiroll tonsofpcs d2r Loki JPT Jamesofur +kloeri Paradox924X Zx3 cruxeternus sdx23 adaptr PwnSauce mattb J21 likewhoa scorche|sh hellome Geek_Juice xorpp Sonar_Guy luckman212 danar psybear eir StarRain sparticus stux|RC-only go|dfish teneightypea BaW d10n riddle Tm_T dive EvilJStoker glowsticks kode54 stwalkerster pocoyo shiftplusone bburhans trucMuche\r\n" + ":moorcock.freenode.net 353 communi = #freenode :moonlight +yano kevank jmfcool BranchPredictor pppingme Namikaze EvilOne FZTMm Sakaki Lord_Aizen demosdemon JasonDC duracrisis IHateHavingToReg +D[_] AlexJFox Th0masR0ss back Exio4 kunwon1 kc8qvp jeblair Jeruvy Kadet EmLeX aways Kester Spr0cket Thorne csssuf iotku nb solution Zanzibar em mwheeler x56 ChauffeR_ phrozen77 ivan`` The_Cop Monkeh ishanyx Whopper ghz JStoker brabo_ Triskelios sosby PoohBear Clete2 ErrantEgo SebastianFlyte JT jose rubick\r\n" + ":moorcock.freenode.net 353 communi = #freenode :RDash[AW] wwraith Hazel|artemis mrgaryniger tabeaux crazedpsyc +denny mh0 TheDrums Nothing4You_ Fieldy akawaka thumbs +Dave2 aghos_ Carly-_ Necrosan K1rk ClaudiaU_ HeavyMetal Zenum KOD3N cooldude mshaw milky sepeck Nineain nxp ktr TheLordOfTime dmlloyd sunitknandi arikb pumba Webu `DiM danmackay zomGreg tomboy_ callumacrae Devels rsrx zz_dbRenaud trout Kye Romance _ruben sfan5 brabo lassefaxoe Arieh John13 +ldunn OldSoul|4SiOS501 evilmquin xrated Ishaq\r\n" + ":moorcock.freenode.net 353 communi = #freenode :phreak turboroot ra roxell topyli jeremias doily Nazca Aehmlo_away nutron +christel +niko DLange drdanick AndrewBarber mediko psk1 TheJH skrip_kid +jbroome +njan RainbowDashh +Plazma vedalken254 codethought md_5 michagogo|cloud brad lolcat +LoRez MissionCritical honzik666 variousnefarious AlanBell tdfischer EricK|AFK AsadH apollo13 Wug[Hyperspace] nullrouted|cloud PeerLesS DarthGandalf cbdev shroud badunkadunk Happzz fortytwo netchip Mike3620 newton\r\n" + ":moorcock.freenode.net 353 communi = #freenode :Detch Gnumarcoo Brownout Junaos ThalinVien evilErrantEgo Bladerunner +JonathanD Beothoric FloTiX Alenah Raccoon ow GLolol c45y coinspelunk mysteerimasa real_alien tburg SPF|Cloud Cloudiumn like2helpU iMast777 geoffw8__ troyt Hypnotoad nkuttler Sjsws1078_ apoplexy3 trawl AntiSpamMeta ShadowNinja Kernel|Panic vinylGhost GaelanAintAround dlu corentin shark KnownUnown pentiumone133 AimHere Mad7Scientist SaMOOrai Fabianius alamar morphium espiral Someguy123\r\n" + ":moorcock.freenode.net 353 communi = #freenode :LIP DURgod tehKitten an0nmat1r FuriousRage nanotube jrgifford Mez +gry n4x TDJACR phuzion ohm BradND TheUni OzBorne RumpledElf Internet13 Muzer lostlabyrinth SeySayux midnightmagic drathir Sling firebird +jtrucks Red_M Stary2001 localhost jefferai mosh sweet_kid +RichiH Nothing4You hvxgr FastLizard4 bren2010 Slasher VunKruz sohum MogDog DJones fooly Arokh swords anaconda rcombs Wiretap jeffmjack petteyg TW1920 grawity JakeOrrall mac-mini _Cr4zi3_VM\r\n" + ":moorcock.freenode.net 353 communi = #freenode :Djole ShapeShifter499 AccessDenied jlcl Jguy sucheta XgF avermedia_ Pyker evil alpha Affliction Spitfire Fohlen rtbt humvee ka6sox benhunter09 mavensk asherkin +Elwell amithkk SolarAquarion chalcedony amarshall mrtux GarethAdams gary_chiang SilentPenguin ebuch_ +jbroome_ TW1920__ LaserShark msimkins Playb3yond music2myear maksbotan tenobi noko eighty4 bitpushr bucketm0use Amrykid phantomcircuit WorldEmperor Reisen pjschmitt armansito piney Yajirobe\r\n" + ":moorcock.freenode.net 353 communi = #freenode :neuro_sys JordanJ2 z3uS kline Clinteger Taylor albel727 Kharec Rarity Tzunamii VictorRedtail|Sa Peng KWC10 Axew iPod Jasper_Deng_away RyanKnack unreal Haseo aegis mst SecretAgent wapiflapi ghoti _spk_ jeremyb LjL +marienz _TMM_ Archer +gheraint cebor Chris_G Schoentoon jsec Bradford|Nosta addshore cyphase jmbsvicetto liori Plasmastar Skunky chaoscon heinrich5991 nealph catsup SierraAR davidhadas levarnu ping- daurnimator Cr0iX ksx4system Lars_G_ Maple__\r\n" + ":moorcock.freenode.net 353 communi = #freenode :PcJamesy rej froggyman LanceBNC Vorpal RojoD asakura jaybe Kyle IsoAnon neal__ G ski ibenox Adran Shirik WaffleZ MRX Damage-X Guest90323 jericon irc_adama Nietzschale Mack d1b balrog ikonia GTAXL Michail1 CoJaBo SkyDreamer suborbital Stryyker farn Matrixiumn Fira benonsoftware kaictl jdiez spectra FriendlyFascist Cyclone Koma dwfreed Phoebus jamesd MichaelC|Mobile PennStater SwedFTP +spaceinvader jumperboy Zic Graet ake gbyers[Away] MJ94 keeleysam Dwarf\r\n" + ":moorcock.freenode.net 353 communi = #freenode :NiTeMaRe arkeet Jake_D alvinek_ debris` Guest13246 infojunky ChrisAM Novacha ImTheBitch capri MartynKeigher BlackoutIsHere WannabeZNC EViLSLuT DrRen KamusHadenes deadpool graphitemaster xy andy_ Cydrobolt Metaleer Oprah Hello71 dirtydawg [Derek] basic` wei2912 nesthib poutine Angelo Simba WormDrink robink zymurgy Guest89644 SirCmpwn enchilado dominikh vivekrai Utility Jason bazhang paddymahoney pinPoint brainproxy TheEpTic Revi N7 Lyude edibsk mb06cs\r\n" + ":moorcock.freenode.net 353 communi = #freenode :bray90820 IdleOne Console kPa_ shadowm winocm spot digikwondo blishchrot MichaelC swagemon Whiskey win2012 VideoDudeMike HavokOC FailPowah ix007 phenom JZTech101 ohama eric1212 Timbo zz_dlu joey Wooble Willis pseubodot lbft elky BlueShark haxxed JamesOff ndngvr` overrider lahwran plasticboy idoru DXtremz Adonis SeanieB Gizmokid2005 Aerox3 Disori ludkiller dhoss_ c xid b_jonas lurst TheLonelyGod Nietzsche MillHouse Guest19968 AlexP Stoo psycho_oreos G1eb\r\n" + ":moorcock.freenode.net 353 communi = #freenode :Obfuscate ggherdov dStruct auscompgeek bdfoster tharkun aperson GeordieNorman mfamos irv +tt argv Psi-Jack cups Cprossu TheBadShepperd Magiobiwan mkb Steakanbake three18ti lysobit raztoki Chex Sellyme caf Guest76346 Louis Lexi sa`tan truexfan81 nitrix CodesInChaos Deus N3LRX Tsunamifox tgs3 multiply JakeSaysSays epochwolf totte +t cam daemoneye stump Sargun ekeih tauntaun Milenko vvv upgrayeddd mrrothhcloud___ _anonymous +issyl0 smokex Pici\r\n" + ":moorcock.freenode.net 366 communi #freenode :End of /NAMES list.\r\n" + ":ChanServ!ChanServ@services. NOTICE communi :[#freenode] Welcome to #freenode. All network staff are voiced in here, but may not always be around - type /stats p to get a list of on call staff. Others may be hiding so do feel free to ping and /msg us at will! Also please read the channel guidelines at http://freenode.net/poundfreenode.shtml - thanks.\r\n" + ":services. 328 communi #freenode :http://freenode.net/\r\n"; + +static const char* freenode_names = + "communi straterra absk007 pefn xlys Gromit TooCool Sambler gat0rs KarneAsada danis_963 Kiryx chrismeller deefloo black_male sxlnxdx bjork Kinny phobos_anomaly T13|sleeps JuxTApose Kolega2357 rorx techhelper1 hermatize Azimi iqualfragile fwilson skasturi mwallacesd mayday Guest76549 mcjohansen MangaKaDenza ARISTIDES ketas `- claptor ylluminate Cooky Brand3n cheater_1 Kirito digitaloktay Will| Iarfen abrotman smurfy Inaunt mist Karol RougeR_ " + "publickeating An_Ony_Moose michagogo Guest915` davidfg4 Ragnor s1lent_1 keee GingerGeek[Away] hibari derp S_T_A_N anonymuse asantoni road|runner LLckfan neoian2 aviancarrier nipples danieldaniel Pyrus Bry8Star shadowm_desktop furtardo rdymac TTSDA seaworthy Chiyo yscc Zombiebaron redpill f4cl3y Boohbah applebloom zorael kameloso^ Zetetic XAMPP wheels_up Cuppy-Cake mindlessjohnny Kymru mquin_ Rodja babilen kirin` David Affix jshyeung_ DarkAceZ karakedi " + "jraglin AdriDJ ToApolytoXaos whaletechno jlf Ricardo__ TmvC Sigma00 Casmo breck7 Oldiesmann Rappy naomi thiras moli FRCorey_ iderik glebihan cool_name Dwade09 UniOn eMBee Samual johnnymoo_logsta darknyan mlk dyay xBytez hammond M2Ys4U kobain monoprotic MiLK_ Noldorin njm Nomado Alina-malina abchirk_ Johannes13_ scorche dreamfighter Lars_G DCMT TomyLobo King_Hual No_One fling Mike_H CoreISP djdoody fdd pipitas Subo1977 jef redarrow marcoecc bin_sh TReK " + "[MortiKi] traveller__ Catie DarkG HisaoNakai scounder alone Corycia rudyismydog ToBeFree mcalabrese micadeyeye_ Sembei candlejackson cobra-the-joker ElectricDuck fuzeman swoolley ali_h dungodung oleo brain8675 Jordach rdy4watever KillYourTV coffeee levine m4v dvu ty _nova jgeboski Olipro CheckDavid impulse150 Shadow` jarr0dsz an3k Sove daemon Sary t0rben monkeyjuice Blas alexa the_TORmentor Transfusion kensington Spaceghost wolfmitchell lubmil synick " + "bitnumus krassomat zerox kel39 basiclaser tristero blaxnake themill meznak chinkung DJJeff RBecker XDS2010_ iamblue_cloud excilan Ristovski JamesTait DrJ pfffx d9b4bef9 Corvus` s0ckpuppet Guest73279 Fritz7 JBreit zinx KhashayaR p3lim_ krisha quackgyver salkaman j4jackj Guest86053 nmmm wiretapped lunchdump goose sam Zarthus jje sl3dge Vutral sins- weie_ Myrtti _raymond_ KindOne youlysses Mizael jeffz` meet_praveen STalKer-X osxdude surfdue torako " + "niloc132_ connor_goodwolf \\mSg vemacs iViLe slobber zendeavor drbean Tonitrus Nightmare ssbr GorillaPatch TingPing Pricey james41382 Chenguang Jyothis RansomTime zz_Enviious TakinOver chrisss404 Brando753 mduca SlashLife_ Fuchs DW-Drew Firzen__ Suprano duke johest_ infinem Birdman3131 tmtowtdi Guest61594 BearPerson GiGaHuRtZ Hausas sdamashek salamanderrake jwbirdsong themadhatter mahomet smeggysmeg kloeri_ kameloso Simonn ryukafalz tigrmesh Borg " + "Kingdom RougeR Venusaur resistivecorpse rush2end destiny rylinaux gskellig Wonkaewt philip quelx hside tann bolt btcvixen joako pr0ggie Xiti` arpita_ Hewn Argus Shippo Tabmow FrankZZ Olanzapin zhezhe swiatos Argure Cathy JKL1234- Elfix Suicide cali urkl laissez-f sig-wall Guest76477 Rix jok- Guest41925 Thehelpfulone Nimrod oscailt stalled anexus _val_ Luke-Jr Konomi German__ acanete knuth Wildblue` juser Reshesnik Saiban corelax brr JoeK DarkSkyes " + "BullShark Zhaofeng_Li vidplace7 aji APLU RiverRat jerome Bateau raSter^ chipster Vito PigFlu Sprocks evaldoxie Atlas petan javalover MobiusL yerodin Barras2 Barras Humbedooh Niichan SlicerDicer slax0r Brodeles Aurora tandoori Davey Culator|Away gtmanfred kPa ex0a contempt Xack ecks prawnsalad wirehack7 nyuszika7h around Kelsie CaHogan mrpeenut24 Mozart IceCraft LifeIspain andrex sloof thismat troybattey notori0us UbuPhillup lasers BlastHardcheese muskeg " + "archigos jayne XJR-9 realazthat Geert ahf nim edk spb ChanServ Azure nhandler a3li edggeek zol Bigcheese stylus DrBash ingo ningrat zu tomaw felipe QueenOfFrance dxrt Y_Ichiro sysdef Ju576 rwg [NOT|HERE] sili Snowolf Shnaw tapout Joori GriGore665 LoganCloud Osaka funtapaz MidnighToker codeM0nK3Y Zen kinlo Corey raj c0ded Remco Vikrant_ xander chadi |L| Shockk nickg ajpiano guntbert funkyHat erry Mkaysi meingtsla seaLne EvilBlueShark pdelvo Strog " + "geb Vlad Deathspawn mdan Zidonuke jjs999jjs Bry8Star4 inthecompanyof Motzfeldt jlouis mooky avelldiroll tonsofpcs d2r Loki JPT Jamesofur kloeri Paradox924X Zx3 cruxeternus sdx23 adaptr PwnSauce mattb J21 likewhoa scorche|sh hellome Geek_Juice xorpp Sonar_Guy luckman212 danar psybear eir StarRain sparticus stux|RC-only go|dfish teneightypea BaW d10n riddle Tm_T dive EvilJStoker glowsticks kode54 stwalkerster pocoyo shiftplusone bburhans trucMuche " + "moonlight yano kevank jmfcool BranchPredictor pppingme Namikaze EvilOne FZTMm Sakaki Lord_Aizen demosdemon JasonDC duracrisis IHateHavingToReg D[_] AlexJFox Th0masR0ss back Exio4 kunwon1 kc8qvp jeblair Jeruvy Kadet EmLeX aways Kester Spr0cket Thorne csssuf iotku nb solution Zanzibar em mwheeler x56 ChauffeR_ phrozen77 ivan`` The_Cop Monkeh ishanyx Whopper ghz JStoker brabo_ Triskelios sosby PoohBear Clete2 ErrantEgo SebastianFlyte JT jose rubick " + "RDash[AW] wwraith Hazel|artemis mrgaryniger tabeaux crazedpsyc denny mh0 TheDrums Nothing4You_ Fieldy akawaka thumbs Dave2 aghos_ Carly-_ Necrosan K1rk ClaudiaU_ HeavyMetal Zenum KOD3N cooldude mshaw milky sepeck Nineain nxp ktr TheLordOfTime dmlloyd sunitknandi arikb pumba Webu `DiM danmackay zomGreg tomboy_ callumacrae Devels rsrx zz_dbRenaud trout Kye Romance _ruben sfan5 brabo lassefaxoe Arieh John13 ldunn OldSoul|4SiOS501 evilmquin xrated Ishaq " + "phreak turboroot ra roxell topyli jeremias doily Nazca Aehmlo_away nutron christel niko DLange drdanick AndrewBarber mediko psk1 TheJH skrip_kid jbroome njan RainbowDashh Plazma vedalken254 codethought md_5 michagogo|cloud brad lolcat LoRez MissionCritical honzik666 variousnefarious AlanBell tdfischer EricK|AFK AsadH apollo13 Wug[Hyperspace] nullrouted|cloud PeerLesS DarthGandalf cbdev shroud badunkadunk Happzz fortytwo netchip Mike3620 newton " + "Detch Gnumarcoo Brownout Junaos ThalinVien evilErrantEgo Bladerunner JonathanD Beothoric FloTiX Alenah Raccoon ow GLolol c45y coinspelunk mysteerimasa real_alien tburg SPF|Cloud Cloudiumn like2helpU iMast777 geoffw8__ troyt Hypnotoad nkuttler Sjsws1078_ apoplexy3 trawl AntiSpamMeta ShadowNinja Kernel|Panic vinylGhost GaelanAintAround dlu corentin shark KnownUnown pentiumone133 AimHere Mad7Scientist SaMOOrai Fabianius alamar morphium espiral Someguy123 " + "LIP DURgod tehKitten an0nmat1r FuriousRage nanotube jrgifford Mez gry n4x TDJACR phuzion ohm BradND TheUni OzBorne RumpledElf Internet13 Muzer lostlabyrinth SeySayux midnightmagic drathir Sling firebird jtrucks Red_M Stary2001 localhost jefferai mosh sweet_kid RichiH Nothing4You hvxgr FastLizard4 bren2010 Slasher VunKruz sohum MogDog DJones fooly Arokh swords anaconda rcombs Wiretap jeffmjack petteyg TW1920 grawity JakeOrrall mac-mini _Cr4zi3_VM " + "Djole ShapeShifter499 AccessDenied jlcl Jguy sucheta XgF avermedia_ Pyker evil alpha Affliction Spitfire Fohlen rtbt humvee ka6sox benhunter09 mavensk asherkin Elwell amithkk SolarAquarion chalcedony amarshall mrtux GarethAdams gary_chiang SilentPenguin ebuch_ jbroome_ TW1920__ LaserShark msimkins Playb3yond music2myear maksbotan tenobi noko eighty4 bitpushr bucketm0use Amrykid phantomcircuit WorldEmperor Reisen pjschmitt armansito piney Yajirobe " + "neuro_sys JordanJ2 z3uS kline Clinteger Taylor albel727 Kharec Rarity Tzunamii VictorRedtail|Sa Peng KWC10 Axew iPod Jasper_Deng_away RyanKnack unreal Haseo aegis mst SecretAgent wapiflapi ghoti _spk_ jeremyb LjL marienz _TMM_ Archer gheraint cebor Chris_G Schoentoon jsec Bradford|Nosta addshore cyphase jmbsvicetto liori Plasmastar Skunky chaoscon heinrich5991 nealph catsup SierraAR davidhadas levarnu ping- daurnimator Cr0iX ksx4system Lars_G_ Maple__ " + "PcJamesy rej froggyman LanceBNC Vorpal RojoD asakura jaybe Kyle IsoAnon neal__ G ski ibenox Adran Shirik WaffleZ MRX Damage-X Guest90323 jericon irc_adama Nietzschale Mack d1b balrog ikonia GTAXL Michail1 CoJaBo SkyDreamer suborbital Stryyker farn Matrixiumn Fira benonsoftware kaictl jdiez spectra FriendlyFascist Cyclone Koma dwfreed Phoebus jamesd MichaelC|Mobile PennStater SwedFTP spaceinvader jumperboy Zic Graet ake gbyers[Away] MJ94 keeleysam Dwarf " + "NiTeMaRe arkeet Jake_D alvinek_ debris` Guest13246 infojunky ChrisAM Novacha ImTheBitch capri MartynKeigher BlackoutIsHere WannabeZNC EViLSLuT DrRen KamusHadenes deadpool graphitemaster xy andy_ Cydrobolt Metaleer Oprah Hello71 dirtydawg [Derek] basic` wei2912 nesthib poutine Angelo Simba WormDrink robink zymurgy Guest89644 SirCmpwn enchilado dominikh vivekrai Utility Jason bazhang paddymahoney pinPoint brainproxy TheEpTic Revi N7 Lyude edibsk mb06cs " + "bray90820 IdleOne Console kPa_ shadowm winocm spot digikwondo blishchrot MichaelC swagemon Whiskey win2012 VideoDudeMike HavokOC FailPowah ix007 phenom JZTech101 ohama eric1212 Timbo zz_dlu joey Wooble Willis pseubodot lbft elky BlueShark haxxed JamesOff ndngvr` overrider lahwran plasticboy idoru DXtremz Adonis SeanieB Gizmokid2005 Aerox3 Disori ludkiller dhoss_ c xid b_jonas lurst TheLonelyGod Nietzsche MillHouse Guest19968 AlexP Stoo psycho_oreos G1eb " + "Obfuscate ggherdov dStruct auscompgeek bdfoster tharkun aperson GeordieNorman mfamos irv tt argv Psi-Jack cups Cprossu TheBadShepperd Magiobiwan mkb Steakanbake three18ti lysobit raztoki Chex Sellyme caf Guest76346 Louis Lexi sa`tan truexfan81 nitrix CodesInChaos Deus N3LRX Tsunamifox tgs3 multiply JakeSaysSays epochwolf totte t cam daemoneye stump Sargun ekeih tauntaun Milenko vvv upgrayeddd mrrothhcloud___ _anonymous issyl0 smokex Pici"; + +static const char* freenode_admins = ""; +static const char* freenode_ops = "ChanServ"; +static const char* freenode_halfops = ""; +static const char* freenode_voices = "mist JamesTait Myrtti Pricey kloeri_ Tabmow jayne nhandler tomaw Corey erry kloeri yano D[_] denny Dave2 ldunn christel niko jbroome njan Plazma LoRez JonathanD gry jtrucks RichiH Elwell jbroome_ marienz gheraint spaceinvader tt t issyl0"; + +#endif // TST_FREENODE_H diff --git a/src/libcommuni/tests/auto/shared/tst_ircclientserver.cpp b/src/libcommuni/tests/auto/shared/tst_ircclientserver.cpp new file mode 100644 index 0000000..2a76ead --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_ircclientserver.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "tst_ircclientserver.h" + +tst_IrcClientServer::tst_IrcClientServer() +{ + server = new QTcpServer(this); +} + +void tst_IrcClientServer::initTestCase() +{ + QVERIFY(server->listen()); +} + +void tst_IrcClientServer::cleanupTestCase() +{ + server->close(); +} + +void tst_IrcClientServer::init() +{ + connection = new IrcConnection(this); + connection->setUserName("user"); + connection->setNickName("nick"); + connection->setRealName("real"); + connection->setPassword("secret"); + connection->setHost("127.0.0.1"); + connection->setPort(server->serverPort()); +} + +void tst_IrcClientServer::cleanup() +{ + delete connection; +} + +bool tst_IrcClientServer::waitForOpened(int timeout) +{ + if (!server->waitForNewConnection(timeout)) + return false; + serverSocket = server->nextPendingConnection(); + clientSocket = connection->socket(); + return serverSocket && clientSocket && clientSocket->waitForConnected(1000); +} + +bool tst_IrcClientServer::waitForWritten(const QByteArray& data, int timeout) +{ + if (!data.isNull()) { + if (data.count('\n') > 1) { + bool success = true; + foreach (const QByteArray& line, data.split('\n')) + success &= waitForWritten(line + '\n', timeout); + return success; + } + if (data.endsWith('\r') || data.endsWith('\n')) + serverSocket->write(data); + else + serverSocket->write(data + "\r\n"); + } + return serverSocket->waitForBytesWritten(timeout) && clientSocket->waitForReadyRead(timeout); +} diff --git a/src/libcommuni/tests/auto/shared/tst_ircclientserver.h b/src/libcommuni/tests/auto/shared/tst_ircclientserver.h new file mode 100644 index 0000000..ae72f29 --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_ircclientserver.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#ifndef TST_IRCCLIENTSERVER_H +#define TST_IRCCLIENTSERVER_H + +#include + +#include +#include +#include +#include + +#if QT_VERSION >= 0x050000 +#define Q4SKIP(description) QSKIP(description) +#else +#define Q4SKIP(description) QSKIP(description, SkipAll) +#endif + +class tst_IrcClientServer : public QObject +{ + Q_OBJECT + +public: + tst_IrcClientServer(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void init(); + void cleanup(); + +protected: + bool waitForOpened(int timeout = 200); + bool waitForWritten(const QByteArray& data, int timeout = 1000); + + QPointer server; + QPointer serverSocket; + QPointer connection; + QPointer clientSocket; +}; + +#endif // TST_IRCCLIENTSERVER_H diff --git a/src/libcommuni/tests/auto/shared/tst_ircdata.cpp b/src/libcommuni/tests/auto/shared/tst_ircdata.cpp new file mode 100644 index 0000000..b3a11b2 --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_ircdata.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#include "tst_ircdata.h" +#include "tst_freenode.h" +#include "tst_ircnet.h" +#include "tst_euirc.h" + +QList tst_IrcData::keys() +{ + return QList() << "freenode" << "ircnet" << "euirc"; +} + +QByteArray tst_IrcData::welcome(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", freenode_welcome); + blobs.insert("ircnet", ircnet_welcome); + blobs.insert("euirc", euirc_welcome); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QByteArray tst_IrcData::join(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", freenode_join); + blobs.insert("ircnet", ircnet_join); + blobs.insert("euirc", euirc_join); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QStringList tst_IrcData::names(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", QString::fromUtf8(freenode_names).split(" ")); + blobs.insert("ircnet", QString::fromUtf8(ircnet_names).split(" ")); + blobs.insert("euirc", QString::fromUtf8(euirc_names).split(" ")); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QStringList tst_IrcData::admins(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", QString::fromUtf8(freenode_admins).split(" ")); + blobs.insert("ircnet", QString::fromUtf8(ircnet_admins).split(" ")); + blobs.insert("euirc", QString::fromUtf8(euirc_admins).split(" ")); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QStringList tst_IrcData::ops(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", QString::fromUtf8(freenode_ops).split(" ")); + blobs.insert("ircnet", QString::fromUtf8(ircnet_ops).split(" ")); + blobs.insert("euirc", QString::fromUtf8(euirc_ops).split(" ")); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QStringList tst_IrcData::halfops(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", QString::fromUtf8(freenode_halfops).split(" ")); + blobs.insert("ircnet", QString::fromUtf8(ircnet_halfops).split(" ")); + blobs.insert("euirc", QString::fromUtf8(euirc_halfops).split(" ")); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} + +QStringList tst_IrcData::voices(const QByteArray& key) +{ + static QHash blobs; + if (blobs.isEmpty()) { + blobs.insert("freenode", QString::fromUtf8(freenode_voices).split(" ")); + blobs.insert("ircnet", QString::fromUtf8(ircnet_voices).split(" ")); + blobs.insert("euirc", QString::fromUtf8(euirc_voices).split(" ")); + } + return blobs.value(key.isEmpty() ? keys().first() : key); +} diff --git a/src/libcommuni/tests/auto/shared/tst_ircdata.h b/src/libcommuni/tests/auto/shared/tst_ircdata.h new file mode 100644 index 0000000..c5126f8 --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_ircdata.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#ifndef TST_IRCDATA_H +#define TST_IRCDATA_H + +#include +#include +#include +#include +#include + +class tst_IrcData +{ +public: + static QList keys(); + static QByteArray welcome(const QByteArray& key = QByteArray()); + static QByteArray join(const QByteArray& key = QByteArray()); + static QStringList names(const QByteArray& key = QByteArray()); + static QStringList admins(const QByteArray& key = QByteArray()); + static QStringList ops(const QByteArray& key = QByteArray()); + static QStringList halfops(const QByteArray& key = QByteArray()); + static QStringList voices(const QByteArray& key = QByteArray()); +}; + +#endif // TST_IRCDATA_H diff --git a/src/libcommuni/tests/auto/shared/tst_ircnet.h b/src/libcommuni/tests/auto/shared/tst_ircnet.h new file mode 100644 index 0000000..e0fb7d4 --- /dev/null +++ b/src/libcommuni/tests/auto/shared/tst_ircnet.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008-2014 The Communi Project + * + * This test is free, and not covered by the BSD license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. + */ + +#ifndef TST_IRCNET_H +#define TST_IRCNET_H + +static const char* ircnet_welcome = + ":irc.ifi.uio.no 020 * :Please wait while we process your connection.\r\n" + ":irc.ifi.uio.no 001 communi :Welcome to the Internet Relay Network communi!~communi@hidd.en\r\n" + ":irc.ifi.uio.no 002 communi :Your host is irc.ifi.uio.no, running version 2.11.2p3\r\n" + ":irc.ifi.uio.no 003 communi :This server was created Wed Aug 8 2012 at 10:28:47 CEST\r\n" + ":irc.ifi.uio.no 004 communi irc.ifi.uio.no 2.11.2p3 aoOirw abeiIklmnoOpqrRstv\r\n" + ":irc.ifi.uio.no 005 communi RFC2812 PREFIX=(ov)@+ CHANTYPES=#&!+ MODES=3 CHANLIMIT=#&!+:21 NICKLEN=15 TOPICLEN=255 KICKLEN=255 MAXLIST=beIR:64 CHANNELLEN=50 IDCHAN=!:5 CHANMODES=beIR,k,l,imnpstaqr :are supported by this server\r\n" + ":irc.ifi.uio.no 005 communi PENALTY FNC EXCEPTS=e INVEX=I CASEMAPPING=ascii NETWORK=IRCNet :are supported by this server\r\n" + ":irc.ifi.uio.no 042 communi 578IAAESX :your unique ID\r\n" + ":irc.ifi.uio.no 251 communi :There are 55235 users and 5 services on 27 servers\r\n" + ":irc.ifi.uio.no 252 communi 95 :operators online\r\n" + ":irc.ifi.uio.no 254 communi 30892 :channels formed\r\n" + ":irc.ifi.uio.no 255 communi :I have 447 users, 0 services and 4 servers\r\n" + ":irc.ifi.uio.no 265 communi 447 456 :Current local users 447, max 456\r\n" + ":irc.ifi.uio.no 266 communi 55235 58824 :Current global users 55235, max 58824\r\n" + ":irc.ifi.uio.no 375 communi :- irc.ifi.uio.no Message of the Day -\r\n" + ":irc.ifi.uio.no 376 communi :End of MOTD command.\r\n"; + +static const char* ircnet_join = + ":communi!~communi@hidd.en JOIN :#uptimed\r\n" + ":irc.ifi.uio.no 332 communi #uptimed :UPTIME CONTEST - STARTS WITH 600 VOICES / The winner gets a 1 year SHELL\r\n" + ":irc.ifi.uio.no 333 communi #uptimed t0r-!t0r@hidd.en 1380194318\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :communi +_box +Ste` +`ViRuS` +sensej +ip +\\x00 +Dos +Plato +sonik +[daro] +056DABT1Q @Voicer +Elcid +NICK +ComeAsYouAre +nightmare +AboutAGirl +once +Arwen +vizion @artico +OnceW3reWarrior +NT2000 +Coolio +babka +dziadek +OnceWereWarrior +kaban +nabak +uytrew +705AAFHDM +705AAFHDO +705AAFHDN +ggefew +233EAGIRG +adsfds +[jp] +233DADVTX +233DADVTW +vaginakkk +szok +datanetek +deeee +italiano +knbb +em +robo +dupeczka +233DADWSZ +mofaya +fogiel +[nsa]\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+vagina +evil_ +vaginallo +why +evil` +inci +yhw +zazaza +ewe +bandoz +zeus +[animanera] +{artic} @Uptimed +sisiako +italianos +elite +polishpower +nsa` +`artic` +RedDevil +varna +s +rudy +draven +lupo +ijnnk +quest[2] +desapir +itsab +r0d +keep +An0nym0uz +_sparco +nsa- +KaPPa +devilkickers +wannie +PaulAnunda +TuOmaS- +Ainame +TeSsIer +MarkrIckeR +Markvillam +LasteS +JaMeS_ +CriStiaNo +IvanaCosta +brunodp +HackYou +Ducentesimo +Created +Ciwarshak\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+BroLy +BriatoRe +tasya +cpanel +liana +shoutcast +humantourch +myznc +kopisusu +ainah +IRC +knb +ipv4 +zguba +{ +rudi +idur +ls_212 +[goku] +xman +josip +mushroom +ajo +Patty +alien^ +ReMoNDiNi +marselo +NiTr0 +iOrOxxo +DartagnaN +TheCure +FurisO +MetroNotte +ToRSoLo +register +init-zero +Pilszcz +DjCaro +wamper +ToRQUaTo +Alison +Wenni^_^ +Hambi +MzMaNdY +Howie^^ +Chiwai +EkinCheng +Jenny^_^ @abuser` +die @Mgla +rcu +|jp| +|be| +egg +suka +ircoholik\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+|de| @ruciu +japanase +zncbot +latitanz +kafir +sparco +invisible +elk +jazz +esprit +strange +rex +grasshopper +miracle +outlaw @t0r- +veronica +artic| @[m] +ToRDo +ToRRoNe +MusSi +ToRBiDo +gozmit +ToReRo +ToRReNTe +Mediterraneo +Sugar +unregistered +bohjan +biskut +xdos +unix +cheap +android +birc +edit +Robocop +Neon +Temp +Apofis +Seth +Sokar +Iron +Control +Kiler +mrozek +widzewiak +klesk +Dj +Rcnet +mybsd +lis +[d] +resu` +ussus_ +ksychy +sp +kln\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+psk +Kulf0n +daro +darecki +pan_ban +Anonymouz +atos +MarRosso +CommenDa +miglia +Spike +Sc0rpion +Krotone +ViboValentia +Arcaverde +AlcaTRaz +Adriatico +MescaliNa +PiPo_ +RogeS +sm0k +kakashi +naintails +smuga +howkey +aven[gers] +[neo] +[dill] +Aptajm +marcin +founder +roger +feedback +M-k +Madmax +Piramida +Hator +Loginek +Lill +Polibuda +Zeus` +bouncer +msdos +gurl +kongsi +mamak +scid +mylinux +sock +nana +ibm +samba +k-pop +gyna +k-chat +mail\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+chat +yatie +ircap +Ho-Nam +mynet +rindunet +qip +eggies +db +fakap +loco +mircpro +mircbot +mynic +bladez +hackintosh +egghelp +kampung +cisco +girl +skepticals +nickname +Uncle-B +bohsia +mircx @Grypsio +kaktej +Asia +HelpAR +VaneSSaBeLL +AcHIni +DjuNaBarnEs +HydRA +WilHElm- +BrIanCHon +LiLi +Br0doWski +Apus +BoUdin0 +ERebpAR +RetIculum +TucANA +CAsIk +CANes +PuppIs +BeNaZech +BeRnaRDus +Lupus +IzrAileviC +UlAIn +AdaMI +Bartels +AGliNK +Helon +UlpAR\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+BemELmaNS +DelphINus +AbBati +FoRNAx +BenKvicH +Ulseth +PIctoR +BeJJini +BroOWn +Br00k +AffanNU +Achenbach +BelloTTo +AbrHHam +CeNtAuRus +Agutte +AlbrECht +AnGeLico +Ar13S +TAuRus +BeReNIces +AzARfAR +AquIlA +Br0uwEr +BreYtenbaCH +CAsImAR +CAssIopeIA +ColumbA +CRux +EuGen +GeoFFrY +HiPPolyter +HoRologIum +LAceRtA +LeoMINoR +NIsAIn +NIsseth +NoRmA +PaVl0viC +ScoRpIus +SeRpeNs +ShuRImAR +artic +TitoAguiAri +ZIRpAR +TuRfAR +VAnIkAIn +VolANs +NIspAR\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+CAsImAl +ThiErry +INdus +Cetus +PeTerFraNcio +GRus +MadDox +PIscIs +VulpeculA +CeCily +TRIANgulum +CApRIcoRNus +FraNtz +TuRIen +AdeMollo +BrIgnOni +AgReSti +AustRAle +BoTTinI +BouVIer +BrenTANA +BriNdiSi +CAelum +DoRAdo +ErNIeBarnEs +Helseth +JeNNiferBart +leBrocQUy +Lepus +LyNx +OctANs +OphIuchus +PeNeTriL +PIsces +PyxIs +roKkmAn +SAgIttA +TelescopIum +CRAteR +PeRseus +ShuRpAR +CAsseth +BeLLini +ChAmAeleoN +MIcRoscopIum +Ad0lphE +BoReAlIs +ARA_ +CARINA\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+AquARIus_ +BartoLomeo +ShuRon +t0r__ +YaAcovAgam +Betty- +HydRus +ANDRoMeD2 +Mercurio +HeRcules_ +ORIoN- +Br00ker +Cepheus +276XAAAPU +PegAsus_ +CAspAR +BoUchE +MoNoceRos +URsAMAjoR +CAsIl +AivaZZovskKy +ERIdANus +BoUdeWijNS +LyR4 +ERebseth +ShuRseth +AleChiNskY +LIbRA +Leo +AceRbi +AuRIgA +BeNNo +Bootes_ +BriSSaud +CIRcINus +DRAco +SAgIttAR2us +WaSHingt0n +JUliUs- +TuRIk +HansBellmEs +PAvo +SculptoR +AddNet +GemINI +ANtlIA +ShuRkAn +BoUcheR +Br0wn\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+URsAMINoR +VelA +CoRvus_ +BoWerANO +AustRINA +Agn0l +KaziMIerZ +PhoeNIx- +Scutum +SebAStieN +VIRgo_ +CANceR_ +CygNus_ +ZIRseth +t0r_ +ERebon +Equuleus +BouLAngeR +CAson +SextANs +JBelliNi +BourdiDIchoN +AzARAth +DiLDoSauRo +PumPinks +Callisto +Cosenza +Meschino +Portos +IoRobot +Eclipse +HighLander +T0XiC +Popoff +PaLLa +Indiano +MDma +Eastie +BleacH +PoSiX +Slash_ +InUtero +FormaGGino +riggiu +tirrenico +papera +MaXMerilio +MalandriNo +ToRTiGLia\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+ToRToRa +BeLGo +NetBeans +NeverMind +BlackSp1rit +Ionico +Anfetamina +t0r +ladyshrew +ToRoNTo +AsTRo` +ToRCeTTo +EnSi +ToRNaDo +ToRReTTa +MaGReBiNo +ToRBoSo +ToRSiDa +ToRCia +ToRCiCoLLo +Wokie +RuMeNiNo +ToRTiNo +TheOne +NOP +oVaCoD +KiFFa +CLeMeNTiNo +ToRaCe +EviLDoG +PoPkiss +NeverDown +EleCTrO +CaM3LS_ +Hulk +StocaZZico +YoUbEgGaReD +Ocean +aLBaNiN0 +CaNeSeCCo +AlwaysBack +Crimson +OuRwEeRiCiN +Shorty +BeeDeePee +Punker +ToRaLBa +BeSTio +BaBy_BluE\r\n" + ":irc.ifi.uio.no 353 communi = #uptimed :+TeSTiCoLo^ +BieBeron +Prosexionist +svansen +artic^\r\n" + ":irc.ifi.uio.no 366 communi #uptimed :End of NAMES list.\r\n"; + +static const char* ircnet_names = + "communi _box Ste` `ViRuS` sensej ip \\x00 Dos Plato sonik [daro] 056DABT1Q Voicer Elcid NICK ComeAsYouAre nightmare AboutAGirl once Arwen vizion artico OnceW3reWarrior NT2000 Coolio babka dziadek OnceWereWarrior kaban nabak uytrew 705AAFHDM 705AAFHDO 705AAFHDN ggefew 233EAGIRG adsfds [jp] 233DADVTX 233DADVTW vaginakkk szok datanetek deeee italiano knbb em robo dupeczka 233DADWSZ mofaya fogiel [nsa] " + "vagina evil_ vaginallo why evil` inci yhw zazaza ewe bandoz zeus [animanera] {artic} Uptimed sisiako italianos elite polishpower nsa` `artic` RedDevil varna s rudy draven lupo ijnnk quest[2] desapir itsab r0d keep An0nym0uz _sparco nsa- KaPPa devilkickers wannie PaulAnunda TuOmaS- Ainame TeSsIer MarkrIckeR Markvillam LasteS JaMeS_ CriStiaNo IvanaCosta brunodp HackYou Ducentesimo Created Ciwarshak " + "BroLy BriatoRe tasya cpanel liana shoutcast humantourch myznc kopisusu ainah IRC knb ipv4 zguba { rudi idur ls_212 [goku] xman josip mushroom ajo Patty alien^ ReMoNDiNi marselo NiTr0 iOrOxxo DartagnaN TheCure FurisO MetroNotte ToRSoLo register init-zero Pilszcz DjCaro wamper ToRQUaTo Alison Wenni^_^ Hambi MzMaNdY Howie^^ Chiwai EkinCheng Jenny^_^ abuser` die Mgla rcu |jp| |be| egg suka ircoholik " + "|de| ruciu japanase zncbot latitanz kafir sparco invisible elk jazz esprit strange rex grasshopper miracle outlaw t0r- veronica artic| [m] ToRDo ToRRoNe MusSi ToRBiDo gozmit ToReRo ToRReNTe Mediterraneo Sugar unregistered bohjan biskut xdos unix cheap android birc edit Robocop Neon Temp Apofis Seth Sokar Iron Control Kiler mrozek widzewiak klesk Dj Rcnet mybsd lis [d] resu` ussus_ ksychy sp kln " + "psk Kulf0n daro darecki pan_ban Anonymouz atos MarRosso CommenDa miglia Spike Sc0rpion Krotone ViboValentia Arcaverde AlcaTRaz Adriatico MescaliNa PiPo_ RogeS sm0k kakashi naintails smuga howkey aven[gers] [neo] [dill] Aptajm marcin founder roger feedback M-k Madmax Piramida Hator Loginek Lill Polibuda Zeus` bouncer msdos gurl kongsi mamak scid mylinux sock nana ibm samba k-pop gyna k-chat mail " + "chat yatie ircap Ho-Nam mynet rindunet qip eggies db fakap loco mircpro mircbot mynic bladez hackintosh egghelp kampung cisco girl skepticals nickname Uncle-B bohsia mircx Grypsio kaktej Asia HelpAR VaneSSaBeLL AcHIni DjuNaBarnEs HydRA WilHElm- BrIanCHon LiLi Br0doWski Apus BoUdin0 ERebpAR RetIculum TucANA CAsIk CANes PuppIs BeNaZech BeRnaRDus Lupus IzrAileviC UlAIn AdaMI Bartels AGliNK Helon UlpAR " + "BemELmaNS DelphINus AbBati FoRNAx BenKvicH Ulseth PIctoR BeJJini BroOWn Br00k AffanNU Achenbach BelloTTo AbrHHam CeNtAuRus Agutte AlbrECht AnGeLico Ar13S TAuRus BeReNIces AzARfAR AquIlA Br0uwEr BreYtenbaCH CAsImAR CAssIopeIA ColumbA CRux EuGen GeoFFrY HiPPolyter HoRologIum LAceRtA LeoMINoR NIsAIn NIsseth NoRmA PaVl0viC ScoRpIus SeRpeNs ShuRImAR artic TitoAguiAri ZIRpAR TuRfAR VAnIkAIn VolANs NIspAR " + "CAsImAl ThiErry INdus Cetus PeTerFraNcio GRus MadDox PIscIs VulpeculA CeCily TRIANgulum CApRIcoRNus FraNtz TuRIen AdeMollo BrIgnOni AgReSti AustRAle BoTTinI BouVIer BrenTANA BriNdiSi CAelum DoRAdo ErNIeBarnEs Helseth JeNNiferBart leBrocQUy Lepus LyNx OctANs OphIuchus PeNeTriL PIsces PyxIs roKkmAn SAgIttA TelescopIum CRAteR PeRseus ShuRpAR CAsseth BeLLini ChAmAeleoN MIcRoscopIum Ad0lphE BoReAlIs ARA_ CARINA " + "AquARIus_ BartoLomeo ShuRon t0r__ YaAcovAgam Betty- HydRus ANDRoMeD2 Mercurio HeRcules_ ORIoN- Br00ker Cepheus 276XAAAPU PegAsus_ CAspAR BoUchE MoNoceRos URsAMAjoR CAsIl AivaZZovskKy ERIdANus BoUdeWijNS LyR4 ERebseth ShuRseth AleChiNskY LIbRA Leo AceRbi AuRIgA BeNNo Bootes_ BriSSaud CIRcINus DRAco SAgIttAR2us WaSHingt0n JUliUs- TuRIk HansBellmEs PAvo SculptoR AddNet GemINI ANtlIA ShuRkAn BoUcheR Br0wn " + "URsAMINoR VelA CoRvus_ BoWerANO AustRINA Agn0l KaziMIerZ PhoeNIx- Scutum SebAStieN VIRgo_ CANceR_ CygNus_ ZIRseth t0r_ ERebon Equuleus BouLAngeR CAson SextANs JBelliNi BourdiDIchoN AzARAth DiLDoSauRo PumPinks Callisto Cosenza Meschino Portos IoRobot Eclipse HighLander T0XiC Popoff PaLLa Indiano MDma Eastie BleacH PoSiX Slash_ InUtero FormaGGino riggiu tirrenico papera MaXMerilio MalandriNo ToRTiGLia " + "ToRToRa BeLGo NetBeans NeverMind BlackSp1rit Ionico Anfetamina t0r ladyshrew ToRoNTo AsTRo` ToRCeTTo EnSi ToRNaDo ToRReTTa MaGReBiNo ToRBoSo ToRSiDa ToRCia ToRCiCoLLo Wokie RuMeNiNo ToRTiNo TheOne NOP oVaCoD KiFFa CLeMeNTiNo ToRaCe EviLDoG PoPkiss NeverDown EleCTrO CaM3LS_ Hulk StocaZZico YoUbEgGaReD Ocean aLBaNiN0 CaNeSeCCo AlwaysBack Crimson OuRwEeRiCiN Shorty BeeDeePee Punker ToRaLBa BeSTio BaBy_BluE " + "TeSTiCoLo^ BieBeron Prosexionist svansen artic^"; + +static const char* ircnet_admins = ""; +static const char* ircnet_ops = "Voicer artico Uptimed abuser` Mgla ruciu t0r- [m] Grypsio"; +static const char* ircnet_halfops = ""; + +static const char* ircnet_voices = + "_box Ste` `ViRuS` sensej ip \\x00 Dos Plato sonik [daro] 056DABT1Q Elcid NICK ComeAsYouAre nightmare AboutAGirl once Arwen vizion OnceW3reWarrior NT2000 Coolio babka dziadek OnceWereWarrior kaban nabak uytrew 705AAFHDM 705AAFHDO 705AAFHDN ggefew 233EAGIRG adsfds [jp] 233DADVTX 233DADVTW vaginakkk szok datanetek deeee italiano knbb em robo dupeczka 233DADWSZ mofaya fogiel [nsa] " + "vagina evil_ vaginallo why evil` inci yhw zazaza ewe bandoz zeus [animanera] {artic} sisiako italianos elite polishpower nsa` `artic` RedDevil varna s rudy draven lupo ijnnk quest[2] desapir itsab r0d keep An0nym0uz _sparco nsa- KaPPa devilkickers wannie PaulAnunda TuOmaS- Ainame TeSsIer MarkrIckeR Markvillam LasteS JaMeS_ CriStiaNo IvanaCosta brunodp HackYou Ducentesimo Created Ciwarshak " + "BroLy BriatoRe tasya cpanel liana shoutcast humantourch myznc kopisusu ainah IRC knb ipv4 zguba { rudi idur ls_212 [goku] xman josip mushroom ajo Patty alien^ ReMoNDiNi marselo NiTr0 iOrOxxo DartagnaN TheCure FurisO MetroNotte ToRSoLo register init-zero Pilszcz DjCaro wamper ToRQUaTo Alison Wenni^_^ Hambi MzMaNdY Howie^^ Chiwai EkinCheng Jenny^_^ die rcu |jp| |be| egg suka ircoholik " + "|de| japanase zncbot latitanz kafir sparco invisible elk jazz esprit strange rex grasshopper miracle outlaw veronica artic| ToRDo ToRRoNe MusSi ToRBiDo gozmit ToReRo ToRReNTe Mediterraneo Sugar unregistered bohjan biskut xdos unix cheap android birc edit Robocop Neon Temp Apofis Seth Sokar Iron Control Kiler mrozek widzewiak klesk Dj Rcnet mybsd lis [d] resu` ussus_ ksychy sp kln " + "psk Kulf0n daro darecki pan_ban Anonymouz atos MarRosso CommenDa miglia Spike Sc0rpion Krotone ViboValentia Arcaverde AlcaTRaz Adriatico MescaliNa PiPo_ RogeS sm0k kakashi naintails smuga howkey aven[gers] [neo] [dill] Aptajm marcin founder roger feedback M-k Madmax Piramida Hator Loginek Lill Polibuda Zeus` bouncer msdos gurl kongsi mamak scid mylinux sock nana ibm samba k-pop gyna k-chat mail " + "chat yatie ircap Ho-Nam mynet rindunet qip eggies db fakap loco mircpro mircbot mynic bladez hackintosh egghelp kampung cisco girl skepticals nickname Uncle-B bohsia mircx kaktej Asia HelpAR VaneSSaBeLL AcHIni DjuNaBarnEs HydRA WilHElm- BrIanCHon LiLi Br0doWski Apus BoUdin0 ERebpAR RetIculum TucANA CAsIk CANes PuppIs BeNaZech BeRnaRDus Lupus IzrAileviC UlAIn AdaMI Bartels AGliNK Helon UlpAR " + "BemELmaNS DelphINus AbBati FoRNAx BenKvicH Ulseth PIctoR BeJJini BroOWn Br00k AffanNU Achenbach BelloTTo AbrHHam CeNtAuRus Agutte AlbrECht AnGeLico Ar13S TAuRus BeReNIces AzARfAR AquIlA Br0uwEr BreYtenbaCH CAsImAR CAssIopeIA ColumbA CRux EuGen GeoFFrY HiPPolyter HoRologIum LAceRtA LeoMINoR NIsAIn NIsseth NoRmA PaVl0viC ScoRpIus SeRpeNs ShuRImAR artic TitoAguiAri ZIRpAR TuRfAR VAnIkAIn VolANs NIspAR " + "CAsImAl ThiErry INdus Cetus PeTerFraNcio GRus MadDox PIscIs VulpeculA CeCily TRIANgulum CApRIcoRNus FraNtz TuRIen AdeMollo BrIgnOni AgReSti AustRAle BoTTinI BouVIer BrenTANA BriNdiSi CAelum DoRAdo ErNIeBarnEs Helseth JeNNiferBart leBrocQUy Lepus LyNx OctANs OphIuchus PeNeTriL PIsces PyxIs roKkmAn SAgIttA TelescopIum CRAteR PeRseus ShuRpAR CAsseth BeLLini ChAmAeleoN MIcRoscopIum Ad0lphE BoReAlIs ARA_ CARINA " + "AquARIus_ BartoLomeo ShuRon t0r__ YaAcovAgam Betty- HydRus ANDRoMeD2 Mercurio HeRcules_ ORIoN- Br00ker Cepheus 276XAAAPU PegAsus_ CAspAR BoUchE MoNoceRos URsAMAjoR CAsIl AivaZZovskKy ERIdANus BoUdeWijNS LyR4 ERebseth ShuRseth AleChiNskY LIbRA Leo AceRbi AuRIgA BeNNo Bootes_ BriSSaud CIRcINus DRAco SAgIttAR2us WaSHingt0n JUliUs- TuRIk HansBellmEs PAvo SculptoR AddNet GemINI ANtlIA ShuRkAn BoUcheR Br0wn " + "URsAMINoR VelA CoRvus_ BoWerANO AustRINA Agn0l KaziMIerZ PhoeNIx- Scutum SebAStieN VIRgo_ CANceR_ CygNus_ ZIRseth t0r_ ERebon Equuleus BouLAngeR CAson SextANs JBelliNi BourdiDIchoN AzARAth DiLDoSauRo PumPinks Callisto Cosenza Meschino Portos IoRobot Eclipse HighLander T0XiC Popoff PaLLa Indiano MDma Eastie BleacH PoSiX Slash_ InUtero FormaGGino riggiu tirrenico papera MaXMerilio MalandriNo ToRTiGLia " + "ToRToRa BeLGo NetBeans NeverMind BlackSp1rit Ionico Anfetamina t0r ladyshrew ToRoNTo AsTRo` ToRCeTTo EnSi ToRNaDo ToRReTTa MaGReBiNo ToRBoSo ToRSiDa ToRCia ToRCiCoLLo Wokie RuMeNiNo ToRTiNo TheOne NOP oVaCoD KiFFa CLeMeNTiNo ToRaCe EviLDoG PoPkiss NeverDown EleCTrO CaM3LS_ Hulk StocaZZico YoUbEgGaReD Ocean aLBaNiN0 CaNeSeCCo AlwaysBack Crimson OuRwEeRiCiN Shorty BeeDeePee Punker ToRaLBa BeSTio BaBy_BluE " + "TeSTiCoLo^ BieBeron Prosexionist svansen artic^"; + +#endif // TST_IRCNET_H -- cgit v1.2.3-54-g00ecf