summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp34
-rw-r--r--tests/auto/corelib/io/qfileselector/platforms/+haiku/test0
-rw-r--r--tests/auto/corelib/io/qfileselector/platforms/+haiku/test20
-rw-r--r--tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test0
-rw-r--r--tests/auto/corelib/io/qfileselector/qfileselector.qrc3
-rw-r--r--tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp3
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp15
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp6
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp37
-rw-r--r--tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp42
-rw-r--r--tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp45
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp85
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp158
-rw-r--r--tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp53
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp46
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp23
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp15
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h1
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm341
20 files changed, 780 insertions, 129 deletions
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 32344f1e26..1b7d410beb 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -49,6 +49,7 @@ private slots:
void debugWithBool() const;
void debugSpaceHandling() const;
void debugNoQuotes() const;
+ void verbosity() const;
void stateSaver() const;
void veryLongWarningMessage() const;
void qDebugQChar() const;
@@ -192,7 +193,11 @@ public:
QDebug operator<< (QDebug s, const MyLine& line)
{
const QDebugStateSaver saver(s);
- s.nospace() << "MyLine(" << line.p1 << ", " << line.p2 << ")";
+ s.nospace();
+ s << "MyLine(" << line.p1 << ", "<< line.p2;
+ if (s.verbosity() > 2)
+ s << ", Manhattan length=" << (qAbs(line.p2.v1 - line.p1.v1) + qAbs(line.p2.v2 - line.p1.v2));
+ s << ')';
return s;
}
@@ -255,6 +260,33 @@ void tst_QDebug::debugNoQuotes() const
QCOMPARE(s_msg, QString::fromLatin1("'H' \"Hello\" \"Hello\" H Hello Hello"));
}
+void tst_QDebug::verbosity() const
+{
+ MyLine line(MyPoint(10, 11), MyPoint (12, 13));
+ QString output;
+ QDebug d(&output);
+ d.nospace();
+ d << line << '\n';
+ const int oldVerbosity = d.verbosity();
+ d.setVerbosity(0);
+ QCOMPARE(d.verbosity(), 0);
+ d.setVerbosity(7);
+ QCOMPARE(d.verbosity(), 7);
+ const int newVerbosity = oldVerbosity + 2;
+ d.setVerbosity(newVerbosity);
+ QCOMPARE(d.verbosity(), newVerbosity);
+ d << line << '\n';
+ d.setVerbosity(oldVerbosity );
+ QCOMPARE(d.verbosity(), oldVerbosity );
+ d << line;
+ const QStringList lines = output.split(QLatin1Char('\n'));
+ QCOMPARE(lines.size(), 3);
+ // Verbose should be longer
+ QVERIFY2(lines.at(1).size() > lines.at(0).size(), qPrintable(lines.join(QLatin1Char(','))));
+ // Switching back to brief produces same output
+ QCOMPARE(lines.at(0).size(), lines.at(2).size());
+}
+
void tst_QDebug::stateSaver() const
{
MessageHandlerSetter mhs(myMessageHandler);
diff --git a/tests/auto/corelib/io/qfileselector/platforms/+haiku/test b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test
diff --git a/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2 b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2
diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test
diff --git a/tests/auto/corelib/io/qfileselector/qfileselector.qrc b/tests/auto/corelib/io/qfileselector/qfileselector.qrc
index 661647f933..6e2699774d 100644
--- a/tests/auto/corelib/io/qfileselector/qfileselector.qrc
+++ b/tests/auto/corelib/io/qfileselector/qfileselector.qrc
@@ -19,6 +19,7 @@
<file>platforms/+unix/+darwin/+mac/+osx/test</file>
<file>platforms/+unix/+darwin/+mac/test</file>
<file>platforms/+unix/+darwin/test</file>
+ <file>platforms/+unix/+haiku/test</file>
<file>platforms/+unix/+linux/test</file>
<file>platforms/+unix/test</file>
<file>platforms/+windows/+wince/test</file>
@@ -30,6 +31,7 @@
<file>platforms/+osx/test</file>
<file>platforms/+darwin/test</file>
<file>platforms/+mac/test</file>
+ <file>platforms/+haiku/test</file>
<file>platforms/+linux/test</file>
<file>platforms/+wince/test</file>
@@ -39,6 +41,7 @@
<file>platforms/+blackberry/test2</file>
<file>platforms/+ios/test2</file>
<file>platforms/+osx/test2</file>
+ <file>platforms/+haiku/test2</file>
<file>platforms/+linux/test2</file>
<file>platforms/+wince/test2</file>
<file>platforms/+winnt/test2</file>
diff --git a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp
index b3767b4887..87381f4c4e 100644
--- a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp
+++ b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp
@@ -89,7 +89,7 @@ void tst_QFileSelector::basicTest_data()
QString expectedPlatform2File(""); //Only the last selector
QString expectedPlatform3File; // Only the first selector (the family)
#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && \
- !defined(Q_OS_DARWIN) && !defined(Q_OS_LINUX)
+ !defined(Q_OS_DARWIN) && !defined(Q_OS_LINUX) && !defined(Q_OS_HAIKU)
/* We are only aware of specific unixes, and do not have test files for any of the others.
However those unixes can get a selector added from the result of a uname call, so this will
lead to a case where we don't have that file so we can't expect the concatenation of platform
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index a192ccde59..6da8f55e61 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -3357,9 +3357,6 @@ void tst_QVariant::numericalConvert_data()
void tst_QVariant::numericalConvert()
{
-#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__)
- QSKIP("Known to fail due to a GCC bug on at least Ubuntu 10.04 32-bit - check QTBUG-8959");
-#endif
QFETCH(QVariant, v);
QFETCH(bool, isInteger);
double num = isInteger ? 5 : 5.3;
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index bdbb291d7f..cd77b188cc 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -120,6 +120,7 @@ private slots:
void loadGarbage();
#endif
void relativePath();
+ void absolutePath();
void reloadPlugin();
void preloadedPlugin_data();
void preloadedPlugin();
@@ -406,6 +407,20 @@ void tst_QPluginLoader::relativePath()
QVERIFY(loader.unload());
}
+void tst_QPluginLoader::absolutePath()
+{
+ // Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
+ const QString binDir = QFINDTESTDATA("bin");
+ QVERIFY(!binDir.isEmpty());
+ QVERIFY(QDir::isAbsolutePath(binDir));
+ QPluginLoader loader(binDir + "/theplugin");
+ loader.load(); // not recommended, instance() should do the job.
+ PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance());
+ QVERIFY(instance);
+ QCOMPARE(instance->pluginName(), QLatin1String("Plugin ok"));
+ QVERIFY(loader.unload());
+}
+
void tst_QPluginLoader::reloadPlugin()
{
QPluginLoader loader;
diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
index 7b1b7ce963..6e09ebb09b 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp
@@ -73,6 +73,12 @@ int main(int argc, char *argv[])
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"));
parser.addOption(newlineOption);
+ // A hidden option
+ QCommandLineOption hiddenOption(QStringList() << QStringLiteral("hidden"));
+ hiddenOption.setDescription(QStringLiteral("THIS SHOULD NEVER APPEAR"));
+ hiddenOption.setHidden(true);
+ parser.addOption(hiddenOption);
+
// This program supports different options depending on the "command" (first argument).
// Call parse() to find out the positional arguments.
parser.parse(QCoreApplication::arguments());
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 6ff46ed20b..9c4ded69de 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -35,6 +35,7 @@
#include <QtCore/QCommandLineParser>
Q_DECLARE_METATYPE(char**)
+Q_DECLARE_METATYPE(QCommandLineParser::OptionsAfterPositionalArgumentsMode)
class tst_QCommandLineParser : public QObject
{
@@ -51,6 +52,8 @@ private slots:
void testPositionalArguments();
void testBooleanOption_data();
void testBooleanOption();
+ void testOptionsAndPositional_data();
+ void testOptionsAndPositional();
void testMultipleNames_data();
void testMultipleNames();
void testSingleValueOption_data();
@@ -141,6 +144,40 @@ void tst_QCommandLineParser::testBooleanOption()
QVERIFY(!parser.isSet("c"));
}
+void tst_QCommandLineParser::testOptionsAndPositional_data()
+{
+ QTest::addColumn<QStringList>("args");
+ QTest::addColumn<QStringList>("expectedOptionNames");
+ QTest::addColumn<bool>("expectedIsSet");
+ QTest::addColumn<QStringList>("expectedPositionalArguments");
+ QTest::addColumn<QCommandLineParser::OptionsAfterPositionalArgumentsMode>("parsingMode");
+
+ const QStringList arg = QStringList() << "arg";
+ QTest::newRow("before_positional_default") << (QStringList() << "tst_qcommandlineparser" << "-b" << "arg") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsOptions;
+ QTest::newRow("after_positional_default") << (QStringList() << "tst_qcommandlineparser" << "arg" << "-b") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsOptions;
+ QTest::newRow("before_positional_parseAsArg") << (QStringList() << "tst_qcommandlineparser" << "-b" << "arg") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsPositionalArguments;
+ QTest::newRow("after_positional_parseAsArg") << (QStringList() << "tst_qcommandlineparser" << "arg" << "-b") << (QStringList()) << false << (QStringList() << "arg" << "-b") << QCommandLineParser::ParseAsPositionalArguments;
+}
+
+void tst_QCommandLineParser::testOptionsAndPositional()
+{
+ QFETCH(QStringList, args);
+ QFETCH(QStringList, expectedOptionNames);
+ QFETCH(bool, expectedIsSet);
+ QFETCH(QStringList, expectedPositionalArguments);
+ QFETCH(QCommandLineParser::OptionsAfterPositionalArgumentsMode, parsingMode);
+
+ QCoreApplication app(empty_argc, empty_argv);
+ QCommandLineParser parser;
+ parser.setOptionsAfterPositionalArgumentsMode(parsingMode);
+ QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("b"), QStringLiteral("a boolean option"))));
+ QVERIFY(parser.parse(args));
+ QCOMPARE(parser.optionNames(), expectedOptionNames);
+ QCOMPARE(parser.isSet("b"), expectedIsSet);
+ QCOMPARE(parser.values("b"), QStringList());
+ QCOMPARE(parser.positionalArguments(), expectedPositionalArguments);
+}
+
void tst_QCommandLineParser::testMultipleNames_data()
{
QTest::addColumn<QStringList>("args");
diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
index 8c29064457..33e143fa7d 100644
--- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
+++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
@@ -60,7 +60,7 @@ void tst_QRingBuffer::sizeWhenReserved()
QRingBuffer ringBuffer;
ringBuffer.reserve(5);
- QCOMPARE(ringBuffer.size(), 5);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(5));
}
void tst_QRingBuffer::sizeWhenReservedAndChopped()
@@ -69,14 +69,14 @@ void tst_QRingBuffer::sizeWhenReservedAndChopped()
ringBuffer.reserve(31337);
ringBuffer.chop(31337);
- QCOMPARE(ringBuffer.size(), 0);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(0));
}
void tst_QRingBuffer::sizeWhenEmpty()
{
QRingBuffer ringBuffer;
- QCOMPARE(ringBuffer.size(), 0);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(0));
}
void tst_QRingBuffer::readPointerAtPositionReadTooMuch()
@@ -101,22 +101,22 @@ void tst_QRingBuffer::readPointerAtPositionWithHead()
qint64 length;
const char* buf2 = ringBuffer.readPointerAtPosition(0, length);
- QCOMPARE(length, qint64(2));
+ QCOMPARE(length, Q_INT64_C(2));
QVERIFY(*buf2 == '2');
QVERIFY(*(buf2+1) == '3');
// advance 2 more, ringBuffer should be empty then
ringBuffer.free(2);
buf2 = ringBuffer.readPointerAtPosition(0, length);
- QCOMPARE(length, qint64(0));
+ QCOMPARE(length, Q_INT64_C(0));
QVERIFY(buf2 == 0);
// check buffer with 2 blocks
memcpy(ringBuffer.reserve(4), "0123", 4);
ringBuffer.append(QByteArray("45678", 5));
ringBuffer.free(3);
- buf2 = ringBuffer.readPointerAtPosition(1, length);
- QCOMPARE(length, qint64(5));
+ buf2 = ringBuffer.readPointerAtPosition(Q_INT64_C(1), length);
+ QCOMPARE(length, Q_INT64_C(5));
}
void tst_QRingBuffer::readPointerAtPositionEmptyRead()
@@ -149,14 +149,14 @@ void tst_QRingBuffer::readPointerAtPositionWriteRead()
// write in chunks of 50 bytes
// this ensures there will be multiple QByteArrays inside the QRingBuffer
// since QRingBuffer is then only using individual arrays of around 4000 bytes
- qint64 thisWrite = qMin(remaining, qint64(50));
+ qint64 thisWrite = qMin(remaining, Q_INT64_C(50));
char *pos = ringBuffer.reserve(thisWrite);
inData.read(pos, thisWrite);
remaining -= thisWrite;
}
// was data put into it?
QVERIFY(ringBuffer.size() > 0);
- QCOMPARE(qint64(ringBuffer.size()), inData.size());
+ QCOMPARE(ringBuffer.size(), inData.size());
//read from the QRingBuffer in loop, put back into another QBuffer
QBuffer outData;
@@ -187,12 +187,12 @@ void tst_QRingBuffer::free()
ringBuffer.append(QByteArray("01234", 5));
ringBuffer.free(1);
- QCOMPARE(ringBuffer.size(), 4095 + 2048 + 5);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(4095 + 2048 + 5));
ringBuffer.free(4096);
- QCOMPARE(ringBuffer.size(), 2047 + 5);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(2047 + 5));
ringBuffer.free(48);
ringBuffer.free(2000);
- QCOMPARE(ringBuffer.size(), 4);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(4));
QVERIFY(memcmp(ringBuffer.readPointer(), "1234", 4) == 0);
}
@@ -211,8 +211,8 @@ void tst_QRingBuffer::reserveAndRead()
for (int i = 1; i < 256; ++i) {
QByteArray ba;
ba.resize(i);
- int thisRead = ringBuffer.read(ba.data(), i);
- QCOMPARE(thisRead, i);
+ qint64 thisRead = ringBuffer.read(ba.data(), i);
+ QCOMPARE(thisRead, qint64(i));
QVERIFY(ba.count(char(i)) == i);
}
QVERIFY(ringBuffer.size() == 0);
@@ -227,12 +227,12 @@ void tst_QRingBuffer::chop()
ringBuffer.reserve(4096);
ringBuffer.chop(1);
- QCOMPARE(ringBuffer.size(), 5 + 2048 + 4095);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(5 + 2048 + 4095));
ringBuffer.chop(4096);
- QCOMPARE(ringBuffer.size(), 5 + 2047);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(5 + 2047));
ringBuffer.chop(48);
ringBuffer.chop(2000);
- QCOMPARE(ringBuffer.size(), 4);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(4));
QVERIFY(memcmp(ringBuffer.readPointer(), "0123", 4) == 0);
}
@@ -248,7 +248,7 @@ void tst_QRingBuffer::ungetChar()
ringBuffer.getChar();
ringBuffer.ungetChar(char(c)); // unget first char
}
- QCOMPARE(ringBuffer.size(), 1);
+ QCOMPARE(ringBuffer.size(), Q_INT64_C(1));
}
void tst_QRingBuffer::indexOf()
@@ -258,8 +258,8 @@ void tst_QRingBuffer::indexOf()
ringBuffer.putChar(char(i));
for (int i = 1; i < 256; ++i) {
- int index = ringBuffer.indexOf(char(i));
- QCOMPARE(i - 1, index);
+ qint64 index = ringBuffer.indexOf(char(i));
+ QCOMPARE(qint64(i - 1), index);
QCOMPARE(index, ringBuffer.indexOf(char(i), i));
QVERIFY(ringBuffer.indexOf(char(i), i - 1) == -1); // test for absent char
}
@@ -298,7 +298,7 @@ void tst_QRingBuffer::readLine()
// check first empty string reading
stringBuf[0] = char(0xFF);
- QCOMPARE(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2), ba2.size());
+ QCOMPARE(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2), qint64(ba2.size()));
QVERIFY(stringBuf[0] == ba2[0]);
QVERIFY(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2) == (ba3.size() + ba4.size()
diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
index 32c228c186..d85e842a23 100644
--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
+++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
@@ -105,6 +105,8 @@ private slots:
void sendWithGui();
void sendAsync();
void sendSignal();
+ void sendSignalToName();
+ void sendSignalToOtherName();
void registerObject_data();
void registerObject();
@@ -189,6 +191,49 @@ void tst_QDBusConnection::sendSignal()
QTest::qWait(1000);
}
+void tst_QDBusConnection::sendSignalToName()
+{
+ QDBusSpy spy;
+
+ QDBusConnection con = QDBusConnection::sessionBus();
+
+ con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy,
+ SLOT(handlePing(QString)));
+
+ QDBusMessage msg =
+ QDBusMessage::createTargetedSignal(con.baseService(), "/org/kde/selftest",
+ "org.kde.selftest", "ping");
+ msg << QLatin1String("ping");
+
+ QVERIFY(con.send(msg));
+
+ QTest::qWait(1000);
+
+ QCOMPARE(spy.args.count(), 1);
+ QCOMPARE(spy.args.at(0).toString(), QString("ping"));
+}
+
+void tst_QDBusConnection::sendSignalToOtherName()
+{
+ QDBusSpy spy;
+
+ QDBusConnection con = QDBusConnection::sessionBus();
+
+ con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy,
+ SLOT(handlePing(QString)));
+
+ QDBusMessage msg =
+ QDBusMessage::createTargetedSignal("some.other.service", "/org/kde/selftest",
+ "org.kde.selftest", "ping");
+ msg << QLatin1String("ping");
+
+ QVERIFY(con.send(msg));
+
+ QTest::qWait(1000);
+
+ QCOMPARE(spy.args.count(), 0);
+}
+
void tst_QDBusConnection::send()
{
QDBusConnection con = QDBusConnection::sessionBus();
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 4fafbf9827..7d17794c0b 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -38,6 +38,7 @@
#include <qcolor.h>
#include <qdebug.h>
+#include <qrgba64.h>
#include <private/qdrawingprimitive_sse2_p.h>
class tst_QColor : public QObject
@@ -105,6 +106,9 @@ private slots:
void premultiply();
void unpremultiply_sse4();
+ void qrgba64();
+ void qrgba64Premultiply();
+ void qrgba64Equivalence();
#ifdef Q_DEAD_CODE_FROM_QT4_X11
void setallowX11ColorNames();
@@ -1455,7 +1459,7 @@ void tst_QColor::unpremultiply_sse4()
for (uint a = 0; a < 256; a++) {
for (uint c = 0; c <= a; c++) {
QRgb p = qRgba(c, a-c, c, a);
- QCOMPARE(qUnpremultiply(p), qUnpremultiply_sse4(p));
+ QCOMPARE(qUnpremultiply_sse4(p), qUnpremultiply(p));
}
}
return;
@@ -1464,5 +1468,84 @@ void tst_QColor::unpremultiply_sse4()
QSKIP("SSE4 not supported on this CPU.");
}
+void tst_QColor::qrgba64()
+{
+ QRgba64 rgb64 = QRgba64::fromRgba(0x22, 0x33, 0x44, 0xff);
+ QCOMPARE(rgb64.red(), quint16(0x2222));
+ QCOMPARE(rgb64.green(), quint16(0x3333));
+ QCOMPARE(rgb64.blue(), quint16(0x4444));
+ QCOMPARE(rgb64.alpha(), quint16(0xffff));
+
+ QColor c(rgb64);
+ QCOMPARE(c.red(), 0x22);
+ QCOMPARE(c.green(), 0x33);
+ QCOMPARE(c.blue(), 0x44);
+
+ QCOMPARE(c.rgba64(), rgb64);
+
+ QColor c2 = QColor::fromRgb(0x22, 0x33, 0x44, 0xff);
+ QCOMPARE(c, c2);
+ QCOMPARE(c2.rgba64(), rgb64);
+
+ rgb64.setAlpha(0x8000);
+ rgb64.setGreen(0x8844);
+ rgb64 = rgb64.premultiplied();
+ QCOMPARE(rgb64.red(), quint16(0x1111));
+ QCOMPARE(rgb64.blue(), quint16(0x2222));
+ QCOMPARE(rgb64.green(), quint16(0x4422));
+}
+
+void tst_QColor::qrgba64Premultiply()
+{
+ // Tests that qPremultiply(qUnpremultiply(rgba64)) returns rgba64.
+ for (uint a = 0; a < 0x10000; a+=7) {
+ const uint step = std::max(a/1024, 1u);
+ for (uint c = 0; c <= a; c+=step) {
+ QRgba64 p = qRgba64(c, a-c, a-c/2, a);
+ QRgba64 pp = qPremultiply(qUnpremultiply(p));
+ QCOMPARE(pp, p);
+ }
+ }
+}
+
+void tst_QColor::qrgba64Equivalence()
+{
+ // Any ARGB32 converted back and forth.
+ for (uint a = 0; a < 256; a++) {
+ for (uint c = 0; c < 256; c++) {
+ QRgb p1 = qRgba(c, 255-c, 255-c, a);
+ QRgba64 p64 = QRgba64::fromArgb32(p1);
+ QCOMPARE(p64.toArgb32(), p1);
+ }
+ }
+ // Any unpremultiplied ARGB32 value premultipled in RGB64 (except alpha 0).
+ for (uint a = 1; a < 256; a++) {
+ for (uint c = 0; c < 256; c++) {
+ QRgb p1 = qRgba(c, 255-c, 255-c, a);
+ QRgb pp1 = qPremultiply(p1);
+ QRgba64 pp64 = qPremultiply(QRgba64::fromArgb32(p1));
+ QRgb pp2 = pp64.toArgb32();
+ // 64bit premultiplied is more accurate than 32bit, so allow slight difference.
+ QCOMPARE(qAlpha(pp2), qAlpha(pp1));
+ QVERIFY(qAbs(qRed(pp2)-qRed(pp1)) <= 1);
+ QVERIFY(qAbs(qGreen(pp2)-qGreen(pp1)) <= 1);
+ QVERIFY(qAbs(qBlue(pp2)-qBlue(pp1)) <= 1);
+ // But verify the added accuracy means we can return to accurate unpremultiplied ARGB32.
+ QRgba64 pu64 = qUnpremultiply(pp64);
+ QRgb p2 = pu64.toArgb32();
+ QCOMPARE(p2, p1);
+ }
+ }
+ // Any premultiplied ARGB32 value unpremultipled in RGB64.
+ for (uint a = 0; a < 256; a++) {
+ for (uint c = 0; c <= a; c++) {
+ QRgb pp = qRgba(c, a-c, a-c, a);
+ QRgb pu = qUnpremultiply(pp);
+ QRgba64 pu64 = qUnpremultiply(QRgba64::fromArgb32(pp));
+ QCOMPARE(pu64.toArgb32(), pu);
+ }
+ }
+}
+
QTEST_MAIN(tst_QColor)
#include "tst_qcolor.moc"
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index c63cfaf6b6..dcb3df834d 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -121,6 +121,14 @@ class tst_QNetworkReply: public QObject
return s;
};
+ static QString tempRedirectReplyStr() {
+ QString s = "HTTP/1.1 307 Temporary Redirect\r\n"
+ "Content-Type: text/plain\r\n"
+ "location: %1\r\n"
+ "\r\n";
+ return s;
+ };
+
QEventLoop *loop;
enum RunSimpleRequestReturn { Timeout = 0, Success, Failure };
int returnCode;
@@ -456,6 +464,11 @@ private Q_SLOTS:
void putWithRateLimiting();
+ void ioHttpSingleRedirect();
+ void ioHttpChangeMaxRedirects();
+ void ioHttpRedirectErrors_data();
+ void ioHttpRedirectErrors();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
@@ -593,10 +606,16 @@ protected:
virtual void reply() {
Q_ASSERT(!client.isNull());
// we need to emulate the bytesWrittenSlot call if the data is empty.
- if (dataToTransmit.size() == 0)
+ if (dataToTransmit.size() == 0) {
QMetaObject::invokeMethod(this, "bytesWrittenSlot", Qt::QueuedConnection);
- else
+ } else {
client->write(dataToTransmit);
+ // FIXME: For SSL connections, if we don't flush the socket, the
+ // client never receives the data and since we're doing a disconnect
+ // immediately afterwards, it causes a RemoteHostClosedError for the
+ // client
+ client->flush();
+ }
}
private:
void connectSocketSignals()
@@ -7962,7 +7981,142 @@ void tst_QNetworkReply::putWithRateLimiting()
QCOMPARE(uploadedData, data);
}
+void tst_QNetworkReply::ioHttpSingleRedirect()
+{
+ QUrl localhost = QUrl("http://localhost");
+ QByteArray http200Reply = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
+
+ // Setup server to which the second server will redirect to
+ MiniHttpServer server2(http200Reply);
+
+ QUrl redirectUrl = QUrl(localhost);
+ redirectUrl.setPort(server2.serverPort());
+
+ QByteArray tempRedirectReply =
+ tempRedirectReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1();
+
+
+ // Setup redirect server
+ MiniHttpServer server(tempRedirectReply);
+
+ localhost.setPort(server.serverPort());
+ QNetworkRequest request(localhost);
+ request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+
+ QNetworkReplyPtr reply(manager.get(request));
+ QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl)));
+ QSignalSpy finSpy(reply.data(), SIGNAL(finished()));
+
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+
+ // Redirected and finished should be emitted exactly once
+ QCOMPARE(redSpy.count(), 1);
+ QCOMPARE(finSpy.count(), 1);
+
+ // Original URL should not be changed after redirect
+ QCOMPARE(request.url(), localhost);
+
+ // Verify Redirect url
+ QList<QVariant> args = redSpy.takeFirst();
+ QCOMPARE(args.at(0).toUrl(), redirectUrl);
+
+ // Reply url is set to the redirect url
+ QCOMPARE(reply->url(), redirectUrl);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+}
+
+void tst_QNetworkReply::ioHttpChangeMaxRedirects()
+{
+ QUrl localhost = QUrl("http://localhost");
+ QByteArray http200Reply = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
+
+ MiniHttpServer server1("");
+ MiniHttpServer server2("");
+ MiniHttpServer server3(http200Reply);
+
+ QUrl server2Url(localhost);
+ server2Url.setPort(server2.serverPort());
+ server1.setDataToTransmit(tempRedirectReplyStr().arg(
+ QString(server2Url.toEncoded())).toLatin1());
+
+ QUrl server3Url(localhost);
+ server3Url.setPort(server3.serverPort());
+ server2.setDataToTransmit(tempRedirectReplyStr().arg(
+ QString(server3Url.toEncoded())).toLatin1());
+
+ localhost.setPort(server1.serverPort());
+ QNetworkRequest request(localhost);
+ request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+
+ // Set Max redirects to 1. This will cause TooManyRedirectsError
+ request.setMaximumRedirectsAllowed(1);
+
+ QNetworkReplyPtr reply(manager.get(request));
+ QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl)));
+ QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+
+ QVERIFY(waitForFinish(reply) == Failure);
+
+ QCOMPARE(redSpy.count(), request.maximumRedirectsAllowed());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(reply->error() == QNetworkReply::TooManyRedirectsError);
+
+ // Increase max redirects to allow successful completion
+ request.setMaximumRedirectsAllowed(3);
+
+ QNetworkReplyPtr reply2(manager.get(request));
+ QSignalSpy redSpy2(reply2.data(), SIGNAL(redirected(QUrl)));
+
+ QVERIFY2(waitForFinish(reply2) == Success, msgWaitForFinished(reply2));
+
+ QCOMPARE(redSpy2.count(), 2);
+ QCOMPARE(reply2->url(), server3Url);
+ QVERIFY(reply2->error() == QNetworkReply::NoError);
+}
+
+void tst_QNetworkReply::ioHttpRedirectErrors_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<QString>("dataToSend");
+ QTest::addColumn<QNetworkReply::NetworkError>("error");
+
+ QString tempRedirectReply = QString("HTTP/1.1 307 Temporary Redirect\r\n"
+ "Content-Type: text/plain\r\n"
+ "location: http://localhost:%1\r\n\r\n");
+
+ QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError;
+ QTest::newRow("insecure-redirect") << "https://localhost" << tempRedirectReply << QNetworkReply::InsecureRedirectError;
+ QTest::newRow("unknown-redirect") << "http://localhost"<< tempRedirectReply.replace("http", "bad_protocol") << QNetworkReply::ProtocolUnknownError;
+}
+
+void tst_QNetworkReply::ioHttpRedirectErrors()
+{
+ QFETCH(QString, url);
+ QFETCH(QString, dataToSend);
+ QFETCH(QNetworkReply::NetworkError, error);
+
+ QUrl localhost(url);
+ MiniHttpServer server("", localhost.scheme() == "https");
+
+ localhost.setPort(server.serverPort());
+
+ QByteArray d2s = dataToSend.arg(
+ QString::number(server.serverPort())).toLatin1();
+ server.setDataToTransmit(d2s);
+
+ QNetworkRequest request(localhost);
+ request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+ QNetworkReplyPtr reply(manager.get(request));
+ if (localhost.scheme() == "https")
+ reply.data()->ignoreSslErrors();
+ QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+
+ QVERIFY(waitForFinish(reply) == Failure);
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(reply->error() == error);
+}
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
diff --git a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
index 76c36831bd..1c79b6c016 100644
--- a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
+++ b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
@@ -37,11 +37,6 @@
#include <qcoreapplication.h>
#include <qdebug.h>
#include <qabstractsocket.h>
-#include <qtcpserver.h>
-#include <qtcpsocket.h>
-#ifndef QT_NO_SSL
-#include <qsslsocket.h>
-#endif
class tst_QAbstractSocket : public QObject
{
@@ -52,9 +47,7 @@ public:
virtual ~tst_QAbstractSocket();
private slots:
- void initTestCase();
void getSetCheck();
- void serverDisconnectWithBuffered();
};
tst_QAbstractSocket::tst_QAbstractSocket()
@@ -73,11 +66,6 @@ public:
void setPeerPort(quint16 port) { QAbstractSocket::setPeerPort(port); }
};
-void tst_QAbstractSocket::initTestCase()
-{
- qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
-}
-
// Testing get/set functions
void tst_QAbstractSocket::getSetCheck()
{
@@ -106,46 +94,5 @@ void tst_QAbstractSocket::getSetCheck()
QCOMPARE(quint16(0xffff), obj1.peerPort());
}
-// Test buffered socket being properly closed on remote disconnect
-void tst_QAbstractSocket::serverDisconnectWithBuffered()
-{
- QTcpServer tcpServer;
-#ifndef QT_NO_SSL
- QSslSocket testSocket;
-#else
- QTcpSocket testSocket;
-#endif
-
- QVERIFY(tcpServer.listen(QHostAddress::LocalHost));
- testSocket.connectToHost(tcpServer.serverAddress(), tcpServer.serverPort());
- // Accept connection on server side
- QVERIFY(tcpServer.waitForNewConnection(5000));
- QTcpSocket *newConnection = tcpServer.nextPendingConnection();
- // Send one char and drop link
- QVERIFY(newConnection != NULL);
- QVERIFY(newConnection->putChar(0));
- QVERIFY(newConnection->flush());
- delete newConnection;
-
- QVERIFY(testSocket.waitForConnected(5000)); // ready for write
- QVERIFY(testSocket.state() == QAbstractSocket::ConnectedState);
-
- QSignalSpy spyStateChanged(&testSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
- QSignalSpy spyDisconnected(&testSocket, SIGNAL(disconnected()));
-
- QVERIFY(testSocket.waitForReadyRead(5000)); // have one char already in internal buffer
- char buf[128];
- QCOMPARE(testSocket.read(buf, sizeof(buf)), Q_INT64_C(1));
- if (testSocket.state() != QAbstractSocket::UnconnectedState) {
- QVERIFY(testSocket.waitForDisconnected(5000));
- QVERIFY(testSocket.state() == QAbstractSocket::UnconnectedState);
- }
- // Test signal emitting
- QVERIFY(spyDisconnected.count() == 1);
- QVERIFY(spyStateChanged.count() > 0);
- QVERIFY(qvariant_cast<QAbstractSocket::SocketState>(spyStateChanged.last().first())
- == QAbstractSocket::UnconnectedState);
-}
-
QTEST_MAIN(tst_QAbstractSocket)
#include "tst_qabstractsocket.moc"
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index 0ba9b6a58c..109e48ed74 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -200,6 +200,7 @@ private slots:
void setSocketOption();
void clientSendDataOnDelayedDisconnect();
+ void serverDisconnectWithBuffered();
protected slots:
void nonBlockingIMAP_hostFound();
@@ -2984,5 +2985,50 @@ void tst_QTcpSocket::clientSendDataOnDelayedDisconnect()
delete socket;
}
+// Test buffered socket being properly closed on remote disconnect
+void tst_QTcpSocket::serverDisconnectWithBuffered()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
+
+ QTcpServer tcpServer;
+ QTcpSocket *socket = newSocket();
+
+ QVERIFY(tcpServer.listen(QHostAddress::LocalHost));
+ socket->connectToHost(tcpServer.serverAddress(), tcpServer.serverPort());
+ // Accept connection on server side
+ QVERIFY(tcpServer.waitForNewConnection(5000));
+ QTcpSocket *newConnection = tcpServer.nextPendingConnection();
+ // Send one char and drop link
+ QVERIFY(newConnection != NULL);
+ QVERIFY(newConnection->putChar(0));
+ QVERIFY(newConnection->flush());
+ delete newConnection;
+
+ QVERIFY(socket->waitForConnected(5000)); // ready for write
+ QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
+
+ QSignalSpy spyStateChanged(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
+ QSignalSpy spyDisconnected(socket, SIGNAL(disconnected()));
+
+ QVERIFY(socket->waitForReadyRead(5000)); // have one char already in internal buffer
+ char buf[128];
+ QCOMPARE(socket->read(buf, sizeof(buf)), Q_INT64_C(1));
+ if (socket->state() != QAbstractSocket::UnconnectedState) {
+ QVERIFY(socket->waitForDisconnected(5000));
+ QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
+ }
+ // Test signal emitting
+ QVERIFY(spyDisconnected.count() == 1);
+ QVERIFY(spyStateChanged.count() > 0);
+ QVERIFY(qvariant_cast<QAbstractSocket::SocketState>(spyStateChanged.last().first())
+ == QAbstractSocket::UnconnectedState);
+
+ delete socket;
+}
+
QTEST_MAIN(tst_QTcpSocket)
#include "tst_qtcpsocket.moc"
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 9937b6f7f8..8061b1ccb9 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -668,7 +668,7 @@ void tst_QAccessibility::textAttributes_data()
defaultComplexFont.setStyle(QFont::StyleItalic);
defaultComplexFont.setUnderline(true);
- static QStringList defaults = QString("font-style:normal;font-weight:normal;text-align:left;text-position:baseline;text-underline-style:none;font-size:13pt").split(';');
+ static QStringList defaults = QString("font-style:normal;font-weight:normal;text-align:left;text-position:baseline;font-size:13pt").split(';');
static QStringList bold = defaults;
bold[1] = QString::fromLatin1("font-weight:bold");
@@ -683,7 +683,7 @@ void tst_QAccessibility::textAttributes_data()
monospace.append(QLatin1String("font-family:\"monospace\""));
static QStringList font8pt = defaults;
- font8pt[5] = (QLatin1String("font-size:8pt"));
+ font8pt[4] = (QLatin1String("font-size:8pt"));
static QStringList color = defaults;
color << QLatin1String("color:rgb(240,241,242)") << QLatin1String("background-color:rgb(20,240,30)");
@@ -694,8 +694,9 @@ void tst_QAccessibility::textAttributes_data()
static QStringList defaultFontDifferent = defaults;
defaultFontDifferent[0] = QString::fromLatin1("font-style:italic");
defaultFontDifferent[1] = QString::fromLatin1("font-weight:bold");
- defaultFontDifferent[4] = QString::fromLatin1("text-underline-style:solid");
- defaultFontDifferent[5] = QString::fromLatin1("font-size:20pt");
+ defaultFontDifferent[4] = QString::fromLatin1("font-size:20pt");
+ defaultFontDifferent.append("text-underline-style:solid");
+ defaultFontDifferent.append("text-underline-type:single");
defaultFontDifferent.append("font-family:\"Arial\"");
static QStringList defaultFontDifferentBoldItalic = defaultFontDifferent;
@@ -703,10 +704,10 @@ void tst_QAccessibility::textAttributes_data()
defaultFontDifferentBoldItalic[1] = QString::fromLatin1("font-weight:bold");
static QStringList defaultFontDifferentMonospace = defaultFontDifferent;
- defaultFontDifferentMonospace[6] = (QLatin1String("font-family:\"monospace\""));
+ defaultFontDifferentMonospace[7] = (QLatin1String("font-family:\"monospace\""));
static QStringList defaultFontDifferentFont8pt = defaultFontDifferent;
- defaultFontDifferentFont8pt[5] = (QLatin1String("font-size:8pt"));
+ defaultFontDifferentFont8pt[4] = (QLatin1String("font-size:8pt"));
static QStringList defaultFontDifferentColor = defaultFontDifferent;
defaultFontDifferentColor << QLatin1String("color:rgb(240,241,242)") << QLatin1String("background-color:rgb(20,240,30)");
@@ -1715,7 +1716,10 @@ static QRect characterRect(const QTextEdit &edit, int offset)
QPointF layoutPosition = layout->position();
int relativeOffset = offset - block.position();
QTextLine line = layout->lineForTextPosition(relativeOffset);
- QFontMetrics fm(edit.currentFont());
+ QTextBlock::iterator it = block.begin();
+ while (!it.fragment().contains(offset))
+ ++it;
+ QFontMetrics fm(it.fragment().charFormat().font());
QChar ch = edit.document()->characterAt(offset);
int w = fm.width(ch);
int h = fm.height();
@@ -1747,6 +1751,7 @@ void tst_QAccessibility::textEditTest()
for (int pass = 0; pass < 2; ++pass) {
{
QTextEdit edit;
+ edit.setMinimumSize(600, 400);
setFrameless(&edit);
int startOffset;
int endOffset;
@@ -1757,7 +1762,7 @@ void tst_QAccessibility::textEditTest()
QFont font("Helvetica");
font.setPointSizeF(12.5);
font.setWordSpacing(1.1);
- edit.setCurrentFont(font);
+ edit.document()->setDefaultFont(font);
}
edit.show();
@@ -1779,7 +1784,7 @@ void tst_QAccessibility::textEditTest()
QCOMPARE(startOffset, 13);
QCOMPARE(endOffset, 31);
QCOMPARE(textIface->characterCount(), 48);
- QFontMetrics fm(edit.currentFont());
+ QFontMetrics fm(edit.document()->defaultFont());
QCOMPARE(textIface->characterRect(0).size(), QSize(fm.width("h"), fm.height()));
QCOMPARE(textIface->characterRect(5).size(), QSize(fm.width(" "), fm.height()));
QCOMPARE(textIface->characterRect(6).size(), QSize(fm.width("w"), fm.height()));
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
index 8e439a61cf..92af5a0757 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
@@ -75,6 +75,7 @@ private slots:
void lineEditTest();
void hierarchyTest();
void notificationsTest();
+ void checkBoxTest();
private:
AccessibleTestWindow *m_window;
@@ -151,5 +152,19 @@ void tst_QAccessibilityMac::notificationsTest()
QVERIFY(notifications(m_window));
}
+void tst_QAccessibilityMac::checkBoxTest()
+{
+ if (!macNativeAccessibilityEnabled())
+ return;
+
+ QCheckBox *cb = new QCheckBox(m_window);
+ cb->setText("Great option");
+ m_window->addWidget(cb);
+ QVERIFY(QTest::qWaitForWindowExposed(m_window));
+ QCoreApplication::processEvents();
+
+ QVERIFY(testCheckBox());
+}
+
QTEST_MAIN(tst_QAccessibilityMac)
#include "tst_qaccessibilitymac.moc"
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
index 78615fa9cd..cdf12489a6 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
@@ -44,3 +44,4 @@ bool testLineEdit();
bool testHierarchy(QWidget *w);
bool singleWidget();
bool notifications(QWidget *w);
+bool testCheckBox();
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
index b004e985bd..d0ff6af640 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
@@ -60,6 +60,43 @@ bool trusted()
return AXIsProcessTrusted();
}
+struct AXErrorTag {
+ AXError err;
+ explicit AXErrorTag(AXError theErr) : err(theErr) {}
+};
+
+QDebug operator<<(QDebug dbg, AXErrorTag err)
+{
+ QDebugStateSaver saver(dbg);
+
+ const char *errDesc = 0;
+ const char *errName = 0;
+ switch (err.err) {
+#define HANDLE_ERR(error, desc) case kAXError##error: errName = "kAXError" #error; errDesc = desc; break
+ HANDLE_ERR(Success, "Success");
+ HANDLE_ERR(Failure, "A system error occurred, such as the failure to allocate an object.");
+ HANDLE_ERR(IllegalArgument, "An illegal argument was passed to the function.");
+ HANDLE_ERR(InvalidUIElement, "The AXUIElementRef passed to the function is invalid.");
+ HANDLE_ERR(InvalidUIElementObserver, "The AXObserverRef passed to the function is not a valid observer.");
+ HANDLE_ERR(CannotComplete, "The function cannot complete because messaging failed in some way or because the application with which the function is communicating is busy or unresponsive.");
+ HANDLE_ERR(AttributeUnsupported, "The attribute is not supported by the AXUIElementRef.");
+ HANDLE_ERR(ActionUnsupported, "The action is not supported by the AXUIElementRef.");
+ HANDLE_ERR(NotificationUnsupported, "The notification is not supported by the AXUIElementRef.");
+ HANDLE_ERR(NotImplemented, "Indicates that the function or method is not implemented (this can be returned if a process does not support the accessibility API).");
+ HANDLE_ERR(NotificationAlreadyRegistered, "This notification has already been registered for.");
+ HANDLE_ERR(NotificationNotRegistered, "Indicates that a notification is not registered yet.");
+ HANDLE_ERR(APIDisabled, "The accessibility API is disabled (as when, for example, the user deselects \"Enable access for assistive devices\" in Universal Access Preferences).");
+ HANDLE_ERR(NoValue, "The requested value or AXUIElementRef does not exist.");
+ HANDLE_ERR(ParameterizedAttributeUnsupported, "The parameterized attribute is not supported by the AXUIElementRef.");
+ HANDLE_ERR(NotEnoughPrecision, "Not enough precision.");
+ default: errName = "<unknown error>"; errDesc = "UNKNOWN ERROR"; break;
+ }
+#undef HANDLE_ERR
+
+ dbg.nospace() << "AXError(value=" << err.err << ", name=" << errName << ", description=\"" << errDesc << "\")";
+
+ return dbg;
+}
#define EXPECT(cond) \
if (!(cond)) { \
@@ -71,41 +108,21 @@ bool trusted()
@interface TestAXObject : NSObject
{
AXUIElementRef reference;
- NSString *_role;
- NSString *_title;
- NSString *_description;
- NSString *_value;
- CGRect _rect;
}
@property (readonly) NSString *role;
@property (readonly) NSString *title;
@property (readonly) NSString *description;
@property (readonly) NSString *value;
@property (readonly) CGRect rect;
+ @property (readonly) NSArray *actions;
@end
@implementation TestAXObject
- @synthesize role = _role;
- @synthesize title = _title;
- @synthesize description = _description;
- @synthesize value = _value;
- @synthesize rect = _rect;
-
- (id) initWithAXUIElementRef: (AXUIElementRef) ref {
if ( self = [super init] ) {
reference = ref;
- AXUIElementCopyAttributeValue(ref, kAXRoleAttribute, (CFTypeRef*)&_role);
- AXUIElementCopyAttributeValue(ref, kAXTitleAttribute, (CFTypeRef*)&_title);
- AXUIElementCopyAttributeValue(ref, kAXDescriptionAttribute, (CFTypeRef*)&_description);
- AXUIElementCopyAttributeValue(ref, kAXValueAttribute, (CFTypeRef*)&_value);
- AXValueRef sizeValue;
- AXUIElementCopyAttributeValue(ref, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
- AXValueGetValue(sizeValue, kAXValueCGSizeType, &_rect.size);
- AXValueRef positionValue;
- AXUIElementCopyAttributeValue(ref, kAXPositionAttribute, (CFTypeRef*)&positionValue);
- AXValueGetValue(positionValue, kAXValueCGPointType, &_rect.origin);
}
return self;
}
@@ -140,24 +157,18 @@ bool trusted()
- (AXUIElementRef) findDirectChildByRole: (CFStringRef) role
{
- AXUIElementRef result = nil;
+ TestAXObject *result = nil;
NSArray *childList = [self childList];
for (id child in childList) {
- CFStringRef typeString;
- AXUIElementCopyAttributeValue((AXUIElementRef)child, kAXRoleAttribute, (CFTypeRef*)&typeString);
- if (CFStringCompare(typeString, role, 0) == 0) {
- result = (AXUIElementRef) child;
+ TestAXObject *childObject = [[TestAXObject alloc] initWithAXUIElementRef:(AXUIElementRef)child];
+ if ([childObject.role isEqualToString:(NSString*)role]) {
+ result = childObject;
break;
}
}
- return result;
-}
-
-- (AXUIElementRef) parent
-{
- AXUIElementRef p = nil;
- AXUIElementCopyAttributeValue(reference, kAXParentAttribute, (CFTypeRef*)&p);
- return p;
+ AXUIElementRef ret = [result ref];
+ [result release];
+ return ret;
}
+ (TestAXObject *) getApplicationAXObject
@@ -168,6 +179,208 @@ bool trusted()
return appObject;
}
++ (NSInteger)_numberFromValue:(CFTypeRef)value
+{
+ NSInteger number = -1;
+ if (!CFNumberGetValue((CFNumberRef)value, kCFNumberNSIntegerType, &number))
+ {
+ qDebug() << "Could not get NSInteger value out of CFNumberRef";
+ }
+ return number;
+}
+
++ (BOOL)_boolFromValue:(CFTypeRef)value
+{
+ return CFBooleanGetValue((CFBooleanRef)value);
+}
+
++ (NSRange)_rangeFromValue:(CFTypeRef)value
+{
+ CFRange cfRange;
+ NSRange range = NSMakeRange(0, 0);
+
+ if (!AXValueGetValue((AXValueRef)value, kAXValueCFRangeType, &cfRange))
+ qDebug() << "Could not get CFRange value out of AXValueRef";
+ else if (cfRange.location < 0 || cfRange.length < 0)
+ qDebug() << "Cannot convert CFRange with negative location or length to NSRange";
+ else if (static_cast<uintmax_t>(cfRange.location) > NSUIntegerMax || static_cast<uintmax_t>(cfRange.length) > NSUIntegerMax)
+ qDebug() << "Cannot convert CFRange with location or length out of bounds for NSUInteger";
+ else
+ {
+ range.length = static_cast<NSUInteger>(cfRange.length);
+ range.location = static_cast<NSUInteger>(cfRange.location);
+ }
+
+ return range;
+}
+
++ (NSRect)_rectFromValue:(CFTypeRef)value
+{
+ NSRect rect = NSMakeRect(0, 0, 0, 0);
+ if (!AXValueGetValue((AXValueRef)value, kAXValueCGRectType, reinterpret_cast<CGRect*>(&rect)))
+ {
+ qDebug() << "Could not get CGRect value out of AXValueRef";
+ }
+ return rect;
+}
+
++ (NSPoint)_pointFromValue:(CFTypeRef)value
+{
+ NSPoint point = NSMakePoint(0, 0);
+ if (!AXValueGetValue((AXValueRef)value, kAXValueCGPointType, reinterpret_cast<CGPoint*>(&point)))
+ {
+ qDebug() << "Could not get CGPoint value out of AXValueRef";
+ }
+ return point;
+}
+
++ (NSSize)_sizeFromValue:(CFTypeRef)value
+{
+ NSSize size = NSMakeSize(0, 0);
+ if (!AXValueGetValue((AXValueRef)value, kAXValueCGSizeType, reinterpret_cast<CGSize*>(&size)))
+ {
+ qDebug() << "Could not get CGSize value out of AXValueRef";
+ }
+ return size;
+}
+
+- (CFTypeRef)_attributeValue:(CFStringRef)attribute
+{
+ CFTypeRef value = NULL;
+ AXError err;
+
+ if (kAXErrorSuccess != (err = AXUIElementCopyAttributeValue(reference, attribute, &value)))
+ {
+ qDebug() << "AXUIElementCopyAttributeValue(" << QString::fromCFString(attribute) << ") returned error = " << AXErrorTag(err);
+ }
+ return value;
+}
+
+- (NSString*)_stringAttributeValue:(CFStringRef)attribute
+{
+ return (NSString*)[self _attributeValue:attribute];
+}
+
+- (NSInteger)_numberAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _numberFromValue:[self _attributeValue:attribute]];
+}
+
+- (BOOL)_boolAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _boolFromValue:[self _attributeValue:attribute]];
+}
+
+- (NSRange)_rangeAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _rangeFromValue:[self _attributeValue:attribute]];
+}
+
+- (NSRect)_rectAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _rectFromValue:[self _attributeValue:attribute]];
+}
+
+- (NSPoint)_pointAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _pointFromValue:[self _attributeValue:attribute]];
+}
+
+- (NSSize)_sizeAttributeValue:(CFStringRef)attribute
+{
+ return [[self class] _sizeFromValue:[self _attributeValue:attribute]];
+}
+
+- (CFTypeRef)_attributeValue:(CFStringRef)attribute forParameter:(CFTypeRef)parameter
+{
+ CFTypeRef value = NULL;
+ AXError err;
+
+ if (kAXErrorSuccess != (err = AXUIElementCopyParameterizedAttributeValue(reference, attribute, parameter, &value)))
+ {
+ CFStringRef description = CFCopyDescription(parameter);
+ qDebug() << "AXUIElementCopyParameterizedAttributeValue(" << QString::fromCFString(attribute) << ", parameter=" << QString::fromCFString(description) << ") returned error = " << AXErrorTag(err);
+ CFRelease(description);
+ }
+ return value;
+}
+
+- (CFTypeRef)_attributeValue:(CFStringRef)attribute forRange:(NSRange)aRange
+{
+ CFRange cfRange = CFRangeMake(aRange.location, aRange.length);
+ AXValueRef range = AXValueCreate(kAXValueCFRangeType, &cfRange);
+ CFTypeRef value = [self _attributeValue:attribute forParameter:range];
+ CFRelease(range);
+ return value;
+}
+
+- (CFTypeRef)_attributeValue:(CFStringRef)attribute forNumber:(NSInteger)aNumber
+{
+ CFNumberRef number = CFNumberCreate(NULL, kCFNumberNSIntegerType, &aNumber);
+ CFTypeRef value = [self _attributeValue:attribute forParameter:number];
+ CFRelease(number);
+ return value;
+}
+
+- (CFTypeRef)_attributeValue:(CFStringRef)attribute forPoint:(CGPoint)aPoint
+{
+ AXValueRef point = AXValueCreate(kAXValueCGPointType, &aPoint);
+ CFTypeRef value = [self _attributeValue:attribute forParameter:point];
+ CFRelease(point);
+ return value;
+}
+
+- (NSArray*)actions
+{
+ AXError err;
+ CFArrayRef actions;
+
+ if (kAXErrorSuccess != (err = AXUIElementCopyActionNames(reference, &actions)))
+ {
+ qDebug() << "AXUIElementCopyActionNames(...) returned error = " << AXErrorTag(err);
+ }
+
+ return (NSArray*)actions;
+}
+
+- (void)performAction:(CFStringRef)action
+{
+ AXError err;
+
+ if (kAXErrorSuccess != (err = AXUIElementPerformAction(reference, action)))
+ {
+ qDebug() << "AXUIElementPerformAction(" << QString::fromCFString(action) << ") returned error = " << AXErrorTag(err);
+ }
+}
+
+- (NSString*) role { return [self _stringAttributeValue:kAXRoleAttribute]; }
+- (NSString*) title { return [self _stringAttributeValue:kAXTitleAttribute]; }
+- (NSString*) description { return [self _stringAttributeValue:kAXDescriptionAttribute]; }
+- (NSString*) value { return [self _stringAttributeValue:kAXValueAttribute]; }
+- (NSInteger) valueNumber { return [self _numberAttributeValue:kAXValueAttribute]; }
+- (NSRect) rect
+{
+ NSRect rect;
+ rect.origin = [self _pointAttributeValue:kAXPositionAttribute];
+ rect.size = [self _sizeAttributeValue:kAXSizeAttribute];
+ return rect;
+}
+- (AXUIElementRef) parent { return (AXUIElementRef)[self _attributeValue:kAXParentAttribute]; }
+- (BOOL) focused { return [self _boolAttributeValue:kAXFocusedAttribute]; }
+- (NSInteger) numberOfCharacters { return [self _numberAttributeValue:kAXNumberOfCharactersAttribute]; }
+- (NSString*) selectedText { return [self _stringAttributeValue:kAXSelectedTextAttribute]; }
+- (NSRange) selectedTextRange { return [self _rangeAttributeValue:kAXSelectedTextRangeAttribute]; }
+- (NSRange) visibleCharacterRange { return [self _rangeAttributeValue:kAXVisibleCharacterRangeAttribute]; }
+- (NSString*) help { return [self _stringAttributeValue:kAXHelpAttribute]; }
+- (NSInteger) insertionPointLineNumber { return [self _numberAttributeValue:kAXInsertionPointLineNumberAttribute]; }
+
+- (NSInteger) lineForIndex:(NSInteger)index { return [[self class] _numberFromValue:[self _attributeValue:kAXLineForIndexParameterizedAttribute forNumber:index]]; }
+- (NSRange) rangeForLine:(NSInteger)line { return [[self class] _rangeFromValue:[self _attributeValue:kAXRangeForLineParameterizedAttribute forNumber:line]]; }
+- (NSString*) stringForRange:(NSRange)range { return (NSString*)[self _attributeValue:kAXStringForRangeParameterizedAttribute forRange:range]; }
+- (NSAttributedString*) attributedStringForRange:(NSRange)range { return (NSAttributedString*)[self _attributeValue:kAXAttributedStringForRangeParameterizedAttribute forRange:range]; }
+- (NSRect) boundsForRange:(NSRange)range { return [[self class] _rectFromValue:[self _attributeValue:kAXBoundsForRangeParameterizedAttribute forRange:range]]; }
+- (NSRange) styleRangeForIndex:(NSInteger)index { return [[self class] _rangeFromValue:[self _attributeValue:kAXStyleRangeForIndexParameterizedAttribute forNumber:index]]; }
+
@end
@@ -225,16 +438,34 @@ bool testLineEdit()
// height of window includes title bar
EXPECT([window rect].size.height >= 400);
- NSString *windowTitle;
- AXUIElementCopyAttributeValue(windowRef, kAXTitleAttribute, (CFTypeRef*)&windowTitle);
- EXPECT([windowTitle isEqualToString:@"Test window"]);
+ EXPECT([window.title isEqualToString:@"Test window"]);
// children of window:
AXUIElementRef lineEdit = [window findDirectChildByRole: kAXTextFieldRole];
EXPECT(lineEdit != nil);
TestAXObject *le = [[TestAXObject alloc] initWithAXUIElementRef: lineEdit];
- EXPECT([[le value] isEqualToString:@"a11y test QLineEdit"]);
+ NSString *value = @"a11y test QLineEdit";
+ EXPECT([le.value isEqualToString:value]);
+ EXPECT(value.length <= NSIntegerMax);
+ EXPECT(le.numberOfCharacters == static_cast<NSInteger>(value.length));
+ const NSRange ranges[] = {
+ { 0, 0},
+ { 0, 1},
+ { 0, 5},
+ { 5, 0},
+ { 5, 1},
+ { 0, value.length},
+ { value.length, 0},
+ };
+ for (size_t i = 0; i < sizeof(ranges)/sizeof(ranges[0]); ++i) {
+ NSRange range = ranges[i];
+ NSString *expectedSubstring = [value substringWithRange:range];
+ NSString *actualSubstring = [le stringForRange:range];
+ NSString *actualAttributedSubstring = [le attributedStringForRange:range].string;
+ EXPECT([actualSubstring isEqualTo:expectedSubstring]);
+ EXPECT([actualAttributedSubstring isEqualTo:expectedSubstring]);
+ }
return true;
}
@@ -357,3 +588,37 @@ bool notifications(QWidget *w)
return true;
}
+
+bool testCheckBox()
+{
+ TestAXObject *appObject = [TestAXObject getApplicationAXObject];
+ EXPECT(appObject);
+
+ NSArray *windowList = [appObject windowList];
+ // one window
+ EXPECT([windowList count] == 1);
+ AXUIElementRef windowRef = (AXUIElementRef) [windowList objectAtIndex: 0];
+ EXPECT(windowRef != nil);
+ TestAXObject *window = [[TestAXObject alloc] initWithAXUIElementRef: windowRef];
+
+ // children of window:
+ AXUIElementRef checkBox = [window findDirectChildByRole: kAXCheckBoxRole];
+ EXPECT(checkBox != nil);
+
+ TestAXObject *cb = [[TestAXObject alloc] initWithAXUIElementRef: checkBox];
+
+ // here start actual checkbox tests
+ EXPECT([cb valueNumber] == 0);
+ EXPECT([cb.title isEqualToString:@"Great option"]);
+ // EXPECT(cb.description == nil); // currently returns "" instead of nil
+
+ EXPECT([cb.actions containsObject:(NSString*)kAXPressAction]);
+
+ [cb performAction:kAXPressAction];
+ EXPECT([cb valueNumber] == 1);
+
+ [cb performAction:kAXPressAction];
+ EXPECT([cb valueNumber] == 0);
+
+ return true;
+}