1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#include <QtXmlPatterns/QXmlNamePool>
33#include <QtXmlPatterns/QXmlName>
34
35/*!
36 \class tst_QXmlName
37 \internal
38 \since 4.4
39 \brief Tests class QXmlName.
40
41 This test is not intended for testing the engine, but the functionality specific
42 to the QXmlName class.
43
44 In other words, if you have an engine bug; don't add it here because it won't be
45 tested properly. Instead add it to the test suite.
46
47 */
48class tst_QXmlName : public QObject
49{
50 Q_OBJECT
51
52private Q_SLOTS:
53 void defaultConstructor() const;
54 void argumentConstructor() const;
55 void argumentConstructor_data() const;
56 void argumentConstructorDefaultArguments() const;
57 void equalnessoperator() const;
58 void inequalnessoperator() const;
59
60 void isNull() const;
61 void operatorEqual() const;
62 void operatorEqual_data() const;
63 void operatorNotEqual() const;
64 void operatorNotEqual_data() const;
65 void toClarkName() const;
66 void toClarkName_data() const;
67 void constCorrectness() const;
68 void qHash() const;
69 void objectSize() const;
70 void withinQVariant() const;
71 void typeWithinQVariant() const;
72 void isNCName() const;
73 void isNCName_data() const;
74 void isNCNameSignature() const;
75 void fromClarkName() const;
76 void fromClarkName_data() const;
77 void fromClarkNameSignature() const;
78};
79
80void tst_QXmlName::defaultConstructor() const
81{
82 /* Allocate instance in different orders. */
83 {
84 QXmlName name;
85 }
86
87 {
88 QXmlName name1;
89 QXmlName name2;
90 QXmlName name3;
91 }
92}
93
94Q_DECLARE_METATYPE(QXmlNamePool)
95void tst_QXmlName::argumentConstructor() const
96{
97 QFETCH(QString, namespaceURI);
98 QFETCH(QString, localName);
99 QFETCH(QString, prefix);
100 QFETCH(QXmlNamePool, namePool);
101
102 const QXmlName name(namePool, localName, namespaceURI, prefix);
103
104 QCOMPARE(name.namespaceUri(namePool), namespaceURI);
105 QCOMPARE(name.localName(namePool), localName);
106 QCOMPARE(name.prefix(namePool), prefix);
107}
108
109/*!
110 \internal
111
112 Below we use the same QXmlNamePool instance. This means the same name pool
113 is used.
114 */
115void tst_QXmlName::argumentConstructor_data() const
116{
117 QTest::addColumn<QString>(name: "namespaceURI");
118 QTest::addColumn<QString>(name: "localName");
119 QTest::addColumn<QString>(name: "prefix");
120 QTest::addColumn<QXmlNamePool>(name: "namePool");
121
122 QXmlNamePool namePool;
123 QTest::newRow(dataTag: "Basic test")
124 << QString::fromLatin1(str: "http://example.com/Namespace1")
125 << QString::fromLatin1(str: "localName1")
126 << QString::fromLatin1(str: "prefix1")
127 << namePool;
128
129 QTest::newRow(dataTag: "Same namespace & prefix as before, different local name.")
130 << QString::fromLatin1(str: "http://example.com/Namespace1")
131 << QString::fromLatin1(str: "localName2")
132 << QString::fromLatin1(str: "prefix1")
133 << namePool;
134
135 QTest::newRow(dataTag: "Same namespace & local name as before, different prefix.")
136 << QString::fromLatin1(str: "http://example.com/Namespace1")
137 << QString::fromLatin1(str: "localName2")
138 << QString::fromLatin1(str: "prefix2")
139 << namePool;
140
141 QTest::newRow(dataTag: "No prefix")
142 << QString::fromLatin1(str: "http://example.com/Namespace2")
143 << QString::fromLatin1(str: "localName3")
144 << QString()
145 << namePool;
146}
147
148/*!
149 Ensure that the three last arguments have default values, and that they are null strings.
150 */
151void tst_QXmlName::argumentConstructorDefaultArguments() const
152{
153 QXmlNamePool np;
154 const QXmlName n1(np, QLatin1String("localName"));
155 const QXmlName n2(np, QLatin1String("localName"), QString(), QString());
156
157 QCOMPARE(n1, n2);
158 QCOMPARE(n1.toClarkName(np), QString::fromLatin1("localName"));
159}
160
161void tst_QXmlName::equalnessoperator() const
162{
163 const QXmlName o1;
164 const QXmlName o2;
165 o1 == o2;
166 // TODO
167}
168
169void tst_QXmlName::inequalnessoperator() const
170{
171 const QXmlName o1;
172 const QXmlName o2;
173 o1 != o2;
174 // TODO
175}
176
177void tst_QXmlName::isNull() const
178{
179 /* Check default value. */
180 QXmlName name;
181 QVERIFY(name.isNull());
182}
183
184void tst_QXmlName::operatorEqual() const
185{
186 QFETCH(QXmlName, op1);
187 QFETCH(QXmlName, op2);
188 QFETCH(bool, expected);
189
190 QCOMPARE(op1 == op2, expected);
191}
192
193void tst_QXmlName::operatorEqual_data() const
194{
195 QTest::addColumn<QXmlName>(name: "op1");
196 QTest::addColumn<QXmlName>(name: "op2");
197 QTest::addColumn<bool>(name: "expected");
198
199 QXmlNamePool namePool;
200 const QXmlName n1(namePool, QString::fromLatin1(str: "localName1"),
201 QString::fromLatin1(str: "http://example.com/Namespace1"),
202 QString::fromLatin1(str: "prefix1"));
203
204 const QXmlName n2(namePool, QString::fromLatin1(str: "localName2"),
205 QString::fromLatin1(str: "http://example.com/Namespace1"),
206 QString::fromLatin1(str: "prefix1"));
207
208 const QXmlName n3(namePool, QString::fromLatin1(str: "localName2"),
209 QString::fromLatin1(str: "http://example.com/Namespace1"),
210 QString::fromLatin1(str: "prefix2"));
211
212 const QXmlName n4(namePool, QString::fromLatin1(str: "localName3"),
213 QString::fromLatin1(str: "http://example.com/Namespace2"));
214
215 const QXmlName n5(namePool, QString::fromLatin1(str: "localName4"),
216 QString::fromLatin1(str: "http://example.com/Namespace2"));
217
218 const QXmlName n6(namePool, QString::fromLatin1(str: "localName4"),
219 QString::fromLatin1(str: "http://example.com/Namespace2"),
220 QString::fromLatin1(str: "prefix3"));
221
222 const QXmlName n7(namePool, QString::fromLatin1(str: "localName2"),
223 QString::fromLatin1(str: "http://example.com/Namespace2"),
224 QString::fromLatin1(str: "prefix3"));
225
226 QTest::newRow(qPrintable(n1.toClarkName(namePool)))
227 << n1
228 << n1
229 << true;
230
231 QTest::newRow(qPrintable(n2.toClarkName(namePool)))
232 << n2
233 << n2
234 << true;
235
236 QTest::newRow(qPrintable(n3.toClarkName(namePool)))
237 << n3
238 << n3
239 << true;
240
241 QTest::newRow(qPrintable(n4.toClarkName(namePool)))
242 << n4
243 << n4
244 << true;
245
246 QTest::newRow(qPrintable(n5.toClarkName(namePool)))
247 << n5
248 << n5
249 << true;
250
251 QTest::newRow(qPrintable(n6.toClarkName(namePool)))
252 << n6
253 << n6
254 << true;
255
256 QTest::newRow(qPrintable(n7.toClarkName(namePool)))
257 << n7
258 << n7
259 << true;
260
261 QTest::newRow(dataTag: "Prefix differs")
262 << n2
263 << n3
264 << true;
265
266 QTest::newRow(dataTag: "No prefix vs. prefix")
267 << n5
268 << n6
269 << true;
270
271 QTest::newRow(dataTag: "Local name differs")
272 << n1
273 << n2
274 << false;
275
276 QTest::newRow(dataTag: "Namespace differs")
277 << n2
278 << n7
279 << false;
280}
281
282void tst_QXmlName::operatorNotEqual() const
283{
284 QFETCH(QXmlName, op1);
285 QFETCH(QXmlName, op2);
286 QFETCH(bool, expected);
287
288 QCOMPARE(op1 != op2, !expected);
289}
290
291void tst_QXmlName::operatorNotEqual_data() const
292{
293 operatorEqual_data();
294}
295
296/*!
297 Check that functions have the correct const qualification.
298 */
299void tst_QXmlName::constCorrectness() const
300{
301 const QXmlName name;
302
303 /* isNull() */
304 QVERIFY(name.isNull());
305
306 /* operator==() */
307 QVERIFY(name == name);
308
309 /* operator!=() */
310 QVERIFY(!(name != name));
311
312 QXmlNamePool namePool;
313 const QXmlName name2(namePool, QLatin1String("localName"), QLatin1String("http://example.com/"), QLatin1String("prefix"));
314
315 /* namespaceUri(). */
316 QCOMPARE(name2.namespaceUri(namePool), QLatin1String("http://example.com/"));
317
318 /* localName(). */
319 QCOMPARE(name2.localName(namePool), QLatin1String("localName"));
320
321 /* prefix(). */
322 QCOMPARE(name2.prefix(namePool), QLatin1String("prefix"));
323
324 /* toClarkname(). */
325 QCOMPARE(name2.toClarkName(namePool), QLatin1String("{http://example.com/}prefix:localName"));
326}
327
328void tst_QXmlName::qHash() const
329{
330 /* Just call it, so we know it exist and that we don't trigger undefined
331 * behavior. We can't test the return value, since it's opaque. */
332 QXmlName name;
333 ::qHash(name);
334}
335
336void tst_QXmlName::objectSize() const
337{
338 QVERIFY2(sizeof(QXmlName) == sizeof(qint64), "QXmlName should have at least a d-pointer.");
339}
340
341void tst_QXmlName::toClarkName() const
342{
343 QFETCH(QString, produced);
344 QFETCH(QString, expected);
345
346 QCOMPARE(produced, expected);
347}
348
349void tst_QXmlName::toClarkName_data() const
350{
351 QTest::addColumn<QString>(name: "produced");
352 QTest::addColumn<QString>(name: "expected");
353
354 QXmlNamePool np;
355
356 /* A null QXmlName. */
357 {
358 const QXmlName n;
359 QTest::newRow(dataTag: "") << n.toClarkName(query: np)
360 << QString::fromLatin1(str: "QXmlName(null)");
361 }
362
363 {
364 const QXmlName n(np, QLatin1String("localName"));
365 QTest::newRow(dataTag: "") << n.toClarkName(query: np)
366 << QString::fromLatin1(str: "localName");
367 }
368
369 /* Local name with namespace URI, empty prefix. */
370 {
371 const QXmlName n(np, QLatin1String("localName"),
372 QLatin1String("http://example.com/"));
373 QTest::newRow(dataTag: "") << n.toClarkName(query: np)
374 << QString::fromLatin1(str: "{http://example.com/}localName");
375 }
376
377 /* Local name with namespace URI and prefix. */
378 {
379 const QXmlName n(np, QLatin1String("localName"),
380 QLatin1String("http://example.com/"),
381 QLatin1String("p"));
382 QTest::newRow(dataTag: "") << n.toClarkName(query: np)
383 << QString::fromLatin1(str: "{http://example.com/}p:localName");
384 }
385}
386
387/*!
388 Check that QXmlName can be used inside QVariant.
389 */
390void tst_QXmlName::withinQVariant() const
391{
392 auto value = QVariant::fromValue(value: QXmlName());
393}
394
395/*!
396 Check that the user type of QXmlName holds.
397 */
398void tst_QXmlName::typeWithinQVariant() const
399{
400 const int qxmlNameType = QVariant::fromValue(value: QXmlName()).userType();
401
402 const auto value = QVariant::fromValue(value: QXmlName());
403
404 QCOMPARE(value.userType(), qxmlNameType);
405}
406
407/*!
408 We don't do full testing here. Don't have the resources for it. We simply assume
409 we use a code path which is fully tested elsewhere.
410 */
411void tst_QXmlName::isNCName() const
412{
413 QFETCH(QString, input);
414 QFETCH(bool, expectedValidity);
415
416 QCOMPARE(QXmlName::isNCName(input), expectedValidity);
417}
418
419void tst_QXmlName::isNCName_data() const
420{
421 QTest::addColumn<QString>(name: "input");
422 QTest::addColumn<bool>(name: "expectedValidity");
423
424 QTest::newRow(dataTag: "empty string")
425 << QString()
426 << false;
427
428 QTest::newRow(dataTag: "A number")
429 << QString::fromLatin1(str: "1")
430 << false;
431
432 QTest::newRow(dataTag: "Simple valid string")
433 << QString::fromLatin1(str: "abc")
434 << true;
435
436 QTest::newRow(dataTag: "Simple valid string")
437 << QString::fromLatin1(str: "abc.123")
438 << true;
439}
440
441void tst_QXmlName::isNCNameSignature() const
442{
443 const QString constQString;
444
445 /* Verify that we can take a const QString. */
446 QXmlName::isNCName(candidate: constQString);
447
448 /* Verify that we can take a temporary QString. */
449 QXmlName::isNCName(candidate: QString());
450}
451
452void tst_QXmlName::fromClarkName() const
453{
454 QFETCH(QString, input);
455 QFETCH(QXmlName, expected);
456 QFETCH(QXmlNamePool, namePool);
457
458 QCOMPARE(QXmlName::fromClarkName(input, namePool), expected);
459}
460
461void tst_QXmlName::fromClarkName_data() const
462{
463 QTest::addColumn<QString>(name: "input");
464 QTest::addColumn<QXmlName>(name: "expected");
465 QTest::addColumn<QXmlNamePool>(name: "namePool");
466
467 QXmlNamePool np;
468
469 QTest::newRow(dataTag: "A null string")
470 << QString()
471 << QXmlName()
472 << np;
473
474 QTest::newRow(dataTag: "An empty string")
475 << QString(QLatin1String(""))
476 << QXmlName()
477 << np;
478
479 QTest::newRow(dataTag: "A single local name")
480 << QString(QLatin1String("foo"))
481 << QXmlName(np, QLatin1String("foo"))
482 << np;
483
484 QTest::newRow(dataTag: "Has prefix, but no namespace, that's invalid")
485 << QString(QLatin1String("prefix:foo"))
486 << QXmlName()
487 << np;
488
489 QTest::newRow(dataTag: "Namespace, local name, no prefix")
490 << QString(QLatin1String("{def}abc"))
491 << QXmlName(np, QLatin1String("abc"), QLatin1String("def"))
492 << np;
493
494 QTest::newRow(dataTag: "Namespace, local name, prefix")
495 << QString(QLatin1String("{def}p:abc"))
496 << QXmlName(np, QLatin1String("abc"), QLatin1String("def"), QLatin1String("p"))
497 << np;
498
499 QTest::newRow(dataTag: "Namespace, local name, prefix syntax error")
500 << QString(QLatin1String("{def}:abc"))
501 << QXmlName()
502 << np;
503
504 QTest::newRow(dataTag: "Namespace, local name syntax error, prefix")
505 << QString(QLatin1String("{def}p:"))
506 << QXmlName()
507 << np;
508
509 QTest::newRow(dataTag: "Only local name which is invalid")
510 << QString(QLatin1String(":::"))
511 << QXmlName()
512 << np;
513
514 QTest::newRow(dataTag: "Namespace, invalid local name")
515 << QString(QLatin1String("{def}a|bc"))
516 << QXmlName()
517 << np;
518
519 QTest::newRow(dataTag: "Namespace, local name, invalid prefix")
520 << QString(QLatin1String("{def}a|b:c"))
521 << QXmlName()
522 << np;
523
524 QTest::newRow(dataTag: "A single left curly, invalid")
525 << QString(QLatin1String("{"))
526 << QXmlName()
527 << np;
528
529 QTest::newRow(dataTag: "A single left curly, invalid")
530 << QString(QLatin1String("{aaswd"))
531 << QXmlName()
532 << np;
533}
534
535void tst_QXmlName::fromClarkNameSignature() const
536{
537 /* We should take const references. */
538 const QXmlNamePool np;
539 const QString in;
540
541 QXmlName::fromClarkName(clarkName: in, namePool: np);
542}
543
544QTEST_MAIN(tst_QXmlName)
545
546#include "tst_qxmlname.moc"
547
548// vim: et:ts=4:sw=4:sts=4
549

source code of qtxmlpatterns/tests/auto/qxmlname/tst_qxmlname.cpp