From cdabdb79808b3788519fa3bde0d240f2b11a4b34 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 10 Nov 2009 12:10:57 +1000 Subject: More XMLHttpRequest tests --- src/declarative/qml/qmlxmlhttprequest.cpp | 37 +++- .../xmlhttprequest/data/send_alreadySent.qml | 27 +++ .../xmlhttprequest/data/send_data.1.expect | 10 ++ .../xmlhttprequest/data/send_data.1.qml | 21 +++ .../xmlhttprequest/data/send_data.2.qml | 23 +++ .../xmlhttprequest/data/send_data.3.qml | 23 +++ .../xmlhttprequest/data/send_data.4.expect | 10 ++ .../xmlhttprequest/data/send_data.4.qml | 24 +++ .../xmlhttprequest/data/send_data.5.qml | 23 +++ .../xmlhttprequest/data/send_data.6.expect | 10 ++ .../xmlhttprequest/data/send_data.6.qml | 21 +++ .../xmlhttprequest/data/send_data.reply | 2 + .../xmlhttprequest/data/send_ignoreData.qml | 26 +++ .../xmlhttprequest/data/send_ignoreData.reply | 2 + .../xmlhttprequest/data/send_ignoreData_GET.expect | 7 + .../xmlhttprequest/data/send_ignoreData_PUT.expect | 7 + .../xmlhttprequest/data/send_unsent.qml | 16 ++ .../declarative/xmlhttprequest/testhttpserver.cpp | 7 +- .../xmlhttprequest/tst_xmlhttprequest.cpp | 193 +++++++++++++++++++++ 19 files changed, 484 insertions(+), 5 deletions(-) create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_alreadySent.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.1.expect create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.1.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.2.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.3.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.4.expect create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.4.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.5.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.6.expect create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.6.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_data.reply create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_ignoreData.qml create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_ignoreData.reply create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_ignoreData_GET.expect create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_ignoreData_PUT.expect create mode 100644 tests/auto/declarative/xmlhttprequest/data/send_unsent.qml diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index f51b59f..6946e7a 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -1092,15 +1092,44 @@ void QmlXMLHttpRequest::send(const QByteArray &data) dispatchCallback(); m_request.setUrl(m_url); + QNetworkRequest request = m_request; + if(m_method == QLatin1String("POST") || + m_method == QLatin1String("PUT")) { + QVariant var = request.header(QNetworkRequest::ContentTypeHeader); + if (var.isValid()) { + QString str = var.toString(); + int charsetIdx = str.indexOf("charset="); + if (charsetIdx == -1) { + // No charset - append + if (!str.isEmpty()) str.append(QLatin1Char(';')); + str.append(QLatin1String("charset=UTF-8")); + } else { + charsetIdx += 8; + int n = 0; + int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx); + if (semiColon == -1) { + n = str.length() - charsetIdx; + } else { + n = semiColon - charsetIdx; + } + + str.replace(charsetIdx, n, QLatin1String("UTF-8")); + } + request.setHeader(QNetworkRequest::ContentTypeHeader, str); + } else { + request.setHeader(QNetworkRequest::ContentTypeHeader, + QLatin1String("text/plain;charset=UTF-8")); + } + } if (m_method == QLatin1String("GET")) - m_network = m_engine->networkAccessManager()->get(m_request); + m_network = m_engine->networkAccessManager()->get(request); else if (m_method == QLatin1String("HEAD")) - m_network = m_engine->networkAccessManager()->head(m_request); + m_network = m_engine->networkAccessManager()->head(request); else if(m_method == QLatin1String("POST")) - m_network = m_engine->networkAccessManager()->post(m_request, data); + m_network = m_engine->networkAccessManager()->post(request, data); else if(m_method == QLatin1String("PUT")) - m_network = m_engine->networkAccessManager()->put(m_request, data); + m_network = m_engine->networkAccessManager()->put(request, data); QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64))); diff --git a/tests/auto/declarative/xmlhttprequest/data/send_alreadySent.qml b/tests/auto/declarative/xmlhttprequest/data/send_alreadySent.qml new file mode 100644 index 0000000..4598169 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_alreadySent.qml @@ -0,0 +1,27 @@ +import Qt 4.6 + +Object { + property bool dataOK: false + property bool test: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("GET", "testdocument.html"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send(); + + try { + x.send() + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + test = true; + } + } +} diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.1.expect b/tests/auto/declarative/xmlhttprequest/data/send_data.1.expect new file mode 100644 index 0000000..1ef179b --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.1.expect @@ -0,0 +1,10 @@ +POST /testdocument.html HTTP/1.1 +Content-Type: text/plain;charset=UTF-8 +Content-Length: 12 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + +My Sent Data \ No newline at end of file diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.1.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.1.qml new file mode 100644 index 0000000..c0b5bf8 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.1.qml @@ -0,0 +1,21 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("POST", url); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.2.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.2.qml new file mode 100644 index 0000000..8a8c375 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.2.qml @@ -0,0 +1,23 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("POST", url); + x.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.3.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.3.qml new file mode 100644 index 0000000..ae5731f --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.3.qml @@ -0,0 +1,23 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("POST", url); + x.setRequestHeader("Content-Type", "text/plain;charset=latin1"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.4.expect b/tests/auto/declarative/xmlhttprequest/data/send_data.4.expect new file mode 100644 index 0000000..6b10b4a --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.4.expect @@ -0,0 +1,10 @@ +POST /testdocument.html HTTP/1.1 +Content-Type: charset=UTF-8;text/plain +Content-Length: 12 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + +My Sent Data \ No newline at end of file diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.4.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.4.qml new file mode 100644 index 0000000..375f2fa --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.4.qml @@ -0,0 +1,24 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("POST", url); + x.setRequestHeader("Content-Type", "charset=UTF-8;text/plain"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} + + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.5.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.5.qml new file mode 100644 index 0000000..eca1676 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.5.qml @@ -0,0 +1,23 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("POST", url); + x.setRequestHeader("Content-Type", "charset=latin1;text/plain"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.6.expect b/tests/auto/declarative/xmlhttprequest/data/send_data.6.expect new file mode 100644 index 0000000..dc0d6c2 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.6.expect @@ -0,0 +1,10 @@ +PUT /testdocument.html HTTP/1.1 +Content-Type: text/plain;charset=UTF-8 +Content-Length: 12 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + +My Sent Data \ No newline at end of file diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.6.qml b/tests/auto/declarative/xmlhttprequest/data/send_data.6.qml new file mode 100644 index 0000000..0bc2e35 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.6.qml @@ -0,0 +1,21 @@ +import Qt 4.6 + +Object { + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("PUT", url); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("My Sent Data"); + } +} diff --git a/tests/auto/declarative/xmlhttprequest/data/send_data.reply b/tests/auto/declarative/xmlhttprequest/data/send_data.reply new file mode 100644 index 0000000..35b11f4 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_data.reply @@ -0,0 +1,2 @@ +HTTP/1.0 200 OK +Content-type: text/html; charset=UTF-8 diff --git a/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.qml b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.qml new file mode 100644 index 0000000..6f33eef --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.qml @@ -0,0 +1,26 @@ +import Qt 4.6 + +Object { + property string reqType + property string url + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open(reqType, url); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + if (reqType == "HEAD") + dataOK = (x.responseText == ""); + else + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send("Data To Ignore"); + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.reply b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.reply new file mode 100644 index 0000000..35b11f4 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData.reply @@ -0,0 +1,2 @@ +HTTP/1.0 200 OK +Content-type: text/html; charset=UTF-8 diff --git a/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_GET.expect b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_GET.expect new file mode 100644 index 0000000..40e648e --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_GET.expect @@ -0,0 +1,7 @@ +GET /testdocument.html HTTP/1.1 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_PUT.expect b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_PUT.expect new file mode 100644 index 0000000..381cc89 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_ignoreData_PUT.expect @@ -0,0 +1,7 @@ +HEAD /testdocument.html HTTP/1.1 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + diff --git a/tests/auto/declarative/xmlhttprequest/data/send_unsent.qml b/tests/auto/declarative/xmlhttprequest/data/send_unsent.qml new file mode 100644 index 0000000..76c26a3 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/send_unsent.qml @@ -0,0 +1,16 @@ +import Qt 4.6 + +Object { + property bool test: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + try { + x.send(); + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + test = true; + } + } +} diff --git a/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp b/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp index 021da05..b579944 100644 --- a/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp +++ b/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp @@ -74,6 +74,11 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod } waitData = expectFile.readAll(); + /* + while (waitData.endsWith('\n')) + waitData = waitData.left(waitData.count() - 1); + */ + replyData = replyFile.readAll(); if (!replyData.endsWith('\n')) @@ -127,7 +132,7 @@ void TestHTTPServer::readyRead() const char c = ba.at(ii); if (c == '\r' && waitData.isEmpty()) continue; - else if (c == waitData.at(0)) + else if (!waitData.isEmpty() && c == waitData.at(0)) waitData = waitData.mid(1); else if (c == '\r') continue; diff --git a/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp b/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp index 9acd6e6..bedb620 100644 --- a/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp +++ b/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp @@ -70,6 +70,11 @@ private slots: void setRequestHeader_illegalName_data(); void setRequestHeader_illegalName(); void setRequestHeader_sent(); + void send_unsent(); + void send_alreadySent(); + void send_ignoreData(); + void send_withdata(); + void abort(); // Crashes // void outstanding_request_at_shutdown(); @@ -420,6 +425,194 @@ void tst_xmlhttprequest::setRequestHeader_sent() delete object; } +// Test that calling send() in UNSENT state throws an exception +void tst_xmlhttprequest::send_unsent() +{ + QmlComponent component(&engine, TEST_FILE("send_unsent.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; +} + +// Test attempting to resend a sent request throws an exception +void tst_xmlhttprequest::send_alreadySent() +{ + QmlComponent component(&engine, TEST_FILE("send_alreadySent.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; +} + +// Test that send for a GET or HEAD ignores data +void tst_xmlhttprequest::send_ignoreData() +{ + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_ignoreData_GET.expect"), + TEST_FILE("send_ignoreData.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_ignoreData.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("reqType", "GET"); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_ignoreData_PUT.expect"), + TEST_FILE("send_ignoreData.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_ignoreData.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("reqType", "HEAD"); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } +} + +// Test that send()'ing data works +void tst_xmlhttprequest::send_withdata() +{ + // No content-type + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.1.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.1.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + // Correct content-type + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.1.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.2.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + // Incorrect content-type + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.1.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.3.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + // Correct content-type - out of order + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.4.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.4.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + // Incorrect content-type - out of order + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.4.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.5.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } + + // PUT + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("send_data.6.expect"), + TEST_FILE("send_data.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("send_data.6.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; + } +} + +void tst_xmlhttprequest::abort() +{ +} QTEST_MAIN(tst_xmlhttprequest) -- cgit v0.12