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 | */ |
48 | class tst_QXmlName : public QObject |
49 | { |
50 | Q_OBJECT |
51 | |
52 | private 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 | |
80 | void 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 | |
94 | Q_DECLARE_METATYPE(QXmlNamePool) |
95 | void 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 | */ |
115 | void 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 | */ |
151 | void 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 | |
161 | void tst_QXmlName::equalnessoperator() const |
162 | { |
163 | const QXmlName o1; |
164 | const QXmlName o2; |
165 | o1 == o2; |
166 | // TODO |
167 | } |
168 | |
169 | void tst_QXmlName::inequalnessoperator() const |
170 | { |
171 | const QXmlName o1; |
172 | const QXmlName o2; |
173 | o1 != o2; |
174 | // TODO |
175 | } |
176 | |
177 | void tst_QXmlName::isNull() const |
178 | { |
179 | /* Check default value. */ |
180 | QXmlName name; |
181 | QVERIFY(name.isNull()); |
182 | } |
183 | |
184 | void 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 | |
193 | void 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 | |
282 | void 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 | |
291 | void tst_QXmlName::operatorNotEqual_data() const |
292 | { |
293 | operatorEqual_data(); |
294 | } |
295 | |
296 | /*! |
297 | Check that functions have the correct const qualification. |
298 | */ |
299 | void 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 | |
328 | void 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 | |
336 | void tst_QXmlName::objectSize() const |
337 | { |
338 | QVERIFY2(sizeof(QXmlName) == sizeof(qint64), "QXmlName should have at least a d-pointer." ); |
339 | } |
340 | |
341 | void tst_QXmlName::toClarkName() const |
342 | { |
343 | QFETCH(QString, produced); |
344 | QFETCH(QString, expected); |
345 | |
346 | QCOMPARE(produced, expected); |
347 | } |
348 | |
349 | void 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 | */ |
390 | void 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 | */ |
398 | void 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 | */ |
411 | void tst_QXmlName::isNCName() const |
412 | { |
413 | QFETCH(QString, input); |
414 | QFETCH(bool, expectedValidity); |
415 | |
416 | QCOMPARE(QXmlName::isNCName(input), expectedValidity); |
417 | } |
418 | |
419 | void 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 | |
441 | void 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 | |
452 | void 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 | |
461 | void 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 | |
535 | void 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 | |
544 | QTEST_MAIN(tst_QXmlName) |
545 | |
546 | #include "tst_qxmlname.moc" |
547 | |
548 | // vim: et:ts=4:sw=4:sts=4 |
549 | |