1 /* This file is part of the KDE project
2 * Copyright (C) 2004 David Faure <faure@kde.org>
3 * Copyright 2008 Thomas Zander <zander@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20 // clazy:excludeall=qstring-arg
21 #include <KoXmlWriter.h>
22
23 #include <QString>
24 #include <QBuffer>
25 #include <QTest>
26
27 class TestXmlWriter : public QObject
28 {
29 Q_OBJECT
30 private Q_SLOTS:
31 void testDocytype();
32 void testEmtpyElement();
33 void testAttributes();
34 void testIndent();
35 void testTextNode();
36 void testTextSpan();
37 void testTextSpanWithTabCache();
38 void testProcessingInstruction();
39 void testAddManifestEntry();
40 void testEscapingLongString();
41 void testEscalingLongString2();
42 void testConfig();
43
44 void speedTest();
45
46 private:
47 void setup(const char *publicId = 0, const char *systemId = 0);
48 QString content();
49
50 KoXmlWriter *writer;
51 QBuffer *buffer;
52 };
53
setup(const char * publicId,const char * systemId)54 void TestXmlWriter::setup(const char *publicId, const char *systemId)
55 {
56 buffer = new QBuffer();
57 buffer->open(QIODevice::WriteOnly);
58
59 writer = new KoXmlWriter(buffer);
60 writer->startDocument("dummy", publicId, systemId);
61 writer->startElement("dummy");
62 }
63
content()64 QString TestXmlWriter::content()
65 {
66 writer->endElement();
67 writer->endDocument();
68 buffer->putChar('\0'); /*null-terminate*/
69 buffer->close();
70 QString stringContent = QString::fromUtf8(buffer->data());
71 int index = stringContent.indexOf("<dummy");
72 Q_ASSERT(index);
73 index = stringContent.indexOf('>', index);
74 stringContent = stringContent.mid(index+1, stringContent.length() - index - 11).trimmed();
75 return stringContent;
76 }
77
testDocytype()78 void TestXmlWriter::testDocytype()
79 {
80 setup("foo", "bar");
81 QCOMPARE(content(), QString());
82 QString stringContent = QString::fromUtf8(buffer->data());
83 QCOMPARE(stringContent, QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
84 "<!DOCTYPE dummy PUBLIC \"foo\" \"bar\">\n<dummy/>\n"));
85 }
86
testAttributes()87 void TestXmlWriter::testAttributes()
88 {
89 setup();
90
91 writer->startElement("test");
92 writer->addAttribute("a", "val");
93 writer->addAttribute("b", "<\">");
94 writer->addAttribute("c", -42);
95 writer->addAttribute("d", 1234.56789012345);
96 writer->addAttributePt("e", 1234.56789012345);
97 writer->addAttribute("f", false);
98 writer->addAttribute("g", true);
99 writer->endElement();
100 QCOMPARE(content(), QString("<test a=\"val\" b=\"<">\" c=\"-42\" d=\"1234.56789012345\" e=\"1234.56789012345pt\" f=\"false\" g=\"true\"/>"));
101 }
102
testEmtpyElement()103 void TestXmlWriter::testEmtpyElement()
104 {
105 setup();
106 writer->startElement("m");
107 writer->endElement();
108 QCOMPARE(content(), QString("<m/>"));
109 }
110
testIndent()111 void TestXmlWriter::testIndent()
112 {
113 setup();
114 writer->startElement("a");
115 writer->startElement("b");
116 writer->startElement("c");
117 writer->endElement();
118 writer->endElement();
119 writer->endElement();
120 QCOMPARE(content(), QString("<a>\n <b>\n <c/>\n </b>\n </a>"));
121 }
122
testTextNode()123 void TestXmlWriter::testTextNode()
124 {
125 setup();
126 writer->startElement("a");
127 writer->startElement("b", false /*no indent*/);
128 writer->startElement("c");
129 writer->endElement();
130 writer->addTextNode("te");
131 writer->addTextNode("xt");
132 writer->endElement();
133 writer->endElement();
134 QCOMPARE(content(), QString("<a>\n <b><c/>text</b>\n </a>"));
135 }
136
testTextSpan()137 void TestXmlWriter::testTextSpan()
138 {
139 setup();
140 writer->startElement("p", false /*no indent*/);
141 writer->addTextSpan(QString::fromLatin1(" \t\n foo "));
142 writer->endElement();
143 QCOMPARE(content(), QString("<p><text:s text:c=\"3\"/><text:tab/><text:line-break/> foo<text:s text:c=\"2\"/></p>"));
144 }
145
testTextSpanWithTabCache()146 void TestXmlWriter::testTextSpanWithTabCache()
147 {
148 setup();
149 writer->startElement("p", false /*no indent*/);
150 QMap<int, int> tabCache;
151 tabCache.insert(3, 0);
152 writer->addTextSpan(QString::fromUtf8(" \t\n foö "), tabCache);
153 writer->endElement();
154 QCOMPARE(content(), QString::fromUtf8("<p><text:s text:c=\"3\"/><text:tab text:tab-ref=\"1\"/>"
155 "<text:line-break/> foö<text:s text:c=\"2\"/></p>"));
156 }
157
testProcessingInstruction()158 void TestXmlWriter::testProcessingInstruction()
159 {
160 setup();
161 writer->startElement("p", false /*no indent*/);
162 writer->addProcessingInstruction("opendocument foobar");
163 writer->addTextSpan(QString::fromLatin1("foo"));
164 writer->endElement();
165 QCOMPARE(content(), QString("<p><?opendocument foobar?>foo</p>"));
166 }
167
testAddManifestEntry()168 void TestXmlWriter::testAddManifestEntry()
169 {
170 setup();
171 writer->addManifestEntry(QString::fromLatin1("foo/bar/blah"), QString::fromLatin1("mime/type"));
172 QCOMPARE(content(), QString("<manifest:file-entry manifest:media-type=\"mime/type\" "
173 "manifest:full-path=\"foo/bar/blah\"/>"));
174 }
175
176
testEscapingLongString()177 void TestXmlWriter::testEscapingLongString()
178 {
179 int sz = 15000; // must be more than KoXmlWriter::s_escapeBufferLen
180 QString x(sz);
181 x.fill('x', sz);
182 x += '&';
183 setup();
184
185 writer->startElement("test");
186 writer->addAttribute("a", x);
187 writer->endElement();
188
189 QString expected = "<test a=\"";
190 expected += x + "amp;\"/>";
191 QCOMPARE(content(), QString(expected));
192 }
193
testEscalingLongString2()194 void TestXmlWriter::testEscalingLongString2()
195 {
196 QString longPath;
197 for (uint i = 0 ; i < 1000 ; ++i)
198 longPath += QString::fromLatin1("M10 10L20 20 ");
199 setup();
200 writer->startElement("test");
201 writer->addAttribute("a", longPath);
202 writer->endElement();
203 QString expected = "<test a=\"";
204 expected += longPath.toUtf8() + "\"/>";
205 QCOMPARE(content(), expected);
206
207 }
208
testConfig()209 void TestXmlWriter::testConfig()
210 {
211 setup();
212 const bool val = true;
213 const int num = 1;
214 const qreal numdouble = 5.0;
215 writer->addConfigItem(QString::fromLatin1("TestConfigBool"), val);
216 writer->addConfigItem(QString::fromLatin1("TestConfigInt"), num);
217 writer->addConfigItem(QString::fromLatin1("TestConfigDouble"), numdouble);
218 QCOMPARE(content(), QString("<config:config-item config:name=\"TestConfigBool\""
219 " config:type=\"boolean\">true</config:config-item>\n"
220 " <config:config-item config:name=\"TestConfigInt\" config:type=\"int\">1</config:config-item>\n"
221 " <config:config-item config:name=\"TestConfigDouble\" config:type=\"double\">5</config:config-item>"));
222 }
223
224 static const int NumParagraphs = 30000;
225
speedTest()226 void TestXmlWriter::speedTest()
227 {
228 QTime time;
229 time.start();
230 QString paragText = QString::fromUtf8("This is the text of the paragraph. I'm including a euro sign to test encoding issues: €");
231 QString styleName = "Heading 1";
232
233 QFile out(QString::fromLatin1("out5.xml"));
234 if (out.open(QIODevice::WriteOnly)) {
235 KoXmlWriter writer(&out);
236 writer.startDocument("rootelem");
237 writer.startElement("rootelem");
238 for (int i = 0 ; i < NumParagraphs ; ++i) {
239 writer.startElement("paragraph");
240 writer.addAttribute("text:style-name", styleName);
241 writer.addTextNode(paragText);
242 writer.endElement();
243 }
244 writer.endElement();
245 writer.endDocument();
246 }
247 out.close();
248 out.remove();
249 qDebug("writing %i XML elements using KoXmlWriter: %i ms", NumParagraphs, time.elapsed());
250 // TODO we might want to convert this into a QBenchmark test
251 }
252
253 QTEST_GUILESS_MAIN(TestXmlWriter)
254 #include <TestXmlWriter.moc>
255
256