1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
2 
3    This file is part of the Trojita Qt IMAP e-mail client,
4    http://trojita.flaska.net/
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of
9    the License or (at your option) version 3 or any later version
10    accepted by the membership of KDE e.V. (or its successor approved
11    by the membership of KDE e.V.), which shall act as a proxy
12    defined in Section 14 of version 3 of the license.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include <QtTest>
24 #include "test_Imap_Model.h"
25 #include "Common/MetaTypes.h"
26 #include "Streams/FakeSocket.h"
27 #include "Imap/Model/ItemRoles.h"
28 #include "Imap/Model/MemoryCache.h"
29 #include "Imap/Model/MailboxModel.h"
30 
initTestCase()31 void ImapModelTest::initTestCase()
32 {
33     Common::registerMetaTypes();
34     mboxModel = 0;
35 }
36 
init()37 void ImapModelTest::init()
38 {
39     Imap::Mailbox::AbstractCache* cache = new Imap::Mailbox::MemoryCache(this);
40     factory = new Streams::FakeSocketFactory(Imap::CONN_STATE_CONNECTED_PRETLS_PRECAPS);
41     Imap::Mailbox::TaskFactoryPtr taskFactory(new Imap::Mailbox::TaskFactory());
42     model = new Imap::Mailbox::Model(this, cache, Imap::Mailbox::SocketFactoryPtr(factory), std::move(taskFactory));
43     setupLogging();
44     LibMailboxSync::setModelNetworkPolicy(model, Imap::Mailbox::NETWORK_ONLINE);
45     QCoreApplication::processEvents();
46 }
47 
testSyncMailbox()48 void ImapModelTest::testSyncMailbox()
49 {
50     model->rowCount( QModelIndex() );
51     QCoreApplication::processEvents();
52     cServer("* PREAUTH [CAPABILITY Imap4Rev1] foo\r\n");
53     cClient(t.mk("LIST \"\" \"%\"\r\n"));
54     cServer("* LIST (\\HasNoChildren) \".\" \"INBOX\"\r\n"
55             "* CAPABILITY IMAP4rev1\r\n"
56             + t.last("ok list completed\r\n"));
57     QModelIndex inbox = model->index(1, 0, QModelIndex());
58     QCOMPARE(model->data( inbox, Qt::DisplayRole), QVariant("INBOX"));
59     cEmpty();
60 
61     // further tests are especially in the Imap_Task_ObtainSynchronizedMailboxTest
62 }
63 
testInboxCaseSensitivity()64 void ImapModelTest::testInboxCaseSensitivity()
65 {
66     mboxModel = new Imap::Mailbox::MailboxModel(this, model);
67     mboxModel->rowCount(QModelIndex());
68     QCoreApplication::processEvents();
69     cServer("* PREAUTH [Capability imap4rev1] foo\r\n");
70     t.reset();
71     cClient(t.mk("LIST \"\" \"%\"\r\n"));
72     cServer("* LIST (\\Noinferiors) \".\" \"Inbox\"\r\n"
73             + t.last("ok list completed\r\n"));
74     QCOMPARE(mboxModel->data(mboxModel->index(0, 0, QModelIndex()), Qt::DisplayRole), QVariant("INBOX"));
75     cEmpty();
76     mboxModel->deleteLater();
77     mboxModel = 0;
78 }
79 
testCreationDeletionHandling()80 void ImapModelTest::testCreationDeletionHandling()
81 {
82     // Start the conversation
83     model->rowCount( QModelIndex() );
84     QCoreApplication::processEvents();
85     cServer("* PREAUTH [CAPABILITY imap4rev1] foo\r\n");
86 
87     // Ask for capabilities and list top-level mailboxes
88     // These commands are interleaved with each other
89     t.reset();
90     cClient(t.mk("LIST \"\" \"%\"\r\n"));
91     cServer("* LIST (\\HasNoChildren) \".\" \"INBOX\"\r\n"
92             "* LIST (\\HasChildren) \".\" \"SomeParent\"\r\n"
93             "* LIST (\\HasNoChildren) \".\" \"one\"\r\n"
94             "* LIST (\\HasNoChildren) \".\" two\r\n"
95             + t.last("ok list completed\r\n"));
96 
97     // Note that the ordering is case-insensitive
98     QModelIndex mbox_inbox = model->index(1, 0, QModelIndex());
99     QModelIndex mbox_one = model->index(2, 0, QModelIndex());
100     QModelIndex mbox_SomeParent = model->index(3, 0, QModelIndex());
101     QModelIndex mbox_two = model->index(4, 0, QModelIndex());
102     QCOMPARE( model->data(mbox_inbox, Qt::DisplayRole), QVariant("INBOX"));
103     QCOMPARE( model->data(mbox_one, Qt::DisplayRole), QVariant("one"));
104     QCOMPARE( model->data(mbox_two, Qt::DisplayRole), QVariant("two"));
105     QCOMPARE( model->data(mbox_SomeParent, Qt::DisplayRole), QVariant("SomeParent"));
106 
107     // Try to create mailbox
108     model->createMailbox(QStringLiteral("zzz_newly-Created"));
109     cClient(t.mk("CREATE zzz_newly-Created\r\n"));
110 
111     // Sane invariants
112     QSignalSpy creationFailed(model, SIGNAL(mailboxCreationFailed(QString,QString)));
113     QVERIFY(creationFailed.isValid());
114     QSignalSpy creationSucceded(model, SIGNAL(mailboxCreationSucceded(QString)));
115     QVERIFY(creationSucceded.isValid());
116     QSignalSpy deletionFailed(model, SIGNAL(mailboxDeletionFailed(QString,QString)));
117     QVERIFY(deletionFailed.isValid());
118     QSignalSpy deletionSucceded(model, SIGNAL(mailboxDeletionSucceded(QString)));
119     QVERIFY(deletionSucceded.isValid());
120 
121     // Test that we handle failure of the CREATE command
122     cServer(t.last("NO go away\r\n"));
123     QCOMPARE(creationFailed.count(), 1);
124     QList<QVariant> args = creationFailed.takeFirst();
125     QCOMPARE(args.size(), 2);
126     QCOMPARE(args[0], QVariant("zzz_newly-Created"));
127     QCOMPARE(args[1], QVariant("go away"));
128     QCOMPARE(creationSucceded.count(), 0);
129     QCOMPARE(deletionFailed.count(), 0);
130     QCOMPARE(deletionSucceded.count(), 0);
131 
132     // Now test its successful completion
133     model->createMailbox(QStringLiteral("zzz_newly-Created2"));
134     cClient(t.mk("CREATE zzz_newly-Created2\r\n"));
135     cServer(t.last("OK mailbox created\r\n"));
136     cClient(t.mk("LIST \"\" zzz_newly-Created2\r\n"));
137     cServer("* LIST (\\HasNoChildren) \".\" zzz_newly-Created2\r\n"
138             + t.last("OK x\r\n"));
139     QCOMPARE(creationFailed.count(), 0);
140     QCOMPARE(creationSucceded.count(), 1);
141     args = creationSucceded.takeFirst();
142     QCOMPARE(args.size(), 1);
143     QCOMPARE(args[0], QVariant("zzz_newly-Created2"));
144     QCOMPARE(deletionFailed.count(), 0);
145     QCOMPARE(deletionSucceded.count(), 0);
146     QModelIndex mbox_zzz = model->index(5, 0, QModelIndex());
147     QCOMPARE(model->data(mbox_zzz, Qt::DisplayRole), QVariant("zzz_newly-Created2"));
148     cEmpty();
149 
150     // Verify automated subscription
151     model->createMailbox(QStringLiteral("zzz_newly-Created3"), Imap::Mailbox::AutoSubscription::SUBSCRIBE);
152     cClient(t.mk("CREATE zzz_newly-Created3\r\n"));
153     cServer(t.last("OK created\r\n"));
154     cClient(t.mk("LIST \"\" zzz_newly-Created3\r\n"));
155     cServer("* LIST (\\HasNoChildren) \".\" zzz_newly-Created3\r\n"
156             + t.last("OK listed\r\n"));
157     cClient(t.mk("SUBSCRIBE zzz_newly-Created3\r\n"));
158     cServer(t.last("OK subscribed\r\n"));
159     QModelIndex mbox_created3 = model->index(6, 0, QModelIndex());
160     QVERIFY(mbox_created3.isValid());
161     QCOMPARE(mbox_created3.data(Qt::DisplayRole), QVariant("zzz_newly-Created3"));
162     QCOMPARE(mbox_created3.data(Imap::Mailbox::RoleMailboxIsSubscribed), QVariant(true));
163     QCOMPARE(mbox_inbox.data(Imap::Mailbox::RoleMailboxIsSubscribed), QVariant(false));
164     cEmpty();
165 }
166 
167 QTEST_GUILESS_MAIN(ImapModelTest)
168