Update license headers and add new license files
[contrib/qtwebsockets.git] / tests / auto / websocketframe / tst_websocketframe.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Kurt Pattyn <pattyn.kurt@gmail.com>.
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** In addition, as a special exception, Digia gives you certain additional
27 ** rights. These rights are described in the Digia Qt LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33 #include <QtTest/QtTest>
34 #include <QtTest/qtestcase.h>
35 #include <QDebug>
36 #include <QByteArray>
37 #include <QtEndian>
38
39 #include "private/qwebsocketframe_p.h"
40 #include "private/qwebsocketprotocol_p.h"
41 #include "qwebsocketprotocol.h"
42
43 QT_USE_NAMESPACE
44
45 Q_DECLARE_METATYPE(QWebSocketProtocol::CloseCode)
46 Q_DECLARE_METATYPE(QWebSocketProtocol::OpCode)
47
48 /*!
49  * \brief class FrameHelper is used to encode a single frame.
50  *
51  * \internal
52  */
53 class FrameHelper
54 {
55 public:
56     FrameHelper();
57
58     QByteArray wireRepresentation();
59
60     void setRsv1(int value) { m_rsv1 = value; }
61     void setRsv2(int value) { m_rsv2 = value; }
62     void setRsv3(int value) { m_rsv3 = value; }
63     void setMask(quint32 mask) { m_mask = mask; }
64     void setOpCode(QWebSocketProtocol::OpCode opCode) { m_opCode = opCode; }
65     void setPayload(const QByteArray &payload) { m_payload = payload; }
66     void setFinalFrame(bool isFinal) { m_isFinalFrame = isFinal; }
67
68 private:
69     int m_rsv1;
70     int m_rsv2;
71     int m_rsv3;
72     quint32 m_mask;
73     QWebSocketProtocol::OpCode m_opCode;
74     QByteArray m_payload;
75     bool m_isFinalFrame;
76 };
77
78 FrameHelper::FrameHelper() :
79     m_rsv1(0), m_rsv2(0), m_rsv3(0),
80     m_mask(0), m_opCode(QWebSocketProtocol::OpCodeReserved3),
81     m_payload(), m_isFinalFrame(false)
82 {}
83
84 QByteArray FrameHelper::wireRepresentation()
85 {
86     quint8 byte = 0x00;
87     QByteArray wireRep;
88     quint64 payloadLength = m_payload.length();
89
90     //FIN, opcode
91     byte = static_cast<quint8>((m_opCode & 0x0F) | (m_isFinalFrame ? 0x80 : 0x00)); //FIN, opcode
92     //RSV1-3
93     byte |= static_cast<quint8>(((m_rsv1 & 0x01) << 6) | ((m_rsv2 & 0x01) << 5) |
94                                 ((m_rsv3 & 0x01) << 4));
95     wireRep.append(static_cast<char>(byte));
96
97     byte = 0x00;
98     if (m_mask != 0)
99     {
100         byte |= 0x80;
101     }
102     if (payloadLength <= 125)
103     {
104         byte |= static_cast<quint8>(payloadLength);
105         wireRep.append(static_cast<char>(byte));
106     }
107     else if (payloadLength <= 0xFFFFU)
108     {
109         byte |= 126;
110         wireRep.append(static_cast<char>(byte));
111         quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength));
112         wireRep.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2);
113     }
114     else
115     {
116         byte |= 127;
117         wireRep.append(static_cast<char>(byte));
118         quint64 swapped = qToBigEndian<quint64>(payloadLength);
119         wireRep.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8);
120     }
121     //Write mask
122     if (m_mask != 0)
123     {
124         wireRep.append(static_cast<const char *>(static_cast<const void *>(&m_mask)),
125                        sizeof(quint32));
126     }
127     QByteArray tmpData = m_payload;
128     if (m_mask)
129     {
130         tmpData.detach();
131         QWebSocketProtocol::mask(&tmpData, m_mask);
132     }
133     wireRep.append(tmpData);
134     return wireRep;
135 }
136
137 class tst_WebSocketFrame : public QObject
138 {
139     Q_OBJECT
140
141 public:
142     tst_WebSocketFrame();
143
144 private Q_SLOTS:
145     void initTestCase();
146     void cleanupTestCase();
147     void init();
148     void cleanup();
149
150     void tst_initialization();
151     void tst_copyConstructorAndAssignment();
152
153     void tst_goodFrames_data();
154     void tst_goodFrames();
155
156     void tst_invalidFrames_data();
157     void tst_invalidFrames();
158
159     void tst_malformedFrames_data();
160     void tst_malformedFrames();
161 };
162
163 tst_WebSocketFrame::tst_WebSocketFrame()
164 {}
165
166 void tst_WebSocketFrame::initTestCase()
167 {
168 }
169
170 void tst_WebSocketFrame::cleanupTestCase()
171 {}
172
173 void tst_WebSocketFrame::init()
174 {
175     qRegisterMetaType<QWebSocketProtocol::OpCode>("QWebSocketProtocol::OpCode");
176     qRegisterMetaType<QWebSocketProtocol::CloseCode>("QWebSocketProtocol::CloseCode");
177 }
178
179 void tst_WebSocketFrame::cleanup()
180 {
181 }
182
183 void tst_WebSocketFrame::tst_initialization()
184 {
185     QWebSocketFrame frame;
186     QVERIFY(!frame.isValid());
187     QCOMPARE(frame.payload().length(), 0);
188 }
189
190 void tst_WebSocketFrame::tst_copyConstructorAndAssignment()
191 {
192     FrameHelper frameHelper;
193     frameHelper.setRsv1(0);
194     frameHelper.setRsv2(0);
195     frameHelper.setRsv3(0);
196     frameHelper.setFinalFrame(true);
197     frameHelper.setMask(1234u);
198     frameHelper.setOpCode(QWebSocketProtocol::OpCodeBinary);
199     frameHelper.setPayload(QByteArrayLiteral("12345"));
200
201     QByteArray payload = frameHelper.wireRepresentation();
202     QBuffer buffer(&payload);
203     buffer.open(QIODevice::ReadOnly);
204
205     QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer);
206     buffer.close();
207
208     {
209         QWebSocketFrame other(frame);
210         QCOMPARE(other.closeCode(), frame.closeCode());
211         QCOMPARE(other.closeReason(), frame.closeReason());
212         QCOMPARE(other.hasMask(), frame.hasMask());
213         QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame());
214         QCOMPARE(other.isControlFrame(), frame.isControlFrame());
215         QCOMPARE(other.isDataFrame(), frame.isDataFrame());
216         QCOMPARE(other.isFinalFrame(), frame.isFinalFrame());
217         QCOMPARE(other.isValid(), frame.isValid());
218         QCOMPARE(other.mask(), frame.mask());
219         QCOMPARE(other.opCode(), frame.opCode());
220         QCOMPARE(other.payload(), frame.payload());
221         QCOMPARE(other.rsv1(), frame.rsv1());
222         QCOMPARE(other.rsv2(), frame.rsv2());
223         QCOMPARE(other.rsv3(), frame.rsv3());
224     }
225     {
226         QWebSocketFrame other;
227         other = frame;
228         QCOMPARE(other.closeCode(), frame.closeCode());
229         QCOMPARE(other.closeReason(), frame.closeReason());
230         QCOMPARE(other.hasMask(), frame.hasMask());
231         QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame());
232         QCOMPARE(other.isControlFrame(), frame.isControlFrame());
233         QCOMPARE(other.isDataFrame(), frame.isDataFrame());
234         QCOMPARE(other.isFinalFrame(), frame.isFinalFrame());
235         QCOMPARE(other.isValid(), frame.isValid());
236         QCOMPARE(other.mask(), frame.mask());
237         QCOMPARE(other.opCode(), frame.opCode());
238         QCOMPARE(other.payload(), frame.payload());
239         QCOMPARE(other.rsv1(), frame.rsv1());
240         QCOMPARE(other.rsv2(), frame.rsv2());
241         QCOMPARE(other.rsv3(), frame.rsv3());
242     }
243 }
244
245 void tst_WebSocketFrame::tst_goodFrames_data()
246 {
247     QTest::addColumn<int>("rsv1");
248     QTest::addColumn<int>("rsv2");
249     QTest::addColumn<int>("rsv3");
250     QTest::addColumn<quint32>("mask");
251     QTest::addColumn<QWebSocketProtocol::OpCode>("opCode");
252     QTest::addColumn<bool>("isFinal");
253     QTest::addColumn<QByteArray>("payload");
254     QTest::addColumn<bool>("isControlFrame");
255     QTest::addColumn<bool>("isDataFrame");
256     QTest::addColumn<bool>("isContinuationFrame");
257
258     QTest::newRow("Non masked final text frame with small payload")
259             << 0 << 0 << 0
260             << 0U << QWebSocketProtocol::OpCodeText
261             << true << QStringLiteral("Hello world!").toUtf8()
262             << false << true << false;
263     QTest::newRow("Non masked final binary frame with small payload")
264             << 0 << 0 << 0
265             << 0U << QWebSocketProtocol::OpCodeBinary
266             << true << QByteArrayLiteral("\x00\x01\x02\x03\x04")
267             << false << true << false;
268     QTest::newRow("Non masked final text frame with no payload")
269             << 0 << 0 << 0
270             << 0U << QWebSocketProtocol::OpCodeText
271             << true << QByteArray()
272             << false << true << false;
273     QTest::newRow("Non masked final binary frame with no payload")
274             << 0 << 0 << 0
275             << 0U << QWebSocketProtocol::OpCodeBinary
276             << true << QByteArray()
277             << false << true << false;
278
279     QTest::newRow("Non masked final close frame with small payload")
280             << 0 << 0 << 0
281             << 0U << QWebSocketProtocol::OpCodeClose
282             << true << QStringLiteral("Hello world!").toUtf8()
283             << true << false << false;
284     QTest::newRow("Non masked final close frame with no payload")
285             << 0 << 0 << 0
286             << 0U << QWebSocketProtocol::OpCodeClose
287             << true << QByteArray()
288             << true << false << false;
289     QTest::newRow("Non masked final ping frame with small payload")
290             << 0 << 0 << 0
291             << 0U << QWebSocketProtocol::OpCodePing
292             << true << QStringLiteral("Hello world!").toUtf8()
293             << true << false << false;
294     QTest::newRow("Non masked final pong frame with no payload")
295             << 0 << 0 << 0
296             << 0U << QWebSocketProtocol::OpCodePong
297             << true << QByteArray()
298             << true << false << false;
299
300     QTest::newRow("Non masked final continuation frame with small payload")
301             << 0 << 0 << 0
302             << 0U << QWebSocketProtocol::OpCodeContinue
303             << true << QStringLiteral("Hello world!").toUtf8()
304             << false << true << true;
305     QTest::newRow("Non masked non-final continuation frame with small payload")
306             << 0 << 0 << 0
307             << 0U << QWebSocketProtocol::OpCodeContinue
308             << false << QStringLiteral("Hello world!").toUtf8()
309             << false << true << true;
310 }
311
312 void tst_WebSocketFrame::tst_goodFrames()
313 {
314     QFETCH(int, rsv1);
315     QFETCH(int, rsv2);
316     QFETCH(int, rsv3);
317     QFETCH(quint32, mask);
318     QFETCH(QWebSocketProtocol::OpCode, opCode);
319     QFETCH(bool, isFinal);
320     QFETCH(QByteArray, payload);
321     QFETCH(bool, isControlFrame);
322     QFETCH(bool, isDataFrame);
323     QFETCH(bool, isContinuationFrame);
324
325     FrameHelper helper;
326     helper.setRsv1(rsv1);
327     helper.setRsv2(rsv2);
328     helper.setRsv3(rsv3);
329     helper.setMask(mask);
330     helper.setOpCode(opCode);
331     helper.setFinalFrame(isFinal);
332     helper.setPayload(payload);
333
334     QByteArray wireRepresentation = helper.wireRepresentation();
335     QBuffer buffer;
336     buffer.setData(wireRepresentation);
337     buffer.open(QIODevice::ReadOnly);
338     QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer);
339     buffer.close();
340     QVERIFY(frame.isValid());
341     QCOMPARE(frame.rsv1(), rsv1);
342     QCOMPARE(frame.rsv2(), rsv2);
343     QCOMPARE(frame.rsv3(), rsv3);
344     QCOMPARE(frame.hasMask(), (mask != 0));
345     QCOMPARE(frame.opCode(), opCode);
346     QCOMPARE(frame.isFinalFrame(), isFinal);
347     QCOMPARE(frame.isControlFrame(), isControlFrame);
348     QCOMPARE(frame.isDataFrame(), isDataFrame);
349     QCOMPARE(frame.isContinuationFrame(), isContinuationFrame);
350     QCOMPARE(frame.payload().length(), payload.length());
351     QCOMPARE(frame.payload(), payload);
352 }
353
354 void tst_WebSocketFrame::tst_invalidFrames_data()
355 {
356     QTest::addColumn<int>("rsv1");
357     QTest::addColumn<int>("rsv2");
358     QTest::addColumn<int>("rsv3");
359     QTest::addColumn<quint32>("mask");
360     QTest::addColumn<QWebSocketProtocol::OpCode>("opCode");
361     QTest::addColumn<bool>("isFinal");
362     QTest::addColumn<QByteArray>("payload");
363     QTest::addColumn<QWebSocketProtocol::CloseCode>("expectedError");
364
365     QTest::newRow("RSV1 != 0")
366             << 1 << 0 << 0
367             << 0U << QWebSocketProtocol::OpCodeText
368             << true << QStringLiteral("Hello world!").toUtf8()
369             << QWebSocketProtocol::CloseCodeProtocolError;
370     QTest::newRow("RSV2 != 0")
371             << 0 << 1 << 0
372             << 0U << QWebSocketProtocol::OpCodeText
373             << true << QStringLiteral("Hello world!").toUtf8()
374             << QWebSocketProtocol::CloseCodeProtocolError;
375     QTest::newRow("RSV3 != 0")
376             << 0 << 0 << 1
377             << 0U << QWebSocketProtocol::OpCodeText
378             << true << QStringLiteral("Hello world!").toUtf8()
379             << QWebSocketProtocol::CloseCodeProtocolError;
380     QTest::newRow("RSV1 != 0 and RSV2 != 0")
381             << 1 << 1 << 0
382             << 0U << QWebSocketProtocol::OpCodeText
383             << true << QStringLiteral("Hello world!").toUtf8()
384             << QWebSocketProtocol::CloseCodeProtocolError;
385     QTest::newRow("RSV1 != 0 and RSV3 != 0")
386             << 1 << 0 << 1
387             << 0U << QWebSocketProtocol::OpCodeText
388             << true << QStringLiteral("Hello world!").toUtf8()
389             << QWebSocketProtocol::CloseCodeProtocolError;
390     QTest::newRow("RSV2 != 0 and RSV3 != 0")
391             << 0 << 1 << 1
392             << 0U << QWebSocketProtocol::OpCodeText
393             << true << QStringLiteral("Hello world!").toUtf8()
394             << QWebSocketProtocol::CloseCodeProtocolError;
395
396     QTest::newRow("Reserved OpCode 3")
397             << 0 << 0 << 0
398             << 0U << QWebSocketProtocol::OpCodeReserved3
399             << true << QStringLiteral("Hello world!").toUtf8()
400             << QWebSocketProtocol::CloseCodeProtocolError;
401     QTest::newRow("Reserved OpCode 4")
402             << 0 << 0 << 0
403             << 0U << QWebSocketProtocol::OpCodeReserved4
404             << true << QStringLiteral("Hello world!").toUtf8()
405             << QWebSocketProtocol::CloseCodeProtocolError;
406     QTest::newRow("Reserved OpCode 5")
407             << 0 << 0 << 0
408             << 0U << QWebSocketProtocol::OpCodeReserved5
409             << true << QStringLiteral("Hello world!").toUtf8()
410             << QWebSocketProtocol::CloseCodeProtocolError;
411     QTest::newRow("Reserved OpCode 6")
412             << 0 << 0 << 0
413             << 0U << QWebSocketProtocol::OpCodeReserved6
414             << true << QStringLiteral("Hello world!").toUtf8()
415             << QWebSocketProtocol::CloseCodeProtocolError;
416     QTest::newRow("Reserved OpCode 7")
417             << 0 << 0 << 0
418             << 0U << QWebSocketProtocol::OpCodeReserved7
419             << true << QStringLiteral("Hello world!").toUtf8()
420             << QWebSocketProtocol::CloseCodeProtocolError;
421     QTest::newRow("Reserved OpCode B")
422             << 0 << 0 << 0
423             << 0U << QWebSocketProtocol::OpCodeReservedB
424             << true << QStringLiteral("Hello world!").toUtf8()
425             << QWebSocketProtocol::CloseCodeProtocolError;
426     QTest::newRow("Reserved OpCode C")
427             << 0 << 0 << 0
428             << 0U << QWebSocketProtocol::OpCodeReservedC
429             << true << QStringLiteral("Hello world!").toUtf8()
430             << QWebSocketProtocol::CloseCodeProtocolError;
431     QTest::newRow("Reserved OpCode D")
432             << 0 << 0 << 0
433             << 0U << QWebSocketProtocol::OpCodeReservedD
434             << true << QStringLiteral("Hello world!").toUtf8()
435             << QWebSocketProtocol::CloseCodeProtocolError;
436     QTest::newRow("Reserved OpCode E")
437             << 0 << 0 << 0
438             << 0U << QWebSocketProtocol::OpCodeReservedE
439             << true << QStringLiteral("Hello world!").toUtf8()
440             << QWebSocketProtocol::CloseCodeProtocolError;
441     QTest::newRow("Reserved OpCode F")
442             << 0 << 0 << 0
443             << 0U << QWebSocketProtocol::OpCodeReservedF
444             << true << QStringLiteral("Hello world!").toUtf8()
445             << QWebSocketProtocol::CloseCodeProtocolError;
446
447     QTest::newRow("Close Frame with payload > 125 bytes")
448             << 0 << 0 << 0
449             << 0U << QWebSocketProtocol::OpCodeClose
450             << true << QString(126, 'a').toUtf8()
451             << QWebSocketProtocol::CloseCodeProtocolError;
452     QTest::newRow("Non-final Close Frame")
453             << 0 << 0 << 0
454             << 0U << QWebSocketProtocol::OpCodeClose
455             << false << QString(126, 'a').toUtf8()
456             << QWebSocketProtocol::CloseCodeProtocolError;
457     QTest::newRow("Ping Frame with payload > 125 bytes")
458             << 0 << 0 << 0
459             << 0U << QWebSocketProtocol::OpCodePing
460             << true << QString(126, 'a').toUtf8()
461             << QWebSocketProtocol::CloseCodeProtocolError;
462     QTest::newRow("Non-final Ping Frame")
463             << 0 << 0 << 0
464             << 0U << QWebSocketProtocol::OpCodePing
465             << false << QString(126, 'a').toUtf8()
466             << QWebSocketProtocol::CloseCodeProtocolError;
467     QTest::newRow("Pong Frame with payload > 125 bytes")
468             << 0 << 0 << 0
469             << 0U << QWebSocketProtocol::OpCodePong
470             << true << QString(126, 'a').toUtf8()
471             << QWebSocketProtocol::CloseCodeProtocolError;
472     QTest::newRow("Non-final Pong Frame")
473             << 0 << 0 << 0
474             << 0U << QWebSocketProtocol::OpCodePong
475             << false << QString(126, 'a').toUtf8()
476             << QWebSocketProtocol::CloseCodeProtocolError;
477 }
478
479 void tst_WebSocketFrame::tst_invalidFrames()
480 {
481     QFETCH(int, rsv1);
482     QFETCH(int, rsv2);
483     QFETCH(int, rsv3);
484     QFETCH(quint32, mask);
485     QFETCH(QWebSocketProtocol::OpCode, opCode);
486     QFETCH(bool, isFinal);
487     QFETCH(QByteArray, payload);
488     QFETCH(QWebSocketProtocol::CloseCode, expectedError);
489
490     FrameHelper helper;
491     helper.setRsv1(rsv1);
492     helper.setRsv2(rsv2);
493     helper.setRsv3(rsv3);
494     helper.setMask(mask);
495     helper.setOpCode(opCode);
496     helper.setFinalFrame(isFinal);
497     helper.setPayload(payload);
498
499     QByteArray wireRepresentation = helper.wireRepresentation();
500     QBuffer buffer;
501     buffer.setData(wireRepresentation);
502     buffer.open(QIODevice::ReadOnly);
503     QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer);
504     buffer.close();
505
506     QVERIFY(!frame.isValid());
507     QCOMPARE(frame.closeCode(), expectedError);
508 }
509
510
511 /*
512  * Incomplete or overly large frames
513  * Payload must be crafted manually
514  *
515     QTest::newRow("Frame Too Big")
516             << 0 << 0 << 0
517             << 0U << QWebSocketProtocol::OpCodeText
518             << true << QString(MAX_FRAME_SIZE_IN_BYTES + 1, 'a').toUtf8()
519             << QWebSocketProtocol::CloseCodeTooMuchData;
520
521  */
522 void tst_WebSocketFrame::tst_malformedFrames_data()
523 {
524     QTest::addColumn<QByteArray>("payload");
525     QTest::addColumn<QWebSocketProtocol::CloseCode>("expectedError");
526
527     //too little data
528     QTest::newRow("No data") << QByteArray() << QWebSocketProtocol::CloseCodeGoingAway;
529     FrameHelper helper;
530     helper.setRsv1(0);
531     helper.setRsv2(0);
532     helper.setRsv3(0);
533     helper.setMask(0U);
534     helper.setOpCode(QWebSocketProtocol::OpCodeText);
535     helper.setFinalFrame(true);
536     helper.setPayload(QString(10, 'a').toUtf8());
537     QByteArray wireRep = helper.wireRepresentation();
538
539     //too little data
540     //header + payload should be 12 bytes for non-masked payloads < 126 bytes
541     for (int i = 1; i < 12; ++i)
542     {
543         QTest::newRow(QStringLiteral("Header too small - %1 byte(s)").arg(i).toLatin1().constData())
544                 << wireRep.left(i)
545                 << QWebSocketProtocol::CloseCodeGoingAway;
546     }
547     //too much data
548     {
549         const char bigpayloadIndicator = char(127);
550         const quint64 payloadSize = MAX_FRAME_SIZE_IN_BYTES + 1;
551         uchar swapped[8] = {0};
552         qToBigEndian<quint64>(payloadSize, swapped);
553         QTest::newRow("Frame too big")
554                 << wireRep.left(1).append(bigpayloadIndicator)
555                                   .append(reinterpret_cast<char *>(swapped), 8)
556                 << QWebSocketProtocol::CloseCodeTooMuchData;
557     }
558     //invalid size field
559     {
560         const char bigpayloadIndicator = char(127);
561         quint64 payloadSize = quint64(1) << 63;
562         uchar swapped[8] = {0};
563         qToBigEndian<quint64>(payloadSize, swapped);
564         QTest::newRow("Highest bit of payload length is set")
565                 << wireRep.left(1).append(bigpayloadIndicator)
566                                   .append(reinterpret_cast<char *>(swapped), 8)
567                 << QWebSocketProtocol::CloseCodeProtocolError;
568
569         payloadSize = 256;
570         qToBigEndian<quint64>(payloadSize, swapped);
571         QTest::newRow("Overlong 64-bit size field; should be 16-bit")
572                 << wireRep.left(1).append(bigpayloadIndicator)
573                                   .append(reinterpret_cast<char *>(swapped), 8)
574                 << QWebSocketProtocol::CloseCodeProtocolError;
575     }
576     //overlong size field
577     {
578         const char largepayloadIndicator = char(126);
579         const quint16 payloadSize = 120;
580         uchar swapped[2] = {0};
581         qToBigEndian<quint16>(payloadSize, swapped);
582         QTest::newRow("Overlong 16-bit size field")
583                 << wireRep.left(1).append(largepayloadIndicator)
584                                   .append(reinterpret_cast<char *>(swapped), 2)
585                 << QWebSocketProtocol::CloseCodeProtocolError;
586     }
587     {
588         const char bigpayloadIndicator = char(127);
589         quint64 payloadSize = 120;
590         uchar swapped[8] = {0};
591         qToBigEndian<quint64>(payloadSize, swapped);
592         QTest::newRow("Overlong 64-bit size field; should be 7-bit")
593                 << wireRep.left(1).append(bigpayloadIndicator)
594                                   .append(reinterpret_cast<char *>(swapped), 8)
595                 << QWebSocketProtocol::CloseCodeProtocolError;
596
597         payloadSize = 256;
598         qToBigEndian<quint64>(payloadSize, swapped);
599         QTest::newRow("Overlong 64-bit size field; should be 16-bit")
600                 << wireRep.left(1).append(bigpayloadIndicator)
601                                   .append(reinterpret_cast<char *>(swapped), 8)
602                 << QWebSocketProtocol::CloseCodeProtocolError;
603     }
604 }
605
606 void tst_WebSocketFrame::tst_malformedFrames()
607 {
608     QFETCH(QByteArray, payload);
609     QFETCH(QWebSocketProtocol::CloseCode, expectedError);
610
611     QBuffer buffer;
612     buffer.setData(payload);
613     buffer.open(QIODevice::ReadOnly);
614     QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer);
615     buffer.close();
616
617     QVERIFY(!frame.isValid());
618     QCOMPARE(frame.closeCode(), expectedError);
619 }
620
621 QTEST_MAIN(tst_WebSocketFrame)
622
623 #include "tst_websocketframe.moc"
624