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