diff options
Diffstat (limited to 'tests/auto/network')
36 files changed, 1417 insertions, 183 deletions
diff --git a/tests/auto/network/access/access.pro b/tests/auto/network/access/access.pro index bc76190e30..6ef10b7b1b 100644 --- a/tests/auto/network/access/access.pro +++ b/tests/auto/network/access/access.pro @@ -12,9 +12,11 @@ SUBDIRS=\ qftp \ qhttpnetworkreply \ qabstractnetworkcache \ + hpack !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qhttpnetworkconnection \ qhttpnetworkreply \ qftp \ + hpack \ diff --git a/tests/auto/network/access/hpack/hpack.pro b/tests/auto/network/access/hpack/hpack.pro new file mode 100644 index 0000000000..3c8b8e7944 --- /dev/null +++ b/tests/auto/network/access/hpack/hpack.pro @@ -0,0 +1,6 @@ +QT += core core-private network network-private testlib +CONFIG += testcase parallel_test c++14 +TEMPLATE = app +TARGET = tst_hpack + +SOURCES += tst_hpack.cpp diff --git a/tests/auto/network/access/hpack/tst_hpack.cpp b/tests/auto/network/access/hpack/tst_hpack.cpp new file mode 100644 index 0000000000..bd337c9f5f --- /dev/null +++ b/tests/auto/network/access/hpack/tst_hpack.cpp @@ -0,0 +1,852 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2014 Governikus GmbH & Co. KG. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <QtNetwork/private/bitstreams_p.h> +#include <QtNetwork/private/hpack_p.h> + +#include <QtCore/qbytearray.h> + +#include <cstdlib> +#include <vector> +#include <string> + +QT_USE_NAMESPACE + +using namespace HPack; + +class tst_Hpack: public QObject +{ + Q_OBJECT + +public: + tst_Hpack(); +private Q_SLOTS: + void bitstreamConstruction(); + void bitstreamWrite(); + void bitstreamReadWrite(); + void bitstreamCompression(); + void bitstreamErrors(); + + void lookupTableConstructor(); + + void lookupTableStatic_data(); + void lookupTableStatic(); + void lookupTableDynamic(); + + void hpackEncodeRequest_data(); + void hpackEncodeRequest(); + void hpackDecodeRequest_data(); + void hpackDecodeRequest(); + + void hpackEncodeResponse_data(); + void hpackEncodeResponse(); + void hpackDecodeResponse_data(); + void hpackDecodeResponse(); + + // TODO: more-more-more tests needed! + +private: + void hpackEncodeRequest(bool withHuffman); + void hpackEncodeResponse(bool withHuffman); + + HttpHeader header1; + std::vector<uchar> buffer1; + BitOStream request1; + + HttpHeader header2; + std::vector<uchar> buffer2; + BitOStream request2; + + HttpHeader header3; + std::vector<uchar> buffer3; + BitOStream request3; +}; + +using StreamError = BitIStream::Error; + +tst_Hpack::tst_Hpack() + : request1(buffer1), + request2(buffer2), + request3(buffer3) +{ +} + +void tst_Hpack::bitstreamConstruction() +{ + const uchar bytes[] = {0xDE, 0xAD, 0xBE, 0xEF}; + const int size = int(sizeof bytes); + + // Default ctors: + std::vector<uchar> buffer; + { + const BitOStream out(buffer); + QVERIFY(out.bitLength() == 0); + QVERIFY(out.byteLength() == 0); + + const BitIStream in; + QVERIFY(in.bitLength() == 0); + QVERIFY(in.streamOffset() == 0); + QVERIFY(in.error() == StreamError::NoError); + } + + // Create istream with some data: + { + BitIStream in(bytes, bytes + size); + QVERIFY(in.bitLength() == size * 8); + QVERIFY(in.streamOffset() == 0); + QVERIFY(in.error() == StreamError::NoError); + // 'Read' some data back: + for (int i = 0; i < size; ++i) { + uchar bitPattern = 0; + const auto bitsRead = in.peekBits(i * 8, 8, &bitPattern); + QVERIFY(bitsRead == 8); + QVERIFY(bitPattern == bytes[i]); + } + } + + // Copy ctors: + { + // Ostreams - copy is disabled. + // Istreams: + const BitIStream in1; + const BitIStream in2(in1); + QVERIFY(in2.bitLength() == in1.bitLength()); + QVERIFY(in2.streamOffset() == in1.streamOffset()); + QVERIFY(in2.error() == StreamError::NoError); + + const BitIStream in3(bytes, bytes + size); + const BitIStream in4(in3); + QVERIFY(in4.bitLength() == in3.bitLength()); + QVERIFY(in4.streamOffset() == in3.streamOffset()); + QVERIFY(in4.error() == StreamError::NoError); + } +} + +void tst_Hpack::bitstreamWrite() +{ + // Known representations, + // https://http2.github.io/http2-spec/compression.html. + // 5.1 Integer Representation + + // Test bit/byte lengths of the + // resulting data: + std::vector<uchar> buffer; + BitOStream out(buffer); + out.write(3); + // 11, fits into 8-bit prefix: + QVERIFY(out.bitLength() == 8); + QVERIFY(out.byteLength() == 1); + QVERIFY(out.begin()[0] == 3); + + out.clear(); + QVERIFY(out.bitLength() == 0); + QVERIFY(out.byteLength() == 0); + + // This number does not fit into 8-bit + // prefix we'll need 2 bytes: + out.write(256); + QVERIFY(out.byteLength() == 2); + QVERIFY(out.bitLength() == 16); + QVERIFY(out.begin()[0] == 0xff); + QVERIFY(out.begin()[1] == 1); + + out.clear(); + + // See 5.2 String Literal Representation. + + // We use Huffman code, + // char 'a' has a prefix code 00011 (5 bits) + out.write(QByteArray("aaa", 3), true); + QVERIFY(out.byteLength() == 3); + QVERIFY(out.bitLength() == 24); + // Now we must have in our stream: + // 10000010 | 00011000| 11000111 + const uchar *encoded = out.begin(); + QVERIFY(encoded[0] == 0x82); + QVERIFY(encoded[1] == 0x18); + QVERIFY(encoded[2] == 0xC7); + // TODO: add more tests ... +} + +void tst_Hpack::bitstreamReadWrite() +{ + // We can write into the bit stream: + // 1) bit patterns + // 2) integers (see HPACK, 5.1) + // 3) string (see HPACK, 5.2) + std::vector<uchar> buffer; + BitOStream out(buffer); + out.writeBits(0xf, 3); + QVERIFY(out.byteLength() == 1); + QVERIFY(out.bitLength() == 3); + + // Now, read it back: + { + BitIStream in(out.begin(), out.end()); + uchar bitPattern = 0; + const auto bitsRead = in.peekBits(0, 3, &bitPattern); + // peekBits pack into the most significant byte/bit: + QVERIFY(bitsRead == 3); + QVERIFY((bitPattern >> 5) == 7); + } + + const quint32 testInt = 133; + out.write(testInt); + + // This integer does not fit into the current 5-bit prefix, + // so byteLength == 2. + QVERIFY(out.byteLength() == 2); + const auto bitLength = out.bitLength(); + QVERIFY(bitLength > 3); + + // Now, read it back: + { + BitIStream in(out.begin(), out.end()); + in.skipBits(3); // Bit pattern + quint32 value = 0; + QVERIFY(in.read(&value)); + QVERIFY(in.error() == StreamError::NoError); + QCOMPARE(value, testInt); + } + + const QByteArray testString("ABCDE", 5); + out.write(testString, true); // Compressed + out.write(testString, false); // Non-compressed + QVERIFY(out.byteLength() > 2); + QVERIFY(out.bitLength() > bitLength); + + // Now, read it back: + { + BitIStream in(out.begin(), out.end()); + in.skipBits(bitLength); // Bit pattern and integer + QByteArray value; + // Read compressed string first ... + QVERIFY(in.read(&value)); + QCOMPARE(value, testString); + QCOMPARE(in.error(), StreamError::NoError); + // Now non-compressed ... + QVERIFY(in.read(&value)); + QCOMPARE(value, testString); + QCOMPARE(in.error(), StreamError::NoError); + } +} + +void tst_Hpack::bitstreamCompression() +{ + // Similar to bitstreamReadWrite but + // writes/reads a lot of mixed strings/integers. + std::vector<std::string> strings; + std::vector<quint32> integers; + std::vector<bool> isA; // integer or string. + const std::string bytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()[]/*"); + const unsigned nValues = 100000; + + quint64 totalStringBytes = 0; + std::vector<uchar> buffer; + BitOStream out(buffer); + for (unsigned i = 0; i < nValues; ++i) { + const bool isString = std::rand() % 1000 > 500; + isA.push_back(isString); + if (!isString) { + integers.push_back(std::rand() % 1000); + out.write(integers.back()); + } else { + const auto start = std::rand() % (bytes.length() / 2); + auto end = start * 2; + if (!end) + end = bytes.length() / 2; + strings.push_back(bytes.substr(start, end - start)); + const auto &s = strings.back(); + totalStringBytes += s.size(); + QByteArray data(s.c_str(), int(s.size())); + const bool compressed(std::rand() % 1000 > 500); + out.write(data, compressed); + } + } + + qDebug() << "Compressed(?) byte length:" << out.byteLength() + << "total string bytes:" << totalStringBytes; + qDebug() << "total integer bytes (for quint32):" << integers.size() * sizeof(quint32); + + QVERIFY(out.byteLength() > 0); + QVERIFY(out.bitLength() > 0); + + BitIStream in(out.begin(), out.end()); + + for (unsigned i = 0, iS = 0, iI = 0; i < nValues; ++i) { + if (isA[i]) { + QByteArray data; + QVERIFY(in.read(&data)); + QCOMPARE(in.error(), StreamError::NoError); + QCOMPARE(data.toStdString(), strings[iS]); + ++iS; + } else { + quint32 value = 0; + QVERIFY(in.read(&value)); + QCOMPARE(in.error(), StreamError::NoError); + QCOMPARE(value, integers[iI]); + ++iI; + } + } +} + +void tst_Hpack::bitstreamErrors() +{ + { + BitIStream in; + quint32 val = 0; + QVERIFY(!in.read(&val)); + QCOMPARE(in.error(), StreamError::NotEnoughData); + } + { + // Integer in a stream, that does not fit into quint32. + const uchar bytes[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + BitIStream in(bytes, bytes + sizeof bytes); + quint32 val = 0; + QVERIFY(!in.read(&val)); + QCOMPARE(in.error(), StreamError::InvalidInteger); + } + { + const uchar byte = 0x82; // 1 - Huffman compressed, 2 - the (fake) byte length. + BitIStream in(&byte, &byte + 1); + QByteArray val; + QVERIFY(!in.read(&val)); + QCOMPARE(in.error(), StreamError::NotEnoughData); + } +} + +void tst_Hpack::lookupTableConstructor() +{ + { + FieldLookupTable nonIndexed(4096, false); + QVERIFY(nonIndexed.dynamicDataSize() == 0); + QVERIFY(nonIndexed.numberOfDynamicEntries() == 0); + QVERIFY(nonIndexed.numberOfStaticEntries() != 0); + QVERIFY(nonIndexed.numberOfStaticEntries() == nonIndexed.numberOfEntries()); + // Now we add some fake field and verify what 'non-indexed' means ... no search + // by name. + QVERIFY(nonIndexed.prependField("custom-key", "custom-value")); + // 54: 10 + 12 in name/value pair above + 32 required by HPACK specs ... + QVERIFY(nonIndexed.dynamicDataSize() == 54); + QVERIFY(nonIndexed.numberOfDynamicEntries() == 1); + QCOMPARE(nonIndexed.numberOfEntries(), nonIndexed.numberOfStaticEntries() + 1); + // Should fail to find it (invalid index 0) - search is disabled. + QVERIFY(nonIndexed.indexOf("custom-key", "custom-value") == 0); + } + { + // "key" + "value" == 8 bytes, + 32 (HPACK's requirement) == 40. + // Let's ask for a max-size 32 so that entry does not fit: + FieldLookupTable nonIndexed(32, false); + QVERIFY(nonIndexed.prependField("key", "value")); + QVERIFY(nonIndexed.numberOfEntries() == nonIndexed.numberOfStaticEntries()); + QVERIFY(nonIndexed.indexOf("key", "value") == 0); + } + { + FieldLookupTable indexed(4096, true); + QVERIFY(indexed.dynamicDataSize() == 0); + QVERIFY(indexed.numberOfDynamicEntries() == 0); + QVERIFY(indexed.numberOfStaticEntries() != 0); + QVERIFY(indexed.numberOfStaticEntries() == indexed.numberOfEntries()); + QVERIFY(indexed.prependField("custom-key", "custom-value")); + QVERIFY(indexed.dynamicDataSize() == 54); + QVERIFY(indexed.numberOfDynamicEntries() == 1); + QVERIFY(indexed.numberOfEntries() == indexed.numberOfStaticEntries() + 1); + QVERIFY(indexed.indexOf("custom-key") == indexed.numberOfStaticEntries() + 1); + QVERIFY(indexed.indexOf("custom-key", "custom-value") == indexed.numberOfStaticEntries() + 1); + } +} + +void tst_Hpack::lookupTableStatic_data() +{ + QTest::addColumn<QByteArray>("expectedName"); + QTest::addColumn<QByteArray>("expectedValue"); + + // Some predefined fields to find + // (they are always defined/required by HPACK). + QTest::newRow(":authority|") << QByteArray(":authority") << QByteArray(""); + QTest::newRow(":method|GET") << QByteArray(":method") << QByteArray("GET"); + QTest::newRow(":method|POST") << QByteArray(":method") << QByteArray("POST"); + QTest::newRow(":path|/") << QByteArray(":path") << QByteArray("/"); + QTest::newRow(":path|/index.html") << QByteArray(":path") << QByteArray("/index.html"); + QTest::newRow(":scheme|http") << QByteArray(":scheme") << QByteArray("http"); + QTest::newRow(":scheme|https") << QByteArray(":scheme") << QByteArray("https"); + QTest::newRow(":status|200") << QByteArray(":status") << QByteArray("200"); + QTest::newRow(":status|204") << QByteArray(":status") << QByteArray("204"); + QTest::newRow(":status|206") << QByteArray(":status") << QByteArray("206"); + QTest::newRow(":status|304") << QByteArray(":status") << QByteArray("304"); + QTest::newRow(":status|400") << QByteArray(":status") << QByteArray("400"); + QTest::newRow(":status|404") << QByteArray(":status") << QByteArray("404"); + QTest::newRow(":status|500") << QByteArray(":status") << QByteArray("500"); +} + +void tst_Hpack::lookupTableStatic() +{ + const FieldLookupTable table(0, false /*all static, no need in 'search index'*/); + + QFETCH(QByteArray, expectedName); + QFETCH(QByteArray, expectedValue); + + const quint32 index = table.indexOf(expectedName, expectedValue); + QVERIFY(index != 0); + + QByteArray name, value; + QVERIFY(table.field(index, &name, &value)); + QCOMPARE(name, expectedName); + QCOMPARE(value, expectedValue); +} + +void tst_Hpack::lookupTableDynamic() +{ + // HPACK's table size: + // for every field -> size += field.name.length() + field.value.length() + 32. + // Let's set some size limit and try to fill table with enough entries to have several + // items evicted. + const quint32 tableSize = 8192; + const char stringData[] = "abcdefghijklmnopABCDEFGHIJKLMNOP0123456789()[]:"; + const quint32 dataSize = sizeof stringData - 1; + + FieldLookupTable table(tableSize, true); + + std::vector<QByteArray> fieldsToFind; + quint32 evicted = 0; + + while (true) { + // Strings are repeating way too often, I want to + // have at least some items really evicted and not found, + // therefore these weird dances with start/len. + const quint32 start = std::rand() % (dataSize - 10); + quint32 len = std::rand() % (dataSize - start); + if (!len) + len = 1; + + const QByteArray val(stringData + start, len); + fieldsToFind.push_back(val); + const quint32 entriesBefore = table.numberOfDynamicEntries(); + QVERIFY(table.prependField(val, val)); + QVERIFY(table.indexOf(val)); + QVERIFY(table.indexOf(val) == table.indexOf(val, val)); + QByteArray fieldName, fieldValue; + table.field(table.indexOf(val), &fieldName, &fieldValue); + + QVERIFY(val == fieldName); + QVERIFY(val == fieldValue); + + if (table.numberOfDynamicEntries() <= entriesBefore) { + // We had to evict several items ... + evicted += entriesBefore - table.numberOfDynamicEntries() + 1; + if (evicted >= 200) + break; + } + } + + QVERIFY(table.dynamicDataSize() <= tableSize); + QVERIFY(table.numberOfDynamicEntries() > 0); + QVERIFY(table.indexOf(fieldsToFind.back())); // We MUST have it in a table! + + using size_type = std::vector<QByteArray>::size_type; + for (size_type i = 0, e = fieldsToFind.size(); i < e; ++i) { + const auto &val = fieldsToFind[i]; + const quint32 index = table.indexOf(val); + if (!index) { + QVERIFY(i < size_type(evicted)); + } else { + QVERIFY(index == table.indexOf(val, val)); + QByteArray fieldName, fieldValue; + QVERIFY(table.field(index, &fieldName, &fieldValue)); + QVERIFY(val == fieldName); + QVERIFY(val == fieldValue); + } + } + + table.clearDynamicTable(); + + QVERIFY(table.numberOfDynamicEntries() == 0); + QVERIFY(table.dynamicDataSize() == 0); + QVERIFY(table.indexOf(fieldsToFind.back()) == 0); + + QVERIFY(table.prependField("name1", "value1")); + QVERIFY(table.prependField("name2", "value2")); + + QVERIFY(table.indexOf("name1") == table.numberOfStaticEntries() + 2); + QVERIFY(table.indexOf("name2", "value2") == table.numberOfStaticEntries() + 1); + QVERIFY(table.indexOf("name1", "value2") == 0); + QVERIFY(table.indexOf("name2", "value1") == 0); + QVERIFY(table.indexOf("name3") == 0); + + QVERIFY(!table.indexIsValid(table.numberOfEntries() + 1)); + + QVERIFY(table.prependField("name1", "value1")); + QVERIFY(table.numberOfDynamicEntries() == 3); + table.evictEntry(); + QVERIFY(table.indexOf("name1") != 0); + table.evictEntry(); + QVERIFY(table.indexOf("name2") == 0); + QVERIFY(table.indexOf("name1") != 0); + table.evictEntry(); + QVERIFY(table.dynamicDataSize() == 0); + QVERIFY(table.numberOfDynamicEntries() == 0); + QVERIFY(table.indexOf("name1") == 0); +} + +void tst_Hpack::hpackEncodeRequest_data() +{ + QTest::addColumn<bool>("compression"); + QTest::newRow("no-string-compression") << false; + QTest::newRow("with-string-compression") << true; +} + +void tst_Hpack::hpackEncodeRequest(bool withHuffman) +{ + // This function uses examples from HPACK specs + // (see appendix). + + Encoder encoder(4096, withHuffman); + // HPACK, C.3.1 First Request + /* + :method: GET + :scheme: http + :path: / + :authority: www.example.com + + Hex dump of encoded data (without Huffman): + + 8286 8441 0f77 7777 2e65 7861 6d70 6c65 | ...A.www.example + 2e63 6f6d + + Hex dump of encoded data (with Huffman): + + 8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff + */ + request1.clear(); + header1 = {{":method", "GET"}, + {":scheme", "http"}, + {":path", "/"}, + {":authority", "www.example.com"}}; + QVERIFY(encoder.encodeRequest(request1, header1)); + QVERIFY(encoder.dynamicTableSize() == 57); + + // HPACK, C.3.2 Second Request + /* + Header list to encode: + + :method: GET + :scheme: http + :path: / + :authority: www.example.com + cache-control: no-cache + + Hex dump of encoded data (without Huffman): + + 8286 84be 5808 6e6f 2d63 6163 6865 + + Hex dump of encoded data (with Huffman): + + 8286 84be 5886 a8eb 1064 9cbf + */ + + request2.clear(); + header2 = {{":method", "GET"}, + {":scheme", "http"}, + {":path", "/"}, + {":authority", "www.example.com"}, + {"cache-control", "no-cache"}}; + encoder.encodeRequest(request2, header2); + QVERIFY(encoder.dynamicTableSize() == 110); + + // HPACK, C.3.3 Third Request + /* + Header list to encode: + + :method: GET + :scheme: https + :path: /index.html + :authority: www.example.com + custom-key: custom-value + + Hex dump of encoded data (without Huffman): + + 8287 85bf 400a 6375 7374 6f6d 2d6b 6579 + 0c63 7573 746f 6d2d 7661 6c75 65 + + Hex dump of encoded data (with Huffman): + + 8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 + a849 e95b b8e8 b4bf + */ + request3.clear(); + header3 = {{":method", "GET"}, + {":scheme", "https"}, + {":path", "/index.html"}, + {":authority", "www.example.com"}, + {"custom-key", "custom-value"}}; + encoder.encodeRequest(request3, header3); + QVERIFY(encoder.dynamicTableSize() == 164); +} + +void tst_Hpack::hpackEncodeRequest() +{ + QFETCH(bool, compression); + + hpackEncodeRequest(compression); + + // See comments above about these hex dumps ... + const uchar bytes1NH[] = {0x82, 0x86, 0x84, 0x41, + 0x0f, 0x77, 0x77, 0x77, + 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d}; + + const uchar bytes1WH[] = {0x82, 0x86, 0x84, 0x41, + 0x8c, 0xf1, 0xe3, 0xc2, + 0xe5, 0xf2, 0x3a, 0x6b, + 0xa0, 0xab, 0x90, 0xf4, + 0xff}; + + const uchar *hexDump1 = compression ? bytes1WH : bytes1NH; + const quint64 byteLength1 = compression ? sizeof bytes1WH : sizeof bytes1NH; + + QCOMPARE(request1.byteLength(), byteLength1); + QCOMPARE(request1.bitLength(), byteLength1 * 8); + + for (quint32 i = 0, e = request1.byteLength(); i < e; ++i) + QCOMPARE(hexDump1[i], request1.begin()[i]); + + const uchar bytes2NH[] = {0x82, 0x86, 0x84, 0xbe, + 0x58, 0x08, 0x6e, 0x6f, + 0x2d, 0x63, 0x61, 0x63, + 0x68, 0x65}; + + const uchar bytes2WH[] = {0x82, 0x86, 0x84, 0xbe, + 0x58, 0x86, 0xa8, 0xeb, + 0x10, 0x64, 0x9c, 0xbf}; + + const uchar *hexDump2 = compression ? bytes2WH : bytes2NH; + const auto byteLength2 = compression ? sizeof bytes2WH : sizeof bytes2NH; + QVERIFY(request2.byteLength() == byteLength2); + QVERIFY(request2.bitLength() == byteLength2 * 8); + for (quint32 i = 0, e = request2.byteLength(); i < e; ++i) + QCOMPARE(hexDump2[i], request2.begin()[i]); + + const uchar bytes3NH[] = {0x82, 0x87, 0x85, 0xbf, + 0x40, 0x0a, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, + 0x2d, 0x6b, 0x65, 0x79, + 0x0c, 0x63, 0x75, 0x73, + 0x74, 0x6f, 0x6d, 0x2d, + 0x76, 0x61, 0x6c, 0x75, + 0x65}; + const uchar bytes3WH[] = {0x82, 0x87, 0x85, 0xbf, + 0x40, 0x88, 0x25, 0xa8, + 0x49, 0xe9, 0x5b, 0xa9, + 0x7d, 0x7f, 0x89, 0x25, + 0xa8, 0x49, 0xe9, 0x5b, + 0xb8, 0xe8, 0xb4, 0xbf}; + + const uchar *hexDump3 = compression ? bytes3WH : bytes3NH; + const quint64 byteLength3 = compression ? sizeof bytes3WH : sizeof bytes3NH; + QCOMPARE(request3.byteLength(), byteLength3); + QCOMPARE(request3.bitLength(), byteLength3 * 8); + for (quint32 i = 0, e = request3.byteLength(); i < e; ++i) + QCOMPARE(hexDump3[i], request3.begin()[i]); +} + +void tst_Hpack::hpackDecodeRequest_data() +{ + QTest::addColumn<bool>("compression"); + QTest::newRow("no-string-compression") << false; + QTest::newRow("with-string-compression") << true; +} + +void tst_Hpack::hpackDecodeRequest() +{ + QFETCH(bool, compression); + hpackEncodeRequest(compression); + + QVERIFY(request1.byteLength()); + QVERIFY(request2.byteLength()); + QVERIFY(request3.byteLength()); + + Decoder decoder(4096); + BitIStream inputStream1(request1.begin(), request1.end()); + QVERIFY(decoder.decodeHeaderFields(inputStream1)); + QCOMPARE(decoder.dynamicTableSize(), quint32(57)); + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header1); + } + + BitIStream inputStream2{request2.begin(), request2.end()}; + QVERIFY(decoder.decodeHeaderFields(inputStream2)); + QCOMPARE(decoder.dynamicTableSize(), quint32(110)); + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header2); + } + + BitIStream inputStream3(request3.begin(), request3.end()); + QVERIFY(decoder.decodeHeaderFields(inputStream3)); + QCOMPARE(decoder.dynamicTableSize(), quint32(164)); + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header3); + } +} + +void tst_Hpack::hpackEncodeResponse_data() +{ + hpackEncodeRequest_data(); +} + +void tst_Hpack::hpackEncodeResponse() +{ + QFETCH(bool, compression); + + hpackEncodeResponse(compression); + + // TODO: we can also test bytes - using hex dumps from HPACK's specs, + // for now only test a table behavior/expected sizes. +} + +void tst_Hpack::hpackEncodeResponse(bool withCompression) +{ + Encoder encoder(256, withCompression); // 256 - this will result in entries evicted. + + // HPACK, C.5.1 First Response + /* + Header list to encode: + + :status: 302 + cache-control: private + date: Mon, 21 Oct 2013 20:13:21 GMT + location: https://www.example.com + */ + request1.clear(); + header1 = {{":status", "302"}, + {"cache-control", "private"}, + {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, + {"location", "https://www.example.com"}}; + + QVERIFY(encoder.encodeResponse(request1, header1)); + QCOMPARE(encoder.dynamicTableSize(), quint32(222)); + + // HPACK, C.5.2 Second Response + /* + + + The (":status", "302") header field is evicted from the dynamic + table to free space to allow adding the (":status", "307") header field. + + Header list to encode: + + :status: 307 + cache-control: private + date: Mon, 21 Oct 2013 20:13:21 GMT + location: https://www.example.com + */ + request2.clear(); + header2 = {{":status", "307"}, + {"cache-control", "private"}, + {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, + {"location", "https://www.example.com"}}; + QVERIFY(encoder.encodeResponse(request2, header2)); + QCOMPARE(encoder.dynamicTableSize(), quint32(222)); + + // HPACK, C.5.3 Third Response + /* + Several header fields are evicted from the dynamic table + during the processing of this header list. + + Header list to encode: + + :status: 200 + cache-control: private + date: Mon, 21 Oct 2013 20:13:22 GMT + location: https://www.example.com + content-encoding: gzip + set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 + */ + request3.clear(); + header3 = {{":status", "200"}, + {"cache-control", "private"}, + {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}, + {"location", "https://www.example.com"}, + {"content-encoding", "gzip"}, + {"set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}}; + QVERIFY(encoder.encodeResponse(request3, header3)); + QCOMPARE(encoder.dynamicTableSize(), quint32(215)); +} + +void tst_Hpack::hpackDecodeResponse_data() +{ + hpackEncodeRequest_data(); +} + +void tst_Hpack::hpackDecodeResponse() +{ + QFETCH(bool, compression); + + hpackEncodeResponse(compression); + + QVERIFY(request1.byteLength()); + Decoder decoder(256); // This size will result in entries evicted. + BitIStream inputStream1(request1.begin(), request1.end()); + QVERIFY(decoder.decodeHeaderFields(inputStream1)); + QCOMPARE(decoder.dynamicTableSize(), quint32(222)); + + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header1); + } + + QVERIFY(request2.byteLength()); + BitIStream inputStream2(request2.begin(), request2.end()); + QVERIFY(decoder.decodeHeaderFields(inputStream2)); + QCOMPARE(decoder.dynamicTableSize(), quint32(222)); + + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header2); + } + + QVERIFY(request3.byteLength()); + BitIStream inputStream3(request3.begin(), request3.end()); + QVERIFY(decoder.decodeHeaderFields(inputStream3)); + QCOMPARE(decoder.dynamicTableSize(), quint32(215)); + + { + const auto &decoded = decoder.decodedHeader(); + QVERIFY(decoded == header3); + } +} + +QTEST_MAIN(tst_Hpack) + +#include "tst_hpack.moc" diff --git a/tests/auto/network/access/qftp/qftp.pro b/tests/auto/network/access/qftp/qftp.pro index 4294f27e74..6f1a4a7543 100644 --- a/tests/auto/network/access/qftp/qftp.pro +++ b/tests/auto/network/access/qftp/qftp.pro @@ -4,10 +4,3 @@ SOURCES += tst_qftp.cpp requires(contains(QT_CONFIG,private_tests)) QT = core network network-private testlib - -wince { - addFiles.files = rfc3252.txt - addFiles.path = . - DEPLOYMENT += addFiles -} - diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp index edeb471401..a13fa86405 100644 --- a/tests/auto/network/access/qftp/tst_qftp.cpp +++ b/tests/auto/network/access/qftp/tst_qftp.cpp @@ -276,14 +276,9 @@ void tst_QFtp::init() inFileDirExistsFunction = false; -#if !defined(Q_OS_WINCE) srand(time(0)); uniqueExtension = QString::number((quintptr)this) + QString::number(rand()) + QString::number((qulonglong)time(0)); -#else - srand(0); - uniqueExtension = QString::number((quintptr)this) + QString::number(rand()) + QLatin1Char('0'); -#endif } void tst_QFtp::cleanup() @@ -1353,11 +1348,7 @@ void tst_QFtp::abort_data() QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray(); // Qt/CE test environment has too little memory for this test -#if !defined(Q_OS_WINCE) QByteArray bigData( 10*1024*1024, 0 ); -#else - QByteArray bigData( 1*1024*1024, 0 ); -#endif bigData.fill( 'B' ); QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData; } diff --git a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro index bd10c77252..d3a92436ac 100644 --- a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro +++ b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -!winrt:!wince: SUBDIRS += echo +!winrt:SUBDIRS += echo test.depends += $$SUBDIRS SUBDIRS += test diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 21a84dfbb2..9ce6fe6256 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -205,6 +205,7 @@ private Q_SLOTS: void invalidProtocol(); void getFromData_data(); void getFromData(); + void getFromFile_data(); void getFromFile(); void getFromFileSpecial_data(); void getFromFileSpecial(); @@ -650,8 +651,10 @@ private slots: #endif void slotError(QAbstractSocket::SocketError err) { - Q_ASSERT(!client.isNull()); - qDebug() << "slotError" << err << client->errorString(); + if (client.isNull()) + qDebug() << "slotError" << err; + else + qDebug() << "slotError" << err << client->errorString(); } public slots: @@ -1674,14 +1677,26 @@ void tst_QNetworkReply::getFromData() QCOMPARE(reply->readAll(), expected); } +void tst_QNetworkReply::getFromFile_data() +{ + QTest::addColumn<bool>("backgroundAttribute"); + + QTest::newRow("no-background-attribute") << false; + QTest::newRow("background-attribute") << true; +} + void tst_QNetworkReply::getFromFile() { + QFETCH(bool, backgroundAttribute); + // create the file: QTemporaryFile file(QDir::currentPath() + "/temp-XXXXXX"); file.setAutoRemove(true); QVERIFY2(file.open(), qPrintable(file.errorString())); QNetworkRequest request(QUrl::fromLocalFile(file.fileName())); + if (backgroundAttribute) + request.setAttribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(true)); QNetworkReplyPtr reply; static const char fileData[] = "This is some data that is in the file.\r\n"; @@ -1691,6 +1706,7 @@ void tst_QNetworkReply::getFromFile() QCOMPARE(file.size(), qint64(data.size())); RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); + QVERIFY(waitForFinish(reply) != Timeout); QCOMPARE(reply->url(), request.url()); QCOMPARE(reply->error(), QNetworkReply::NoError); @@ -4319,9 +4335,6 @@ void tst_QNetworkReply::ioPutToFileFromProcess() QSKIP("No qprocess support", SkipAll); #else -#if defined(Q_OS_WINCE) - QSKIP("Currently no stdin/out supported for Windows CE"); -#else #ifdef Q_OS_WIN if (qstrcmp(QTest::currentDataTag(), "small") == 0) QSKIP("When passing a CR-LF-LF sequence through Windows stdio, it gets converted, " @@ -4355,7 +4368,6 @@ void tst_QNetworkReply::ioPutToFileFromProcess() QCOMPARE(file.size(), qint64(data.size())); QByteArray contents = file.readAll(); QCOMPARE(contents, data); -#endif #endif // QT_NO_PROCESS } @@ -6561,12 +6573,7 @@ void tst_QNetworkReply::getFromHttpIntoBuffer2() QFETCH(bool, useDownloadBuffer); // On my Linux Desktop the results are already visible with 128 kB, however we use this to have good results. -#if defined(Q_OS_WINCE_WM) - // Show some mercy to non-desktop platform/s - enum {UploadSize = 4*1024*1024}; // 4 MB -#else enum {UploadSize = 32*1024*1024}; // 32 MB -#endif GetFromHttpIntoBuffer2Server server(UploadSize, true, false); @@ -7888,10 +7895,6 @@ void tst_QNetworkReply::backgroundRequestInterruption() QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original); QVERIFY(reply->isFinished()); -#ifdef Q_OS_OSX - if (QSysInfo::MacintoshVersion == QSysInfo::MV_10_8) - QEXPECT_FAIL("ftp, bg, nobg", "See QTBUG-32435", Abort); -#endif QCOMPARE(reply->error(), error); #endif } diff --git a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro index 19d74dfd9b..a79fa2f59d 100644 --- a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro +++ b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro @@ -5,10 +5,4 @@ SOURCES += tst_qhostaddress.cpp QT = core network testlib -win32: { -wince { - LIBS += -lws2 -} else { - LIBS += -lws2_32 -} -} +win32:LIBS += -lws2_32 diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 4fb97fe1f2..419c781aab 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -62,6 +62,8 @@ private slots: void specialAddresses(); void compare_data(); void compare(); + void isEqual_data(); + void isEqual(); void assignment(); void scopeId(); void hashKey(); @@ -291,6 +293,7 @@ void tst_QHostAddress::compare_data() QTest::newRow("5") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Broadcast) << false; QTest::newRow("6") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << false; QTest::newRow("7") << QHostAddress() << QHostAddress(QHostAddress::LocalHostIPv6) << false; + QTest::newRow("any4-any6") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::AnyIPv6) << false; Q_IPV6ADDR localhostv4mapped = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1 } }; QTest::newRow("v4-v4mapped") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("::ffff:127.0.0.1") << false; @@ -309,6 +312,53 @@ void tst_QHostAddress::compare() QCOMPARE(qHash(first), qHash(second)); } +void tst_QHostAddress::isEqual_data() +{ + QTest::addColumn<QHostAddress>("first"); + QTest::addColumn<QHostAddress>("second"); + QTest::addColumn<int>("flags"); + QTest::addColumn<bool>("result"); + + // QHostAddress::StrictConversion is already tested in compare() + QTest::newRow("localhost4to6-local") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertLocalHost << true; + QTest::newRow("localhost4to6-compat") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertV4CompatToIPv4 << false; + QTest::newRow("localhost4to6-mapped") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertV4MappedToIPv4 << false; + QTest::newRow("localhost4to6-unspec") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertUnspecifiedAddress << false; + QTest::newRow("0.0.0.1-::1-local") << QHostAddress("0.0.0.1") << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("v4-v4compat-local") << QHostAddress("192.168.1.1") << QHostAddress("::192.168.1.1") << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("v4-v4mapped-local") << QHostAddress("192.168.1.1") << QHostAddress("::ffff:192.168.1.1") << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("0.0.0.1-::1-unspec") << QHostAddress("0.0.0.1") << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertUnspecifiedAddress << false; + QTest::newRow("v4-v4compat-unspec") << QHostAddress("192.168.1.1") << QHostAddress("::192.168.1.1") << (int)QHostAddress::ConvertUnspecifiedAddress << false; + QTest::newRow("v4-v4mapped-unspec") << QHostAddress("192.168.1.1") << QHostAddress("::ffff:192.168.1.1") << (int)QHostAddress::ConvertUnspecifiedAddress << false; + QTest::newRow("0.0.0.1-::1-compat") << QHostAddress("0.0.0.1") << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertV4CompatToIPv4 << false; + QTest::newRow("v4-v4compat-compat") << QHostAddress("192.168.1.1") << QHostAddress("::192.168.1.1") << (int)QHostAddress::ConvertV4CompatToIPv4 << true; + QTest::newRow("v4-v4mapped-compat") << QHostAddress("192.168.1.1") << QHostAddress("::ffff:192.168.1.1") << (int)QHostAddress::ConvertV4CompatToIPv4 << false; + QTest::newRow("0.0.0.1-::1-mapped") << QHostAddress("0.0.0.1") << QHostAddress(QHostAddress::LocalHostIPv6) << (int)QHostAddress::ConvertV4MappedToIPv4 << false; + QTest::newRow("v4-v4compat-mapped") << QHostAddress("192.168.1.1") << QHostAddress("::192.168.1.1") << (int)QHostAddress::ConvertV4MappedToIPv4 << false; + QTest::newRow("v4-v4mapped-mapped") << QHostAddress("192.168.1.1") << QHostAddress("::FFFF:192.168.1.1") << (int)QHostAddress::ConvertV4MappedToIPv4 << true; + QTest::newRow("undef-any-local") << QHostAddress() << QHostAddress(QHostAddress::Any) << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("undef-any-unspec") << QHostAddress() << QHostAddress(QHostAddress::Any) << (int)QHostAddress::ConvertUnspecifiedAddress << false; + QTest::newRow("anyv6-anyv4-compat") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertV4CompatToIPv4 << true; + QTest::newRow("anyv6-anyv4-mapped") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertV4MappedToIPv4 << false; + QTest::newRow("anyv6-anyv4-unspec") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertUnspecifiedAddress << true; + QTest::newRow("any-anyv4-unspec") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertUnspecifiedAddress << true; + QTest::newRow("any-anyv6-unspec") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::ConvertUnspecifiedAddress << true; + QTest::newRow("anyv6-anyv4-local") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("any-anyv4-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("any-anyv6-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::ConvertLocalHost << false; +} + +void tst_QHostAddress::isEqual() +{ + QFETCH(QHostAddress, first); + QFETCH(QHostAddress, second); + QFETCH(int, flags); + QFETCH(bool, result); + + QCOMPARE(first.isEqual(second, QHostAddress::ConversionModeFlag(flags)), result); + QCOMPARE(second.isEqual(first, QHostAddress::ConversionModeFlag(flags)), result); +} + void tst_QHostAddress::assignment() { QHostAddress address; diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro index 12858c97ee..4ea415c529 100644 --- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro +++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro @@ -6,11 +6,7 @@ SOURCES += tst_qhostinfo.cpp requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib -wince { - LIBS += ws2.lib -} else { - win32:LIBS += -lws2_32 -} +win32:LIBS += -lws2_32 # needed for getaddrinfo with official MinGW mingw:DEFINES += _WIN32_WINNT=0x0501 diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index 13d4442ada..f6d9b71aa2 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -66,11 +66,7 @@ #include "private/qhostinfo_p.h" #if !defined(QT_NO_GETADDRINFO) -# if !defined(Q_OS_WINCE) # include <sys/types.h> -# else -# include <types.h> -# endif # if defined(Q_OS_UNIX) # include <sys/socket.h> # endif @@ -399,11 +395,7 @@ protected: void tst_QHostInfo::threadSafety() { const int nattempts = 5; -#if defined(Q_OS_WINCE) - const int runs = 10; -#else const int runs = 100; -#endif LookupThread thr[nattempts]; for (int j = 0; j < runs; ++j) { for (int i = 0; i < nattempts; ++i) diff --git a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri index a3b4e89450..6c7857ea1d 100644 --- a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri +++ b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri @@ -4,13 +4,7 @@ QNETWORK_SRC = $$QT_SOURCE_TREE/src/network INCLUDEPATH += $$QNETWORK_SRC -win32 { - wince { - LIBS += -lws2 - } else { - LIBS += -lws2_32 - } -} +win32:LIBS += -lws2_32 unix:contains(QT_CONFIG, reduce_exports) { SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp index 041a0ce16c..d159d6d683 100644 --- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp @@ -494,9 +494,6 @@ void tst_PlatformSocketEngine::readWriteBufferSize() qint64 bufferSize = device.receiveBufferSize(); QVERIFY(bufferSize != -1); device.setReceiveBufferSize(bufferSize + 1); -#if defined(Q_OS_WINCE) - QEXPECT_FAIL(0, "Not supported by default on WinCE", Continue); -#endif QVERIFY(device.receiveBufferSize() > bufferSize); bufferSize = device.sendBufferSize(); @@ -649,7 +646,7 @@ void tst_PlatformSocketEngine::receiveUrgentData() QByteArray response; // Native OOB data test doesn't work on HP-UX or WinCE -#if !defined(Q_OS_HPUX) && !defined(Q_OS_WINCE) +#if !defined(Q_OS_HPUX) // The server sends an urgent message msg = 'Q'; QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); diff --git a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp index 7237542e5c..68f3ea059b 100644 --- a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp +++ b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp @@ -626,11 +626,7 @@ void tst_QHttpSocketEngine::downloadBigFile() QTime stopWatch; stopWatch.start(); -#if defined(Q_OS_WINCE) - QTestEventLoop::instance().enterLoop(240); -#else QTestEventLoop::instance().enterLoop(60); -#endif if (QTestEventLoop::instance().timeout()) QFAIL("Network operation timed out"); diff --git a/tests/auto/network/socket/qlocalsocket/test/test.pro b/tests/auto/network/socket/qlocalsocket/test/test.pro index 6a5df7f9b6..ab9ed90b1d 100644 --- a/tests/auto/network/socket/qlocalsocket/test/test.pro +++ b/tests/auto/network/socket/qlocalsocket/test/test.pro @@ -2,13 +2,7 @@ CONFIG += testcase DEFINES += QLOCALSERVER_DEBUG DEFINES += QLOCALSOCKET_DEBUG - -wince* { - DEFINES += QT_LOCALSOCKET_TCP - DEFINES += SRCDIR=\\\"../\\\" -} else { - DEFINES += SRCDIR=\\\"$$PWD/../\\\" -} +DEFINES += SRCDIR=\\\"$$PWD/../\\\" QT = core network testlib diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 4bea9b116c..00e01094a4 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -867,10 +867,8 @@ void tst_QLocalSocket::threadedConnection_data() QTest::newRow("1 client") << 1; QTest::newRow("2 clients") << 2; QTest::newRow("5 clients") << 5; -#ifndef Q_OS_WINCE QTest::newRow("10 clients") << 10; QTest::newRow("20 clients") << 20; -#endif } void tst_QLocalSocket::threadedConnection() diff --git a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp index b4955df107..c945d77cda 100644 --- a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp +++ b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp @@ -785,11 +785,7 @@ void tst_QSocks5SocketEngine::downloadBigFile() QTime stopWatch; stopWatch.start(); -#if !defined(Q_OS_WINCE) QTestEventLoop::instance().enterLoop(60); -#else - QTestEventLoop::instance().enterLoop(180); -#endif if (QTestEventLoop::instance().timeout()) QFAIL("Network operation timed out"); diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp index fdf1c48adf..1a8e7920d3 100644 --- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp +++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp @@ -47,16 +47,8 @@ int main(int argc, char *argv[]) return 1; } -#if defined(Q_OS_WINCE) - QFile file(QLatin1String("/test_signal.txt")); - file.open(QIODevice::WriteOnly); - file.write("Listening\n"); - file.flush(); - file.close(); -#else printf("Listening\n"); fflush(stdout); -#endif server.waitForNewConnection(5000); qFatal("Crash"); diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro index f0abfbc085..4491523383 100644 --- a/tests/auto/network/socket/qtcpserver/test/test.pro +++ b/tests/auto/network/socket/qtcpserver/test/test.pro @@ -1,16 +1,7 @@ CONFIG += testcase SOURCES += ../tst_qtcpserver.cpp -win32: { -wince { - LIBS += -lws2 - crashApp.files = ../crashingServer/crashingServer.exe - crashApp.path = crashingServer - DEPLOYMENT += crashApp -} else { - LIBS += -lws2_32 -} -} +win32:LIBS += -lws2_32 TARGET = ../tst_qtcpserver diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp index 30aab3bf34..5a0baf73b5 100644 --- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp @@ -106,6 +106,8 @@ private slots: void eagainBlockingAccept(); + void canAccessPendingConnectionsWhileNotListening(); + private: #ifndef QT_NO_BEARERMANAGEMENT QNetworkSession *networkSession; @@ -467,11 +469,7 @@ void tst_QTcpServer::waitForConnectionTest() ThreadConnector connector(findLocalIpSocket.localAddress(), server.serverPort()); connector.start(); -#if defined(Q_OS_WINCE) - QVERIFY(server.waitForNewConnection(9000, &timeout)); -#else QVERIFY(server.waitForNewConnection(3000, &timeout)); -#endif QVERIFY(!timeout); } @@ -562,21 +560,6 @@ void tst_QTcpServer::addressReusable() QSKIP("No proxy support"); #endif // QT_NO_NETWORKPROXY } -#if defined(Q_OS_WINCE) - QString signalName = QString::fromLatin1("/test_signal.txt"); - QFile::remove(signalName); - // The crashingServer process will crash once it gets a connection. - QProcess process; - QString processExe = crashingServerDir + "/crashingServer"; - process.start(processExe); - QVERIFY2(process.waitForStarted(), qPrintable( - QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString()))); - int waitCount = 5; - while (waitCount-- && !QFile::exists(signalName)) - QTest::qWait(1000); - QVERIFY(QFile::exists(signalName)); - QFile::remove(signalName); -#else // The crashingServer process will crash once it gets a connection. QProcess process; QString processExe = crashingServerDir + "/crashingServer"; @@ -584,7 +567,6 @@ void tst_QTcpServer::addressReusable() QVERIFY2(process.waitForStarted(), qPrintable( QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString()))); QVERIFY(process.waitForReadyRead(5000)); -#endif QTcpSocket socket; socket.connectToHost(QHostAddress::LocalHost, 49199); @@ -990,5 +972,22 @@ void tst_QTcpServer::eagainBlockingAccept() server.close(); } +class NonListeningTcpServer : public QTcpServer +{ +public: + void addSocketFromOutside(QTcpSocket* s) + { + addPendingConnection(s); + } +}; + +void tst_QTcpServer::canAccessPendingConnectionsWhileNotListening() +{ + NonListeningTcpServer server; + QTcpSocket socket; + server.addSocketFromOutside(&socket); + QCOMPARE(&socket, server.nextPendingConnection()); +} + QTEST_MAIN(tst_QTcpServer) #include "tst_qtcpserver.moc" diff --git a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro index fe6042b8a7..5686f4a697 100644 --- a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro +++ b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs SUBDIRS = test -!wince:!vxworks: SUBDIRS += stressTest +!vxworks: SUBDIRS += stressTest requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro index 325abcaab8..2dc1490256 100644 --- a/tests/auto/network/socket/qtcpsocket/test/test.pro +++ b/tests/auto/network/socket/qtcpsocket/test/test.pro @@ -2,13 +2,7 @@ CONFIG += testcase QT = core-private network-private testlib SOURCES += ../tst_qtcpsocket.cpp -win32: { -wince { - LIBS += -lws2 -} else { - LIBS += -lws2_32 -} -} +win32:LIBS += -lws2_32 TARGET = tst_qtcpsocket diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index 8ad16c652d..efa50b21b4 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -15,12 +15,6 @@ win32 { DESTDIR = ../ } -wince* { - addApp.files = ../clientserver/clientserver.exe - addApp.path = clientserver - DEPLOYMENT += addApp -} - TARGET = tst_qudpsocket CONFIG+=insignificant_test # QTBUG-25367, QTBUG-25368 diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index ba49e8b041..942a074c87 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -435,13 +435,8 @@ void tst_QUdpSocket::ipv6Loop() char peterBuffer[16*1024]; char paulBuffer[16*1024]; -#if !defined(Q_OS_WINCE) - QVERIFY2(peter.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(peter).constData()); - QVERIFY2(paul.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(paul).constData()); -#else - QVERIFY(peter.waitForReadyRead(15000)); - QVERIFY(paul.waitForReadyRead(15000)); -#endif + QVERIFY(peter.waitForReadyRead(5000)); + QVERIFY(paul.waitForReadyRead(5000)); if (success) { QCOMPARE(peter.readDatagram(peterBuffer, sizeof(peterBuffer)), qint64(paulMessage.length())); QCOMPARE(paul.readDatagram(paulBuffer, sizeof(peterBuffer)), qint64(peterMessage.length())); @@ -938,9 +933,6 @@ void tst_QUdpSocket::outOfProcessConnectedClientServerTest() #ifdef QT_NO_PROCESS QSKIP("No qprocess support", SkipAll); #else -#if defined(Q_OS_WINCE) - QSKIP("This test depends on reading data from QProcess (not supported on Qt/WinCE)."); -#endif QProcess serverProcess; serverProcess.start(QLatin1String("clientserver/clientserver server 1 1"), QIODevice::ReadWrite | QIODevice::Text); @@ -1002,9 +994,6 @@ void tst_QUdpSocket::outOfProcessUnconnectedClientServerTest() #ifdef QT_NO_PROCESS QSKIP("No qprocess support", SkipAll); #else -#if defined(Q_OS_WINCE) - QSKIP("This test depends on reading data from QProcess (not supported on Qt/WinCE)."); -#endif QProcess serverProcess; serverProcess.start(QLatin1String("clientserver/clientserver server 1 1"), QIODevice::ReadWrite | QIODevice::Text); diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro index 87a210c051..7c1cd5b66b 100644 --- a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro +++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslcertificate.cpp -!wince:win32:LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core network testlib TARGET = tst_qsslcertificate diff --git a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro index 4cb2dfebab..81ef2d8d9a 100644 --- a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro +++ b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslcipher.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core network testlib TARGET = tst_qsslcipher diff --git a/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro b/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro new file mode 100644 index 0000000000..b8053f9eb3 --- /dev/null +++ b/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +CONFIG += parallel_test + +SOURCES += tst_qssldiffiehellmanparameters.cpp +!wince*:win32:LIBS += -lws2_32 +QT = core network testlib + +TARGET = tst_qssldiffiehellmanparameters diff --git a/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp b/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp new file mode 100644 index 0000000000..32cc982a65 --- /dev/null +++ b/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNetwork 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QSslDiffieHellmanParameters> +#include <QSslSocket> +#include <QByteArray> + +class tst_QSslDiffieHellmanParameters : public QObject +{ + Q_OBJECT + +#ifndef QT_NO_SSL +private Q_SLOTS: + void constructionEmpty(); + void constructionDefault(); + void constructionDER(); + void constructionPEM(); + void unsafe512Bits(); + void unsafeNonPrime(); +#endif +}; + +#ifndef QT_NO_SSL + +void tst_QSslDiffieHellmanParameters::constructionEmpty() +{ + QSslDiffieHellmanParameters dh; + + QCOMPARE(dh.isEmpty(), true); + QCOMPARE(dh.isValid(), true); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError); +} + +void tst_QSslDiffieHellmanParameters::constructionDefault() +{ + QSslDiffieHellmanParameters dh = QSslDiffieHellmanParameters::defaultParameters(); + +#ifndef QT_NO_OPENSSL + QCOMPARE(dh.isValid(), true); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError); +#endif +} + +void tst_QSslDiffieHellmanParameters::constructionDER() +{ + // Uniquely generated with 'openssl dhparam -outform DER -out out.der -check -2 4096' + QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral( + "MIICCAKCAgEAsbQYx57ZlyEyWF8jD5WYEswGR2aTVFsHqP3026SdyTwcjY+YlMOae0EagK" + "jDA0UlPcih1kguQOvOVgyc5gI3YbBb4pCNEdy048xITlsdqG7qC3+2VvFR3vfixEbQQll9" + "2cGIIneD/36p7KJcDnBNUwwWj/VJKhTwelTfKTj2T39si9xGMkqZiQuCaXRk6vSKZ4ZDPk" + "jiq5Ti1kHVFbL9SMWRa8zplPtDMrVfhSyw10njgD4qKd1UoUPdmhEPhRZlHaZ/cAHNSHMj" + "uhDakeMpN+XP2/sl5IpPZ3/vVOk9PhBDFO1NYzKx/b7RQgZCUmXoglKYpfBiz8OheoI0hK" + "V0fU/OCtHjRrP4hE9vIHA2aE+gaQZiYCciGcR9BjHQ7Y8K9qHyTX8UIz2G4ZKzQZK9G+pA" + "K0xD+1H3qZ/MaUhzNDQOwwihnTjjXzTjfIGqYDdbouAhw+tX51CsGonI0cL3s3QMa3CwGH" + "mw+AH2b/Z68dTSy0sC3CYn9cNbrctqyeHwQrsx9FfpOz+Z6sk2WsPgqgSp/pDVVgm5oSfO" + "2mN7WAWgUlf9TQuj1HIRCTI+PbBq2vYvn+YResMRo+8ng1QptKAAgQoVVGNRYxZ9iAZlvO" + "52DcHKlsqDuafQ1XVGmzVIrKtBi2gfLtPqY4v6g6v26l8gbzK67PpWstllHiPb4VMCAQI=" + )), QSsl::Der); + +#ifndef QT_NO_OPENSSL + QCOMPARE(dh.isValid(), true); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError); +#endif +} + +void tst_QSslDiffieHellmanParameters::constructionPEM() +{ + // Uniquely generated with 'openssl dhparam -outform PEM -out out.pem -check -2 4096' + QSslDiffieHellmanParameters dh(QByteArrayLiteral( + "-----BEGIN DH PARAMETERS-----\n" + "MIICCAKCAgEA9QTdqhQkbGuhWzBsW5X475AjjrITpg1BHX5+mp1sstUd84Lshq1T\n" + "+S2QQQtdl25EPoUblpyyLAf8krFSH4YwR7jjLWklA8paDOwRYod0zLmVZ1Wx6og3\n" + "PRc8P+SCs+6gKTXfv//bJJhiJXnM73lDFsGHbSqN+msf20ei/zy5Rwey2t8dPjLC\n" + "Q+qkb/avlovi2t2rsUWcxMT1875TQ4HuApayqw3R3lTQe9u05b9rTrinmT7AE4mm\n" + "xGqO9FZJdXYE2sOKwwJkpM48KFyV90uJANmqJnQrkgdukaGTHwxZxgAyO6ur/RWC\n" + "kzf9STFT6IY4Qy05q+oZVJfh8xPHszKmmC8nWaLfiHMYBnL5fv+1kh/aU11Kz9TG\n" + "iDXwQ+tzhKAutQPUwe3IGQUYQMZPwZI4vegdU88/7YPXuWt7b/0Il5+2ma5FbtG2\n" + "u02PMi+J3JZsYi/tEUv1tJBVHGH0kDpgcyOm8rvkCtNbNkETzfwUPoEgA0oPMhVt\n" + "sFGub1av+jLRyFNGNBJcqXAO+Tq2zXG00DxbGY+aooJ50qU/Lh5gfnCEMDXlMM9P\n" + "T8JVpWaaNLCC+0Z5txsfYp+FO8mOttIPIF6F8FtmTnm/jhNntvqKvsU+NHylIYzr\n" + "o42EpiWwS7ktPPUS2GtG+IUdy8rvdO1xJ5kNxs7ZlygY4W1htOhbUusCAQI=\n" + "-----END DH PARAMETERS-----\n" + ), QSsl::Pem); + +#ifndef QT_NO_OPENSSL + QCOMPARE(dh.isValid(), true); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError); +#endif +} + +void tst_QSslDiffieHellmanParameters::unsafe512Bits() +{ + // Uniquely generated with 'openssl dhparam -outform PEM -out out.pem -check -2 512' + QSslDiffieHellmanParameters dh(QByteArrayLiteral( + "-----BEGIN DH PARAMETERS-----\n" + "MEYCQQCf8goDn56akiliAtEL1ZG7VH+9wfLxsv8/B1emTUG+rMKB1yaVAU7HaAiM\n" + "Gtmo2bAWUqBczUTOTzqmWTm28P6bAgEC\n" + "-----END DH PARAMETERS-----\n" + ), QSsl::Pem); + +#ifndef QT_NO_OPENSSL + QCOMPARE(dh.isValid(), false); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::UnsafeParametersError); +#endif +} + +void tst_QSslDiffieHellmanParameters::unsafeNonPrime() +{ + // Uniquely generated with 'openssl dhparam -outform DER -out out.der -check -2 1024' + // and then modified by hand to make P not be a prime number. + QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral( + "MIGHAoGBALLcOLg+ow8TMnbCUeNjwys6wUTIH9mn4ZSeIbD6qvCsJgg4cUxXwJQmPY" + "Xl15AsKXgkXWh0n+/N6tjH0sSRJnzDvN2H3KxFLKkvxmBYrDOJMdCuMgZD50aOsVyd" + "vholAW9zilkoYkB6sqwxY1Z2dbpTWajCsUAWZQ0AIP4Y5nesAgEC" + )), QSsl::Der); + +#ifndef QT_NO_OPENSSL + QCOMPARE(dh.isValid(), false); + QCOMPARE(dh.error(), QSslDiffieHellmanParameters::UnsafeParametersError); +#endif +} + +#endif // QT_NO_SSL + +QTEST_MAIN(tst_QSslDiffieHellmanParameters) +#include "tst_qssldiffiehellmanparameters.moc" diff --git a/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro b/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro index e67b64b2b7..a180086c5e 100644 --- a/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro +++ b/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslellipticcurve.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core network testlib TARGET = tst_qsslellipticcurve diff --git a/tests/auto/network/ssl/qsslerror/qsslerror.pro b/tests/auto/network/ssl/qsslerror/qsslerror.pro index 7737aae3f1..117fd4ac27 100644 --- a/tests/auto/network/ssl/qsslerror/qsslerror.pro +++ b/tests/auto/network/ssl/qsslerror/qsslerror.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslerror.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core network testlib TARGET = tst_qsslerror diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro index 7eb04793f3..52377a9005 100644 --- a/tests/auto/network/ssl/qsslkey/qsslkey.pro +++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslkey.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core network testlib contains(QT_CONFIG, private_tests) { QT += core-private network-private diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro index de2be8e126..9a525408fd 100644 --- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro +++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslsocket.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core core-private network-private testlib TARGET = tst_qsslsocket @@ -20,14 +20,6 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { LIBS += $$OPENSSL_LIBS } -wince* { - DEFINES += SRCDIR=\\\"./\\\" - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles -} else { - DEFINES += SRCDIR=\\\"$$PWD/\\\" -} +DEFINES += SRCDIR=\\\"$$PWD/\\\" requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 17a3f3a4d0..c1ed865d02 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -219,6 +219,10 @@ private slots: void qtbug18498_peek(); void qtbug18498_peek2(); void dhServer(); +#ifndef QT_NO_OPENSSL + void dhServerCustomParamsNull(); + void dhServerCustomParams(); +#endif void ecdhServer(); void verifyClientCertificate_data(); void verifyClientCertificate(); @@ -228,6 +232,8 @@ private slots: void simplePskConnect(); void ephemeralServerKey_data(); void ephemeralServerKey(); + void allowedProtocolNegotiation(); + void pskServer(); #endif void setEmptyDefaultConfiguration(); // this test should be last @@ -2819,10 +2825,8 @@ void tst_QSslSocket::qtbug18498_peek2() void tst_QSslSocket::dhServer() { - if (!QSslSocket::supportsSsl()) { - qWarning("SSL not supported, skipping test"); - return; - } + if (!QSslSocket::supportsSsl()) + QSKIP("No SSL support"); QFETCH_GLOBAL(bool, setProxy); if (setProxy) @@ -2847,6 +2851,87 @@ void tst_QSslSocket::dhServer() QCOMPARE(client->state(), QAbstractSocket::ConnectedState); } +#ifndef QT_NO_OPENSSL +void tst_QSslSocket::dhServerCustomParamsNull() +{ + if (!QSslSocket::supportsSsl()) + QSKIP("No SSL support"); + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + SslServer server; + server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA"); + + QSslConfiguration cfg = server.config; + cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters()); + server.config = cfg; + + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + QSslSocketPtr client(new QSslSocket); + socket = client.data(); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit())); + + client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + loop.exec(); + + QVERIFY(client->state() != QAbstractSocket::ConnectedState); +} +#endif // QT_NO_OPENSSL + +#ifndef QT_NO_OPENSSL +void tst_QSslSocket::dhServerCustomParams() +{ + if (!QSslSocket::supportsSsl()) + QSKIP("No SSL support"); + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + SslServer server; + server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA"); + + QSslConfiguration cfg = server.config; + + // Custom 2048-bit DH parameters generated with 'openssl dhparam -outform DER -out out.der -check -2 2048' + QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral( + "MIIBCAKCAQEAvVA7b8keTfjFutCtTJmP/pnQfw/prKa+GMed/pBWjrC4N1YwnI8h/A861d9WE/VWY7XMTjvjX3/0" + "aaU8wEe0EXNpFdlTH+ZMQctQTSJOyQH0RCTwJfDGPCPT9L+c9GKwEKWORH38Earip986HJc0w3UbnfIwXUdsWHiXi" + "Z6r3cpyBmTKlsXTFiDVAOUXSiO8d/zOb6zHZbDfyB/VbtZRmnA7TXVn9oMzC0g9+FXHdrV4K+XfdvNZdCegvoAZiy" + "R6ZQgNG9aZ36/AQekhg060hp55f9HDPgXqYeNeXBiferjUtU7S9b3s83XhOJAr01/0Tf5dENwCfg2gK36TM8cC4wI" + "BAg==")), QSsl::Der); + cfg.setDiffieHellmanParameters(dh); + + server.config = cfg; + + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + QSslSocketPtr client(new QSslSocket); + socket = client.data(); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit())); + + client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + loop.exec(); + + QVERIFY(client->state() == QAbstractSocket::ConnectedState); +} +#endif // QT_NO_OPENSSL + void tst_QSslSocket::ecdhServer() { if (!QSslSocket::supportsSsl()) { @@ -3037,8 +3122,12 @@ class PskProvider : public QObject Q_OBJECT public: + bool m_server; + QByteArray m_identity; + QByteArray m_psk; + explicit PskProvider(QObject *parent = 0) - : QObject(parent) + : QObject(parent), m_server(false) { } @@ -3057,7 +3146,11 @@ public slots: { QVERIFY(authenticator); QCOMPARE(authenticator->identityHint(), PSK_SERVER_IDENTITY_HINT); - QVERIFY(authenticator->maximumIdentityLength() > 0); + if (m_server) + QCOMPARE(authenticator->maximumIdentityLength(), 0); + else + QVERIFY(authenticator->maximumIdentityLength() > 0); + QVERIFY(authenticator->maximumPreSharedKeyLength() > 0); if (!m_identity.isEmpty()) { @@ -3070,12 +3163,61 @@ public slots: QCOMPARE(authenticator->preSharedKey(), m_psk); } } - -private: - QByteArray m_identity; - QByteArray m_psk; }; +class PskServer : public QTcpServer +{ + Q_OBJECT +public: + PskServer() + : socket(0), + config(QSslConfiguration::defaultConfiguration()), + ignoreSslErrors(true), + peerVerifyMode(QSslSocket::AutoVerifyPeer), + protocol(QSsl::TlsV1_0), + m_pskProvider() + { + m_pskProvider.m_server = true; + } + QSslSocket *socket; + QSslConfiguration config; + bool ignoreSslErrors; + QSslSocket::PeerVerifyMode peerVerifyMode; + QSsl::SslProtocol protocol; + QString ciphers; + PskProvider m_pskProvider; + +protected: + void incomingConnection(qintptr socketDescriptor) + { + socket = new QSslSocket(this); + socket->setSslConfiguration(config); + socket->setPeerVerifyMode(peerVerifyMode); + socket->setProtocol(protocol); + if (ignoreSslErrors) + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + + if (!ciphers.isEmpty()) { + socket->setCiphers(ciphers); + } + + QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); + QVERIFY(!socket->peerAddress().isNull()); + QVERIFY(socket->peerPort() != 0); + QVERIFY(!socket->localAddress().isNull()); + QVERIFY(socket->localPort() != 0); + + connect(socket, &QSslSocket::preSharedKeyAuthenticationRequired, &m_pskProvider, &PskProvider::providePsk); + + socket->startServerEncryption(); + } + +protected slots: + void ignoreErrorSlot() + { + socket->ignoreSslErrors(); + } +}; void tst_QSslSocket::simplePskConnect_data() { QTest::addColumn<PskConnectTestType>("pskTestType"); @@ -3377,6 +3519,129 @@ void tst_QSslSocket::ephemeralServerKey() QCOMPARE(client->sslConfiguration().ephemeralServerKey().isNull(), emptyKey); } +void tst_QSslSocket::allowedProtocolNegotiation() +{ +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT) + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + const QByteArray expectedNegotiated("cool-protocol"); + QList<QByteArray> serverProtos; + serverProtos << expectedNegotiated << "not-so-cool-protocol"; + QList<QByteArray> clientProtos; + clientProtos << "uber-cool-protocol" << expectedNegotiated << "not-so-cool-protocol"; + + + SslServer server; + server.config.setAllowedNextProtocols(serverProtos); + QVERIFY(server.listen()); + + QSslSocket clientSocket; + auto configuration = clientSocket.sslConfiguration(); + configuration.setAllowedNextProtocols(clientProtos); + clientSocket.setSslConfiguration(configuration); + + clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort()); + clientSocket.ignoreSslErrors(); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit())); + loop.exec(); + + QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() == + clientSocket.sslConfiguration().nextNegotiatedProtocol()); + QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() == expectedNegotiated); + +#endif // OPENSSL_VERSION_NUMBER +} + +void tst_QSslSocket::pskServer() +{ + QFETCH_GLOBAL(bool, setProxy); + if (!QSslSocket::supportsSsl() || setProxy) + return; + + QSslSocket socket; + this->socket = &socket; + + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + QVERIFY(connectedSpy.isValid()); + + QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected())); + QVERIFY(disconnectedSpy.isValid()); + + QSignalSpy connectionEncryptedSpy(&socket, SIGNAL(encrypted())); + QVERIFY(connectionEncryptedSpy.isValid()); + + QSignalSpy pskAuthenticationRequiredSpy(&socket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*))); + QVERIFY(pskAuthenticationRequiredSpy.isValid()); + + connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(disconnected()), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(peerVerifyError(QSslError)), this, SLOT(exitLoop())); + connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop())); + + // force a PSK cipher w/o auth + socket.setCiphers(PSK_CIPHER_WITHOUT_AUTH); + + PskProvider provider; + provider.setIdentity(PSK_CLIENT_IDENTITY); + provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY); + connect(&socket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), &provider, SLOT(providePsk(QSslPreSharedKeyAuthenticator*))); + socket.setPeerVerifyMode(QSslSocket::VerifyNone); + + PskServer server; + server.m_pskProvider.setIdentity(provider.m_identity); + server.m_pskProvider.setPreSharedKey(provider.m_psk); + server.config.setPreSharedKeyIdentityHint(PSK_SERVER_IDENTITY_HINT); + QVERIFY(server.listen()); + + // Start connecting + socket.connectToHost(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + enterLoop(5); + + // Entered connected state + QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); + QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode); + QVERIFY(!socket.isEncrypted()); + QCOMPARE(connectedSpy.count(), 1); + QCOMPARE(disconnectedSpy.count(), 0); + + // Enter encrypted mode + socket.startClientEncryption(); + QCOMPARE(socket.mode(), QSslSocket::SslClientMode); + QVERIFY(!socket.isEncrypted()); + QCOMPARE(connectionEncryptedSpy.count(), 0); + + // Start handshake. + enterLoop(10); + + // We must get the PSK signal in all cases + QCOMPARE(pskAuthenticationRequiredSpy.count(), 1); + + QCOMPARE(connectionEncryptedSpy.count(), 1); + QVERIFY(socket.isEncrypted()); + QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); + + // check writing + socket.write("Hello from Qt TLS/PSK!"); + QVERIFY(socket.waitForBytesWritten()); + + // disconnect + socket.disconnectFromHost(); + enterLoop(10); + + QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState); + QCOMPARE(disconnectedSpy.count(), 1); +} + #endif // QT_NO_OPENSSL #endif // QT_NO_SSL diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro index ae911e43ed..4ea878f840 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro @@ -2,7 +2,7 @@ CONFIG += testcase testcase.timeout = 300 # this test is slow SOURCES += tst_qsslsocket_onDemandCertificates_member.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core core-private network-private testlib TARGET = tst_qsslsocket_onDemandCertificates_member @@ -15,10 +15,6 @@ win32 { } } -wince* { - DEFINES += SRCDIR=\\\"./\\\" -} else { - DEFINES += SRCDIR=\\\"$$PWD/\\\" -} +DEFINES += SRCDIR=\\\"$$PWD/\\\" requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro index 25e5a5d5c7..d69ea7fb3d 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += tst_qsslsocket_onDemandCertificates_static.cpp -win32:!wince: LIBS += -lws2_32 +win32:LIBS += -lws2_32 QT = core core-private network-private testlib TARGET = tst_qsslsocket_onDemandCertificates_static @@ -14,10 +14,6 @@ win32 { } } -wince* { - DEFINES += SRCDIR=\\\"./\\\" -} else { - DEFINES += SRCDIR=\\\"$$PWD/\\\" -} +DEFINES += SRCDIR=\\\"$$PWD/\\\" requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro index 25d79ebfe8..df7c10ed19 100644 --- a/tests/auto/network/ssl/ssl.pro +++ b/tests/auto/network/ssl/ssl.pro @@ -21,6 +21,7 @@ winrt: SUBDIRS -= \ contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { contains(QT_CONFIG, private_tests) { - SUBDIRS += qasn1element + SUBDIRS += qasn1element \ + qssldiffiehellmanparameters } } |