Add benchmark test for QHttpHeaders

Fixes: QTBUG-122472
Change-Id: I8293bb49926ea63a4456e6c3affe1853be9ab86b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Juha Vuolle 2024-02-15 13:26:37 +02:00
parent d9397479e6
commit 3e2a811f7a
3 changed files with 277 additions and 0 deletions

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(qfile_vs_qnetworkaccessmanager)
add_subdirectory(qhttpheaders)
add_subdirectory(qnetworkreply)
add_subdirectory(qnetworkreply_from_cache)
add_subdirectory(qnetworkdiskcache)

View File

@ -0,0 +1,10 @@
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_benchmark(tst_bench_qhttpheaders
SOURCES
tst_bench_qhttpheaders.cpp
LIBRARIES
Qt::Test
Qt::Network
)

View File

@ -0,0 +1,266 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/qhttpheaders.h>
#include <QtCore/qstring.h>
#include <QTest>
using namespace Qt::StringLiterals;
class tst_QHttpHeaders : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void append_enum();
void append_string_data();
void append_string();
void contains_enum_data() { setupBasicEnumData(); }
void contains_enum();
void contains_string_data() { setupBasicStringData(); }
void contains_string();
void values_enum_data() { setupBasicEnumData(); }
void values_enum();
void values_string_data() { setupBasicStringData(); }
void values_string();
void combinedValue_enum_data() { setupBasicEnumData(); }
void combinedValue_enum();
void combinedValue_string_data() { setupBasicStringData(); }
void combinedValue_string();
void removeAll_enum_data() { setupBasicEnumData(); }
void removeAll_enum();
void removeAll_string_data() { setupBasicStringData(); }
void removeAll_string();
private:
using WKH = QHttpHeaders::WellKnownHeader;
void setupBasicEnumData()
{
QTest::addColumn<WKH>("name");
QTest::addColumn<bool>("exists");
QTest::newRow("Nonexistent enum") << WKH::CDNLoop << false;
QTest::newRow("Existent enum") << WKH::Accept << true;
}
void setupBasicStringData()
{
QTest::addColumn<QString>("name");
QTest::addColumn<bool>("exists");
QTest::newRow("Nonexistent string") << "cdn-loop" << false;
QTest::newRow("Existent wellknown string") << "accept" << true;
QTest::newRow("Existent custom string") << "customheader" << true;
}
const QString customNameLowCase = u"customm-name"_s; // Not a typo, same length as knownName
const QString customNameMixCase = u"Customm-Name"_s;
const QString knownNameLowCase = u"content-type"_s;
const QString knownNameMixCase = u"Content-Type"_s;
static constexpr QAnyStringView value1{"value1"};
static constexpr QAnyStringView value2{"value2"};
static constexpr QAnyStringView value3{"value3"};
static constexpr QAnyStringView value4{"value4"};
QHttpHeaders m_complexHeaders;
QHttpHeaders m_simpleHeaders;
};
void tst_QHttpHeaders::initTestCase()
{
// A mix of known and custom headers in non-alphabetical order.
// "accept" (wellknown header) and "customheader" (custom header)
// have four values and in same order: value3, value1, value2, value4
m_complexHeaders.append(WKH::Upgrade, value1);
m_complexHeaders.append("timeout", value1);
m_complexHeaders.append(WKH::KeepAlive, value1);
m_complexHeaders.append("nel", value1);
m_complexHeaders.append(WKH::Date, value1);
m_complexHeaders.append("accept", value3);
m_complexHeaders.append("customheader", value3);
m_complexHeaders.append(WKH::SoapAction, value1);
m_complexHeaders.append("foobar", value1);
m_complexHeaders.append(WKH::Accept, value1);
m_complexHeaders.append("customheader", value1);
m_complexHeaders.append(WKH::Cookie, value1);
m_complexHeaders.append("cookie", value1);
m_complexHeaders.append(WKH::ProxyStatus, value1);
m_complexHeaders.append("cookie", value1);
m_complexHeaders.append(WKH::Accept, value2);
m_complexHeaders.append("customheader", value2);
m_complexHeaders.append(WKH::Authorization, value1);
m_complexHeaders.append("content-type", value1);
m_complexHeaders.append(WKH::Destination, value1);
m_complexHeaders.append("rover", value1);
m_complexHeaders.append("accept", value4);
m_complexHeaders.append("customheader", value4);
m_complexHeaders.append(WKH::Range, value1);
m_complexHeaders.append("destination", value1);
m_complexHeaders.append(WKH::Location, value1);
m_complexHeaders.append("font", value1);
// Simple headers with one value-less entry; having at least one entry ensures
// we don't include initial memory allocation into a test, and having
// as few as possible reduces cost of copying (header re-set)
m_simpleHeaders.append(WKH::Accept, "");
}
void tst_QHttpHeaders::append_enum()
{
QHttpHeaders headers;
QBENCHMARK {
headers = m_simpleHeaders; // (Re-)set as we'll modify the headers
headers.append(WKH::Link, value1);
}
QCOMPARE(headers.size(), m_simpleHeaders.size() + 1);
QCOMPARE(headers.nameAt(headers.size() - 1), "link");
}
void tst_QHttpHeaders::append_string_data()
{
QTest::addColumn<QString>("name");
QTest::newRow("Custom lowcase string") << customNameLowCase;
QTest::newRow("WellKnown lowcase string") << knownNameLowCase;
QTest::newRow("Custom mixcase string") << customNameMixCase;
QTest::newRow("WellKnown mixcase string") << knownNameMixCase;
}
void tst_QHttpHeaders::append_string()
{
QFETCH(QString, name);
QHttpHeaders headers;
QBENCHMARK {
headers = m_simpleHeaders; // (Re-)set as we'll modify the headers
headers.append(name, value1);
}
QCOMPARE(headers.size(), m_simpleHeaders.size() + 1);
QCOMPARE(headers.nameAt(headers.size() - 1), name.toLower());
}
void tst_QHttpHeaders::contains_enum()
{
QFETCH(WKH, name);
QFETCH(bool, exists);
bool result;
QBENCHMARK {
result = m_complexHeaders.contains(name);
}
QCOMPARE(result, exists);
}
void tst_QHttpHeaders::contains_string()
{
QFETCH(QString, name);
QFETCH(bool, exists);
bool result;
QBENCHMARK {
result = m_complexHeaders.contains(name);
}
QCOMPARE(result, exists);
}
void tst_QHttpHeaders::values_enum()
{
QFETCH(WKH, name);
QFETCH(bool, exists);
QList<QByteArray> result;
const QList<QByteArray> expectedResult{"value3", "value1", "value2", "value4"};
QBENCHMARK {
result = m_complexHeaders.values(name);
}
if (exists)
QCOMPARE(result, expectedResult);
else
QVERIFY(result.isEmpty());
}
void tst_QHttpHeaders::values_string()
{
QFETCH(QString, name);
QFETCH(bool, exists);
QList<QByteArray> result;
const QList<QByteArray> expectedResult{"value3", "value1", "value2", "value4"};
QBENCHMARK {
result = m_complexHeaders.values(name);
}
if (exists)
QCOMPARE(result, expectedResult);
else
QVERIFY(result.isEmpty());
}
void tst_QHttpHeaders::combinedValue_enum()
{
QFETCH(WKH, name);
QFETCH(bool, exists);
QByteArray result;
constexpr QByteArrayView expectedResult = "value3, value1, value2, value4";
QBENCHMARK {
result = m_complexHeaders.combinedValue(name);
}
if (exists)
QCOMPARE(result, expectedResult);
else
QVERIFY(result.isEmpty());
}
void tst_QHttpHeaders::combinedValue_string()
{
QFETCH(QString, name);
QFETCH(bool, exists);
QByteArray result;
constexpr QByteArrayView expectedResult = "value3, value1, value2, value4";
QBENCHMARK {
result = m_complexHeaders.combinedValue(name);
}
if (exists)
QCOMPARE(result, expectedResult);
else
QVERIFY(result.isEmpty());
}
void tst_QHttpHeaders::removeAll_enum()
{
QFETCH(WKH, name);
QFETCH(bool, exists);
QHttpHeaders headers = m_complexHeaders;
QCOMPARE(headers.contains(name), exists);
QBENCHMARK {
headers = m_complexHeaders; // Restore as we'll modify the headers
headers.removeAll(name);
}
QVERIFY(!headers.contains(name));
}
void tst_QHttpHeaders::removeAll_string()
{
QFETCH(QString, name);
QFETCH(bool, exists);
QHttpHeaders headers = m_complexHeaders;
QCOMPARE(headers.contains(name), exists);
QBENCHMARK {
headers = m_complexHeaders; // Restore as we'll modify the headers
headers.removeAll(name);
}
QVERIFY(!headers.contains(name));
}
QTEST_MAIN(tst_QHttpHeaders)
#include "tst_bench_qhttpheaders.moc"