blob: 25d392b37e72b009592c461a769e4d2121fe18e0 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QUrlQuery>
#include <QtTest/QtTest>
typedef QList<QPair<QString, QString> > QueryItems;
Q_DECLARE_METATYPE(QueryItems)
Q_DECLARE_METATYPE(QUrl::ComponentFormattingOptions)
class tst_QUrlQuery : public QObject
{
Q_OBJECT
public:
tst_QUrlQuery()
{
qRegisterMetaType<QueryItems>();
}
private Q_SLOTS:
void constructing();
void addRemove();
void multiAddRemove();
void multiplyAddSamePair();
void setQueryItems_data();
void setQueryItems();
void basicParsing_data();
void basicParsing();
void reconstructQuery_data();
void reconstructQuery();
void encodedSetQueryItems_data();
void encodedSetQueryItems();
void encodedParsing_data();
void encodedParsing();
void differentDelimiters();
// old tests from tst_qurl.cpp
// add new tests above
void old_queryItems();
void old_hasQueryItem_data();
void old_hasQueryItem();
};
static QString prettyElement(const QString &key, const QString &value)
{
QString result;
if (key.isNull())
result += "null -> ";
else
result += '"' % key % "\" -> ";
if (value.isNull())
result += "null";
else
result += '"' % value % '"';
return result;
}
static QString prettyPair(QList<QPair<QString, QString> >::const_iterator it)
{
return prettyElement(it->first, it->second);
}
template <typename T>
static QByteArray prettyList(const T &items)
{
QString result = "(";
bool first = true;
typename T::const_iterator it = items.constBegin();
for ( ; it != items.constEnd(); ++it) {
if (!first)
result += ", ";
first = false;
result += prettyPair(it);
}
result += QLatin1Char(')');
return result.toLocal8Bit();
}
static bool compare(const QList<QPair<QString, QString> > &actual, const QueryItems &expected,
const char *actualStr, const char *expectedStr, const char *file, int line)
{
return QTest::compare_helper(actual == expected, "Compared values are not the same",
qstrdup(prettyList(actual)), qstrdup(prettyList(expected).data()),
actualStr, expectedStr, file, line);
}
#define COMPARE_ITEMS(actual, expected) \
do { \
if (!compare(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
return; \
} while (0)
inline QueryItems operator+(QueryItems items, const QPair<QString, QString> &pair)
{
// items is already a copy
items.append(pair);
return items;
}
inline QueryItems operator+(const QPair<QString, QString> &pair, QueryItems items)
{
// items is already a copy
items.prepend(pair);
return items;
}
inline QPair<QString, QString> qItem(const QString &first, const QString &second)
{
return qMakePair(first, second);
}
inline QPair<QString, QString> qItem(const char *first, const QString &second)
{
return qMakePair(QString::fromUtf8(first), second);
}
inline QPair<QString, QString> qItem(const char *first, const char *second)
{
return qMakePair(QString::fromUtf8(first), QString::fromUtf8(second));
}
inline QPair<QString, QString> qItem(const QString &first, const char *second)
{
return qMakePair(first, QString::fromUtf8(second));
}
static QUrlQuery emptyQuery()
{
return QUrlQuery();
}
void tst_QUrlQuery::constructing()
{
QUrlQuery empty;
QVERIFY(empty.isEmpty());
QCOMPARE(empty.queryPairDelimiter(), QUrlQuery::defaultQueryPairDelimiter());
QCOMPARE(empty.queryValueDelimiter(), QUrlQuery::defaultQueryValueDelimiter());
// undefined whether it is detached, but don't crash
QVERIFY(empty.isDetached() || !empty.isDetached());
empty.clear();
QVERIFY(empty.isEmpty());
{
QUrlQuery copy(empty);
QVERIFY(copy.isEmpty());
QVERIFY(!copy.isDetached());
QCOMPARE(copy, empty);
QCOMPARE(qHash(copy), qHash(empty));
QVERIFY(!(copy != empty));
copy = empty;
QCOMPARE(copy, empty);
copy = QUrlQuery();
QCOMPARE(copy, empty);
QCOMPARE(qHash(copy), qHash(empty));
}
{
QUrlQuery copy(emptyQuery());
QCOMPARE(copy, empty);
}
QVERIFY(!empty.hasQueryItem("a"));
QVERIFY(empty.queryItemValue("a").isEmpty());
QVERIFY(empty.allQueryItemValues("a").isEmpty());
QVERIFY(!empty.hasQueryItem(""));
QVERIFY(empty.queryItemValue("").isEmpty());
QVERIFY(empty.allQueryItemValues("").isEmpty());
QVERIFY(!empty.hasQueryItem(QString()));
QVERIFY(empty.queryItemValue(QString()).isEmpty());
QVERIFY(empty.allQueryItemValues(QString()).isEmpty());
QVERIFY(empty.queryItems().isEmpty());
QUrlQuery other;
other.addQueryItem("a", "b");
QVERIFY(!other.isEmpty());
QVERIFY(other.isDetached());
QVERIFY(other != empty);
QVERIFY(!(other == empty));
QUrlQuery copy(other);
QCOMPARE(copy, other);
copy.clear();
QVERIFY(copy.isEmpty());
QVERIFY(copy != other);
copy = other;
QVERIFY(!copy.isEmpty());
QCOMPARE(copy, other);
copy = QUrlQuery();
QVERIFY(copy.isEmpty());
empty.setQueryDelimiters('(', ')');
QCOMPARE(empty.queryValueDelimiter(), QChar(QLatin1Char('(')));
QCOMPARE(empty.queryPairDelimiter(), QChar(QLatin1Char(')')));
QList<QPair<QString, QString> > query;
query += qMakePair(QString("type"), QString("login"));
query += qMakePair(QString("name"), QString::fromUtf8("Ã¥ge nissemannsen"));
query += qMakePair(QString("ole&du"), QString::fromUtf8("anne+jørgen=sant"));
query += qMakePair(QString("prosent"), QString("%"));
copy.setQueryItems(query);
QVERIFY(!copy.isEmpty());
QUrlQuery fromList = {
{QString("type"), QString("login")},
{QString("name"), QString::fromUtf8("Ã¥ge nissemannsen")},
{QString("ole&du"), QString::fromUtf8("anne+jørgen=sant")},
{QString("prosent"), QString("%")}
};
QCOMPARE(fromList, copy);
}
void tst_QUrlQuery::addRemove()
{
QUrlQuery query;
{
// one item
query.addQueryItem("a", "b");
QVERIFY(!query.isEmpty());
QVERIFY(query.hasQueryItem("a"));
QCOMPARE(query.queryItemValue("a"), QString("b"));
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "b");
QList<QPair<QString, QString> > allItems = query.queryItems();
QCOMPARE(allItems.count(), 1);
QCOMPARE(allItems.at(0).first, QString("a"));
QCOMPARE(allItems.at(0).second, QString("b"));
}
QUrlQuery original = query;
{
// two items
query.addQueryItem("c", "d");
QVERIFY(query.hasQueryItem("a"));
QCOMPARE(query.queryItemValue("a"), QString("b"));
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "b");
QVERIFY(query.hasQueryItem("c"));
QCOMPARE(query.queryItemValue("c"), QString("d"));
QCOMPARE(query.allQueryItemValues("c"), QStringList() << "d");
QList<QPair<QString, QString> > allItems = query.queryItems();
QCOMPARE(allItems.count(), 2);
QVERIFY(allItems.contains(qItem("a", "b")));
QVERIFY(allItems.contains(qItem("c", "d")));
QVERIFY(query != original);
QVERIFY(!(query == original));
}
{
// remove an item that isn't there
QUrlQuery copy = query;
query.removeQueryItem("e");
QCOMPARE(query, copy);
}
{
// remove an item
query.removeQueryItem("c");
QVERIFY(query.hasQueryItem("a"));
QCOMPARE(query.queryItemValue("a"), QString("b"));
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "b");
QList<QPair<QString, QString> > allItems = query.queryItems();
QCOMPARE(allItems.count(), 1);
QCOMPARE(allItems.at(0).first, QString("a"));
QCOMPARE(allItems.at(0).second, QString("b"));
QCOMPARE(query, original);
QVERIFY(!(query != original));
QCOMPARE(qHash(query), qHash(original));
}
{
// add an item with en empty value
QString emptyButNotNull(0, Qt::Uninitialized);
QVERIFY(emptyButNotNull.isEmpty());
QVERIFY(!emptyButNotNull.isNull());
query.addQueryItem("e", "");
QVERIFY(query.hasQueryItem("a"));
QCOMPARE(query.queryItemValue("a"), QString("b"));
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "b");
QVERIFY(query.hasQueryItem("e"));
QCOMPARE(query.queryItemValue("e"), emptyButNotNull);
QCOMPARE(query.allQueryItemValues("e"), QStringList() << emptyButNotNull);
QList<QPair<QString, QString> > allItems = query.queryItems();
QCOMPARE(allItems.count(), 2);
QVERIFY(allItems.contains(qItem("a", "b")));
QVERIFY(allItems.contains(qItem("e", emptyButNotNull)));
QVERIFY(query != original);
QVERIFY(!(query == original));
}
{
// remove the items
query.removeQueryItem("a");
query.removeQueryItem("e");
QVERIFY(query.isEmpty());
}
}
void tst_QUrlQuery::multiAddRemove()
{
QUrlQuery query;
{
// one item, two values
query.addQueryItem("a", "b");
query.addQueryItem("a", "c");
QVERIFY(!query.isEmpty());
QVERIFY(query.hasQueryItem("a"));
// returns the first one
QCOMPARE(query.queryItemValue("a"), QLatin1String("b"));
// order is the order we set them in
QVERIFY(query.allQueryItemValues("a") == QStringList() << "b" << "c");
}
{
// add another item, two values
query.addQueryItem("A", "B");
query.addQueryItem("A", "C");
QVERIFY(query.hasQueryItem("A"));
QVERIFY(query.hasQueryItem("a"));
QCOMPARE(query.queryItemValue("a"), QLatin1String("b"));
QVERIFY(query.allQueryItemValues("a") == QStringList() << "b" << "c");
QCOMPARE(query.queryItemValue("A"), QLatin1String("B"));
QVERIFY(query.allQueryItemValues("A") == QStringList() << "B" << "C");
}
{
// remove one of the original items
query.removeQueryItem("a");
QVERIFY(query.hasQueryItem("a"));
// it must have removed the first one
QCOMPARE(query.queryItemValue("a"), QLatin1String("c"));
}
{
// remove the items we added later
query.removeAllQueryItems("A");
QVERIFY(!query.isEmpty());
QVERIFY(!query.hasQueryItem("A"));
}
{
// add one element to the current, then remove them
query.addQueryItem("a", "d");
query.removeAllQueryItems("a");
QVERIFY(!query.hasQueryItem("a"));
QVERIFY(query.isEmpty());
}
}
void tst_QUrlQuery::multiplyAddSamePair()
{
QUrlQuery query;
query.addQueryItem("a", "a");
query.addQueryItem("a", "a");
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "a" << "a");
query.addQueryItem("a", "a");
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "a" << "a" << "a");
query.removeQueryItem("a");
QCOMPARE(query.allQueryItemValues("a"), QStringList() << "a" << "a");
}
void tst_QUrlQuery::setQueryItems_data()
{
QTest::addColumn<QueryItems>("items");
QString emptyButNotNull(0, Qt::Uninitialized);
QTest::newRow("empty") << QueryItems();
QTest::newRow("1-novalue") << (QueryItems() << qItem("a", QString()));
QTest::newRow("1-emptyvalue") << (QueryItems() << qItem("a", emptyButNotNull));
QueryItems list;
list << qItem("a", "b");
QTest::newRow("1-value") << list;
QTest::newRow("1-multi") << (list + qItem("a", "c"));
QTest::newRow("1-duplicated") << (list + qItem("a", "b"));
list << qItem("c", "d");
QTest::newRow("2") << list;
list << qItem("c", "e");
QTest::newRow("2-multi") << list;
}
void tst_QUrlQuery::setQueryItems()
{
QFETCH(QueryItems, items);
QUrlQuery query;
QueryItems::const_iterator it = items.constBegin();
for ( ; it != items.constEnd(); ++it)
query.addQueryItem(it->first, it->second);
COMPARE_ITEMS(query.queryItems(), items);
query.clear();
query.setQueryItems(items);
COMPARE_ITEMS(query.queryItems(), items);
}
void tst_QUrlQuery::basicParsing_data()
{
QTest::addColumn<QString>("queryString");
QTest::addColumn<QueryItems>("items");
QString emptyButNotNull(0, Qt::Uninitialized);
QTest::newRow("null") << QString() << QueryItems();
QTest::newRow("empty") << "" << QueryItems();
QTest::newRow("1-novalue") << "a" << (QueryItems() << qItem("a", QString()));
QTest::newRow("1-emptyvalue") << "a=" << (QueryItems() << qItem("a", emptyButNotNull));
QTest::newRow("1-value") << "a=b" << (QueryItems() << qItem("a", "b"));
// some longer keys
QTest::newRow("1-longkey-novalue") << "thisisalongkey" << (QueryItems() << qItem("thisisalongkey", QString()));
QTest::newRow("1-longkey-emptyvalue") << "thisisalongkey=" << (QueryItems() << qItem("thisisalongkey", emptyButNotNull));
QTest::newRow("1-longkey-value") << "thisisalongkey=b" << (QueryItems() << qItem("thisisalongkey", "b"));
// longer values
QTest::newRow("1-longvalue-value") << "a=thisisalongreasonablyvalue"
<< (QueryItems() << qItem("a", "thisisalongreasonablyvalue"));
QTest::newRow("1-longboth-value") << "thisisalongkey=thisisalongreasonablyvalue"
<< (QueryItems() << qItem("thisisalongkey", "thisisalongreasonablyvalue"));
// two or more entries
QueryItems baselist;
baselist << qItem("a", "b") << qItem("c", "d");
QTest::newRow("2-ab-cd") << "a=b&c=d" << baselist;
QTest::newRow("2-cd-ab") << "c=d&a=b" << (QueryItems() << qItem("c", "d") << qItem("a", "b"));
// the same entry multiply defined
QTest::newRow("2-a-a") << "a&a" << (QueryItems() << qItem("a", QString()) << qItem("a", QString()));
QTest::newRow("2-ab-a") << "a=b&a" << (QueryItems() << qItem("a", "b") << qItem("a", QString()));
QTest::newRow("2-ab-ab") << "a=b&a=b" << (QueryItems() << qItem("a", "b") << qItem("a", "b"));
QTest::newRow("2-ab-ac") << "a=b&a=c" << (QueryItems() << qItem("a", "b") << qItem("a", "c"));
QPair<QString, QString> novalue = qItem("somekey", QString());
QueryItems list2 = baselist + novalue;
QTest::newRow("3-novalue-ab-cd") << "somekey&a=b&c=d" << (novalue + baselist);
QTest::newRow("3-ab-novalue-cd") << "a=b&somekey&c=d" << (QueryItems() << qItem("a", "b") << novalue << qItem("c", "d"));
QTest::newRow("3-ab-cd-novalue") << "a=b&c=d&somekey" << list2;
list2 << qItem("otherkeynovalue", QString());
QTest::newRow("4-ab-cd-novalue-novalue") << "a=b&c=d&somekey&otherkeynovalue" << list2;
QPair<QString, QString> emptyvalue = qItem("somekey", emptyButNotNull);
list2 = baselist + emptyvalue;
QTest::newRow("3-emptyvalue-ab-cd") << "somekey=&a=b&c=d" << (emptyvalue + baselist);
QTest::newRow("3-ab-emptyvalue-cd") << "a=b&somekey=&c=d" << (QueryItems() << qItem("a", "b") << emptyvalue << qItem("c", "d"));
QTest::newRow("3-ab-cd-emptyvalue") << "a=b&c=d&somekey=" << list2;
}
void tst_QUrlQuery::basicParsing()
{
QFETCH(QString, queryString);
QFETCH(QueryItems, items);
QUrlQuery query(queryString);
QCOMPARE(query.isEmpty(), items.isEmpty());
COMPARE_ITEMS(query.queryItems(), items);
}
void tst_QUrlQuery::reconstructQuery_data()
{
QTest::addColumn<QString>("queryString");
QTest::addColumn<QueryItems>("items");
QString emptyButNotNull(0, Qt::Uninitialized);
QTest::newRow("null") << QString() << QueryItems();
QTest::newRow("empty") << "" << QueryItems();
QTest::newRow("1-novalue") << "a" << (QueryItems() << qItem("a", QString()));
QTest::newRow("1-emptyvalue") << "a=" << (QueryItems() << qItem("a", emptyButNotNull));
QTest::newRow("1-value") << "a=b" << (QueryItems() << qItem("a", "b"));
// some longer keys
QTest::newRow("1-longkey-novalue") << "thisisalongkey" << (QueryItems() << qItem("thisisalongkey", QString()));
QTest::newRow("1-longkey-emptyvalue") << "thisisalongkey=" << (QueryItems() << qItem("thisisalongkey", emptyButNotNull));
QTest::newRow("1-longkey-value") << "thisisalongkey=b" << (QueryItems() << qItem("thisisalongkey", "b"));
// longer values
QTest::newRow("1-longvalue-value") << "a=thisisalongreasonablyvalue"
<< (QueryItems() << qItem("a", "thisisalongreasonablyvalue"));
QTest::newRow("1-longboth-value") << "thisisalongkey=thisisalongreasonablyvalue"
<< (QueryItems() << qItem("thisisalongkey", "thisisalongreasonablyvalue"));
// two or more entries
QueryItems baselist;
baselist << qItem("a", "b") << qItem("c", "d");
QTest::newRow("2-ab-cd") << "a=b&c=d" << baselist;
// the same entry multiply defined
QTest::newRow("2-a-a") << "a&a" << (QueryItems() << qItem("a", QString()) << qItem("a", QString()));
QTest::newRow("2-ab-ab") << "a=b&a=b" << (QueryItems() << qItem("a", "b") << qItem("a", "b"));
QTest::newRow("2-ab-ac") << "a=b&a=c" << (QueryItems() << qItem("a", "b") << qItem("a", "c"));
QTest::newRow("2-ac-ab") << "a=c&a=b" << (QueryItems() << qItem("a", "c") << qItem("a", "b"));
QTest::newRow("2-ab-cd") << "a=b&c=d" << (QueryItems() << qItem("a", "b") << qItem("c", "d"));
QTest::newRow("2-cd-ab") << "c=d&a=b" << (QueryItems() << qItem("c", "d") << qItem("a", "b"));
QueryItems list2 = baselist + qItem("somekey", QString());
QTest::newRow("3-ab-cd-novalue") << "a=b&c=d&somekey" << list2;
list2 << qItem("otherkeynovalue", QString());
QTest::newRow("4-ab-cd-novalue-novalue") << "a=b&c=d&somekey&otherkeynovalue" << list2;
list2 = baselist + qItem("somekey", emptyButNotNull);
QTest::newRow("3-ab-cd-emptyvalue") << "a=b&c=d&somekey=" << list2;
}
void tst_QUrlQuery::reconstructQuery()
{
QFETCH(QString, queryString);
QFETCH(QueryItems, items);
QUrlQuery query;
// add the items
for (QueryItems::ConstIterator it = items.constBegin(); it != items.constEnd(); ++it) {
query.addQueryItem(it->first, it->second);
}
QCOMPARE(query.query(), queryString);
}
void tst_QUrlQuery::encodedSetQueryItems_data()
{
QTest::addColumn<QString>("queryString");
QTest::addColumn<QString>("key");
QTest::addColumn<QString>("value");
QTest::addColumn<QUrl::ComponentFormattingOptions>("encoding");
QTest::addColumn<QString>("expectedQuery");
QTest::addColumn<QString>("expectedKey");
QTest::addColumn<QString>("expectedValue");
typedef QUrl::ComponentFormattingOptions F;
QTest::newRow("nul") << "f%00=bar%00" << "f%00" << "bar%00" << F(QUrl::PrettyDecoded)
<< "f%00=bar%00" << "f%00" << "bar%00";
QTest::newRow("non-decodable-1") << "foo%01%7f=b%1ar" << "foo%01%7f" << "b%1ar" << F(QUrl::PrettyDecoded)
<< "foo%01%7F=b%1Ar" << "foo%01%7F" << "b%1Ar";
QTest::newRow("non-decodable-2") << "foo\x01\x7f=b\x1ar" << "foo\x01\x7f" << "b\x1Ar" << F(QUrl::PrettyDecoded)
<< "foo%01%7F=b%1Ar" << "foo%01%7F" << "b%1Ar";
QTest::newRow("space") << "%20=%20" << "%20" << "%20" << F(QUrl::PrettyDecoded)
<< " = " << " " << " ";
QTest::newRow("encode-space") << " = " << " " << " " << F(QUrl::FullyEncoded)
<< "%20=%20" << "%20" << "%20";
// tri-state
QTest::newRow("decode-non-delimiters") << "%3C%5C%3E=%7B%7C%7D%5E%60" << "%3C%5C%3E" << "%7B%7C%7D%5E%60" << F(QUrl::DecodeReserved)
<< "<\\>={|}^`" << "<\\>" << "{|}^`";
QTest::newRow("encode-non-delimiters") << "<\\>={|}^`" << "<\\>" << "{|}^`" << F(QUrl::EncodeReserved)
<< "%3C%5C%3E=%7B%7C%7D%5E%60" << "%3C%5C%3E" << "%7B%7C%7D%5E%60";
QTest::newRow("pretty-non-delimiters") << "<\\>={|}^`" << "<\\>" << "{|}^`" << F(QUrl::PrettyDecoded)
<< "%3C%5C%3E=%7B%7C%7D%5E%60" << "<\\>" << "{|}^`";
QTest::newRow("equals") << "%3D=%3D" << "%3D" << "%3D" << F(QUrl::PrettyDecoded)
<< "%3D=%3D" << "=" << "=";
QTest::newRow("equals-2") << "%3D==" << "=" << "=" << F(QUrl::PrettyDecoded)
<< "%3D=%3D" << "=" << "=";
QTest::newRow("ampersand") << "%26=%26" << "%26" << "%26" << F(QUrl::PrettyDecoded)
<< "%26=%26" << "&" << "&";
QTest::newRow("hash") << "#=#" << "%23" << "%23" << F(QUrl::PrettyDecoded)
<< "#=#" << "#" << "#";
QTest::newRow("decode-hash") << "%23=%23" << "%23" << "%23" << F(QUrl::PrettyDecoded)
<< "#=#" << "#" << "#";
QTest::newRow("percent") << "%25=%25" << "%25" << "%25" << F(QUrl::PrettyDecoded)
<< "%25=%25" << "%25" << "%25";
QTest::newRow("bad-percent-1") << "%=%" << "%" << "%" << F(QUrl::PrettyDecoded)
<< "%25=%25" << "%25" << "%25";
QTest::newRow("bad-percent-2") << "%2=%2" << "%2" << "%2" << F(QUrl::PrettyDecoded)
<< "%252=%252" << "%252" << "%252";
QTest::newRow("plus") << "+=+" << "+" << "+" << F(QUrl::PrettyDecoded)
<< "+=+" << "+" << "+";
QTest::newRow("2b") << "%2b=%2b" << "%2b" << "%2b" << F(QUrl::PrettyDecoded)
<< "%2B=%2B" << "%2B" << "%2B";
// plus signs must not be touched
QTest::newRow("encode-plus") << "+=+" << "+" << "+" << F(QUrl::FullyEncoded)
<< "+=+" << "+" << "+";
QTest::newRow("decode-2b") << "%2b=%2b" << "%2b" << "%2b" << F(QUrl::PrettyDecoded)
<< "%2B=%2B" << "%2B" << "%2B";
QTest::newRow("unicode") << "q=R%C3%a9sum%c3%A9" << "q" << "R%C3%a9sum%c3%A9" << F(QUrl::PrettyDecoded)
<< QString::fromUtf8("q=R\xc3\xa9sum\xc3\xa9") << "q" << QString::fromUtf8("R\xc3\xa9sum\xc3\xa9");
QTest::newRow("encode-unicode") << QString::fromUtf8("q=R\xc3\xa9sum\xc3\xa9") << "q" << QString::fromUtf8("R\xc3\xa9sum\xc3\xa9")
<< F(QUrl::FullyEncoded)
<< "q=R%C3%A9sum%C3%A9" << "q" << "R%C3%A9sum%C3%A9";
}
void tst_QUrlQuery::encodedSetQueryItems()
{
QFETCH(QString, key);
QFETCH(QString, value);
QFETCH(QString, expectedQuery);
QFETCH(QString, expectedKey);
QFETCH(QString, expectedValue);
QFETCH(QUrl::ComponentFormattingOptions, encoding);
QUrlQuery query;
query.addQueryItem(key, value);
COMPARE_ITEMS(query.queryItems(encoding), QueryItems() << qItem(expectedKey, expectedValue));
QCOMPARE(query.query(encoding), expectedQuery);
}
void tst_QUrlQuery::encodedParsing_data()
{
encodedSetQueryItems_data();
}
void tst_QUrlQuery::encodedParsing()
{
QFETCH(QString, queryString);
QFETCH(QString, expectedQuery);
QFETCH(QString, expectedKey);
QFETCH(QString, expectedValue);
QFETCH(QUrl::ComponentFormattingOptions, encoding);
QUrlQuery query(queryString);
COMPARE_ITEMS(query.queryItems(encoding), QueryItems() << qItem(expectedKey, expectedValue));
QCOMPARE(query.query(encoding), expectedQuery);
}
void tst_QUrlQuery::differentDelimiters()
{
QUrlQuery query;
query.setQueryDelimiters('(', ')');
{
// parse:
query.setQuery("foo(bar)hello(world)");
QueryItems expected;
expected << qItem("foo", "bar") << qItem("hello", "world");
COMPARE_ITEMS(query.queryItems(), expected);
COMPARE_ITEMS(query.queryItems(QUrl::FullyEncoded), expected);
COMPARE_ITEMS(query.queryItems(QUrl::PrettyDecoded), expected);
}
{
// reconstruct:
// note the final ')' is missing because there are no further items
QCOMPARE(query.query(), QString("foo(bar)hello(world"));
}
{
// set items containing the new delimiters and the old ones
query.clear();
query.addQueryItem("z(=)", "y(&)");
QCOMPARE(query.query(), QString("z%28=%29(y%28&%29"));
QUrlQuery copy = query;
QCOMPARE(query.query(), QString("z%28=%29(y%28&%29"));
copy.setQueryDelimiters(QUrlQuery::defaultQueryValueDelimiter(),
QUrlQuery::defaultQueryPairDelimiter());
QCOMPARE(copy.query(), QString("z(%3D)=y(%26)"));
}
}
void tst_QUrlQuery::old_queryItems()
{
// test imported from old tst_qurl.cpp
QUrlQuery url;
QList<QPair<QString, QString> > newItems;
newItems += qMakePair(QString("1"), QString("a"));
newItems += qMakePair(QString("2"), QString("b"));
newItems += qMakePair(QString("3"), QString("c"));
newItems += qMakePair(QString("4"), QString("a b"));
newItems += qMakePair(QString("5"), QString("&"));
newItems += qMakePair(QString("foo bar"), QString("hello world"));
newItems += qMakePair(QString("foo+bar"), QString("hello+world"));
newItems += qMakePair(QString("tex"), QString("a + b = c"));
url.setQueryItems(newItems);
QVERIFY(!url.isEmpty());
QList<QPair<QString, QString> > setItems = url.queryItems();
QCOMPARE(newItems, setItems);
url.addQueryItem("1", "z");
#if 0
// undefined behaviour in the new QUrlQuery
QVERIFY(url.hasQueryItem("1"));
QCOMPARE(url.queryItemValue("1").toLatin1().constData(), "a");
url.addQueryItem("1", "zz");
QStringList expected;
expected += "a";
expected += "z";
expected += "zz";
QCOMPARE(url.allQueryItemValues("1"), expected);
url.removeQueryItem("1");
QCOMPARE(url.allQueryItemValues("1").size(), 2);
QCOMPARE(url.queryItemValue("1").toLatin1().constData(), "z");
#endif
url.removeAllQueryItems("1");
QVERIFY(!url.hasQueryItem("1"));
QCOMPARE(url.queryItemValue("4"), QLatin1String("a b"));
QCOMPARE(url.queryItemValue("5"), QLatin1String("&"));
QCOMPARE(url.queryItemValue("tex"), QLatin1String("a + b = c"));
QCOMPARE(url.queryItemValue("foo bar"), QLatin1String("hello world"));
//url.setUrl("http://www.google.com/search?q=a+b");
url.setQuery("q=a+b");
QCOMPARE(url.queryItemValue("q"), QLatin1String("a+b"));
//url.setUrl("http://www.google.com/search?q=a=b"); // invalid, but should be tolerated
url.setQuery("q=a=b");
QCOMPARE(url.queryItemValue("q"), QLatin1String("a=b"));
}
void tst_QUrlQuery::old_hasQueryItem_data()
{
QTest::addColumn<QString>("url");
QTest::addColumn<QString>("item");
QTest::addColumn<bool>("trueFalse");
// the old tests started with "http://www.foo.bar"
QTest::newRow("no query items") << "" << "baz" << false;
QTest::newRow("query item: hello") << "hello=world" << "hello" << true;
QTest::newRow("no query item: world") << "hello=world" << "world" << false;
QTest::newRow("query item: qt") << "hello=world&qt=rocks" << "qt" << true;
}
void tst_QUrlQuery::old_hasQueryItem()
{
QFETCH(QString, url);
QFETCH(QString, item);
QFETCH(bool, trueFalse);
QCOMPARE(QUrlQuery(url).hasQueryItem(item), trueFalse);
}
#if 0
// this test doesn't make sense anymore
void tst_QUrl::removeAllEncodedQueryItems_data()
{
QTest::addColumn<QUrl>("url");
QTest::addColumn<QByteArray>("key");
QTest::addColumn<QUrl>("result");
QTest::newRow("test1") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b&ccc=c") << QByteArray("bbb") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&ccc=c");
QTest::newRow("test2") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b&ccc=c") << QByteArray("aaa") << QUrl::fromEncoded("http://qt-project.org/foo?bbb=b&ccc=c");
// QTest::newRow("test3") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b&ccc=c") << QByteArray("ccc") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b");
QTest::newRow("test4") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b&ccc=c") << QByteArray("b%62b") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&bbb=b&ccc=c");
QTest::newRow("test5") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&b%62b=b&ccc=c") << QByteArray("b%62b") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&ccc=c");
QTest::newRow("test6") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&b%62b=b&ccc=c") << QByteArray("bbb") << QUrl::fromEncoded("http://qt-project.org/foo?aaa=a&b%62b=b&ccc=c");
}
void tst_QUrl::removeAllEncodedQueryItems()
{
QFETCH(QUrl, url);
QFETCH(QByteArray, key);
QFETCH(QUrl, result);
url.removeAllEncodedQueryItems(key);
QCOMPARE(url, result);
}
#endif
QTEST_APPLESS_MAIN(tst_QUrlQuery)
#include "tst_qurlquery.moc"