1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34//TESTED_COMPONENT=src/versit
35
36#include "tst_qversitwriter.h"
37#include <QtVersit/qversitwriter.h>
38#include <QtVersit/qversitdocument.h>
39#include <QtVersit/qversitproperty.h>
40#include <QtTest/QtTest>
41#include <QByteArray>
42
43QTVERSIT_USE_NAMESPACE
44
45void tst_QVersitWriter::init()
46{
47 mOutputDevice = new QBuffer;
48 mWriter = new QVersitWriter;
49 mSignalCatcher = new SignalCatcher;
50 connect(sender: mWriter, SIGNAL(stateChanged(QVersitWriter::State)),
51 receiver: mSignalCatcher, SLOT(stateChanged(QVersitWriter::State)));
52}
53
54void tst_QVersitWriter::cleanup()
55{
56 delete mWriter;
57 delete mOutputDevice;
58 delete mSignalCatcher;
59}
60
61void tst_QVersitWriter::testDevice()
62{
63 // No device
64 QVERIFY(mWriter->device() == NULL);
65
66 // Device has been set
67 mWriter->setDevice(mOutputDevice);
68 QVERIFY(mWriter->device() == mOutputDevice);
69}
70
71void tst_QVersitWriter::testDefaultCodec()
72{
73 QVERIFY(mWriter->defaultCodec() == 0);
74 mWriter->setDefaultCodec(QTextCodec::codecForName(name: "UTF-16BE"));
75 QVERIFY(mWriter->defaultCodec() == QTextCodec::codecForName("UTF-16BE"));
76}
77
78void tst_QVersitWriter::testWritingVersions()
79{
80 mWriter->setDevice(mOutputDevice);
81 mOutputDevice->open(openMode: QBuffer::ReadWrite);
82
83 QVersitDocument document;
84 QVersitProperty property;
85 property.setName(QString(QString::fromLatin1(str: "FN")));
86 property.setValue(QString::fromLatin1(str: "John"));
87 document.addProperty(property);
88
89 QByteArray vCard30(
90 "BEGIN:VCARD\r\n"
91 "VERSION:3.0\r\n"
92 "FN:John\r\n"
93 "END:VCARD\r\n");
94 QByteArray vCard21(
95 "BEGIN:VCARD\r\n"
96 "VERSION:2.1\r\n"
97 "FN:John\r\n"
98 "END:VCARD\r\n");
99
100 // Given no type or componentType, it should be vCard 3.0
101 QVERIFY(mWriter->startWriting(document));
102 mWriter->waitForFinished();
103 QCOMPARE(mOutputDevice->buffer(), vCard30);
104
105 // document type should override the guess
106 document.setType(QVersitDocument::VCard21Type);
107 mOutputDevice->buffer().clear();
108 mOutputDevice->seek(off: 0);
109 QVERIFY(mWriter->startWriting(document));
110 mWriter->waitForFinished();
111 QCOMPARE(mOutputDevice->buffer(), vCard21);
112
113 // param to startWriting should override document type
114 mOutputDevice->buffer().clear();
115 mOutputDevice->seek(off: 0);
116 QVERIFY(mWriter->startWriting(document, QVersitDocument::VCard30Type));
117 mWriter->waitForFinished();
118 QCOMPARE(mOutputDevice->buffer(), vCard30);
119}
120
121void tst_QVersitWriter::testWriting21()
122{
123 // vCard 2.1
124 QByteArray vCard21(
125"BEGIN:VCARD\r\n\
126VERSION:2.1\r\n\
127FN:John\r\n\
128END:VCARD\r\n");
129 QVersitDocument document;
130 document.setComponentType(QStringLiteral("VCARD"));
131 QVersitProperty property;
132 property.setName(QString(QStringLiteral("FN")));
133 property.setValue(QStringLiteral("John"));
134 document.addProperty(property);
135 document.setType(QVersitDocument::VCard21Type);
136 QList<QVersitDocument> list;
137 list.append(t: document);
138
139 // Device not set
140 QCOMPARE(mWriter->state(), QVersitWriter::InactiveState);
141 QCOMPARE(mWriter->error(), QVersitWriter::NoError);
142 QVERIFY(!mWriter->startWriting(list));
143 QCOMPARE(mWriter->state(), QVersitWriter::InactiveState);
144 QCOMPARE(mWriter->error(), QVersitWriter::IOError);
145 QVERIFY(!mWriter->waitForFinished());
146
147 // Device not opened
148 mWriter->setDevice(mOutputDevice);
149 QVERIFY(!mWriter->startWriting(list));
150 QCOMPARE(mWriter->state(), QVersitWriter::InactiveState);
151 QCOMPARE(mWriter->error(), QVersitWriter::IOError);
152
153 // Now open the device and it should work.
154 mOutputDevice->open(openMode: QBuffer::ReadWrite);
155 QVERIFY2(mWriter->startWriting(list), QString::number(mWriter->error()).toLatin1().data());
156 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
157 QCOMPARE(mWriter->state(), QVersitWriter::FinishedState);
158 QCOMPARE(mWriter->error(), QVersitWriter::NoError);
159 mOutputDevice->seek(off: 0);
160 QByteArray result(mOutputDevice->readAll());
161 QCOMPARE(result, vCard21);
162
163 // Try some other codec
164 delete mOutputDevice;
165 mOutputDevice = new QBuffer;
166 mOutputDevice->open(openMode: QBuffer::ReadWrite);
167 mWriter->setDevice(mOutputDevice);
168 QTextCodec* utf16(QTextCodec::codecForName(name: "UTF-16"));
169 mWriter->setDefaultCodec(utf16);
170 QVERIFY2(mWriter->startWriting(list), QString::number(mWriter->error()).toLatin1().data());
171 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
172 QCOMPARE(mWriter->state(), QVersitWriter::FinishedState);
173 QCOMPARE(mWriter->error(), QVersitWriter::NoError);
174 mOutputDevice->seek(off: 0);
175 result = mOutputDevice->readAll();
176 QByteArray expected(utf16->fromUnicode(uc: QLatin1String(vCard21.data())));
177 QCOMPARE(result, expected);
178}
179
180void tst_QVersitWriter::testWriting30()
181{
182 // vCard 3.0
183 QByteArray vCard30(
184"BEGIN:VCARD\r\n\
185VERSION:3.0\r\n\
186FN:John\r\n\
187END:VCARD\r\n");
188
189 QVersitDocument document;
190 document.setComponentType(QStringLiteral("VCARD"));
191 QVersitProperty property;
192 property.setName(QString(QStringLiteral("FN")));
193 property.setValue(QStringLiteral("John"));
194 document.addProperty(property);
195 document.setType(QVersitDocument::VCard30Type);
196 QList<QVersitDocument> list;
197 list.append(t: document);
198
199 // Basic 3.0 test
200 mOutputDevice->open(openMode: QBuffer::ReadWrite);
201 mWriter->setDevice(mOutputDevice);
202 QVERIFY2(mWriter->startWriting(list), QString::number(mWriter->error()).toLatin1().data());
203 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
204 QCOMPARE(mWriter->state(), QVersitWriter::FinishedState);
205 QCOMPARE(mWriter->error(), QVersitWriter::NoError);
206 mOutputDevice->seek(off: 0);
207 QByteArray result(mOutputDevice->readAll());
208 QCOMPARE(result, vCard30);
209
210 qApp->processEvents(); // clean up before we start sniffing signals
211
212 // Asynchronous writing
213 mOutputDevice->reset();
214 mSignalCatcher->mReceived.clear();
215 QVERIFY2(mWriter->startWriting(list), QString::number(mWriter->error()).toLatin1().data());
216 QTRY_VERIFY(mSignalCatcher->mReceived.count() >= 2);
217 QCOMPARE(mSignalCatcher->mReceived.at(0), QVersitWriter::ActiveState);
218 QCOMPARE(mSignalCatcher->mReceived.at(1), QVersitWriter::FinishedState);
219
220 // Cancelling
221 delete mOutputDevice;
222 mOutputDevice = new QBuffer;
223 mOutputDevice->open(openMode: QBuffer::ReadWrite);
224 mSignalCatcher->mReceived.clear();
225 mWriter->setDevice(mOutputDevice);
226 mWriter->startWriting(input: list);
227 mWriter->cancel();
228 mWriter->waitForFinished();
229 QTRY_VERIFY(mSignalCatcher->mReceived.count() >= 2);
230 QCOMPARE(mSignalCatcher->mReceived.at(0), QVersitWriter::ActiveState);
231 QVersitWriter::State state(mSignalCatcher->mReceived.at(i: 1));
232 // It's possible that it finishes before it cancels.
233 QVERIFY(state == QVersitWriter::CanceledState
234 || state == QVersitWriter::FinishedState);
235}
236
237void tst_QVersitWriter::testByteArrayOutput()
238{
239 const QByteArray vCard30(
240 "BEGIN:VCARD\r\n"
241 "VERSION:3.0\r\n"
242 "FN:John\r\n"
243 "END:VCARD\r\n");
244
245 delete mWriter; // we don't want the init()ed writer.
246
247 QByteArray output;
248 mWriter = new QVersitWriter(&output);
249
250 QVERIFY(mWriter->device() == 0);
251
252 QVersitDocument document(QVersitDocument::VCard30Type);
253 document.setComponentType(QStringLiteral("VCARD"));
254 QVersitProperty property;
255 property.setName(QString(QStringLiteral("FN")));
256 property.setValue(QStringLiteral("John"));
257 document.addProperty(property);
258 QVERIFY2(mWriter->startWriting(document), QString::number(mWriter->error()).toLatin1().data());
259 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
260 QCOMPARE(output, vCard30);
261}
262
263void tst_QVersitWriter::testWritingDocument()
264{
265 QFETCH(QVersitDocument, document);
266 QFETCH(QByteArray, expected);
267
268 mOutputDevice->open(openMode: QBuffer::ReadWrite);
269 mWriter->setDevice(mOutputDevice);
270 QVERIFY2(mWriter->startWriting(document), QString::number(mWriter->error()).toLatin1().data());
271 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
272 mOutputDevice->seek(off: 0);
273 QByteArray result(mOutputDevice->readAll());
274 if (result!=expected) qDebug() << result << expected;
275 QCOMPARE(result, expected);
276
277 // try it again in another codec
278 QTextCodec* utf16(QTextCodec::codecForName(name: "UTF-16"));
279 mWriter->setDefaultCodec(utf16);
280 mOutputDevice->buffer().clear();
281 mOutputDevice->seek(off: 0);
282 QVERIFY2(mWriter->startWriting(document), QString::number(mWriter->error()).toLatin1().data());
283 QVERIFY2(mWriter->waitForFinished(), QString::number(mWriter->error()).toLatin1().data());
284 mOutputDevice->seek(off: 0);
285 result = mOutputDevice->readAll();
286 expected = utf16->fromUnicode(uc: QString::fromLatin1(str: expected));
287 if (result!=expected) qDebug() << result << expected;
288 QCOMPARE(result, expected);
289}
290
291void tst_QVersitWriter::testWritingDocument_data()
292{
293 QTest::addColumn<QVersitDocument>(name: "document");
294 QTest::addColumn<QByteArray>(name: "expected");
295
296 QVersitDocument document(QVersitDocument::VCard21Type);
297 document.setComponentType(QStringLiteral("VCARD"));
298 QVersitProperty property;
299 property.setName(QStringLiteral("FN"));
300 property.setValue(QStringLiteral("Bob"));
301 document.addProperty(property);
302 QTest::newRow(dataTag: "basic vCard 2.1") << document << QByteArray(
303 "BEGIN:VCARD\r\n"
304 "VERSION:2.1\r\n"
305 "FN:Bob\r\n"
306 "END:VCARD\r\n"
307 );
308
309 document.setComponentType(QStringLiteral("VCARD"));
310 document.setType(QVersitDocument::VCard30Type);
311 QTest::newRow(dataTag: "basic vCard 3.0") << document << QByteArray(
312 "BEGIN:VCARD\r\n"
313 "VERSION:3.0\r\n"
314 "FN:Bob\r\n"
315 "END:VCARD\r\n"
316 );
317
318 document.setComponentType(QStringLiteral("VCARD"));
319 document.setType(QVersitDocument::VCard40Type);
320 QTest::newRow(dataTag: "basic vCard 4.0") << document << QByteArray(
321 "BEGIN:VCARD\r\n"
322 "VERSION:4.0\r\n"
323 "FN:Bob\r\n"
324 "END:VCARD\r\n"
325 );
326
327 {
328 QVersitDocument document(QVersitDocument::ICalendar20Type);
329 document.setComponentType(QStringLiteral("VCALENDAR"));
330 QVersitDocument subdocument(QVersitDocument::ICalendar20Type);
331 subdocument.setComponentType(QStringLiteral("VEVENT"));
332 property.setValueType(QVersitProperty::PreformattedType);
333 property.setName(QStringLiteral("RRULE"));
334 property.setValue(QStringLiteral("FREQ=MONTHLY;BYMONTHDAY=1,3"));
335 subdocument.addProperty(property);
336 document.addSubDocument(subdocument);
337 QTest::newRow(dataTag: "basic iCalendar 2.0") << document << QByteArray(
338 "BEGIN:VCALENDAR\r\n"
339 "VERSION:2.0\r\n"
340 "BEGIN:VEVENT\r\n"
341 "RRULE:FREQ=MONTHLY;BYMONTHDAY=1,3\r\n"
342 "END:VEVENT\r\n"
343 "END:VCALENDAR\r\n");
344 }
345
346 {
347 QVersitDocument document(QVersitDocument::ICalendar20Type);
348 document.setComponentType(QStringLiteral("VCALENDAR"));
349 QVersitProperty property;
350 property.setName(QStringLiteral("PRODID"));
351 property.setValue(QStringLiteral("-//hacksw/handcal//NONSGML v1.0//EN"));
352 document.addProperty(property);
353 QVersitDocument nested(QVersitDocument::ICalendar20Type);
354 nested.setComponentType(QStringLiteral("VEVENT"));
355 property.setName(QStringLiteral("DTSTART"));
356 property.setValue(QStringLiteral("19970714T170000Z"));
357 nested.addProperty(property);
358 property.setName(QStringLiteral("DTEND"));
359 property.setValue(QStringLiteral("19970715T035959Z"));
360 nested.addProperty(property);
361 property.setName(QStringLiteral("SUMMARY"));
362 property.setValue(QStringLiteral("Bastille Day Party"));
363 nested.addProperty(property);
364 document.addSubDocument(subdocument: nested);
365 QTest::newRow(dataTag: "iCalendar 2.0 from spec") << document << QByteArray(
366 "BEGIN:VCALENDAR\r\n"
367 "VERSION:2.0\r\n"
368 "PRODID:-//hacksw/handcal//NONSGML v1.0//EN\r\n"
369 "BEGIN:VEVENT\r\n"
370 "DTSTART:19970714T170000Z\r\n"
371 "DTEND:19970715T035959Z\r\n"
372 "SUMMARY:Bastille Day Party\r\n"
373 "END:VEVENT\r\n"
374 "END:VCALENDAR\r\n");
375 }
376
377 {
378 QString longString(QLatin1String(
379 "4567890123456789012345678901234567890123456789012345678901234567890123456"
380 "234567890123456789012345678901234567890123456789012345678901234567890123456"
381 "234567890123456789012"));
382 QVersitDocument document(QVersitDocument::VCard21Type);
383 document.setComponentType(QStringLiteral("VCARD"));
384 QVersitProperty property;
385 property.setName(QStringLiteral("FN"));
386 property.setValue(longString);
387 document.addProperty(property);
388 QByteArray expected21(
389 "BEGIN:VCARD\r\n"
390 "VERSION:2.1\r\n"
391 "FN:4567890123456789012345678901234567890123456789012345678901234567890123456\r\n"
392 " 234567890123456789012345678901234567890123456789012345678901234567890123456\r\n"
393 " 234567890123456789012\r\n"
394 "END:VCARD\r\n");
395 QTest::newRow(dataTag: "folding 2.1") << document << expected21;
396
397 document.setType(QVersitDocument::VCard30Type);
398 QByteArray expected30(
399 "BEGIN:VCARD\r\n"
400 "VERSION:3.0\r\n"
401 "FN:4567890123456789012345678901234567890123456789012345678901234567890123456\r\n"
402 " 234567890123456789012345678901234567890123456789012345678901234567890123456\r\n"
403 " 234567890123456789012\r\n"
404 "END:VCARD\r\n");
405 QTest::newRow(dataTag: "folding 3.0") << document << expected30;
406
407 document.setType(QVersitDocument::VCard21Type);
408 property.setValue(longString.toLatin1());
409 property.setValueType(QVersitProperty::BinaryType);
410 document.removeProperties(name: "FN");
411 document.addProperty(property);
412 QByteArray expected21b(
413 "BEGIN:VCARD\r\n"
414 "VERSION:2.1\r\n"
415 "FN;ENCODING=BASE64:\r\n"
416 " NDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODk\r\n"
417 " wMTIzNDU2Nzg5MDEyMzQ1NjIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MD\r\n"
418 " EyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1NjIzNDU2Nzg5MDEyMzQ1Njc4OTAxM\r\n"
419 " g==\r\n"
420 "\r\n"
421 "END:VCARD\r\n");
422 QTest::newRow(dataTag: "folding 2.1") << document << expected21b;
423
424 document.setType(QVersitDocument::VCard30Type);
425 QByteArray expected30b(
426 "BEGIN:VCARD\r\n"
427 "VERSION:3.0\r\n"
428 "FN;ENCODING=b:NDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OT\r\n"
429 " AxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1NjIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwM\r\n"
430 " TIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1NjIzNDU2Nzg5MDEy\r\n"
431 " MzQ1Njc4OTAxMg==\r\n"
432 "END:VCARD\r\n");
433 QTest::newRow(dataTag: "folding 3.0") << document << expected30b;
434 }
435}
436
437QTEST_MAIN(tst_QVersitWriter)
438

source code of qtpim/tests/auto/versit/qversitwriter/tst_qversitwriter.cpp