2
* Copyright (C) 2014 Daniel Vrátil <dvratil@redhat.com>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
#include "fakeakonadiserver.h"
23
#include "fakeconnection.h"
24
#include "akstandarddirs.h"
27
#include "imapstreamparser.h"
30
#include "storage/partstreamer.h"
31
#include <storage/parthelper.h>
36
using namespace Akonadi;
37
using namespace Akonadi::Server;
39
Q_DECLARE_METATYPE(Akonadi::Server::PimItem)
41
class PartStreamerTest : public QObject
48
qRegisterMetaType<Akonadi::Server::Response>();
50
// Set a very small treshold for easier testing
51
const QString serverConfigFile = AkStandardDirs::serverConfigFile(XdgBaseDirs::ReadWrite);
52
QSettings settings(serverConfigFile, QSettings::IniFormat);
53
settings.setValue(QLatin1String("General/SizeThreshold"), 5);
56
FakeAkonadiServer::instance()->init();
57
} catch (const FakeAkonadiServerException &e) {
58
akError() << "Server exception: " << e.what();
59
akFatal() << "Fake Akonadi Server failed to start up, aborting test";
65
FakeAkonadiServer::instance()->quit();
70
void slotStreamerResponseAvailable(const Akonadi::Server::Response &response)
72
const QByteArray string = response.asString();
73
const qint64 fnStart = string.indexOf("[FILE ") + 6;
74
const qint64 fnEnd = string.indexOf("]", fnStart);
75
const QByteArray name = string.mid(fnStart, fnEnd - fnStart);
76
const QString fileName = PartHelper::resolveAbsolutePath(name);
77
qDebug() << string << fileName;
80
QVERIFY(f.open(QIODevice::ReadWrite));
82
QFETCH(QByteArray, expectedData);
83
qDebug() << "Wrote" << f.write(expectedData) << "bytes to" << f.fileName();
87
void testStreamer_data()
89
QTest::addColumn<QByteArray>("expectedPartName");
90
QTest::addColumn<QByteArray>("expectedData");
91
QTest::addColumn<qint64>("expectedPartSize");
92
QTest::addColumn<bool>("expectedChanged");
93
QTest::addColumn<bool>("isExternal");
94
QTest::addColumn<PimItem>("pimItem");
97
item.setCollectionId(Collection::retrieveByName(QLatin1String("Col A")).id());
98
item.setMimeType(MimeType::retrieveByName(QLatin1String("application/octet-stream")));
99
item.setSize(1); // this will not match reality during the test, but that does not matter, as
100
// that's not the subject of this test
101
QVERIFY(item.insert());
103
// Order of these tests matters!
104
QTest::newRow("item 1, internal") << QByteArray("PLD:DATA") << QByteArray("123") << 3ll << true << false << item;
105
QTest::newRow("item 1, change to external") << QByteArray("PLD:DATA") << QByteArray("123456789") << 9ll << true << true << item;
106
QTest::newRow("item 1, update external") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << true << true << item;
107
QTest::newRow("item 1, external, no change") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << false << true << item;
108
QTest::newRow("item 1, change to internal") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << true << false << item;
109
QTest::newRow("item 1, internal, no change") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << false << false << item;
115
QFETCH(QByteArray, expectedPartName);
116
QFETCH(QByteArray, expectedData);
117
QFETCH(qint64, expectedPartSize);
118
QFETCH(bool, expectedChanged);
119
QFETCH(bool, isExternal);
120
QFETCH(PimItem, pimItem);
122
FakeConnection connection;
123
ClientCapabilities capabilities;
124
capabilities.setAkAppendStreaming(true);
125
capabilities.setDirectStreaming(true);
126
capabilities.setNoPayloadPath(true);
127
connection.setCapabilities(capabilities);
130
QVERIFY(buffer.open(QIODevice::ReadWrite));
131
buffer.write("PLD:DATA[0] {" + QByteArray::number(expectedPartSize) + "}\n");
133
buffer.write(expectedData);
138
ImapStreamParser parser(&buffer);
139
const QByteArray command = parser.readString();
141
PartStreamer streamer(&connection, &parser, pimItem);
142
connect(&streamer, SIGNAL(responseAvailable(Akonadi::Server::Response)),
143
this, SLOT(slotStreamerResponseAvailable(Akonadi::Server::Response)));
144
QSignalSpy streamerSpy(&streamer, SIGNAL(responseAvailable(Akonadi::Server::Response)));
148
bool changed = false;
151
QVERIFY(streamer.stream(command, false, partName, partSize, &changed));
152
} catch (const Exception &e) {
153
qDebug() << e.type() << ":" << e.what();
154
QFAIL("Caught an unexpected exception");
157
QCOMPARE(QString::fromUtf8(partName), QString::fromUtf8(expectedPartName));
158
QCOMPARE(partSize, expectedPartSize);
159
QCOMPARE(expectedChanged, changed);
161
PimItem item = PimItem::retrieveById(pimItem.id());
162
const QVector<Part> parts = item.parts();
163
QVERIFY(parts.count() == 1);
164
const Part part = parts[0];
165
QCOMPARE(part.datasize(), expectedPartSize);
166
QCOMPARE(part.external(), isExternal);
167
const QByteArray data = part.data();
169
QVERIFY(streamerSpy.count() == 1);
170
QVERIFY(streamerSpy.first().count() == 1);
171
const Response response = streamerSpy.first().first().value<Akonadi::Server::Response>();
172
const QByteArray str = response.asString();
173
const QByteArray expectedResponse = "+ STREAM [FILE " + QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version()) + "]";
174
QCOMPARE(QString::fromUtf8(str), QString::fromUtf8(expectedResponse));
176
QFile file(PartHelper::resolveAbsolutePath(data));
177
QVERIFY(file.exists());
178
QCOMPARE(file.size(), expectedPartSize);
179
QVERIFY(file.open(QIODevice::ReadOnly));
180
const QByteArray fileData = file.readAll();
181
QCOMPARE(QString::fromUtf8(fileData), QString::fromUtf8(expectedData));
182
QCOMPARE(fileData, expectedData);
184
// Make sure no previous versions are left behind in file_db_data
185
for (int i = 0; i < part.version(); ++i) {
186
const QByteArray fileName = QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version());
187
const QString filePath = PartHelper::resolveAbsolutePath(fileName);
188
QVERIFY(!QFile::exists(filePath));
191
QVERIFY(streamerSpy.isEmpty());
193
QCOMPARE(QString::fromUtf8(data), QString::fromUtf8(expectedData));
194
QCOMPARE(data, expectedData);
196
// Make sure nothing is left behind in file_db_data
197
for (int i = 0; i <= part.version(); ++i) {
198
const QByteArray fileName = QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version());
199
const QString filePath = PartHelper::resolveAbsolutePath(fileName);
200
QVERIFY(!QFile::exists(filePath));
207
AKTEST_FAKESERVER_MAIN(PartStreamerTest)
209
#include "partstreamertest.moc"