add benchmarks from Qt4, some of which not yet ported to CMake build system

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2016-02-01 03:33:31 +02:00
parent 9cae2e9e5d
commit 7e2cedaf54
589 changed files with 166644 additions and 0 deletions

1
tests/auto/qsqldatabase/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
tst_qsqldatabase

View file

@ -0,0 +1,10 @@
CONFIG += testcase
TARGET = tst_qsqldatabase
SOURCES += tst_qsqldatabase.cpp
QT += sql testlib
win32: {
!wince*: LIBS += -lws2_32
else: LIBS += -lws2
}

Binary file not shown.

View file

@ -0,0 +1,600 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/* possible connection parameters */
#ifndef TST_DATABASES_H
#define TST_DATABASES_H
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
#include <QRegExp>
#include <QDir>
#include <QVariant>
#include <QDebug>
#include <QSqlTableModel>
#include <QtTest/QtTest>
#if defined (Q_OS_WIN) || defined (Q_OS_WIN32)
# include <qt_windows.h>
# if defined (Q_OS_WINCE)
# include <winsock2.h>
# endif
#else
#include <unistd.h>
#endif
#define CHECK_DATABASE( db ) \
if ( !db.isValid() ) { qFatal( "db is Invalid" ); }
#define QVERIFY_SQL(q, stmt) QVERIFY2((q).stmt, tst_Databases::printError((q).lastError(), db))
#define QFAIL_SQL(q, stmt) QVERIFY2(!(q).stmt, tst_Databases::printError((q).lastError(), db))
#define DBMS_SPECIFIC(db, driver) \
if (!db.driverName().startsWith(driver)) { QSKIP(driver " specific test", SkipSingle); return; }
// ### use QSystem::hostName if it is integrated in qtest/main
static QString qGetHostName()
{
static QString hostname;
if ( !hostname.isEmpty() )
return hostname;
char hn[257];
if ( gethostname( hn, 255 ) == 0 ) {
hn[256] = '\0';
hostname = QString::fromLatin1( hn );
hostname.replace( QLatin1Char( '.' ), QLatin1Char( '_' ) );
hostname.replace( QLatin1Char( '-' ), QLatin1Char( '_' ) );
}
return hostname;
}
// to prevent nameclashes on our database server, each machine
// will use its own set of table names. Call this function to get
// "tablename_hostname"
inline static QString qTableName( const QString& prefix, const char *sourceFileName )
{
return QLatin1String("dbtst")+QString::number(qHash(QLatin1String(sourceFileName) + "_" + qGetHostName().replace( "-", "_" )), 16)+"_"+prefix;
}
inline static QString qTableName( const QString& prefix, QSqlDriver* driver )
{
return driver->escapeIdentifier( prefix + "_" + qGetHostName(), QSqlDriver::TableName );
}
inline static bool testWhiteSpaceNames( const QString &name )
{
/* return name.startsWith( "QPSQL" )
|| name.startsWith( "QODBC" )
|| name.startsWith( "QSQLITE" )
|| name.startsWith( "QMYSQL" );*/
return name != QLatin1String("QSQLITE2");
}
inline static QString toHex( const QString& binary )
{
QString str;
static char const hexchars[] = "0123456789ABCDEF";
for ( int i = 0; i < binary.size(); i++ ) {
ushort code = binary.at(i).unicode();
str += (QChar)(hexchars[ (code >> 12) & 0x0F ]);
str += (QChar)(hexchars[ (code >> 8) & 0x0F ]);
str += (QChar)(hexchars[ (code >> 4) & 0x0F ]);
str += (QChar)(hexchars[ code & 0x0F ]);
}
return str;
}
class tst_Databases
{
public:
tst_Databases(): counter( 0 ), m_sqLitePrefix(QDir::tempPath())
{
if (!m_sqLitePrefix.endsWith(QLatin1Char('/')))
m_sqLitePrefix += QLatin1Char('/');
m_sqLitePrefix += QLatin1String("foo");
m_sqLitePrefix += QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch() % quint64(1000));
}
~tst_Databases()
{
close();
for (int i = m_sqLiteFiles.size() - 1; i >= 0; --i) {
QFile sqLiteFile(m_sqLiteFiles.at(i));
if (sqLiteFile.exists() && !sqLiteFile.remove()) {
qWarning() << "Cannot remove " << QDir::toNativeSeparators(sqLiteFile.fileName())
<< ':' << sqLiteFile.errorString();
}
}
}
// returns a testtable consisting of the names of all database connections if
// driverPrefix is empty, otherwise only those that start with driverPrefix.
int fillTestTable( const QString& driverPrefix = QString() ) const
{
QTest::addColumn<QString>( "dbName" );
int count = 0;
for ( int i = 0; i < dbNames.count(); ++i ) {
QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) );
if ( !db.isValid() )
continue;
if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) {
QTest::newRow( dbNames.at( i ).toLatin1() ) << dbNames.at( i );
++count;
}
}
return count;
}
int fillTestTableWithStrategies( const QString& driverPrefix = QString() ) const
{
QTest::addColumn<QString>( "dbName" );
QTest::addColumn<int>("submitpolicy_i");
int count = 0;
for ( int i = 0; i < dbNames.count(); ++i ) {
QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) );
if ( !db.isValid() )
continue;
if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) {
QTest::newRow( QString("%1 [field]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnFieldChange;
QTest::newRow( QString("%1 [row]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnRowChange;
QTest::newRow( QString("%1 [manual]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnManualSubmit;
++count;
}
}
return count;
}
void addDb( const QString& driver, const QString& dbName,
const QString& user = QString(), const QString& passwd = QString(),
const QString& host = QString(), int port = -1, const QString params = QString() )
{
QSqlDatabase db;
if ( !QSqlDatabase::drivers().contains( driver ) ) {
qWarning() << "Driver" << driver << "is not installed";
return;
}
// construct a stupid unique name
QString cName = QString::number( counter++ ) + "_" + driver + "@";
cName += host.isEmpty() ? dbName : host;
if ( port > 0 )
cName += ":" + QString::number( port );
db = QSqlDatabase::addDatabase( driver, cName );
if ( !db.isValid() ) {
qWarning( "Could not create database object" );
return;
}
db.setDatabaseName( dbName );
db.setUserName( user );
db.setPassword( passwd );
db.setHostName( host );
db.setPort( port );
db.setConnectOptions( params );
dbNames.append( cName );
}
void addDbs()
{
// addDb( "QOCI8", "//horsehead.nokia.troll.no:1521/pony.troll.no", "scott", "tiger" ); // Oracle 9i on horsehead
// addDb( "QOCI8", "//horsehead.nokia.troll.no:1521/ustest.troll.no", "scott", "tiger", "" ); // Oracle 9i on horsehead
// addDb( "QOCI8", "//iceblink.nokia.troll.no:1521/ice.troll.no", "scott", "tiger", "" ); // Oracle 8 on iceblink (not currently working)
// addDb( "QOCI", "//silence.nokia.troll.no:1521/testdb", "scott", "tiger" ); // Oracle 10g on silence
// addDb( "QOCI", "//bq-oracle10g.apac.nokia.com:1521/XE", "scott", "tiger" ); // Oracle 10gexpress
// This requires a local ODBC data source to be configured( pointing to a MySql database )
// addDb( "QODBC", "mysqlodbc", "troll", "trond" );
// addDb( "QODBC", "SqlServer", "troll", "trond" );
// addDb( "QTDS7", "testdb", "troll", "trondk", "horsehead" );
// addDb( "QODBC", "silencetestdb", "troll", "trond", "silence" );
// addDb( "QODBC", "horseheadtestdb", "troll", "trondk", "horsehead" );
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no" );
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3307 );
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3308, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 4.1.1
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3309, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 5.0.18 Linux
// addDb( "QMYSQL3", "testdb", "troll", "trond", "silence.nokia.troll.no" ); // MySQL 5.1.36 Windows
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "bq-mysql41.apac.nokia.com" ); // MySQL 4.1.22-2.el4 linux
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "bq-mysql50.apac.nokia.com" ); // MySQL 5.0.45-7.el5 linux
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "bq-mysql51.apac.nokia.com" ); // MySQL 5.1.36-6.7.2.i586 linux
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no" ); // V7.2 NOT SUPPORTED!
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5434 ); // V7.2 NOT SUPPORTED! Multi-byte
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5435 ); // V7.3
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5436 ); // V7.4
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5437 ); // V8.0.3
// addDb( "QPSQL7", "testdb", "troll", "trond", "silence.nokia.troll.no" ); // V8.2.1, UTF-8
// addDb( "QPSQL7", "testdb", "testuser", "Ee4Gabf6_", "bq-postgres74.apac.nokia.com" ); // Version 7.4.19-1.el4_6.1
// addDb( "QPSQL7", "testdb", "testuser", "Ee4Gabf6_", "bq-pgsql81.apac.nokia.com" ); // Version 8.1.11-1.el5_1.1
// addDb( "QPSQL7", "testdb", "testuser", "Ee4Gabf6_", "bq-pgsql84.apac.nokia.com" ); // Version 8.4.1-2.1.i586
// addDb( "QPSQL7", "testdb", "testuser", "Ee4Gabf6_", "bq-pgsql90.apac.nokia.com" ); // Version 9.0.0
// addDb( "QDB2", "testdb", "troll", "trond", "silence.nokia.troll.no" ); // DB2 v9.1 on silence
// addDb( "QDB2", "testdb", "testuser", "Ee4Gabf6_", "bq-db2-972.apac.nokia.com" ); // DB2
// yes - interbase really wants the physical path on the host machine.
// addDb( "QIBASE", "/opt/interbase/qttest.gdb", "SYSDBA", "masterkey", "horsehead.nokia.troll.no" );
// addDb( "QIBASE", "silence.troll.no:c:\\ibase\\testdb", "SYSDBA", "masterkey", "" ); // InterBase 7.5 on silence
// addDb( "QIBASE", "silence.troll.no:c:\\ibase\\testdb_ascii", "SYSDBA", "masterkey", "" ); // InterBase 7.5 on silence
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "firebird1-nokia.trolltech.com.au" ); // Firebird 1.5.5
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "firebird2-nokia.trolltech.com.au" ); // Firebird 2.1.1
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "bq-firebird1.apac.nokia.com" ); // Firebird 1.5.5
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "bq-firebird2.apac.nokia.com" ); // Firebird 2.1.1
// use in-memory database to prevent local files
// addDb("QSQLITE", ":memory:");
addDb( "QSQLITE", QDir::toNativeSeparators(sqLiteFileName()));
// addDb( "QSQLITE2", QDir::toNativeSeparators(QDir::tempPath()+"/foo2.db") );
// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=iceblink.nokia.troll.no\\ICEBLINK", "troll", "trond", "" );
// addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" );
// addDb( "QODBC", "DRIVER={MySQL ODBC 5.1 Driver};SERVER=bq-mysql50.apac.nokia.com;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
// addDb( "QODBC", "DRIVER={MySQL ODBC 5.1 Driver};SERVER=bq-mysql51.apac.nokia.com;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" );
// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" );
// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" );
// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" );
// addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" );
// addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" );
// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" );
// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" );
// addDb( "QODBC", "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\\dbs\\access\\testdb.mdb", "", "", "" );
// addDb( "QODBC", "DRIVER={Postgresql};SERVER=bq-pgsql84.apac.nokia.com;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
}
void open()
{
addDbs();
QStringList::Iterator it = dbNames.begin();
while ( it != dbNames.end() ) {
QSqlDatabase db = QSqlDatabase::database(( *it ), false );
qDebug() << "Opening:" << (*it);
if ( db.isValid() && !db.isOpen() ) {
if ( !db.open() ) {
qWarning( "tst_Databases: Unable to open %s on %s:\n%s", qPrintable( db.driverName() ), qPrintable( *it ), qPrintable( db.lastError().databaseText() ) );
// well... opening failed, so we just ignore the server, maybe it is not running
it = dbNames.erase( it );
} else {
++it;
}
}
}
}
void close()
{
for ( QStringList::Iterator it = dbNames.begin(); it != dbNames.end(); ++it ) {
{
QSqlDatabase db = QSqlDatabase::database(( *it ), false );
if ( db.isValid() && db.isOpen() )
db.close();
}
QSqlDatabase::removeDatabase(( *it ) );
}
dbNames.clear();
}
// for debugging only: outputs the connection as string
static QString dbToString( const QSqlDatabase db )
{
QString res = db.driverName() + "@";
if ( db.driverName().startsWith( "QODBC" ) || db.driverName().startsWith( "QOCI" ) ) {
res += db.databaseName();
} else {
res += db.hostName();
}
if ( db.port() > 0 ) {
res += ":" + QString::number( db.port() );
}
return res;
}
// drop a table only if it exists to prevent warnings
static void safeDropTables( QSqlDatabase db, const QStringList& tableNames )
{
bool wasDropped;
QSqlQuery q( db );
QStringList dbtables=db.tables();
foreach(const QString &tableName, tableNames)
{
wasDropped = true;
QString table=tableName;
if ( db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName))
table = db.driver()->stripDelimiters(table, QSqlDriver::TableName);
if ( dbtables.contains( table, Qt::CaseInsensitive ) ) {
foreach(const QString &table2, dbtables.filter(table, Qt::CaseInsensitive)) {
if(table2.compare(table.section('.', -1, -1), Qt::CaseInsensitive) == 0) {
table=db.driver()->escapeIdentifier(table2, QSqlDriver::TableName);
if(isPostgreSQL(db))
wasDropped = q.exec( "drop table " + table + " cascade");
else
wasDropped = q.exec( "drop table " + table);
dbtables.removeAll(table2);
}
}
}
if ( !wasDropped ) {
qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError();
// qWarning() << "last query:" << q.lastQuery();
// qWarning() << "dbtables:" << dbtables;
// qWarning() << "db.tables():" << db.tables();
}
}
}
static void safeDropTable( QSqlDatabase db, const QString& tableName )
{
safeDropTables(db, QStringList() << tableName);
}
static void safeDropViews( QSqlDatabase db, const QStringList &viewNames )
{
if ( isMSAccess( db ) ) // Access is sooo stupid.
safeDropTables( db, viewNames );
bool wasDropped;
QSqlQuery q( db );
QStringList dbtables=db.tables(QSql::Views);
foreach(QString viewName, viewNames)
{
wasDropped = true;
QString view=viewName;
if ( db.driver()->isIdentifierEscaped(view, QSqlDriver::TableName))
view = db.driver()->stripDelimiters(view, QSqlDriver::TableName);
if ( dbtables.contains( view, Qt::CaseInsensitive ) ) {
foreach(const QString &view2, dbtables.filter(view, Qt::CaseInsensitive)) {
if(view2.compare(view.section('.', -1, -1), Qt::CaseInsensitive) == 0) {
view=db.driver()->escapeIdentifier(view2, QSqlDriver::TableName);
wasDropped = q.exec( "drop view " + view);
dbtables.removeAll(view);
}
}
}
if ( !wasDropped )
qWarning() << dbToString(db) << "unable to drop view" << viewName << ':' << q.lastError();
// << "\nlast query:" << q.lastQuery()
// << "\ndbtables:" << dbtables
// << "\ndb.tables(QSql::Views):" << db.tables(QSql::Views);
}
}
static void safeDropView( QSqlDatabase db, const QString& tableName )
{
safeDropViews(db, QStringList() << tableName);
}
// returns the type name of the blob datatype for the database db.
// blobSize is only used if the db doesn't have a generic blob type
static QString blobTypeName( QSqlDatabase db, int blobSize = 10000 )
{
if ( db.driverName().startsWith( "QMYSQL" ) )
return "longblob";
if ( db.driverName().startsWith( "QPSQL" ) )
return "bytea";
if ( db.driverName().startsWith( "QTDS" )
|| isSqlServer( db )
|| isMSAccess( db ) )
return "image";
if ( db.driverName().startsWith( "QDB2" ) )
return QString( "blob(%1)" ).arg( blobSize );
if ( db.driverName().startsWith( "QIBASE" ) )
return QString( "blob sub_type 0 segment size 4096" );
if ( db.driverName().startsWith( "QOCI" )
|| db.driverName().startsWith( "QSQLITE" ) )
return "blob";
qDebug() << "tst_Databases::blobTypeName: Don't know the blob type for" << dbToString( db );
return "blob";
}
static QString autoFieldName( QSqlDatabase db )
{
if ( db.driverName().startsWith( "QMYSQL" ) )
return "AUTO_INCREMENT";
if ( db.driverName().startsWith( "QTDS" ) )
return "IDENTITY";
/* if ( db.driverName().startsWith( "QPSQL" ) )
return "SERIAL";*/
// if ( db.driverName().startsWith( "QDB2" ) )
// return "GENERATED BY DEFAULT AS IDENTITY";
return QString();
}
static QByteArray printError( const QSqlError& err )
{
QString result;
if(err.number() > 0)
result += '(' + QString::number(err.number()) + ") ";
result += '\'';
if(!err.driverText().isEmpty())
result += err.driverText() + "' || '";
result += err.databaseText() + "'";
return result.toLocal8Bit();
}
static QByteArray printError( const QSqlError& err, const QSqlDatabase& db )
{
QString result(dbToString(db) + ": ");
if(err.number() > 0)
result += '(' + QString::number(err.number()) + ") ";
result += '\'';
if(!err.driverText().isEmpty())
result += err.driverText() + "' || '";
result += err.databaseText() + "'";
return result.toLocal8Bit();
}
static bool isSqlServer( QSqlDatabase db )
{
return db.databaseName().contains( "sql server", Qt::CaseInsensitive )
|| db.databaseName().contains( "sqlserver", Qt::CaseInsensitive )
|| db.databaseName().contains( "sql native client", Qt::CaseInsensitive )
|| db.databaseName().contains( "bq-winserv", Qt::CaseInsensitive )
|| db.hostName().contains( "bq-winserv", Qt::CaseInsensitive );
}
static bool isMSAccess( QSqlDatabase db )
{
return db.databaseName().contains( "Access Driver", Qt::CaseInsensitive );
}
static bool isPostgreSQL( QSqlDatabase db )
{
return db.driverName().startsWith("QPSQL") || (db.driverName().startsWith("QODBC") && ( db.databaseName().contains("PostgreSQL", Qt::CaseInsensitive) || db.databaseName().contains("pgsql", Qt::CaseInsensitive) ) );
}
static bool isMySQL( QSqlDatabase db )
{
return db.driverName().startsWith("QMYSQL") || (db.driverName().startsWith("QODBC") && db.databaseName().contains("MySQL", Qt::CaseInsensitive) );
}
static bool isDB2( QSqlDatabase db )
{
return db.driverName().startsWith("QDB2") || (db.driverName().startsWith("QODBC") && db.databaseName().contains("db2", Qt::CaseInsensitive) );
}
// -1 on fail, else Oracle version
static int getOraVersion( QSqlDatabase db )
{
int ver = -1;
QSqlQuery q( "SELECT banner FROM v$version", db );
q.next();
QRegExp vers( "([0-9]+)\\.[0-9\\.]+[0-9]" );
if ( vers.indexIn( q.value( 0 ).toString() ) ) {
bool ok;
ver = vers.cap( 1 ).toInt( &ok );
if ( !ok )
ver = -1;
}
return ver;
}
static QString getMySqlVersion( const QSqlDatabase &db )
{
QSqlQuery q(db);
q.exec( "select version()" );
if(q.next())
return q.value( 0 ).toString();
else
return QString();
}
static QString getPSQLVersion( const QSqlDatabase &db )
{
QSqlQuery q(db);
q.exec( "select version()" );
if(q.next())
return q.value( 0 ).toString();
else
return QString();
}
QString sqLiteFileName() // Return a temporary file name for SQLite DB
{
const QString newFileName = m_sqLitePrefix + QLatin1Char('_')
+ QString::number(m_sqLiteFiles.size()) + QLatin1String(".db");
m_sqLiteFiles.append(newFileName);
return newFileName;
}
QStringList dbNames;
int counter;
private:
QString m_sqLitePrefix;
QStringList m_sqLiteFiles;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
# if(WITH_OPENGL AND OPENGL_FOUND)
# add_subdirectory(opengl)
# endif()
# if(WITH_DBUS AND DBUS_FOUND)
# add_subdirectory(dbus)
# endif()

81
tests/benchmarks/README Normal file
View file

@ -0,0 +1,81 @@
The most reliable way of running benchmarks is to do it in an otherwise idle
system. On a busy system, the results will vary according to the other tasks
demanding attention in the system.
We have managed to obtain quite reliable results by doing the following on
Linux (and you need root):
- switching the scheduler to a Real-Time mode
- setting the processor affinity to one single processor
- disabling the other thread of the same core
This should work rather well for CPU-intensive tasks. A task that is in Real-
Time mode will simply not be preempted by the OS. But if you make OS syscalls,
especially I/O ones, your task will be de-scheduled. Note that this includes
page faults, so if you can, make sure your benchmark's warmup code paths touch
most of the data.
To do this you need a tool called schedtool (package schedtool), from
http://freequaos.host.sk/schedtool/
From this point on, we are using CPU0 for all tasks:
If you have a Hyperthreaded multi-core processor (Core-i5 and Core-i7), you
have to disable the other thread of the same core as CPU0. To discover which
one it is:
$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
This will print something like 0,4, meaning that CPUs 0 and 4 are sibling
threads on the same core. So we'll turn CPU 4 off:
(as root)
# echo 0 > /sys/devices/system/cpu/cpu4/online
To turn it back on, echo 1 into the same file.
To run a task on CPU 0 exclusively, using FIFO RT priority 10, you run the
following:
(as root)
# schedtool -F -p 10 -a 1 -e ./taskname
For example:
# schedtool -F -p 10 -a 1 -e ./tst_bench_qstring -tickcounter
Warning: if your task livelocks or takes far too long to complete, your system
may be unusable for a long time, especially if you don't have other cores to
run stuff on. To prevent that, run it before schedtool and time it.
You can also limit the CPU time that the task is allowed to take. Run in the
same shell as you'll run schedtool:
$ ulimit -s 300
To limit to 300 seconds (5 minutes)
If your task runs away, it will get a SIGXCPU after consuming 5 minutes of CPU
time (5 minutes running at 100%).
If your app is multithreaded, you may want to give it more CPUs, like CPU0 and
CPU1 with -a 3 (it's a bitmask).
For best results, you should disable ALL other cores and threads of the same
processor. The new Core-i7 have one processor with 4 cores,
each core can run 2 threads; the older Mac Pros have two processors with 4
cores each. So on those Mac Pros, you'd disable cores 1, 2 and 3, while on the
Core-i7, you'll need to disable all other CPUs.
However, disabling just the sibling thread seems to produce very reliable
results for me already, with variance often below 0.5% (even though there are
some measurable spikes).
Other things to try:
Running the benchmark with highest priority, i.e. "sudo nice -19"
usually produces stable results on some machines. If the benchmark also
involves displaying something on the screen (on X11), running it with
"-sync" is a must. Though, in that case the "real" cost is not correct,
but it is useful to discover regressions.
Also; not many people know about ionice (1)
ionice - get/set program io scheduling class and priority

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qtextcodec
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,179 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QTextCodec>
#include <QFile>
#include <qtest.h>
Q_DECLARE_METATYPE(QList<QByteArray>)
Q_DECLARE_METATYPE(QTextCodec *)
class tst_QTextCodec: public QObject
{
Q_OBJECT
private slots:
void codecForName() const;
void codecForName_data() const;
void codecForMib() const;
void fromUnicode_data() const;
void fromUnicode() const;
void toUnicode_data() const;
void toUnicode() const;
};
void tst_QTextCodec::codecForName() const
{
QFETCH(QList<QByteArray>, codecs);
QBENCHMARK {
foreach(const QByteArray& c, codecs) {
QVERIFY(QTextCodec::codecForName(c));
QVERIFY(QTextCodec::codecForName(c + "-"));
}
foreach(const QByteArray& c, codecs) {
QVERIFY(QTextCodec::codecForName(c + "+"));
QVERIFY(QTextCodec::codecForName(c + "*"));
}
}
}
void tst_QTextCodec::codecForName_data() const
{
QTest::addColumn<QList<QByteArray> >("codecs");
QTest::newRow("all") << QTextCodec::availableCodecs();
QTest::newRow("many utf-8") << (QList<QByteArray>()
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8"
<< "utf-8" << "utf-8" << "utf-8" << "utf-8" << "utf-8" );
}
void tst_QTextCodec::codecForMib() const
{
QBENCHMARK {
QTextCodec::codecForMib(106);
QTextCodec::codecForMib(111);
QTextCodec::codecForMib(106);
QTextCodec::codecForMib(2254);
QTextCodec::codecForMib(2255);
QTextCodec::codecForMib(2256);
QTextCodec::codecForMib(2257);
QTextCodec::codecForMib(2258);
QTextCodec::codecForMib(111);
QTextCodec::codecForMib(2250);
QTextCodec::codecForMib(2251);
QTextCodec::codecForMib(2252);
QTextCodec::codecForMib(106);
QTextCodec::codecForMib(106);
QTextCodec::codecForMib(106);
QTextCodec::codecForMib(106);
}
}
void tst_QTextCodec::fromUnicode_data() const
{
QTest::addColumn<QTextCodec*>("codec");
QTest::newRow("utf-8") << QTextCodec::codecForName("utf-8");
QTest::newRow("latin 1") << QTextCodec::codecForName("latin 1");
QTest::newRow("utf-16") << QTextCodec::codecForName("utf16"); ;
QTest::newRow("utf-32") << QTextCodec::codecForName("utf32");
QTest::newRow("latin15") << QTextCodec::codecForName("iso-8859-15");
QTest::newRow("eucKr") << QTextCodec::codecForName("eucKr");
}
void tst_QTextCodec::fromUnicode() const
{
QFETCH(QTextCodec*, codec);
QFile file(SRCDIR "utf-8.txt");
if (!file.open(QFile::ReadOnly)) {
qFatal("Cannot open input file");
return;
}
QByteArray data = file.readAll();
const char *d = data.constData();
int size = data.size();
QString s = QString::fromUtf8(d, size);
s = s + s + s;
s = s + s + s;
QBENCHMARK {
for (int i = 0; i < 10; i ++)
codec->fromUnicode(s);
}
}
void tst_QTextCodec::toUnicode_data() const
{
fromUnicode_data();
}
void tst_QTextCodec::toUnicode() const
{
QFETCH(QTextCodec*, codec);
QFile file(SRCDIR "utf-8.txt");
QVERIFY(file.open(QFile::ReadOnly));
QByteArray data = file.readAll();
const char *d = data.constData();
int size = data.size();
QString s = QString::fromUtf8(d, size);
s = s + s + s;
s = s + s + s;
QByteArray orig = codec->fromUnicode(s);
QBENCHMARK {
for (int i = 0; i < 10; i ++)
codec->toUnicode(orig);
}
}
QTEST_MAIN(tst_QTextCodec)
#include "moc_main.cpp"

View file

@ -0,0 +1,72 @@
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français

View file

@ -0,0 +1,200 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QtCore/QDirIterator>
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
# include <unistd.h>
#endif
class bench_QDir_10000 : public QObject{
Q_OBJECT
public slots:
void initTestCase() {
QDir testdir = QDir::tempPath();
const QString subfolder_name = QLatin1String("test_speed");
QVERIFY(testdir.mkdir(subfolder_name));
QVERIFY(testdir.cd(subfolder_name));
for (uint i=0; i<10000; ++i) {
QFile file(testdir.absolutePath() + "/testfile_" + QString::number(i));
file.open(QIODevice::WriteOnly);
}
}
void cleanupTestCase() {
{
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
testdir.setSorting(QDir::Unsorted);
testdir.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
foreach (const QString &filename, testdir.entryList()) {
testdir.remove(filename);
}
}
const QDir temp = QDir(QDir::tempPath());
temp.rmdir(QLatin1String("test_speed"));
}
private slots:
void baseline() {}
void sizeSpeed() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
QBENCHMARK {
QFileInfoList fileInfoList = testdir.entryInfoList(QDir::Files, QDir::Unsorted);
foreach (const QFileInfo &fileInfo, fileInfoList) {
fileInfo.isDir();
fileInfo.size();
}
}
}
void sizeSpeedIterator() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
QBENCHMARK {
QDirIterator dit(testdir.path(), QDir::Files);
while (dit.hasNext()) {
dit.next();
dit.fileInfo().isDir();
dit.fileInfo().size();
}
}
}
void sizeSpeedWithoutFilter() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
QBENCHMARK {
QFileInfoList fileInfoList = testdir.entryInfoList(QDir::NoFilter, QDir::Unsorted);
foreach (const QFileInfo &fileInfo, fileInfoList) {
fileInfo.size();
}
}
}
void sizeSpeedWithoutFilterIterator() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
QBENCHMARK {
QDirIterator dit(testdir.path());
while (dit.hasNext()) {
dit.next();
dit.fileInfo().isDir();
dit.fileInfo().size();
}
}
}
void sizeSpeedWithoutFileInfoList() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
testdir.setSorting(QDir::Unsorted);
QBENCHMARK {
QStringList fileList = testdir.entryList(QDir::NoFilter, QDir::Unsorted);
foreach (const QString &filename, fileList) {
QFileInfo fileInfo(filename);
fileInfo.size();
}
}
}
void iDontWantAnyStat() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
testdir.setSorting(QDir::Unsorted);
testdir.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
QBENCHMARK {
QStringList fileList = testdir.entryList(QDir::NoFilter, QDir::Unsorted);
foreach (const QString &filename, fileList) {
}
}
}
void iDontWantAnyStatIterator() {
QBENCHMARK {
QDirIterator dit(QDir::tempPath() + QLatin1String("/test_speed"));
while (dit.hasNext()) {
dit.next();
}
}
}
void sizeSpeedWithoutFilterLowLevel() {
QDir testdir(QDir::tempPath() + QLatin1String("/test_speed"));
#ifdef Q_OS_WIN
const wchar_t *dirpath = (wchar_t*)testdir.absolutePath().utf16();
wchar_t appendedPath[MAX_PATH];
wcscpy(appendedPath, dirpath);
wcscat(appendedPath, L"\\*");
WIN32_FIND_DATA fd;
HANDLE hSearch = FindFirstFileW(appendedPath, &fd);
QVERIFY(hSearch != INVALID_HANDLE_VALUE);
QBENCHMARK {
do {
} while (FindNextFile(hSearch, &fd));
}
FindClose(hSearch);
#else
DIR *dir = opendir(qPrintable(testdir.absolutePath()));
QVERIFY(dir);
QVERIFY(!chdir(qPrintable(testdir.absolutePath())));
QBENCHMARK {
struct dirent *item = readdir(dir);
while (item) {
char *fileName = item->d_name;
struct stat fileStat;
QVERIFY(!stat(fileName, &fileStat));
item = readdir(dir);
}
}
closedir(dir);
#endif
}
};
QTEST_MAIN(bench_QDir_10000)
#include "10000/moc_bench_qdir_10000.cpp"

View file

@ -0,0 +1,8 @@
katie_test(bench_qdir_10000
${CMAKE_CURRENT_SOURCE_DIR}/10000/bench_qdir_10000.cpp
)
katie_test(bench_qdir_tree
${CMAKE_CURRENT_SOURCE_DIR}/tree/bench_qdir_tree.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tree/bench_qdir_tree.qrc
)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,242 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QTest>
#include <QDirIterator>
#include <QFile>
#include <QString>
#include <QStack>
#include "../../../../../shared/filesystem.h"
class bench_QDir_tree
: public QObject
{
Q_OBJECT
public:
bench_QDir_tree()
: prefix("./test-tree/"),
musicprefix(QLatin1String("music")),
photoprefix(QLatin1String("photos")),
sourceprefix(QLatin1String("source")),
musicsize(0),
photosize(0),
sourcesize(0)
{
}
private:
QByteArray prefix;
QString musicprefix;
QString photoprefix;
QString sourceprefix;
qint64 musicsize;
qint64 photosize;
qint64 sourcesize;
private slots:
void initTestCase()
{
QFile list(":/4.6.0-list.txt");
QVERIFY(list.open(QIODevice::ReadOnly | QIODevice::Text));
QVERIFY(fs.createDirectory(prefix));
QStack<QByteArray> stack;
QByteArray line;
Q_FOREVER {
char ch;
if (!list.getChar(&ch))
break;
if (ch != ' ') {
line.append(ch);
continue;
}
int pop = 1;
if (!line.isEmpty())
pop = line.toInt();
while (pop) {
stack.pop();
--pop;
}
line = list.readLine();
line.chop(1);
stack.push(line);
line = prefix;
Q_FOREACH(const QByteArray &pathElement, stack)
line += pathElement;
if (line.endsWith('/'))
QVERIFY(fs.createDirectory(line));
else
QVERIFY(fs.createFile(line));
line.clear();
}
//Use case: music collection - 10 files in 100 directories (albums)
QVERIFY(fs.createDirectory(musicprefix));
for (int i=0;i<1000;i++) {
if ((i % 10) == 0)
QVERIFY(fs.createDirectory(QString("%1/directory%2").arg(musicprefix).arg(i/10)));
qint64 size = fs.createFileWithContent(QString("%1/directory%2/file%3").arg(musicprefix).arg(i/10).arg(i));
QVERIFY(size > 0);
musicsize += size;
}
//Use case: photos - 1000 files in 1 directory
QVERIFY(fs.createDirectory(photoprefix));
for (int i=0;i<1000;i++) {
qint64 size = fs.createFileWithContent(QString("%1/file%2").arg(photoprefix).arg(i));
QVERIFY(size > 0);
photosize += size;
}
//Use case: source - 10 files in 10 subdirectories in 10 directories (1000 total)
QVERIFY(fs.createDirectory(sourceprefix));
for (int i=0;i<1000;i++) {
if ((i % 100) == 0)
QVERIFY(fs.createDirectory(QString("%1/directory%2").arg(sourceprefix).arg(i/100)));
if ((i % 10) == 0)
QVERIFY(fs.createDirectory(QString("%1/directory%2/subdirectory%3").arg(sourceprefix).arg(i/100).arg(i/10)));
qint64 size = fs.createFileWithContent(QString("%1/directory%2/subdirectory%3/file%4").arg(sourceprefix).arg(i/100).arg(i/10).arg(i));
QVERIFY(size > 0);
sourcesize += size;
}
}
void fileSearch_data() const
{
QTest::addColumn<QStringList>("nameFilters");
QTest::addColumn<int>("filter");
QTest::addColumn<int>("entryCount");
QTest::newRow("*.cpp") << QStringList("*.cpp")
<< int(QDir::Files)
<< 3813;
QTest::newRow("executables") << QStringList("*")
<< int(QDir::Executable | QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot)
<< 543;
}
void fileSearch() const
{
QFETCH(QStringList, nameFilters);
QFETCH(int, filter);
QFETCH(int, entryCount);
int count = 0;
QBENCHMARK {
// Recursive directory iteration
QDirIterator iterator(prefix, nameFilters, QDir::Filter(filter),
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
count = 0;
while (iterator.hasNext()) {
iterator.next();
++count;
}
QCOMPARE(count, entryCount);
}
QCOMPARE(count, entryCount);
}
void traverseDirectory() const
{
int count = 0;
QBENCHMARK {
QDirIterator iterator(prefix,
QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System,
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
count = 0;
while (iterator.hasNext()) {
iterator.next();
++count;
}
QCOMPARE(count, 11963);
}
QCOMPARE(count, 11963);
}
void thousandFiles_data() const
{
QTest::addColumn<QString>("dirName");
QTest::addColumn<qint64>("expectedSize");
QTest::newRow("music") << musicprefix << musicsize;
QTest::newRow("photos") << photoprefix << photosize;
QTest::newRow("src") << sourceprefix << sourcesize;
}
void thousandFiles() const
{
QFETCH(QString, dirName);
QFETCH(qint64, expectedSize);
QBENCHMARK {
qint64 totalsize = 0;
int count = 0;
QDirIterator iter(dirName, QDir::Files, QDirIterator::Subdirectories);
while(iter.hasNext()) {
iter.next();
count++;
totalsize += iter.fileInfo().size();
}
QCOMPARE(count, 1000);
QCOMPARE(totalsize, expectedSize);
}
}
private:
FileSystem fs;
};
QTEST_MAIN(bench_QDir_tree)
#include "tree/moc_bench_qdir_tree.cpp"
#include "tree/qrc_bench_qdir_tree.cpp"

View file

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>4.6.0-list.txt</file>
</qresource>
</RCC>

View file

@ -0,0 +1,5 @@
katie_test(tst_bench_qdiriterator
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qfilesystemiterator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qfilesystemiterator.h
)

View file

@ -0,0 +1,252 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QDirIterator>
#include <QString>
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
# include <errno.h>
# include <string.h>
#endif
#include <qtest.h>
#include "qfilesystemiterator.h"
class tst_qdiriterator : public QObject
{
Q_OBJECT
private slots:
void posix();
void posix_data() { data(); }
void diriterator();
void diriterator_data() { data(); }
void fsiterator();
void fsiterator_data() { data(); }
void data();
};
void tst_qdiriterator::data()
{
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
QByteArray qtdir = qPrintable(QCoreApplication::applicationDirPath());
qtdir += "/depot";
#else
#if defined(Q_OS_WIN)
const char *qtdir = "C:\\depot\\qt\\main";
#else
const char *qtdir = ::getenv("QTDIR");
#endif
if (!qtdir) {
fprintf(stderr, "QTDIR not set\n");
exit(1);
}
#endif
QTest::addColumn<QByteArray>("dirpath");
QByteArray ba = QByteArray(qtdir) + "/src/core";
QByteArray ba1 = ba + "/io";
QTest::newRow(ba) << ba;
//QTest::newRow(ba1) << ba1;
}
#ifdef Q_OS_WIN
static int posix_helper(const wchar_t *dirpath)
{
int count = 0;
HANDLE hSearch;
WIN32_FIND_DATA fd;
const size_t origDirPathLength = wcslen(dirpath);
wchar_t appendedPath[MAX_PATH];
wcscpy(appendedPath, dirpath);
wcscat(appendedPath, L"\\*");
hSearch = FindFirstFile(appendedPath, &fd);
appendedPath[origDirPathLength] = 0;
if (hSearch == INVALID_HANDLE_VALUE) {
qWarning("FindFirstFile failed");
return count;
}
do {
if (!(fd.cFileName[0] == L'.' && fd.cFileName[1] == 0) &&
!(fd.cFileName[0] == L'.' && fd.cFileName[1] == L'.' && fd.cFileName[2] == 0))
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
wcscat(appendedPath, L"\\");
wcscat(appendedPath, fd.cFileName);
count += posix_helper(appendedPath);
appendedPath[origDirPathLength] = 0;
}
else {
++count;
}
}
} while (FindNextFile(hSearch, &fd));
FindClose(hSearch);
return count;
}
#else
static int posix_helper(const char *dirpath)
{
//qDebug() << "DIR" << dirpath;
DIR *dir = ::opendir(dirpath);
if (!dir)
return 0;
dirent *entry = 0;
int count = 0;
while ((entry = ::readdir(dir))) {
if (qstrcmp(entry->d_name, ".") == 0)
continue;
if (qstrcmp(entry->d_name, "..") == 0)
continue;
++count;
QByteArray ba = dirpath;
ba += '/';
ba += entry->d_name;
struct stat st;
lstat(ba.constData(), &st);
if (S_ISDIR(st.st_mode))
count += posix_helper(ba.constData());
}
::closedir(dir);
return count;
}
#endif
void tst_qdiriterator::posix()
{
QFETCH(QByteArray, dirpath);
int count = 0;
QString path(dirpath);
QBENCHMARK {
#ifdef Q_OS_WIN
wchar_t wPath[MAX_PATH];
path.toWCharArray(wPath);
count = posix_helper(wPath);
#else
count = posix_helper(dirpath.constData());
#endif
}
qDebug() << count;
}
void tst_qdiriterator::diriterator()
{
QFETCH(QByteArray, dirpath);
int count = 0;
QBENCHMARK {
int c = 0;
QDirIterator dir(dirpath,
//QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot,
//QDir::AllEntries | QDir::Hidden,
QDir::Files,
QDirIterator::Subdirectories);
while (dir.hasNext()) {
dir.next();
//printf("%s\n", qPrintable(dir.fileName()));
0 && printf("%d %s\n",
dir.fileInfo().isDir(),
//qPrintable(dir.fileInfo().absoluteFilePath()),
//qPrintable(dir.path()),
qPrintable(dir.filePath()));
++c;
}
count = c;
}
qDebug() << count;
}
void tst_qdiriterator::fsiterator()
{
QFETCH(QByteArray, dirpath);
int count = 0;
int dump = 0;
QBENCHMARK {
int c = 0;
dump && printf("\n\n\n\n");
QFileSystemIterator dir(dirpath,
//QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot,
//QDir::AllEntries | QDir::Hidden,
//QDir::Files | QDir::NoDotAndDotDot,
QDir::Files,
QFileSystemIterator::Subdirectories);
for (; !dir.atEnd(); dir.next()) {
dump && printf("%d %s\n",
dir.fileInfo().isDir(),
//qPrintable(dir.fileInfo().absoluteFilePath()),
//qPrintable(dir.path()),
qPrintable(dir.filePath())
);
++c;
}
count = c;
}
qDebug() << count;
}
QTEST_MAIN(tst_qdiriterator)
#include "moc_main.cpp"

View file

@ -0,0 +1,678 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\since 4.5
\class QFileSystemIterator
\brief The QFileSystemIterator class provides an iterator for directory entrylists.
You can use QFileSystemIterator to navigate entries of a directory one at a time.
It is similar to QDir::entryList() and QDir::entryInfoList(), but because
it lists entries one at a time instead of all at once, it scales better
and is more suitable for large directories. It also supports listing
directory contents recursively, and following symbolic links. Unlike
QDir::entryList(), QFileSystemIterator does not support sorting.
The QFileSystemIterator constructor takes a QDir or a directory as
argument. After construction, the iterator is located before the first
directory entry. Here's how to iterate over all the entries sequentially:
\snippet doc/src/snippets/code/src.corelib.io.qdiriterator.cpp 0
The next() function returns the path to the next directory entry and
advances the iterator. You can also call filePath() to get the current
file path without advancing the iterator. The fileName() function returns
only the name of the file, similar to how QDir::entryList() works. You can
also call fileInfo() to get a QFileInfo for the current entry.
Unlike Qt's container iterators, QFileSystemIterator is uni-directional (i.e.,
you cannot iterate directories in reverse order) and does not allow random
access.
QFileSystemIterator works with all supported file engines, and is implemented
using QAbstractFileEngineIterator.
\sa QDir, QDir::entryList(), QAbstractFileEngineIterator
*/
/*! \enum QFileSystemIterator::IteratorFlag
This enum describes flags that you can combine to configure the behavior
of QFileSystemIterator.
\value NoIteratorFlags The default value, representing no flags. The
iterator will return entries for the assigned path.
\value Subdirectories List entries inside all subdirectories as well.
\value FollowSymlinks When combined with Subdirectories, this flag
enables iterating through all subdirectories of the assigned path,
following all symbolic links. Symbolic link loops (e.g., "link" => "." or
"link" => "..") are automatically detected and ignored.
*/
#include "qfilesystemiterator.h"
#include <QDebug>
#include <QtCore/qset.h>
#include <QtCore/qstack.h>
#include <QtCore/qvariant.h>
#ifdef Q_OS_WIN
# include <windows.h>
# include <atlbase.h>
#else
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
# include <errno.h>
#endif
QT_BEGIN_NAMESPACE
class QFileSystemIteratorPrivate
{
public:
QFileSystemIteratorPrivate(const QString &path, const QStringList &nameFilters,
QDir::Filters filters, QFileSystemIterator::IteratorFlags flags);
~QFileSystemIteratorPrivate();
void pushSubDirectory(const QByteArray &path);
void advance();
bool isAcceptable() const;
bool shouldFollowDirectory(const QFileInfo &);
//bool matchesFilters(const QAbstractFileEngineIterator *it) const;
inline bool atEnd() const { return m_dirPaths.isEmpty(); }
#ifdef Q_OS_WIN
QStack<HANDLE> m_dirStructs;
WIN32_FIND_DATA* m_entry;
WIN32_FIND_DATA m_fileSearchResult;
bool m_bFirstSearchResult;
#else
QStack<DIR *> m_dirStructs;
dirent *m_entry;
#endif
QSet<QString> visitedLinks;
QStack<QByteArray> m_dirPaths;
QFileInfo fileInfo;
QString currentFilePath;
QFileSystemIterator::IteratorFlags iteratorFlags;
QDir::Filters filters;
QStringList nameFilters;
enum { DontShowDir, ShowDotDotDir, ShowDotDir, ShowDir }
m_currentDirShown, m_nextDirShown;
QFileSystemIterator *q;
private:
bool advanceHelper(); // returns true if we know we have something suitable
};
/*!
\internal
*/
QFileSystemIteratorPrivate::QFileSystemIteratorPrivate(const QString &path,
const QStringList &nameFilters, QDir::Filters filters,
QFileSystemIterator::IteratorFlags flags)
: iteratorFlags(flags)
{
if (filters == QDir::NoFilter)
filters = QDir::AllEntries;
this->filters = filters;
this->nameFilters = nameFilters;
fileInfo.setFile(path);
QString dir = fileInfo.isSymLink() ? fileInfo.canonicalFilePath() : path;
pushSubDirectory(dir.toLocal8Bit());
// skip to acceptable entry
while (true) {
if (atEnd())
return;
if (isAcceptable())
return;
if (advanceHelper())
return;
}
}
/*!
\internal
*/
QFileSystemIteratorPrivate::~QFileSystemIteratorPrivate()
{
#ifdef Q_OS_WIN
while (!m_dirStructs.isEmpty())
::FindClose(m_dirStructs.pop());
#else
while (!m_dirStructs.isEmpty())
::closedir(m_dirStructs.pop());
#endif
}
#ifdef Q_OS_WIN
static bool isDotOrDotDot(const wchar_t* name)
{
if (name[0] == L'.' && name[1] == 0)
return true;
if (name[0] == L'.' && name[1] == L'.' && name[2] == 0)
return true;
return false;
}
#else
static bool isDotOrDotDot(const char *name)
{
if (name[0] == '.' && name[1] == 0)
return true;
if (name[0] == '.' && name[1] == '.' && name[2] == 0)
return true;
return false;
}
#endif
/*!
\internal
*/
void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path)
{
/*
if (iteratorFlags & QFileSystemIterator::FollowSymlinks) {
if (fileInfo.filePath() != path)
fileInfo.setFile(path);
if (fileInfo.isSymLink()) {
visitedLinks << fileInfo.canonicalFilePath();
} else {
visitedLinks << fileInfo.absoluteFilePath();
}
}
*/
#ifdef Q_OS_WIN
wchar_t szSearchPath[MAX_PATH];
QString::fromAscii(path).toWCharArray(szSearchPath);
wcscat(szSearchPath, L"\\*");
HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult);
m_bFirstSearchResult = true;
#else
DIR *dir = ::opendir(path.constData());
//m_entry = ::readdir(dir);
//while (m_entry && isDotOrDotDot(m_entry->d_name))
// m_entry = ::readdir(m_dirStructs.top());
#endif
m_dirStructs.append(dir);
m_dirPaths.append(path);
m_entry = 0;
if (filters & QDir::Dirs)
m_nextDirShown = ShowDir;
else
m_nextDirShown = DontShowDir;
m_currentDirShown = DontShowDir;
}
/*!
\internal
*/
bool QFileSystemIteratorPrivate::isAcceptable() const
{
if (!m_entry)
return false;
return true;
}
/*!
\internal
*/
void QFileSystemIteratorPrivate::advance()
{
while (true) {
if (advanceHelper())
return;
if (atEnd())
return;
if (isAcceptable())
return;
}
}
bool QFileSystemIteratorPrivate::advanceHelper()
{
if (m_dirStructs.isEmpty())
return true;
//printf("ADV %d %d\n", int(m_currentDirShown), int(m_nextDirShown));
if ((filters & QDir::Dirs)) {
m_currentDirShown = m_nextDirShown;
if (m_nextDirShown == ShowDir) {
//printf("RESTING ON DIR %s %x\n", m_dirPaths.top().constData(), int(filters));
m_nextDirShown = (filters & QDir::NoDotAndDotDot) ? DontShowDir : ShowDotDir;
// skip start directory itself
if (m_dirStructs.size() == 1 && m_currentDirShown == ShowDir)
return advanceHelper();
return true;
}
if (m_nextDirShown == ShowDotDir) {
//printf("RESTING ON DOT %s %x\n", m_dirPaths.top().constData(), int(filters));
m_nextDirShown = ShowDotDotDir;
return true;
}
if (m_nextDirShown == ShowDotDotDir) {
//printf("RESTING ON DOTDOT %s %x\n", m_dirPaths.top().constData(), int(filters));
m_nextDirShown = DontShowDir;
return true;
}
m_currentDirShown = DontShowDir;
}
#ifdef Q_OS_WIN
m_entry = &m_fileSearchResult;
if (m_bFirstSearchResult) {
m_bFirstSearchResult = false;
} else {
if (!FindNextFile(m_dirStructs.top(), m_entry))
m_entry = 0;
}
while (m_entry && isDotOrDotDot(m_entry->cFileName))
if (!FindNextFile(m_dirStructs.top(), m_entry))
m_entry = 0;
if (!m_entry) {
m_dirPaths.pop();
FindClose(m_dirStructs.pop());
return false;
}
if (m_entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
QByteArray ba = m_dirPaths.top();
ba += '\\';
ba += QString::fromWCharArray(m_entry->cFileName);
pushSubDirectory(ba);
}
#else
m_entry = ::readdir(m_dirStructs.top());
while (m_entry && isDotOrDotDot(m_entry->d_name))
m_entry = ::readdir(m_dirStructs.top());
//return false; // further iteration possibly needed
//printf("READ %p %s\n", m_entry, m_entry ? m_entry->d_name : "");
if (!m_entry) {
m_dirPaths.pop();
DIR *dir = m_dirStructs.pop();
::closedir(dir);
return false; // further iteration possibly needed
}
const char *name = m_entry->d_name;
QByteArray ba = m_dirPaths.top();
ba += '/';
ba += name;
struct stat st;
lstat(ba.constData(), &st);
if (S_ISDIR(st.st_mode)) {
pushSubDirectory(ba);
return false; // further iteration possibly needed
}
#endif
return false; // further iteration possiblye needed
}
/*!
\internal
*/
bool QFileSystemIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo)
{
// If we're doing flat iteration, we're done.
if (!(iteratorFlags & QFileSystemIterator::Subdirectories))
return false;
// Never follow non-directory entries
if (!fileInfo.isDir())
return false;
// Never follow . and ..
if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String(".."))
return false;
// Check symlinks
if (fileInfo.isSymLink() && !(iteratorFlags & QFileSystemIterator::FollowSymlinks)) {
// Follow symlinks only if FollowSymlinks was passed
return false;
}
// Stop link loops
if (visitedLinks.contains(fileInfo.canonicalFilePath()))
return false;
return true;
}
/*!
\internal
This convenience function implements the iterator's filtering logics and
applies then to the current directory entry.
It returns true if the current entry matches the filters (i.e., the
current entry will be returned as part of the directory iteration);
otherwise, false is returned.
*/
#if 0
bool QFileSystemIteratorPrivate::matchesFilters(const QAbstractFileEngineIterator *it) const
{
const bool filterPermissions = ((filters & QDir::PermissionMask)
&& (filters & QDir::PermissionMask) != QDir::PermissionMask);
const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
const bool skipFiles = !(filters & QDir::Files);
const bool skipSymlinks = (filters & QDir::NoSymLinks);
const bool doReadable = !filterPermissions || (filters & QDir::Readable);
const bool doWritable = !filterPermissions || (filters & QDir::Writable);
const bool doExecutable = !filterPermissions || (filters & QDir::Executable);
const bool includeHidden = (filters & QDir::Hidden);
const bool includeSystem = (filters & QDir::System);
#ifndef QT_NO_REGEXP
// Prepare name filters
QList<QRegExp> regexps;
bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*")));
if (hasNameFilters) {
for (int i = 0; i < nameFilters.size(); ++i) {
regexps << QRegExp(nameFilters.at(i),
(filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
QRegExp::Wildcard);
}
}
#endif
QString fileName = it->currentFileName();
if (fileName.isEmpty()) {
// invalid entry
return false;
}
QFileInfo fi = it->currentFileInfo();
QString filePath = it->currentFilePath();
#ifndef QT_NO_REGEXP
// Pass all entries through name filters, except dirs if the AllDirs
// filter is passed.
if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) {
bool matched = false;
for (int i = 0; i < regexps.size(); ++i) {
if (regexps.at(i).exactMatch(fileName)) {
matched = true;
break;
}
}
if (!matched)
return false;
}
#endif
bool dotOrDotDot = (fileName == QLatin1String(".") || fileName == QLatin1String(".."));
if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot)
return false;
bool isHidden = !dotOrDotDot && fi.isHidden();
if (!includeHidden && isHidden)
return false;
bool isSystem = (!fi.isFile() && !fi.isDir() && !fi.isSymLink())
|| (!fi.exists() && fi.isSymLink());
if (!includeSystem && isSystem)
return false;
bool alwaysShow = (filters & QDir::TypeMask) == 0
&& ((isHidden && includeHidden)
|| (includeSystem && isSystem));
// Skip files and directories
if ((filters & QDir::AllDirs) == 0 && skipDirs && fi.isDir()) {
if (!alwaysShow)
return false;
}
if ((skipFiles && (fi.isFile() || !fi.exists()))
|| (skipSymlinks && fi.isSymLink())) {
if (!alwaysShow)
return false;
}
if (filterPermissions
&& ((doReadable && !fi.isReadable())
|| (doWritable && !fi.isWritable())
|| (doExecutable && !fi.isExecutable()))) {
return false;
}
if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink())
|| (!fi.exists() && fi.isSymLink()))) {
return false;
}
return true;
}
#endif
/*!
Constructs a QFileSystemIterator that can iterate over \a dir's entrylist, using
\a dir's name filters and regular filters. You can pass options via \a
flags to decide how the directory should be iterated.
By default, \a flags is NoIteratorFlags, which provides the same behavior
as in QDir::entryList().
The sorting in \a dir is ignored.
\sa atEnd(), next(), IteratorFlags
*/
QFileSystemIterator::QFileSystemIterator(const QDir &dir, IteratorFlags flags)
: d(new QFileSystemIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags))
{
d->q = this;
}
/*!
Constructs a QFileSystemIterator that can iterate over \a path, with no name
filtering and \a filters for entry filtering. You can pass options via \a
flags to decide how the directory should be iterated.
By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags,
which provides the same behavior as in QDir::entryList().
\sa atEnd(), next(), IteratorFlags
*/
QFileSystemIterator::QFileSystemIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
: d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags))
{
d->q = this;
}
/*!
Constructs a QFileSystemIterator that can iterate over \a path. You can pass
options via \a flags to decide how the directory should be iterated.
By default, \a flags is NoIteratorFlags, which provides the same behavior
as in QDir::entryList().
\sa atEnd(), next(), IteratorFlags
*/
QFileSystemIterator::QFileSystemIterator(const QString &path, IteratorFlags flags)
: d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags))
{
d->q = this;
}
/*!
Constructs a QFileSystemIterator that can iterate over \a path, using \a
nameFilters and \a filters. You can pass options via \a flags to decide
how the directory should be iterated.
By default, \a flags is NoIteratorFlags, which provides the same behavior
as QDir::entryList().
\sa atEnd(), next(), IteratorFlags
*/
QFileSystemIterator::QFileSystemIterator(const QString &path, const QStringList &nameFilters,
QDir::Filters filters, IteratorFlags flags)
: d(new QFileSystemIteratorPrivate(path, nameFilters, filters, flags))
{
d->q = this;
}
/*!
Destroys the QFileSystemIterator.
*/
QFileSystemIterator::~QFileSystemIterator()
{
delete d;
}
/*!
Advances the iterator to the next entry, and returns the file path of this
new entry. If atEnd() returns true, this function does nothing, and
returns a null QString.
You can call fileName() or filePath() to get the current entry file name
or path, or fileInfo() to get a QFileInfo for the current entry.
\sa hasNext(), fileName(), filePath(), fileInfo()
*/
void QFileSystemIterator::next()
{
d->advance();
}
/*!
Returns true if there is at least one more entry in the directory;
otherwise, false is returned.
\sa next(), fileName(), filePath(), fileInfo()
*/
bool QFileSystemIterator::atEnd() const
{
return d->atEnd();
}
/*!
Returns the file name for the current directory entry, without the path
prepended. If the current entry is invalid (i.e., isValid() returns
false), a null QString is returned.
This function is provided for the convenience when iterating single
directories. For recursive iteration, you should call filePath() or
fileInfo() instead.
\sa filePath(), fileInfo()
*/
QString QFileSystemIterator::fileName() const
{
if (d->atEnd() || !d->m_entry)
return QString();
if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDir)
return QString();
if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
return QLatin1String("@");
if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
return QLatin1String("@@");
#ifdef Q_OS_WIN
return QString::fromWCharArray(d->m_entry->cFileName);
#else
return QString::fromLocal8Bit(d->m_entry->d_name);
#endif
}
/*!
Returns the full file path for the current directory entry. If the current
entry is invalid (i.e., isValid() returns false), a null QString is
returned.
\sa fileInfo(), fileName()
*/
QString QFileSystemIterator::filePath() const
{
if (d->atEnd())
return QString();
QByteArray ba = d->m_dirPaths.top();
if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir)
ba += "/.";
else if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir)
ba += "/..";
else if (d->m_entry) {
ba += '/';
#ifdef Q_OS_WIN
ba += QString::fromWCharArray(d->m_entry->cFileName);
#else
ba += d->m_entry->d_name;
#endif
}
return QString::fromLocal8Bit(ba);
}
/*!
Returns a QFileInfo for the current directory entry. If the current entry
is invalid (i.e., isValid() returns false), a null QFileInfo is returned.
\sa filePath(), fileName()
*/
QFileInfo QFileSystemIterator::fileInfo() const
{
return QFileInfo(filePath());
}
/*!
Returns the base directory of the iterator.
*/
QString QFileSystemIterator::path() const
{
return QString::fromLocal8Bit(d->m_dirPaths.top());
}
QT_END_NAMESPACE

View file

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILESYSTEMITERATOR_H
#define QFILESYSTEMITERATOR_H
#include <QtCore/qdir.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QFileSystemIteratorPrivate;
class //Q_CORE_EXPORT
QFileSystemIterator
{
public:
enum IteratorFlag {
NoIteratorFlags = 0x0,
FollowSymlinks = 0x1,
Subdirectories = 0x2
};
Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag)
QFileSystemIterator(const QDir &dir, IteratorFlags flags = NoIteratorFlags);
QFileSystemIterator(const QString &path,
IteratorFlags flags = NoIteratorFlags);
QFileSystemIterator(const QString &path,
QDir::Filters filter,
IteratorFlags flags = NoIteratorFlags);
QFileSystemIterator(const QString &path,
const QStringList &nameFilters,
QDir::Filters filters = QDir::NoFilter,
IteratorFlags flags = NoIteratorFlags);
virtual ~QFileSystemIterator();
void next();
bool atEnd() const;
QString fileName() const;
QString filePath() const;
QFileInfo fileInfo() const;
QString path() const;
private:
Q_DISABLE_COPY(QFileSystemIterator)
QFileSystemIteratorPrivate *d;
friend class QDir;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemIterator::IteratorFlags)
QT_END_NAMESPACE
QT_END_HEADER
#endif

View file

@ -0,0 +1,9 @@
katie_test(tst_bench_qfile
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
if(KATIE_PLATFORM STREQUAL "wince")
set_target_properties(tst_bench_qfile PROPERTIES PRIVATE
COMPILE_DEFINITIONS -D_CRT_SECURE_NO_WARNINGS
)
endif()

View file

@ -0,0 +1,787 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QTemporaryFile>
#include <QFSFileEngine>
#include <QString>
#include <QDirIterator>
#include <qtest.h>
#include <stdio.h>
#ifdef Q_OS_WIN
# include <windows.h>
#endif
#define BUFSIZE 1024*512
#define FACTOR 1024*512
#define TF_SIZE FACTOR*81
// 10 predefined (but random() seek positions
// hardcoded to be comparable over several runs
const int seekpos[] = {int(TF_SIZE*0.52),
int(TF_SIZE*0.23),
int(TF_SIZE*0.73),
int(TF_SIZE*0.77),
int(TF_SIZE*0.80),
int(TF_SIZE*0.12),
int(TF_SIZE*0.53),
int(TF_SIZE*0.21),
int(TF_SIZE*0.27),
int(TF_SIZE*0.78)};
const int sp_size = sizeof(seekpos)/sizeof(int);
class tst_qfile: public QObject
{
Q_ENUMS(BenchmarkType)
Q_OBJECT
public:
enum BenchmarkType {
QFileBenchmark = 1,
QFSFileEngineBenchmark,
Win32Benchmark,
PosixBenchmark,
QFileFromPosixBenchmark
};
private slots:
void initTestCase();
void cleanupTestCase();
void open_data();
void open();
void seek_data();
void seek();
void readSmallFiles_QFile();
void readSmallFiles_QFSFileEngine();
void readSmallFiles_posix();
void readSmallFiles_Win32();
void readSmallFiles_QFile_data();
void readSmallFiles_QFSFileEngine_data();
void readSmallFiles_posix_data();
void readSmallFiles_Win32_data();
void readBigFile_QFile_data();
void readBigFile_QFSFileEngine_data();
void readBigFile_posix_data();
void readBigFile_Win32_data();
void readBigFile_QFile();
void readBigFile_QFSFileEngine();
void readBigFile_posix();
void readBigFile_Win32();
void writeFileSequential_data();
void writeFileSequential();
void writeFileBackwards_data();
void writeFileBackwards();
void writeFileSequentialWithSeeks_data();
void writeFileSequentialWithSeeks();
private:
void readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b);
void readBigFile();
void readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b);
void readSmallFiles();
void createFile();
void fillFile(int factor=FACTOR);
void removeFile();
void createSmallFiles();
void removeSmallFiles();
QString filename;
QString tmpDirName;
};
Q_DECLARE_METATYPE(tst_qfile::BenchmarkType)
Q_DECLARE_METATYPE(QIODevice::OpenMode)
Q_DECLARE_METATYPE(QIODevice::OpenModeFlag)
void tst_qfile::createFile()
{
removeFile(); // Cleanup in case previous test case aborted before cleaning up
QTemporaryFile tmpFile;
tmpFile.setAutoRemove(false);
if (!tmpFile.open())
::exit(1);
filename = tmpFile.fileName();
tmpFile.close();
}
void tst_qfile::removeFile()
{
if (!filename.isEmpty())
QFile::remove(filename);
}
void tst_qfile::fillFile(int factor)
{
QFile tmpFile(filename);
tmpFile.open(QIODevice::WriteOnly);
//for (int row=0; row<factor; ++row) {
// tmpFile.write(QByteArray().fill('0'+row%('0'-'z'), 80));
// tmpFile.write("\n");
//}
tmpFile.seek(factor*80);
tmpFile.putChar('\n');
tmpFile.close();
// let IO settle
QTest::qSleep(2000);
}
void tst_qfile::initTestCase()
{
}
void tst_qfile::cleanupTestCase()
{
}
void tst_qfile::readBigFile_QFile() { readBigFile(); }
void tst_qfile::readBigFile_QFSFileEngine() { readBigFile(); }
void tst_qfile::readBigFile_posix()
{
readBigFile();
}
void tst_qfile::readBigFile_Win32() { readBigFile(); }
void tst_qfile::readBigFile_QFile_data()
{
readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered);
readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen);
readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered);
}
void tst_qfile::readBigFile_QFSFileEngine_data()
{
readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered);
readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen);
readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered);
}
void tst_qfile::readBigFile_posix_data()
{
readBigFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
}
void tst_qfile::readBigFile_Win32_data()
{
readBigFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen);
}
void tst_qfile::readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b)
{
QTest::addColumn<tst_qfile::BenchmarkType>("testType");
QTest::addColumn<int>("blockSize");
QTest::addColumn<QFile::OpenModeFlag>("textMode");
QTest::addColumn<QFile::OpenModeFlag>("bufferedMode");
const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512};
int bs_entries = sizeof(bs)/sizeof(const int);
QString flagstring;
if (t & QIODevice::Text) flagstring += "textMode ";
if (b & QIODevice::Unbuffered) flagstring += "unbuffered ";
if (flagstring.isEmpty()) flagstring = "none";
for (int i=0; i<bs_entries; ++i)
QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b;
}
void tst_qfile::readBigFile()
{
QFETCH(tst_qfile::BenchmarkType, testType);
QFETCH(int, blockSize);
QFETCH(QFile::OpenModeFlag, textMode);
QFETCH(QFile::OpenModeFlag, bufferedMode);
#ifndef Q_OS_WIN
if (testType == Win32Benchmark)
QSKIP("This is Windows only benchmark.", SkipSingle);
#endif
char *buffer = new char[BUFSIZE];
createFile();
fillFile();
switch (testType) {
case(QFileBenchmark): {
QFile file(filename);
file.open(QIODevice::ReadOnly|textMode|bufferedMode);
QBENCHMARK {
while(!file.atEnd())
file.read(blockSize);
file.reset();
}
file.close();
}
break;
case(QFSFileEngineBenchmark): {
QFSFileEngine fse(filename);
fse.open(QIODevice::ReadOnly|textMode|bufferedMode);
QBENCHMARK {
//qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension);
while(fse.read(buffer, blockSize));
fse.seek(0);
}
fse.close();
}
break;
case(PosixBenchmark): {
QByteArray data = filename.toLocal8Bit();
const char* cfilename = data.constData();
FILE* cfile = ::fopen(cfilename, "rb");
QBENCHMARK {
while(!feof(cfile))
::fread(buffer, blockSize, 1, cfile);
::fseek(cfile, 0, SEEK_SET);
}
::fclose(cfile);
}
break;
case(QFileFromPosixBenchmark): {
// No gain in benchmarking this case
}
break;
case(Win32Benchmark): {
#ifdef Q_OS_WIN
HANDLE hndl;
// ensure we don't account string conversion
wchar_t* cfilename = (wchar_t*)filename.utf16();
hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
Q_ASSERT(hndl);
wchar_t* nativeBuffer = new wchar_t[BUFSIZE];
DWORD numberOfBytesRead;
QBENCHMARK {
do {
ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL);
} while(numberOfBytesRead != 0);
SetFilePointer(hndl, 0, NULL, FILE_BEGIN);
}
delete[] nativeBuffer;
CloseHandle(hndl);
#else
QFAIL("Not running on a non-Windows platform!");
#endif
}
break;
}
removeFile();
delete[] buffer;
}
void tst_qfile::seek_data()
{
QTest::addColumn<tst_qfile::BenchmarkType>("testType");
QTest::newRow("QFile") << QFileBenchmark;
QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark;
QTest::newRow("Posix FILE*") << PosixBenchmark;
#ifdef Q_OS_WIN
QTest::newRow("Win32 API") << Win32Benchmark;
#endif
}
void tst_qfile::seek()
{
QFETCH(tst_qfile::BenchmarkType, testType);
int i = 0;
createFile();
fillFile();
switch (testType) {
case(QFileBenchmark): {
QFile file(filename);
file.open(QIODevice::ReadOnly);
QBENCHMARK {
i=(i+1)%sp_size;
file.seek(seekpos[i]);
}
file.close();
}
break;
case(QFSFileEngineBenchmark): {
QFSFileEngine fse(filename);
fse.open(QIODevice::ReadOnly);
QBENCHMARK {
i=(i+1)%sp_size;
fse.seek(seekpos[i]);
}
fse.close();
}
break;
case(PosixBenchmark): {
QByteArray data = filename.toLocal8Bit();
const char* cfilename = data.constData();
FILE* cfile = ::fopen(cfilename, "rb");
QBENCHMARK {
i=(i+1)%sp_size;
::fseek(cfile, seekpos[i], SEEK_SET);
}
::fclose(cfile);
}
break;
case(QFileFromPosixBenchmark): {
// No gain in benchmarking this case
}
break;
case(Win32Benchmark): {
#ifdef Q_OS_WIN
HANDLE hndl;
// ensure we don't account string conversion
wchar_t* cfilename = (wchar_t*)filename.utf16();
hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
Q_ASSERT(hndl);
QBENCHMARK {
i=(i+1)%sp_size;
SetFilePointer(hndl, seekpos[i], NULL, 0);
}
CloseHandle(hndl);
#else
QFAIL("Not running on a Windows plattform!");
#endif
}
break;
}
removeFile();
}
void tst_qfile::open_data()
{
QTest::addColumn<tst_qfile::BenchmarkType>("testType");
QTest::newRow("QFile") << QFileBenchmark;
QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark;
QTest::newRow("Posix FILE*") << PosixBenchmark;
QTest::newRow("QFile from FILE*") << QFileFromPosixBenchmark;
#ifdef Q_OS_WIN
QTest::newRow("Win32 API") << Win32Benchmark;
#endif
}
void tst_qfile::open()
{
QFETCH(tst_qfile::BenchmarkType, testType);
createFile();
switch (testType) {
case(QFileBenchmark): {
QBENCHMARK {
QFile file( filename );
file.open( QIODevice::ReadOnly );
file.close();
}
}
break;
case(QFSFileEngineBenchmark): {
QBENCHMARK {
QFSFileEngine fse(filename);
fse.open(QIODevice::ReadOnly);
fse.close();
}
}
break;
case(PosixBenchmark): {
// ensure we don't account toLocal8Bit()
QByteArray data = filename.toLocal8Bit();
const char* cfilename = data.constData();
QBENCHMARK {
FILE* cfile = ::fopen(cfilename, "rb");
::fclose(cfile);
}
}
break;
case(QFileFromPosixBenchmark): {
// ensure we don't account toLocal8Bit()
QByteArray data = filename.toLocal8Bit();
const char* cfilename = data.constData();
FILE* cfile = ::fopen(cfilename, "rb");
QBENCHMARK {
QFile file;
file.open(cfile, QIODevice::ReadOnly);
file.close();
}
::fclose(cfile);
}
break;
case(Win32Benchmark): {
#ifdef Q_OS_WIN
HANDLE hndl;
// ensure we don't account string conversion
wchar_t* cfilename = (wchar_t*)filename.utf16();
QBENCHMARK {
hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
Q_ASSERT(hndl);
CloseHandle(hndl);
}
#else
QFAIL("Not running on a non-Windows platform!");
#endif
}
break;
}
removeFile();
}
void tst_qfile::readSmallFiles_QFile() { readSmallFiles(); }
void tst_qfile::readSmallFiles_QFSFileEngine() { readSmallFiles(); }
void tst_qfile::readSmallFiles_posix()
{
readSmallFiles();
}
void tst_qfile::readSmallFiles_Win32()
{
readSmallFiles();
}
void tst_qfile::readSmallFiles_QFile_data()
{
readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered);
readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen);
readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered);
}
void tst_qfile::readSmallFiles_QFSFileEngine_data()
{
readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered);
readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen);
readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered);
}
void tst_qfile::readSmallFiles_posix_data()
{
readSmallFiles_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen);
}
void tst_qfile::readSmallFiles_Win32_data()
{
readSmallFiles_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen);
}
void tst_qfile::readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b)
{
QTest::addColumn<tst_qfile::BenchmarkType>("testType");
QTest::addColumn<int>("blockSize");
QTest::addColumn<QFile::OpenModeFlag>("textMode");
QTest::addColumn<QFile::OpenModeFlag>("bufferedMode");
const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512};
int bs_entries = sizeof(bs)/sizeof(const int);
QString flagstring;
if (t & QIODevice::Text) flagstring += "textMode ";
if (b & QIODevice::Unbuffered) flagstring += "unbuffered ";
if (flagstring.isEmpty()) flagstring = "none";
for (int i=0; i<bs_entries; ++i)
QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b;
}
void tst_qfile::createSmallFiles()
{
QDir dir = QDir::temp();
dir.mkdir("tst");
dir.cd("tst");
tmpDirName = dir.absolutePath();
#if defined(Q_OS_SYMBIAN) || defined(Q_WS_WINCE)
for (int i = 0; i < 100; ++i)
#else
for (int i = 0; i < 1000; ++i)
#endif
{
QFile f(tmpDirName+"/"+QString::number(i));
f.open(QIODevice::WriteOnly);
f.seek(511);
f.putChar('\n');
f.close();
}
}
void tst_qfile::removeSmallFiles()
{
QDirIterator it(tmpDirName, QDirIterator::FollowSymlinks);
while (it.hasNext())
QFile::remove(it.next());
QDir::temp().rmdir("tst");
}
void tst_qfile::readSmallFiles()
{
QFETCH(tst_qfile::BenchmarkType, testType);
QFETCH(int, blockSize);
QFETCH(QFile::OpenModeFlag, textMode);
QFETCH(QFile::OpenModeFlag, bufferedMode);
#ifndef Q_OS_WIN
if (testType == Win32Benchmark)
QSKIP("This is Windows only benchmark.", SkipSingle);
#endif
createSmallFiles();
QDir dir(tmpDirName);
const QStringList files = dir.entryList(QDir::NoDotAndDotDot|QDir::NoSymLinks|QDir::Files);
char *buffer = new char[BUFSIZE];
switch (testType) {
case(QFileBenchmark): {
QList<QFile*> fileList;
Q_FOREACH(QString file, files) {
QFile *f = new QFile(tmpDirName+ "/" + file);
f->open(QIODevice::ReadOnly|textMode|bufferedMode);
fileList.append(f);
}
QBENCHMARK {
Q_FOREACH(QFile *file, fileList) {
while (!file->atEnd()) {
file->read(buffer, blockSize);
}
}
}
Q_FOREACH(QFile *file, fileList) {
file->close();
delete file;
}
}
break;
case(QFSFileEngineBenchmark): {
QList<QFSFileEngine*> fileList;
Q_FOREACH(QString file, files) {
QFSFileEngine *fse = new QFSFileEngine(tmpDirName+ "/" + file);
fse->open(QIODevice::ReadOnly|textMode|bufferedMode);
fileList.append(fse);
}
QBENCHMARK {
Q_FOREACH(QFSFileEngine *fse, fileList) {
while (fse->read(buffer, blockSize));
}
}
Q_FOREACH(QFSFileEngine *fse, fileList) {
fse->close();
delete fse;
}
}
break;
case(PosixBenchmark): {
QList<FILE*> fileList;
Q_FOREACH(QString file, files) {
fileList.append(::fopen(QFile::encodeName(tmpDirName+ "/" + file).constData(), "rb"));
}
QBENCHMARK {
Q_FOREACH(FILE* cfile, fileList) {
while(!feof(cfile))
::fread(buffer, blockSize, 1, cfile);
::fseek(cfile, 0, SEEK_SET);
}
}
Q_FOREACH(FILE* cfile, fileList) {
::fclose(cfile);
}
}
break;
case(QFileFromPosixBenchmark): {
// No gain in benchmarking this case
}
break;
case(Win32Benchmark): {
#ifdef Q_OS_WIN
HANDLE hndl;
// ensure we don't account string conversion
wchar_t* cfilename = (wchar_t*)filename.utf16();
hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
Q_ASSERT(hndl);
wchar_t* nativeBuffer = new wchar_t[BUFSIZE];
DWORD numberOfBytesRead;
QBENCHMARK {
do {
ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL);
} while(numberOfBytesRead != 0);
}
delete nativeBuffer;
CloseHandle(hndl);
#else
QFAIL("Not running on a non-Windows platform!");
#endif
}
break;
}
removeSmallFiles();
delete[] buffer;
}
void tst_qfile::writeFileSequential_data()
{
QTest::addColumn<int>("blockSize");
QTest::addColumn<QString>("path");
QTest::newRow("internal 16b") << 16 << QDir::tempPath();
QTest::newRow("internal 512b") << 512 << QDir::tempPath();
QTest::newRow("internal 4k") << 4096 << QDir::tempPath();
QTest::newRow("internal 16k") << 16384 << QDir::tempPath();
QTest::newRow("internal 64k") << 65536 << QDir::tempPath();
//slow media (e.g. SD card)
QString externalPath;
#ifdef Q_OS_SYMBIAN
externalPath = "E:/";
#endif
if (!externalPath.isEmpty()) {
QTest::newRow("external 16b") << 16 << externalPath;
QTest::newRow("external 512b") << 512 << externalPath;
QTest::newRow("external 4k") << 4096 << externalPath;
QTest::newRow("external 16k") << 16384 << externalPath;
QTest::newRow("external 64k") << 65536 << externalPath;
}
}
void tst_qfile::writeFileSequential()
{
const qint64 limit = 1024 * 1024;
QFETCH(int, blockSize);
QFETCH(QString, path);
QTemporaryFile f;
f.setFileTemplate(path);
QByteArray block;
block.fill('@', blockSize);
QBENCHMARK {
QVERIFY(f.open());
for (qint64 pos = 0; pos < limit; pos += blockSize) {
QVERIFY(f.write(block));
}
QVERIFY(f.flush());
QCOMPARE(f.size(), limit);
f.close();
}
}
void tst_qfile::writeFileBackwards_data()
{
writeFileSequential_data();
}
void tst_qfile::writeFileBackwards()
{
const qint64 limit = 1024 * 1024;
QFETCH(int, blockSize);
QFETCH(QString, path);
QTemporaryFile f;
f.setFileTemplate(path);
QByteArray block;
block.fill('@', blockSize);
QBENCHMARK {
QVERIFY(f.open());
for (qint64 pos = limit - blockSize; pos >= 0; pos -= blockSize) {
QVERIFY(f.seek(pos));
QVERIFY(f.write(block));
}
QVERIFY(f.flush());
QCOMPARE(f.size(), limit);
f.close();
}
}
void tst_qfile::writeFileSequentialWithSeeks_data()
{
writeFileSequential_data();
}
void tst_qfile::writeFileSequentialWithSeeks()
{
const qint64 limit = 1024 * 1024;
QFETCH(int, blockSize);
QFETCH(QString, path);
QTemporaryFile f;
f.setFileTemplate(path);
QByteArray block;
block.fill('@', blockSize);
QBENCHMARK {
QVERIFY(f.open());
for (qint64 pos = 0; pos < limit; pos += blockSize) {
QVERIFY(f.seek(pos));
QVERIFY(f.write(block));
}
QVERIFY(f.flush());
QCOMPARE(f.size(), limit);
f.close();
}
}
QTEST_MAIN(tst_qfile)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qfileinfo
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,125 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <qtest.h>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QFile>
#include "qfsfileengine_p.h"
#include "../../../../shared/filesystem.h"
class qfileinfo : public QObject
{
Q_OBJECT
private slots:
void canonicalFileNamePerformance();
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
void symLinkTargetPerformanceLNK();
void symLinkTargetPerformanceMounpoint();
#endif
void initTestCase();
void cleanupTestCase();
public:
qfileinfo() : QObject() {};
};
void qfileinfo::initTestCase()
{
}
void qfileinfo::cleanupTestCase()
{
}
void qfileinfo::canonicalFileNamePerformance()
{
QString appPath = QCoreApplication::applicationFilePath();
QFSFileEnginePrivate::canonicalized(appPath); // warmup
QFSFileEnginePrivate::canonicalized(appPath); // more warmup
QBENCHMARK {
for (int i = 0; i < 5000; i++) {
QFSFileEnginePrivate::canonicalized(appPath);
}
}
}
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
void qfileinfo::symLinkTargetPerformanceLNK()
{
QVERIFY(QFile::link("file","link.lnk"));
QFileInfo info("link.lnk");
info.setCaching(false);
QVERIFY(info.isSymLink());
QString linkTarget;
QBENCHMARK {
for(int i=0; i<100; i++)
linkTarget = info.readLink();
}
QVERIFY(QFile::remove("link.lnk"));
}
void qfileinfo::symLinkTargetPerformanceMounpoint()
{
wchar_t buffer[MAX_PATH];
QString rootPath = QDir::toNativeSeparators(QDir::rootPath());
QVERIFY(GetVolumeNameForVolumeMountPointW(rootPath.utf16(), buffer, MAX_PATH));
QString rootVolume = QString::fromWCharArray(buffer);
QString mountpoint = "mountpoint";
rootVolume.replace("\\\\?\\","\\??\\");
FileSystem::createNtfsJunction(rootVolume, mountpoint);
QFileInfo info(mountpoint);
info.setCaching(false);
QVERIFY(info.isSymLink());
QString linkTarget;
QBENCHMARK {
for(int i=0; i<100; i++)
linkTarget = info.readLink();
}
QVERIFY(QDir().rmdir(mountpoint));
}
#endif
QTEST_MAIN(qfileinfo)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qiodevice
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,107 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QIODevice>
#include <QFile>
#include <QString>
#include <qtest.h>
class tst_qiodevice : public QObject
{
Q_OBJECT
private slots:
void read_old();
void read_old_data() { read_data(); }
//void read_new();
//void read_new_data() { read_data(); }
private:
void read_data();
};
void tst_qiodevice::read_data()
{
QTest::addColumn<qint64>("size");
QTest::newRow("10k") << qint64(10 * 1024);
QTest::newRow("100k") << qint64(100 * 1024);
QTest::newRow("1000k") << qint64(1000 * 1024);
QTest::newRow("10000k") << qint64(10000 * 1024);
#ifndef Q_OS_SYMBIAN // Symbian devices don't (yet) have enough available RAM to run these
QTest::newRow("100000k") << qint64(100000 * 1024);
QTest::newRow("1000000k") << qint64(1000000 * 1024);
#endif
}
void tst_qiodevice::read_old()
{
QFETCH(qint64, size);
QString name = "tmp" + QString::number(size);
{
QFile file(name);
file.open(QIODevice::WriteOnly);
file.seek(size);
file.write("x", 1);
file.close();
}
QBENCHMARK {
QFile file(name);
file.open(QIODevice::ReadOnly);
QByteArray ba;
qint64 s = size - 1024;
file.seek(512);
ba = file.read(s); // crash happens during this read / assignment operation
}
{
QFile file(name);
file.remove();
}
}
QTEST_MAIN(tst_qiodevice)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qtemporaryfile
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QIODevice>
#include <QFile>
#include <QString>
#include <QTemporaryFile>
#include <qtest.h>
class tst_qtemporaryfile : public QObject
{
Q_OBJECT
private slots:
void openclose_data();
void openclose();
void readwrite_data() { openclose_data(); }
void readwrite();
private:
};
void tst_qtemporaryfile::openclose_data()
{
QTest::addColumn<qint64>("amount");
QTest::newRow("100") << qint64(100);
QTest::newRow("1000") << qint64(1000);
QTest::newRow("10000") << qint64(10000);
}
void tst_qtemporaryfile::openclose()
{
QFETCH(qint64, amount);
QBENCHMARK {
for (qint64 i = 0; i < amount; ++i) {
QTemporaryFile file;
file.open();
file.close();
}
}
}
void tst_qtemporaryfile::readwrite()
{
QFETCH(qint64, amount);
const int dataSize = 4096;
QByteArray data;
data.fill('a', dataSize);
QBENCHMARK {
for (qint64 i = 0; i < amount; ++i) {
QTemporaryFile file;
file.open();
file.write(data);
file.seek(0);
file.read(dataSize);
file.close();
}
}
}
QTEST_MAIN(tst_qtemporaryfile)
#include "moc_main.cpp"

View file

@ -0,0 +1,9 @@
katie_test(tst_qurl
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
if(KATIE_PLATFORM STREQUAL "wince")
set_target_properties(tst_bench_qfile PROPERTIES PRIVATE
COMPILE_DEFINITIONS -D_CRT_SECURE_NO_WARNINGS
)
endif()

View file

@ -0,0 +1,244 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qurl.h>
#include <qtest.h>
class tst_qurl: public QObject
{
Q_OBJECT
private slots:
void emptyUrl();
void relativeUrl();
void absoluteUrl();
void isRelative_data();
void isRelative();
void toLocalFile_data();
void toLocalFile();
void toString_data();
void toString();
void toEncoded_data();
void toEncoded();
void resolved_data();
void resolved();
void equality_data();
void equality();
void qmlPropertyWriteUseCase();
private:
void generateFirstRunData();
};
void tst_qurl::emptyUrl()
{
QBENCHMARK {
QUrl url;
}
}
void tst_qurl::relativeUrl()
{
QBENCHMARK {
QUrl url("pics/avatar.png");
}
}
void tst_qurl::absoluteUrl()
{
QBENCHMARK {
QUrl url("/tmp/avatar.png");
}
}
void tst_qurl::generateFirstRunData()
{
QTest::addColumn<bool>("firstRun");
QTest::newRow("construction + first run") << true;
QTest::newRow("subsequent runs") << false;
}
void tst_qurl::isRelative_data()
{
generateFirstRunData();
}
void tst_qurl::isRelative()
{
QFETCH(bool, firstRun);
if (firstRun) {
QBENCHMARK {
QUrl url("pics/avatar.png");
url.isRelative();
}
} else {
QUrl url("pics/avatar.png");
QBENCHMARK {
url.isRelative();
}
}
}
void tst_qurl::toLocalFile_data()
{
generateFirstRunData();
}
void tst_qurl::toLocalFile()
{
QFETCH(bool, firstRun);
if (firstRun) {
QBENCHMARK {
QUrl url("/tmp/avatar.png");
url.toLocalFile();
}
} else {
QUrl url("/tmp/avatar.png");
QBENCHMARK {
url.toLocalFile();
}
}
}
void tst_qurl::toString_data()
{
generateFirstRunData();
}
void tst_qurl::toString()
{
QFETCH(bool, firstRun);
if(firstRun) {
QBENCHMARK {
QUrl url("pics/avatar.png");
url.toString();
}
} else {
QUrl url("pics/avatar.png");
QBENCHMARK {
url.toString();
}
}
}
void tst_qurl::toEncoded_data()
{
generateFirstRunData();
}
void tst_qurl::toEncoded()
{
QFETCH(bool, firstRun);
if(firstRun) {
QBENCHMARK {
QUrl url("pics/avatar.png");
url.toEncoded(QUrl::FormattingOption(0x100));
}
} else {
QUrl url("pics/avatar.png");
QBENCHMARK {
url.toEncoded(QUrl::FormattingOption(0x100));
}
}
}
void tst_qurl::resolved_data()
{
generateFirstRunData();
}
void tst_qurl::resolved()
{
QFETCH(bool, firstRun);
if(firstRun) {
QBENCHMARK {
QUrl baseUrl("/home/user/");
QUrl url("pics/avatar.png");
baseUrl.resolved(url);
}
} else {
QUrl baseUrl("/home/user/");
QUrl url("pics/avatar.png");
QBENCHMARK {
baseUrl.resolved(url);
}
}
}
void tst_qurl::equality_data()
{
generateFirstRunData();
}
void tst_qurl::equality()
{
QFETCH(bool, firstRun);
if(firstRun) {
QBENCHMARK {
QUrl url("pics/avatar.png");
QUrl url2("pics/avatar2.png");
//url == url2;
}
} else {
QUrl url("pics/avatar.png");
QUrl url2("pics/avatar2.png");
QBENCHMARK {
url == url2;
}
}
}
void tst_qurl::qmlPropertyWriteUseCase()
{
QUrl base("file:///home/user/qt/demos/declarative/samegame/SamegameCore/");
QString str("pics/redStar.png");
QBENCHMARK {
QUrl u = QUrl(str);
if (!u.isEmpty() && u.isRelative())
u = base.resolved(u);
}
}
QTEST_MAIN(tst_qurl)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_events
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,187 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <qtest.h>
#include <qtesteventloop.h>
class PingPong : public QObject
{
public:
void setPeer(QObject *peer);
void resetCounter() {m_counter = 100;}
protected:
bool event(QEvent *e);
private:
QObject *m_peer;
int m_counter;
};
void PingPong::setPeer(QObject *peer)
{
m_peer = peer;
m_counter = 100;
}
bool PingPong::event(QEvent *)
{
--m_counter;
if (m_counter > 0) {
QEvent *e = new QEvent(QEvent::User);
QCoreApplication::postEvent(m_peer, e);
} else {
QTestEventLoop::instance().exitLoop();
}
return true;
}
class EventTester : public QObject
{
public:
int foo(int bar);
protected:
bool event(QEvent *e);
};
bool EventTester::event(QEvent *e)
{
if (e->type() == QEvent::User+1)
return foo(e->type()) != 0;
return false;
}
int EventTester::foo(int bar)
{
return bar + 1;
}
class EventsBench : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void cleanupTestCase();
void noEvent();
void sendEvent_data();
void sendEvent();
void postEvent_data();
void postEvent();
};
void EventsBench::initTestCase()
{
}
void EventsBench::cleanupTestCase()
{
}
void EventsBench::noEvent()
{
EventTester tst;
int val = 0;
QBENCHMARK {
val += tst.foo(1);
}
}
void EventsBench::sendEvent_data()
{
QTest::addColumn<bool>("filterEvents");
QTest::newRow("no eventfilter") << false;
QTest::newRow("eventfilter") << true;
}
void EventsBench::sendEvent()
{
QFETCH(bool, filterEvents);
EventTester tst;
if (filterEvents)
tst.installEventFilter(this);
QEvent evt(QEvent::Type(QEvent::User+1));
QBENCHMARK {
QCoreApplication::sendEvent(&tst, &evt);
}
}
void EventsBench::postEvent_data()
{
QTest::addColumn<bool>("filterEvents");
// The first time an eventloop is executed, the case runs radically slower at least
// on some platforms, so test the "no eventfilter" case to get a comparable results
// with the "eventfilter" case.
QTest::newRow("first time, no eventfilter") << false;
QTest::newRow("no eventfilter") << false;
QTest::newRow("eventfilter") << true;
}
void EventsBench::postEvent()
{
QFETCH(bool, filterEvents);
PingPong ping;
PingPong pong;
ping.setPeer(&pong);
pong.setPeer(&ping);
if (filterEvents) {
ping.installEventFilter(this);
pong.installEventFilter(this);
}
QBENCHMARK {
// In case multiple iterations are done, event needs to be created inside the QBENCHMARK,
// or it gets deleted once first iteration exits and can cause a crash. Similarly,
// ping and pong need their counters reset.
QEvent *e = new QEvent(QEvent::User);
ping.resetCounter();
pong.resetCounter();
QCoreApplication::postEvent(&ping, e);
QTestEventLoop::instance().enterLoop( 61 );
}
}
QTEST_MAIN(EventsBench)
#include "moc_main.cpp"

View file

@ -0,0 +1,5 @@
katie_test(tst_bench_qmetaobject
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
target_link_libraries(tst_bench_qmetaobject KtGui)

View file

@ -0,0 +1,264 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtGui>
#include <qtest.h>
class LotsOfSignals : public QObject
{
Q_OBJECT
public:
LotsOfSignals() {}
signals:
void extraSignal1();
void extraSignal2();
void extraSignal3();
void extraSignal4();
void extraSignal5();
void extraSignal6();
void extraSignal7();
void extraSignal8();
void extraSignal9();
void extraSignal10();
void extraSignal12();
void extraSignal13();
void extraSignal14();
void extraSignal15();
void extraSignal16();
void extraSignal17();
void extraSignal18();
void extraSignal19();
void extraSignal20();
void extraSignal21();
void extraSignal22();
void extraSignal23();
void extraSignal24();
void extraSignal25();
void extraSignal26();
void extraSignal27();
void extraSignal28();
void extraSignal29();
void extraSignal30();
void extraSignal31();
void extraSignal32();
void extraSignal33();
void extraSignal34();
void extraSignal35();
void extraSignal36();
void extraSignal37();
void extraSignal38();
void extraSignal39();
void extraSignal40();
void extraSignal41();
void extraSignal42();
void extraSignal43();
void extraSignal44();
void extraSignal45();
void extraSignal46();
void extraSignal47();
void extraSignal48();
void extraSignal49();
void extraSignal50();
void extraSignal51();
void extraSignal52();
void extraSignal53();
void extraSignal54();
void extraSignal55();
void extraSignal56();
void extraSignal57();
void extraSignal58();
void extraSignal59();
void extraSignal60();
void extraSignal61();
void extraSignal62();
void extraSignal63();
void extraSignal64();
void extraSignal65();
void extraSignal66();
void extraSignal67();
void extraSignal68();
void extraSignal69();
void extraSignal70();
};
class tst_qmetaobject: public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void cleanupTestCase();
void indexOfProperty_data();
void indexOfProperty();
void indexOfMethod_data();
void indexOfMethod();
void indexOfSignal_data();
void indexOfSignal();
void indexOfSlot_data();
void indexOfSlot();
void unconnected_data();
void unconnected();
};
void tst_qmetaobject::initTestCase()
{
}
void tst_qmetaobject::cleanupTestCase()
{
}
void tst_qmetaobject::indexOfProperty_data()
{
QTest::addColumn<QByteArray>("name");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->propertyCount(); ++i) {
QMetaProperty prop = mo->property(i);
QTest::newRow(prop.name()) << QByteArray(prop.name());
}
}
void tst_qmetaobject::indexOfProperty()
{
QFETCH(QByteArray, name);
const char *p = name.constData();
const QMetaObject *mo = &QTreeView::staticMetaObject;
QBENCHMARK {
(void)mo->indexOfProperty(p);
}
}
void tst_qmetaobject::indexOfMethod_data()
{
QTest::addColumn<QByteArray>("method");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->methodCount(); ++i) {
QMetaMethod method = mo->method(i);
QByteArray sig = method.signature();
QTest::newRow(sig) << sig;
}
}
void tst_qmetaobject::indexOfMethod()
{
QFETCH(QByteArray, method);
const char *p = method.constData();
const QMetaObject *mo = &QTreeView::staticMetaObject;
QBENCHMARK {
(void)mo->indexOfMethod(p);
}
}
void tst_qmetaobject::indexOfSignal_data()
{
QTest::addColumn<QByteArray>("signal");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->methodCount(); ++i) {
QMetaMethod method = mo->method(i);
if (method.methodType() != QMetaMethod::Signal)
continue;
QByteArray sig = method.signature();
QTest::newRow(sig) << sig;
}
}
void tst_qmetaobject::indexOfSignal()
{
QFETCH(QByteArray, signal);
const char *p = signal.constData();
const QMetaObject *mo = &QTreeView::staticMetaObject;
QBENCHMARK {
(void)mo->indexOfSignal(p);
}
}
void tst_qmetaobject::indexOfSlot_data()
{
QTest::addColumn<QByteArray>("slot");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->methodCount(); ++i) {
QMetaMethod method = mo->method(i);
if (method.methodType() != QMetaMethod::Slot)
continue;
QByteArray sig = method.signature();
QTest::newRow(sig) << sig;
}
}
void tst_qmetaobject::indexOfSlot()
{
QFETCH(QByteArray, slot);
const char *p = slot.constData();
const QMetaObject *mo = &QTreeView::staticMetaObject;
QBENCHMARK {
(void)mo->indexOfSlot(p);
}
}
void tst_qmetaobject::unconnected_data()
{
QTest::addColumn<int>("signal_index");
QTest::newRow("signal--9") << 9;
QTest::newRow("signal--32") << 32;
QTest::newRow("signal--33") << 33;
QTest::newRow("signal--64") << 64;
QTest::newRow("signal--65") << 65;
QTest::newRow("signal--70") << 70;
}
void tst_qmetaobject::unconnected()
{
LotsOfSignals *obj = new LotsOfSignals;
QFETCH(int, signal_index);
QVERIFY(obj->metaObject()->methodCount() == 73);
void *v;
QBENCHMARK {
//+1 because QObject has one slot
QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, signal_index+1, &v);
}
delete obj;
}
QTEST_MAIN(tst_qmetaobject)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_qmetatype
${CMAKE_CURRENT_SOURCE_DIR}/tst_qmetatype.cpp
)

View file

@ -0,0 +1,286 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtCore/qmetatype.h>
//TESTED_FILES=
class tst_QMetaType : public QObject
{
Q_OBJECT
public:
tst_QMetaType();
virtual ~tst_QMetaType();
private slots:
void typeBuiltin_data();
void typeBuiltin();
void typeBuiltinNotNormalized_data();
void typeBuiltinNotNormalized();
void typeCustom();
void typeCustomNotNormalized();
void typeNotRegistered();
void typeNotRegisteredNotNormalized();
void typeNameBuiltin_data();
void typeNameBuiltin();
void typeNameCustom();
void typeNameNotRegistered();
void isRegisteredBuiltin_data();
void isRegisteredBuiltin();
void isRegisteredCustom();
void isRegisteredNotRegistered();
void constructCoreType_data();
void constructCoreType();
void constructCoreTypeCopy_data();
void constructCoreTypeCopy();
};
tst_QMetaType::tst_QMetaType()
{
}
tst_QMetaType::~tst_QMetaType()
{
}
void tst_QMetaType::typeBuiltin_data()
{
QTest::addColumn<QByteArray>("typeName");
for (int i = 0; i < QMetaType::User; ++i) {
const char *name = QMetaType::typeName(i);
if (name)
QTest::newRow(name) << QByteArray(name);
}
}
void tst_QMetaType::typeBuiltin()
{
QFETCH(QByteArray, typeName);
const char *nm = typeName.constData();
QBENCHMARK {
for (int i = 0; i < 100000; ++i)
QMetaType::type(nm);
}
}
void tst_QMetaType::typeBuiltinNotNormalized_data()
{
QTest::addColumn<QByteArray>("typeName");
for (int i = 0; i < QMetaType::User; ++i) {
const char *name = QMetaType::typeName(i);
if (name)
QTest::newRow(name) << QByteArray(name).append(" ");
}
}
void tst_QMetaType::typeBuiltinNotNormalized()
{
QFETCH(QByteArray, typeName);
const char *nm = typeName.constData();
QBENCHMARK {
for (int i = 0; i < 10000; ++i)
QMetaType::type(nm);
}
}
struct Foo { int i; };
void tst_QMetaType::typeCustom()
{
qRegisterMetaType<Foo>("Foo");
QBENCHMARK {
for (int i = 0; i < 10000; ++i)
QMetaType::type("Foo");
}
}
void tst_QMetaType::typeCustomNotNormalized()
{
qRegisterMetaType<Foo>("Foo");
QBENCHMARK {
for (int i = 0; i < 10000; ++i)
QMetaType::type("Foo ");
}
}
void tst_QMetaType::typeNotRegistered()
{
Q_ASSERT(QMetaType::type("Bar") == 0);
QBENCHMARK {
for (int i = 0; i < 10000; ++i)
QMetaType::type("Bar");
}
}
void tst_QMetaType::typeNotRegisteredNotNormalized()
{
Q_ASSERT(QMetaType::type("Bar") == 0);
QBENCHMARK {
for (int i = 0; i < 10000; ++i)
QMetaType::type("Bar ");
}
}
void tst_QMetaType::typeNameBuiltin_data()
{
QTest::addColumn<int>("type");
for (int i = 0; i < QMetaType::User; ++i) {
const char *name = QMetaType::typeName(i);
if (name)
QTest::newRow(name) << i;
}
}
void tst_QMetaType::typeNameBuiltin()
{
QFETCH(int, type);
QBENCHMARK {
for (int i = 0; i < 500000; ++i)
QMetaType::typeName(type);
}
}
void tst_QMetaType::typeNameCustom()
{
int type = qRegisterMetaType<Foo>("Foo");
QBENCHMARK {
for (int i = 0; i < 100000; ++i)
QMetaType::typeName(type);
}
}
void tst_QMetaType::typeNameNotRegistered()
{
// We don't care much about this case, but test it anyway.
Q_ASSERT(QMetaType::typeName(-1) == 0);
QBENCHMARK {
for (int i = 0; i < 500000; ++i)
QMetaType::typeName(-1);
}
}
void tst_QMetaType::isRegisteredBuiltin_data()
{
typeNameBuiltin_data();
}
void tst_QMetaType::isRegisteredBuiltin()
{
QFETCH(int, type);
QBENCHMARK {
for (int i = 0; i < 500000; ++i)
QMetaType::isRegistered(type);
}
}
void tst_QMetaType::isRegisteredCustom()
{
int type = qRegisterMetaType<Foo>("Foo");
QBENCHMARK {
for (int i = 0; i < 100000; ++i)
QMetaType::isRegistered(type);
}
}
void tst_QMetaType::isRegisteredNotRegistered()
{
Q_ASSERT(QMetaType::typeName(-1) == 0);
QBENCHMARK {
for (int i = 0; i < 100000; ++i)
QMetaType::isRegistered(-1);
}
}
void tst_QMetaType::constructCoreType_data()
{
QTest::addColumn<int>("typeId");
for (int i = 0; i <= QMetaType::LastCoreType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
// GUI types are tested in tst_QGuiMetaType.
}
// Tests how fast QMetaType can default-construct and destroy a Qt
// core type. The purpose of this benchmark is to measure the overhead
// of using type id-based creation compared to creating the type
// directly (i.e. "T *t = new T(); delete t;").
void tst_QMetaType::constructCoreType()
{
QFETCH(int, typeId);
QBENCHMARK {
for (int i = 0; i < 100000; ++i) {
void *data = QMetaType::construct(typeId, (void *)0);
QMetaType::destroy(typeId, data);
}
}
}
void tst_QMetaType::constructCoreTypeCopy_data()
{
constructCoreType_data();
}
// Tests how fast QMetaType can copy-construct and destroy a Qt core
// type. The purpose of this benchmark is to measure the overhead of
// using type id-based creation compared to creating the type directly
// (i.e. "T *t = new T(other); delete t;").
void tst_QMetaType::constructCoreTypeCopy()
{
QFETCH(int, typeId);
QVariant other(typeId, (void *)0);
const void *copy = other.constData();
QBENCHMARK {
for (int i = 0; i < 100000; ++i) {
void *data = QMetaType::construct(typeId, copy);
QMetaType::destroy(typeId, data);
}
}
}
QTEST_MAIN(tst_QMetaType)
#include "moc_tst_qmetatype.cpp"

View file

@ -0,0 +1,7 @@
katie_test(tst_bench_qobject
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/object.cpp
${CMAKE_CURRENT_SOURCE_DIR}/object.h
)
target_link_libraries(tst_bench_qobject KtGui)

View file

@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtGui>
#include <qtest.h>
#include "object.h"
#include <qcoreapplication.h>
#include <qdatetime.h>
enum {
CreationDeletionBenckmarkConstant = 34567,
SignalsAndSlotsBenchmarkConstant = 456789
};
class QObjectBenchmark : public QObject
{
Q_OBJECT
private slots:
void signal_slot_benchmark();
void signal_slot_benchmark_data();
void qproperty_benchmark_data();
void qproperty_benchmark();
void dynamic_property_benchmark();
void connect_disconnect_benchmark_data();
void connect_disconnect_benchmark();
};
void QObjectBenchmark::signal_slot_benchmark_data()
{
QTest::addColumn<int>("type");
QTest::newRow("simple function") << 0;
QTest::newRow("single signal/slot") << 1;
QTest::newRow("multi signal/slot") << 2;
QTest::newRow("unconnected signal") << 3;
}
void QObjectBenchmark::signal_slot_benchmark()
{
QFETCH(int, type);
Object singleObject;
Object multiObject;
singleObject.setObjectName("single");
multiObject.setObjectName("multi");
singleObject.connect(&singleObject, SIGNAL(signal0()), SLOT(slot0()));
multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(slot0()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal1()));
multiObject.connect(&multiObject, SIGNAL(signal1()), SLOT(slot1()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal2()));
multiObject.connect(&multiObject, SIGNAL(signal2()), SLOT(slot2()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal3()));
multiObject.connect(&multiObject, SIGNAL(signal3()), SLOT(slot3()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal4()));
multiObject.connect(&multiObject, SIGNAL(signal4()), SLOT(slot4()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal5()));
multiObject.connect(&multiObject, SIGNAL(signal5()), SLOT(slot5()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal6()));
multiObject.connect(&multiObject, SIGNAL(signal6()), SLOT(slot6()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal7()));
multiObject.connect(&multiObject, SIGNAL(signal7()), SLOT(slot7()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal8()));
multiObject.connect(&multiObject, SIGNAL(signal8()), SLOT(slot8()));
// multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal9()));
multiObject.connect(&multiObject, SIGNAL(signal9()), SLOT(slot9()));
if (type == 0) {
QBENCHMARK {
singleObject.slot0();
}
} else if (type == 1) {
QBENCHMARK {
singleObject.emitSignal0();
}
} else if (type == 2) {
QBENCHMARK {
multiObject.emitSignal0();
}
} else if (type == 3) {
QBENCHMARK {
singleObject.emitSignal1();
}
}
}
void QObjectBenchmark::qproperty_benchmark_data()
{
QTest::addColumn<QByteArray>("name");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->propertyCount(); ++i) {
QMetaProperty prop = mo->property(i);
QTest::newRow(prop.name()) << QByteArray(prop.name());
}
}
void QObjectBenchmark::qproperty_benchmark()
{
QFETCH(QByteArray, name);
const char *p = name.constData();
QTreeView obj;
QVariant v = obj.property(p);
QBENCHMARK {
obj.setProperty(p, v);
(void)obj.property(p);
}
}
void QObjectBenchmark::dynamic_property_benchmark()
{
QTreeView obj;
QBENCHMARK {
obj.setProperty("myProperty", 123);
(void)obj.property("myProperty");
obj.setProperty("myOtherProperty", 123);
(void)obj.property("myOtherProperty");
}
}
void QObjectBenchmark::connect_disconnect_benchmark_data()
{
QTest::addColumn<QByteArray>("signal");
const QMetaObject *mo = &QTreeView::staticMetaObject;
for (int i = 0; i < mo->methodCount(); ++i) {
QMetaMethod method = mo->method(i);
if (method.methodType() != QMetaMethod::Signal)
continue;
QByteArray sig = method.signature();
QTest::newRow(sig) << sig;
}
}
void QObjectBenchmark::connect_disconnect_benchmark()
{
QFETCH(QByteArray, signal);
signal.prepend('2');
const char *p = signal.constData();
QTreeView obj;
QBENCHMARK {
QObject::connect(&obj, p, &obj, p);
QObject::disconnect(&obj, p, &obj, p);
}
}
QTEST_MAIN(QObjectBenchmark)
#include "moc_main.cpp"

View file

@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "object.h"
void Object::emitSignal0()
{ emit signal0(); }
void Object::emitSignal1()
{ emit signal1(); }
void Object::slot0()
{ }
void Object::slot1()
{ }
void Object::slot2()
{ }
void Object::slot3()
{ }
void Object::slot4()
{ }
void Object::slot5()
{ }
void Object::slot6()
{ }
void Object::slot7()
{ }
void Object::slot8()
{ }
void Object::slot9()
{ }
#include "moc_object.h"

View file

@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef OBJECT_H
#define OBJECT_H
#include <qobject.h>
class Object : public QObject
{
Q_OBJECT
public:
void emitSignal0();
void emitSignal1();
signals:
void signal0();
void signal1();
void signal2();
void signal3();
void signal4();
void signal5();
void signal6();
void signal7();
void signal8();
void signal9();
public slots:
void slot0();
void slot1();
void slot2();
void slot3();
void slot4();
void slot5();
void slot6();
void slot7();
void slot8();
void slot9();
};
#endif // OBJECT_H

View file

@ -0,0 +1,3 @@
katie_test(qtimer_vs_qmetaobject
${CMAKE_CURRENT_SOURCE_DIR}/tst_qtimer_vs_qmetaobject.cpp
)

View file

@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtTest/QtTest>
#define INVOKE_COUNT 10000
class qtimer_vs_qmetaobject : public QObject
{
Q_OBJECT
private slots:
void testZeroTimerSingleShot();
void testQueuedInvokeMethod();
};
class InvokeCounter : public QObject {
Q_OBJECT
public:
InvokeCounter() : count(0) { };
public slots:
void invokeSlot() {
count++;
if (count == INVOKE_COUNT)
QTestEventLoop::instance().exitLoop();
}
protected:
int count;
};
void qtimer_vs_qmetaobject::testZeroTimerSingleShot()
{
QBENCHMARK {
InvokeCounter invokeCounter;
for(int i = 0; i < INVOKE_COUNT; ++i) {
QTimer::singleShot(0, &invokeCounter, SLOT(invokeSlot()));
}
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
}
}
void qtimer_vs_qmetaobject::testQueuedInvokeMethod()
{
QBENCHMARK {
InvokeCounter invokeCounter;
for(int i = 0; i < INVOKE_COUNT; ++i) {
QMetaObject::invokeMethod(&invokeCounter, "invokeSlot", Qt::QueuedConnection);
}
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
}
}
QTEST_MAIN(qtimer_vs_qmetaobject)
#include "moc_tst_qtimer_vs_qmetaobject.cpp"

View file

@ -0,0 +1,5 @@
katie_test(tst_bench_qvariant
${CMAKE_CURRENT_SOURCE_DIR}/tst_qvariant.cpp
)
target_link_libraries(tst_bench_qvariant KtGui)

View file

@ -0,0 +1,272 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtGui/QPixmap>
#include <qtest.h>
#define ITERATION_COUNT 1e5
class tst_qvariant : public QObject
{
Q_OBJECT
private slots:
void testBound();
void doubleVariantCreation();
void floatVariantCreation();
void rectVariantCreation();
void stringVariantCreation();
void pixmapVariantCreation();
void doubleVariantSetValue();
void floatVariantSetValue();
void rectVariantSetValue();
void stringVariantSetValue();
void doubleVariantAssignment();
void floatVariantAssignment();
void rectVariantAssignment();
void stringVariantAssignment();
void doubleVariantValue();
void floatVariantValue();
void rectVariantValue();
void stringVariantValue();
void createCoreType_data();
void createCoreType();
void createCoreTypeCopy_data();
void createCoreTypeCopy();
};
void tst_qvariant::testBound()
{
qreal d = qreal(.5);
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
d = qBound<qreal>(0, d, 1);
}
}
}
template <typename T>
static void variantCreation(T val)
{
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
QVariant v(val);
}
}
}
void tst_qvariant::doubleVariantCreation()
{
variantCreation<double>(0.0);
}
void tst_qvariant::floatVariantCreation()
{
variantCreation<float>(0.0f);
}
void tst_qvariant::rectVariantCreation()
{
variantCreation<QRect>(QRect(1, 2, 3, 4));
}
void tst_qvariant::stringVariantCreation()
{
variantCreation<QString>(QString());
}
void tst_qvariant::pixmapVariantCreation()
{
variantCreation<QPixmap>(QPixmap());
}
template <typename T>
static void variantSetValue(T d)
{
QVariant v;
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
qVariantSetValue(v, d);
}
}
}
void tst_qvariant::doubleVariantSetValue()
{
variantSetValue<double>(0.0);
}
void tst_qvariant::floatVariantSetValue()
{
variantSetValue<float>(0.0f);
}
void tst_qvariant::rectVariantSetValue()
{
variantSetValue<QRect>(QRect());
}
void tst_qvariant::stringVariantSetValue()
{
variantSetValue<QString>(QString());
}
template <typename T>
static void variantAssignment(T d)
{
QVariant v;
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
v = d;
}
}
}
void tst_qvariant::doubleVariantAssignment()
{
variantAssignment<double>(0.0);
}
void tst_qvariant::floatVariantAssignment()
{
variantAssignment<float>(0.0f);
}
void tst_qvariant::rectVariantAssignment()
{
variantAssignment<QRect>(QRect());
}
void tst_qvariant::stringVariantAssignment()
{
variantAssignment<QString>(QString());
}
void tst_qvariant::doubleVariantValue()
{
QVariant v(0.0);
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
v.toDouble();
}
}
}
void tst_qvariant::floatVariantValue()
{
QVariant v(0.0f);
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
v.toFloat();
}
}
}
void tst_qvariant::rectVariantValue()
{
QVariant v(QRect(1,2,3,4));
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
v.toRect();
}
}
}
void tst_qvariant::stringVariantValue()
{
QVariant v = QString();
QBENCHMARK {
for(int i = 0; i < ITERATION_COUNT; ++i) {
v.toString();
}
}
}
void tst_qvariant::createCoreType_data()
{
QTest::addColumn<int>("typeId");
for (int i = 0; i <= QMetaType::LastCoreType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
}
// Tests how fast a Qt core type can be default-constructed by a
// QVariant. The purpose of this benchmark is to measure the overhead
// of creating (and destroying) a QVariant compared to creating the
// type directly.
void tst_qvariant::createCoreType()
{
QFETCH(int, typeId);
QBENCHMARK {
for (int i = 0; i < ITERATION_COUNT; ++i)
QVariant(typeId, (void *)0);
}
}
void tst_qvariant::createCoreTypeCopy_data()
{
createCoreType_data();
}
// Tests how fast a Qt core type can be copy-constructed by a
// QVariant. The purpose of this benchmark is to measure the overhead
// of creating (and destroying) a QVariant compared to creating the
// type directly.
void tst_qvariant::createCoreTypeCopy()
{
QFETCH(int, typeId);
QVariant other(typeId, (void *)0);
const void *copy = other.constData();
QBENCHMARK {
for (int i = 0; i < ITERATION_COUNT; ++i)
QVariant(typeId, copy);
}
}
QTEST_MAIN(tst_qvariant)
#include "moc_tst_qvariant.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_quuid
${CMAKE_CURRENT_SOURCE_DIR}/tst_quuid.cpp
)

View file

@ -0,0 +1,192 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QCoreApplication>
#include <QtCore/QUuid>
#include <QtTest/QtTest>
class tst_bench_QUuid : public QObject
{
Q_OBJECT
public:
tst_bench_QUuid()
{ }
private slots:
void createUuid();
void fromChar();
void toString();
void fromString();
void toByteArray();
void fromByteArray();
void toRfc4122();
void fromRfc4122();
void toDataStream();
void fromDataStream();
void isNull();
void operatorLess();
void operatorMore();
};
void tst_bench_QUuid::createUuid()
{
QBENCHMARK {
QUuid::createUuid();
}
}
void tst_bench_QUuid::fromChar()
{
QBENCHMARK {
QUuid uuid("{67C8770B-44F1-410A-AB9A-F9B5446F13EE}");
}
}
void tst_bench_QUuid::toString()
{
QUuid uuid = QUuid::createUuid();
QBENCHMARK {
uuid.toString();
}
}
void tst_bench_QUuid::fromString()
{
QString string = "{67C8770B-44F1-410A-AB9A-F9B5446F13EE}";
QBENCHMARK {
QUuid uuid(string);
}
}
void tst_bench_QUuid::toByteArray()
{
QUuid uuid = QUuid::createUuid();
QBENCHMARK {
uuid.toByteArray();
}
}
void tst_bench_QUuid::fromByteArray()
{
QByteArray string = "{67C8770B-44F1-410A-AB9A-F9B5446F13EE}";
QBENCHMARK {
QUuid uuid(string);
}
}
void tst_bench_QUuid::toRfc4122()
{
QUuid uuid = QUuid::createUuid();
QBENCHMARK {
uuid.toRfc4122();
}
}
void tst_bench_QUuid::fromRfc4122()
{
QByteArray string = QByteArray::fromHex("67C8770B44F1410AAB9AF9B5446F13EE");
QBENCHMARK {
QUuid uuid = QUuid::fromRfc4122(string);
}
}
void tst_bench_QUuid::toDataStream()
{
QUuid uuid1, uuid2;
uuid1 = QUuid::createUuid();
QByteArray ar;
{
QDataStream out(&ar,QIODevice::WriteOnly);
QBENCHMARK {
out << uuid1;
}
}
}
void tst_bench_QUuid::fromDataStream()
{
QUuid uuid1, uuid2;
uuid1 = QUuid::createUuid();
QByteArray ar;
{
QDataStream out(&ar,QIODevice::WriteOnly);
out << uuid1;
}
{
QDataStream in(&ar,QIODevice::ReadOnly);
QBENCHMARK {
in >> uuid2;
}
}
}
void tst_bench_QUuid::isNull()
{
QUuid uuid = QUuid();
QBENCHMARK {
uuid.isNull();
}
}
void tst_bench_QUuid::operatorLess()
{
QUuid uuid1, uuid2;
uuid1 = QUuid::createUuid();
uuid2 = QUuid::createUuid();
QBENCHMARK {
uuid1 < uuid2;
}
}
void tst_bench_QUuid::operatorMore()
{
QUuid uuid1, uuid2;
uuid1 = QUuid::createUuid();
uuid2 = QUuid::createUuid();
QBENCHMARK {
uuid1 > uuid2;
}
}
QTEST_MAIN(tst_bench_QUuid);
#include "moc_tst_quuid.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qmutex
${CMAKE_CURRENT_SOURCE_DIR}/tst_qmutex.cpp
)

View file

@ -0,0 +1,453 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>
#include <math.h>
#if defined(Q_OS_UNIX)
# include <pthread.h>
# include <errno.h>
typedef pthread_mutex_t NativeMutexType;
void NativeMutexInitialize(NativeMutexType *mutex)
{
pthread_mutex_init(mutex, NULL);
}
void NativeMutexDestroy(NativeMutexType *mutex)
{
pthread_mutex_destroy(mutex);
}
void NativeMutexLock(NativeMutexType *mutex)
{
pthread_mutex_lock(mutex);
}
void NativeMutexUnlock(NativeMutexType *mutex)
{
pthread_mutex_unlock(mutex);
}
#elif defined(Q_OS_WIN)
# define _WIN32_WINNT 0x0400
# include <windows.h>
typedef CRITICAL_SECTION NativeMutexType;
void NativeMutexInitialize(NativeMutexType *mutex)
{
InitializeCriticalSection(mutex);
}
void NativeMutexDestroy(NativeMutexType *mutex)
{
DeleteCriticalSection(mutex);
}
void NativeMutexLock(NativeMutexType *mutex)
{
EnterCriticalSection(mutex);
}
void NativeMutexUnlock(NativeMutexType *mutex)
{
LeaveCriticalSection(mutex);
}
#endif
//TESTED_FILES=
class tst_QMutex : public QObject
{
Q_OBJECT
int threadCount;
public:
// barriers for the contended tests
static QSemaphore semaphore1, semaphore2, semaphore3, semaphore4;
tst_QMutex()
{
// at least 2 threads, even on single cpu/core machines
threadCount = qMax(2, QThread::idealThreadCount());
qDebug("thread count: %d", threadCount);
}
private slots:
void noThread_data();
void noThread();
void constructionNative();
void uncontendedNative();
void constructionQMutex();
void uncontendedQMutex();
void uncontendedQMutexLocker();
void contendedNative_data();
void contendedQMutex_data() { contendedNative_data(); }
void contendedQMutexLocker_data() { contendedNative_data(); }
void contendedNative();
void contendedQMutex();
void contendedQMutexLocker();
};
QSemaphore tst_QMutex::semaphore1;
QSemaphore tst_QMutex::semaphore2;
QSemaphore tst_QMutex::semaphore3;
QSemaphore tst_QMutex::semaphore4;
void tst_QMutex::noThread_data()
{
QTest::addColumn<int>("t");
QTest::newRow("noLock") << 1;
QTest::newRow("QMutexInline") << 2;
QTest::newRow("QMutex") << 3;
QTest::newRow("QMutexLocker") << 4;
}
void tst_QMutex::noThread()
{
volatile int count = 0;
const int N = 5000000;
QMutex mtx;
QFETCH(int, t);
switch(t) {
case 1:
QBENCHMARK {
count = 0;
for (int i = 0; i < N; i++) {
count++;
}
}
break;
case 2:
QBENCHMARK {
count = 0;
for (int i = 0; i < N; i++) {
mtx.lockInline();
count++;
mtx.unlockInline();
}
}
break;
case 3:
QBENCHMARK {
count = 0;
for (int i = 0; i < N; i++) {
mtx.lock();
count++;
mtx.unlock();
}
}
break;
case 4:
QBENCHMARK {
count = 0;
for (int i = 0; i < N; i++) {
QMutexLocker locker(&mtx);
count++;
}
}
break;
}
QCOMPARE(int(count), N);
}
void tst_QMutex::constructionNative()
{
QBENCHMARK {
NativeMutexType mutex;
NativeMutexInitialize(&mutex);
NativeMutexDestroy(&mutex);
}
}
void tst_QMutex::uncontendedNative()
{
NativeMutexType mutex;
NativeMutexInitialize(&mutex);
QBENCHMARK {
NativeMutexLock(&mutex);
NativeMutexUnlock(&mutex);
}
NativeMutexDestroy(&mutex);
}
void tst_QMutex::constructionQMutex()
{
QBENCHMARK {
QMutex mutex;
Q_UNUSED(mutex);
}
}
void tst_QMutex::uncontendedQMutex()
{
QMutex mutex;
QBENCHMARK {
mutex.lock();
mutex.unlock();
}
}
void tst_QMutex::uncontendedQMutexLocker()
{
QMutex mutex;
QBENCHMARK {
QMutexLocker locker(&mutex);
}
}
void tst_QMutex::contendedNative_data()
{
QTest::addColumn<int>("iterations");
QTest::addColumn<int>("msleepDuration");
QTest::addColumn<bool>("use2mutexes");
QTest::newRow("baseline") << 0 << -1 << false;
QTest::newRow("no msleep, 1 mutex") << 1000 << -1 << false;
QTest::newRow("no msleep, 2 mutexes") << 1000 << -1 << true;
QTest::newRow("msleep(0), 1 mutex") << 1000 << 0 << false;
QTest::newRow("msleep(0), 2 mutexes") << 1000 << 0 << true;
QTest::newRow("msleep(1), 1 mutex") << 10 << 1 << false;
QTest::newRow("msleep(1), 2 mutexes") << 10 << 1 << true;
QTest::newRow("msleep(2), 1 mutex") << 10 << 2 << false;
QTest::newRow("msleep(2), 2 mutexes") << 10 << 2 << true;
QTest::newRow("msleep(10), 1 mutex") << 10 << 10 << false;
QTest::newRow("msleep(10), 2 mutexes") << 10 << 10 << true;
}
class NativeMutexThread : public QThread
{
NativeMutexType *mutex1, *mutex2;
int iterations, msleepDuration;
bool use2mutexes;
public:
bool done;
NativeMutexThread(NativeMutexType *mutex1, NativeMutexType *mutex2, int iterations, int msleepDuration, bool use2mutexes)
: mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false)
{ }
void run() {
forever {
tst_QMutex::semaphore1.release();
tst_QMutex::semaphore2.acquire();
if (done)
break;
for (int i = 0; i < iterations; ++i) {
NativeMutexLock(mutex1);
if (use2mutexes)
NativeMutexLock(mutex2);
if (msleepDuration >= 0)
msleep(msleepDuration);
if (use2mutexes)
NativeMutexUnlock(mutex2);
NativeMutexUnlock(mutex1);
QThread::yieldCurrentThread();
}
tst_QMutex::semaphore3.release();
tst_QMutex::semaphore4.acquire();
}
}
};
void tst_QMutex::contendedNative()
{
QFETCH(int, iterations);
QFETCH(int, msleepDuration);
QFETCH(bool, use2mutexes);
NativeMutexType mutex1, mutex2;
NativeMutexInitialize(&mutex1);
NativeMutexInitialize(&mutex2);
QVector<NativeMutexThread *> threads(threadCount);
for (int i = 0; i < threads.count(); ++i) {
threads[i] = new NativeMutexThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes);
threads[i]->start();
}
QBENCHMARK {
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
semaphore3.acquire(threadCount);
semaphore4.release(threadCount);
}
for (int i = 0; i < threads.count(); ++i)
threads[i]->done = true;
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
for (int i = 0; i < threads.count(); ++i)
threads[i]->wait();
qDeleteAll(threads);
NativeMutexDestroy(&mutex1);
NativeMutexDestroy(&mutex2);
}
class QMutexThread : public QThread
{
QMutex *mutex1, *mutex2;
int iterations, msleepDuration;
bool use2mutexes;
public:
bool done;
QMutexThread(QMutex *mutex1, QMutex *mutex2, int iterations, int msleepDuration, bool use2mutexes)
: mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false)
{ }
void run() {
forever {
tst_QMutex::semaphore1.release();
tst_QMutex::semaphore2.acquire();
if (done)
break;
for (int i = 0; i < iterations; ++i) {
mutex1->lock();
if (use2mutexes)
mutex2->lock();
if (msleepDuration >= 0)
msleep(msleepDuration);
if (use2mutexes)
mutex2->unlock();
mutex1->unlock();
QThread::yieldCurrentThread();
}
tst_QMutex::semaphore3.release();
tst_QMutex::semaphore4.acquire();
}
}
};
void tst_QMutex::contendedQMutex()
{
QFETCH(int, iterations);
QFETCH(int, msleepDuration);
QFETCH(bool, use2mutexes);
QMutex mutex1, mutex2;
QVector<QMutexThread *> threads(threadCount);
for (int i = 0; i < threads.count(); ++i) {
threads[i] = new QMutexThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes);
threads[i]->start();
}
QBENCHMARK {
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
semaphore3.acquire(threadCount);
semaphore4.release(threadCount);
}
for (int i = 0; i < threads.count(); ++i)
threads[i]->done = true;
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
for (int i = 0; i < threads.count(); ++i)
threads[i]->wait();
qDeleteAll(threads);
}
class QMutexLockerThread : public QThread
{
QMutex *mutex1, *mutex2;
int iterations, msleepDuration;
bool use2mutexes;
public:
bool done;
QMutexLockerThread(QMutex *mutex1, QMutex *mutex2, int iterations, int msleepDuration, bool use2mutexes)
: mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false)
{ }
void run() {
forever {
tst_QMutex::semaphore1.release();
tst_QMutex::semaphore2.acquire();
if (done)
break;
for (int i = 0; i < iterations; ++i) {
{
QMutexLocker locker1(mutex1);
QMutexLocker locker2(use2mutexes ? mutex2 : 0);
if (msleepDuration >= 0)
msleep(msleepDuration);
}
QThread::yieldCurrentThread();
}
tst_QMutex::semaphore3.release();
tst_QMutex::semaphore4.acquire();
}
}
};
void tst_QMutex::contendedQMutexLocker()
{
QFETCH(int, iterations);
QFETCH(int, msleepDuration);
QFETCH(bool, use2mutexes);
QMutex mutex1, mutex2;
QVector<QMutexLockerThread *> threads(threadCount);
for (int i = 0; i < threads.count(); ++i) {
threads[i] = new QMutexLockerThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes);
threads[i]->start();
}
QBENCHMARK {
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
semaphore3.acquire(threadCount);
semaphore4.release(threadCount);
}
for (int i = 0; i < threads.count(); ++i)
threads[i]->done = true;
semaphore1.acquire(threadCount);
semaphore2.release(threadCount);
for (int i = 0; i < threads.count(); ++i)
threads[i]->wait();
qDeleteAll(threads);
}
QTEST_MAIN(tst_QMutex)
#include "moc_tst_qmutex.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qthreadstorage
${CMAKE_CURRENT_SOURCE_DIR}/tst_qthreadstorage.cpp
)

View file

@ -0,0 +1,125 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtCore>
//TESTED_FILES=
QThreadStorage<int *> dummy[8];
QThreadStorage<QString *> tls1;
class tst_QThreadStorage : public QObject
{
Q_OBJECT
public:
tst_QThreadStorage();
virtual ~tst_QThreadStorage();
public slots:
void init();
void cleanup();
private slots:
void construct();
void get();
void set();
};
tst_QThreadStorage::tst_QThreadStorage()
{
}
tst_QThreadStorage::~tst_QThreadStorage()
{
}
void tst_QThreadStorage::init()
{
dummy[1].setLocalData(new int(5));
dummy[2].setLocalData(new int(4));
dummy[3].setLocalData(new int(3));
tls1.setLocalData(new QString());
}
void tst_QThreadStorage::cleanup()
{
}
void tst_QThreadStorage::construct()
{
QBENCHMARK {
QThreadStorage<int *> ts;
}
}
void tst_QThreadStorage::get()
{
QThreadStorage<int *> ts;
ts.setLocalData(new int(45));
int count = 0;
QBENCHMARK {
int *i = ts.localData();
count += *i;
}
ts.setLocalData(0);
}
void tst_QThreadStorage::set()
{
QThreadStorage<int *> ts;
int count = 0;
QBENCHMARK {
ts.setLocalData(new int(count));
count++;
}
ts.setLocalData(0);
}
QTEST_MAIN(tst_QThreadStorage)
#include "moc_tst_qthreadstorage.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qwaitcondition
${CMAKE_CURRENT_SOURCE_DIR}/tst_qwaitcondition.cpp
)

View file

@ -0,0 +1,211 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>
#include <math.h>
class tst_QWaitCondition : public QObject
{
Q_OBJECT
public:
tst_QWaitCondition()
{
}
private slots:
void oscillate_data();
void oscillate();
void thrash_data();
void thrash();
public:
static QWaitCondition local, remote;
enum Turn {LocalTurn, RemoteTurn};
static Turn turn;
};
QWaitCondition tst_QWaitCondition::local;
QWaitCondition tst_QWaitCondition::remote;
tst_QWaitCondition::Turn tst_QWaitCondition::turn = tst_QWaitCondition::LocalTurn;
class OscillateThread : public QThread
{
public:
bool m_done;
bool m_useMutex;
unsigned long m_timeout;
bool m_wakeOne;
int count;
OscillateThread(bool useMutex, unsigned long timeout, bool wakeOne)
: m_done(false), m_useMutex(useMutex), m_timeout(timeout), m_wakeOne(wakeOne)
{}
void run()
{
QMutex mtx;
QReadWriteLock rwl;
count = 0;
forever {
if (m_done)
break;
if (m_useMutex) {
mtx.lock();
while (tst_QWaitCondition::turn == tst_QWaitCondition::LocalTurn)
tst_QWaitCondition::remote.wait(&mtx, m_timeout);
mtx.unlock();
} else {
rwl.lockForWrite();
while (tst_QWaitCondition::turn == tst_QWaitCondition::LocalTurn)
tst_QWaitCondition::remote.wait(&rwl, m_timeout);
rwl.unlock();
}
tst_QWaitCondition::turn = tst_QWaitCondition::LocalTurn;
if (m_wakeOne)
tst_QWaitCondition::local.wakeOne();
else
tst_QWaitCondition::local.wakeAll();
count++;
}
}
};
void tst_QWaitCondition::oscillate_data()
{
QTest::addColumn<bool>("useMutex");
QTest::addColumn<unsigned long>("timeout");
QTest::addColumn<bool>("wakeOne");
QTest::newRow("mutex, timeout, one") << true << 1000ul << true;
QTest::newRow("readWriteLock, timeout, one") << false << 1000ul << true;
QTest::newRow("mutex, timeout, all") << true << 1000ul << false;
QTest::newRow("readWriteLock, timeout, all") << false << 1000ul << false;
QTest::newRow("mutex, forever, one") << true << ULONG_MAX << true;
QTest::newRow("readWriteLock, forever, one") << false << ULONG_MAX << true;
QTest::newRow("mutex, forever, all") << true << ULONG_MAX << false;
QTest::newRow("readWriteLock, forever, all") << false << ULONG_MAX << false;
}
void tst_QWaitCondition::oscillate()
{
QMutex mtx;
QReadWriteLock rwl;
QFETCH(bool, useMutex);
QFETCH(unsigned long, timeout);
QFETCH(bool, wakeOne);
turn = LocalTurn;
OscillateThread thrd(useMutex, timeout, wakeOne);
thrd.start();
QBENCHMARK {
if (useMutex)
mtx.lock();
else
rwl.lockForWrite();
turn = RemoteTurn;
if (wakeOne)
remote.wakeOne();
else
remote.wakeAll();
if (useMutex) {
while (turn == RemoteTurn)
local.wait(&mtx, timeout);
mtx.unlock();
} else {
while (turn == RemoteTurn)
local.wait(&rwl, timeout);
rwl.unlock();
}
}
thrd.m_done = true;
remote.wakeAll();
thrd.wait();
QCOMPARE(0, 0);
}
void tst_QWaitCondition::thrash_data()
{
oscillate_data();
}
void tst_QWaitCondition::thrash()
{
QMutex mtx;
mtx.lock();
QFETCH(bool, useMutex);
QFETCH(unsigned long, timeout);
QFETCH(bool, wakeOne);
turn = LocalTurn;
OscillateThread thrd(useMutex, timeout, wakeOne);
thrd.start();
local.wait(&mtx, 1000ul);
mtx.unlock();
QBENCHMARK {
turn = RemoteTurn;
if (wakeOne)
remote.wakeOne();
else
remote.wakeAll();
}
thrd.m_done = true;
turn = RemoteTurn;
remote.wakeAll();
thrd.wait();
QCOMPARE(0, 0);
}
QTEST_MAIN(tst_QWaitCondition)
#include "moc_tst_qwaitcondition.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_containers-associative
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,143 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QString>
#include <qtest.h>
class tst_associative_containers : public QObject
{
Q_OBJECT
private slots:
void insert_data();
void insert();
void lookup_data();
void lookup();
};
template <typename T>
void testInsert(int size)
{
T container;
QBENCHMARK {
for (int i = 0; i < size; ++i)
container.insert(i, i);
}
}
void tst_associative_containers::insert_data()
{
QTest::addColumn<bool>("useHash");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("hash--" + sizeString).constData()) << true << size;
QTest::newRow(("map--" + sizeString).constData()) << false << size;
}
}
void tst_associative_containers::insert()
{
QFETCH(bool, useHash);
QFETCH(int, size);
QHash<int, int> testHash;
QMap<int, int> testMap;
if (useHash) {
testInsert<QHash<int, int> >(size);
} else {
testInsert<QMap<int, int> >(size);
}
}
void tst_associative_containers::lookup_data()
{
// setReportType(LineChartReport);
// setChartTitle("Time to call value(), with an increasing number of items in the container");
QTest::addColumn<bool>("useHash");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("hash--" + sizeString).constData()) << true << size;
QTest::newRow(("map--" + sizeString).constData()) << false << size;
}
}
template <typename T>
void testLookup(int size)
{
T container;
for (int i = 0; i < size; ++i)
container.insert(i, i);
int val;
QBENCHMARK {
for (int i = 0; i < size; ++i)
val = container.value(i);
}
}
void tst_associative_containers::lookup()
{
QFETCH(bool, useHash);
QFETCH(int, size);
if (useHash) {
testLookup<QHash<int, int> >(size);
} else {
testLookup<QMap<int, int> >(size);
}
}
QTEST_MAIN(tst_associative_containers)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_containers-sequential
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,266 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// This file contains benchmarks for comparing QVector against std::vector
#include <QtCore>
#include <QVector>
#include <vector>
#include <qtest.h>
template <typename T> // T is the item type
class UseCases {
public:
virtual ~UseCases() {}
// Use case: Insert \a size items into the vector.
virtual void insert(int size) = 0;
// Use case: Lookup \a size items from the vector.
virtual void lookup(int size) = 0;
};
template <typename T>
T * f(T *ts) // dummy function to prevent code from being optimized away by the compiler
{
return ts;
}
// This subclass implements the use cases using QVector as efficiently as possible.
template <typename T>
class UseCases_QVector : public UseCases<T>
{
void insert(int size)
{
QVector<T> v;
T t;
QBENCHMARK {
for (int i = 0; i < size; ++i)
v.append(t);
}
}
void lookup(int size)
{
QVector<T> v;
T t;
for (int i = 0; i < size; ++i)
v.append(t);
T *ts = new T[size];
QBENCHMARK {
for (int i = 0; i < size; ++i)
ts[i] = v.value(i);
}
f<T>(ts);
delete[] ts;
}
};
// This subclass implements the use cases using std::vector as efficiently as possible.
template <typename T>
class UseCases_stdvector : public UseCases<T>
{
void insert(int size)
{
std::vector<T> v;
T t;
QBENCHMARK {
for (int i = 0; i < size; ++i)
v.push_back(t);
}
}
void lookup(int size)
{
std::vector<T> v;
T t;
for (int i = 0; i < size; ++i)
v.push_back(t);
T *ts = new T[size];
QBENCHMARK {
for (int i = 0; i < size; ++i)
ts[i] = v[i];
}
f<T>(ts);
delete[] ts;
}
};
struct Large { // A "large" item type
int x[1000];
};
// Symbian devices typically have limited memory
#if defined(Q_OS_SYMBIAN) || defined(Q_WS_WINCE)
# define LARGE_MAX_SIZE 2000
#else
# define LARGE_MAX_SIZE 20000
#endif
class tst_vector_vs_std : public QObject
{
Q_OBJECT
public:
tst_vector_vs_std()
{
useCases_QVector_int = new UseCases_QVector<int>;
useCases_stdvector_int = new UseCases_stdvector<int>;
useCases_QVector_Large = new UseCases_QVector<Large>;
useCases_stdvector_Large = new UseCases_stdvector<Large>;
}
private:
UseCases<int> *useCases_QVector_int;
UseCases<int> *useCases_stdvector_int;
UseCases<Large> *useCases_QVector_Large;
UseCases<Large> *useCases_stdvector_Large;
private slots:
void insert_int_data();
void insert_int();
void insert_Large_data();
void insert_Large();
void lookup_int_data();
void lookup_int();
void lookup_Large_data();
void lookup_Large();
};
void tst_vector_vs_std::insert_int_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size;
QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::insert_int()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_int->insert(size);
else
useCases_QVector_int->insert(size);
}
void tst_vector_vs_std::insert_Large_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < LARGE_MAX_SIZE; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size;
QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::insert_Large()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_Large->insert(size);
else
useCases_QVector_Large->insert(size);
}
void tst_vector_vs_std::lookup_int_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size;
QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::lookup_int()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_int->lookup(size);
else
useCases_QVector_int->lookup(size);
}
void tst_vector_vs_std::lookup_Large_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < LARGE_MAX_SIZE; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size;
QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::lookup_Large()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_Large->lookup(size);
else
useCases_QVector_Large->lookup(size);
}
QTEST_MAIN(tst_vector_vs_std)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qbytearray
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QIODevice>
#include <QFile>
#include <QString>
#include <qtest.h>
class tst_qbytearray : public QObject
{
Q_OBJECT
private slots:
void append();
void append_data();
};
void tst_qbytearray::append_data()
{
QTest::addColumn<int>("size");
QTest::newRow("1") << int(1);
QTest::newRow("10") << int(10);
QTest::newRow("100") << int(100);
QTest::newRow("1000") << int(1000);
QTest::newRow("10000") << int(10000);
QTest::newRow("100000") << int(100000);
QTest::newRow("1000000") << int(1000000);
QTest::newRow("10000000") << int(10000000);
QTest::newRow("100000000") << int(100000000);
}
void tst_qbytearray::append()
{
QFETCH(int, size);
QByteArray ba;
QBENCHMARK {
QByteArray ba2(size, 'x');
ba.append(ba2);
ba.clear();
}
}
QTEST_MAIN(tst_qbytearray)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qcontiguouscache
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,189 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QObject>
#include <QTest>
#include <QCache>
#include <QContiguousCache>
#include <QDebug>
#include <stdio.h>
class tst_QContiguousCache : public QObject
{
Q_OBJECT
private slots:
void asScrollingList();
void cacheBenchmark();
void contiguousCacheBenchmark();
};
QTEST_MAIN(tst_QContiguousCache)
void tst_QContiguousCache::asScrollingList()
{
int i;
QContiguousCache<int> c(10);
// Once allocated QContiguousCache should not
// allocate any additional memory for non
// complex data types.
QBENCHMARK {
// simulate scrolling in a list of items;
for (i = 0; i < 10; ++i) {
QCOMPARE(c.available(), 10-i);
c.append(i);
}
QCOMPARE(c.firstIndex(), 0);
QCOMPARE(c.lastIndex(), 9);
QCOMPARE(c.first(), 0);
QCOMPARE(c.last(), 9);
QVERIFY(!c.containsIndex(-1));
QVERIFY(!c.containsIndex(10));
QCOMPARE(c.available(), 0);
for (i = 0; i < 10; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int>)c)[i], i);
}
for (i = 10; i < 30; ++i)
c.append(i);
QCOMPARE(c.firstIndex(), 20);
QCOMPARE(c.lastIndex(), 29);
QCOMPARE(c.first(), 20);
QCOMPARE(c.last(), 29);
QVERIFY(!c.containsIndex(19));
QVERIFY(!c.containsIndex(30));
QCOMPARE(c.available(), 0);
for (i = 20; i < 30; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
for (i = 19; i >= 10; --i)
c.prepend(i);
QCOMPARE(c.firstIndex(), 10);
QCOMPARE(c.lastIndex(), 19);
QCOMPARE(c.first(), 10);
QCOMPARE(c.last(), 19);
QVERIFY(!c.containsIndex(9));
QVERIFY(!c.containsIndex(20));
QCOMPARE(c.available(), 0);
for (i = 10; i < 20; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
for (i = 200; i < 220; ++i)
c.insert(i, i);
QCOMPARE(c.firstIndex(), 210);
QCOMPARE(c.lastIndex(), 219);
QCOMPARE(c.first(), 210);
QCOMPARE(c.last(), 219);
QVERIFY(!c.containsIndex(209));
QVERIFY(!c.containsIndex(300));
QCOMPARE(c.available(), 0);
for (i = 210; i < 220; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
c.clear(); // needed to reset benchmark
}
// from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed.
// bug was that item at 150 would instead be item that should have been inserted at 250
c.setCapacity(200);
for (i = 100; i < 300; ++i)
c.insert(i, i);
for (i = 250; i <= 306; ++i)
c.insert(i, 1000+i);
for (i = 107; i <= 306; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i < 250 ? i : 1000+i);
}
}
/*
Benchmarks must be near identical in tasks to be fair.
QCache uses pointers to ints as its a requirement of QCache,
whereas QContiguousCache doesn't support pointers (won't free them).
Given the ability to use simple data types is a benefit, its
fair. Although this obviously must take into account we are
testing QContiguousCache use cases here, QCache has its own
areas where it is the more sensible class to use.
*/
void tst_QContiguousCache::cacheBenchmark()
{
QBENCHMARK {
QCache<int, int> cache;
cache.setMaxCost(100);
for (int i = 0; i < 1000; i++)
cache.insert(i, new int(i));
}
}
void tst_QContiguousCache::contiguousCacheBenchmark()
{
QBENCHMARK {
QContiguousCache<int> contiguousCache(100);
for (int i = 0; i < 1000; i++)
contiguousCache.insert(i, i);
}
}
#include "moc_main.cpp"

View file

@ -0,0 +1,4 @@
katie_test(tst_hash
${CMAKE_CURRENT_SOURCE_DIR}/qhash_string.cpp
${CMAKE_CURRENT_SOURCE_DIR}/outofline.cpp
)

View file

@ -0,0 +1,195 @@
.
./corelib.pro
./kernel
./kernel/kernel.pro
./kernel/qobject
./kernel/qobject/main.cpp
./kernel/qobject/object.cpp
./kernel/qobject/object.h
./kernel/qobject/Makefile
./kernel/qobject/qobject.pro
./kernel/qvariant
./kernel/qvariant/tst_qvariant.cpp
./kernel/qvariant/Makefile
./kernel/qvariant/qvariant.pro
./kernel/qtimer_vs_qmetaobject
./kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
./kernel/qtimer_vs_qmetaobject/Makefile
./kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro
./kernel/.pch
./kernel/.pch/debug-shared
./kernel/qmetaobject
./kernel/qmetaobject/main.cpp
./kernel/qmetaobject/qmetaobject.pro
./kernel/qmetaobject/Makefile
./kernel/Makefile
./kernel/.obj
./kernel/.obj/debug-shared
./kernel/events
./kernel/events/events.pro
./kernel/events/main.cpp
./kernel/events/Makefile
./kernel/qmetatype
./kernel/qmetatype/qmetatype.pro
./kernel/qmetatype/Makefile
./kernel/qmetatype/tst_qmetatype.cpp
./codecs
./codecs/qtextcodec
./codecs/qtextcodec/qtextcodec.pro
./codecs/qtextcodec/main.cpp
./codecs/qtextcodec/Makefile
./codecs/qtextcodec/utf-8.txt
./codecs/codecs.pro
./codecs/.pch
./codecs/.pch/debug-shared
./codecs/Makefile
./codecs/.obj
./codecs/.obj/debug-shared
./.pch
./.pch/debug-shared
./tools
./tools/tools.pro
./tools/qregexp
./tools/qregexp/qregexp.qrc
./tools/qregexp/main.cpp
./tools/qregexp/Makefile
./tools/qregexp/qregexp.pro
./tools/qvector
./tools/qvector/tst_vector
./tools/qvector/.pch
./tools/qvector/.pch/debug-shared
./tools/qvector/qrawvector.h
./tools/qvector/main.cpp
./tools/qvector/Makefile
./tools/qvector/.moc
./tools/qvector/.moc/release-shared
./tools/qvector/.moc/release-shared/main.moc
./tools/qvector/.obj
./tools/qvector/.obj/release-shared
./tools/qvector/.obj/release-shared/outofline.o
./tools/qvector/.obj/release-shared/main.o
./tools/qvector/outofline.cpp
./tools/qvector/qvector.pro
./tools/.pch
./tools/.pch/debug-shared
./tools/qstringbuilder
./tools/qstringbuilder/main.cpp
./tools/qstringbuilder/Makefile
./tools/qstringbuilder/qstringbuilder.pro
./tools/containers-sequential
./tools/containers-sequential/containers-sequential.pro
./tools/containers-sequential/main.cpp
./tools/containers-sequential/Makefile
./tools/qstring
./tools/qstring/generatelist.pl
./tools/qstring/data.h
./tools/qstring/qstring.pro
./tools/qstring/main.cpp
./tools/qstring/data.cpp
./tools/qstring/Makefile
./tools/qstring/utf-8.txt
./tools/qstringlist
./tools/qstringlist/qstringlist.pro
./tools/qstringlist/main.cpp
./tools/qstringlist/.gitignore
./tools/qstringlist/Makefile
./tools/qbytearray
./tools/qbytearray/qbytearray.pro
./tools/qbytearray/main.cpp
./tools/qbytearray/Makefile
./tools/containers-associative
./tools/containers-associative/containers-associative.pro
./tools/containers-associative/main.cpp
./tools/containers-associative/Makefile
./tools/qrect
./tools/qrect/main.cpp
./tools/qrect/Makefile
./tools/qrect/qrect.pro
./tools/Makefile
./tools/qhash
./tools/qhash/data.txt
./tools/qhash/qhash_string.cpp
./tools/qhash/.qhash_string.cpp.swp
./tools/qhash/qhash.pro
./tools/qhash/outofline.cpp
./tools/.obj
./tools/.obj/debug-shared
./Makefile
./.obj
./.obj/debug-shared
./plugin
./plugin/plugin.pro
./plugin/.pch
./plugin/.pch/debug-shared
./plugin/Makefile
./plugin/.obj
./plugin/.obj/debug-shared
./plugin/quuid
./plugin/quuid/tst_quuid.cpp
./plugin/quuid/quuid.pro
./plugin/quuid/Makefile
./io
./io/qtemporaryfile
./io/qtemporaryfile/qtemporaryfile.pro
./io/qtemporaryfile/main.cpp
./io/qtemporaryfile/Makefile
./io/qiodevice
./io/qiodevice/qiodevice.pro
./io/qiodevice/main.cpp
./io/qiodevice/Makefile
./io/qurl
./io/qurl/main.cpp
./io/qurl/Makefile
./io/qurl/qurl.pro
./io/qdir
./io/qdir/.pch
./io/qdir/.pch/debug-shared
./io/qdir/qdir.pro
./io/qdir/tree
./io/qdir/tree/bench_qdir_tree.qrc
./io/qdir/tree/tree.pro
./io/qdir/tree/4.6.0-list.txt
./io/qdir/tree/Makefile
./io/qdir/tree/bench_qdir_tree.cpp
./io/qdir/Makefile
./io/qdir/.obj
./io/qdir/.obj/debug-shared
./io/qdir/10000
./io/qdir/10000/10000.pro
./io/qdir/10000/bench_qdir_10000.cpp
./io/qdir/10000/Makefile
./io/.pch
./io/.pch/debug-shared
./io/qfile
./io/qfile/qfile.pro
./io/qfile/main.cpp
./io/qfile/Makefile
./io/io.pro
./io/qfileinfo
./io/qfileinfo/qfileinfo.pro
./io/qfileinfo/main.cpp
./io/qfileinfo/Makefile
./io/qdiriterator
./io/qdiriterator/qfilesystemiterator.h
./io/qdiriterator/main.cpp
./io/qdiriterator/Makefile
./io/qdiriterator/qfilesystemiterator.cpp
./io/qdiriterator/qdiriterator.pro
./io/Makefile
./io/.obj
./io/.obj/debug-shared
./thread
./thread/qmutex
./thread/qmutex/tst_qmutex.cpp
./thread/qmutex/Makefile
./thread/qmutex/qmutex.pro
./thread/qthreadstorage
./thread/qthreadstorage/qthreadstorage.pro
./thread/qthreadstorage/Makefile
./thread/qthreadstorage/tst_qthreadstorage.cpp
./thread/.pch
./thread/.pch/debug-shared
./thread/Makefile
./thread/.obj
./thread/.obj/debug-shared
./thread/thread.pro

View file

@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtTest module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qhash_string.h"
static void doHash(const unsigned short *p, uint &h)
{
#if 1
// Copied from static uint hash(const QChar *p, int n).
// Possibly not the cheapest way.
h = (h << 4) + (*p++);
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
h = (h << 4) + (*p++);
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
h = (h << 4) + (*p++);
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
h = (h << 4) + (*p++);
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
#else
// Faster, but probably less spread.
h ^= *(unsigned int *)p;
#endif
}
QT_BEGIN_NAMESPACE
uint qHash(const String &str)
{
const unsigned short *p = (unsigned short *)str.constData();
const int s = str.size();
switch (s) {
case 0: return 0;
case 1: return *p;
case 2: return *(unsigned int *)p;
case 3: return (*(unsigned int *)p) ^ *(p + 2);
//case 3: return (*p << 11) + (*(p + 1) << 22) + *(p + 2);
}
uint h = 0;
doHash(p, h);
doHash(p + s / 2 - 2, h);
doHash(p + s - 4, h);
return h;
}
QT_END_NAMESPACE

View file

@ -0,0 +1,131 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*
////////////////////////////////////////////////////////////////////
This benchmark serves as reality check on the idea that hashing the complete
string is a good idea.
Executive summary: It is not a good idea.
////////////////////////////////////////////////////////////////////
********* Start testing of tst_QHash *********
Config: Using QTest library 4.8.0, Qt 4.8.0
PASS : tst_QHash::initTestCase()
RESULT : tst_QHash::qhash_qt4():
0.041 msecs per iteration (total: 85, iterations: 2048)
PASS : tst_QHash::qhash_qt4()
RESULT : tst_QHash::qhash_faster():
0.0122 msecs per iteration (total: 100, iterations: 8192)
PASS : tst_QHash::qhash_faster()
PASS : tst_QHash::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped
////////////////////////////////////////////////////////////////////
*/
#include "qhash_string.h"
#include <QFile>
#include <QHash>
#include <QString>
#include <QStringList>
#include <QTest>
class tst_QHash : public QObject
{
Q_OBJECT
private slots:
void qhash_qt4();
void qhash_faster();
private:
QString data();
};
const int N = 1000000;
extern double s;
///////////////////// QHash /////////////////////
QString tst_QHash::data()
{
QFile file("data.txt");
file.open(QIODevice::ReadOnly);
return QString::fromLatin1(file.readAll());
}
void tst_QHash::qhash_qt4()
{
QStringList items = data().split(QLatin1Char('\n'));
QHash<QString, int> hash;
QBENCHMARK {
for (int i = 0, n = items.size(); i != n; ++i) {
hash[items.at(i)] = i;
}
}
}
void tst_QHash::qhash_faster()
{
QList<String> items;
foreach (const QString &s, data().split(QLatin1Char('\n')))
items.append(s);
QHash<String, int> hash;
QBENCHMARK {
for (int i = 0, n = items.size(); i != n; ++i) {
hash[items.at(i)] = i;
}
}
}
QTEST_MAIN(tst_QHash)
#include "moc_qhash_string.cpp"

View file

@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtTest module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QString>
struct String : QString
{
String() {}
String(const QString &s) : QString(s) {}
};
QT_BEGIN_NAMESPACE
uint qHash(const String &);
QT_END_NAMESPACE

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qline
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,157 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// This file contains benchmarks for QLineF functions.
#include <QDebug>
#include <qtest.h>
#include <QLine>
class tst_qline : public QObject
{
Q_OBJECT
private slots:
void fromPolar();
void intersect_data();
void intersect();
void length();
void setLength();
void angle();
void setAngle();
void angleTo();
void unitVector();
void normalVector();
void angle2();
};
void tst_qline::fromPolar()
{
QBENCHMARK {
QLineF::fromPolar(10, 2);
}
}
void tst_qline::intersect_data()
{
QTest::addColumn<QLineF>("l1");
QTest::addColumn<QLineF>("l2");
QTest::newRow("cross") << QLineF(-1,-1,1,1) << QLineF(-1,1,1,-1);
QTest::newRow("miss") << QLineF(1,1,2,2) << QLineF(1,11,2,12);
}
void tst_qline::intersect()
{
QFETCH(QLineF, l1);
QFETCH(QLineF, l2);
QPointF intersection;
QBENCHMARK {
l1.intersect(l2, &intersection);
}
}
void tst_qline::length()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.length();
}
}
void tst_qline::setLength()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.setLength(5);
}
}
void tst_qline::angle()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.angle();
}
}
void tst_qline::setAngle()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.setAngle(1);
}
}
void tst_qline::angleTo()
{
QLineF line1(1,2,3,4);
QLineF line2(8,7,6,5);
QBENCHMARK {
line1.angleTo(line2);
}
}
void tst_qline::unitVector()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.unitVector();
}
}
void tst_qline::normalVector()
{
QLineF line(1,2,3,4);
QBENCHMARK {
line.normalVector();
}
}
void tst_qline::angle2()
{
QLineF line1(1,2,3,4);
QLineF line2(8,7,6,5);
QBENCHMARK {
line1.angle(line2);
}
}
QTEST_MAIN(tst_qline)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_qlist
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,250 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QList>
#include <QTest>
static const int N = 1000;
struct MyBase
{
MyBase(int i_)
: isCopy(false)
{
++liveCount;
i = i_;
}
MyBase(const MyBase &other)
: isCopy(true)
{
if (isCopy)
++copyCount;
++liveCount;
i = other.i;
}
MyBase &operator=(const MyBase &other)
{
if (!isCopy) {
isCopy = true;
++copyCount;
} else {
++errorCount;
}
i = other.i;
return *this;
}
~MyBase()
{
if (isCopy) {
if (!copyCount)
++errorCount;
else
--copyCount;
}
if (!liveCount)
++errorCount;
else
--liveCount;
}
bool operator==(const MyBase &other) const
{ return i == other.i; }
protected:
ushort i;
bool isCopy;
public:
static int errorCount;
static int liveCount;
static int copyCount;
};
int MyBase::errorCount = 0;
int MyBase::liveCount = 0;
int MyBase::copyCount = 0;
struct MyPrimitive : public MyBase
{
MyPrimitive(int i = -1) : MyBase(i)
{ ++errorCount; }
MyPrimitive(const MyPrimitive &other) : MyBase(other)
{ ++errorCount; }
~MyPrimitive()
{ ++errorCount; }
};
struct MyMovable : public MyBase
{
MyMovable(int i = -1) : MyBase(i) {}
};
struct MyComplex : public MyBase
{
MyComplex(int i = -1) : MyBase(i) {}
};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MyPrimitive, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(MyMovable, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(MyComplex, Q_COMPLEX_TYPE);
QT_END_NAMESPACE
class tst_QList: public QObject
{
Q_OBJECT
private Q_SLOTS:
void removeAll_primitive_data();
void removeAll_primitive();
void removeAll_movable_data();
void removeAll_movable();
void removeAll_complex_data();
void removeAll_complex();
};
template <class T>
void removeAll_test(const QList<int> &i10, ushort valueToRemove, int itemsToRemove)
{
bool isComplex = QTypeInfo<T>::isComplex;
MyBase::errorCount = 0;
MyBase::liveCount = 0;
MyBase::copyCount = 0;
{
QList<T> list;
QCOMPARE(MyBase::liveCount, 0);
QCOMPARE(MyBase::copyCount, 0);
for (int i = 0; i < 10 * N; ++i) {
T t(i10.at(i % 10));
list.append(t);
}
QCOMPARE(MyBase::liveCount, isComplex ? list.size() : 0);
QCOMPARE(MyBase::copyCount, isComplex ? list.size() : 0);
T t(valueToRemove);
QCOMPARE(MyBase::liveCount, isComplex ? list.size() + 1 : 1);
QCOMPARE(MyBase::copyCount, isComplex ? list.size() : 0);
int removedCount;
QList<T> l;
QBENCHMARK {
l = list;
removedCount = l.removeAll(t);
}
QCOMPARE(removedCount, itemsToRemove * N);
QCOMPARE(l.size() + removedCount, list.size());
QVERIFY(!l.contains(valueToRemove));
QCOMPARE(MyBase::liveCount, isComplex ? l.isDetached() ? list.size() + l.size() + 1 : list.size() + 1 : 1);
QCOMPARE(MyBase::copyCount, isComplex ? l.isDetached() ? list.size() + l.size() : list.size() : 0);
}
if (isComplex)
QCOMPARE(MyBase::errorCount, 0);
}
Q_DECLARE_METATYPE(QList<int>);
void tst_QList::removeAll_primitive_data()
{
qRegisterMetaType<QList<int> >();
QTest::addColumn<QList<int> >("i10");
QTest::addColumn<int>("valueToRemove");
QTest::addColumn<int>("itemsToRemove");
QTest::newRow("0%") << (QList<int>() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0) << 5 << 0;
QTest::newRow("10%") << (QList<int>() << 0 << 0 << 0 << 0 << 5 << 0 << 0 << 0 << 0 << 0) << 5 << 1;
QTest::newRow("90%") << (QList<int>() << 5 << 5 << 5 << 5 << 0 << 5 << 5 << 5 << 5 << 5) << 5 << 9;
QTest::newRow("100%") << (QList<int>() << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 5 << 5) << 5 << 10;
}
void tst_QList::removeAll_primitive()
{
QFETCH(QList<int>, i10);
QFETCH(int, valueToRemove);
QFETCH(int, itemsToRemove);
removeAll_test<MyPrimitive>(i10, valueToRemove, itemsToRemove);
}
void tst_QList::removeAll_movable_data()
{
removeAll_primitive_data();
}
void tst_QList::removeAll_movable()
{
QFETCH(QList<int>, i10);
QFETCH(int, valueToRemove);
QFETCH(int, itemsToRemove);
removeAll_test<MyMovable>(i10, valueToRemove, itemsToRemove);
}
void tst_QList::removeAll_complex_data()
{
removeAll_primitive_data();
}
void tst_QList::removeAll_complex()
{
QFETCH(QList<int>, i10);
QFETCH(int, valueToRemove);
QFETCH(int, itemsToRemove);
removeAll_test<MyComplex>(i10, valueToRemove, itemsToRemove);
}
QTEST_APPLESS_MAIN(tst_QList)
#include "moc_main.cpp"

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qrect
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,329 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// This file contains benchmarks for QRect/QRectF functions.
#include <QDebug>
#include <qtest.h>
class tst_qrect : public QObject
{
Q_OBJECT
private slots:
// QRect functions:
void contains_point_data();
void contains_point();
void contains_rect_data();
void contains_rect();
void intersects_data();
void intersects();
void intersected_data();
void intersected();
void united_data();
void united();
// QRectF functions:
void contains_point_f_data();
void contains_point_f();
void contains_rect_f_data();
void contains_rect_f();
void intersects_f_data();
void intersects_f();
void intersected_f_data();
void intersected_f();
void united_f_data();
void united_f();
};
struct RectRectCombination
{
QString tag;
qreal x1, y1, w1, h1, x2, y2, w2, h2;
RectRectCombination(
const QString &tag,
const qreal x1, const qreal y1, const qreal w1, const qreal h1,
const qreal x2, const qreal y2, const qreal w2, const qreal h2)
: tag(tag), x1(x1), y1(y1), w1(w1), h1(h1), x2(x2), y2(y2), w2(w2), h2(h2) {}
};
static QList<RectRectCombination> createRectRectCombinations()
{
QList<RectRectCombination> result;
result << RectRectCombination("null", 0, 0, 0, 0, 0, 0, 0, 0);
result << RectRectCombination("null1", 0, 0, 0, 0, 0, 0, 10, 10);
result << RectRectCombination("null2", 0, 0, 10, 10, 0, 0, 0, 0);
result << RectRectCombination("miss", 0, 0, 10, 10, 11, 11, 10, 10);
result << RectRectCombination("intersect", 0, 0, 10, 10, 5, 5, 10, 10);
result << RectRectCombination("contain1", 0, 0, 10, 10, 1, 1, 8, 8);
result << RectRectCombination("contain2", 1, 1, 8, 8, 0, 0, 10, 10);
result << RectRectCombination("miss_flip1", 9, 9, -10, -10, 11, 11, 10, 10);
result << RectRectCombination("intersect_flip1", 9, 9, -10, -10, 5, 5, 10, 10);
result << RectRectCombination("contain1_flip1", 9, 9, -10, -10, 1, 1, 8, 8);
result << RectRectCombination("contain2_flip1", 8, 8, -8, -8, 0, 0, 10, 10);
result << RectRectCombination("miss_flip2", 0, 0, 10, 10, 20, 20, -10, -10);
result << RectRectCombination("intersect_flip2", 0, 0, 10, 10, 14, 14, -10, -10);
result << RectRectCombination("contain1_flip2", 0, 0, 10, 10, 8, 8, -8, -8);
result << RectRectCombination("contain2_flip2", 1, 1, 8, 8, 9, 9, -10, -10);
return result;
}
static void addRectRectData(bool includeProperArg = false)
{
QTest::addColumn<QRectF>("rf1");
QTest::addColumn<QRectF>("rf2");
if (includeProperArg)
QTest::addColumn<bool>("proper");
for (int i = 0; i < (includeProperArg ? 2 : 1); ++i) {
QList<RectRectCombination> combinations = createRectRectCombinations();
foreach (RectRectCombination c, combinations) {
QTestData &testData = QTest::newRow(c.tag.toLatin1().data());
QRectF r1(c.x1, c.y1, c.w1, c.h1);
QRectF r2(c.x2, c.y2, c.w2, c.h2);
testData << r1 << r2;
if (includeProperArg)
testData << (i == 0);
}
}
}
struct RectPointCombination
{
QString tag;
qreal x, y, w, h, px, py;
RectPointCombination(
const QString &tag,
const qreal x, const qreal y, const qreal w, const qreal h, const qreal px, const qreal py)
: tag(tag), x(x), y(y), w(w), h(h), px(px), py(py) {}
};
static QList<RectPointCombination> createRectPointCombinations()
{
QList<RectPointCombination> result;
result << RectPointCombination("null", 0, 0, 0, 0, 0, 0);
result << RectPointCombination("miss", 0, 0, 10, 10, -1, -1);
result << RectPointCombination("contain", 0, 0, 10, 10, 0, 0);
result << RectPointCombination("contain_proper", 0, 0, 10, 10, 1, 1);
result << RectPointCombination("miss_flip", 9, 9, -10, -10, -1, -1);
result << RectPointCombination("contain_flip", 9, 9, -10, -10, 0, 0);
result << RectPointCombination("contain_flip_proper", 9, 9, -10, -10, 1, 1);
return result;
}
static void addRectPointData(bool includeProperArg = false)
{
QTest::addColumn<QRectF>("rf");
QTest::addColumn<QPointF>("pf");
if (includeProperArg)
QTest::addColumn<bool>("proper");
for (int i = 0; i < (includeProperArg ? 2 : 1); ++i) {
QList<RectPointCombination> combinations = createRectPointCombinations();
foreach (RectPointCombination c, combinations) {
QTestData &testData = QTest::newRow(c.tag.toLatin1().data());
QRectF r(c.x, c.y, c.w, c.h);
QPointF p(c.px, c.py);
testData << r << p;
if (includeProperArg)
testData << (i == 0);
}
}
}
void tst_qrect::contains_point_data()
{
addRectPointData(true);
}
void tst_qrect::contains_point()
{
QFETCH(QRectF, rf);
QFETCH(QPointF, pf);
QFETCH(bool, proper);
QRect r(rf.toRect());
QPoint p(pf.toPoint());
QBENCHMARK {
r.contains(p, proper);
}
}
void tst_qrect::contains_rect_data()
{
addRectRectData(true);
}
void tst_qrect::contains_rect()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QFETCH(bool, proper);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.contains(r2, proper);
}
}
void tst_qrect::intersects_data()
{
addRectRectData();
}
void tst_qrect::intersects()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.intersects(r2);
}
}
void tst_qrect::intersected_data()
{
addRectRectData();
}
void tst_qrect::intersected()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.intersected(r2);
}
}
void tst_qrect::united_data()
{
addRectRectData();
}
void tst_qrect::united()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.united(r2);
}
}
void tst_qrect::contains_point_f_data()
{
addRectPointData();
}
void tst_qrect::contains_point_f()
{
QFETCH(QRectF, rf);
QFETCH(QPointF, pf);
QBENCHMARK {
rf.contains(pf);
}
}
void tst_qrect::contains_rect_f_data()
{
addRectRectData();
}
void tst_qrect::contains_rect_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.contains(rf2);
}
}
void tst_qrect::intersects_f_data()
{
addRectRectData();
}
void tst_qrect::intersects_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.intersects(rf2);
}
}
void tst_qrect::intersected_f_data()
{
addRectRectData();
}
void tst_qrect::intersected_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.intersected(rf2);
}
}
void tst_qrect::united_f_data()
{
addRectRectData();
}
void tst_qrect::united_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.united(rf2);
}
}
QTEST_MAIN(tst_qrect)
#include "moc_main.cpp"

View file

@ -0,0 +1,6 @@
katie_test(tst_bench_qregexp
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qregexp.qrc
)
target_link_libraries(tst_bench_qregexp KtScript)

View file

@ -0,0 +1,595 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QRegExp>
#include <QString>
#include <QFile>
#include <qtest.h>
#ifdef HAVE_BOOST
#include <boost/regex.hpp>
#endif
#include <QtScript>
#include "pcre/pcre.h"
#define ZLIB_VERSION "1.2.3.4"
class tst_qregexp : public QObject
{
Q_OBJECT
public:
tst_qregexp();
private slots:
void escape_old();
void escape_old_data() { escape_data(); }
void escape_new1();
void escape_new1_data() { escape_data(); }
void escape_new2();
void escape_new2_data() { escape_data(); }
void escape_new3();
void escape_new3_data() { escape_data(); }
void escape_new4();
void escape_new4_data() { escape_data(); }
/*
JSC outperforms everything.
Boost is less impressive then expected.
*/
void simpleFind1();
void rangeReplace1();
void matchReplace1();
void simpleFind2();
void rangeReplace2();
void matchReplace2();
void simpleFindJSC();
void rangeReplaceJSC();
void matchReplaceJSC();
#ifdef HAVE_BOOST
void simpleFindBoost();
void rangeReplaceBoost();
void matchReplaceBoost();
#endif
/* those apply an (incorrect) regexp on entire source
(this main.cpp). JSC appears to handle this
(ab)use case best. QRegExp performs extremly bad.
*/
void horribleWrongReplace1();
void horribleReplace1();
void horribleReplace2();
void horribleWrongReplace2();
void horribleWrongReplaceJSC();
void horribleReplaceJSC();
#ifdef HAVE_BOOST
void horribleWrongReplaceBoost();
void horribleReplaceBoost();
#endif
private:
QString str1;
QString str2;
void escape_data();
};
tst_qregexp::tst_qregexp()
:QObject()
,str1("We are all happy monkeys")
{
QFile f(":/main.cpp");
f.open(QFile::ReadOnly);
str2=f.readAll();
}
static void verify(const QString &quoted, const QString &expected)
{
if (quoted != expected)
qDebug() << "ERROR:" << quoted << expected;
}
void tst_qregexp::escape_data()
{
QTest::addColumn<QString>("pattern");
QTest::addColumn<QString>("expected");
QTest::newRow("escape 0") << "Hello world" << "Hello world";
QTest::newRow("escape 1") << "(Hello world)" << "\\(Hello world\\)";
{
QString s;
for (int i = 0; i < 10; ++i)
s += "(escape)";
QTest::newRow("escape 10") << s << QRegExp::escape(s);
}
{
QString s;
for (int i = 0; i < 100; ++i)
s += "(escape)";
QTest::newRow("escape 100") << s << QRegExp::escape(s);
}
}
void tst_qregexp::escape_old()
{
QFETCH(QString, pattern);
QFETCH(QString, expected);
QBENCHMARK {
static const char meta[] = "$()*+.?[\\]^{|}";
QString quoted = pattern;
int i = 0;
while (i < quoted.length()) {
if (strchr(meta, quoted.at(i).toLatin1()) != 0)
quoted.insert(i++, QLatin1Char('\\'));
++i;
}
verify(quoted, expected);
}
}
void tst_qregexp::escape_new1()
{
QFETCH(QString, pattern);
QFETCH(QString, expected);
QBENCHMARK {
QString quoted;
const int count = pattern.count();
quoted.reserve(count * 2);
const QLatin1Char backslash('\\');
for (int i = 0; i < count; i++) {
switch (pattern.at(i).toLatin1()) {
case '$':
case '(':
case ')':
case '*':
case '+':
case '.':
case '?':
case '[':
case '\\':
case ']':
case '^':
case '{':
case '|':
case '}':
quoted.append(backslash);
}
quoted.append(pattern.at(i));
}
verify(quoted, expected);
}
}
void tst_qregexp::escape_new2()
{
QFETCH(QString, pattern);
QFETCH(QString, expected);
QBENCHMARK {
int count = pattern.count();
const QLatin1Char backslash('\\');
QString quoted(count * 2, backslash);
const QChar *patternData = pattern.data();
QChar *quotedData = quoted.data();
int escaped = 0;
for ( ; --count >= 0; ++patternData) {
const QChar c = *patternData;
switch (c.unicode()) {
case '$':
case '(':
case ')':
case '*':
case '+':
case '.':
case '?':
case '[':
case '\\':
case ']':
case '^':
case '{':
case '|':
case '}':
++escaped;
++quotedData;
}
*quotedData = c;
++quotedData;
}
quoted.resize(pattern.size() + escaped);
verify(quoted, expected);
}
}
void tst_qregexp::escape_new3()
{
QFETCH(QString, pattern);
QFETCH(QString, expected);
QBENCHMARK {
QString quoted;
const int count = pattern.count();
quoted.reserve(count * 2);
const QLatin1Char backslash('\\');
for (int i = 0; i < count; i++) {
switch (pattern.at(i).toLatin1()) {
case '$':
case '(':
case ')':
case '*':
case '+':
case '.':
case '?':
case '[':
case '\\':
case ']':
case '^':
case '{':
case '|':
case '}':
quoted += backslash;
}
quoted += pattern.at(i);
}
verify(quoted, expected);
}
}
static inline bool needsEscaping(int c)
{
switch (c) {
case '$':
case '(':
case ')':
case '*':
case '+':
case '.':
case '?':
case '[':
case '\\':
case ']':
case '^':
case '{':
case '|':
case '}':
return true;
}
return false;
}
void tst_qregexp::escape_new4()
{
QFETCH(QString, pattern);
QFETCH(QString, expected);
QBENCHMARK {
const int n = pattern.size();
const QChar *patternData = pattern.data();
// try to prevent copy if no escape is needed
int i = 0;
for (int i = 0; i != n; ++i) {
const QChar c = patternData[i];
if (needsEscaping(c.unicode()))
break;
}
if (i == n) {
verify(pattern, expected);
// no escaping needed, "return pattern" should be done here.
return;
}
const QLatin1Char backslash('\\');
QString quoted(n * 2, backslash);
QChar *quotedData = quoted.data();
for (int j = 0; j != i; ++j)
*quotedData++ = *patternData++;
int escaped = 0;
for (; i != n; ++i) {
const QChar c = *patternData;
if (needsEscaping(c.unicode())) {
++escaped;
++quotedData;
}
*quotedData = c;
++quotedData;
++patternData;
}
quoted.resize(n + escaped);
verify(quoted, expected);
// "return quoted"
}
}
void tst_qregexp::simpleFind1()
{
int roff;
QRegExp rx("happy");
rx.setPatternSyntax(QRegExp::RegExp);
QBENCHMARK{
roff = rx.indexIn(str1);
}
QCOMPARE(roff, 11);
}
void tst_qregexp::rangeReplace1()
{
QString r;
QRegExp rx("[a-f]");
rx.setPatternSyntax(QRegExp::RegExp);
QBENCHMARK{
r = QString(str1).replace(rx, "-");
}
QCOMPARE(r, QString("W- -r- -ll h-ppy monk-ys"));
}
void tst_qregexp::matchReplace1()
{
QString r;
QRegExp rx("[^a-f]*([a-f]+)[^a-f]*");
rx.setPatternSyntax(QRegExp::RegExp);
QBENCHMARK{
r = QString(str1).replace(rx, "\\1");
}
QCOMPARE(r, QString("eaeaae"));
}
void tst_qregexp::horribleWrongReplace1()
{
QString r;
QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*");
rx.setPatternSyntax(QRegExp::RegExp);
QBENCHMARK{
r = QString(str2).replace(rx, "\\1.\\2.\\3");
}
QCOMPARE(r, str2);
}
void tst_qregexp::horribleReplace1()
{
QString r;
QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*");
rx.setPatternSyntax(QRegExp::RegExp);
QBENCHMARK{
r = QString(str2).replace(rx, "\\1.\\2.\\3");
}
QCOMPARE(r, QString("1.2.3"));
}
void tst_qregexp::simpleFind2()
{
int roff;
QRegExp rx("happy");
rx.setPatternSyntax(QRegExp::RegExp2);
QBENCHMARK{
roff = rx.indexIn(str1);
}
QCOMPARE(roff, 11);
}
void tst_qregexp::rangeReplace2()
{
QString r;
QRegExp rx("[a-f]");
rx.setPatternSyntax(QRegExp::RegExp2);
QBENCHMARK{
r = QString(str1).replace(rx, "-");
}
QCOMPARE(r, QString("W- -r- -ll h-ppy monk-ys"));
}
void tst_qregexp::matchReplace2()
{
QString r;
QRegExp rx("[^a-f]*([a-f]+)[^a-f]*");
rx.setPatternSyntax(QRegExp::RegExp2);
QBENCHMARK{
r = QString(str1).replace(rx, "\\1");
}
QCOMPARE(r, QString("eaeaae"));
}
void tst_qregexp::horribleWrongReplace2()
{
QString r;
QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*");
rx.setPatternSyntax(QRegExp::RegExp2);
QBENCHMARK{
r = QString(str2).replace(rx, "\\1.\\2.\\3");
}
QCOMPARE(r, str2);
}
void tst_qregexp::horribleReplace2()
{
QString r;
QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*");
rx.setPatternSyntax(QRegExp::RegExp2);
QBENCHMARK{
r = QString(str2).replace(rx, "\\1.\\2.\\3");
}
QCOMPARE(r, QString("1.2.3"));
}
void tst_qregexp::simpleFindJSC()
{
int numr;
const char * errmsg=" ";
QString rxs("happy");
JSRegExp *rx = jsRegExpCompile(rxs.utf16(), rxs.length(), JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, 0, &errmsg);
QVERIFY(rx != 0);
QString s(str1);
int offsetVector[3];
QBENCHMARK{
numr = jsRegExpExecute(rx, s.utf16(), s.length(), 0, offsetVector, 3);
}
jsRegExpFree(rx);
QCOMPARE(numr, 1);
QCOMPARE(offsetVector[0], 11);
}
void tst_qregexp::rangeReplaceJSC()
{
QScriptValue r;
QScriptEngine engine;
engine.globalObject().setProperty("s", str1);
QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/[a-f]/g, '-') } )");
QVERIFY(replaceFunc.isFunction());
QBENCHMARK{
r = replaceFunc.call(QScriptValue());
}
QCOMPARE(r.toString(), QString("W- -r- -ll h-ppy monk-ys"));
}
void tst_qregexp::matchReplaceJSC()
{
QScriptValue r;
QScriptEngine engine;
engine.globalObject().setProperty("s", str1);
QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/[^a-f]*([a-f]+)[^a-f]*/g, '$1') } )");
QVERIFY(replaceFunc.isFunction());
QBENCHMARK{
r = replaceFunc.call(QScriptValue());
}
QCOMPARE(r.toString(), QString("eaeaae"));
}
void tst_qregexp::horribleWrongReplaceJSC()
{
QScriptValue r;
QScriptEngine engine;
engine.globalObject().setProperty("s", str2);
QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/.*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*/gm, '$1.$2.$3') } )");
QVERIFY(replaceFunc.isFunction());
QBENCHMARK{
r = replaceFunc.call(QScriptValue());
}
QCOMPARE(r.toString(), str2);
}
void tst_qregexp::horribleReplaceJSC()
{
QScriptValue r;
QScriptEngine engine;
// the m flag doesnt actually work here; dunno
engine.globalObject().setProperty("s", str2.replace('\n', ' '));
QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/.*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*/gm, '$1.$2.$3') } )");
QVERIFY(replaceFunc.isFunction());
QBENCHMARK{
r = replaceFunc.call(QScriptValue());
}
QCOMPARE(r.toString(), QString("1.2.3"));
}
#ifdef HAVE_BOOST
void tst_qregexp::simpleFindBoost(){
int roff;
boost::regex rx ("happy", boost::regex_constants::perl);
std::string s = str1.toStdString();
std::string::const_iterator start, end;
start = s.begin();
end = s.end();
boost::match_flag_type flags = boost::match_default;
QBENCHMARK{
boost::match_results<std::string::const_iterator> what;
regex_search(start, end, what, rx, flags);
roff = (what[0].first)-start;
}
QCOMPARE(roff, 11);
}
void tst_qregexp::rangeReplaceBoost()
{
boost::regex pattern ("[a-f]", boost::regex_constants::perl);
std::string s = str1.toStdString();
std::string r;
QBENCHMARK{
r = boost::regex_replace (s, pattern, "-");
}
QCOMPARE(r, std::string("W- -r- -ll h-ppy monk-ys"));
}
void tst_qregexp::matchReplaceBoost()
{
boost::regex pattern ("[^a-f]*([a-f]+)[^a-f]*",boost::regex_constants::perl);
std::string s = str1.toStdString();
std::string r;
QBENCHMARK{
r = boost::regex_replace (s, pattern, "$1");
}
QCOMPARE(r, std::string("eaeaae"));
}
void tst_qregexp::horribleWrongReplaceBoost()
{
boost::regex pattern (".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*", boost::regex_constants::perl);
std::string s = str2.toStdString();
std::string r;
QBENCHMARK{
r = boost::regex_replace (s, pattern, "$1.$2.$3");
}
QCOMPARE(r, s);
}
void tst_qregexp::horribleReplaceBoost()
{
boost::regex pattern (".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*", boost::regex_constants::perl);
std::string s = str2.toStdString();
std::string r;
QBENCHMARK{
r = boost::regex_replace (s, pattern, "$1.$2.$3");
}
QCOMPARE(r, std::string("1.2.3"));
}
#endif //HAVE_BOOST
QTEST_MAIN(tst_qregexp)
#include "moc_main.cpp"
#include "qrc_qregexp.cpp"

View file

@ -0,0 +1,7 @@
include( $${QT_SOURCE_TREE}/src/3rdparty/webkit/Source/JavaScriptCore/JavaScriptCore.pri )
exists( /usr/include/boost/regex.hpp ){
DEFINES+=HAVE_BOOST
LIBS+=-lboost_regex
}

View file

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>main.cpp</file>
</qresource>
</RCC>

View file

@ -0,0 +1,8 @@
if(NOT KATIE_COMPILER STREQUAL "gcc")
katie_test(tst_bench_qstring
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/data.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fromlatin1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fromutf8.cpp
)
endif()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DATA_H
#define DATA_H
#include <qglobal.h>
struct StringCollection
{
int len;
int offset1, offset2;
ushort align1, align2;
};
extern const ushort stringCollectionData[];
extern const StringCollection stringCollection[];
extern const int stringCollectionCount;
struct StringData
{
const int *entries;
union {
const char *charData;
const ushort *ushortData;
};
int entryCount;
int maxLength;
};
#endif // DATA_H

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,198 @@
#!/usr/bin/perl
## Copyright (C) 2015 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the QtCore module of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL$
## 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 http://www.qt.io/terms-conditions. For further
## information use the contact form at http://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 2.1 or version 3 as published by the Free
## Software Foundation and appearing in the file LICENSE.LGPLv21 and
## LICENSE.LGPLv3 included in the packaging of this file. Please review the
## following information to ensure the GNU Lesser General Public License
## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## As a special exception, The Qt Company gives you certain additional
## rights. These rights are described in The Qt Company LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 3.0 as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL included in the
## packaging of this file. Please review the following information to
## ensure the GNU General Public License version 3.0 requirements will be
## met: http://www.gnu.org/copyleft/gpl.html.
##
## $QT_END_LICENSE$
#
# Parses a file (passed as argument) that contains a dump of pairs of
# strings and generates C source code including said data.
#
# The format of the file is:
# LEN = <len> <keyword> <align1> <align2>\n<data1><data2>\n
# where:
# LEN the literal string "LEN"
# <len> the length of the data, in 16-bit words
# <keyword> the literal string "SAME" or "DIFF"
# <align1> the alignment or pointer value of the first data
# <align2> the alignment or pointer value of the second data
# <data1> the first data
# <data2> the second data
# \n newline
#
# The code to write this data would be:
# fprintf(out, "LEN = %d %s %d %d\n", len,
# (p1 == p2) ? "SAME" : "DIFF",
# uint(quintptr(p1)) & 0xfff, uint(quintptr(p2)) & 0xfff);
# fwrite(p1, 2, len, out);
# fwrite(p2, 2, len, out);
# fwrite("\n", 1, 1, out);
sub printUshortArray($$$) {
$str = $_[0];
$align = $_[1] & 0x1f;
$offset = $_[2];
die if ($align & 1) != 0;
$align /= 2;
$len = (length $str) / 2;
$headpadding = $align & 0x7;
$tailpadding = 8 - (($len + $headpadding) & 0x7);
$multiplecachelines = ($align + $len) > 0x20;
if ($multiplecachelines) {
# if this string crosses into a new cacheline, then
# replicate the result
$headpadding |= ($offset & ~0x1f);
$headpadding += 0x20
if ($headpadding < $offset);
$headpadding -= $offset;
++$cachelinecrosses;
}
for $i (1..$headpadding) {
print 65536-$i,",";
}
print "\n " if ($headpadding > 0);
print " " if ($headpadding == 0);
for ($i = 0; $i < $len * 2; $i += 2) {
print " ", ord(substr($str, $i, 1)) +
ord(substr($str, $i + 1, 1)) * 256,
",";
}
print "\n " if ($tailpadding > 0);
for $i (1..$tailpadding) {
print 65536-$i, ",";
}
print " // ", $offset + $headpadding + $len + $tailpadding;
print "+" if $multiplecachelines;
return ($offset + $headpadding, $offset + $headpadding + $len + $tailpadding);
}
print "// This is a generated file - DO NOT EDIT\n\n";
print "#include \"data.h\"\n\n";
print "const ushort stringCollectionData[] __attribute__((aligned(64))) = {\n";
$count = 0;
$offset = 0;
$totalsize = 0;
$maxlen = 0;
$cachelinecrosses = 0;
open IN, "<" . $ARGV[0];
while (1) {
$line = readline(*IN);
last unless defined($line);
$line =~ /LEN = (\d+) (\w+) (\d+) (\d+)/;
$len = $1;
$data[$count]->{len} = $len;
$sameptr = $2;
$data[$count]->{align1} = $3 - 0;
$data[$count]->{align2} = $4 - 0;
# statistics
$alignhistogram{$3 & 0xf}++;
$alignhistogram{$4 & 0xf}++;
$samealignments{$3 & 0xf}++ if ($3 & 0xf) == ($4 & 0xf);
read IN, $a, $len * 2;
read IN, $b, $len * 2;
<IN>; # Eat the newline
if ($len == 0) {
$data[$count]->{offset1} = $offset;
$data[$count]->{offset2} = $data[$count]->{offset1};
++$data[$count]->{offset2} if ($sameptr eq "DIFF");
} else {
print " // #$count\n";
print " ";
($data[$count]->{offset1}, $offset) =
printUshortArray($a, $data[$count]->{align1}, $offset);
print "\n ";
die if ($offset & 0x7) != 0;
if ($sameptr eq "DIFF") {
($data[$count]->{offset2}, $offset) =
printUshortArray($b, $data[$count]->{align2}, $offset);
print "\n\n";
} else {
$data[$count]->{offset2} = $data[$count]->{offset1};
print "\n\n";
}
}
++$count;
$totalsize += $len;
$maxlen = $len if $len > $maxlen;
}
print "};\n";
close IN;
print "const struct StringCollection stringCollection[] = {\n";
for $i (0..$count-1) {
print " {",
$data[$i]->{len}, ", ",
$data[$i]->{offset1}, ", ",
$data[$i]->{offset2}, ", ",
$data[$i]->{align1}, ", ",
$data[$i]->{align2},
"}, // #$i\n";
next if $data[$i]->{len} == 0;
die if (($data[$i]->{offset1} & 0x7) != ($data[$i]->{align1} & 0xf)/2);
die if (($data[$i]->{offset2} & 0x7) != ($data[$i]->{align2} & 0xf)/2);
}
print "};\n";
print "const int stringCollectionCount = $count;\n";
print "const int stringCollectionMaxLen = $maxlen;\n";
printf "// average comparison length: %.4f\n", ($totalsize * 1.0 / $count);
printf "// cache-line crosses: %d (%.1f%%)\n",
$cachelinecrosses, ($cachelinecrosses * 100.0 / $count / 2);
print "// alignment histogram:\n";
for $key (sort { $a <=> $b } keys(%alignhistogram)) {
$value = $alignhistogram{$key};
$samealigned = $samealignments{$key};
printf "// 0xXXX%x = %d (%.1f%%) strings, %d (%.1f%%) of which same-aligned\n",
$key, $value, $value * 100.0 / ($count*2),
$samealigned, $samealigned * 100.0 / $value;
$samealignedtotal += $samealigned;
}
printf "// total = %d (100%) strings, %d (%.1f%%) of which same-aligned\n",
$count * 2, $samealignedtotal, $samealignedtotal * 100 / $count / 2;

View file

@ -0,0 +1,208 @@
#!/usr/bin/perl
# -*- mode: utf-8; tabs: nil -*-
## Copyright (C) 2015 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the QtCore module of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL$
## 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 http://www.qt.io/terms-conditions. For further
## information use the contact form at http://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 2.1 or version 3 as published by the Free
## Software Foundation and appearing in the file LICENSE.LGPLv21 and
## LICENSE.LGPLv3 included in the packaging of this file. Please review the
## following information to ensure the GNU Lesser General Public License
## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## As a special exception, The Qt Company gives you certain additional
## rights. These rights are described in The Qt Company LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 3.0 as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL included in the
## packaging of this file. Please review the following information to
## ensure the GNU General Public License version 3.0 requirements will be
## met: http://www.gnu.org/copyleft/gpl.html.
##
## $QT_END_LICENSE$
#
# Parses a file (passed as argument) that contains a dump of pairs of
# strings and generates C source code including said data.
#
# The format of the file is:
# LEN = <len> <keyword> <align1> <align2>\n<data1><data2>\n
# where:
# LEN the literal string "LEN"
# <len> the length of the data, in 16-bit words
# <keyword> the literal string "SAME" or "DIFF"
# <align1> the alignment or pointer value of the first data
# <align2> the alignment or pointer value of the second data
# <data1> the first data
# <data2> the second data
# \n newline
#
# The code to write this data would be:
# fprintf(out, "LEN = %d %s %d %d\n", len,
# (p1 == p2) ? "SAME" : "DIFF",
# uint(quintptr(p1)) & 0xfff, uint(quintptr(p2)) & 0xfff);
# fwrite(p1, 2, len, out);
# fwrite(p2, 2, len, out);
# fwrite("\n", 1, 1, out);
sub printCharArray($$$) {
$str = $_[0];
$align = $_[1] & 0x3f;
$offset = $_[2];
$headpadding = $align & 0xf;
$tailpadding = 16 - (($len + $headpadding) & 0xf);
$multiplecachelines = ($align + $len) > 0x40;
if ($multiplecachelines) {
# if this string crosses into a new cacheline, then
# replicate the result
$headpadding |= ($offset & ~0x3f);
$headpadding += 0x40
if ($headpadding < $offset);
$headpadding -= $offset;
++$cachelinecrosses;
}
if ($headpadding > 0) {
print " \"";
for $i (1..$headpadding) {
printf "\\%o", 256-$i;
}
print "\"\n";
}
print " \"";
for ($i = 0; $i < $len; $i++) {
$c = substr($str, $i, 1);
if (ord($c) < 0x20 || ord($c) > 0x7f || $c eq '"' || $c eq '\\') {
printf "\\%o\"\"", ord($c);
} else {
print $c;
}
}
if ($tailpadding > 0) {
print "\"\n \"";
for $i (1..$tailpadding) {
printf "\\%o", 256-$i;
}
}
print "\" // ", $offset + $headpadding + $len + $tailpadding;
print "+" if $multiplecachelines;
print "\n";
return ($offset + $headpadding, $offset + $headpadding + $len + $tailpadding);
}
print "// This is a generated file - DO NOT EDIT\n\n";
print "#include \"data.h\"\n\n";
$varname = shift @ARGV;
print "static const char charData[] __attribute__((aligned(64))) = {\n";
$count = 0;
$offset = 0;
$totalsize = 0;
$maxlen = 0;
$cachelinecrosses = 0;
open IN, "<" . $ARGV[0];
while (1) {
$line = readline(*IN);
last unless defined($line);
$line =~ /LEN = (\d+) (\w+) (\d+) (\d+)/;
$len = $1;
$data[$count]->{len} = $len;
$sameptr = $2;
$data[$count]->{align1} = $3 - 0;
$data[$count]->{align2} = $4 - 0;
# statistics
$alignhistogram{$3 & 0xf}++;
$alignhistogram{$4 & 0xf}++;
$samealignments{$3 & 0xf}++ if ($3 & 0xf) == ($4 & 0xf);
read IN, $a, $len;
read IN, $b, $len;
<IN>; # Eat the newline
if ($len == 0) {
$data[$count]->{offset1} = $offset;
$data[$count]->{offset2} = $data[$count]->{offset1};
++$data[$count]->{offset2} if ($sameptr eq "DIFF");
} else {
print " // #$count\n";
($data[$count]->{offset1}, $offset) =
printCharArray($a, $data[$count]->{align1}, $offset);
die if ($offset & 0xf) != 0;
if ($sameptr eq "DIFF") {
($data[$count]->{offset2}, $offset) =
printCharArray($b, $data[$count]->{align2}, $offset);
} else {
$data[$count]->{offset2} = $data[$count]->{offset1};
}
print "\n";
}
++$count;
$totalsize += $len;
$maxlen = $len if $len > $maxlen;
}
print "};\n";
close IN;
print "static const int intData[] = {\n";
for $i (0..$count-1) {
print " ",
$data[$i]->{len}, ", ",
$data[$i]->{offset1}, ", ",
$data[$i]->{offset2}, ", ",
$data[$i]->{align1}, ", ",
$data[$i]->{align2},
", // #$i\n";
next if $data[$i]->{len} == 0;
die if (($data[$i]->{offset1} & 0xf) != ($data[$i]->{align1} & 0xf));
die if (($data[$i]->{offset2} & 0xf) != ($data[$i]->{align2} & 0xf));
}
print "};\n\n";
print "struct StringData $varname = {\n" .
" intData,\n" .
" { charData },\n" .
" $count, /* entryCount */\n" .
" $maxlen /* maxLength */\n" .
"};\n\n";
printf "// average comparison length: %.4f\n", ($totalsize * 1.0 / $count);
printf "// cache-line crosses: %d (%.1f%%)\n",
$cachelinecrosses, ($cachelinecrosses * 100.0 / $count / 2);
print "// alignment histogram:\n";
for $key (sort { $a <=> $b } keys(%alignhistogram)) {
$value = $alignhistogram{$key};
$samealigned = $samealignments{$key};
printf "// 0xXXX%x = %d (%.1f%%) strings, %d (%.1f%%) of which same-aligned\n",
$key, $value, $value * 100.0 / ($count*2),
$samealigned, $samealigned * 100.0 / $value;
$samealignedtotal += $samealigned;
}
printf "// total = %d (100%) strings, %d (%.1f%%) of which same-aligned\n",
$count * 2, $samealignedtotal, $samealignedtotal * 100 / $count / 2;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
sse4:QMAKE_CXXFLAGS += -msse4
else:ssse3:QMAKE_FLAGS += -mssse3
else:sse2:QMAKE_CXXFLAGS += -msse2
neon:QMAKE_CXXFLAGS += -mfpu=neon

View file

@ -0,0 +1,72 @@
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français
Språk: Norsk
Γλώσσα: Ελληνικά
Язык: Русский
언어 : 한국어
言語: 日本語
Langage : Français

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qstringbuilder
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,433 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// Select one of the scenarios below
#define SCENARIO 1
#if SCENARIO == 1
// this is the "no harm done" version. Only operator% is active,
// with NO_CAST * defined
#define P %
#undef QT_USE_FAST_OPERATOR_PLUS
#undef QT_USE_FAST_CONCATENATION
#define QT_NO_CAST_FROM_ASCII
#define QT_NO_CAST_TO_ASCII
#endif
#if SCENARIO == 2
// this is the "full" version. Operator+ is replaced by a QStringBuilder
// based version
// with NO_CAST * defined
#define P +
#define QT_USE_FAST_OPERATOR_PLUS
#define QT_USE_FAST_CONCATENATION
#define QT_NO_CAST_FROM_ASCII
#define QT_NO_CAST_TO_ASCII
#endif
#if SCENARIO == 3
// this is the "no harm done" version. Only operator% is active,
// with NO_CAST * _not_ defined
#define P %
#undef QT_USE_FAST_OPERATOR_PLUS
#undef QT_USE_FAST_CONCATENATION
#undef QT_NO_CAST_FROM_ASCII
#undef QT_NO_CAST_TO_ASCII
#endif
#if SCENARIO == 4
// this is the "full" version. Operator+ is replaced by a QStringBuilder
// based version
// with NO_CAST * _not_ defined
#define P +
#define QT_USE_FAST_OPERATOR_PLUS
#define QT_USE_FAST_CONCATENATION
#undef QT_NO_CAST_FROM_ASCII
#undef QT_NO_CAST_TO_ASCII
#endif
#include <qbytearray.h>
#include <qdebug.h>
#include <qstring.h>
#include <qstringbuilder.h>
#include <qtest.h>
#include <string>
#define COMPARE(a, b) QCOMPARE(a, b)
//#define COMPARE(a, b)
#define SEP(s) qDebug() << "\n\n-------- " s " ---------";
#define LITERAL "some string literal"
class tst_qstringbuilder : public QObject
{
Q_OBJECT
public:
tst_qstringbuilder()
: l1literal(LITERAL),
l1string(LITERAL),
ba(LITERAL),
string(l1string),
stdstring(LITERAL),
stringref(&string, 2, 10),
achar('c'),
r2(QLatin1String(LITERAL LITERAL)),
r3(QLatin1String(LITERAL LITERAL LITERAL)),
r4(QLatin1String(LITERAL LITERAL LITERAL LITERAL)),
r5(QLatin1String(LITERAL LITERAL LITERAL LITERAL LITERAL))
{}
public:
enum { N = 10000 };
int run_traditional()
{
int s = 0;
for (int i = 0; i < N; ++i) {
#if 0
s += QString(l1string + l1string).size();
s += QString(l1string + l1string + l1string).size();
s += QString(l1string + l1string + l1string + l1string).size();
s += QString(l1string + l1string + l1string + l1string + l1string).size();
#endif
s += QString(achar + l1string + achar).size();
}
return s;
}
int run_builder()
{
int s = 0;
for (int i = 0; i < N; ++i) {
#if 0
s += QString(l1literal P l1literal).size();
s += QString(l1literal P l1literal P l1literal).size();
s += QString(l1literal P l1literal P l1literal P l1literal).size();
s += QString(l1literal P l1literal P l1literal P l1literal P l1literal).size();
#endif
s += QString(achar % l1literal % achar).size();
}
return s;
}
private slots:
void separator_0() {
qDebug() << "\nIn each block the QStringBuilder based result appear first "
"(with a 'b_' prefix), QStringBased second ('q_' prefix), std::string "
"last ('s_' prefix)\n";
}
void separator_1() { SEP("literal + literal (builder first)"); }
void b_2_l1literal() {
QBENCHMARK { r = l1literal P l1literal; }
COMPARE(r, r2);
}
#ifndef QT_NO_CAST_FROM_ASCII
void b_l1literal_LITERAL() {
QBENCHMARK { r = l1literal P LITERAL; }
COMPARE(r, r2);
}
#endif
void q_2_l1string() {
QBENCHMARK { r = l1string + l1string; }
COMPARE(r, r2);
}
void separator_2() { SEP("2 strings"); }
void b_2_string() {
QBENCHMARK { r = string P string; }
COMPARE(r, r2);
}
void q_2_string() {
QBENCHMARK { r = string + string; }
COMPARE(r, r2);
}
void s_2_string() {
QBENCHMARK { stdr = stdstring + stdstring; }
COMPARE(stdr, stdstring + stdstring);
}
void separator_2c() { SEP("2 string refs"); }
void b_2_stringref() {
QBENCHMARK { r = stringref % stringref; }
COMPARE(r, QString(stringref.toString() + stringref.toString()));
}
void q_2_stringref() {
QBENCHMARK { r = stringref.toString() + stringref.toString(); }
COMPARE(r, QString(stringref % stringref));
}
void separator_2b() { SEP("3 strings"); }
void b_3_string() {
QBENCHMARK { r = string P string P string; }
COMPARE(r, r3);
}
void q_3_string() {
QBENCHMARK { r = string + string + string; }
COMPARE(r, r3);
}
void s_3_string() {
QBENCHMARK { stdr = stdstring + stdstring + stdstring; }
COMPARE(stdr, stdstring + stdstring + stdstring);
}
void separator_2e() { SEP("4 strings"); }
void b_4_string() {
QBENCHMARK { r = string P string P string P string; }
COMPARE(r, r4);
}
void q_4_string() {
QBENCHMARK { r = string + string + string + string; }
COMPARE(r, r4);
}
void s_4_string() {
QBENCHMARK { stdr = stdstring + stdstring + stdstring + stdstring; }
COMPARE(stdr, stdstring + stdstring + stdstring + stdstring);
}
void separator_2a() { SEP("string + literal (builder first)"); }
void b_string_l1literal() {
QBENCHMARK { r = string % l1literal; }
COMPARE(r, r2);
}
#ifndef QT_NO_CAST_FROM_ASCII
void b_string_LITERAL() {
QBENCHMARK { r = string P LITERAL; }
COMPARE(r, r2);
}
void b_LITERAL_string() {
QBENCHMARK { r = LITERAL P string; }
COMPARE(r, r2);
}
#endif
void b_string_l1string() {
QBENCHMARK { r = string P l1string; }
COMPARE(r, r2);
}
void q_string_l1literal() {
QBENCHMARK { r = string + l1string; }
COMPARE(r, r2);
}
void q_string_l1string() {
QBENCHMARK { r = string + l1string; }
COMPARE(r, r2);
}
void s_LITERAL_string() {
QBENCHMARK { stdr = LITERAL + stdstring; }
COMPARE(stdr, stdstring + stdstring);
}
void separator_3() { SEP("3 literals"); }
void b_3_l1literal() {
QBENCHMARK { r = l1literal P l1literal P l1literal; }
COMPARE(r, r3);
}
void q_3_l1string() {
QBENCHMARK { r = l1string + l1string + l1string; }
COMPARE(r, r3);
}
void s_3_l1string() {
QBENCHMARK { stdr = stdstring + LITERAL + LITERAL; }
COMPARE(stdr, stdstring + stdstring + stdstring);
}
void separator_4() { SEP("4 literals"); }
void b_4_l1literal() {
QBENCHMARK { r = l1literal P l1literal P l1literal P l1literal; }
COMPARE(r, r4);
}
void q_4_l1string() {
QBENCHMARK { r = l1string + l1string + l1string + l1string; }
COMPARE(r, r4);
}
void separator_5() { SEP("5 literals"); }
void b_5_l1literal() {
QBENCHMARK { r = l1literal P l1literal P l1literal P l1literal P l1literal; }
COMPARE(r, r5);
}
void q_5_l1string() {
QBENCHMARK { r = l1string + l1string + l1string + l1string + l1string; }
COMPARE(r, r5);
}
void separator_6() { SEP("4 chars"); }
void b_string_4_char() {
QBENCHMARK { r = string + achar + achar + achar + achar; }
COMPARE(r, QString(string P achar P achar P achar P achar));
}
void q_string_4_char() {
QBENCHMARK { r = string + achar + achar + achar + achar; }
COMPARE(r, QString(string P achar P achar P achar P achar));
}
void s_string_4_char() {
QBENCHMARK { stdr = stdstring + 'c' + 'c' + 'c' + 'c'; }
COMPARE(stdr, stdstring + 'c' + 'c' + 'c' + 'c');
}
void separator_7() { SEP("char + string + char"); }
void b_char_string_char() {
QBENCHMARK { r = achar + string + achar; }
COMPARE(r, QString(achar P string P achar));
}
void q_char_string_char() {
QBENCHMARK { r = achar + string + achar; }
COMPARE(r, QString(achar P string P achar));
}
void s_char_string_char() {
QBENCHMARK { stdr = 'c' + stdstring + 'c'; }
COMPARE(stdr, 'c' + stdstring + 'c');
}
void separator_8() { SEP("string.arg"); }
void b_string_arg() {
const QString pattern = l1string + QString::fromLatin1("%1") + l1string;
QBENCHMARK { r = l1literal P string P l1literal; }
COMPARE(r, r3);
}
void q_string_arg() {
const QString pattern = l1string + QLatin1String("%1") + l1string;
QBENCHMARK { r = pattern.arg(string); }
COMPARE(r, r3);
}
void q_bytearray_arg() {
QByteArray result;
QBENCHMARK { result = ba + ba + ba; }
}
void separator_9() { SEP("QString::reserve()"); }
void b_reserve() {
QBENCHMARK {
r.clear();
r = string P string P string P string;
}
COMPARE(r, r4);
}
void b_reserve_lit() {
QBENCHMARK {
r.clear();
r = string P l1literal P string P string;
}
COMPARE(r, r4);
}
void s_reserve() {
QBENCHMARK {
r.clear();
r.reserve(string.size() + string.size() + string.size() + string.size());
r += string;
r += string;
r += string;
r += string;
}
COMPARE(r, r4);
}
void s_reserve_lit() {
QBENCHMARK {
r.clear();
//r.reserve(string.size() + qstrlen(l1string.latin1())
// + string.size() + string.size());
r.reserve(1024);
r += string;
r += l1string;
r += string;
r += string;
}
COMPARE(r, r4);
}
private:
const QLatin1Literal l1literal;
const QLatin1String l1string;
const QByteArray ba;
const QString string;
const std::string stdstring;
const QStringRef stringref;
const QLatin1Char achar;
const QString r2, r3, r4, r5;
// short cuts for results
QString r;
std::string stdr;
};
QTEST_MAIN(tst_qstringbuilder)
#include "moc_main.cpp"

View file

@ -0,0 +1 @@
tst_qstringlist

View file

@ -0,0 +1,3 @@
katie_test(tst_bench_qstringlist
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)

View file

@ -0,0 +1,218 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QStringList>
#include <QtTest>
#include <sstream>
#include <string>
#include <vector>
class tst_QStringList: public QObject
{
Q_OBJECT
private slots:
void join() const;
void join_data() const;
void split_qlist_qbytearray() const;
void split_qlist_qbytearray_data() const { return split_data(); }
void split_data() const;
void split_qlist_qstring() const;
void split_qlist_qstring_data() const { return split_data(); }
void split_stdvector_stdstring() const;
void split_stdvector_stdstring_data() const { return split_data(); }
void split_stdvector_stdwstring() const;
void split_stdvector_stdwstring_data() const { return split_data(); }
void split_stdlist_stdstring() const;
void split_stdlist_stdstring_data() const { return split_data(); }
private:
static QStringList populateList(const int count, const QString &unit);
static QString populateString(const int count, const QString &unit);
};
QStringList tst_QStringList::populateList(const int count, const QString &unit)
{
QStringList retval;
for (int i = 0; i < count; ++i)
retval.append(unit);
return retval;
}
QString tst_QStringList::populateString(const int count, const QString &unit)
{
QString retval;
for (int i = 0; i < count; ++i) {
retval.append(unit);
retval.append(QLatin1Char(':'));
}
return retval;
}
void tst_QStringList::join() const
{
QFETCH(QStringList, input);
QFETCH(QString, separator);
QBENCHMARK {
input.join(separator);
}
}
void tst_QStringList::join_data() const
{
QTest::addColumn<QStringList>("input");
QTest::addColumn<QString>("separator");
QTest::newRow("")
<< populateList(100, QLatin1String("unit"))
<< QString();
QTest::newRow("")
<< populateList(1000, QLatin1String("unit"))
<< QString();
QTest::newRow("")
<< populateList(10000, QLatin1String("unit"))
<< QString();
QTest::newRow("")
<< populateList(100000, QLatin1String("unit"))
<< QString();
}
void tst_QStringList::split_data() const
{
QTest::addColumn<QString>("input");
QString unit = QLatin1String("unit") + QString(100, QLatin1Char('s'));
//QTest::newRow("") << populateString(10, unit);
QTest::newRow("") << populateString(100, unit);
//QTest::newRow("") << populateString(100, unit);
//QTest::newRow("") << populateString(1000, unit);
//QTest::newRow("") << populateString(10000, unit);
}
void tst_QStringList::split_qlist_qbytearray() const
{
QFETCH(QString, input);
const char splitChar = ':';
QByteArray ba = input.toLatin1();
QBENCHMARK {
ba.split(splitChar);
}
}
void tst_QStringList::split_qlist_qstring() const
{
QFETCH(QString, input);
const QChar splitChar = ':';
QBENCHMARK {
input.split(splitChar);
}
}
void tst_QStringList::split_stdvector_stdstring() const
{
#ifndef QT_NO_STL
QFETCH(QString, input);
const char split_char = ':';
std::string stdinput = input.toStdString();
QBENCHMARK {
std::istringstream split(stdinput);
std::vector<std::string> token;
for (std::string each;
std::getline(split, each, split_char);
token.push_back(each))
;
}
#endif
}
void tst_QStringList::split_stdvector_stdwstring() const
{
#ifndef QT_NO_STL
QFETCH(QString, input);
const wchar_t split_char = ':';
std::wstring stdinput = input.toStdWString();
QBENCHMARK {
std::wistringstream split(stdinput);
std::vector<std::wstring> token;
for (std::wstring each;
std::getline(split, each, split_char);
token.push_back(each))
;
}
#endif
}
void tst_QStringList::split_stdlist_stdstring() const
{
QFETCH(QString, input);
const char split_char = ':';
std::string stdinput = input.toStdString();
QBENCHMARK {
std::istringstream split(stdinput);
std::list<std::string> token;
for (std::string each;
std::getline(split, each, split_char);
token.push_back(each))
;
}
}
QTEST_MAIN(tst_QStringList)
#include "moc_main.cpp"

View file

@ -0,0 +1,4 @@
katie_test(tst_vector
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/outofline.cpp
)

View file

@ -0,0 +1,390 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QVector>
#include <QDebug>
#include <QtTest>
#include "qrawvector.h"
#include <vector>
/*
Code generated by g++ 4.3.3. The lines marked with '!' are the ones that get
executed inside the loop. Using the external 's' causes some load making the
loop resembling a 'simple inner loop' in 'real' applications.
qvector_mutable_read_access:
.L166:
! movl -16(%ebp), %edx
! movl (%edx), %eax
! subl $1, %eax
! je .L165
movl 4(%edx), %eax
movl %eax, 8(%esp)
movl 8(%edx), %eax
movl %esi, (%esp)
movl %eax, 4(%esp)
call _ZN4myns7QVectorIdE7reallocEii
.L165:
! movl -16(%ebp), %eax
! fldl s
! faddl 16(%eax,%ebx,8)
! addl $1, %ebx
! cmpl $10000, %ebx
! fstpl s
! jne .L166
qvector_const_read_access:
movl -16(%ebp), %edx
xorl %eax, %eax
.L183:
! fldl s
! faddl 16(%edx,%eax,8)
! addl $1, %eax
! cmpl $10000, %eax
! fstpl s
! jne .L183
stdvector_const_read_access and stdvector_mutable_read_access and
qrawvector_const_read_access and qrawvector_mutable_read_access:
xorl %eax, %eax
.L64:
! fldl s
! faddl (%ebx,%eax,8)
! addl $1, %eax
! cmpl $10000, %eax
! fstpl s
! jne .L64
Behaviour varies with small modifications, but total is more or
less stable:
qrawvector_mutable_read_access, using size() instead of N:
.L145:
! faddl (%edx,%eax,8)
! addl $1, %eax
! cmpl %ecx, %eax
! fstl s
! jne .L145
! fstp %st(0)
qrawvector_mutable_read_access, counting backward:
.L145:
! faddl (%edx,%eax,8)
! subl $1, %eax
! cmpl $-1, %eax
! fstl s
! jne .L145
qrawvector_mutable_read_access, counting backward, using size():
.L146:
! faddl (%edx)
! addl $1, %eax
! subl $8, %edx
! cmpl %ecx, %eax
! fstl s
! jne .L146
*/
/*
////////////////////////////////////////////////////////////////////
time ./tst_vector qvector_const_read_access
real 0m12.912s
user 0m12.401s
sys 0m0.016s
time ./tst_vector qvector_mutable_read_access
real 0m38.566s
user 0m36.754s
sys 0m0.008s
time ./tst_vector stdvector_mutable_read_access
real 0m12.736s
user 0m12.665s
sys 0m0.004s
////////////////////////////////////////////////////////////////////
time ./tst_vector qvector_fill_and_return
real 0m28.778s
user 0m28.522s
sys 0m0.012s
time ./tst_vector stdvector_fill_and_return
real 0m26.675s
user 0m26.558s
sys 0m0.012s
time ./tst_vector qrawvector_fill_and_return
real 0m23.370s
user 0m23.269s
sys 0m0.008s
*/
#define TEST_RETURN 1
// For some reason, both 'plain' and '-callgrind' create strange results
// (like varying instruction count for the same assembly code)
// So replace it by a plain loop and measure wall clock time.
//#undef QBENCHMARK
//#define QBENCHMARK for (int j = 0; j != 10000; ++j)
class tst_QVector: public QObject
{
Q_OBJECT
private slots:
void calibration();
// Pure Qt solution
void qvector_separator() { qWarning() << "QVector results: "; }
void qvector_const_read_access();
void qvector_mutable_read_access();
#ifdef TEST_RETURN
void qvector_fill_and_return();
#endif
// Purre Standard solution
void stdvector() { qWarning() << "std::vector results: "; }
void stdvector_const_read_access();
void stdvector_mutable_read_access();
#ifdef TEST_RETURN
void stdvector_fill_and_return();
#endif
// Build using std, pass as QVector
void mixedvector() { qWarning() << "mixed results: "; }
#ifdef TEST_RETURN
void mixedvector_fill_and_return();
#endif
// Alternative implementation
void qrawvector_separator() { qWarning() << "QRawVector results: "; }
void qrawvector_const_read_access();
void qrawvector_mutable_read_access();
#ifdef TEST_RETURN
void qrawvector_fill_and_return();
#endif
};
const int N = 1000000;
extern double s;
void tst_QVector::calibration()
{
QVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += i;
}
}
///////////////////// QVector /////////////////////
void tst_QVector::qvector_const_read_access()
{
QVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
const QVector<double> &vc = v;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += vc[i];
}
}
void tst_QVector::qvector_mutable_read_access()
{
QVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += v[i];
}
}
#ifdef TEST_RETURN
extern QVector<double> qvector_fill_and_return_helper();
void tst_QVector::qvector_fill_and_return()
{
QBENCHMARK {
QVector<double> v = qvector_fill_and_return_helper();
s += v[1];
}
}
#endif
///////////////////// QRawVector /////////////////////
void tst_QVector::qrawvector_const_read_access()
{
QRawVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
const QRawVector<double> &vc = v;
QBENCHMARK {
for (int i = vc.size(); --i >= 0;)
s += vc[i];
}
}
void tst_QVector::qrawvector_mutable_read_access()
{
QRawVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += v[i];
}
}
#ifdef TEST_RETURN
extern QVector<double> qrawvector_fill_and_return_helper();
void tst_QVector::qrawvector_fill_and_return()
{
QBENCHMARK {
QVector<double> v = qrawvector_fill_and_return_helper();
s += v[1];
}
}
#endif
///////////////////// std::vector /////////////////////
void tst_QVector::stdvector_const_read_access()
{
std::vector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
const std::vector<double> &vc = v;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += vc[i];
}
}
void tst_QVector::stdvector_mutable_read_access()
{
std::vector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i != N; ++i)
s += v[i];
}
}
#ifdef TEST_RETURN
extern std::vector<double> stdvector_fill_and_return_helper();
void tst_QVector::stdvector_fill_and_return()
{
QBENCHMARK {
std::vector<double> v = stdvector_fill_and_return_helper();
s += v[1];
}
}
#endif
///////////////////// mixed vector /////////////////////
#ifdef TEST_RETURN
extern QVector<double> mixedvector_fill_and_return_helper();
void tst_QVector::mixedvector_fill_and_return()
{
QBENCHMARK {
std::vector<double> v = stdvector_fill_and_return_helper();
s += v[1];
}
}
#endif
QTEST_MAIN(tst_QVector)
#include "moc_main.cpp"

View file

@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtTest module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QVector>
#include <vector>
#include "qrawvector.h"
const int N = 1000000;
double s = 0;
QVector<double> qvector_fill_and_return_helper()
{
QVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
return v;
}
QVector<double> qrawvector_fill_and_return_helper()
{
QRawVector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
return v.mutateToVector();
}
QVector<double> mixedvector_fill_and_return_helper()
{
std::vector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
return QVector<double>::fromStdVector(v);
}
std::vector<double> stdvector_fill_and_return_helper()
{
std::vector<double> v(N);
for (int i = 0; i != N; ++i)
v[i] = i;
return v;
}

View file

@ -0,0 +1,738 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QRAWVECTOR_H
#define QRAWVECTOR_H
#include <QtCore/qiterator.h>
#include <QtCore/qdebug.h>
#include <QtCore/qatomic.h>
#include <QtCore/qalgorithms.h>
#include <QtCore/qlist.h>
#ifndef QT_NO_STL
#include <iterator>
#include <vector>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
template <typename T>
class QRawVector
{
struct Data : QVectorData { T array[1]; };
T *m_begin;
int m_size;
int m_alloc;
public:
//static Data dummy;
//int headerOffset() { return (char*)&dummy.array - (char*)&dummy; }
inline int headerOffset() const {
// gcc complains about: return offsetof(Data, array); and also
// does not like '0' in the expression below.
return (char *)&(((Data *)(1))->array) - (char *)1;
}
inline Data *toBase(T *begin) const
{ return (Data*)((char*)begin - headerOffset()); }
inline T *fromBase(void *d) const
{ return (T*)((char*)d + headerOffset()); }
inline QRawVector()
{ m_begin = fromBase(0); m_alloc = m_size = 0; realloc(m_size, m_alloc, true); }
explicit QRawVector(int size);
QRawVector(int size, const T &t);
inline QRawVector(const QRawVector<T> &v)
{ m_begin = v.m_begin; m_alloc = v.m_alloc; m_size = v.m_size; realloc(m_size, m_alloc, true); }
inline ~QRawVector() { free(m_begin, m_size); }
QRawVector<T> &operator=(const QRawVector<T> &v);
bool operator==(const QRawVector<T> &v) const;
inline bool operator!=(const QRawVector<T> &v) const { return !(*this == v); }
inline int size() const { return m_size; }
inline bool isEmpty() const { return m_size == 0; }
void resize(int size);
inline int capacity() const { return m_alloc; }
void reserve(int size);
inline void squeeze() { realloc(m_size, m_size, false); }
inline T *data() { return m_begin; }
inline const T *data() const { return m_begin; }
inline const T *constData() const { return m_begin; }
void clear();
const T &at(int i) const;
T &operator[](int i);
const T &operator[](int i) const;
void append(const T &t);
void prepend(const T &t);
void insert(int i, const T &t);
void insert(int i, int n, const T &t);
void replace(int i, const T &t);
void remove(int i);
void remove(int i, int n);
QRawVector<T> &fill(const T &t, int size = -1);
int indexOf(const T &t, int from = 0) const;
int lastIndexOf(const T &t, int from = -1) const;
bool contains(const T &t) const;
int count(const T &t) const;
#ifdef QT_STRICT_ITERATORS
class iterator {
public:
T *i;
typedef std::random_access_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T *pointer;
typedef T &reference;
inline iterator() : i(0) {}
inline iterator(T *n) : i(n) {}
inline iterator(const iterator &o): i(o.i){}
inline T &operator*() const { return *i; }
inline T *operator->() const { return i; }
inline T &operator[](int j) const { return *(i + j); }
inline bool operator==(const iterator &o) const { return i == o.i; }
inline bool operator!=(const iterator &o) const { return i != o.i; }
inline bool operator<(const iterator& other) const { return i < other.i; }
inline bool operator<=(const iterator& other) const { return i <= other.i; }
inline bool operator>(const iterator& other) const { return i > other.i; }
inline bool operator>=(const iterator& other) const { return i >= other.i; }
inline iterator &operator++() { ++i; return *this; }
inline iterator operator++(int) { T *n = i; ++i; return n; }
inline iterator &operator--() { i--; return *this; }
inline iterator operator--(int) { T *n = i; i--; return n; }
inline iterator &operator+=(int j) { i+=j; return *this; }
inline iterator &operator-=(int j) { i-=j; return *this; }
inline iterator operator+(int j) const { return iterator(i+j); }
inline iterator operator-(int j) const { return iterator(i-j); }
inline int operator-(iterator j) const { return i - j.i; }
};
friend class iterator;
class const_iterator {
public:
T *i;
typedef std::random_access_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef const T *pointer;
typedef const T &reference;
inline const_iterator() : i(0) {}
inline const_iterator(T *n) : i(n) {}
inline const_iterator(const const_iterator &o): i(o.i) {}
inline explicit const_iterator(const iterator &o): i(o.i) {}
inline const T &operator*() const { return *i; }
inline const T *operator->() const { return i; }
inline const T &operator[](int j) const { return *(i + j); }
inline bool operator==(const const_iterator &o) const { return i == o.i; }
inline bool operator!=(const const_iterator &o) const { return i != o.i; }
inline bool operator<(const const_iterator& other) const { return i < other.i; }
inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
inline bool operator>(const const_iterator& other) const { return i > other.i; }
inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
inline const_iterator &operator++() { ++i; return *this; }
inline const_iterator operator++(int) { T *n = i; ++i; return n; }
inline const_iterator &operator--() { i--; return *this; }
inline const_iterator operator--(int) { T *n = i; i--; return n; }
inline const_iterator &operator+=(int j) { i+=j; return *this; }
inline const_iterator &operator-=(int j) { i+=j; return *this; }
inline const_iterator operator+(int j) const { return const_iterator(i+j); }
inline const_iterator operator-(int j) const { return const_iterator(i-j); }
inline int operator-(const_iterator j) const { return i - j.i; }
};
friend class const_iterator;
#else
// STL-style
typedef T *iterator;
typedef const T *const_iterator;
#endif
inline iterator begin() { return m_begin; }
inline const_iterator begin() const { return m_begin; }
inline const_iterator constBegin() const { return m_begin; }
inline iterator end() { return m_begin + m_size; }
inline const_iterator end() const { return m_begin + m_size; }
inline const_iterator constEnd() const { return m_begin + m_size; }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
inline iterator erase(iterator pos) { return erase(pos, pos+1); }
// more Qt
inline int count() const { return m_size; }
inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
QRawVector<T> mid(int pos, int length = -1) const;
T value(int i) const;
T value(int i, const T &defaultValue) const;
// STL compatibility
typedef T value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef ptrdiff_t difference_type;
typedef iterator Iterator;
typedef const_iterator ConstIterator;
typedef int size_type;
inline void push_back(const T &t) { append(t); }
inline void push_front(const T &t) { prepend(t); }
void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
inline bool empty() const { return m_size == 0; }
inline T &front() { return first(); }
inline const_reference front() const { return first(); }
inline reference back() { return last(); }
inline const_reference back() const { return last(); }
// comfort
QRawVector<T> &operator+=(const QRawVector<T> &l);
inline QRawVector<T> operator+(const QRawVector<T> &l) const
{ QRawVector n = *this; n += l; return n; }
inline QRawVector<T> &operator+=(const T &t)
{ append(t); return *this; }
inline QRawVector<T> &operator<< (const T &t)
{ append(t); return *this; }
inline QRawVector<T> &operator<<(const QRawVector<T> &l)
{ *this += l; return *this; }
QList<T> toList() const;
//static QRawVector<T> fromList(const QList<T> &list);
#ifndef QT_NO_STL
static inline QRawVector<T> fromStdVector(const std::vector<T> &vector)
{ QRawVector<T> tmp; qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
inline std::vector<T> toStdVector() const
{ std::vector<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
#endif
private:
T *allocate(int alloc);
void realloc(int size, int alloc, bool ref);
void free(T *begin, int size);
int sizeOfTypedData() {
// this is more or less the same as sizeof(Data), except that it doesn't
// count the padding at the end
return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
}
static inline int alignOfTypedData()
{
#ifdef Q_ALIGNOF
return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
#else
return 0;
#endif
}
public:
QVector<T> mutateToVector()
{
Data *d = toBase(m_begin);
d->ref = 1;
d->alloc = m_alloc;
d->size = m_size;
d->sharable = 0;
d->capacity = 0;
QVector<T> v;
*reinterpret_cast<QVectorData **>(&v) = d;
m_begin = fromBase(0);
m_size = m_alloc = 0;
return v;
}
};
template <typename T>
void QRawVector<T>::reserve(int asize)
{ if (asize > m_alloc) realloc(m_size, asize, false); }
template <typename T>
void QRawVector<T>::resize(int asize)
{ realloc(asize, (asize > m_alloc || (asize < m_size && asize < (m_alloc >> 1)))
? QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
: m_alloc, false); }
template <typename T>
inline void QRawVector<T>::clear()
{ *this = QRawVector<T>(); }
template <typename T>
inline const T &QRawVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::at", "index out of range");
return m_begin[i]; }
template <typename T>
inline const T &QRawVector<T>::operator[](int i) const
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::operator[]", "index out of range");
return m_begin[i]; }
template <typename T>
inline T &QRawVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::operator[]", "index out of range");
return data()[i]; }
template <typename T>
inline void QRawVector<T>::insert(int i, const T &t)
{ Q_ASSERT_X(i >= 0 && i <= m_size, "QRawVector<T>::insert", "index out of range");
insert(begin() + i, 1, t); }
template <typename T>
inline void QRawVector<T>::insert(int i, int n, const T &t)
{ Q_ASSERT_X(i >= 0 && i <= m_size, "QRawVector<T>::insert", "index out of range");
insert(begin() + i, n, t); }
template <typename T>
inline void QRawVector<T>::remove(int i, int n)
{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= m_size, "QRawVector<T>::remove", "index out of range");
erase(begin() + i, begin() + i + n); }
template <typename T>
inline void QRawVector<T>::remove(int i)
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::remove", "index out of range");
erase(begin() + i, begin() + i + 1); }
template <typename T>
inline void QRawVector<T>::prepend(const T &t)
{ insert(begin(), 1, t); }
template <typename T>
inline void QRawVector<T>::replace(int i, const T &t)
{
Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::replace", "index out of range");
const T copy(t);
data()[i] = copy;
}
template <typename T>
QRawVector<T> &QRawVector<T>::operator=(const QRawVector<T> &v)
{
if (this != &v) {
free(m_begin, m_size);
m_alloc = v.m_alloc;
m_size = v.m_size;
m_begin = v.m_begin;
realloc(m_size, m_alloc, true);
}
return *this;
}
template <typename T>
inline T *QRawVector<T>::allocate(int aalloc)
{
QVectorData *d = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(d);
return fromBase(d);
}
template <typename T>
QRawVector<T>::QRawVector(int asize)
{
m_size = m_alloc = asize;
m_begin = allocate(asize);
if (QTypeInfo<T>::isComplex) {
T *b = m_begin;
T *i = m_begin + m_size;
while (i != b)
new (--i) T;
} else {
qMemSet(m_begin, 0, asize * sizeof(T));
}
}
template <typename T>
QRawVector<T>::QRawVector(int asize, const T &t)
{
m_size = m_alloc = asize;
m_begin = allocate(asize);
T *i = m_begin + m_size;
while (i != m_begin)
new (--i) T(t);
}
template <typename T>
void QRawVector<T>::free(T *begin, int size)
{
if (QTypeInfo<T>::isComplex) {
T *i = begin + size;
while (i-- != begin)
i->~T();
}
Data *x = toBase(begin);
x->free(x, alignOfTypedData());
}
template <typename T>
void QRawVector<T>::realloc(int asize, int aalloc, bool ref)
{
if (QTypeInfo<T>::isComplex && asize < m_size && !ref) {
// call the destructor on all objects that need to be
// destroyed when shrinking
T *pOld = m_begin + m_size;
while (asize < m_size) {
(--pOld)->~T();
--m_size;
}
}
int xalloc = m_alloc;
int xsize = m_size;
bool changed = false;
T *xbegin = m_begin;
if (aalloc != xalloc || ref) {
// (re)allocate memory
if (QTypeInfo<T>::isStatic) {
xbegin = allocate(aalloc);
xsize = 0;
changed = true;
} else if (ref) {
xbegin = allocate(aalloc);
if (QTypeInfo<T>::isComplex) {
xsize = 0;
} else {
::memcpy(xbegin, m_begin, qMin(aalloc, xalloc) * sizeof(T));
xsize = m_size;
}
changed = true;
} else {
QT_TRY {
QVectorData *mem = QVectorData::reallocate(
toBase(m_begin), sizeOfTypedData() + (aalloc - 1) * sizeof(T),
sizeOfTypedData()
+ (xalloc - 1) * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(mem);
xbegin = fromBase(mem);
xsize = m_size;
} QT_CATCH (const std::bad_alloc &) {
if (aalloc > xalloc) // ignore the error in case we are just shrinking.
QT_RETHROW;
}
}
xalloc = aalloc;
}
if (QTypeInfo<T>::isComplex) {
QT_TRY {
T *pOld = m_begin + xsize;
T *pNew = xbegin + xsize;
// copy objects from the old array into the new array
while (xsize < qMin(asize, m_size)) {
new (pNew++) T(*pOld++);
++xsize;
}
// construct all new objects when growing
while (xsize < asize) {
new (pNew++) T;
++xsize;
}
} QT_CATCH (...) {
free(xbegin, xsize);
QT_RETHROW;
}
} else if (asize > xsize) {
// initialize newly allocated memory to 0
qMemSet(xbegin + xsize, 0, (asize - xsize) * sizeof(T));
}
xsize = asize;
if (changed) {
if (!ref)
free(m_begin, m_size);
}
m_alloc = xalloc;
m_size = xsize;
m_begin = xbegin;
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QRawVector<T>::value(int i) const
{
return (i < 0 || i >= m_size) ? T() : m_begin[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QRawVector<T>::value(int i, const T &defaultValue) const
{
return (i < 0 || i >= m_size) ? defaultValue : m_begin[i];
}
template <typename T>
void QRawVector<T>::append(const T &t)
{
if (m_size + 1 > m_alloc) {
const T copy(t);
realloc(m_size, QVectorData::grow(sizeOfTypedData(), m_size + 1, sizeof(T),
QTypeInfo<T>::isStatic), false);
if (QTypeInfo<T>::isComplex)
new (m_begin + m_size) T(copy);
else
m_begin[m_size] = copy;
} else {
if (QTypeInfo<T>::isComplex)
new (m_begin + m_size) T(t);
else
m_begin[m_size] = t;
}
++m_size;
}
template <typename T>
Q_TYPENAME QRawVector<T>::iterator QRawVector<T>::insert(iterator before, size_type n, const T &t)
{
int offset = int(before - m_begin);
if (n != 0) {
const T copy(t);
if (m_size + n > m_alloc)
realloc(m_size, QVectorData::grow(sizeOfTypedData(), m_size + n, sizeof(T),
QTypeInfo<T>::isStatic), false);
if (QTypeInfo<T>::isStatic) {
T *b = m_begin + m_size;
T *i = m_begin + m_size + n;
while (i != b)
new (--i) T;
i = m_begin + m_size;
T *j = i + n;
b = m_begin + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
T *b = m_begin + offset;
T *i = b + n;
memmove(i, b, (m_size - offset) * sizeof(T));
while (i != b)
new (--i) T(copy);
}
m_size += n;
}
return m_begin + offset;
}
template <typename T>
Q_TYPENAME QRawVector<T>::iterator QRawVector<T>::erase(iterator abegin, iterator aend)
{
int f = int(abegin - m_begin);
int l = int(aend - m_begin);
int n = l - f;
if (QTypeInfo<T>::isComplex) {
qCopy(m_begin + l, m_begin + m_size, m_begin + f);
T *i = m_begin + m_size;
T *b = m_begin + m_size - n;
while (i != b) {
--i;
i->~T();
}
} else {
memmove(m_begin + f, m_begin + l, (m_size - l) * sizeof(T));
}
m_size -= n;
return m_begin + f;
}
template <typename T>
bool QRawVector<T>::operator==(const QRawVector<T> &v) const
{
if (m_size != v.m_size)
return false;
T* b = m_begin;
T* i = b + m_size;
T* j = v.m_begin + m_size;
while (i != b)
if (!(*--i == *--j))
return false;
return true;
}
template <typename T>
QRawVector<T> &QRawVector<T>::fill(const T &from, int asize)
{
const T copy(from);
resize(asize < 0 ? m_size : asize);
if (m_size) {
T *i = m_begin + m_size;
T *b = m_begin;
while (i != b)
*--i = copy;
}
return *this;
}
template <typename T>
QRawVector<T> &QRawVector<T>::operator+=(const QRawVector &l)
{
int newSize = m_size + l.m_size;
realloc(m_size, newSize, false);
T *w = m_begin + newSize;
T *i = l.m_begin + l.m_size;
T *b = l.m_begin;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
else
*--w = *--i;
}
m_size = newSize;
return *this;
}
template <typename T>
int QRawVector<T>::indexOf(const T &t, int from) const
{
if (from < 0)
from = qMax(from + m_size, 0);
if (from < m_size) {
T* n = m_begin + from - 1;
T* e = m_begin + m_size;
while (++n != e)
if (*n == t)
return n - m_begin;
}
return -1;
}
template <typename T>
int QRawVector<T>::lastIndexOf(const T &t, int from) const
{
if (from < 0)
from += m_size;
else if (from >= m_size)
from = m_size-1;
if (from >= 0) {
T* b = m_begin;
T* n = m_begin + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
}
}
return -1;
}
template <typename T>
bool QRawVector<T>::contains(const T &t) const
{
T* b = m_begin;
T* i = m_begin + m_size;
while (i != b)
if (*--i == t)
return true;
return false;
}
template <typename T>
int QRawVector<T>::count(const T &t) const
{
int c = 0;
T* b = m_begin;
T* i = m_begin + m_size;
while (i != b)
if (*--i == t)
++c;
return c;
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QRawVector<T> QRawVector<T>::mid(int pos, int length) const
{
if (length < 0)
length = size() - pos;
if (pos == 0 && length == size())
return *this;
QRawVector<T> copy;
if (pos + length > size())
length = size() - pos;
for (int i = pos; i < pos + length; ++i)
copy += at(i);
return copy;
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QRawVector<T>::toList() const
{
QList<T> result;
for (int i = 0; i < size(); ++i)
result.append(at(i));
return result;
}
/*template <typename T>
Q_OUTOFLINE_TEMPLATE QRawVector<T> QList<T>::toVector() const
{
QRawVector<T> result(size());
for (int i = 0; i < size(); ++i)
result[i] = at(i);
return result;
}
template <typename T>
QRawVector<T> QRawVector<T>::fromList(const QList<T> &list)
{
return list.toVector();
}
template <typename T>
QList<T> QList<T>::fromVector(const QRawVector<T> &vector)
{
return vector.toList();
}
*/
Q_DECLARE_SEQUENTIAL_ITERATOR(RawVector)
Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(RawVector)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QRAWVECTOR_H

View file

@ -0,0 +1,2 @@
tst_qdbusperformance
server/server

View file

@ -0,0 +1,16 @@
if(WITH_DBUS AND DBUS_FOUND)
katie_test(tst_qdbusperformance
${CMAKE_CURRENT_SOURCE_DIR}/tst_qdbusperformance.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serverobject.h
)
target_link_libraries(tst_qdbusperformance KtDBus)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_executable(server
${CMAKE_CURRENT_SOURCE_DIR}/server/server.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serverobject.h
)
target_link_libraries(server KtDBus)
endif()

View file

@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtDBus/QtDBus>
#include "../serverobject.h"
static const char serviceName[] = "com.trolltech.autotests.performance";
static const char objectPath[] = "/";
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QDBusConnection con = QDBusConnection::sessionBus();
if (!con.isConnected())
exit(1);
if (!con.registerService(serviceName))
exit(2);
ServerObject obj(objectPath, con);
printf("ready.\n");
return app.exec();
}
#include "moc_serverobject.h"

View file

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SERVEROBJECT_H
#define SERVEROBJECT_H
#include <QObject>
#include <QtDBus/QtDBus>
class ServerObject: public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.Performance")
public:
ServerObject(const QString &objectPath, QDBusConnection conn, QObject *parent = 0)
: QObject(parent)
{
conn.registerObject(objectPath, this, QDBusConnection::ExportAllSlots);
}
public slots:
Q_NOREPLY void noReply(const QByteArray &)
{
// black hole
}
Q_NOREPLY void noReply(const QString &)
{
// black hole
}
Q_NOREPLY void noReply(const QDBusVariant &)
{
// black hole
}
int size(const QByteArray &data)
{
return data.size();
}
int size(const QString &data)
{
return data.size();
}
int size(const QDBusVariant &data)
{
QVariant v = data.variant();
switch (v.type())
{
case QVariant::ByteArray:
return v.toByteArray().size();
case QVariant::StringList:
return v.toStringList().size();
case QVariant::String:
default:
return v.toString().size();
}
}
QByteArray echo(const QByteArray &data)
{
return data;
}
QString echo(const QString &data)
{
return data;
}
QDBusVariant echo(const QDBusVariant &data)
{
return data;
}
void nothing()
{
}
};
#endif

View file

@ -0,0 +1,232 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>
#include <QtDBus/QtDBus>
#include "./serverobject.h"
static const char serviceName[] = "com.trolltech.autotests.performance";
static const int runTime = 500;
class tst_QDBusPerformance: public QObject
{
Q_OBJECT
QProcess proc;
QDBusInterface *target;
QDBusInterface *remote;
QDBusInterface *local;
bool executeTest(const char *funcname, int size, const QVariant &data);
public slots:
void initTestCase_data();
void initTestCase();
void init();
private slots:
void callSpeed();
void oneWay_data();
void oneWay();
void oneWayVariant_data();
void oneWayVariant();
void roundTrip_data();
void roundTrip();
void roundTripVariant_data();
void roundTripVariant();
};
Q_DECLARE_METATYPE(QVariant)
void tst_QDBusPerformance::initTestCase()
{
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
QDBusServiceWatcher watcher(serviceName, con,
QDBusServiceWatcher::WatchForRegistration);
connect(&watcher, SIGNAL(serviceRegistered(QString)),
&QTestEventLoop::instance(), SLOT(exitLoop()));
#ifdef Q_OS_WIN
proc.start("server");
#else
proc.start("./server/server");
#endif
QVERIFY(proc.waitForStarted());
QTestEventLoop::instance().enterLoop(5);
QVERIFY(con.interface()->isServiceRegistered(serviceName));
remote = new QDBusInterface(serviceName, "/", "com.trolltech.autotests.Performance", con, this);
QVERIFY(remote->isValid());
new ServerObject("/", con, this);
local = new QDBusInterface(con.baseService(), "/", "com.trolltech.autotests.Performance", con, this);
QVERIFY(local->isValid());
}
void tst_QDBusPerformance::initTestCase_data()
{
QTest::addColumn<bool>("loopback");
QTest::newRow("normal") << false;
QTest::newRow("loopback") << true;
}
void tst_QDBusPerformance::init()
{
QFETCH_GLOBAL(bool, loopback);
if (loopback)
target = local;
else
target = remote;
}
void tst_QDBusPerformance::callSpeed()
{
QElapsedTimer timer;
int callCount = 0;
timer.start();
while (timer.elapsed() < runTime) {
QDBusReply<void> reply = target->call("nothing");
QVERIFY(reply.isValid());
++callCount;
}
qDebug() << callCount << "calls in" << timer.elapsed() << "ms:"
<< (callCount * 1000.0 / timer.elapsed()) << "calls/sec";
}
bool tst_QDBusPerformance::executeTest(const char *funcname, int size, const QVariant &data)
{
QElapsedTimer timer;
int callCount = 0;
qint64 transferred = 0;
timer.start();
while (timer.elapsed() < runTime) {
QDBusMessage reply = target->call(funcname, data);
if (reply.type() != QDBusMessage::ReplyMessage)
return false;
transferred += size;
++callCount;
}
qDebug() << transferred << "bytes in" << timer.elapsed() << "ms"
<< "(in" << callCount << "calls):"
<< (transferred * 1000.0 / timer.elapsed() / 1024 / 1024) << "MB/s";
return true;
}
void tst_QDBusPerformance::oneWay_data()
{
QTest::addColumn<QVariant>("data");
QTest::addColumn<int>("size");
QByteArray ba(256, 'a');
while (ba.size() < 8193) {
QTest::newRow(QString("%1-byteArray").arg(ba.size()).toAscii()) << qVariantFromValue(ba) << ba.size();
ba += ba;
}
QString s(256, QLatin1Char('a'));
while (s.size() < 8193) {
QTest::newRow(QString("%1-string").arg(s.size()).toAscii()) << qVariantFromValue(s) << s.size();
s += s;
}
}
void tst_QDBusPerformance::oneWay()
{
QFETCH(QVariant, data);
QFETCH(int, size);
QVERIFY(executeTest("size", size, data));
}
void tst_QDBusPerformance::oneWayVariant_data()
{
oneWay_data();
}
void tst_QDBusPerformance::oneWayVariant()
{
QFETCH(QVariant, data);
QFETCH(int, size);
QVERIFY(executeTest("size", size, qVariantFromValue(QDBusVariant(data))));
}
void tst_QDBusPerformance::roundTrip_data()
{
oneWay_data();
}
void tst_QDBusPerformance::roundTrip()
{
QFETCH(QVariant, data);
QFETCH(int, size);
QVERIFY(executeTest("echo", size, data));
}
void tst_QDBusPerformance::roundTripVariant_data()
{
oneWay_data();
}
void tst_QDBusPerformance::roundTripVariant()
{
QFETCH(QVariant, data);
QFETCH(int, size);
QVERIFY(executeTest("echo", size, qVariantFromValue(QDBusVariant(data))));
}
QTEST_MAIN(tst_QDBusPerformance)
#include "moc_tst_qdbusperformance.cpp"
#include "moc_serverobject.h"

View file

@ -0,0 +1,8 @@
if(WITH_DBUS AND DBUS_FOUND)
katie_test(tst_bench_qdbustype
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
target_link_libraries(tst_bench_qdbustype KtDBus)
include_directories(${DBUS_INCLUDES})
endif()

View file

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>
#include <QtDBus/qdbusutil_p.h>
#include <dbus/dbus.h>
class tst_QDBusType: public QObject
{
Q_OBJECT
private Q_SLOTS:
void benchmarkSignature_data();
void benchmarkSignature();
};
static inline void benchmarkAddRow(const char *name, const char *data)
{
QTest::newRow(QByteArray("native-") + name) << data << true;
QTest::newRow(name) << data << false;
}
void tst_QDBusType::benchmarkSignature_data()
{
QTest::addColumn<QString>("data");
QTest::addColumn<bool>("useNative");
for (int loopCount = 0; loopCount < 2; ++loopCount) {
bool useNative = loopCount;
QByteArray prefix = useNative ? "native-" : "";
benchmarkAddRow("single-invalid", "~");
benchmarkAddRow("single-invalid-array", "a~");
benchmarkAddRow("single-invalid-struct", "(.)");
benchmarkAddRow("single-char", "b");
benchmarkAddRow("single-array", "as");
benchmarkAddRow("single-simplestruct", "(y)");
benchmarkAddRow("single-simpledict", "a{sv}");
benchmarkAddRow("single-complexdict", "a{s(aya{io})}");
benchmarkAddRow("multiple-char", "ssg");
benchmarkAddRow("multiple-arrays", "asasay");
benchmarkAddRow("struct-missingclose", "(ayyyy");
benchmarkAddRow("longstruct", "(yyyyyyayasy)");
benchmarkAddRow("invalid-longstruct", "(yyyyyyayas.y)");
benchmarkAddRow("complexstruct", "(y(aasay)oga{sv})");
benchmarkAddRow("multiple-simple-structs", "(y)(y)(y)");
}
}
void tst_QDBusType::benchmarkSignature()
{
QFETCH(QString, data);
QFETCH(bool, useNative);
bool result;
if (useNative) {
dbus_signature_validate(data.toLatin1(), 0);
QBENCHMARK {
result = dbus_signature_validate(data.toLatin1(), 0);
}
} else {
QDBusUtil::isValidSignature(data);
QBENCHMARK {
result = QDBusUtil::isValidSignature(data);
}
}
Q_UNUSED(result);
}
QTEST_MAIN(tst_QDBusType)
#include "moc_main.cpp"

Some files were not shown because too many files have changed in this diff Show more