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:LGPL$
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 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 
43 #include <QtTest/QtTest>
44 #include <QtCore/QDebug>
45 
46 #include <qcoreapplication.h>
47 
48 #include <qfileinfo.h>
49 #include <qurl.h>
50 #include <qtextcodec.h>
51 #include <qmap.h>
52 #include "private/qtldurl_p.h"
53 
54 // For testsuites
55 #define IDNA_ACE_PREFIX "xn--"
56 #define IDNA_SUCCESS 1
57 #define STRINGPREP_NO_UNASSIGNED 1
58 #define STRINGPREP_CONTAINS_UNASSIGNED 2
59 #define STRINGPREP_CONTAINS_PROHIBITED 3
60 #define STRINGPREP_BIDI_BOTH_L_AND_RAL 4
61 #define STRINGPREP_BIDI_LEADTRAIL_NOT_RAL 5
62 
63 struct ushortarray {
ushortarrayushortarray64     ushortarray(unsigned short *array = 0)
65     {
66         if (array)
67             memcpy(points, array, sizeof(points));
68     }
69 
70     unsigned short points[100];
71 };
72 
73 Q_DECLARE_METATYPE(ushortarray)
74 Q_DECLARE_METATYPE(QUrl::FormattingOptions)
75 
76 //TESTED_CLASS=
77 //TESTED_FILES=
78 
79 class tst_QUrl : public QObject
80 {
81     Q_OBJECT
82 
83 public:
84     tst_QUrl();
85     virtual ~tst_QUrl();
86 
87 
88 public slots:
89     void init();
90     void cleanup();
91 private slots:
92     void effectiveTLDs_data();
93     void effectiveTLDs();
94     void getSetCheck();
95     void constructing();
96     void assignment();
97     void comparison();
98     void copying();
99     void setUrl();
100     void i18n_data();
101     void i18n();
102     void punycode_data();
103     void punycode();
104     void resolving_data();
105     void resolving();
106     void toString_data();
107     void toString();
108     void toString_constructed_data();
109     void toString_constructed();
110     void isParentOf_data();
111     void isParentOf();
112     void toLocalFile_data();
113     void toLocalFile();
114     void fromLocalFile_data();
115     void fromLocalFile();
116     void relative();
117     void compat_legacy();
118     void compat_constructor_01_data();
119     void compat_constructor_01();
120     void compat_constructor_02_data();
121     void compat_constructor_02();
122     void compat_constructor_03_data();
123     void compat_constructor_03();
124     void compat_isValid_01_data();
125     void compat_isValid_01();
126     void compat_isValid_02_data();
127     void compat_isValid_02();
128     void compat_path_data();
129     void compat_path();
130     void compat_fileName_data();
131     void compat_fileName();
132     void compat_decode_data();
133     void compat_decode();
134     void compat_encode_data();
135     void compat_encode();
136     void percentEncoding_data();
137     void percentEncoding();
138     void swap();
139     void symmetry();
140     void ipv6_data();
141     void ipv6();
142     void ipv6_2_data();
143     void ipv6_2();
144     void moreIpv6();
145     void toPercentEncoding_data();
146     void toPercentEncoding();
147     void isRelative_data();
148     void isRelative();
149     void queryItems();
150     void hasQuery_data();
151     void hasQuery();
152     void hasQueryItem_data();
153     void hasQueryItem();
154     void nameprep();
155     void isValid();
156     void schemeValidator_data();
157     void schemeValidator();
158     void invalidSchemeValidator();
159     void tolerantParser();
160     void correctEncodedMistakes_data();
161     void correctEncodedMistakes();
162     void correctDecodedMistakes_data();
163     void correctDecodedMistakes();
164     void idna_testsuite_data();
165     void idna_testsuite();
166     void nameprep_testsuite_data();
167     void nameprep_testsuite();
168     void nameprep_highcodes_data();
169     void nameprep_highcodes();
170     void ace_testsuite_data();
171     void ace_testsuite();
172     void std3violations_data();
173     void std3violations();
174     void std3deviations_data();
175     void std3deviations();
176     void tldRestrictions_data();
177     void tldRestrictions();
178     void emptyQueryOrFragment();
179     void hasFragment_data();
180     void hasFragment();
181     void setEncodedFragment_data();
182     void setEncodedFragment();
183     void fromEncoded();
184     void stripTrailingSlash();
185     void hosts_data();
186     void hosts();
187     void setPort();
188     void toEncoded_data();
189     void toEncoded();
190     void setAuthority_data();
191     void setAuthority();
192     void setEmptyAuthority_data();
193     void setEmptyAuthority();
194     void errorString();
195     void clear();
196     void resolvedWithAbsoluteSchemes() const;
197     void resolvedWithAbsoluteSchemes_data() const;
198     void binaryData_data();
199     void binaryData();
200     void fromUserInput_data();
201     void fromUserInput();
202     void task_199967();
203     void task_240612();
204     void taskQTBUG_6962();
205     void taskQTBUG_8701();
206     void removeAllEncodedQueryItems_data();
207     void removeAllEncodedQueryItems();
208     void detach();
209     void testThreading();
210 
211 private:
212     void testThreadingHelper();
213 };
214 
215 // Testing get/set functions
getSetCheck()216 void tst_QUrl::getSetCheck()
217 {
218     QUrl obj1;
219     // int QUrl::port()
220     // void QUrl::setPort(int)
221     obj1.setPort(0);
222     QCOMPARE(0, obj1.port());
223 
224     QTest::ignoreMessage(QtWarningMsg, "QUrl::setPort: Out of range");
225     obj1.setPort(INT_MIN);
226     QCOMPARE(-1, obj1.port()); // Out of range, -1
227 
228     QTest::ignoreMessage(QtWarningMsg, "QUrl::setPort: Out of range");
229     obj1.setPort(INT_MAX);
230     QCOMPARE(-1, obj1.port()); // Out of range, -1
231 
232     obj1.setPort(1234);
233     QCOMPARE(1234, obj1.port());
234 
235     // static QStringList QUrl::idnWhitelist()
236     // static void QUrl::setIdnWhitelist(QStringList)
237     QStringList original = QUrl::idnWhitelist(); // save for later
238 
239     QUrl::setIdnWhitelist(QStringList());
240     QCOMPARE(QUrl::idnWhitelist(), QStringList());
241 
242     QStringList norway; norway << "no";
243     QUrl::setIdnWhitelist(norway);
244     QCOMPARE(QUrl::idnWhitelist(), norway);
245 
246     QStringList modified = original;
247     modified << "foo";
248     QUrl::setIdnWhitelist(modified);
249     QCOMPARE(QUrl::idnWhitelist(), modified);
250 
251     // reset to the original
252     QUrl::setIdnWhitelist(original);
253     QCOMPARE(QUrl::idnWhitelist(), original);
254 }
255 
tst_QUrl()256 tst_QUrl::tst_QUrl()
257 {
258 }
259 
~tst_QUrl()260 tst_QUrl::~tst_QUrl()
261 {
262 
263 }
264 
init()265 void tst_QUrl::init()
266 {
267 }
268 
cleanup()269 void tst_QUrl::cleanup()
270 {
271 }
272 
constructing()273 void tst_QUrl::constructing()
274 {
275     QUrl url;
276     QVERIFY(!url.isValid());
277     QVERIFY(url.isEmpty());
278     QCOMPARE(url.port(), -1);
279     QCOMPARE(url.toString(), QString());
280     QVERIFY(url == url);
281     QVERIFY(!(url < url));
282 
283     QList<QPair<QString, QString> > query;
284     query += qMakePair(QString("type"), QString("login"));
285     query += qMakePair(QString("name"), QString("�ge nissemannsen"));
286     query += qMakePair(QString("ole&du"), QString("anne+j�rgen=sant"));
287     query += qMakePair(QString("prosent"), QString("%"));
288     url.setQueryItems(query);
289     QVERIFY(!url.isEmpty());
290 
291     QCOMPARE(url.encodedQuery().constData(),
292             QByteArray("type=login&name=%C3%A5ge%20nissemannsen&ole%26du="
293                        "anne+j%C3%B8rgen%3Dsant&prosent=%25").constData());
294 
295     url.setQueryDelimiters('>', '/');
296     url.setQueryItems(query);
297 
298     QCOMPARE(url.encodedQuery(),
299             QByteArray("type>login/name>%C3%A5ge%20nissemannsen/ole&du>"
300                        "anne+j%C3%B8rgen=sant/prosent>%25"));
301 
302     url.setFragment(QString::fromLatin1("top"));
303     QCOMPARE(url.fragment(), QString::fromLatin1("top"));
304 
305     url.setScheme("http");
306     url.setHost("qt.nokia.com");
307 
308     QCOMPARE(url.toString(),
309             QString::fromLatin1("http://qt.nokia.com?type>login/name>�ge nissemannsen"
310                           "/ole&du>anne+j�rgen=sant/prosent>%#top"));
311 
312     QUrl justHost("qt.nokia.com");
313     QVERIFY(!justHost.isEmpty());
314     QVERIFY(justHost.host().isEmpty());
315     QCOMPARE(justHost.path(), QString::fromLatin1("qt.nokia.com"));
316 
317     QUrl hostWithSlashes("//qt.nokia.com");
318     QVERIFY(hostWithSlashes.path().isEmpty());
319     QCOMPARE(hostWithSlashes.host(), QString::fromLatin1("qt.nokia.com"));
320 
321 
322     QUrl withHashInPath;
323     withHashInPath.setPath(QString::fromLatin1("hi#mum.txt"));
324     QCOMPARE(withHashInPath.path(), QString::fromLatin1("hi#mum.txt"));
325     QCOMPARE(withHashInPath.toEncoded(), QByteArray("hi%23mum.txt"));
326     QUrl fromHashInPath = QUrl::fromEncoded(withHashInPath.toEncoded());
327     QVERIFY(withHashInPath == fromHashInPath);
328 
329 
330     QUrl buildUNC;
331     buildUNC.setScheme(QString::fromLatin1("file"));
332     buildUNC.setHost(QString::fromLatin1("somehost"));
333     buildUNC.setPath(QString::fromLatin1("somepath"));
334     QCOMPARE(buildUNC.toLocalFile(), QString::fromLatin1("//somehost/somepath"));
335     buildUNC.toEncoded();
336     QVERIFY(!buildUNC.isEmpty());
337 }
338 
assignment()339 void tst_QUrl::assignment()
340 {
341     QUrl url("http://qt.nokia.com/");
342     QVERIFY(url.isValid());
343 
344     QUrl copy;
345     copy = url;
346 
347     QVERIFY(url == copy);
348 }
349 
comparison()350 void tst_QUrl::comparison()
351 {
352     QUrl url1("http://qt.nokia.com/");
353     QVERIFY(url1.isValid());
354 
355     QUrl url2("http://qt.nokia.com/");
356     QVERIFY(url2.isValid());
357 
358     QVERIFY(url1 == url2);
359     QVERIFY(!(url1 < url2));
360     QVERIFY(!(url2 < url1));
361 
362     // 6.2.2 Syntax-based Normalization
363     QUrl url3 = QUrl::fromEncoded("example://a/b/c/%7Bfoo%7D");
364     QUrl url4 = QUrl::fromEncoded("eXAMPLE://a/./b/../b/%63/%7bfoo%7d");
365     QVERIFY(url3 == url4);
366 
367     // 6.2.2.1 Make sure hexdecimal characters in percent encoding are
368     // treated case-insensitively
369     QUrl url5;
370     url5.setEncodedQuery("a=%2a");
371     QUrl url6;
372     url6.setEncodedQuery("a=%2A");
373     QVERIFY(url5 == url6);
374 
375     // ensure that encoded characters in the query do not match
376     QUrl url7;
377     url7.setEncodedQuery("a=%63");
378     QUrl url8;
379     url8.setEncodedQuery("a=c");
380     QVERIFY(url7 != url8);
381     QVERIFY(url7 < url8);
382 }
383 
copying()384 void tst_QUrl::copying()
385 {
386     QUrl url("http://qt.nokia.com/");
387     QVERIFY(url.isValid());
388 
389     QUrl copy(url);
390 
391     QVERIFY(url == copy);
392 }
393 
setUrl()394 void tst_QUrl::setUrl()
395 {
396     {
397         QUrl url("http://0.foo.com");
398         QVERIFY(url.isValid());
399         QCOMPARE(url.scheme(), QString::fromLatin1("http"));
400         QCOMPARE(url.path(), QString());
401         QCOMPARE(url.host(), QString::fromLatin1("0.foo.com"));
402     }
403 
404     {
405         QUrl url("file:/");
406         QVERIFY(url.isValid());
407         QCOMPARE(url.scheme(), QString::fromLatin1("file"));
408         QCOMPARE(url.path(), QString::fromLatin1("/"));
409         QVERIFY(url.encodedQuery().isEmpty());
410         QVERIFY(url.userInfo().isEmpty());
411         QVERIFY(url.authority().isEmpty());
412         QVERIFY(url.fragment().isEmpty());
413         QCOMPARE(url.port(), -1);
414     }
415 
416     {
417         QUrl url("hTTp://www.foo.bar:80");
418         QVERIFY(url.isValid());
419         QCOMPARE(url.scheme(), QString::fromLatin1("hTTp"));
420         QCOMPARE(url.path(), QString());
421         QVERIFY(url.encodedQuery().isEmpty());
422         QVERIFY(url.userInfo().isEmpty());
423         QVERIFY(url.fragment().isEmpty());
424         QCOMPARE(url.host(), QString::fromLatin1("www.foo.bar"));
425         QCOMPARE(url.authority(), QString::fromLatin1("www.foo.bar:80"));
426         QCOMPARE(url.port(), 80);
427 
428         QUrl url2("//www1.foo.bar");
429         QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("hTTp://www1.foo.bar"));
430     }
431 
432     {
433         QUrl url("http://user:pass@[56::56:56:56:127.0.0.1]:99");
434         QVERIFY(url.isValid());
435         QCOMPARE(url.scheme(), QString::fromLatin1("http"));
436         QCOMPARE(url.path(), QString());
437         QVERIFY(url.encodedQuery().isEmpty());
438         QCOMPARE(url.userInfo(), QString::fromLatin1("user:pass"));
439         QVERIFY(url.fragment().isEmpty());
440         QCOMPARE(url.host(), QString::fromLatin1("56::56:56:56:127.0.0.1"));
441         QCOMPARE(url.authority(), QString::fromLatin1("user:pass@[56::56:56:56:127.0.0.1]:99"));
442         QCOMPARE(url.port(), 99);
443     }
444 
445     {
446         QUrl url("http://www.foo.bar");
447         QVERIFY(url.isValid());
448 
449         QUrl url2("/top//test/../test1/file.html");
450         QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("http://www.foo.bar/top//test1/file.html"));
451     }
452 
453     {
454         QUrl url("http://www.foo.bar");
455         QVERIFY(url.isValid());
456 
457         QUrl url2("/top//test/../test1/file.html");
458         QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("http://www.foo.bar/top//test1/file.html"));
459     }
460 
461     {
462         QUrl url("http://www.foo.bar/top//test2/file2.html");
463         QVERIFY(url.isValid());
464 
465         QCOMPARE(url.toString(), QString::fromLatin1("http://www.foo.bar/top//test2/file2.html"));
466     }
467 
468     {
469         QUrl url("http://www.foo.bar/top//test2/file2.html");
470         QVERIFY(url.isValid());
471 
472         QCOMPARE(url.toString(), QString::fromLatin1("http://www.foo.bar/top//test2/file2.html"));
473     }
474 
475     {
476         QUrl url("file:/usr/local/src/kde2/////kdelibs/kio");
477         QVERIFY(url.isValid());
478         QCOMPARE(url.toString(), QString::fromLatin1("file:///usr/local/src/kde2/////kdelibs/kio"));
479     }
480 
481     {
482         QUrl url("http://www.foo.bar");
483         QVERIFY(url.isValid());
484 
485         QUrl url2("mailto:bastian@kde.org");
486         QVERIFY(url2.isValid());
487         QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("mailto:bastian@kde.org"));
488     }
489 
490     {
491         QUrl url("mailto:bastian@kde.org?subject=hello");
492         QCOMPARE(url.toString(), QString::fromLatin1("mailto:bastian@kde.org?subject=hello"));
493     }
494 
495     {
496         QUrl url("file:/usr/local/src/kde2/kdelibs/kio/");
497         QVERIFY(url.isValid());
498 
499         QUrl url2("../../////kdebase/konqueror");
500         QCOMPARE(url.resolved(url2).toString(),
501                 QString::fromLatin1("file:///usr/local/src/kde2/////kdebase/konqueror"));
502     }
503 
504     {
505         QString u1 = "file:/home/dfaure/my#myref";
506         QUrl url = u1;
507         QVERIFY(url.isValid());
508         QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref"));
509         QCOMPARE(url.fragment(), QString::fromLatin1("myref"));
510     }
511 
512     {
513         QString u1 = "file:/home/dfaure/my#myref";
514         QUrl url = u1;
515         QVERIFY(url.isValid());
516 
517         QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref"));
518         QCOMPARE(url.fragment(), QString::fromLatin1("myref"));
519     }
520 
521     {
522         QUrl url("gg:www.kde.org");
523         QVERIFY(url.isValid());
524         QCOMPARE(url.scheme(), QString::fromLatin1("gg"));
525         QVERIFY(url.host().isEmpty());
526         QCOMPARE(url.path(), QString::fromLatin1("www.kde.org"));
527     }
528 
529     {
530         QUrl url("KDE");
531         QVERIFY(url.isValid());
532         QCOMPARE(url.path(), QString::fromLatin1("KDE"));
533         QVERIFY(url.scheme().isEmpty());
534     }
535 
536     {
537         QUrl url("$HOME/.kde/share/config");
538         QVERIFY(url.isValid());
539         QCOMPARE(url.path(), QString::fromLatin1("$HOME/.kde/share/config"));
540         QVERIFY(url.scheme().isEmpty());
541     }
542 
543     {
544         QUrl url("file:/opt/kde2/qt2/doc/html/showimg-main-cpp.html#QObject::connect");
545         QVERIFY(url.isValid());
546         QCOMPARE(url.fragment(), QString::fromLatin1("QObject::connect"));
547     }
548 
549     {
550         QUrl url("file:/opt/kde2/qt2/doc/html/showimg-main-cpp.html#QObject:connect");
551         QVERIFY(url.isValid());
552         QCOMPARE(url.fragment(), QString::fromLatin1("QObject:connect"));
553     }
554 
555     {
556         // suburls
557         QUrl url("file:/home/dfaure/my%20tar%20file.tgz#gzip:/#tar:/#myref");
558         QVERIFY(url.isValid());
559 
560         // or simply 'myref?'
561         QCOMPARE(url.fragment(), QString::fromLatin1("gzip:/#tar:/#myref"));
562     }
563 
564     {
565         QUrl url("error:/?error=14&errText=Unknown%20host%20asdfu.adgi.sdfgoi#http://asdfu.adgi.sdfgoi");
566         QVERIFY(url.isValid());
567         QCOMPARE(url.fragment(), QString::fromLatin1("http://asdfu.adgi.sdfgoi"));
568     }
569 
570     {
571         // suburls
572         QUrl url("file:/home/dfaure/my%20tar%20file.tgz#gzip:/#tar:/");
573         QVERIFY(url.isValid());
574     }
575 
576     {
577         QUrl url("file:/home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cc#");
578         QVERIFY(url.isValid());
579     }
580 
581     {
582         QUrl url("file:/home/dfaure/my%20tar%20file.tgz#gzip:/#tar:/README");
583         QVERIFY(url.isValid());
584         QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my tar file.tgz#gzip:/#tar:/README"));
585     }
586 
587     {
588         QUrl notPretty;
589         notPretty.setEncodedUrl("http://ferret.lmh.ox.ac.uk/%7Ekdecvs/");
590         QVERIFY(notPretty.isValid());
591         QCOMPARE(notPretty.toString(), QString::fromLatin1("http://ferret.lmh.ox.ac.uk/~kdecvs/"));
592 
593         QUrl notPretty2;
594         notPretty2.setEncodedUrl("file:/home/test/directory%20with%20spaces");
595         QVERIFY(notPretty2.isValid());
596         QCOMPARE(notPretty2.toString(), QString::fromLatin1("file:///home/test/directory with spaces"));
597 
598         QUrl notPretty3("fish://foo/%23README%23");
599         QVERIFY(notPretty3.isValid());
600         QCOMPARE(notPretty3.toString(), QString::fromLatin1("fish://foo/%23README%23"));
601 
602         QUrl url15581;
603         url15581.setUrl("http://alain.knaff.linux.lu/bug-reports/kde/spaces in url.html");
604         QCOMPARE(url15581.toString(), QString::fromLatin1("http://alain.knaff.linux.lu/bug-reports/kde/spaces in url.html"));
605         QCOMPARE(url15581.toEncoded().constData(), QByteArray("http://alain.knaff.linux.lu/bug-reports/kde/spaces%20in%20url.html").constData());
606 
607         QUrl url15582("http://alain.knaff.linux.lu/bug-reports/kde/percentage%in%url.html");
608         QCOMPARE(url15582.toString(), QString::fromLatin1("http://alain.knaff.linux.lu/bug-reports/kde/percentage%in%url.html"));
609         QCOMPARE(url15582.toEncoded(), QByteArray("http://alain.knaff.linux.lu/bug-reports/kde/percentage%25in%25url.html"));
610     }
611 
612     {
613         QUrl carsten;
614         carsten.setPath("/home/gis/src/kde/kdelibs/kfile/.#kfiledetailview.cpp.1.18");
615         QCOMPARE(carsten.path(), QString::fromLatin1("/home/gis/src/kde/kdelibs/kfile/.#kfiledetailview.cpp.1.18"));
616 
617         QUrl charles;
618         charles.setPath("/home/charles/foo%20moo");
619         QCOMPARE(charles.path(), QString::fromLatin1("/home/charles/foo%20moo"));
620 
621         QUrl charles2;
622         charles2.setEncodedUrl("file:/home/charles/foo%20moo");
623         QCOMPARE(charles2.path(), QString::fromLatin1("/home/charles/foo moo"));
624     }
625 
626     {
627         QUrl udir;
628         QCOMPARE(udir.toEncoded(), QByteArray());
629         QVERIFY(!udir.isValid());
630 
631         udir = QUrl::fromLocalFile("/home/dfaure/file.txt");
632         QCOMPARE(udir.path(), QString::fromLatin1("/home/dfaure/file.txt"));
633         QCOMPARE(udir.toEncoded(), QByteArray("file:///home/dfaure/file.txt"));
634     }
635 
636     {
637         QUrl url;
638         url.setUrl("hello.com#?");
639         QVERIFY(url.isValid());
640         url.setUrl("hello.com");
641         QVERIFY(!url.toString().contains(QLatin1Char('#')));
642         QVERIFY(!url.toString().contains(QLatin1Char('?')));
643     }
644 
645     {
646         QUrl url;
647         url.setUrl("http://1.2.3.4.example.com");
648         QVERIFY(url.isValid());
649         QCOMPARE(url.scheme(), QString("http"));
650         QCOMPARE(url.host(), QString("1.2.3.4.example.com"));
651     }
652 
653     {
654         QUrl url;
655         url.setUrl("http://1.2.3.4");
656         QVERIFY(url.isValid());
657         QCOMPARE(url.scheme(), QString("http"));
658         QCOMPARE(url.host(), QString("1.2.3.4"));
659     }
660     {
661         QUrl url;
662         url.setUrl("http://1.2.3.4/");
663         QVERIFY(url.isValid());
664         QCOMPARE(url.scheme(), QString("http"));
665         QCOMPARE(url.host(), QString("1.2.3.4"));
666         QCOMPARE(url.path(), QString("/"));
667     }
668     {
669         QUrl url;
670         url.setUrl("http://1.2.3.4?foo");
671         QVERIFY(url.isValid());
672         QCOMPARE(url.scheme(), QString("http"));
673         QCOMPARE(url.host(), QString("1.2.3.4"));
674         QCOMPARE(url.encodedQuery(), QByteArray("foo"));
675     }
676     {
677         QUrl url;
678         url.setUrl("http://1.2.3.4#bar");
679         QVERIFY(url.isValid());
680         QCOMPARE(url.scheme(), QString("http"));
681         QCOMPARE(url.host(), QString("1.2.3.4"));
682         QCOMPARE(url.fragment(), QString("bar"));
683     }
684 
685     {
686         QUrl url;
687         url.setEncodedUrl("data:text/javascript,d5%20%3D%20'five\\u0027s'%3B");
688         QVERIFY(url.isValid());
689         QCOMPARE(url.scheme(), QString("data"));
690         QCOMPARE(url.host(), QString());
691         QCOMPARE(url.path(), QString("text/javascript,d5 = 'five\\u0027s';"));
692         QCOMPARE(url.encodedPath().constData(), "text/javascript,d5%20%3D%20'five%5Cu0027s'%3B");
693     }
694 
695     {
696         // invalid port number
697         QUrl url;
698         url.setEncodedUrl("foo://tel:2147483648");
699         QVERIFY(url.isValid()); // ### should be !isValid(), but the parser can't catch it
700         QCOMPARE(url.scheme(), QString("foo"));
701         QCOMPARE(url.host(), QString("tel"));
702         QCOMPARE(url.port(), -1);
703     }
704 
705     { //check it calls detach
706         QUrl u1("http://aaa.com");
707         QUrl u2 = u1;
708         u2.setUrl("http://bbb.com");
709         QCOMPARE(u1.host(), QString::fromLatin1("aaa.com"));
710         QCOMPARE(u2.host(), QString::fromLatin1("bbb.com"));
711     }
712 
713 /*
714    The tests below are copied from kdelibs/kdecore/tests/kurltest.cpp (an old version of)
715 
716     Copyright (c) 1999-2005 Waldo Bastian <bastian@kde.org>
717     Copyright (c) 2000-2005 David Faure <faure@kde.org>
718 
719     This library is free software; you can redistribute it and/or
720     modify it under the terms of the GNU Library General Public
721     License version 2 as published by the Free Software Foundation.
722 
723     This library is distributed in the hope that it will be useful,
724     but WITHOUT ANY WARRANTY; without even the implied warranty of
725     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
726     Library General Public License for more details.
727 
728     You should have received a copy of the GNU Library General Public License
729     along with this library; see the file COPYING.LIB.  If not, write to
730     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
731     Boston, MA 02110-1301, USA.
732  */
733 /*
734     ### File / directory specifics
735 
736     KURL u2( QCString("/home/dfaure/") );
737     printf("\n* URL is %s\n",u2.url().ascii());
738 // not ignoring trailing slash
739     check("KURL::directory(false,false)", u2.directory(false,false), "/home/dfaure/");
740     check("KURL::directory(true,false)", u2.directory(true,false), "/home/dfaure");
741 // ignoring trailing slash
742     check("KURL::directory(false,true)", u2.directory(false,true), "/home/");
743     check("KURL::directory(true,true)", u2.directory(true,true), "/home");
744     u2.cd("..");
745     check("KURL::cd(\"..\")", u2.url(), "file:/home");
746     u2.cd("thomas");
747     check("KURL::cd(\"thomas\")", u2.url(), "file:/home/thomas");
748     u2.cd("/opt/kde/bin/");
749     check("KURL::cd(\"/opt/kde/bin/\")", u2.url(), "file:/opt/kde/bin/");
750     u2 = "ftp://ftp.kde.org/";
751     printf("\n* URL is %s\n",u2.url().ascii());
752     u2.cd("pub");
753     check("KURL::cd(\"pub\")", u2.url(), "ftp://ftp.kde.org/pub");
754     u2 = u2.upURL();
755     check("KURL::upURL()", u2.url(), "ftp://ftp.kde.org/");
756     u2 = u1;
757     printf("\n* URL is %s\n",u2.url().ascii());
758 // setFileName
759     u2.setFileName( "myfile.txt" );
760     check("KURL::setFileName()", u2.url(), "file:/home/dfaure/myfile.txt");
761     u2.setFileName( "myotherfile.txt" );
762     check("KURL::setFileName()", u2.url(), "file:/home/dfaure/myotherfile.txt");
763 // more tricky, renaming a directory (kpropsdlg.cc, line ~ 238)
764     QString tmpurl = "file:/home/dfaure/myolddir/";
765     if ( tmpurl.at(tmpurl.length() - 1) == '/')
766 // It's a directory, so strip the trailing slash first
767         tmpurl.truncate( tmpurl.length() - 1);
768     KURL newUrl = tmpurl;
769     newUrl.setFileName( "mynewdir" );
770     check("KURL::setFileName() special", newUrl.url(), "file:/home/dfaure/mynewdir");
771 // addPath tests
772     newUrl.addPath( "subdir" );
773     check("KURL::addPath(\"subdir\")", newUrl.url(), "file:/home/dfaure/mynewdir/subdir");
774     newUrl.addPath( "/foo/" );
775     check("KURL::addPath(\"/foo/\")", newUrl.url(), "file:/home/dfaure/mynewdir/subdir/foo/");
776     u2 = "http://www.kde.org"; // no path
777     u2.addPath( "subdir" );
778     check("KURL::addPath(\"subdir\")", u2.url(), "http://www.kde.org/subdir");
779     u2.addPath( "" );
780     check("KURL::addPath(\"subdir\")", u2.url(), "http://www.kde.org/subdir"); // unchanged
781 
782 // even more tricky
783     u2 = "print:/specials/Print%20To%20File%20(PDF%2FAcrobat)";
784     printf("\n* URL is %s\n",u2.url().ascii());
785     check("KURL::path()", u2.path(), "/specials/Print To File (PDF/Acrobat)");
786     check("KURL::fileName()", u2.fileName(), "Print To File (PDF/Acrobat)");
787     u2.setFileName( "" );
788     check("KURL::setFileName()", u2.url(), "print:/specials/");
789 
790     u2 = "file:/specials/Print";
791     printf("\n* URL is %s\n",u2.url().ascii());
792     check("KURL::path()", u2.path(), "/specials/Print");
793     check("KURL::fileName()", u2.fileName(), "Print");
794     u2.setFileName( "" );
795     check("KURL::setFileName()", u2.url(), "file:/specials/");
796 
797     const char * u3 = "ftp://host/dir1/dir2/myfile.txt";
798     printf("\n* URL is %s\n",u3);
799     check("KURL::hasSubURL()", KURL(u3).hasSubURL() ? "yes" : "no", "no");
800     lst.clear();
801     lst = KURL::split( KURL(u3) );
802     check("KURL::split()", lst.count()==1 ? "1" : "error", "1");
803     check("KURL::split()", lst.first().url(), "ftp://host/dir1/dir2/myfile.txt");
804 // cdUp code
805     KURL lastUrl = lst.last();
806     QString dir = lastUrl.directory( true, true );
807     check( "KURL::directory(true,true)", dir, "/dir1/dir2");
808 */
809 
810     {
811         // !!! FAILS
812 //        QString ucmp1 = "ftp://ftp.de.kde.org/dir";
813 //        QString ucmp2 = "ftp://ftp.de.kde.org/dir/";
814 //        QVERIFY(QUrl(ucmp1) == QUrl(ucmp2));
815     }
816 
817 
818     /*
819 /// Comparisons
820     QString ucmp1 = "ftp://ftp.de.kde.org/dir";
821     QString ucmp2 = "ftp://ftp.de.kde.org/dir/";
822     check("urlcmp(only slash difference)", urlcmp(ucmp1,ucmp2)?"ko":"ok","ok");
823     check("urlcmp(only slash difference, ignore_trailing)", urlcmp(ucmp1,ucmp2,true,false)?"ok":"ko","ok");
824     QString ucmp3 = "ftp://ftp.de.kde.org/dir/#";
825     check("urlcmp(only hash difference)", urlcmp(ucmp2,ucmp3)?"ko":"ok","ok");
826     check("urlcmp(only hash difference, ignore_ref)", urlcmp(ucmp2,ucmp3,false,true)?"ok":"ko","ok");
827     check("urlcmp(slash and hash difference, ignore_trailing, ignore_ref)", urlcmp(ucmp2,ucmp3,true,true)?"ok":"ko","ok");
828     check("urlcmp(empty, empty)", urlcmp("","",false,true)?"ok":"ko","ok");
829     check("urlcmp(empty, empty)", urlcmp("","")?"ok":"ko","ok");
830     check("urlcmp(empty, not empty)", urlcmp("",ucmp1)?"ok":"ko","ko");
831     check("urlcmp(empty, not empty)", urlcmp("",ucmp1,false,true)?"ok":"ko","ko");
832     check("urlcmp(malformed, not empty)", urlcmp("file",ucmp1)?"ok":"ko","ko");
833     check("urlcmp(malformed, not empty)", urlcmp("file",ucmp1,false,true)?"ok":"ko","ko");
834 
835     KURL ftpUrl ( "ftp://ftp.de.kde.org" );
836     printf("\n* URL is %s\n",ftpUrl.url().latin1());
837     check("KURL::path()", ftpUrl.path(), QString());
838     ftpUrl = "ftp://ftp.de.kde.org/";
839     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp.de.kde.org/host/subdir/") ? "yes" : "no", "yes");
840     ftpUrl = "ftp://ftp/host/subdir/";
841     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/host/subdir/") ? "yes" : "no", "yes");
842     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/host/subdir") ? "yes" : "no", "yes");
843     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/host/subdi") ? "yes" : "no", "no");
844     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/host/subdir/blah/") ? "yes" : "no", "yes");
845     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/blah/subdir") ? "yes" : "no", "no");
846     check("KURL::isParentOf()", ftpUrl.isParentOf( "file://ftp/host/subdir/") ? "yes" : "no", "no");
847     check("KURL::isParentOf()", ftpUrl.isParentOf( "ftp://ftp/host/subdir/subsub") ? "yes" : "no", "yes");
848 
849 // WABA: The following tests are to test the handling of relative URLs as
850 //       found on web-pages.
851 
852     KURL waba1( "http://www.website.com/directory/?hello#ref" );
853     {
854         KURL waba2( waba1, "relative.html");
855         check("http: Relative URL, single file", waba2.url(), "http://www.website.com/directory/relative.html");
856     }
857     {
858         KURL waba2( waba1, "../relative.html");
859         check("http: Relative URL, single file, directory up", waba2.url(), "http://www.website.com/relative.html");
860     }
861     {
862         KURL waba2( waba1, "down/relative.html");
863         check("http: Relative URL, single file, directory down", waba2.url(), "http://www.website.com/directory/down/relative.html");
864     }
865     {
866         KURL waba2( waba1, "/down/relative.html");
867         check("http: Relative URL, full path", waba2.url(), "http://www.website.com/down/relative.html");
868     }
869     {
870         KURL waba2( waba1, "//www.kde.org/relative.html");
871         check("http: Relative URL, with host", waba2.url(), "http://www.kde.org/relative.html");
872     }
873     {
874         KURL waba2( waba1, "relative.html?query=test&name=harry");
875         check("http: Relative URL, with query", waba2.url(), "http://www.website.com/directory/relative.html?query=test&name=harry");
876         waba2.removeQueryItem("query");
877         check("http: Removing query item", waba2.url(), "http://www.website.com/directory/relative.html?name=harry");
878         waba2.addQueryItem("age", "18");
879         check("http: Adding query item", waba2.url(), "http://www.website.com/directory/relative.html?name=harry&age=18");
880         waba2.addQueryItem("age", "21");
881         check("http: Adding query item", waba2.url(), "http://www.website.com/directory/relative.html?name=harry&age=18&age=21");
882         waba2.addQueryItem("fullname", "Harry Potter");
883         check("http: Adding query item", waba2.url(), "http://www.website.com/directory/relative.html?name=harry&age=18&age=21&fullname=Harry%20Potter");
884     }
885     {
886         KURL waba2( waba1, "?query=test&name=harry");
887         check("http: Relative URL, with query and no filename", waba2.url(), "http://www.website.com/directory/?query=test&name=harry");
888     }
889     {
890         KURL waba2( waba1, "relative.html#with_reference");
891         check("http: Relative URL, with reference", waba2.url(), "http://www.website.com/directory/relative.html#with_reference");
892     }
893     {
894         KURL waba2( waba1, "#");
895         check("http: Relative URL, with empty reference", waba2.url(), "http://www.website.com/directory/?hello#");
896     }
897     {
898         KURL waba2( waba1, "");
899         check("http: Empty relative URL", waba2.url(), "http://www.website.com/directory/?hello#ref");
900     }
901     {
902         KURL base( "http://faure@www.kde.org" ); // no path
903         KURL waba2( base, "filename.html");
904         check("http: Relative URL, orig URL had no path", waba2.url(), "http://faure@www.kde.org/filename.html");
905     }
906     {
907         KURL base( "http://faure:pass@www.kde.org:81?query" );
908         KURL rel1( base, "http://www.kde.org/bleh/"); // same host
909         check("http: Relative URL, orig URL had username", rel1.url(), "http://faure:pass@www.kde.org/bleh/");
910         KURL rel2( base, "http://www.yahoo.org"); // different host
911         check("http: Relative URL, orig URL had username", rel2.url(), "http://www.yahoo.org");
912     }
913 
914     waba1 = "http://www.website.com/directory/filename?bla#blub";
915     {
916         KURL waba2( waba1, "relative.html");
917         check("http: Relative URL, single file", waba2.url(), "http://www.website.com/directory/relative.html");
918     }
919     {
920         KURL waba2( waba1, "../relative.html");
921         check("http: Relative URL, single file, directory up", waba2.url(), "http://www.website.com/relative.html");
922     }
923     {
924         KURL waba2( waba1, "down/relative.html");
925         check("http: Relative URL, single file, directory down", waba2.url(), "http://www.website.com/directory/down/relative.html");
926     }
927     {
928         KURL waba2( waba1, "/down/relative.html");
929         check("http: Relative URL, full path", waba2.url(), "http://www.website.com/down/relative.html");
930     }
931     {
932         KURL waba2( waba1, "relative.html?query=test&name=harry");
933         check("http: Relative URL, with query", waba2.url(), "http://www.website.com/directory/relative.html?query=test&name=harry");
934     }
935     {
936         KURL waba2( waba1, "?query=test&name=harry");
937         check("http: Relative URL, with query and no filename", waba2.url(), "http://www.website.com/directory/filename?query=test&name=harry");
938     }
939     {
940         KURL waba2( waba1, "relative.html#with_reference");
941         check("http: Relative URL, with reference", waba2.url(), "http://www.website.com/directory/relative.html#with_reference");
942     }
943     {
944         KURL waba2( waba1, "http:/relative.html"); // "rfc 1606 loophole"
945         check("http: Strange relative URL", waba2.url(), "http://www.website.com/relative.html");
946     }
947     waba1.setUser("waldo");
948     check("http: Set user", waba1.url(), "http://waldo@www.website.com/directory/filename?bla#blub");
949     waba1.setUser("waldo/bastian");
950     check("http: Set user with slash in it", waba1.url(), "http://waldo%2Fbastian@www.website.com/directory/filename?bla#blub");
951     waba1.setRef( QString() );
952     waba1.setPass( "pass" );
953     waba1.setDirectory( "/foo" );
954     waba1.setProtocol( "https" );
955     waba1.setHost( "web.com" );
956     waba1.setPort( 881 );
957     check("http: setRef/setPass/setDirectory/setHost/setPort", waba1.url(), "https://waldo%2Fbastian:pass@web.com:881/foo/?bla");
958     waba1.setDirectory( "/foo/" );
959     check("http: setDirectory #2", waba1.url(), "https://waldo%2Fbastian:pass@web.com:881/foo/?bla");
960 
961 // Empty queries should be preserved!
962     waba1 = "http://www.kde.org/cgi/test.cgi?";
963     check("http: URL with empty query string", waba1.url(),
964           "http://www.kde.org/cgi/test.cgi?");
965 
966 // Empty references should be preserved
967     waba1 = "http://www.kde.org/cgi/test.cgi#";
968     check("http: URL with empty reference string", waba1.url(),
969           "http://www.kde.org/cgi/test.cgi#");
970     check("hasRef()", waba1.hasRef()?"true":"false","true");
971     check("hasHTMLRef()", waba1.hasHTMLRef()?"true":"false","true");
972     check("encodedHtmlRef()", waba1.encodedHtmlRef(),QString());
973 
974 // URLs who forgot to encode spaces in the query.
975     waba1 = "http://www.kde.org/cgi/test.cgi?hello=My Value";
976     check("http: URL with incorrect encoded query", waba1.url(),
977           "http://www.kde.org/cgi/test.cgi?hello=My%20Value");
978 
979 // URL with ':' in query (':' should NOT be encoded!)
980     waba1.setQuery("hello:My Value");
981     check("http: URL with ':' in query", waba1.url(),
982           "http://www.kde.org/cgi/test.cgi?hello:My%20Value");
983     check("upURL() removes query", waba1.upURL().url(),
984           "http://www.kde.org/cgi/test.cgi");
985 
986 // URLs who forgot to encode spaces in the query.
987     waba1 = "http://www.kde.org/cgi/test.cgi?hello=My Value+20";
988     check("http: URL with incorrect encoded query", waba1.url(),
989           "http://www.kde.org/cgi/test.cgi?hello=My%20Value+20");
990 
991 // Urls without path (BR21387)
992     waba1 = "http://meine.db24.de?link=home_c_login_login";
993     check("http: URL with empty path string", waba1.url(),
994           "http://meine.db24.de?link=home_c_login_login");
995     check("http: URL with empty path string path", waba1.path(),
996           "");
997     check("http: URL with empty path string query", waba1.query(),
998           "?link=home_c_login_login");
999 
1000     waba1 = "http://a:389?b=c";
1001     check( "http: URL with port, query, and empty path; url", waba1.url(), "http://a:389?b=c" );
1002     check( "http: URL with port, query, and empty path; host", waba1.host(), "a" );
1003     check( "http: URL with port, query, and empty path; port", QString::number( waba1.port() ), "389" );
1004     check( "http: URL with port, query, and empty path; path", waba1.path(), "" );
1005     check( "http: URL with port, query, and empty path; query", waba1.query(), "?b=c" );
1006 
1007 // Urls without path (BR21387)
1008     waba1 = "http://meine.db24.de#link=home_c_login_login";
1009     check("http: URL with empty path string", waba1.url(),
1010           "http://meine.db24.de#link=home_c_login_login");
1011     check("http: URL with empty path string path", waba1.path(),
1012           "");
1013 
1014     waba1 = "http://a:389#b=c";
1015     check( "http: URL with port, ref, and empty path; url", waba1.url(), "http://a:389#b=c" );
1016     check( "http: URL with port, ref, and empty path; host", waba1.host(), "a" );
1017     check( "http: URL with port, ref, and empty path; port", QString::number( waba1.port() ), "389" );
1018     check( "http: URL with port, ref, and empty path; path", waba1.path(), "" );
1019     check( "http: URL with port, ref, and empty path; ref", waba1.ref(), "b=c" );
1020     check( "http: URL with port, ref, and empty path; query", waba1.query(), "" );
1021 
1022 // IPV6
1023     waba1 = "http://[::FFFF:129.144.52.38]:81/index.html";
1024     check("http: IPV6 host", waba1.host(),
1025           "::ffff:129.144.52.38");
1026     check("http: IPV6 port", QString("%1").arg(waba1.port()),
1027           "81");
1028 
1029 // IPV6
1030     waba1 = "http://waba:pass@[::FFFF:129.144.52.38]:81/index.html";
1031     check("http: IPV6 host", waba1.host(),
1032           "::ffff:129.144.52.38");
1033     check("http: IPV6 host", waba1.user(),
1034           "waba");
1035     check("http: IPV6 host", waba1.pass(),
1036           "pass");
1037     check("http: IPV6 port", QString("%1").arg(waba1.port()),
1038           "81");
1039 
1040 // IPV6
1041     waba1 = "http://www.kde.org/cgi/test.cgi";
1042     waba1.setHost("::ffff:129.144.52.38");
1043     check("http: IPV6 host", waba1.url(),
1044           "http://[::ffff:129.144.52.38]/cgi/test.cgi");
1045     waba1 = "http://[::ffff:129.144.52.38]/cgi/test.cgi";
1046     assert( waba1.isValid() );
1047 
1048 // IPV6 without path
1049     waba1 = "http://[::ffff:129.144.52.38]?query";
1050     assert( waba1.isValid() );
1051     check("http: IPV6 without path", waba1.url(),
1052           "http://[::ffff:129.144.52.38]?query");
1053     check("http: IPV6 without path; query", waba1.query(),
1054           "?query");
1055     waba1 = "http://[::ffff:129.144.52.38]#ref";
1056     assert( waba1.isValid() );
1057     check("http: IPV6 without path", waba1.url(),
1058           "http://[::ffff:129.144.52.38]#ref");
1059     check("http: IPV6 without path; ref", waba1.ref(),
1060           "ref");
1061 // IPV6 without path but with a port
1062     waba1 = "http://[::ffff:129.144.52.38]:81?query";
1063     assert( waba1.isValid() );
1064     check("http: IPV6 without path", waba1.url(),
1065           "http://[::ffff:129.144.52.38]:81?query");
1066     check("http: IPV6 without path; port", QString::number( waba1.port() ), "81" );
1067     check("http: IPV6 without path; query", waba1.query(), "?query");
1068     waba1 = "http://[::ffff:129.144.52.38]:81#ref";
1069     assert( waba1.isValid() );
1070     check("http: IPV6 without path", waba1.url(),
1071           "http://[::ffff:129.144.52.38]:81#ref");
1072     check("http: IPV6 without path; port", QString::number( waba1.port() ), "81" );
1073     check("http: IPV6 without path; ref", waba1.ref(), "ref");
1074 
1075 // Streaming operators
1076     KURL origURL( "http://www.website.com/directory/?#ref" );
1077     waba1 = "http://[::ffff:129.144.52.38]:81?query";
1078     QByteArray buffer;
1079     {
1080         QDataStream stream( buffer, QIODevice::WriteOnly );
1081         stream << origURL
1082                << KURL( "file:" ) // an invalid one
1083                << waba1; // the IPv6 one
1084     }
1085     {
1086         QDataStream stream( buffer, QIODevice::ReadOnly );
1087         KURL restoredURL;
1088         stream >> restoredURL;
1089         check( "Streaming valid URL", origURL.url(), restoredURL.url() );
1090         stream >> restoredURL;
1091         check( "Streaming invalid URL", restoredURL.isValid()?"valid":"malformed", "malformed" );
1092         check( "Streaming invalid URL", restoredURL.url(), "file:" );
1093         stream >> restoredURL;
1094         check( "Streaming ipv6 URL with query", restoredURL.url(), waba1.url() );
1095     }
1096 
1097 // Broken stuff
1098     waba1 = "file:a";
1099     check("Broken stuff #1 path", waba1.path(), "a");
1100     check("Broken stuff #1 fileName(false)", waba1.fileName(false), "a");
1101     check("Broken stuff #1 fileName(true)", waba1.fileName(true), "a");
1102     check("Broken stuff #1 directory(false, false)", waba1.directory(false, false), "");
1103     check("Broken stuff #1 directory(true, false)", waba1.directory(true, false), "");
1104     check("Broken stuff #1 directory(false, true)", waba1.directory(true, true), "");
1105 
1106     waba1 = "file:a/";
1107     check("Broken stuff #2 path", waba1.path(), "a/");
1108     check("Broken stuff #2 fileName(false)", waba1.fileName(false), "");
1109     check("Broken stuff #2 fileName(true)", waba1.fileName(true), "a");
1110     check("Broken stuff #2 directory(false, false)", waba1.directory(false, false), "a/");
1111     check("Broken stuff #2 directory(true, false)", waba1.directory(true, false), "a");
1112     check("Broken stuff #2 directory(false, true)", waba1.directory(true, true), "");
1113 
1114     waba1 = "file:";
1115     check("Broken stuff #3 empty", waba1.isEmpty()?"EMPTY":"NOT", "NOT");
1116     check("Broken stuff #3 valid", waba1.isValid()?"VALID":"MALFORMED", "MALFORMED");
1117     check("Broken stuff #3 path", waba1.path(), "");
1118     check("Broken stuff #3 fileName(false)", waba1.fileName(false), "");
1119     check("Broken stuff #3 fileName(true)", waba1.fileName(true), "");
1120     check("Broken stuff #3 directory(false, false)", waba1.directory(false, false), "");
1121     check("Broken stuff #3 directory(true, false)", waba1.directory(true, false), "");
1122     check("Broken stuff #3 directory(false, true)", waba1.directory(true, true), "");
1123     KURL broken;
1124     broken.setPath( QString() );
1125     check("Broken stuff #4 empty", broken.isEmpty()?"EMPTY":"NOT", "NOT");
1126 // It's valid: because isValid refers to parsing, not to what happens afterwards.
1127     check("Broken stuff #4 valid", broken.isValid()?"VALID":"MALFORMED", "VALID");
1128     check("Broken stuff #4 path", broken.path(), "");
1129     broken = "file://"; // just because coolo wondered
1130     check("Broken stuff #5 empty", broken.isEmpty()?"EMPTY":"NOT", "NOT");
1131     check("Broken stuff #5 valid", broken.isValid()?"VALID":"MALFORMED", "MALFORMED");
1132     check("Broken stuff #5 path", broken.path(), "");
1133     broken = "file";
1134     check("Broken stuff #6 valid", broken.isValid()?"VALID":"MALFORMED", "MALFORMED");
1135 
1136 #if 0 // BROKEN?
1137 // UNC like names
1138     KURL unc1("FILE://localhost/home/root");
1139     check("UNC, with localhost", unc1.path(), "/home/root");
1140     check("UNC, with localhost", unc1.url(), "file:/home/root");
1141 #endif
1142     KURL unc2("file:///home/root");
1143     check("UNC, with empty host", unc2.path(), "/home/root");
1144     check("UNC, with empty host", unc2.url(), "file:/home/root");
1145 
1146     {
1147         KURL unc3("FILE://remotehost/home/root");
1148 #if 0 // BROKEN?
1149         check("UNC, with remote host", unc3.path(), "//remotehost/home/root");
1150 #endif
1151         check("UNC, with remote host", unc3.url(), "file://remotehost/home/root");
1152         KURL url2("file://atlas/dfaure");
1153         check("KURL::host()", url2.host(), "atlas");
1154         check("KURL::path()", url2.path(), "/dfaure");
1155         //check("KURL::path()", url3.path(), "//atlas/dfaure"); // says Waba
1156         //KURL url3("file:////atlas/dfaure");
1157         //check("KURL::path()", url3.path(), "//atlas/dfaure"); // says Waba
1158     }
1159 
1160     KURL umail1 ( "mailto:faure@kde.org" );
1161     check("mailto: URL, general form", umail1.protocol(), "mailto");
1162     check("mailto: URL, general form", umail1.path(), "faure@kde.org");
1163     check("mailto: URL, is relative", KURL::isRelativeURL("mailto:faure@kde.org") ? "true" : "false", "false");
1164     KURL umail2 ( "mailto:Faure David <faure@kde.org>" );
1165     check("mailto: URL, general form", umail2.protocol(), "mailto");
1166     check("mailto: URL, general form", umail2.path(), "Faure David <faure@kde.org>");
1167     check("isRelativeURL(\"mailto:faure@kde.org\")", KURL::isRelativeURL("mailto:faure@kde.org") ? "yes" : "no", "no");
1168     KURL umail3 ( "mailto:" );
1169     check("mailto: invalid URL", umail3.isValid()?"valid":"malformed", "malformed");
1170 
1171     check("man: URL, is relative", KURL::isRelativeURL("man:mmap") ? "true" : "false", "false");
1172     check("javascript: URL, is relative", KURL::isRelativeURL("javascript:doSomething()") ? "true" : "false", "false");
1173 // more isRelative
1174     check("file: URL, is relative", KURL::isRelativeURL("file:/blah") ? "true" : "false", "false");
1175     check("/path, is relative", KURL::isRelativeURL("/path") ? "true" : "false", "true"); // arguable
1176     check("something, is relative", KURL::isRelativeURL("something") ? "true" : "false", "true");
1177     KURL about("about:konqueror");
1178     check("about:",about.path(),"konqueror");
1179 
1180     KURL ulong("https://swww.gad.de:443/servlet/CookieAccepted?MAIL=s@gad.de&VER=25901");
1181     check("host",ulong.host(),"swww.gad.de");
1182     check("path",ulong.path(),"/servlet/CookieAccepted");
1183 
1184     QTextCodec::setCodecForLocale( KGlobal::charsets()->codecForName( "iso-8859-1" ) );
1185 // UTF8 tests
1186     KURL uloc("/home/dfaure/konqtests/Mat�riel");
1187     check("locale8bit",uloc.url().latin1(),"file:/home/dfaure/konqtests/Mat%E9riel"); // escaping the letter would be correct too
1188     check("pretty",uloc.prettyURL(),"file:/home/dfaure/konqtests/Mat�riel"); // escaping the letter would be correct too
1189 // 106 is MIB for UTF-8
1190     check("UTF8",uloc.url(0, 106),"file:/home/dfaure/konqtests/Mat%C3%A9riel");
1191     uloc = KURL("file:/home/dfaure/konqtests/Mat%C3%A9riel", 106);
1192     check("UTF8 path", uloc.path(), "/home/dfaure/konqtests/Mat�riel");
1193 
1194 // fromPathOrURL tests
1195     uloc = KURL::fromPathOrURL( "/home/dfaure/konqtests/Mat%E9riel" );
1196     check("fromPathOrURL path", uloc.path(), "/home/dfaure/konqtests/Mat%E9riel");
1197     uloc = KURL::fromPathOrURL( "http://www.kde.org" );
1198     check("fromPathOrURL url", uloc.url(), "http://www.kde.org");
1199     uloc = KURL::fromPathOrURL( "www.kde.org" );
1200     check("fromPathOrURL url", uloc.isValid()?"valid":"malformed", "malformed");
1201     uloc = KURL::fromPathOrURL( "index.html" );
1202     check("fromPathOrURL url", uloc.isValid()?"valid":"malformed", "malformed");
1203     uloc = KURL::fromPathOrURL( "" );
1204     check("fromPathOrURL url", uloc.isValid()?"valid":"malformed", "malformed");
1205 
1206     QTextCodec::setCodecForLocale( KGlobal::charsets()->codecForName( "koi8-r" ) );
1207     baseURL = "file:/home/coolo";
1208     KURL russian = baseURL.directory(false, true) + QString::fromLocal8Bit( "���7" );
1209     check( "russian", russian.url(), "file:/home/%C6%C7%CE7" );
1210 
1211     KURL tobi1("http://some.host.net/path/to/file#fragmentPrecedes?theQuery");
1212     check("wrong order of query and hypertext reference #1", tobi1.ref(), "fragmentPrecedes");
1213     check("wrong order of query and hypertext reference #2", tobi1.query(), "?theQuery");
1214 
1215     tobi1 = "http://host.net/path/?#http://broken�adsfk�poij31�029mu�2890zupyc�*!*'O�+�0i";
1216     check("zero-length query",tobi1.query(),"?");
1217 
1218     tobi1 = "http://host.net/path/#no-query";
1219     check("no query", tobi1.query(),"");
1220 
1221     tobi1 = "http://host.net/path?myfirstquery#andsomeReference";
1222     tobi1.setEncodedPathAndQuery("another/path/?another&query");
1223     check("setEncodedPathAndQuery test#1", tobi1.query(), "?another&query");
1224     check("setEncodedPathAndQuery test#2", tobi1.path(), "another/path/");
1225     tobi1.setEncodedPathAndQuery("another/path?another&query");
1226     check("setEncodedPathAndQuery test#1", tobi1.query(), "?another&query");
1227     check("setEncodedPathAndQuery test#2", tobi1.path(), "another/path");
1228 
1229     KURL theKow = "http://www.google.de/search?q=frerich&hlx=xx&hl=de&empty=&lr=lang+de&test=%2B%20%3A%25";
1230     check("queryItem (first item)", theKow.queryItem("q"), "frerich");
1231     check("queryItem (middle item)", theKow.queryItem("hl"), "de");
1232     check("queryItem (last item)", theKow.queryItem("lr"), "lang de");
1233     check("queryItem (invalid item)", theKow.queryItem("InterstellarCounselor"), QString());
1234     check("queryItem (empty item)", theKow.queryItem("empty"), "");
1235     check("queryItem (item with encoded chars)", theKow.queryItem("test"), "+ :%");
1236 
1237 // checks for queryItems(), which returns a QMap<QString,QString>:
1238     KURL queryUrl( "mailto:Marc%20Mutz%20%3cmutz@kde.org%3E?"
1239                    "Subject=subscribe+me&"
1240                    "body=subscribe+mutz%40kde.org&"
1241                    "Cc=majordomo%40lists.kde.org" );
1242     check("queryItems (c.s. keys)",
1243           QStringList(queryUrl.queryItems().keys()).join(", "),
1244           "Cc, Subject, body" );
1245     check("queryItems (c.i.s. keys)",
1246           QStringList(queryUrl.queryItems(KURL::CaseInsensitiveKeys).keys()).join(", "),
1247           "body, cc, subject" );
1248     check("queryItems (values; c.s. keys)",
1249           QStringList(queryUrl.queryItems().values()).join(", "),
1250           "majordomo@lists.kde.org, subscribe me, subscribe mutz@kde.org" );
1251     check("queryItems (values; c.i.s. keys)",
1252           QStringList(queryUrl.queryItems(KURL::CaseInsensitiveKeys).values()).join(", "),
1253           "subscribe mutz@kde.org, majordomo@lists.kde.org, subscribe me" );
1254 
1255     KURL umlaut1("http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel");
1256     check("umlaut1.url()", umlaut1.url(), "http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel");
1257 
1258     KURL umlaut2("http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel", 106);
1259     check("umlaut2.url()", umlaut2.url(), "http://www.clever-tanken.de/liste.asp?ort=N%FCrnberg&typ=Diesel");
1260 
1261 // Needed for #49616
1262     check( "encode_string('C++')", KURL::encode_string( "C++" ), "C%2B%2B" );
1263     check( "decode_string('C%2B%2B')", KURL::decode_string( "C%2B%2B" ), "C++" );
1264     check( "decode_string('C%00A')", KURL::decode_string( "C%00%A" ), "C" ); // we stop at %00
1265 
1266     check( "encode_string('%')", KURL::encode_string( "%" ), "%25" );
1267     check( "encode_string(':')", KURL::encode_string( ":" ), "%3A" );
1268 
1269     KURL amantia( "http://%E1.foo" );
1270     check("amantia.isValid()", amantia.isValid() ? "true" : "false", "true");
1271 #ifdef HAVE_IDNA_H
1272     check("amantia.url()", amantia.url(), "http://xn--80a.foo");   // Non-ascii is allowed in IDN domain names.
1273 #else
1274     check("amantia.url()", amantia.url(), "http://?.foo"); // why not
1275 #endif
1276 
1277     KURL smb("smb://domain;username:password@server/share");
1278     check("smb.isValid()", smb.isValid() ? "true" : "false", "true");
1279     check("smb.user()", smb.user(), "domain;username");
1280     smb = "smb:/";
1281     check("smb:/", smb.isValid()?"VALID":"MALFORMED", "VALID");
1282     smb = "smb://"; // kurl.cpp rev 1.106
1283     check("smb://", smb.isValid()?"VALID":"MALFORMED", "MALFORMED");
1284     smb = "smb://host";
1285     check("smb://host", smb.isValid()?"VALID":"MALFORMED", "VALID");
1286     smb = "smb:///";
1287     check("smb:///", smb.isValid()?"VALID":"MALFORMED", "VALID");
1288 
1289     KURL weird;
1290     weird = "http://strange<hostname>/";
1291     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1292 
1293     weird = "http://strange<username>@strange<hostname>/";
1294     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1295 
1296     weird = "http://strange<username>@ok_hostname/";
1297     check("weird.isValid()", weird.isValid() ? "true" : "false", "true");
1298     check("weird.host()", weird.host(), "ok_hostname");
1299 
1300     weird = "http://strange;hostname/";
1301     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1302 
1303     weird = "http://strange;username@strange;hostname/";
1304     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1305 
1306     weird = "http://strange;username@ok_hostname/";
1307     check("weird.isValid()", weird.isValid() ? "true" : "false", "true");
1308     check("weird.host()", weird.host(), "ok_hostname");
1309 
1310     weird = "http://strange;username:password@strange;hostname/";
1311     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1312 
1313     weird = "http://strange;username:password@ok_hostname/";
1314     check("weird.isValid()", weird.isValid() ? "true" : "false", "true");
1315     check("weird.host()", weird.host(), "ok_hostname");
1316 
1317     weird = "http://[strange;hostname]/";
1318     check("weird.isValid()", weird.isValid() ? "true" : "false", "false");
1319 
1320     weird = "http://[::fff:1:23]/";
1321     check("weird.isValid()", weird.isValid() ? "true" : "false", "true");
1322     check("weird.host()", weird.host(), "::fff:1:23");
1323 
1324     KURL com1("http://server.com/dir/", ".");
1325     check("com1.url()", com1.url(), "http://server.com/dir/");
1326 
1327     KURL com2("http://server.com/dir/blubb/", "blah/");
1328     check("com2.url()", com2.url(), "http://server.com/dir/blubb/blah/");
1329 
1330     KURL utf8_1("audiocd:/By%20Name/15%20Geantra%C3%AE.wav", 106);
1331     check("utf8_1.fileName()", utf8_1.fileName(), QString::fromLatin1("15 Geantra�.wav"));
1332 
1333     KURL utf8_2("audiocd:/By%20Name/15%2fGeantra%C3%AE.wav", 106);
1334     check("utf8_2.fileName()", utf8_2.fileName(), QString::fromLatin1("15/Geantra�.wav"));
1335 
1336     KURL url_newline_1("http://www.foo.bar/foo/bar\ngnork");
1337     check("url_newline_1.url()", url_newline_1.url(), QString::fromLatin1("http://www.foo.bar/foo/bar%0Agnork"));
1338 
1339     KURL url_newline_2("http://www.foo.bar/foo?bar\ngnork");
1340     check("url_newline_2.url()", url_newline_2.url(), QString::fromLatin1("http://www.foo.bar/foo?bar%0Agnork"));
1341 
1342     KURL local_file_1("file://localhost/my/file");
1343     check("local_file_1.isLocalFile()", local_file_1.isLocalFile() ? "true" : "false", "true");
1344 
1345     KURL local_file_2("file://www.kde.org/my/file");
1346     check("local_file_2.isLocalFile()", local_file_2.isLocalFile() ? "true" : "false", "false");
1347 
1348     KURL local_file_3;
1349     local_file_3.setHost(getenv("HOSTNAME"));
1350     local_file_3.setPath("/my/file");
1351     printf("\nURL=%s\n", local_file_3.url().latin1());
1352     check("local_file_3.isLocalFile()", local_file_3.isLocalFile() ? "true" : "false", "true");
1353 
1354     KURL local_file_4("file:///my/file");
1355     check("local_file_4.isLocalFile()", local_file_4.isLocalFile() ? "true" : "false", "true");
1356 
1357     KURL local_file_5;
1358     local_file_5.setPath("/foo?bar");
1359     check("local_file_5.url()", local_file_5.url(), "file:/foo%3Fbar");
1360 
1361     QString basePath = "/home/bastian";
1362 
1363     check("relativePath(\"/home/bastian\", \"/home/bastian\")", KURL::relativePath(basePath, "/home/bastian"), "./");
1364     bool b;
1365     check("relativePath(\"/home/bastian\", \"/home/bastian/src/plugins\")", KURL::relativePath(basePath, "/home/bastian/src/plugins", &b), "./src/plugins");
1366     check("Is a subdirectory?", b ? "true" : "false", "true");
1367     check("relativePath(\"/home/bastian\", \"./src/plugins\")", KURL::relativePath(basePath, "./src/plugins"), "./src/plugins");
1368     check("relativePath(\"/home/bastian\", \"/home/waba/src/plugins\")", KURL::relativePath(basePath, "/home/waba/src/plugins", &b), "../waba/src/plugins");
1369     check("Is a subdirectory?", b ? "true" : "false", "false");
1370     check("relativePath(\"/home/bastian\", \"/\")", KURL::relativePath(basePath, "/"), "../../");
1371 
1372     check("relativePath(\"/\", \"/\")", KURL::relativePath("/", "/"), "./");
1373     check("relativePath(\"/\", \"/home/bastian\")", KURL::relativePath("/", "/home/bastian"), "./home/bastian");
1374     check("relativePath(\"\", \"/home/bastian\")", KURL::relativePath("", "/home/bastian"), "/home/bastian");
1375 
1376     baseURL = "http://www.kde.org/index.html";
1377     check("relativeURL(\"http://www.kde.org/index.html\", \"http://www.kde.org/index.html#help\")", KURL::relativeURL(baseURL, "http://www.kde.org/index.html#help"), "#help");
1378     check("relativeURL(\"http://www.kde.org/index.html\", \"http://www.kde.org/index.html?help=true\")", KURL::relativeURL(baseURL, "http://www.kde.org/index.html?help=true"), "index.html?help=true");
1379     check("relativeURL(\"http://www.kde.org/index.html\", \"http://www.kde.org/contact.html\")", KURL::relativeURL(baseURL, "http://www.kde.org/contact.html"), "contact.html");
1380     check("relativeURL(\"http://www.kde.org/index.html\", \"ftp://ftp.kde.org/pub/kde\")", KURL::relativeURL(baseURL, "ftp://ftp.kde.org/pub/kde"), "ftp://ftp.kde.org/pub/kde");
1381     check("relativeURL(\"http://www.kde.org/index.html\", \"http://www.kde.org/index.html\")", KURL::relativeURL(baseURL, "http://www.kde.org/index.html"), "./");
1382 
1383     baseURL = "http://www.kde.org/info/index.html";
1384     check("relativeURL(\"http://www.kde.org/info/index.html\", \"http://www.kde.org/bugs/contact.html\")", KURL::relativeURL(baseURL, "http://www.kde.org/bugs/contact.html"), "../bugs/contact.html");
1385 
1386     baseURL = "ptal://mlc:usb:PC_970";
1387     check("isValid()?", baseURL.isValid() ? "true" : "false", "false");
1388     check("url()", baseURL.url(), "ptal://mlc:usb:PC_970");
1389 
1390     baseURL = "http://mlc:80/";
1391     check("isValid()?", baseURL.isValid() ? "true" : "false", "true");
1392     check("port()?", QString::number(baseURL.port()), "80");
1393     check("path()?", baseURL.path(), "/");
1394 
1395     baseURL = "ptal://mlc:usb@PC_970"; // User=mlc, password=usb, host=PC_970
1396     check("isValid()?", baseURL.isValid() ? "true" : "false", "true");
1397     check("host()?", baseURL.host(), "pc_970");
1398     check("user()?", baseURL.user(), "mlc");
1399     check("pass()?", baseURL.pass(), "usb");
1400 
1401     weird = "ftp://user%40host.com@ftp.host.com/var/www/";
1402     check("user()?", weird.user(), "user@host.com" );
1403     check("host()?", weird.host(), "ftp.host.com" );
1404     KURL up = weird.upURL();
1405     check("KURL::upURL()", up.url(), "ftp://user%40host.com@ftp.host.com/var/");
1406     up = up.upURL();
1407     check("KURL::upURL()", up.url(), "ftp://user%40host.com@ftp.host.com/");
1408     up = up.upURL();
1409     check("KURL::upURL()", up.url(), "ftp://user%40host.com@ftp.host.com/"); // unchanged
1410 
1411     KURL ldap = "ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)";
1412     check("host()?", ldap.host(), "host.com");
1413     check("port()?", QString("%1").arg(ldap.port()), "6666");
1414     check("path()?", ldap.path(), "/o=University of Michigan,c=US");
1415     check("query()?", ldap.query(), "??sub?(cn=Babs%20Jensen)");
1416     check("url()?", ldap.url(), "ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)");
1417     ldap.setQuery("??sub?(cn=Karl%20Marx)");
1418     check("query()?", ldap.query(), "??sub?(cn=Karl%20Marx)");
1419     check("url()?", ldap.url(), "ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Karl%20Marx)");
1420 
1421     KURL leo = "data:text/html,http://www.invalid/";
1422     check("data URL: isValid", leo.isValid()?"valid":"malformed", "valid" );
1423     check("data URL: protocol", leo.protocol(), "data" );
1424     check("data URL: url", leo.url(), "data:text/html,http://www.invalid/" );
1425     check("data URL: path", leo.path(), "text/html,http://www.invalid/" );
1426 
1427 // URI Mode tests
1428     url1 = "http://www.foobar.com/";
1429     check("KURL(\"http://www.foobar.com/\").uriMode()", QString::number(url1.uriMode()), QString::number(KURL::URL));
1430     url1 = "mailto:user@host.com";
1431     check("KURL(\"mailto:user@host.com\").uriMode()", QString::number(url1.uriMode()), QString::number(KURL::Mailto));
1432     check("KURL(\"mailto:user@host.com\").url()", url1.url(), "mailto:user@host.com");
1433     check("KURL(\"mailto:user@host.com\").url(0, 106)", url1.url(0, 106), "mailto:user@host.com");
1434     url1 = "data:text/plain,foobar?gazonk=flarp";
1435     check("KURL(\"data:text/plain,foobar?gazonk=flarp\").uriMode()", QString::number(url1.uriMode()), QString::number(KURL::RawURI));
1436     check("KURL(\"data:text/plain,foobar?gazonk=flarp\").path()", url1.path(), "text/plain,foobar?gazonk=flarp");
1437     url1 = "mailto:User@Host.COM?subject=Hello";
1438     check("KURL(\"mailto:User@Host.COM?subject=Hello\").path()", url1.path(), "User@host.com");
1439 
1440     printf("\nTest OK !\n");
1441     */
1442 
1443 
1444         }
1445 
i18n_data()1446 void tst_QUrl::i18n_data()
1447 {
1448     QTest::addColumn<QString>("input");
1449     QTest::addColumn<QByteArray>("punyOutput");
1450 
1451     QTest::newRow("�l") << QString::fromLatin1("http://ole:passord@www.�l.no/index.html?ole=�semann&ilder gud=hei#top")
1452                      <<          QByteArray("http://ole:passord@www.xn--l-4ga.no/index.html?ole=%C3%A6semann&ilder%20gud=hei#top");
1453     QTest::newRow("r�ksm�rg�s") << QString::fromLatin1("http://www.r�ksm�rg�s.no/")
1454                              << QByteArray("http://www.xn--rksmrgs-5wao1o.no/");
1455     QTest::newRow("b�hler") << QString::fromLatin1("http://www.b�hler.no/")
1456                          << QByteArray("http://www.xn--bhler-kva.no/");
1457     QTest::newRow("non-latin1")
1458         << QString::fromUtf8("http://www.\316\261\316\270\316\256\316\275\316\261.info")
1459         << QByteArray("http://www.xn--jxafb0a0a.info");
1460 }
1461 
i18n()1462 void tst_QUrl::i18n()
1463 {
1464     QFETCH(QString, input);
1465     QFETCH(QByteArray, punyOutput);
1466 
1467     QUrl url(input);
1468     QVERIFY(url.isValid());
1469 
1470     QCOMPARE(url.toEncoded().constData(), punyOutput.constData());
1471     QCOMPARE(QUrl::fromEncoded(punyOutput), url);
1472     QCOMPARE(QUrl::fromEncoded(punyOutput).toString(), input);
1473 }
1474 
1475 
resolving_data()1476 void tst_QUrl::resolving_data()
1477 {
1478     QTest::addColumn<QString>("baseUrl");
1479     QTest::addColumn<QString>("relativeUrl");
1480     QTest::addColumn<QString>("relsolvedUrl");
1481 
1482     // 5.4.1 Normal Examples (http://www.ietf.org/rfc/rfc3986.txt)
1483     QTest::newRow("g:h")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g:h")      << QString::fromLatin1("g:h");
1484     QTest::newRow("g")         << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g")        << QString::fromLatin1("http://a/b/c/g");
1485     QTest::newRow("./g")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("./g")      << QString::fromLatin1("http://a/b/c/g");
1486     QTest::newRow("g/")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g/")       << QString::fromLatin1("http://a/b/c/g/");
1487     QTest::newRow("/g")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("/g")       << QString::fromLatin1("http://a/g");
1488     QTest::newRow("//g")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("//g")      << QString::fromLatin1("http://g");
1489     QTest::newRow("?y")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("?y")       << QString::fromLatin1("http://a/b/c/d;p?y");
1490     QTest::newRow("g?y")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g?y")      << QString::fromLatin1("http://a/b/c/g?y");
1491     QTest::newRow("#s")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("#s")       << QString::fromLatin1("http://a/b/c/d;p?q#s");
1492     QTest::newRow("g#s")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g#s")      << QString::fromLatin1("http://a/b/c/g#s");
1493     QTest::newRow("g?y#s")     << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g?y#s")    << QString::fromLatin1("http://a/b/c/g?y#s");
1494     QTest::newRow(";x")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1(";x")       << QString::fromLatin1("http://a/b/c/;x");
1495     QTest::newRow("g;x")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g;x")      << QString::fromLatin1("http://a/b/c/g;x");
1496     QTest::newRow("g;x?y#s")   << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g;x?y#s")  << QString::fromLatin1("http://a/b/c/g;x?y#s");
1497     QTest::newRow("[empty]")   << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("")         << QString::fromLatin1("http://a/b/c/d;p?q");
1498     QTest::newRow(".")         << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1(".")        << QString::fromLatin1("http://a/b/c/");
1499     QTest::newRow("./")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("./")       << QString::fromLatin1("http://a/b/c/");
1500     QTest::newRow("..")        << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("..")       << QString::fromLatin1("http://a/b/");
1501     QTest::newRow("../")       << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../")      << QString::fromLatin1("http://a/b/");
1502     QTest::newRow("../g")      << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../g")     << QString::fromLatin1("http://a/b/g");
1503     QTest::newRow("../..")     << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../..")    << QString::fromLatin1("http://a/");
1504     QTest::newRow("../../")    << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../../")   << QString::fromLatin1("http://a/");
1505     QTest::newRow("../../g")   << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../../g")  << QString::fromLatin1("http://a/g");
1506 
1507     // 5.4.2  Abnormal Examples (http://www.ietf.org/rfc/rfc3986.txt)
1508 
1509     // Parsers must be careful in handling cases where there are more
1510     // relative path ".." segments than there are hierarchical levels in the
1511     // base URI's path.  Note that the ".." syntax cannot be used to change
1512     // the authority component of a URI.
1513     QTest::newRow("../../../g")    << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../../../g")     << QString::fromLatin1("http://a/g");
1514     QTest::newRow("../../../../g") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("../../../../g")  << QString::fromLatin1("http://a/g");
1515 
1516     // Similarly, parsers must remove the dot-segments "." and ".." when
1517     // they are complete components of a path, but not when they are only
1518     // part of a segment.
1519     QTest::newRow("/./g")  << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("/./g")  << QString::fromLatin1("http://a/g");
1520     QTest::newRow("/../g") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("/../g") << QString::fromLatin1("http://a/g");
1521     QTest::newRow("g.")    << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g.")    << QString::fromLatin1("http://a/b/c/g.");
1522     QTest::newRow(".g")    << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1(".g")    << QString::fromLatin1("http://a/b/c/.g");
1523     QTest::newRow("g..")   << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g..")   << QString::fromLatin1("http://a/b/c/g..");
1524     QTest::newRow("..g")   << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("..g")   << QString::fromLatin1("http://a/b/c/..g");
1525 
1526     // Less likely are cases where the relative URI reference uses
1527     // unnecessary or nonsensical forms of the "." and ".." complete path
1528     // segments.
1529     QTest::newRow("./../g")     << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("./../g")     << QString::fromLatin1("http://a/b/g");
1530     QTest::newRow("./g/.")      << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("./g/.")      << QString::fromLatin1("http://a/b/c/g/");
1531     QTest::newRow("g/./h")      << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g/./h")      << QString::fromLatin1("http://a/b/c/g/h");
1532     QTest::newRow("g/../h")     << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g/../h")     << QString::fromLatin1("http://a/b/c/h");
1533     QTest::newRow("g;x=1/./y")  << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g;x=1/./y")  << QString::fromLatin1("http://a/b/c/g;x=1/y");
1534     QTest::newRow("g;x=1/../y") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g;x=1/../y") << QString::fromLatin1("http://a/b/c/y");
1535 
1536     // Some applications fail to separate the reference's query and/or
1537     // fragment components from a relative path before merging it with the
1538     // base path and removing dot-segments.  This error is rarely noticed,
1539     // since typical usage of a fragment never includes the hierarchy ("/")
1540     // character, and the query component is not normally used within
1541     // relative references.
1542     QTest::newRow("g?y/./x")  << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g?y/./x")  << QString::fromLatin1("http://a/b/c/g?y/./x");
1543     QTest::newRow("g?y/../x") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g?y/../x") << QString::fromLatin1("http://a/b/c/g?y/../x");
1544     QTest::newRow("g#s/./x")  << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g#s/./x")  << QString::fromLatin1("http://a/b/c/g#s/./x");
1545     QTest::newRow("g#s/../x") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("g#s/../x") << QString::fromLatin1("http://a/b/c/g#s/../x");
1546 
1547     // Some parsers allow the scheme name to be present in a relative URI
1548     // reference if it is the same as the base URI scheme.  This is
1549     // considered to be a loophole in prior specifications of partial URI
1550     // [RFC1630]. Its use should be avoided, but is allowed for backward
1551     // compatibility.
1552     // For strict parsers :
1553 //    QTest::newRow("http:g [for strict parsers]")         << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http:g");
1554     // For backward compatibility :
1555     QTest::newRow("http:g [for backward compatibility]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http://a/b/c/g");
1556 
1557     // Resolve relative with relative
1558     QTest::newRow("../a (1)")  << QString::fromLatin1("b") << QString::fromLatin1("../a")  << QString::fromLatin1("a");
1559     QTest::newRow("../a (2)")  << QString::fromLatin1("b/a") << QString::fromLatin1("../a")  << QString::fromLatin1("a");
1560     QTest::newRow("../a (3)")  << QString::fromLatin1("b/c/a") << QString::fromLatin1("../a")  << QString::fromLatin1("b/a");
1561     QTest::newRow("../a (4)")  << QString::fromLatin1("b") << QString::fromLatin1("/a")  << QString::fromLatin1("/a");
1562 
1563     QTest::newRow("../a (5)")  << QString::fromLatin1("/b") << QString::fromLatin1("../a")  << QString::fromLatin1("/a");
1564     QTest::newRow("../a (6)")  << QString::fromLatin1("/b/a") << QString::fromLatin1("../a")  << QString::fromLatin1("/a");
1565     QTest::newRow("../a (7)")  << QString::fromLatin1("/b/c/a") << QString::fromLatin1("../a")  << QString::fromLatin1("/b/a");
1566     QTest::newRow("../a (8)")  << QString::fromLatin1("/b") << QString::fromLatin1("/a")  << QString::fromLatin1("/a");
1567 }
1568 
resolving()1569 void tst_QUrl::resolving()
1570 {
1571     QFETCH(QString, baseUrl);
1572     QFETCH(QString, relativeUrl);
1573     QFETCH(QString, relsolvedUrl);
1574 
1575     QUrl url(baseUrl);
1576     QCOMPARE(url.resolved(relativeUrl).toString(), relsolvedUrl);
1577 }
1578 
1579 
toString_data()1580 void tst_QUrl::toString_data()
1581 {
1582     QTest::addColumn<QString>("urlString");
1583     QTest::addColumn<uint>("options");
1584     QTest::addColumn<QString>("string");
1585 
1586     QTest::newRow("data0")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1587 			<< uint(QUrl::RemoveScheme)
1588 			<< QString::fromLatin1("//ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top");
1589 
1590     QTest::newRow("data2")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1591 			<< uint(QUrl::RemovePassword)
1592 			<< QString::fromLatin1("http://ole@www.troll.no:9090/index.html?ole=semann&gud=hei#top");
1593 
1594     QTest::newRow("data3")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1595 			<< uint(QUrl::RemoveUserInfo)
1596 			<< QString::fromLatin1("http://www.troll.no:9090/index.html?ole=semann&gud=hei#top");
1597 
1598     QTest::newRow("data4")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1599 			<< uint(QUrl::RemovePort)
1600 			<< QString::fromLatin1("http://ole:password@www.troll.no/index.html?ole=semann&gud=hei#top");
1601 
1602     QTest::newRow("data5")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1603 			<< uint(QUrl::RemoveAuthority)
1604 			<< QString::fromLatin1("http:/index.html?ole=semann&gud=hei#top");
1605 
1606     QTest::newRow("data6")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1607 			<< uint(QUrl::RemovePath)
1608 			<< QString::fromLatin1("http://ole:password@www.troll.no:9090?ole=semann&gud=hei#top");
1609 
1610     QTest::newRow("data7")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1611 			<< uint(QUrl::RemoveQuery)
1612 			<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html#top");
1613 
1614     QTest::newRow("data8")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1615 			<< uint(QUrl::RemoveFragment)
1616 			<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei");
1617 
1618     QTest::newRow("data9")	<< QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1619 			<< uint(QUrl::RemoveScheme | QUrl::RemovePassword)
1620 			<< QString::fromLatin1("//ole@www.troll.no:9090/index.html?ole=semann&gud=hei#top");
1621 
1622     QTest::newRow("data10") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1623 			 << uint(QUrl::RemoveScheme | QUrl::RemoveUserInfo)
1624 			 << QString::fromLatin1("//www.troll.no:9090/index.html?ole=semann&gud=hei#top");
1625 
1626     QTest::newRow("data11") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1627 			 << uint(QUrl::RemoveScheme | QUrl::RemovePort)
1628 			 << QString::fromLatin1("//ole:password@www.troll.no/index.html?ole=semann&gud=hei#top");
1629 
1630     QTest::newRow("data12") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1631 			 << uint(QUrl::RemoveScheme | QUrl::RemoveAuthority)
1632 			 << QString::fromLatin1("/index.html?ole=semann&gud=hei#top");
1633 
1634     QTest::newRow("data13") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1635 			 << uint(QUrl::RemoveScheme | QUrl::RemovePath)
1636 			 << QString::fromLatin1("//ole:password@www.troll.no:9090?ole=semann&gud=hei#top");
1637 
1638     QTest::newRow("data14") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1639 			 << uint(QUrl::RemoveScheme | QUrl::RemoveAuthority | QUrl::RemoveFragment)
1640 			 << QString::fromLatin1("/index.html?ole=semann&gud=hei");
1641 
1642     QTest::newRow("data15") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1643 			 << uint(QUrl::RemoveAuthority | QUrl::RemoveQuery)
1644 			 << QString::fromLatin1("http:/index.html#top");
1645 
1646     QTest::newRow("data16") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1647 			 << uint(QUrl::RemovePassword | QUrl::RemovePort
1648 			    | QUrl::RemovePath | QUrl::RemoveQuery
1649 			    | QUrl::RemoveFragment)
1650 			 << QString::fromLatin1("http://ole@www.troll.no");
1651 
1652     QTest::newRow("data17") << QString::fromLatin1("http://ole:password@www.troll.no:9090/index.html?ole=semann&gud=hei#top")
1653 			 << uint(QUrl::RemoveScheme | QUrl::RemovePassword
1654 			    | QUrl::RemovePort | QUrl::RemovePath
1655 			    | QUrl::RemoveQuery | QUrl::RemoveFragment)
1656 			 << QString::fromLatin1("//ole@www.troll.no");
1657 
1658     QTest::newRow("data18") << QString::fromLatin1("http://andreas:hemmelig@www.vg.no/?my=query&your=query#yougotfragged")
1659                          << uint(QUrl::None)
1660                          << QString::fromLatin1("http://andreas:hemmelig@www.vg.no/?my=query&your=query#yougotfragged");
1661 
1662     /*
1663     QTest::newRow("data19") << QString::fromLatin1("http://andreas:hemmelig@www.vg.no/a/../?my=query&your=query#yougotfragged")
1664                          << uint(QUrl::None)
1665                          << QString::fromLatin1("http://andreas:hemmelig@www.vg.no/?my=query&your=query#yougotfragged");
1666     */
1667 
1668     QTest::newRow("nopath_task31320") << QString::fromLatin1("host://protocol")
1669                                    << uint(QUrl::None)
1670                                    << QString::fromLatin1("host://protocol");
1671 
1672     QTest::newRow("underscore_QTBUG-7434") << QString::fromLatin1("http://foo_bar.host.com/rss.php")
1673                                    << uint(QUrl::None)
1674                                    << QString::fromLatin1("http://foo_bar.host.com/rss.php");
1675 }
1676 
toString()1677 void tst_QUrl::toString()
1678 {
1679     QFETCH(QString, urlString);
1680     QFETCH(uint, options);
1681     QFETCH(QString, string);
1682 
1683     QUrl url(urlString);
1684     QCOMPARE(url.toString(QUrl::FormattingOptions(options)), string);
1685 }
1686 
1687 //### more tests ... what do we expect ...
isParentOf_data()1688 void tst_QUrl::isParentOf_data()
1689 {
1690     QTest::addColumn<QString>("parent");
1691     QTest::addColumn<QString>("child");
1692     QTest::addColumn<bool>("trueFalse");
1693 
1694     QTest::newRow("data0")	<< QString::fromLatin1("http://a.b.c/d")
1695 			<< QString::fromLatin1("http://a.b.c/d/e?f") << true;
1696     QTest::newRow("data1")	<< QString::fromLatin1("http://a.b.c/d")
1697 			<< QString::fromLatin1("http://a.b.c/d") << false;
1698     QTest::newRow("data2")	<< QString::fromLatin1("http://a.b.c/d")
1699 			<< QString::fromLatin1("http://a.b.c/de") << false;
1700     QTest::newRow("data3")	<< QString::fromLatin1("http://a.b.c/d/")
1701 			<< QString::fromLatin1("http://a.b.c/de") << false;
1702     QTest::newRow("data4")	<< QString::fromLatin1("http://a.b.c/d/")
1703 			<< QString::fromLatin1("http://a.b.c/d/e") << true;
1704 
1705 
1706 }
1707 
toString_constructed_data()1708 void tst_QUrl::toString_constructed_data()
1709 {
1710     QTest::addColumn<QString>("scheme");
1711     QTest::addColumn<QString>("userName");
1712     QTest::addColumn<QString>("password");
1713     QTest::addColumn<QString>("host");
1714     QTest::addColumn<int>("port");
1715     QTest::addColumn<QString>("path");
1716     QTest::addColumn<QByteArray>("query");
1717     QTest::addColumn<QString>("fragment");
1718     QTest::addColumn<QString>("asString");
1719     QTest::addColumn<QByteArray>("asEncoded");
1720 
1721     QString n("");
1722 
1723     QTest::newRow("data1") << n << n << n << QString::fromLatin1("qt.nokia.com") << -1 << QString::fromLatin1("index.html")
1724 	                << QByteArray() << n << QString::fromLatin1("//qt.nokia.com/index.html")
1725 			<< QByteArray("//qt.nokia.com/index.html");
1726     QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray()
1727                         << n << QString::fromLatin1("file:///root") << QByteArray("file:///root");
1728     QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde")
1729                                  << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
1730                                  << QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/");
1731     QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde")
1732                                      << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
1733                                      << QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/");
1734 }
1735 
toString_constructed()1736 void tst_QUrl::toString_constructed()
1737 {
1738     QFETCH(QString, scheme);
1739     QFETCH(QString, userName);
1740     QFETCH(QString, password);
1741     QFETCH(QString, host);
1742     QFETCH(int, port);
1743     QFETCH(QString, path);
1744     QFETCH(QByteArray, query);
1745     QFETCH(QString, fragment);
1746     QFETCH(QString, asString);
1747     QFETCH(QByteArray, asEncoded);
1748 
1749     QUrl url;
1750     if (!scheme.isEmpty())
1751 	url.setScheme(scheme);
1752     if (!userName.isEmpty())
1753 	url.setUserName(userName);
1754     if (!password.isEmpty())
1755 	url.setPassword(password);
1756     if (!host.isEmpty())
1757 	url.setHost(host);
1758     if (port != -1)
1759 	url.setPort(port);
1760     if (!path.isEmpty())
1761 	url.setPath(path);
1762     if (!query.isEmpty())
1763 	url.setEncodedQuery(query);
1764     if (!fragment.isEmpty())
1765 	url.setFragment(fragment);
1766 
1767     QVERIFY(url.isValid());
1768     QCOMPARE(url.toString(), asString);
1769     QCOMPARE(QString::fromLatin1(url.toEncoded()), QString::fromLatin1(asEncoded)); // readable in case of differences
1770     QCOMPARE(url.toEncoded(), asEncoded);
1771 }
1772 
1773 
isParentOf()1774 void tst_QUrl::isParentOf()
1775 {
1776     QFETCH(QString, parent);
1777     QFETCH(QString, child);
1778     QFETCH(bool, trueFalse);
1779 
1780     QUrl url(parent);
1781     QCOMPARE(url.isParentOf(QUrl(child)), trueFalse);
1782 }
1783 
toLocalFile_data()1784 void tst_QUrl::toLocalFile_data()
1785 {
1786     QTest::addColumn<QString>("theUrl");
1787     QTest::addColumn<QString>("theFile");
1788 
1789     QTest::newRow("data0")	<< QString::fromLatin1("file:/a.txt") << QString::fromLatin1("/a.txt");
1790     QTest::newRow("data4")	<< QString::fromLatin1("file:///a.txt") << QString::fromLatin1("/a.txt");
1791     QTest::newRow("data5")	<< QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("c:/a.txt");
1792     QTest::newRow("data6")	<< QString::fromLatin1("file://somehost/somedir/somefile") << QString::fromLatin1("//somehost/somedir/somefile");
1793     QTest::newRow("data7")	<< QString::fromLatin1("file://somehost/") << QString::fromLatin1("//somehost/");
1794     QTest::newRow("data8")	<< QString::fromLatin1("file://somehost") << QString::fromLatin1("//somehost");
1795     QTest::newRow("data9")	<< QString::fromLatin1("file:////somehost/somedir/somefile") << QString::fromLatin1("//somehost/somedir/somefile");
1796     QTest::newRow("data10")	<< QString::fromLatin1("FILE:/a.txt") << QString::fromLatin1("/a.txt");
1797 
1798     // relative urls
1799     QTest::newRow("relative0") << QString::fromLatin1("a.txt") << QString::fromLatin1("a.txt");
1800     QTest::newRow("relative1") << QString::fromLatin1("/a.txt") << QString::fromLatin1("/a.txt");
1801     QTest::newRow("relative2") << QString::fromLatin1("//a.txt") << QString::fromLatin1("//a.txt");
1802 
1803     // and some that result in empty (i.e., not local)
1804     QTest::newRow("xdata3") << QString::fromLatin1("foo:/a.txt") << QString();
1805     QTest::newRow("xdata4") << QString::fromLatin1("foo://a.txt") << QString();
1806     QTest::newRow("xdata5") << QString::fromLatin1("foo:///a.txt") << QString();
1807 }
1808 
toLocalFile()1809 void tst_QUrl::toLocalFile()
1810 {
1811     QFETCH(QString, theUrl);
1812     QFETCH(QString, theFile);
1813 
1814     QUrl url(theUrl);
1815     QCOMPARE(url.toLocalFile(), theFile);
1816 }
1817 
fromLocalFile_data()1818 void tst_QUrl::fromLocalFile_data()
1819 {
1820     QTest::addColumn<QString>("theFile");
1821     QTest::addColumn<QString>("theUrl");
1822     QTest::addColumn<QString>("thePath");
1823 
1824     QTest::newRow("data0")	<< QString::fromLatin1("/a.txt") << QString::fromLatin1("file:///a.txt") << QString::fromLatin1("/a.txt");
1825     QTest::newRow("data1")	<< QString::fromLatin1("a.txt") << QString::fromLatin1("file:a.txt") << QString::fromLatin1("a.txt");
1826     QTest::newRow("data2")	<< QString::fromLatin1("/a/b.txt") << QString::fromLatin1("file:///a/b.txt") << QString::fromLatin1("/a/b.txt");
1827     QTest::newRow("data3")	<< QString::fromLatin1("c:/a.txt") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("/c:/a.txt");
1828     QTest::newRow("data4")	<< QString::fromLatin1("//somehost/somedir/somefile") << QString::fromLatin1("file://somehost/somedir/somefile")
1829 	                << QString::fromLatin1("/somedir/somefile");
1830     QTest::newRow("data5")	<< QString::fromLatin1("//somehost") << QString::fromLatin1("file://somehost")
1831 	                << QString::fromLatin1("");
1832     QTest::newRow("data6")	<< QString::fromLatin1("//somehost/") << QString::fromLatin1("file://somehost/")
1833 	                << QString::fromLatin1("/");
1834 }
1835 
fromLocalFile()1836 void tst_QUrl::fromLocalFile()
1837 {
1838     QFETCH(QString, theFile);
1839     QFETCH(QString, theUrl);
1840     QFETCH(QString, thePath);
1841 
1842     QUrl url = QUrl::fromLocalFile(theFile);
1843 
1844     QCOMPARE(url.toString(), theUrl);
1845     QCOMPARE(url.path(), thePath);
1846 }
1847 
compat_legacy()1848 void tst_QUrl::compat_legacy()
1849 {
1850     {
1851 	QUrl u( "file:bar" );
1852 	QCOMPARE( u.toString(QUrl::RemoveScheme), QString("bar") );
1853     }
1854 
1855     /* others
1856      */
1857     {
1858 	QUrl u( "http://qt.nokia.com/images/ban/pgs_front.jpg" );
1859 	QCOMPARE( u.path(), QString("/images/ban/pgs_front.jpg") );
1860     }
1861     {
1862 	QUrl tmp( "http://qt.nokia.com/images/ban/" );
1863 	QUrl u = tmp.resolved(QString("pgs_front.jpg"));
1864 	QCOMPARE( u.path(), QString("/images/ban/pgs_front.jpg") );
1865     }
1866     {
1867 	QUrl tmp;
1868 	QUrl u = tmp.resolved(QString("http://qt.nokia.com/images/ban/pgs_front.jpg"));
1869 	QCOMPARE( u.path(), QString("/images/ban/pgs_front.jpg") );
1870     }
1871     {
1872 	QUrl tmp;
1873 	QUrl u = tmp.resolved(QString("http://qt.nokia.com/images/ban/pgs_front.jpg"));
1874 	QFileInfo fi(u.path());
1875 	u.setPath(fi.path());
1876 	QCOMPARE( u.path(), QString("/images/ban") );
1877     }
1878 }
1879 
compat_constructor_01_data()1880 void tst_QUrl::compat_constructor_01_data()
1881 {
1882     QTest::addColumn<QString>("urlStr");
1883     QTest::addColumn<QString>("res");
1884 
1885     //next we fill it with data
1886     QTest::newRow( "data0" )  << QString("Makefile") << QString("Makefile"); // nolonger add file by default
1887     QTest::newRow( "data1" )  << QString("Makefile") << QString("Makefile");
1888     QTest::newRow( "data2" )  << QString("ftp://ftp.qt.nokia.com/qt/INSTALL") << QString("ftp://ftp.qt.nokia.com/qt/INSTALL");
1889     QTest::newRow( "data3" )  << QString("ftp://ftp.qt.nokia.com/qt/INSTALL") << QString("ftp://ftp.qt.nokia.com/qt/INSTALL");
1890 }
1891 
compat_constructor_01()1892 void tst_QUrl::compat_constructor_01()
1893 {
1894     /* The following should work as expected:
1895      *
1896      * QUrlOperator op;
1897      * op.copy( QString( "Makefile" ),
1898      *          QString("ftp://rms:grmpf12@nibbler/home/rms/tmp"),
1899      *          false );
1900      *
1901      * as well as the following:
1902      *
1903      * QUrlOperator op;
1904      * op.copy(QString("ftp://ftp.qt.nokia.com/qt/INSTALL"), ".");
1905      */
1906     QFETCH( QString, urlStr );
1907 
1908     {
1909 	QUrl empty;
1910 	QUrl u = empty.resolved(urlStr);
1911 
1912 	QTEST( u.toString(), "res" );
1913     }
1914     {
1915 	QUrl empty;
1916 	QUrl u = empty.resolved(urlStr);
1917 
1918 	QTEST( u.toString(), "res" );
1919     }
1920 }
1921 
compat_constructor_02_data()1922 void tst_QUrl::compat_constructor_02_data()
1923 {
1924     QTest::addColumn<QString>("urlStr");
1925     QTest::addColumn<QString>("fileName");
1926     QTest::addColumn<QString>("res");
1927 
1928     //next we fill it with data
1929     QTest::newRow( "data0" )  << QString("ftp://ftp.qt.nokia.com/qt") << QString("INSTALL") << QString("ftp://ftp.qt.nokia.com/INSTALL");
1930     QTest::newRow( "data1" )  << QString("ftp://ftp.qt.nokia.com/qt/") << QString("INSTALL") << QString("ftp://ftp.qt.nokia.com/qt/INSTALL");
1931 }
1932 
compat_constructor_02()1933 void tst_QUrl::compat_constructor_02()
1934 {
1935     /* The following should work as expected:
1936      *
1937      * QUrlOperator op( "ftp://ftp.qt.nokia.com/qt" );
1938      * op.copy(QString("INSTALL"), ".");
1939      */
1940     QFETCH( QString, urlStr );
1941     QFETCH( QString, fileName );
1942 
1943     QUrl tmp( urlStr );
1944     QUrl u = tmp.resolved(fileName);
1945 
1946     QTEST( u.toString(), "res" );
1947 }
1948 
compat_constructor_03_data()1949 void tst_QUrl::compat_constructor_03_data()
1950 {
1951     QTest::addColumn<QString>("urlStr");
1952     QTest::addColumn<QString>("res");
1953 
1954     //next we fill it with data
1955     QTest::newRow( "protocol00" )  << QString( "http://qt.nokia.com/index.html" ) << QString( "http://qt.nokia.com/index.html" );
1956     QTest::newRow( "protocol01" )  << QString( "http://qt.nokia.com" ) << QString( "http://qt.nokia.com" );
1957     QTest::newRow( "protocol02" )  << QString( "http://qt.nokia.com/" ) << QString( "http://qt.nokia.com/" );
1958     QTest::newRow( "protocol03" )  << QString( "http://qt.nokia.com/foo" ) << QString( "http://qt.nokia.com/foo" );
1959     QTest::newRow( "protocol04" )  << QString( "http://qt.nokia.com/foo/" ) << QString( "http://qt.nokia.com/foo/" );
1960     QTest::newRow( "protocol05" )  << QString( "ftp://ftp.qt.nokia.com/foo/index.txt" ) << QString( "ftp://ftp.qt.nokia.com/foo/index.txt" );
1961 
1962     QTest::newRow( "local00" )  << QString( "/foo" ) << QString( "/foo" );
1963     QTest::newRow( "local01" )  << QString( "/foo/" ) << QString( "/foo/" );
1964     QTest::newRow( "local02" )  << QString( "/foo/bar" ) << QString( "/foo/bar" );
1965     QTest::newRow( "local03" )  << QString( "/foo/bar/" ) << QString( "/foo/bar/" );
1966     QTest::newRow( "local04" )  << QString( "foo" ) << QString( "foo" );
1967     QTest::newRow( "local05" )  << QString( "foo/" ) << QString( "foo/" );
1968     QTest::newRow( "local06" )  << QString( "foo/bar" ) << QString( "foo/bar" );
1969     QTest::newRow( "local07" )  << QString( "foo/bar/" ) << QString( "foo/bar/" );
1970     QTest::newRow( "local09" )  << QString( "" ) << QString( "" );
1971 
1972     QTest::newRow( "file00" )  << QString( "file:/foo" ) << QString( "file:///foo" );
1973     QTest::newRow( "file01" )  << QString( "file:/foo/" ) << QString( "file:///foo/" );
1974     QTest::newRow( "file02" )  << QString( "file:/foo/bar" ) << QString( "file:///foo/bar" );
1975     QTest::newRow( "file03" )  << QString( "file:/foo/bar/" ) << QString( "file:///foo/bar/" );
1976     QTest::newRow( "relProtocol00" )  << QString( "foo:bar" ) << QString( "foo:bar" );
1977     QTest::newRow( "relProtocol01" )  << QString( "foo:/bar" ) << QString( "foo:/bar" );
1978 
1979     QTest::newRow( "windowsDrive00" )  << QString( "c:/" ) << QString( "c:/" );
1980     QTest::newRow( "windowsDrive01" )  << QString( "c:" ) << QString( "c:" );
1981     QTest::newRow( "windowsDrive02" )  << QString( "c:/WinNT/" ) << QString( "c:/WinNT/" );
1982     QTest::newRow( "windowsDrive03" )  << QString( "c:/autoexec.bat" ) << QString( "c:/autoexec.bat" );
1983     QTest::newRow( "windowsDrive04" )  << QString( "c:WinNT/" ) << QString( "c:WinNT/" );
1984     QTest::newRow( "windowsDrive05" )  << QString( "c:autoexec.bat" ) << QString( "c:autoexec.bat" );
1985 
1986     QTest::newRow("task31280") << QString("protocol://host") << QString("protocol://host");
1987 }
1988 
compat_constructor_03()1989 void tst_QUrl::compat_constructor_03()
1990 {
1991     QFETCH( QString, urlStr );
1992 
1993     QUrl u( urlStr );
1994     QTEST( u.toString(), "res" );
1995 }
1996 
compat_isValid_01_data()1997 void tst_QUrl::compat_isValid_01_data()
1998 {
1999     QTest::addColumn<QString>("urlStr");
2000     QTest::addColumn<bool>("res");
2001 
2002     QTest::newRow( "ok_01" ) << QString("ftp://ftp.qt.nokia.com/qt/INSTALL") << (bool)true;
2003     QTest::newRow( "ok_02" ) << QString( "file:/foo") << (bool)true;
2004     QTest::newRow( "ok_03" ) << QString( "file:foo") << (bool)true;
2005 
2006     QTest::newRow( "err_01" ) << QString("#ftp://ftp.qt.nokia.com/qt/INSTALL") << (bool)true;
2007     QTest::newRow( "err_02" ) << QString( "file:/::foo") << (bool)true;
2008 }
2009 
compat_isValid_01()2010 void tst_QUrl::compat_isValid_01()
2011 {
2012     QFETCH( QString, urlStr );
2013     QFETCH( bool, res );
2014 
2015     QUrl url( urlStr );
2016     QVERIFY( url.isValid() == res );
2017 }
2018 
compat_isValid_02_data()2019 void tst_QUrl::compat_isValid_02_data()
2020 {
2021     QTest::addColumn<QString>("protocol");
2022     QTest::addColumn<QString>("user");
2023     QTest::addColumn<QString>("password");
2024     QTest::addColumn<QString>("host");
2025     QTest::addColumn<int>("port");
2026     QTest::addColumn<QString>("path");
2027     QTest::addColumn<bool>("res");
2028 
2029     QString n = "";
2030 
2031     QTest::newRow( "ok_01" ) << n     << n     << n     << n                   << -1 << QString("path") << (bool)true;
2032     QTest::newRow( "ok_02" ) << QString("ftp") << n     << n     << QString("ftp.qt.nokia.com") << -1 << n      << (bool)true;
2033     QTest::newRow( "ok_03" ) << QString("ftp") << QString("foo") << n     << QString("ftp.qt.nokia.com") << -1 << n      << (bool)true;
2034     QTest::newRow( "ok_04" ) << QString("ftp") << QString("foo") << QString("bar") << QString("ftp.qt.nokia.com") << -1 << n      << (bool)true;
2035     QTest::newRow( "ok_05" ) << QString("ftp") << n     << n     << QString("ftp.qt.nokia.com") << -1 << QString("path")<< (bool)true;
2036     QTest::newRow( "ok_06" ) << QString("ftp") << QString("foo") << n     << QString("ftp.qt.nokia.com") << -1 << QString("path") << (bool)true;
2037     QTest::newRow( "ok_07" ) << QString("ftp") << QString("foo") << QString("bar") << QString("ftp.qt.nokia.com") << -1 << QString("path")<< (bool)true;
2038 
2039     QTest::newRow( "err_01" ) << n     << n     << n     << n                   << -1 << n << (bool)false;
2040     QTest::newRow( "err_02" ) << QString("ftp") << n     << n     << n                   << -1 << n << (bool)true;
2041     QTest::newRow( "err_03" ) << n     << QString("foo") << n     << n                   << -1 << n << (bool)true;
2042     QTest::newRow( "err_04" ) << n     << n     << QString("bar") << n                   << -1 << n << (bool)true;
2043     QTest::newRow( "err_05" ) << n     << n     << n     << QString("ftp.qt.nokia.com") << -1 << n << (bool)true;
2044     QTest::newRow( "err_06" ) << n     << n     << n     << n                   << 80 << n << (bool)true;
2045     QTest::newRow( "err_07" ) << QString("ftp") << QString("foo") << n     << n                   << -1 << n << (bool)true;
2046     QTest::newRow( "err_08" ) << QString("ftp") << n     << QString("bar") << n                   << -1 << n << (bool)true;
2047     QTest::newRow( "err_09" ) << QString("ftp") << QString("foo") << QString("bar") << n                   << -1 << n << (bool)true;
2048 }
2049 
compat_isValid_02()2050 void tst_QUrl::compat_isValid_02()
2051 {
2052     QFETCH( QString, protocol );
2053     QFETCH( QString, user );
2054     QFETCH( QString, password );
2055     QFETCH( QString, host );
2056     QFETCH( int, port );
2057     QFETCH( QString, path );
2058     QFETCH( bool, res );
2059 
2060     QUrl url;
2061     if ( !protocol.isEmpty() )
2062 	url.setScheme( protocol );
2063     if ( !user.isEmpty() )
2064 	url.setUserName( user );
2065     if ( !password.isEmpty() )
2066 	url.setPassword( password );
2067     if ( !host.isEmpty() )
2068 	url.setHost( host );
2069     if ( port != -1 )
2070 	url.setPort( port );
2071     if ( !path.isEmpty() )
2072 	url.setPath( path );
2073 
2074     QVERIFY( url.isValid() == res );
2075 }
2076 
compat_path_data()2077 void tst_QUrl::compat_path_data()
2078 {
2079     QTest::addColumn<QString>("url");
2080     QTest::addColumn<QString>("res");
2081 
2082     QTest::newRow( "protocol00" ) << "http://qt.nokia.com/images/ban/pgs_front.jpg" << "/images/ban/pgs_front.jpg";
2083 
2084 #if defined( Q_OS_WIN32 )
2085     QTest::newRow( "winShare00" ) << "//Anarki/homes" << "/homes";
2086 #endif
2087 }
2088 
compat_path()2089 void tst_QUrl::compat_path()
2090 {
2091     QFETCH( QString, url );
2092 
2093     QUrl u( url );
2094     QTEST( u.path(), "res" );
2095 }
2096 
compat_fileName_data()2097 void tst_QUrl::compat_fileName_data()
2098 {
2099     QTest::addColumn<QString>("url");
2100     QTest::addColumn<QString>("fileName");
2101 
2102 #ifdef Q_OS_WIN32
2103     QTest::newRow( "Windows - DrivePathFileName - \\" ) << QString("c:\\windows\\tmp\\filename.txt")<< QString("filename.txt");
2104     QTest::newRow( "Windows - DrivePathFileName - /" ) << QString("c:/windows/tmp/filename.txt") << QString("filename.txt");
2105     QTest::newRow( "Windows - DrivePathWithSlash - \\" ) << QString("c:\\windows\\tmp\\") << QString();
2106     QTest::newRow( "Windows - DrivePathWithSlash - /" ) << QString("c:/windows/tmp/") << QString();
2107     QTest::newRow( "Windows - DrivePathWithoutSlash - \\" ) << QString("c:/windows/tmp") << QString("tmp");
2108     QTest::newRow( "Windows - DrivePathWithoutSlash - /" ) << QString("c:/windows/tmp") << QString("tmp");
2109 #endif
2110     QTest::newRow( "Path00" ) << QString("/") << QString();
2111     QTest::newRow( "Path01" ) << QString("/home/dev/test/") << QString();
2112     QTest::newRow( "PathFileName00" ) << QString("/home/dev/test") << QString("test");
2113 }
2114 
compat_fileName()2115 void tst_QUrl::compat_fileName()
2116 {
2117     QFETCH( QString, url );
2118     QFETCH( QString, fileName );
2119     QUrl fileUrl = QUrl::fromLocalFile(url);
2120     QFileInfo fi(fileUrl.toLocalFile());
2121     QCOMPARE( fi.fileName(), fileName );
2122 }
2123 
compat_decode_data()2124 void tst_QUrl::compat_decode_data()
2125 {
2126     QTest::addColumn<QByteArray>("encodedString");
2127     QTest::addColumn<QString>("decodedString");
2128 
2129     QTest::newRow("NormalString") << QByteArray("filename") << QString("filename");
2130     QTest::newRow("NormalStringEncoded") << QByteArray("file%20name") << QString("file name");
2131     QTest::newRow("JustEncoded") << QByteArray("%20") << QString(" ");
2132     QTest::newRow("HTTPUrl") << QByteArray("http://qt.nokia.com") << QString("http://qt.nokia.com");
2133     QTest::newRow("HTTPUrlEncoded") << QByteArray("http://qt%20nokia%20com") << QString("http://qt nokia com");
2134     QTest::newRow("EmptyString") << QByteArray("") << QString("");
2135     QTest::newRow("Task27166") << QByteArray("Fran%C3%A7aise") << QString("Fran�aise");
2136 }
2137 
compat_decode()2138 void tst_QUrl::compat_decode()
2139 {
2140     QFETCH(QByteArray, encodedString);
2141     QFETCH(QString, decodedString);
2142 
2143     QCOMPARE(QUrl::fromPercentEncoding(encodedString), decodedString);
2144 }
2145 
compat_encode_data()2146 void tst_QUrl::compat_encode_data()
2147 {
2148     QTest::addColumn<QString>("decodedString");
2149     QTest::addColumn<QByteArray>("encodedString");
2150 
2151     QTest::newRow("NormalString") << QString("filename") << QByteArray("filename");
2152     QTest::newRow("NormalStringEncoded") << QString("file name") << QByteArray("file%20name");
2153     QTest::newRow("JustEncoded") << QString(" ") << QByteArray("%20");
2154     QTest::newRow("HTTPUrl") << QString("http://qt.nokia.com") << QByteArray("http%3A//qt.nokia.com");
2155     QTest::newRow("HTTPUrlEncoded") << QString("http://qt nokia com") << QByteArray("http%3A//qt%20nokia%20com");
2156     QTest::newRow("EmptyString") << QString("") << QByteArray("");
2157     QTest::newRow("Task27166") << QString::fromLatin1("Fran�aise") << QByteArray("Fran%C3%A7aise");
2158 }
2159 
compat_encode()2160 void tst_QUrl::compat_encode()
2161 {
2162     QFETCH(QString, decodedString);
2163     QFETCH(QByteArray, encodedString);
2164 
2165     QCOMPARE(QUrl::toPercentEncoding(decodedString, "/.").constData(), encodedString.constData());
2166 }
2167 
2168 
relative()2169 void tst_QUrl::relative()
2170 {
2171     QUrl url("../ole");
2172     QCOMPARE(url.path(), QString::fromLatin1("../ole"));
2173 
2174     QUrl url2("./");
2175     QCOMPARE(url2.path(), QString::fromLatin1("./"));
2176 
2177     QUrl url3("..");
2178     QCOMPARE(url3.path(), QString::fromLatin1(".."));
2179 
2180     QUrl url4("../..");
2181     QCOMPARE(url4.path(), QString::fromLatin1("../.."));
2182 }
2183 
percentEncoding_data()2184 void tst_QUrl::percentEncoding_data()
2185 {
2186     QTest::addColumn<QString>("original");
2187     QTest::addColumn<QByteArray>("encoded");
2188 
2189     QTest::newRow("test_01") << QString::fromLatin1("sdfsdf") << QByteArray("sdfsdf");
2190     QTest::newRow("test_02") << QString::fromLatin1("�ss") << QByteArray("%C3%A6ss");
2191     // not unreserved or reserved
2192     QTest::newRow("test_03") << QString::fromLatin1("{}") << QByteArray("%7B%7D");
2193 }
2194 
percentEncoding()2195 void tst_QUrl::percentEncoding()
2196 {
2197     QFETCH(QString, original);
2198     QFETCH(QByteArray, encoded);
2199 
2200     QCOMPARE(QUrl(original).toEncoded().constData(), encoded.constData());
2201     QVERIFY(QUrl::fromEncoded(QUrl(original).toEncoded()) == QUrl(original));
2202     QCOMPARE(QUrl::fromEncoded(QUrl(original).toEncoded()).toString(), original);
2203     QVERIFY(QUrl::fromEncoded(encoded) == QUrl(original));
2204 }
2205 
toPercentEncoding_data()2206 void tst_QUrl::toPercentEncoding_data()
2207 {
2208     QTest::addColumn<QString>("original");
2209     QTest::addColumn<QByteArray>("encoded");
2210     QTest::addColumn<QByteArray>("excludeInEncoding");
2211     QTest::addColumn<QByteArray>("includeInEncoding");
2212 
2213     QTest::newRow("test_01") << QString::fromLatin1("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~")
2214                           << QByteArray("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~")
2215                           << QByteArray("")
2216                           << QByteArray("");
2217     QTest::newRow("test_02") << QString::fromLatin1("{\t\n\r^\"abc}")
2218                           << QByteArray("%7B%09%0A%0D%5E%22abc%7D")
2219                           << QByteArray("")
2220                           << QByteArray("");
2221     QTest::newRow("test_03") << QString::fromLatin1("://?#[]@!$&'()*+,;=")
2222                           << QByteArray("%3A%2F%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D")
2223                           << QByteArray("")
2224                           << QByteArray("");
2225     QTest::newRow("test_04") << QString::fromLatin1("://?#[]@!$&'()*+,;=")
2226                           << QByteArray("%3A%2F%2F%3F%23%5B%5D%40!$&'()*+,;=")
2227                           << QByteArray("!$&'()*+,;=")
2228                           << QByteArray("");
2229     QTest::newRow("test_05") << QString::fromLatin1("abcd")
2230                           << QByteArray("a%62%63d")
2231                           << QByteArray("")
2232                           << QByteArray("bc");
2233 }
2234 
toPercentEncoding()2235 void tst_QUrl::toPercentEncoding()
2236 {
2237     QFETCH(QString, original);
2238     QFETCH(QByteArray, encoded);
2239     QFETCH(QByteArray, excludeInEncoding);
2240     QFETCH(QByteArray, includeInEncoding);
2241 
2242     QByteArray encodedUrl = QUrl::toPercentEncoding(original, excludeInEncoding, includeInEncoding);
2243     QCOMPARE(encodedUrl.constData(), encoded.constData());
2244     QCOMPARE(original, QUrl::fromPercentEncoding(encodedUrl));
2245 }
2246 
swap()2247 void tst_QUrl::swap()
2248 {
2249     QUrl u1(QLatin1String("http://qt.nokia.com")), u2(QLatin1String("http://www.kdab.com"));
2250     u1.swap(u2);
2251     QCOMPARE(u2.host(),QLatin1String("qt.nokia.com"));
2252     QCOMPARE(u1.host(),QLatin1String("www.kdab.com"));
2253 }
2254 
symmetry()2255 void tst_QUrl::symmetry()
2256 {
2257     QUrl url(QString::fromLatin1("http://www.r�ksm�rg�s.se/pub?a=b&a=d�&a=f#vr�l"));
2258     QCOMPARE(url.scheme(), QString::fromLatin1("http"));
2259     QCOMPARE(url.host(), QString::fromLatin1("www.r�ksm�rg�s.se"));
2260     QCOMPARE(url.path(), QString::fromLatin1("/pub"));
2261     // this will be encoded ...
2262     QCOMPARE(url.encodedQuery().constData(), QString::fromLatin1("a=b&a=d%C3%B8&a=f").toLatin1().constData());
2263     // unencoded
2264     QCOMPARE(url.allQueryItemValues("a").join("").toLatin1().constData(), "bd�f");
2265     QCOMPARE(url.fragment(), QString::fromLatin1("vr�l"));
2266 
2267     QUrl onlyHost("//qt.nokia.com");
2268     QCOMPARE(onlyHost.toString(), QString::fromLatin1("//qt.nokia.com"));
2269 
2270     {
2271         QString urlString = QString::fromLatin1("http://desktop:33326/upnp/{32f525a6-6f31-426e-91ca-01c2e6c2c57e}");
2272         QUrl urlPreviewList(urlString);
2273         QCOMPARE(urlPreviewList.toString(), urlString);
2274         QByteArray b = urlPreviewList.toEncoded();
2275         QCOMPARE(b.constData(), "http://desktop:33326/upnp/%7B32f525a6-6f31-426e-91ca-01c2e6c2c57e%7D");
2276         QCOMPARE(QUrl::fromEncoded(b).toString(), urlString);
2277 
2278     }{
2279         QString urlString = QString::fromLatin1("http://desktop:53423/deviceDescription?uuid={7977c17b-00bf-4af9-894e-fed28573c3a9}");
2280         QUrl urlPreviewList(urlString);
2281         QCOMPARE(urlPreviewList.toString(), urlString);
2282         QByteArray b = urlPreviewList.toEncoded();
2283         QCOMPARE(b.constData(), "http://desktop:53423/deviceDescription?uuid=%7B7977c17b-00bf-4af9-894e-fed28573c3a9%7D");
2284         QCOMPARE(QUrl::fromEncoded(b).toString(), urlString);
2285     }
2286 }
2287 
2288 
ipv6_data()2289 void tst_QUrl::ipv6_data()
2290 {
2291     QTest::addColumn<QString>("ipv6Auth");
2292     QTest::addColumn<bool>("isValid");
2293 
2294     QTest::newRow("case 1") << QString::fromLatin1("//[56:56:56:56:56:56:56:56]") << true;
2295     QTest::newRow("case 2") << QString::fromLatin1("//[::56:56:56:56:56:56:56]") << true;
2296     QTest::newRow("case 3") << QString::fromLatin1("//[56::56:56:56:56:56:56]") << true;
2297     QTest::newRow("case 4") << QString::fromLatin1("//[56:56::56:56:56:56:56]") << true;
2298     QTest::newRow("case 5") << QString::fromLatin1("//[56:56:56::56:56:56:56]") << true;
2299     QTest::newRow("case 6") << QString::fromLatin1("//[56:56:56:56::56:56:56]") << true;
2300     QTest::newRow("case 7") << QString::fromLatin1("//[56:56:56:56:56::56:56]") << true;
2301     QTest::newRow("case 8") << QString::fromLatin1("//[56:56:56:56:56:56::56]") << true;
2302     QTest::newRow("case 9") << QString::fromLatin1("//[56:56:56:56:56:56:56::]") << true;
2303     QTest::newRow("case 4 with one less") << QString::fromLatin1("//[56::56:56:56:56:56]") << true;
2304     QTest::newRow("case 4 with less and ip4") << QString::fromLatin1("//[56::56:56:56:127.0.0.1]") << true;
2305     QTest::newRow("case 7 with one and ip4") << QString::fromLatin1("//[56::255.0.0.0]") << true;
2306     QTest::newRow("case 2 with ip4") << QString::fromLatin1("//[::56:56:56:56:56:0.0.0.255]") << true;
2307     QTest::newRow("case 2 with half ip4") << QString::fromLatin1("//[::56:56:56:56:56:56:0.255]") << false;
2308     QTest::newRow("case 4 with less and ip4 and port and useinfo") << QString::fromLatin1("//user:pass@[56::56:56:56:127.0.0.1]:99") << true;
2309     QTest::newRow("case :,") << QString::fromLatin1("//[:,]") << false;
2310     QTest::newRow("case ::bla") << QString::fromLatin1("//[::bla]") << false;
2311 }
2312 
ipv6()2313 void tst_QUrl::ipv6()
2314 {
2315     QFETCH(QString, ipv6Auth);
2316     QFETCH(bool, isValid);
2317 
2318     QUrl url(ipv6Auth);
2319 
2320     QCOMPARE(url.isValid(), isValid);
2321     if (url.isValid()) {
2322         QCOMPARE(url.toString(), ipv6Auth);
2323         url.setHost(url.host());
2324         QCOMPARE(url.toString(), ipv6Auth);
2325     }
2326 };
2327 
ipv6_2_data()2328 void tst_QUrl::ipv6_2_data()
2329 {
2330     QTest::addColumn<QString>("input");
2331     QTest::addColumn<QString>("output");
2332 
2333     QTest::newRow("[::ffff:129.144.52.38]")
2334         << QString("http://[::ffff:129.144.52.38]/cgi/test.cgi")
2335         << QString("http://[::ffff:129.144.52.38]/cgi/test.cgi");
2336     QTest::newRow("[::FFFF:129.144.52.38]")
2337         << QString("http://[::FFFF:129.144.52.38]/cgi/test.cgi")
2338         << QString("http://[::ffff:129.144.52.38]/cgi/test.cgi");
2339 }
2340 
ipv6_2()2341 void tst_QUrl::ipv6_2()
2342 {
2343     QFETCH(QString, input);
2344     QFETCH(QString, output);
2345 
2346     QUrl url(input);
2347     QCOMPARE(url.toString(), output);
2348     url.setHost(url.host());
2349     QCOMPARE(url.toString(), output);
2350 }
2351 
moreIpv6()2352 void tst_QUrl::moreIpv6()
2353 {
2354     QUrl waba1("http://www.kde.org/cgi/test.cgi");
2355     waba1.setHost("::ffff:129.144.52.38");
2356     QCOMPARE(QString::fromLatin1(waba1.toEncoded()), QString::fromLatin1("http://[::ffff:129.144.52.38]/cgi/test.cgi"));
2357 }
2358 
punycode_data()2359 void tst_QUrl::punycode_data()
2360 {
2361     QTest::addColumn<QString>("original");
2362     QTest::addColumn<QByteArray>("encoded");
2363 
2364     QTest::newRow("�l") << QString::fromLatin1("�l") << QByteArray("xn--l-4ga");
2365     QTest::newRow("B�hler") << QString::fromLatin1("B�hler") << QByteArray("xn--Bhler-kva");
2366     QTest::newRow("r�ksm�rg�s") << QString::fromLatin1("r�ksm�rg�s") << QByteArray("xn--rksmrgs-5wao1o");
2367 }
2368 
punycode()2369 void tst_QUrl::punycode()
2370 {
2371     QFETCH(QString, original);
2372     QFETCH(QByteArray, encoded);
2373 
2374     QCOMPARE(QUrl::fromPunycode(encoded), original);
2375     QCOMPARE(QUrl::fromPunycode(QUrl::toPunycode(original)), original);
2376     QCOMPARE(QUrl::toPunycode(original).constData(), encoded.constData());
2377 }
2378 
isRelative_data()2379 void tst_QUrl::isRelative_data()
2380 {
2381     QTest::addColumn<QString>("url");
2382     QTest::addColumn<bool>("trueFalse");
2383 
2384     QTest::newRow("not") << QString::fromLatin1("http://qt.nokia.com") << false;
2385     QTest::newRow("55288") << QString::fromLatin1("node64.html#fig:form:ana") << true;
2386 
2387     // kde
2388     QTest::newRow("mailto: URL, is relative") << "mailto:faure@kde.org" << false;
2389     QTest::newRow("man: URL, is relative") << "man:mmap" << false;
2390     QTest::newRow("javascript: URL, is relative") << "javascript:doSomething()" << false;
2391     QTest::newRow("file: URL, is relative") << "file:/blah" << false;
2392     QTest::newRow("/path, is relative") << "/path" << true;
2393     QTest::newRow("something, is relative") << "something" << true;
2394     // end kde
2395 }
2396 
isRelative()2397 void tst_QUrl::isRelative()
2398 {
2399     QFETCH(QString, url);
2400     QFETCH(bool, trueFalse);
2401 
2402     QCOMPARE(QUrl(url).isRelative(), trueFalse);
2403 }
2404 
queryItems()2405 void tst_QUrl::queryItems()
2406 {
2407     QUrl url;
2408     QVERIFY(!url.hasQuery());
2409 
2410     QList<QPair<QString, QString> > newItems;
2411     newItems += qMakePair(QString("2"), QString("b"));
2412     newItems += qMakePair(QString("1"), QString("a"));
2413     newItems += qMakePair(QString("3"), QString("c"));
2414     newItems += qMakePair(QString("4"), QString("a b"));
2415     newItems += qMakePair(QString("5"), QString("&"));
2416     newItems += qMakePair(QString("foo bar"), QString("hello world"));
2417     newItems += qMakePair(QString("foo+bar"), QString("hello+world"));
2418     newItems += qMakePair(QString("tex"), QString("a + b = c"));
2419     url.setQueryItems(newItems);
2420     QVERIFY(url.hasQuery());
2421 
2422     QList<QPair<QString, QString> > setItems = url.queryItems();
2423     QVERIFY(newItems == setItems);
2424 
2425     url.addQueryItem("1", "z");
2426 
2427     QVERIFY(url.hasQueryItem("1"));
2428     QCOMPARE(url.queryItemValue("1").toLatin1().constData(), "a");
2429 
2430     url.addQueryItem("1", "zz");
2431 
2432     QStringList expected;
2433     expected += "a";
2434     expected += "z";
2435     expected += "zz";
2436     QCOMPARE(expected, url.allQueryItemValues("1"));
2437 
2438     url.removeQueryItem("1");
2439     QCOMPARE(url.allQueryItemValues("1").size(), 2);
2440     QCOMPARE(url.queryItemValue("1").toLatin1().constData(), "z");
2441 
2442     url.removeAllQueryItems("1");
2443     QVERIFY(!url.hasQueryItem("1"));
2444 
2445     QCOMPARE(url.queryItemValue("4").toLatin1().constData(), "a b");
2446     QCOMPARE(url.queryItemValue("5").toLatin1().constData(), "&");
2447     QCOMPARE(url.queryItemValue("tex").toLatin1().constData(), "a + b = c");
2448     QCOMPARE(url.queryItemValue("foo bar").toLatin1().constData(), "hello world");
2449     url.setUrl("http://www.google.com/search?q=a+b");
2450     QCOMPARE(url.queryItemValue("q"), QString("a+b"));
2451     url.setUrl("http://www.google.com/search?q=a=b"); // invalid, but should be tolerated
2452     QCOMPARE(url.queryItemValue("q"), QString("a=b"));
2453 }
2454 
hasQuery_data()2455 void tst_QUrl::hasQuery_data()
2456 {
2457     QTest::addColumn<QString>("url");
2458     QTest::addColumn<bool>("trueFalse");
2459 
2460     QTest::newRow("no query items") << "http://www.foo.bar" << false;
2461 
2462     QTest::newRow("empty query") << "http://www.foo.bar?" << true;
2463     QTest::newRow("empty query 2") << "http://www.foo.bar/?" << true;
2464 
2465     QTest::newRow("query") << "http://www.foo.bar?query" << true;
2466     QTest::newRow("query=") << "http://www.foo.bar?query=" << true;
2467     QTest::newRow("query=value") << "http://www.foo.bar?query=value" << true;
2468 
2469     QTest::newRow("%3f") << "http://www.foo.bar/file%3f" << false;
2470     QTest::newRow("%3f-query") << "http://www.foo.bar/file%3fquery" << false;
2471     QTest::newRow("%3f-query=value") << "http://www.foo.bar/file%3fquery=value" << false;
2472 }
2473 
hasQuery()2474 void tst_QUrl::hasQuery()
2475 {
2476     QFETCH(QString, url);
2477     QFETCH(bool, trueFalse);
2478 
2479     QUrl qurl(url);
2480     QCOMPARE(qurl.hasQuery(), trueFalse);
2481     QCOMPARE(qurl.encodedQuery().isNull(), !trueFalse);
2482 }
2483 
hasQueryItem_data()2484 void tst_QUrl::hasQueryItem_data()
2485 {
2486     QTest::addColumn<QString>("url");
2487     QTest::addColumn<QString>("item");
2488     QTest::addColumn<bool>("trueFalse");
2489 
2490     QTest::newRow("no query items") << "http://www.foo.bar" << "baz" << false;
2491     QTest::newRow("query item: hello") << "http://www.foo.bar?hello=world" << "hello" << true;
2492     QTest::newRow("no query item: world") << "http://www.foo.bar?hello=world" << "world" << false;
2493     QTest::newRow("query item: qt") << "http://www.foo.bar?hello=world&qt=rocks" << "qt" << true;
2494 }
2495 
hasQueryItem()2496 void tst_QUrl::hasQueryItem()
2497 {
2498     QFETCH(QString, url);
2499     QFETCH(QString, item);
2500     QFETCH(bool, trueFalse);
2501 
2502     QCOMPARE(QUrl(url).hasQueryItem(item), trueFalse);
2503 }
2504 
nameprep()2505 void tst_QUrl::nameprep()
2506 {
2507     QUrl url(QString::fromUtf8("http://www.fu""\xc3""\x9f""ball.de/"));
2508     QCOMPARE(url.toString(), QString::fromLatin1("http://www.fussball.de/"));
2509 }
2510 
isValid()2511 void tst_QUrl::isValid()
2512 {
2513     {
2514         QUrl url(QString("A=B"));
2515         QVERIFY(url.isValid());
2516         QCOMPARE(url.path(), QString("A=B"));
2517     }
2518     {
2519         QUrl url = QUrl::fromEncoded("http://strange<username>@ok-hostname/", QUrl::StrictMode);
2520         QVERIFY(!url.isValid());
2521         // < and > are not allowed in userinfo in strict mode
2522         url.setUserName("normal_username");
2523         QVERIFY(url.isValid());
2524     }
2525     {
2526         QUrl url = QUrl::fromEncoded("http://strange<username>@ok-hostname/");
2527         QVERIFY(url.isValid());
2528         // < and > are allowed in tolerant mode
2529     }
2530     {
2531         QUrl url = QUrl::fromEncoded("http://strange;hostname/here");
2532         QVERIFY(!url.isValid());
2533         QCOMPARE(url.path(), QString("/here"));
2534         url.setAuthority("strange;hostname");
2535         QVERIFY(!url.isValid());
2536         url.setAuthority("foobar@bar");
2537         QVERIFY(url.isValid());
2538         url.setAuthority("strange;hostname");
2539         QVERIFY(!url.isValid());
2540         QVERIFY(url.errorString().contains("invalid hostname"));
2541     }
2542 
2543     {
2544         QUrl url = QUrl::fromEncoded("foo://stuff;1/g");
2545         QVERIFY(!url.isValid());
2546         QCOMPARE(url.path(), QString("/g"));
2547         url.setHost("stuff;1");
2548         QVERIFY(!url.isValid());
2549         url.setHost("stuff-1");
2550         QVERIFY(url.isValid());
2551         url.setHost("stuff;1");
2552         QVERIFY(!url.isValid());
2553         QVERIFY(url.errorString().contains("invalid hostname"));
2554     }
2555 
2556 }
2557 
schemeValidator_data()2558 void tst_QUrl::schemeValidator_data()
2559 {
2560     QTest::addColumn<QByteArray>("encodedUrl");
2561     QTest::addColumn<bool>("result");
2562     QTest::addColumn<QString>("toString");
2563 
2564     QTest::newRow("empty") << QByteArray() << false << QString();
2565 
2566     // ftp
2567     QTest::newRow("ftp:") << QByteArray("ftp:") << true << QString("ftp:");
2568     QTest::newRow("ftp://ftp.qt.nokia.com")
2569         << QByteArray("ftp://ftp.qt.nokia.com")
2570         << true << QString("ftp://ftp.qt.nokia.com");
2571     QTest::newRow("ftp://ftp.qt.nokia.com/")
2572         << QByteArray("ftp://ftp.qt.nokia.com/")
2573         << true << QString("ftp://ftp.qt.nokia.com/");
2574     QTest::newRow("ftp:/index.html")
2575         << QByteArray("ftp:/index.html")
2576         << false << QString();
2577 
2578     // mailto
2579     QTest::newRow("mailto:") << QByteArray("mailto:") << true << QString("mailto:");
2580     QTest::newRow("mailto://smtp.trolltech.com/ole@bull.name")
2581         << QByteArray("mailto://smtp.trolltech.com/ole@bull.name") << false << QString();
2582     QTest::newRow("mailto:") << QByteArray("mailto:") << true << QString("mailto:");
2583     QTest::newRow("mailto:ole@bull.name")
2584         << QByteArray("mailto:ole@bull.name") << true << QString("mailto:ole@bull.name");
2585 
2586     // file
2587     QTest::newRow("file:") << QByteArray("file:/etc/passwd") << true << QString("file:///etc/passwd");
2588 }
2589 
schemeValidator()2590 void tst_QUrl::schemeValidator()
2591 {
2592     QFETCH(QByteArray, encodedUrl);
2593     QFETCH(bool, result);
2594     QFETCH(QString, toString);
2595 
2596     QUrl url = QUrl::fromEncoded(encodedUrl);
2597     QCOMPARE(url.isValid(), result);
2598 }
2599 
invalidSchemeValidator()2600 void tst_QUrl::invalidSchemeValidator()
2601 {
2602     // test that if scheme does not start with an ALPHA, QUrl::isValid() returns false
2603     {
2604         QUrl url("1http://qt.nokia.com", QUrl::StrictMode);
2605         QCOMPARE(url.isValid(), false);
2606     }
2607     {
2608         QUrl url("http://qt.nokia.com");
2609         url.setScheme("111http://qt.nokia.com");
2610         QCOMPARE(url.isValid(), false);
2611     }
2612     {
2613         QUrl url = QUrl::fromEncoded("1http://qt.nokia.com", QUrl::StrictMode);
2614         QCOMPARE(url.isValid(), false);
2615     }
2616 
2617     // non-ALPHA character at other positions in the scheme are ok
2618     {
2619         QUrl url("ht111tp://qt.nokia.com", QUrl::StrictMode);
2620         QVERIFY(url.isValid());
2621     }
2622     {
2623         QUrl url("http://qt.nokia.com");
2624         url.setScheme("ht123tp://qt.nokia.com");
2625         QVERIFY(url.isValid());
2626     }
2627     {
2628         QUrl url = QUrl::fromEncoded("ht321tp://qt.nokia.com", QUrl::StrictMode);
2629         QVERIFY(url.isValid());
2630     }
2631 }
2632 
tolerantParser()2633 void tst_QUrl::tolerantParser()
2634 {
2635     {
2636         QUrl url("http://www.example.com/path%20with spaces.html");
2637         QVERIFY(url.isValid());
2638         QCOMPARE(url.path(), QString("/path with spaces.html"));
2639         QCOMPARE(url.toEncoded(), QByteArray("http://www.example.com/path%20with%20spaces.html"));
2640         url.setUrl("http://www.example.com/path%20with spaces.html", QUrl::StrictMode);
2641         QVERIFY(url.isValid());
2642         QCOMPARE(url.toEncoded(), QByteArray("http://www.example.com/path%2520with%20spaces.html"));
2643     }
2644     {
2645         QUrl url = QUrl::fromEncoded("http://www.example.com/path%20with spaces.html");
2646         QVERIFY(url.isValid());
2647         QCOMPARE(url.path(), QString("/path with spaces.html"));
2648         url.setEncodedUrl("http://www.example.com/path%20with spaces.html", QUrl::StrictMode);
2649         QVERIFY(!url.isValid());
2650     }
2651 
2652     {
2653         QUrl url15581("http://alain.knaff.linux.lu/bug-reports/kde/percentage%in%url.htm>");
2654         QVERIFY(url15581.isValid());
2655         QCOMPARE(url15581.toEncoded().constData(), "http://alain.knaff.linux.lu/bug-reports/kde/percentage%25in%25url.htm%3E");
2656     }
2657 
2658     {
2659         QUrl webkit22616 =
2660             QUrl::fromEncoded("http://example.com/testya.php?browser-info=s:1400x1050x24:f:9.0%20r152:t:%u0442%u0435%u0441%u0442");
2661         QVERIFY(webkit22616.isValid());
2662         QCOMPARE(webkit22616.toEncoded().constData(),
2663                  "http://example.com/testya.php?browser-info=s:1400x1050x24:f:9.0%20r152:t:%25u0442%25u0435%25u0441%25u0442");
2664     }
2665 
2666     {
2667         QUrl url;
2668         url.setUrl("http://foo.bar/[image][1].jpg");
2669         QVERIFY(url.isValid());
2670         QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
2671 
2672         url.setUrl("[].jpg");
2673         QCOMPARE(url.toEncoded(), QByteArray("%5B%5D.jpg"));
2674 
2675         url.setUrl("/some/[path]/[]");
2676         QCOMPARE(url.toEncoded(), QByteArray("/some/%5Bpath%5D/%5B%5D"));
2677 
2678         url.setUrl("//[::56:56:56:56:56:56:56]");
2679         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]"));
2680 
2681         url.setUrl("//[::56:56:56:56:56:56:56]#[]");
2682         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]#%5B%5D"));
2683 
2684         url.setUrl("//[::56:56:56:56:56:56:56]?[]");
2685         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]?%5B%5D"));
2686 
2687         url.setUrl("%hello.com/f%");
2688         QCOMPARE(url.toEncoded(), QByteArray("%25hello.com/f%25"));
2689 
2690         url.setEncodedUrl("http://www.host.com/foo.php?P0=[2006-3-8]");
2691         QVERIFY(url.isValid());
2692 
2693         url.setEncodedUrl("http://foo.bar/[image][1].jpg");
2694         QVERIFY(url.isValid());
2695         QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
2696 
2697         url.setEncodedUrl("[].jpg");
2698         QCOMPARE(url.toEncoded(), QByteArray("%5B%5D.jpg"));
2699 
2700         url.setEncodedUrl("/some/[path]/[]");
2701         QCOMPARE(url.toEncoded(), QByteArray("/some/%5Bpath%5D/%5B%5D"));
2702 
2703         url.setEncodedUrl("//[::56:56:56:56:56:56:56]");
2704         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]"));
2705 
2706         url.setEncodedUrl("//[::56:56:56:56:56:56:56]#[]");
2707         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]#%5B%5D"));
2708 
2709         url.setEncodedUrl("//[::56:56:56:56:56:56:56]?[]");
2710         QCOMPARE(url.toEncoded(), QByteArray("//[::56:56:56:56:56:56:56]?%5B%5D"));
2711 
2712         url.setEncodedUrl("data:text/css,div%20{%20border-right:%20solid;%20}");
2713         QCOMPARE(url.toEncoded(), QByteArray("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
2714 
2715         QUrl url2 = url;
2716         url2.setEncodedUrl("http://www.example.com");
2717         // Check that it detached
2718         QCOMPARE(url.toEncoded(), QByteArray("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
2719         QCOMPARE(url2.toEncoded(), QByteArray("http://www.example.com"));
2720     }
2721 
2722     {
2723         // task 243557
2724         QByteArray tsdgeos("http://google.com/c?c=Translation+%C2%BB+trunk|");
2725         QUrl tsdgeosQUrl;
2726         tsdgeosQUrl.setEncodedUrl(tsdgeos, QUrl::TolerantMode);
2727         QVERIFY(tsdgeosQUrl.isValid()); // failed in Qt-4.4, works in Qt-4.5
2728         QByteArray tsdgeosExpected("http://google.com/c?c=Translation+%C2%BB+trunk%7C");
2729         //QCOMPARE(tsdgeosQUrl.toEncoded(), tsdgeosExpected); // unusable output from qtestlib...
2730         QCOMPARE(QString(tsdgeosQUrl.toEncoded()), QString(tsdgeosExpected));
2731     }
2732 
2733     {
2734         QUrl url;
2735         url.setUrl("http://strange<username>@hostname/", QUrl::TolerantMode);
2736         QVERIFY(url.isValid());
2737         QCOMPARE(QString(url.toEncoded()), QString("http://strange%3Cusername%3E@hostname/"));
2738     }
2739 }
2740 
correctEncodedMistakes_data()2741 void tst_QUrl::correctEncodedMistakes_data()
2742 {
2743     QTest::addColumn<QByteArray>("encodedUrl");
2744     QTest::addColumn<bool>("result");
2745     QTest::addColumn<QString>("toString");
2746     QTest::addColumn<QByteArray>("toEncoded");
2747 
2748     QTest::newRow("%") << QByteArray("%") << true << QString("%") << QByteArray("%25");
2749     QTest::newRow("3%") << QByteArray("3%") << true << QString("3%") << QByteArray("3%25");
2750     QTest::newRow("13%") << QByteArray("13%") << true << QString("13%") << QByteArray("13%25");
2751     QTest::newRow("13%!") << QByteArray("13%!") << true << QString("13%!") << QByteArray("13%25!");
2752     QTest::newRow("13%!!") << QByteArray("13%!!") << true << QString("13%!!") << QByteArray("13%25!!");
2753     QTest::newRow("13%a") << QByteArray("13%a") << true << QString("13%a") << QByteArray("13%25a");
2754     QTest::newRow("13%az") << QByteArray("13%az") << true << QString("13%az") << QByteArray("13%25az");
2755     QTest::newRow("13%25") << QByteArray("13%25") << true << QString("13%") << QByteArray("13%25");
2756 }
2757 
correctEncodedMistakes()2758 void tst_QUrl::correctEncodedMistakes()
2759 {
2760     QFETCH(QByteArray, encodedUrl);
2761     QFETCH(bool, result);
2762     QFETCH(QString, toString);
2763     QFETCH(QByteArray, toEncoded);
2764 
2765     QUrl url = QUrl::fromEncoded(encodedUrl);
2766     QCOMPARE(url.isValid(), result);
2767     if (url.isValid()) {
2768         QCOMPARE(url.toString(), toString);
2769         QCOMPARE(url.toEncoded(), toEncoded);
2770     }
2771 }
2772 
correctDecodedMistakes_data()2773 void tst_QUrl::correctDecodedMistakes_data()
2774 {
2775     QTest::addColumn<QString>("decodedUrl");
2776     QTest::addColumn<bool>("result");
2777     QTest::addColumn<QString>("toString");
2778     QTest::addColumn<QByteArray>("toEncoded");
2779 
2780     QTest::newRow("%") << QString("%") << true << QString("%") << QByteArray("%25");
2781     QTest::newRow("3%") << QString("3%") << true << QString("3%") << QByteArray("3%25");
2782     QTest::newRow("13%") << QString("13%") << true << QString("13%") << QByteArray("13%25");
2783     QTest::newRow("13%!") << QString("13%!") << true << QString("13%!") << QByteArray("13%25!");
2784     QTest::newRow("13%!!") << QString("13%!!") << true << QString("13%!!") << QByteArray("13%25!!");
2785     QTest::newRow("13%a") << QString("13%a") << true << QString("13%a") << QByteArray("13%25a");
2786     QTest::newRow("13%az") << QString("13%az") << true << QString("13%az") << QByteArray("13%25az");
2787     QTest::newRow("13%25") << QString("13%25") << true << QString("13%25") << QByteArray("13%2525");
2788 }
2789 
correctDecodedMistakes()2790 void tst_QUrl::correctDecodedMistakes()
2791 {
2792     QFETCH(QString, decodedUrl);
2793     QFETCH(bool, result);
2794     QFETCH(QString, toString);
2795     QFETCH(QByteArray, toEncoded);
2796 
2797     QUrl url(decodedUrl);
2798     QCOMPARE(url.isValid(), result);
2799     if (url.isValid()) {
2800         QCOMPARE(url.toString(), toString);
2801         QCOMPARE(url.toEncoded(), toEncoded);
2802     }
2803 }
2804 
idna_testsuite_data()2805 void tst_QUrl::idna_testsuite_data()
2806 {
2807     QTest::addColumn<int>("numchars");
2808     QTest::addColumn<ushortarray>("unicode");
2809     QTest::addColumn<QByteArray>("punycode");
2810     QTest::addColumn<int>("allowunassigned");
2811     QTest::addColumn<int>("usestd3asciirules");
2812     QTest::addColumn<int>("toasciirc");
2813     QTest::addColumn<int>("tounicoderc");
2814 
2815     unsigned short d1[] = { 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
2816                             0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
2817                             0x061F };
2818     QTest::newRow("Arabic (Egyptian)") << 17 << ushortarray(d1)
2819                                     << QByteArray(IDNA_ACE_PREFIX "egbpdaj6bu4bxfgehfvwxn")
2820                                     << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2821 
2822     unsigned short d2[] = { 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D,
2823                             0x6587 };
2824     QTest::newRow("Chinese (simplified)") << 9 << ushortarray(d2)
2825                                        << QByteArray(IDNA_ACE_PREFIX "ihqwcrb4cv8a8dqg056pqjye")
2826                                        << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2827 
2828     unsigned short d3[] = { 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D,
2829                             0x6587 };
2830     QTest::newRow("Chinese (traditional)") << 9 << ushortarray(d3)
2831                                         << QByteArray(IDNA_ACE_PREFIX "ihqwctvzc91f659drss3x8bo0yb")
2832                                         << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2833 
2834     unsigned short d4[] = { 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
2835                             0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
2836                             0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 };
2837     QTest::newRow("Czech") << 22 << ushortarray(d4)
2838                         << QByteArray(IDNA_ACE_PREFIX "Proprostnemluvesky-uyb24dma41a")
2839                         << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2840 
2841     unsigned short d5[] = { 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
2842                             0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
2843                             0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA };
2844     QTest::newRow("Hebrew") << 22 << ushortarray(d5)
2845                          << QByteArray(IDNA_ACE_PREFIX "4dbcagdahymbxekheh6e0a7fei0b")
2846                          << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2847 
2848     unsigned short d6[] = { 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
2849                             0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
2850                             0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
2851                             0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 };
2852     QTest::newRow("Hindi (Devanagari)") << 30 << ushortarray(d6)
2853                                      << QByteArray(IDNA_ACE_PREFIX "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd")
2854                                      << 0 << 0 << IDNA_SUCCESS;
2855 
2856     unsigned short d7[] = { 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
2857                             0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
2858                             0x306E, 0x304B };
2859     QTest::newRow("Japanese (kanji and hiragana)") << 18 << ushortarray(d7)
2860                                                 << QByteArray(IDNA_ACE_PREFIX "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa")
2861                                                 << 0 << 0 << IDNA_SUCCESS;
2862 
2863     unsigned short d8[] = { 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
2864                             0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
2865                             0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
2866                             0x0441, 0x0441, 0x043A, 0x0438 };
2867     QTest::newRow("Russian (Cyrillic)") << 28 << ushortarray(d8)
2868                                      << QByteArray(IDNA_ACE_PREFIX "b1abfaaepdrnnbgefbadotcwatmq2g4l")
2869                                      << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2870 
2871     unsigned short d9[] = { 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
2872                             0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
2873                             0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
2874                             0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
2875                             0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C };
2876     QTest::newRow("Spanish") << 40 << ushortarray(d9)
2877                           << QByteArray(IDNA_ACE_PREFIX "PorqunopuedensimplementehablarenEspaol-fmd56a")
2878                           << 0 << 0 << IDNA_SUCCESS;
2879 
2880     unsigned short d10[] = { 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
2881                              0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
2882                              0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
2883                              0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 };
2884     QTest::newRow("Vietnamese") << 31 << ushortarray(d10)
2885                              << QByteArray(IDNA_ACE_PREFIX "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g")
2886                              << 0 << 0 << IDNA_SUCCESS;
2887 
2888     unsigned short d11[] = { 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F };
2889     QTest::newRow("Japanese") << 8 << ushortarray(d11)
2890                            << QByteArray(IDNA_ACE_PREFIX "3B-ww4c5e180e575a65lsy2b")
2891                            << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2892 
2893     unsigned short d12[] = { 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
2894                              0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
2895                              0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053 };
2896     QTest::newRow("Japanese2") << 24 << ushortarray(d12)
2897                             << QByteArray(IDNA_ACE_PREFIX "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n")
2898                             << 0 << 0 << IDNA_SUCCESS;
2899 
2900     unsigned short d13[] = { 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
2901                              0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
2902                              0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
2903                              0x6240 };
2904     QTest::newRow("Japanese3") << 25 << ushortarray(d13)
2905                             << QByteArray(IDNA_ACE_PREFIX "Hello-Another-Way--fc4qua05auwb3674vfr0b")
2906                             << 0 << 0 << IDNA_SUCCESS;
2907 
2908     unsigned short d14[] = { 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032 };
2909     QTest::newRow("Japanese4") << 8 << ushortarray(d14)
2910                             << QByteArray(IDNA_ACE_PREFIX "2-u9tlzr9756bt3uc0v")
2911                             << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2912 
2913     unsigned short d15[] = { 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
2914                              0x3059, 0x308B, 0x0035, 0x79D2, 0x524D };
2915     QTest::newRow("Japanese5") << 13 << ushortarray(d15)
2916                             << QByteArray(IDNA_ACE_PREFIX "MajiKoi5-783gue6qz075azm5e")
2917                             << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2918 
2919     unsigned short d16[] = { 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0 };
2920     QTest::newRow("Japanese6") << 9 << ushortarray(d16)
2921                             << QByteArray(IDNA_ACE_PREFIX "de-jg4avhby1noc0d")
2922                             << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2923 
2924     unsigned short d17[] = { 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 };
2925     QTest::newRow("Japanese7") << 7 << ushortarray(d17)
2926                             << QByteArray(IDNA_ACE_PREFIX "d9juau41awczczp")
2927                             << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2928 
2929     unsigned short d18[] = { 0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac };
2930     QTest::newRow("Greek") << 8 << ushortarray(d18)
2931                         << QByteArray(IDNA_ACE_PREFIX "hxargifdar")
2932                         << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2933 
2934     unsigned short d19[] = { 0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127,
2935                              0x0127, 0x0061 };
2936     QTest::newRow("Maltese (Malti)") << 10 << ushortarray(d19)
2937                                   << QByteArray(IDNA_ACE_PREFIX "bonusaa-5bb1da")
2938                                   << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2939 
2940     unsigned short d20[] = {0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435,
2941                             0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432,
2942                             0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443,
2943                             0x0441, 0x0441, 0x043a, 0x0438 };
2944     QTest::newRow("Russian (Cyrillic)") << 28 << ushortarray(d20)
2945                                      << QByteArray(IDNA_ACE_PREFIX "b1abfaaepdrnnbgefbadotcwatmq2g4l")
2946                                      << 0 << 0 << IDNA_SUCCESS << IDNA_SUCCESS;
2947 }
2948 
idna_testsuite()2949 void tst_QUrl::idna_testsuite()
2950 {
2951     QFETCH(int, numchars);
2952     QFETCH(ushortarray, unicode);
2953     QFETCH(QByteArray, punycode);
2954 
2955     QString s = QString::fromUtf16(unicode.points, numchars);
2956     QCOMPARE(punycode, QUrl::toPunycode(s));
2957 }
2958 
nameprep_testsuite_data()2959 void tst_QUrl::nameprep_testsuite_data()
2960 {
2961     QTest::addColumn<QString>("in");
2962     QTest::addColumn<QString>("out");
2963     QTest::addColumn<QString>("profile");
2964     QTest::addColumn<int>("flags");
2965     QTest::addColumn<int>("rc");
2966 
2967     QTest::newRow("Map to nothing")
2968         << QString::fromUtf8("foo\xC2\xAD\xCD\x8F\xE1\xA0\x86\xE1\xA0\x8B"
2969                              "bar""\xE2\x80\x8B\xE2\x81\xA0""baz\xEF\xB8\x80\xEF\xB8\x88"
2970                              "\xEF\xB8\x8F\xEF\xBB\xBF")
2971         << QString::fromUtf8("foobarbaz")
2972         << QString() << 0 << 0;
2973 
2974     QTest::newRow("Case folding ASCII U+0043 U+0041 U+0046 U+0045")
2975         << QString::fromUtf8("CAFE")
2976         << QString::fromUtf8("cafe")
2977         << QString() << 0 << 0;
2978 
2979     QTest::newRow("Case folding 8bit U+00DF (german sharp s)")
2980         << QString::fromUtf8("\xC3\x9F")
2981         << QString("ss")
2982         << QString() << 0 << 0;
2983 
2984     QTest::newRow("Case folding U+0130 (turkish capital I with dot)")
2985         << QString::fromUtf8("\xC4\xB0")
2986         << QString::fromUtf8("i\xcc\x87")
2987         << QString() << 0 << 0;
2988 
2989     QTest::newRow("Case folding multibyte U+0143 U+037A")
2990         << QString::fromUtf8("\xC5\x83\xCD\xBA")
2991         << QString::fromUtf8("\xC5\x84 \xCE\xB9")
2992         << QString() << 0 << 0;
2993 
2994     QTest::newRow("Case folding U+2121 U+33C6 U+1D7BB")
2995         << QString::fromUtf8("\xE2\x84\xA1\xE3\x8F\x86\xF0\x9D\x9E\xBB")
2996         << QString::fromUtf8("telc\xE2\x88\x95""kg\xCF\x83")
2997         << QString() << 0 << 0;
2998 
2999     QTest::newRow("Normalization of U+006a U+030c U+00A0 U+00AA")
3000         << QString::fromUtf8("\x6A\xCC\x8C\xC2\xA0\xC2\xAA")
3001         << QString::fromUtf8("\xC7\xB0 a")
3002         << QString() << 0 << 0;
3003 
3004     QTest::newRow("Case folding U+1FB7 and normalization")
3005         << QString::fromUtf8("\xE1\xBE\xB7")
3006         << QString::fromUtf8("\xE1\xBE\xB6\xCE\xB9")
3007         << QString() << 0 << 0;
3008 
3009     QTest::newRow("Self-reverting case folding U+01F0 and normalization")
3010 //        << QString::fromUtf8("\xC7\xF0") ### typo in the original testsuite
3011         << QString::fromUtf8("\xC7\xB0")
3012         << QString::fromUtf8("\xC7\xB0")
3013         << QString() << 0 << 0;
3014 
3015     QTest::newRow("Self-reverting case folding U+0390 and normalization")
3016         << QString::fromUtf8("\xCE\x90")
3017         << QString::fromUtf8("\xCE\x90")
3018         << QString() << 0 << 0;
3019 
3020     QTest::newRow("Self-reverting case folding U+03B0 and normalization")
3021         << QString::fromUtf8("\xCE\xB0")
3022         << QString::fromUtf8("\xCE\xB0")
3023         << QString() << 0 << 0;
3024 
3025     QTest::newRow("Self-reverting case folding U+1E96 and normalization")
3026         << QString::fromUtf8("\xE1\xBA\x96")
3027         << QString::fromUtf8("\xE1\xBA\x96")
3028         << QString() << 0 << 0;
3029 
3030     QTest::newRow("Self-reverting case folding U+1F56 and normalization")
3031         << QString::fromUtf8("\xE1\xBD\x96")
3032         << QString::fromUtf8("\xE1\xBD\x96")
3033         << QString() << 0 << 0;
3034 
3035     QTest::newRow("ASCII space character U+0020")
3036         << QString::fromUtf8("\x20")
3037         << QString::fromUtf8("\x20")
3038         << QString() << 0 << 0;
3039 
3040     QTest::newRow("Non-ASCII 8bit space character U+00A0")
3041         << QString::fromUtf8("\xC2\xA0")
3042         << QString::fromUtf8("\x20")
3043         << QString() << 0 << 0;
3044 
3045     QTest::newRow("Non-ASCII multibyte space character U+1680")
3046         << QString::fromUtf8("x\xE1\x9A\x80x")
3047         << QString()
3048         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3049 
3050     QTest::newRow("Non-ASCII multibyte space character U+2000")
3051         << QString::fromUtf8("\xE2\x80\x80")
3052         << QString::fromUtf8("\x20")
3053         << QString() << 0 << 0;
3054 
3055     QTest::newRow("Zero Width Space U+200b")
3056         << QString::fromUtf8("\xE2\x80\x8b")
3057         << QString()
3058         << QString() << 0 << 0;
3059 
3060     QTest::newRow("Non-ASCII multibyte space character U+3000")
3061         << QString::fromUtf8("\xE3\x80\x80")
3062         << QString::fromUtf8("\x20")
3063         << QString() << 0 << 0;
3064 
3065     QTest::newRow("ASCII control characters U+0010 U+007F")
3066         << QString::fromUtf8("\x10\x7F")
3067         << QString::fromUtf8("\x10\x7F")
3068         << QString() << 0 << 0;
3069 
3070     QTest::newRow("Non-ASCII 8bit control character U+0080")
3071         << QString::fromUtf8("x\xC2\x80x")
3072         << QString()
3073         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3074 
3075     QTest::newRow("Non-ASCII 8bit control character U+0085")
3076         << QString::fromUtf8("x\xC2\x85x")
3077         << QString()
3078         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3079 
3080     QTest::newRow("Non-ASCII multibyte control character U+180E")
3081         << QString::fromUtf8("x\xE1\xA0\x8Ex")
3082         << QString()
3083         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3084 
3085     QTest::newRow("Zero Width No-Break Space U+FEFF")
3086         << QString::fromUtf8("\xEF\xBB\xBF")
3087         << QString()
3088         << QString() << 0 << 0;
3089 
3090     QTest::newRow("Non-ASCII control character U+1D175")
3091         << QString::fromUtf8("x\xF0\x9D\x85\xB5x")
3092         << QString()
3093         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3094 
3095     QTest::newRow("Plane 0 private use character U+F123")
3096         << QString::fromUtf8("x\xEF\x84\xA3x")
3097         << QString()
3098         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3099 
3100     QTest::newRow("Plane 15 private use character U+F1234")
3101         << QString::fromUtf8("x\xF3\xB1\x88\xB4x")
3102         << QString()
3103         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3104 
3105     QTest::newRow("Plane 16 private use character U+10F234")
3106         << QString::fromUtf8("x\xF4\x8F\x88\xB4x")
3107         << QString()
3108         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3109 
3110     QTest::newRow("Non-character code point U+8FFFE")
3111         << QString::fromUtf8("x\xF2\x8F\xBF\xBEx")
3112         << QString()
3113         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3114 
3115     QTest::newRow("Non-character code point U+10FFFF")
3116         << QString::fromUtf8("x\xF4\x8F\xBF\xBFx")
3117         << QString()
3118         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3119 
3120     QTest::newRow("Surrogate code U+DF42")
3121         << QString::fromUtf8("x\xED\xBD\x82x")
3122         << QString()
3123         << QString("Nameprep") << 0 <<  STRINGPREP_CONTAINS_PROHIBITED;
3124 
3125     QTest::newRow("Non-plain text character U+FFFD")
3126         << QString::fromUtf8("x\xEF\xBF\xBDx")
3127         << QString()
3128         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3129 
3130     QTest::newRow("Ideographic description character U+2FF5")
3131         << QString::fromUtf8("x\xE2\xBF\xB5x")
3132         << QString()
3133         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3134 
3135     QTest::newRow("Display property character U+0341")
3136         << QString::fromUtf8("\xCD\x81")
3137         << QString::fromUtf8("\xCC\x81")
3138         << QString() << 0 << 0;
3139 
3140     QTest::newRow("Left-to-right mark U+200E")
3141         << QString::fromUtf8("x\xE2\x80\x8Ex")
3142         << QString()
3143         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3144 
3145     QTest::newRow("Deprecated U+202A")
3146         << QString::fromUtf8("x\xE2\x80\xAA")
3147         << QString()
3148         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3149 
3150     QTest::newRow("Language tagging character U+E0001")
3151         << QString::fromUtf8("x\xF3\xA0\x80\x81x")
3152         << QString()
3153         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3154 
3155     QTest::newRow("Language tagging character U+E0042")
3156         << QString::fromUtf8("x\xF3\xA0\x81\x82x")
3157         << QString()
3158         << QString("Nameprep") << 0 << STRINGPREP_CONTAINS_PROHIBITED;
3159 
3160     QTest::newRow("Bidi: RandALCat character U+05BE and LCat characters")
3161         << QString::fromUtf8("foo\xD6\xBE""bar")
3162         << QString()
3163         << QString("Nameprep") << 0 << STRINGPREP_BIDI_BOTH_L_AND_RAL;
3164 
3165     QTest::newRow("Bidi: RandALCat character U+FD50 and LCat characters")
3166         << QString::fromUtf8("foo\xEF\xB5\x90""bar")
3167         << QString()
3168         << QString("Nameprep") << 0 << STRINGPREP_BIDI_BOTH_L_AND_RAL;
3169 
3170     QTest::newRow("Bidi: RandALCat character U+FB38 and LCat characters")
3171         << QString::fromUtf8("foo\xEF\xB9\xB6""bar")
3172         << QString::fromUtf8("foo \xd9\x8e""bar")
3173         << QString() << 0 << 0;
3174 
3175     QTest::newRow("Bidi: RandALCat without trailing RandALCat U+0627 U+0031")
3176         << QString::fromUtf8("\xD8\xA7\x31")
3177         << QString()
3178         << QString("Nameprep") << 0 << STRINGPREP_BIDI_LEADTRAIL_NOT_RAL;
3179 
3180     QTest::newRow("Bidi: RandALCat character U+0627 U+0031 U+0628")
3181         << QString::fromUtf8("\xD8\xA7\x31\xD8\xA8")
3182         << QString::fromUtf8("\xD8\xA7\x31\xD8\xA8")
3183         << QString() << 0 << 0;
3184 
3185     QTest::newRow("Unassigned code point U+E0002")
3186         << QString::fromUtf8("\xF3\xA0\x80\x82")
3187         << QString()
3188         << QString("Nameprep") << STRINGPREP_NO_UNASSIGNED << STRINGPREP_CONTAINS_UNASSIGNED;
3189 
3190     QTest::newRow("Larger test (shrinking)")
3191         << QString::fromUtf8("X\xC2\xAD\xC3\x9F\xC4\xB0\xE2\x84\xA1\x6a\xcc\x8c\xc2\xa0\xc2"
3192                              "\xaa\xce\xb0\xe2\x80\x80")
3193         << QString::fromUtf8("xssi\xcc\x87""tel\xc7\xb0 a\xce\xb0 ")
3194         << QString("Nameprep") << 0 << 0;
3195 
3196     QTest::newRow("Larger test (expanding)")
3197         << QString::fromUtf8("X\xC3\x9F\xe3\x8c\x96\xC4\xB0\xE2\x84\xA1\xE2\x92\x9F\xE3\x8c\x80")
3198         << QString::fromUtf8("xss\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88"
3199                              "\xe3\x83\xab""i\xcc\x87""tel\x28""d\x29\xe3\x82\xa2\xe3\x83\x91"
3200                              "\xe3\x83\xbc\xe3\x83\x88")
3201         << QString() << 0 << 0;
3202 }
3203 
3204 #ifdef QT_BUILD_INTERNAL
3205 QT_BEGIN_NAMESPACE
3206 Q_CORE_EXPORT extern void qt_nameprep(QString *source, int from);
3207 Q_CORE_EXPORT extern bool qt_check_std3rules(const QChar *, int);
3208 QT_END_NAMESPACE
3209 #endif
3210 
nameprep_testsuite()3211 void tst_QUrl::nameprep_testsuite()
3212 {
3213 #ifdef QT_BUILD_INTERNAL
3214     QFETCH(QString, in);
3215     QFETCH(QString, out);
3216     QFETCH(QString, profile);
3217 
3218     qt_nameprep(&in, 0);
3219     QCOMPARE(in, out);
3220 #endif
3221 }
3222 
nameprep_highcodes_data()3223 void tst_QUrl::nameprep_highcodes_data()
3224 {
3225     QTest::addColumn<QString>("in");
3226     QTest::addColumn<QString>("out");
3227     QTest::addColumn<QString>("profile");
3228     QTest::addColumn<int>("flags");
3229     QTest::addColumn<int>("rc");
3230 
3231     {
3232         QChar st[] = { '-', 0xd801, 0xdc1d, 'a' };
3233         QChar se[] = { '-', 0xd801, 0xdc45, 'a' };
3234         QTest::newRow("highcodes (U+1041D)")
3235             << QString(st, sizeof(st)/sizeof(st[0]))
3236             << QString(se, sizeof(se)/sizeof(se[0]))
3237             << QString() << 0 << 0;
3238     }
3239     {
3240         QChar st[] = { 0x011C, 0xd835, 0xdf6e, 0x0110 };
3241         QChar se[] = { 0x011D, 0x03C9, 0x0111 };
3242         QTest::newRow("highcodes (U+1D76E)")
3243             << QString(st, sizeof(st)/sizeof(st[0]))
3244             << QString(se, sizeof(se)/sizeof(se[0]))
3245             << QString() << 0 << 0;
3246     }
3247     {
3248         QChar st[] = { 'D', 'o', '\'', 0x2060, 'h' };
3249         QChar se[] = { 'd', 'o', '\'', 'h' };
3250         QTest::newRow("highcodes (D, o, ', U+2060, h)")
3251             << QString(st, sizeof(st)/sizeof(st[0]))
3252             << QString(se, sizeof(se)/sizeof(se[0]))
3253             << QString() << 0 << 0;
3254     }
3255 }
3256 
nameprep_highcodes()3257 void tst_QUrl::nameprep_highcodes()
3258 {
3259 #ifdef QT_BUILD_INTERNAL
3260     QFETCH(QString, in);
3261     QFETCH(QString, out);
3262     QFETCH(QString, profile);
3263 
3264     qt_nameprep(&in, 0);
3265     QCOMPARE(in, out);
3266 #endif
3267 }
3268 
ace_testsuite_data()3269 void tst_QUrl::ace_testsuite_data()
3270 {
3271     QTest::addColumn<QString>("in");
3272     QTest::addColumn<QString>("toace");
3273     QTest::addColumn<QString>("fromace");
3274     QTest::addColumn<QString>("unicode");
3275 
3276     QTest::newRow("ascii-lower") << "fluke" << "fluke" << "fluke" << "fluke";
3277     QTest::newRow("ascii-mixed") << "FLuke" << "fluke" << "fluke" << "fluke";
3278     QTest::newRow("ascii-upper") << "FLUKE" << "fluke" << "fluke" << "fluke";
3279 
3280     QTest::newRow("asciifolded") << QString::fromLatin1("stra\337e") << "strasse" << "." << "strasse";
3281     QTest::newRow("asciifolded-dotcom") << QString::fromLatin1("stra\337e.example.com") << "strasse.example.com" << "." << "strasse.example.com";
3282     QTest::newRow("greek-mu") << QString::fromLatin1("\265V")
3283                               <<"xn--v-lmb"
3284                               << "."
3285                               << QString::fromUtf8("\316\274v");
3286 
3287     QTest::newRow("non-ascii-lower") << QString::fromLatin1("alqualond\353")
3288                                      << "xn--alqualond-34a"
3289                                      << "."
3290                                      << QString::fromLatin1("alqualond\353");
3291     QTest::newRow("non-ascii-mixed") << QString::fromLatin1("Alqualond\353")
3292                                      << "xn--alqualond-34a"
3293                                      << "."
3294                                      << QString::fromLatin1("alqualond\353");
3295     QTest::newRow("non-ascii-upper") << QString::fromLatin1("ALQUALOND\313")
3296                                      << "xn--alqualond-34a"
3297                                      << "."
3298                                      << QString::fromLatin1("alqualond\353");
3299 
3300     QTest::newRow("idn-lower") << "xn--alqualond-34a" << "xn--alqualond-34a"
3301                                << QString::fromLatin1("alqualond\353")
3302                                << QString::fromLatin1("alqualond\353");
3303     QTest::newRow("idn-mixed") << "Xn--alqualond-34a" << "xn--alqualond-34a"
3304                                << QString::fromLatin1("alqualond\353")
3305                                << QString::fromLatin1("alqualond\353");
3306     QTest::newRow("idn-mixed2") << "XN--alqualond-34a" << "xn--alqualond-34a"
3307                                 << QString::fromLatin1("alqualond\353")
3308                                 << QString::fromLatin1("alqualond\353");
3309     QTest::newRow("idn-mixed3") << "xn--ALQUALOND-34a" << "xn--alqualond-34a"
3310                                 << QString::fromLatin1("alqualond\353")
3311                                 << QString::fromLatin1("alqualond\353");
3312     QTest::newRow("idn-mixed4") << "xn--alqualond-34A" << "xn--alqualond-34a"
3313                                 << QString::fromLatin1("alqualond\353")
3314                                 << QString::fromLatin1("alqualond\353");
3315     QTest::newRow("idn-upper") << "XN--ALQUALOND-34A" << "xn--alqualond-34a"
3316                                << QString::fromLatin1("alqualond\353")
3317                                << QString::fromLatin1("alqualond\353");
3318 
3319     QTest::newRow("separator-3002") << QString::fromUtf8("example\343\200\202com")
3320                                     << "example.com" << "." << "example.com";
3321 
3322     QString egyptianIDN =
3323         QString::fromUtf8("\331\210\330\262\330\247\330\261\330\251\055\330\247\331\204\330"
3324                           "\243\330\252\330\265\330\247\331\204\330\247\330\252.\331\205"
3325                           "\330\265\330\261");
3326     QTest::newRow("egyptian-tld-ace")
3327         << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
3328         << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
3329         << "."
3330         << egyptianIDN;
3331     QTest::newRow("egyptian-tld-unicode")
3332         << egyptianIDN
3333         << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
3334         << "."
3335         << egyptianIDN;
3336     QTest::newRow("egyptian-tld-mix1")
3337         << QString::fromUtf8("\331\210\330\262\330\247\330\261\330\251\055\330\247\331\204\330"
3338                              "\243\330\252\330\265\330\247\331\204\330\247\330\252.xn--wgbh1c")
3339         << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
3340         << "."
3341         << egyptianIDN;
3342     QTest::newRow("egyptian-tld-mix2")
3343         << QString::fromUtf8("xn----rmckbbajlc6dj7bxne2c.\331\205\330\265\330\261")
3344         << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
3345         << "."
3346         << egyptianIDN;
3347 }
3348 
ace_testsuite()3349 void tst_QUrl::ace_testsuite()
3350 {
3351     static const char canonsuffix[] = ".troll.no";
3352     QFETCH(QString, in);
3353     QFETCH(QString, toace);
3354     QFETCH(QString, fromace);
3355     QFETCH(QString, unicode);
3356 
3357     const char *suffix = canonsuffix;
3358     if (toace.contains('.'))
3359         suffix = 0;
3360 
3361     QString domain = in + suffix;
3362     QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix);
3363     if (fromace != ".")
3364         QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix);
3365     QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix);
3366 
3367     domain = in + (suffix ? ".troll.No" : "");
3368     QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix);
3369     if (fromace != ".")
3370         QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix);
3371     QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix);
3372 
3373     domain = in + (suffix ? ".troll.NO" : "");
3374     QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix);
3375     if (fromace != ".")
3376         QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix);
3377     QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix);
3378 }
3379 
std3violations_data()3380 void tst_QUrl::std3violations_data()
3381 {
3382     QTest::addColumn<QString>("source");
3383     QTest::addColumn<bool>("validUrl");
3384 
3385     QTest::newRow("too-long") << "this-domain-is-far-too-long-for-its-own-good-and-should-have-been-limited-to-63-chars" << false;
3386     QTest::newRow("dash-begin") << "-x-foo" << false;
3387     QTest::newRow("dash-end") << "x-foo-" << false;
3388     QTest::newRow("dash-begin-end") << "-foo-" << false;
3389 
3390     QTest::newRow("control") << "\033foo" << false;
3391     QTest::newRow("bang") << "foo!" << false;
3392     QTest::newRow("plus") << "foo+bar" << false;
3393     QTest::newRow("dot") << "foo.bar";
3394     QTest::newRow("startingdot") << ".bar" << false;
3395     QTest::newRow("startingdot2") << ".example.com" << false;
3396     QTest::newRow("slash") << "foo/bar" << true;
3397     QTest::newRow("colon") << "foo:80" << true;
3398     QTest::newRow("question") << "foo?bar" << true;
3399     QTest::newRow("at") << "foo@bar" << true;
3400     QTest::newRow("backslash") << "foo\\bar" << false;
3401 
3402     // these characters are transformed by NFKC to non-LDH characters
3403     QTest::newRow("dot-like") << QString::fromUtf8("foo\342\200\244bar") << false;  // U+2024 ONE DOT LEADER
3404     QTest::newRow("slash-like") << QString::fromUtf8("foo\357\274\217bar") << false;    // U+FF0F FULLWIDTH SOLIDUS
3405 
3406     // The following should be invalid but isn't
3407     // the DIVISON SLASH doesn't case-fold to a slash
3408     // is this a problem with RFC 3490?
3409     //QTest::newRow("slash-like2") << QString::fromUtf8("foo\342\210\225bar") << false; // U+2215 DIVISION SLASH
3410 }
3411 
std3violations()3412 void tst_QUrl::std3violations()
3413 {
3414     QFETCH(QString, source);
3415 
3416 #ifdef QT_BUILD_INTERNAL
3417     {
3418         QString prepped = source;
3419         qt_nameprep(&prepped, 0);
3420         QVERIFY(!qt_check_std3rules(prepped.constData(), prepped.length()));
3421     }
3422 #endif
3423 
3424     if (source.contains('.'))
3425         return; // this test ends here
3426 
3427     QUrl url;
3428     url.setHost(source);
3429     QVERIFY(url.host().isEmpty());
3430 
3431     QFETCH(bool, validUrl);
3432     if (validUrl)
3433         return;  // test ends here for these cases
3434 
3435     url = QUrl("http://" + source + "/some/path");
3436     QVERIFY(!url.isValid());
3437 }
3438 
std3deviations_data()3439 void tst_QUrl::std3deviations_data()
3440 {
3441     QTest::addColumn<QString>("source");
3442 
3443     QTest::newRow("ending-dot") << "example.com.";
3444     QTest::newRow("ending-dot3002") << QString("example.com") + QChar(0x3002);
3445     QTest::newRow("underline") << "foo_bar";  //QTBUG-7434
3446 }
3447 
std3deviations()3448 void tst_QUrl::std3deviations()
3449 {
3450     QFETCH(QString, source);
3451     QVERIFY(!QUrl::toAce(source).isEmpty());
3452 
3453     QUrl url;
3454     url.setHost(source);
3455     QVERIFY(!url.host().isEmpty());
3456 }
3457 
tldRestrictions_data()3458 void tst_QUrl::tldRestrictions_data()
3459 {
3460     QTest::addColumn<QString>("tld");
3461     QTest::addColumn<bool>("encode");
3462 
3463     // current whitelist
3464     QTest::newRow("ac")  << QString("ac")  << true;
3465     QTest::newRow("at") << QString("at") << true;
3466     QTest::newRow("br") << QString("br") << true;
3467     QTest::newRow("cat")  << QString("cat")  << true;
3468     QTest::newRow("ch")  << QString("ch")  << true;
3469     QTest::newRow("cl")  << QString("cl")  << true;
3470     QTest::newRow("cn") << QString("cn") << true;
3471     QTest::newRow("de")  << QString("de")  << true;
3472     QTest::newRow("dk") << QString("dk") << true;
3473     QTest::newRow("fi") << QString("fi") << true;
3474     QTest::newRow("hu") << QString("hu") << true;
3475     QTest::newRow("info")  << QString("info")  << true;
3476     QTest::newRow("io") << QString("io") << true;
3477     QTest::newRow("jp") << QString("jp") << true;
3478     QTest::newRow("kr") << QString("kr") << true;
3479     QTest::newRow("li")  << QString("li")  << true;
3480     QTest::newRow("lt") << QString("lt") << true;
3481     QTest::newRow("museum") << QString("museum") << true;
3482     QTest::newRow("no") << QString("no") << true;
3483     QTest::newRow("se")  << QString("se")  << true;
3484     QTest::newRow("sh") << QString("sh") << true;
3485     QTest::newRow("th")  << QString("th")  << true;
3486     QTest::newRow("tm")  << QString("tm")  << true;
3487     QTest::newRow("tw") << QString("tw") << true;
3488     QTest::newRow("vn") << QString("vn") << true;
3489 
3490     // known blacklists:
3491     QTest::newRow("com") << QString("com") << false;
3492     QTest::newRow("foo") << QString("foo") << false;
3493 }
3494 
tldRestrictions()3495 void tst_QUrl::tldRestrictions()
3496 {
3497     QFETCH(QString, tld);
3498 
3499     // www.br�d.tld
3500     QByteArray ascii = "www.xn--brd-1na." + tld.toLatin1();
3501     QString unicode = QLatin1String("www.br\370d.") + tld;
3502     QString encoded = QUrl::fromAce(ascii);
3503     QTEST(!encoded.contains(".xn--"), "encode");
3504     QTEST(encoded == unicode, "encode");
3505 
3506     QUrl url = QUrl::fromEncoded("http://www.xn--brd-1na." + tld.toLatin1());
3507     QTEST(!url.host().contains(".xn--"), "encode");
3508     QTEST(url.host() == unicode, "encode");
3509 
3510     url.setUrl(QLatin1String("http://www.xn--brd-1na.") + tld);
3511     QTEST(!url.host().contains(".xn--"), "encode");
3512     QTEST(url.host() == unicode, "encode");
3513 
3514     url.setUrl(QLatin1String("http://www.br\370d.") + tld);
3515     QTEST(!url.host().contains(".xn--"), "encode");
3516     QTEST(url.host() == unicode, "encode");
3517 
3518     url = QUrl::fromEncoded("http://www.br%C3%B8d." + tld.toLatin1());
3519     QTEST(!url.host().contains(".xn--"), "encode");
3520     QTEST(url.host() == unicode, "encode");
3521 }
3522 
emptyQueryOrFragment()3523 void tst_QUrl::emptyQueryOrFragment()
3524 {
3525     QUrl qurl = QUrl::fromEncoded("http://www.kde.org/cgi/test.cgi?", QUrl::TolerantMode);
3526     QCOMPARE(qurl.toEncoded().constData(), "http://www.kde.org/cgi/test.cgi?"); // Empty refs should be preserved
3527     QCOMPARE(qurl.toString(), QString("http://www.kde.org/cgi/test.cgi?"));
3528     qurl = QUrl::fromEncoded("http://www.kde.org/cgi/test.cgi#", QUrl::TolerantMode);
3529     QCOMPARE(qurl.toEncoded().constData(), "http://www.kde.org/cgi/test.cgi#");
3530     QCOMPARE(qurl.toString(), QString("http://www.kde.org/cgi/test.cgi#"));
3531 
3532     {
3533         // start with an empty one
3534         QUrl url("http://www.foo.bar/baz");
3535         QVERIFY(!url.hasFragment());
3536         QVERIFY(url.fragment().isNull());
3537 
3538         // add fragment
3539         url.setFragment(QLatin1String("abc"));
3540         QVERIFY(url.hasFragment());
3541         QCOMPARE(url.fragment(), QString(QLatin1String("abc")));
3542         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz#abc")));
3543 
3544         // remove fragment
3545         url.setFragment(QString());
3546         QVERIFY(!url.hasFragment());
3547         QVERIFY(url.fragment().isNull());
3548         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
3549 
3550         // add empty fragment
3551         url.setFragment(QLatin1String(""));
3552         QVERIFY(url.hasFragment());
3553         QVERIFY(url.fragment().isEmpty());
3554         QVERIFY(!url.fragment().isNull());
3555         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz#")));
3556     }
3557 
3558     {
3559         // start with an empty one
3560         QUrl url("http://www.foo.bar/baz");
3561         QVERIFY(!url.hasQuery());
3562         QVERIFY(url.encodedQuery().isNull());
3563 
3564         // add encodedQuery
3565         url.setEncodedQuery("abc=def");
3566         QVERIFY(url.hasQuery());
3567         QCOMPARE(QString(url.encodedQuery()), QString(QLatin1String("abc=def")));
3568         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def")));
3569 
3570         // remove encodedQuery
3571         url.setEncodedQuery(0);
3572         QVERIFY(!url.hasQuery());
3573         QVERIFY(url.encodedQuery().isNull());
3574         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
3575 
3576         // add empty encodedQuery
3577         url.setEncodedQuery("");
3578         QVERIFY(url.hasQuery());
3579         QVERIFY(url.encodedQuery().isEmpty());
3580         QVERIFY(!url.encodedQuery().isNull());
3581         QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?")));
3582     }
3583 }
3584 
hasFragment_data()3585 void tst_QUrl::hasFragment_data()
3586 {
3587     QTest::addColumn<QString>("url");
3588     QTest::addColumn<bool>("trueFalse");
3589 
3590     QTest::newRow("no fragment") << "http://www.foo.bar" << false;
3591 
3592     QTest::newRow("empty fragment") << "http://www.foo.bar#" << true;
3593     QTest::newRow("empty fragment 2") << "http://www.foo.bar/#" << true;
3594 
3595     QTest::newRow("fragment") << "http://www.foo.bar#baz" << true;
3596     QTest::newRow("fragment2") << "http://www.foo.bar/#baz" << true;
3597 
3598     QTest::newRow("%23") << "http://www.foo.bar/%23" << false;
3599     QTest::newRow("%23-and-something") << "http://www.foo.bar/%23baz" << false;
3600 }
3601 
hasFragment()3602 void tst_QUrl::hasFragment()
3603 {
3604     QFETCH(QString, url);
3605     QFETCH(bool, trueFalse);
3606 
3607     QUrl qurl(url);
3608     QCOMPARE(qurl.hasFragment(), trueFalse);
3609     QCOMPARE(qurl.fragment().isNull(), !trueFalse);
3610 }
3611 
setEncodedFragment_data()3612 void tst_QUrl::setEncodedFragment_data()
3613 {
3614     QTest::addColumn<QByteArray>("base");
3615     QTest::addColumn<QByteArray>("fragment");
3616     QTest::addColumn<QByteArray>("expected");
3617 
3618     typedef QByteArray BA;
3619     QTest::newRow("empty") << BA("http://www.kde.org") << BA("") << BA("http://www.kde.org#");
3620     QTest::newRow("basic test") << BA("http://www.kde.org") << BA("abc") << BA("http://www.kde.org#abc");
3621     QTest::newRow("initial url has fragment") << BA("http://www.kde.org#old") << BA("new") << BA("http://www.kde.org#new");
3622     QTest::newRow("encoded fragment") << BA("http://www.kde.org") << BA("a%20c") << BA("http://www.kde.org#a%20c");
3623     QTest::newRow("with #") << BA("http://www.kde.org") << BA("a#b") << BA("http://www.kde.org#a#b");
3624 }
3625 
setEncodedFragment()3626 void tst_QUrl::setEncodedFragment()
3627 {
3628     QFETCH(QByteArray, base);
3629     QFETCH(QByteArray, fragment);
3630     QFETCH(QByteArray, expected);
3631     QUrl u;
3632     u.setEncodedUrl(base, QUrl::TolerantMode);
3633     QVERIFY(u.isValid());
3634     u.setEncodedFragment(fragment);
3635     QVERIFY(u.isValid());
3636     QVERIFY(u.hasFragment());
3637     QCOMPARE(QString::fromLatin1(u.toEncoded()), QString::fromLatin1(expected));
3638 }
3639 
fromEncoded()3640 void tst_QUrl::fromEncoded()
3641 {
3642     QUrl qurl2 = QUrl::fromEncoded("print:/specials/Print%20To%20File%20(PDF%252FAcrobat)", QUrl::TolerantMode);
3643     QCOMPARE(qurl2.path(), QString::fromLatin1("/specials/Print To File (PDF%2FAcrobat)"));
3644     QCOMPARE(QFileInfo(qurl2.path()).fileName(), QString::fromLatin1("Print To File (PDF%2FAcrobat)"));
3645     QCOMPARE(qurl2.toEncoded().constData(), "print:/specials/Print%20To%20File%20(PDF%252FAcrobat)");
3646 
3647     QUrl qurl = QUrl::fromEncoded("http://\303\244.de");
3648     QVERIFY(qurl.isValid());
3649     QCOMPARE(qurl.toEncoded().constData(), "http://xn--4ca.de");
3650 
3651     QUrl qurltest(QUrl::fromPercentEncoding("http://\303\244.de"));
3652     QVERIFY(qurltest.isValid());
3653 
3654     QUrl qurl_newline_1 = QUrl::fromEncoded("http://www.foo.bar/foo/bar\ngnork", QUrl::TolerantMode);
3655     QVERIFY(qurl_newline_1.isValid());
3656     QCOMPARE(qurl_newline_1.toEncoded().constData(), "http://www.foo.bar/foo/bar%0Agnork");
3657 }
3658 
stripTrailingSlash()3659 void tst_QUrl::stripTrailingSlash()
3660 {
3661     QUrl u1( "ftp://ftp.de.kde.org/dir" );
3662     QUrl u2( "ftp://ftp.de.kde.org/dir/" );
3663     QUrl::FormattingOptions options = QUrl::None;
3664     options |= QUrl::StripTrailingSlash;
3665     QString str1 = u1.toString(options);
3666     QString str2 = u2.toString(options);
3667     QCOMPARE( str1, u1.toString() );
3668     QCOMPARE( str2, u1.toString() );
3669     bool same = str1 == str2;
3670     QVERIFY( same );
3671 }
3672 
hosts_data()3673 void tst_QUrl::hosts_data()
3674 {
3675     QTest::addColumn<QString>("url");
3676     QTest::addColumn<QString>("host");
3677 
3678     QTest::newRow("empty") << QString("") << QString("");
3679     QTest::newRow("empty1") << QString("file:///file") << QString("");
3680     QTest::newRow("empty2") << QString("file:/file") << QString("");
3681     QTest::newRow("empty3") << QString("http:///file") << QString("");
3682     QTest::newRow("empty4") << QString("http:/file") << QString("");
3683 
3684     // numeric hostnames
3685     QTest::newRow("http://123/") << QString("http://123/") << QString("123");
3686     QTest::newRow("http://456/") << QString("http://456/") << QString("456");
3687     QTest::newRow("http://1000/") << QString("http://1000/") << QString("1000");
3688 
3689     // IP literals
3690     QTest::newRow("normal-ip-literal") << QString("http://1.2.3.4") << QString("1.2.3.4");
3691     QTest::newRow("normal-ip-literal-with-port") << QString("http://1.2.3.4:80")
3692                                                  << QString("1.2.3.4");
3693     QTest::newRow("ipv6-literal") << QString("http://[::1]") << QString("::1");
3694     QTest::newRow("ipv6-literal-with-port") << QString("http://[::1]:80") << QString("::1");
3695     QTest::newRow("long-ipv6-literal") << QString("http://[2001:200:0:8002:203:47ff:fea5:3085]")
3696                                        << QString("2001:200:0:8002:203:47ff:fea5:3085");
3697     QTest::newRow("long-ipv6-literal-with-port") << QString("http://[2001:200:0:8002:203:47ff:fea5:3085]:80")
3698                                                  << QString("2001:200:0:8002:203:47ff:fea5:3085");
3699     QTest::newRow("ipv6-literal-v4compat") << QString("http://[::255.254.253.252]")
3700                                            << QString("::255.254.253.252");
3701     QTest::newRow("ipv6-literal-v4compat-2") << QString("http://[1000::ffff:127.128.129.1]")
3702                                              << QString("1000::ffff:127.128.129.1");
3703     QTest::newRow("long-ipv6-literal-v4compat") << QString("http://[fec0:8000::8002:1000:ffff:200.100.50.250]")
3704                                                 << QString("fec0:8000::8002:1000:ffff:200.100.50.250");
3705     QTest::newRow("longer-ipv6-literal-v4compat") << QString("http://[fec0:8000:4000:8002:1000:ffff:200.100.50.250]")
3706                                                   << QString("fec0:8000:4000:8002:1000:ffff:200.100.50.250");
3707 
3708 #if 0
3709     // this is actually invalid
3710     QTest::newRow("mac-literal") << QString("obex://[00:30:1b:b7:21:fb]")
3711                                  << QString("00:30:1b:b7:21:fb");
3712 #endif
3713 
3714     // normal hostnames
3715     QTest::newRow("normal") << QString("http://intern") << QString("intern");
3716     QTest::newRow("normal2") << QString("http://qt.nokia.com") << QString("qt.nokia.com");
3717 
3718     // IDN hostnames
3719     QTest::newRow("idn") << QString(QLatin1String("http://\345r.no")) << QString(QLatin1String("\345r.no"));
3720     QTest::newRow("idn-ace") << QString("http://xn--r-1fa.no") << QString(QLatin1String("\345r.no"));
3721 }
3722 
hosts()3723 void tst_QUrl::hosts()
3724 {
3725     QFETCH(QString, url);
3726 
3727     QTEST(QUrl(url).host(), "host");
3728 }
3729 
setPort()3730 void tst_QUrl::setPort()
3731 {
3732     {
3733         QUrl url;
3734         QVERIFY(url.toString().isEmpty());
3735         url.setPort(80);
3736         QCOMPARE(url.port(), 80);
3737         QCOMPARE(url.toString(), QString::fromLatin1("//:80"));
3738         url.setPort(-1);
3739         QCOMPARE(url.port(), -1);
3740         QVERIFY(url.toString().isEmpty());
3741         url.setPort(80);
3742         QTest::ignoreMessage(QtWarningMsg, "QUrl::setPort: Out of range");
3743         url.setPort(65536);
3744         QCOMPARE(url.port(), -1);
3745     }
3746 }
3747 
toEncoded_data()3748 void tst_QUrl::toEncoded_data()
3749 {
3750     QTest::addColumn<QByteArray>("url");
3751     QTest::addColumn<QUrl::FormattingOptions>("options");
3752     QTest::addColumn<QByteArray>("encoded");
3753     QTest::newRow("file:///dir/") << QByteArray("file:///dir/")
3754                                   << QUrl::FormattingOptions(QUrl::StripTrailingSlash)
3755                                   << QByteArray("file:///dir");
3756 }
3757 
toEncoded()3758 void tst_QUrl::toEncoded()
3759 {
3760     QFETCH(QByteArray, url);
3761     QFETCH(QUrl::FormattingOptions, options);
3762     QFETCH(QByteArray, encoded);
3763 
3764     QCOMPARE(QUrl::fromEncoded(url).toEncoded(options), encoded);
3765 }
3766 
setAuthority_data()3767 void tst_QUrl::setAuthority_data()
3768 {
3769     QTest::addColumn<QString>("authority");
3770     QTest::addColumn<QString>("url");
3771     QTest::newRow("Plain auth") << QString("62.70.27.22:21") << QString("//62.70.27.22:21");
3772     QTest::newRow("Yet another plain auth") << QString("192.168.1.1:21") << QString("//192.168.1.1:21");
3773     QTest::newRow("Auth without port") << QString("192.168.1.1") << QString("//192.168.1.1");
3774     QTest::newRow("Auth w/full hostname without port") << QString("shusaku.troll.no") << QString("//shusaku.troll.no");
3775     QTest::newRow("Auth w/hostname without port") << QString("shusaku") << QString("//shusaku");
3776     QTest::newRow("Auth w/full hostname that ends with number, without port") << QString("shusaku.troll.no.2") << QString("//shusaku.troll.no.2");
3777     QTest::newRow("Auth w/hostname that ends with number, without port") << QString("shusaku2") << QString("//shusaku2");
3778     QTest::newRow("Empty auth") << QString() << QString();
3779 }
3780 
setAuthority()3781 void tst_QUrl::setAuthority()
3782 {
3783     QUrl u;
3784     QFETCH(QString, authority);
3785     QFETCH(QString, url);
3786     u.setAuthority(authority);
3787     QCOMPARE(u.toString(), url);
3788 }
3789 
setEmptyAuthority_data()3790 void tst_QUrl::setEmptyAuthority_data()
3791 {
3792     QTest::addColumn<QString>("host");
3793     QTest::addColumn<QString>("authority");
3794     QTest::addColumn<QString>("expectedUrlString");
3795 
3796     QTest::newRow("null host and authority") << QString() << QString() << QString("");
3797     QTest::newRow("empty host and authority") << QString("") << QString("") << QString("//");
3798 }
3799 
setEmptyAuthority()3800 void tst_QUrl::setEmptyAuthority()
3801 {
3802     QFETCH(QString, host);
3803     QFETCH(QString, authority);
3804     QFETCH(QString, expectedUrlString);
3805     QUrl u;
3806     u.setHost(host);
3807     QCOMPARE(u.toString(), expectedUrlString);
3808     u.setAuthority(authority);
3809     QCOMPARE(u.toString(), expectedUrlString);
3810 }
3811 
errorString()3812 void tst_QUrl::errorString()
3813 {
3814     QUrl u = QUrl::fromEncoded("http://strange<username>@bad_hostname/", QUrl::StrictMode);
3815     QVERIFY(!u.isValid());
3816     QString errorString = "Invalid URL \"http://strange<username>@bad_hostname/\": "
3817                           "error at position 14: expected end of URL, but found '<'";
3818     QCOMPARE(u.errorString(), errorString);
3819 
3820     QUrl v;
3821     errorString = "Invalid URL \"\": ";
3822     QCOMPARE(v.errorString(), errorString);
3823 }
3824 
clear()3825 void tst_QUrl::clear()
3826 {
3827     QUrl url("a");
3828     QUrl url2("a");
3829     QCOMPARE(url, url2);
3830     url.clear();
3831     QVERIFY(url != url2);
3832 }
3833 
binaryData_data()3834 void tst_QUrl::binaryData_data()
3835 {
3836     QTest::addColumn<QString>("url");
3837     QTest::newRow("username") << "http://%01%0D%0A%7F@foo/";
3838     QTest::newRow("username-at") << "http://abc%40_def@foo/";
3839     QTest::newRow("username-nul") << "http://abc%00_def@foo/";
3840     QTest::newRow("username-colon") << "http://abc%3A_def@foo/";
3841     QTest::newRow("username-nonutf8") << "http://abc%E1_def@foo/";
3842 
3843     QTest::newRow("password") << "http://user:%01%0D%0A%7F@foo/";
3844     QTest::newRow("password-at") << "http://user:abc%40_def@foo/";
3845     QTest::newRow("password-nul") << "http://user:abc%00_def@foo/";
3846     QTest::newRow("password-nonutf8") << "http://user:abc%E1_def@foo/";
3847 
3848     QTest::newRow("file") << "http://foo/%01%0D%0A%7F";
3849     QTest::newRow("file-nul") << "http://foo/abc%00_def";
3850     QTest::newRow("file-hash") << "http://foo/abc%23_def";
3851     QTest::newRow("file-question") << "http://foo/abc%3F_def";
3852     QTest::newRow("file-nonutf8") << "http://foo/abc%E1_def";
3853     QTest::newRow("file-slash") << "http://foo/abc%2f_def";
3854 
3855     QTest::newRow("ref") << "http://foo/file#a%01%0D%0A%7F";
3856     QTest::newRow("ref-nul") << "http://foo/file#abc%00_def";
3857     QTest::newRow("ref-question") << "http://foo/file#abc?_def";
3858     QTest::newRow("ref-nonutf8") << "http://foo/file#abc%E1_def";
3859 
3860     QTest::newRow("query-value") << "http://foo/query?foo=%01%0D%0A%7F";
3861     QTest::newRow("query-value-nul") << "http://foo/query?foo=abc%00_def";
3862     QTest::newRow("query-value-nonutf8") << "http://foo/query?foo=abc%E1_def";
3863 
3864     QTest::newRow("query-name") << "http://foo/query/a%01%0D%0A%7Fz=foo";
3865     QTest::newRow("query-name-nul") << "http://foo/query/abc%00_def=foo";
3866     QTest::newRow("query-name-nonutf8") << "http://foo/query/abc%E1_def=foo";
3867 }
3868 
binaryData()3869 void tst_QUrl::binaryData()
3870 {
3871     QFETCH(QString, url);
3872     QUrl u = QUrl::fromEncoded(url.toUtf8());
3873 
3874     QVERIFY(u.isValid());
3875     QVERIFY(!u.isEmpty());
3876 
3877     QString url2 = QString::fromUtf8(u.toEncoded());
3878     //QCOMPARE(url2.length(), url.length());
3879     QCOMPARE(url2, url);
3880 }
3881 
fromUserInput_data()3882 void tst_QUrl::fromUserInput_data()
3883 {
3884     //
3885     // most of this test is:
3886     //  Copyright (C) Research In Motion Limited 2009. All rights reserved.
3887     // Distributed under the BSD license.
3888     // See qurl.cpp
3889     //
3890 
3891     QTest::addColumn<QString>("string");
3892     QTest::addColumn<QUrl>("guessUrlFromString");
3893 
3894     // Null
3895     QTest::newRow("null") << QString() << QUrl();
3896 
3897     // File
3898     QDirIterator it(QDir::homePath());
3899     int c = 0;
3900     while (it.hasNext()) {
3901         it.next();
3902         QTest::newRow(QString("file-%1").arg(c++).toLatin1()) << it.filePath() << QUrl::fromLocalFile(it.filePath());
3903     }
3904 
3905     // basic latin1
3906     QTest::newRow("unicode-0") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xc3\xa5.com/").toUtf8(), QUrl::TolerantMode);
3907     QTest::newRow("unicode-0b") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded("http://%C3%A5.com/", QUrl::TolerantMode);
3908     QTest::newRow("unicode-0c") << QString::fromUtf8("\xc3\xa5.com/") << QUrl::fromEncoded("http://xn--5ca.com/", QUrl::TolerantMode);
3909     // unicode
3910     QTest::newRow("unicode-1") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded(QString::fromUtf8("http://\xce\xbb.com/").toUtf8(), QUrl::TolerantMode);
3911     QTest::newRow("unicode-1b") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded("http://%CE%BB.com/", QUrl::TolerantMode);
3912     QTest::newRow("unicode-1c") << QString::fromUtf8("\xce\xbb.com/") << QUrl::fromEncoded("http://xn--wxa.com/", QUrl::TolerantMode);
3913 
3914     // no scheme
3915     QTest::newRow("add scheme-0") << "example.org" << QUrl("http://example.org");
3916     QTest::newRow("add scheme-1") << "www.example.org" << QUrl("http://www.example.org");
3917     QTest::newRow("add scheme-2") << "ftp.example.org" << QUrl("ftp://ftp.example.org");
3918     QTest::newRow("add scheme-3") << "hostname" << QUrl("http://hostname");
3919 
3920     // no host
3921     QTest::newRow("nohost-1") << "http://" << QUrl("http://");
3922     QTest::newRow("nohost-2") << "smb:" << QUrl("smb:");
3923 
3924     // QUrl's tolerant parser should already handle this
3925     QTest::newRow("not-encoded-0") << "http://example.org/test page.html" << QUrl::fromEncoded("http://example.org/test%20page.html");
3926 
3927     // Make sure the :80, i.e. port doesn't screw anything up
3928     QUrl portUrl("http://example.org");
3929     portUrl.setPort(80);
3930     QTest::newRow("port-0") << "example.org:80" << portUrl;
3931     QTest::newRow("port-1") << "http://example.org:80" << portUrl;
3932     portUrl.setPath("path");
3933     QTest::newRow("port-1") << "example.org:80/path" << portUrl;
3934     QTest::newRow("port-1") << "http://example.org:80/path" << portUrl;
3935 
3936     // mailto doesn't have a ://, but is valid
3937     QUrl mailto("ben@example.net");
3938     mailto.setScheme("mailto");
3939     QTest::newRow("mailto") << "mailto:ben@example.net" << mailto;
3940 
3941     // misc
3942     QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80");
3943     QTest::newRow("spaces-0") << "  http://example.org/test page.html " << QUrl("http://example.org/test%20page.html");
3944     QTest::newRow("trash-0") << "example.org/test?someData=42%&someOtherData=abcde#anchor" << QUrl::fromEncoded("http://example.org/test?someData=42%25&someOtherData=abcde#anchor");
3945     QTest::newRow("other-scheme-0") << "spotify:track:0hO542doVbfGDAGQULMORT" << QUrl("spotify:track:0hO542doVbfGDAGQULMORT");
3946     QTest::newRow("other-scheme-1") << "weirdscheme:80:otherstuff" << QUrl("weirdscheme:80:otherstuff");
3947     QTest::newRow("number-path-0") << "tel:2147483648" << QUrl("tel:2147483648");
3948 
3949     // FYI: The scheme in the resulting url user
3950     QUrl authUrl("user:pass@domain.com");
3951     QTest::newRow("misc-1") << "user:pass@domain.com" << authUrl;
3952 }
3953 
fromUserInput()3954 void tst_QUrl::fromUserInput()
3955 {
3956     QFETCH(QString, string);
3957     QFETCH(QUrl, guessUrlFromString);
3958 
3959     QUrl url = QUrl::fromUserInput(string);
3960     QCOMPARE(url, guessUrlFromString);
3961 }
3962 
task_199967()3963 void tst_QUrl::task_199967()
3964 {
3965     {
3966         QUrl url;
3967         url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
3968         QVERIFY( url.isValid() );
3969         QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
3970         QVERIFY( !url.isEmpty() );
3971     }
3972     {
3973         QUrl url;
3974         url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
3975         QVERIFY( url.isValid() );
3976         QVERIFY( !url.isEmpty() );
3977         QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
3978     }
3979 }
3980 
task_240612()3981 void tst_QUrl::task_240612()
3982 {
3983     QUrl url;
3984     url.setEncodedPath("test.txt");
3985     url.setHost("example.com");
3986 
3987     QCOMPARE(url.toEncoded().constData(), "//example.com/test.txt");
3988 
3989     url.path();
3990     QCOMPARE(url.toEncoded().constData(), "//example.com/test.txt");
3991 }
3992 
3993 #ifdef QT3_SUPPORT
dirPath()3994 void tst_QUrl::dirPath()
3995 {
3996     QCOMPARE(QUrl("http://www.vg.no/test/file.txt").dirPath(), QString("/test"));
3997 }
3998 #endif
3999 
resolvedWithAbsoluteSchemes() const4000 void tst_QUrl::resolvedWithAbsoluteSchemes() const
4001 {
4002     QFETCH(QUrl, base);
4003     QFETCH(QUrl, relative);
4004     QFETCH(QUrl, expected);
4005 
4006     /* Check our input. */
4007     QVERIFY(relative.isValid());
4008     QVERIFY(base.isValid());
4009     QVERIFY(expected.isValid());
4010 
4011     const QUrl result(base.resolved(relative));
4012 
4013     QVERIFY(result.isValid());
4014     QCOMPARE(result, expected);
4015 }
4016 
resolvedWithAbsoluteSchemes_data() const4017 void tst_QUrl::resolvedWithAbsoluteSchemes_data() const
4018 {
4019     QTest::addColumn<QUrl>("base");
4020     QTest::addColumn<QUrl>("relative");
4021     QTest::addColumn<QUrl>("expected");
4022 
4023     QTest::newRow("Absolute file:/// against absolute FTP.")
4024         << QUrl::fromEncoded("file:///foo/")
4025         << QUrl::fromEncoded("ftp://example.com/")
4026         << QUrl::fromEncoded("ftp://example.com/");
4027 
4028     QTest::newRow("Absolute file:/// against absolute HTTP.")
4029         << QUrl::fromEncoded("file:///foo/")
4030         << QUrl::fromEncoded("http://example.com/")
4031         << QUrl::fromEncoded("http://example.com/");
4032 
4033 
4034     QTest::newRow("Absolute file:/// against data scheme.")
4035         << QUrl::fromEncoded("file:///foo/")
4036         << QUrl::fromEncoded("data:application/xml,%3Ce%2F%3E")
4037         << QUrl::fromEncoded("data:application/xml,%3Ce%2F%3E");
4038 
4039     QTest::newRow("Resolve with base url and port.")
4040         << QUrl::fromEncoded("http://www.foo.com:8080/")
4041         << QUrl::fromEncoded("newfile.html")
4042         << QUrl::fromEncoded("http://www.foo.com:8080/newfile.html");
4043 }
4044 
taskQTBUG_6962()4045 void tst_QUrl::taskQTBUG_6962()
4046 {
4047     //bug 6962: empty authority ignored by setAuthority
4048     QUrl url("http://example.com/something");
4049     url.setAuthority(QString());
4050     QCOMPARE(url.authority(), QString());
4051 }
4052 
taskQTBUG_8701()4053 void tst_QUrl::taskQTBUG_8701()
4054 {
4055     //bug 8701: foo:///bar mangled to foo:/bar
4056     QString foo_triple_bar("foo:///bar"), foo_uni_bar("foo:/bar");
4057 
4058     QCOMPARE(foo_triple_bar, QUrl(foo_triple_bar).toString());
4059     QCOMPARE(foo_triple_bar, QString::fromUtf8(QUrl(foo_triple_bar).toEncoded()));
4060 
4061     QCOMPARE(foo_uni_bar, QUrl(foo_uni_bar).toString());
4062     QCOMPARE(foo_uni_bar, QString::fromUtf8(QUrl(foo_uni_bar).toEncoded()));
4063 
4064     QCOMPARE(foo_triple_bar, QUrl(foo_triple_bar, QUrl::StrictMode).toString()); // fails
4065     QCOMPARE(foo_triple_bar, QString::fromUtf8(QUrl(foo_triple_bar, QUrl::StrictMode).toEncoded())); // fails
4066 
4067     QCOMPARE(foo_uni_bar, QUrl(foo_uni_bar, QUrl::StrictMode).toString());
4068     QCOMPARE(foo_uni_bar, QString::fromUtf8(QUrl(foo_uni_bar, QUrl::StrictMode).toEncoded()));
4069 }
4070 
effectiveTLDs_data()4071 void tst_QUrl::effectiveTLDs_data()
4072 {
4073     QTest::addColumn<QUrl>("domain");
4074     QTest::addColumn<QString>("TLD");
4075 
4076     QTest::newRow("yes0") << QUrl::fromEncoded("http://test.co.uk") << ".co.uk";
4077     QTest::newRow("yes1") << QUrl::fromEncoded("http://test.com") << ".com";
4078     QTest::newRow("yes2") << QUrl::fromEncoded("http://www.test.de") << ".de";
4079     QTest::newRow("yes3") << QUrl::fromEncoded("http://test.ulm.museum") << ".ulm.museum";
4080     QTest::newRow("yes4") << QUrl::fromEncoded("http://www.com.krodsherad.no") << ".krodsherad.no";
4081     QTest::newRow("yes5") << QUrl::fromEncoded("http://www.co.uk.1.bg") << ".1.bg";
4082     QTest::newRow("yes6") << QUrl::fromEncoded("http://www.com.com.cn") << ".com.cn";
4083     QTest::newRow("yes7") << QUrl::fromEncoded("http://www.test.org.ws") << ".org.ws";
4084     QTest::newRow("yes9") << QUrl::fromEncoded("http://www.com.co.uk.wallonie.museum") << ".wallonie.museum";
4085 }
4086 
effectiveTLDs()4087 void tst_QUrl::effectiveTLDs()
4088 {
4089     QFETCH(QUrl, domain);
4090     QFETCH(QString, TLD);
4091     QCOMPARE(domain.topLevelDomain(), TLD);
4092 }
4093 
removeAllEncodedQueryItems_data()4094 void tst_QUrl::removeAllEncodedQueryItems_data()
4095 {
4096     QTest::addColumn<QUrl>("url");
4097     QTest::addColumn<QByteArray>("key");
4098     QTest::addColumn<QUrl>("result");
4099 
4100     QTest::newRow("test1") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b&ccc=c") << QByteArray("bbb") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&ccc=c");
4101     QTest::newRow("test2") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b&ccc=c") << QByteArray("aaa") << QUrl::fromEncoded("http://qt.nokia.com/foo?bbb=b&ccc=c");
4102 //    QTest::newRow("test3") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b&ccc=c") << QByteArray("ccc") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b");
4103     QTest::newRow("test4") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b&ccc=c") << QByteArray("b%62b") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&bbb=b&ccc=c");
4104     QTest::newRow("test5") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&b%62b=b&ccc=c") << QByteArray("b%62b") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&ccc=c");
4105     QTest::newRow("test6") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&b%62b=b&ccc=c") << QByteArray("bbb") << QUrl::fromEncoded("http://qt.nokia.com/foo?aaa=a&b%62b=b&ccc=c");
4106 }
4107 
removeAllEncodedQueryItems()4108 void tst_QUrl::removeAllEncodedQueryItems()
4109 {
4110     QFETCH(QUrl, url);
4111     QFETCH(QByteArray, key);
4112     QFETCH(QUrl, result);
4113     url.removeAllEncodedQueryItems(key);
4114     QCOMPARE(url, result);
4115 }
4116 
detach()4117 void tst_QUrl::detach()
4118 {
4119     QUrl empty;
4120     empty.detach();
4121 
4122     QUrl foo("http://www.kde.org");
4123     QUrl foo2 = foo;
4124     foo2.detach(); // not that it's needed, given that setHost detaches, of course. But this increases coverage :)
4125     foo2.setHost("www.gnome.org");
4126     QCOMPARE(foo2.host(), QString("www.gnome.org"));
4127     QCOMPARE(foo.host(), QString("www.kde.org"));
4128 }
4129 
4130 // Test accessing the same QUrl from multiple threads concurrently
4131 // To maximize the chances of a race (and of a report from helgrind), we actually use
4132 // 10 urls rather than one.
4133 class UrlStorage
4134 {
4135 public:
UrlStorage()4136     UrlStorage() {
4137         m_urls.resize(10);
4138         for (int i = 0 ; i < m_urls.size(); ++i)
4139             m_urls[i] = QUrl::fromEncoded("http://www.kde.org", QUrl::StrictMode);
4140     }
4141     QVector<QUrl> m_urls;
4142 };
4143 
4144 static const UrlStorage * s_urlStorage = 0;
4145 
testThreadingHelper()4146 void tst_QUrl::testThreadingHelper()
4147 {
4148     const UrlStorage* storage = s_urlStorage;
4149     for (int i = 0 ; i < storage->m_urls.size(); ++i ) {
4150         const QUrl& u = storage->m_urls.at(i);
4151         // QVERIFY/QCOMPARE trigger race conditions in helgrind
4152         if (!u.isValid())
4153             qFatal("invalid url");
4154         if (u.scheme() != QLatin1String("http"))
4155             qFatal("invalid scheme");
4156         if (!u.toString().startsWith('h'))
4157             qFatal("invalid toString");
4158         QUrl copy(u);
4159         copy.setHost("www.new-host.com");
4160         QUrl copy2(u);
4161         copy2.setUserName("dfaure");
4162         QUrl copy3(u);
4163         copy3.setUrl("http://www.new-host.com");
4164         QUrl copy4(u);
4165         copy4.detach();
4166         QUrl copy5(u);
4167         QUrl resolved1 = u.resolved(QUrl("index.html"));
4168         Q_UNUSED(resolved1);
4169         QUrl resolved2 = QUrl("http://www.kde.org").resolved(u);
4170         Q_UNUSED(resolved2);
4171         QString local = u.toLocalFile();
4172         Q_UNUSED(local);
4173         QTest::qWait(10); // give time for the other threads to start
4174     }
4175 }
4176 
4177 #include <QThreadPool>
4178 
testThreading()4179 void tst_QUrl::testThreading()
4180 {
4181     s_urlStorage = new UrlStorage;
4182     QThreadPool::globalInstance()->setMaxThreadCount(100);
4183     QFutureSynchronizer<void> sync;
4184     for (int i = 0; i < 100; ++i)
4185         sync.addFuture(QtConcurrent::run(this, &tst_QUrl::testThreadingHelper));
4186     sync.waitForFinished();
4187     delete s_urlStorage;
4188 }
4189 
4190 QTEST_MAIN(tst_QUrl)
4191 
4192 #include "tst_qurl.moc"
4193