1/****************************************************************************
2**
3** Copyright (C) 2016 Kurt Pattyn <pattyn.kurt@gmail.com>.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include <QtTest/QtTest>
29#include <QtTest/qtestcase.h>
30#include <QtEndian>
31
32#include <QDebug>
33
34#include "QtWebSockets/qwebsocketprotocol.h"
35#include "private/qwebsocketprotocol_p.h"
36
37QT_USE_NAMESPACE
38
39Q_DECLARE_METATYPE(QWebSocketProtocol::CloseCode)
40Q_DECLARE_METATYPE(QWebSocketProtocol::OpCode)
41Q_DECLARE_METATYPE(QWebSocketProtocol::Version)
42
43class tst_WebSocketProtocol : public QObject
44{
45 Q_OBJECT
46
47public:
48 tst_WebSocketProtocol();
49
50private Q_SLOTS:
51 void initTestCase();
52 void cleanupTestCase();
53 void init();
54 void cleanup();
55
56 void tst_validMasks_data();
57 void tst_validMasks();
58
59 void tst_opCodes_data();
60 void tst_opCodes();
61
62 void tst_closeCodes_data();
63 void tst_closeCodes();
64
65 void tst_versionFromString_data();
66 void tst_versionFromString();
67};
68
69tst_WebSocketProtocol::tst_WebSocketProtocol()
70{}
71
72void tst_WebSocketProtocol::initTestCase()
73{
74}
75
76void tst_WebSocketProtocol::cleanupTestCase()
77{}
78
79void tst_WebSocketProtocol::init()
80{
81 qRegisterMetaType<QWebSocketProtocol::OpCode>(typeName: "QWebSocketProtocol::OpCode");
82 qRegisterMetaType<QWebSocketProtocol::CloseCode>(typeName: "QWebSocketProtocol::CloseCode");
83}
84
85void tst_WebSocketProtocol::cleanup()
86{
87}
88
89void tst_WebSocketProtocol::tst_validMasks_data()
90{
91 QTest::addColumn<quint32>(name: "mask");
92 QTest::addColumn<QString>(name: "inputdata");
93 QTest::addColumn<QByteArray>(name: "result");
94
95 QTest::newRow(dataTag: "Empty payload") << 0x12345678u << QString() << QByteArray();
96 QTest::newRow(dataTag: "ASCII payload of 8 characters")
97 << 0x12345678u
98 << QStringLiteral("abcdefgh")
99 << QByteArrayLiteral("\x73\x56\x35\x1C\x77\x52\x31\x10");
100 QTest::newRow(dataTag: "ASCII payload of 9 characters")
101 << 0x12345678u
102 << QStringLiteral("abcdefghi")
103 << QByteArrayLiteral("\x73\x56\x35\x1C\x77\x52\x31\x10\x7B");
104 //MSVC doesn't like UTF-8 in source code;
105 //the following text is represented in the string below: ∫∂ƒ©øØ
106 QTest::newRow(dataTag: "UTF-8 payload")
107 << 0x12345678u
108 << QString::fromUtf8(str: "\xE2\x88\xAB\xE2\x88\x82\xC6\x92\xC2\xA9\xC3\xB8\xC3\x98")
109 << QByteArrayLiteral("\x2D\x0B\x69\xD1\xEA\xEC");
110}
111
112void tst_WebSocketProtocol::tst_validMasks()
113{
114 QFETCH(quint32, mask);
115 QFETCH(QString, inputdata);
116 QFETCH(QByteArray, result);
117
118 //put latin1 into an explicit array
119 //otherwise, the intermediate object is deleted and the data pointer becomes invalid
120 QByteArray latin1 = inputdata.toLatin1();
121 char *data = latin1.data();
122
123 QWebSocketProtocol::mask(payload: data, size: inputdata.size(), maskingKey: mask);
124 QCOMPARE(QByteArray::fromRawData(data, inputdata.size()), result);
125}
126
127void tst_WebSocketProtocol::tst_opCodes_data()
128{
129 QTest::addColumn<QWebSocketProtocol::OpCode>(name: "opCode");
130 QTest::addColumn<bool>(name: "isReserved");
131
132 QTest::newRow(dataTag: "OpCodeBinary") << QWebSocketProtocol::OpCodeBinary << false;
133 QTest::newRow(dataTag: "OpCodeClose") << QWebSocketProtocol::OpCodeClose << false;
134 QTest::newRow(dataTag: "OpCodeContinue") << QWebSocketProtocol::OpCodeContinue << false;
135 QTest::newRow(dataTag: "OpCodePing") << QWebSocketProtocol::OpCodePing << false;
136 QTest::newRow(dataTag: "OpCodePong") << QWebSocketProtocol::OpCodePong << false;
137 QTest::newRow(dataTag: "OpCodeReserved3") << QWebSocketProtocol::OpCodeReserved3 << true;
138 QTest::newRow(dataTag: "OpCodeReserved4") << QWebSocketProtocol::OpCodeReserved4 << true;
139 QTest::newRow(dataTag: "OpCodeReserved5") << QWebSocketProtocol::OpCodeReserved5 << true;
140 QTest::newRow(dataTag: "OpCodeReserved6") << QWebSocketProtocol::OpCodeReserved6 << true;
141 QTest::newRow(dataTag: "OpCodeReserved7") << QWebSocketProtocol::OpCodeReserved7 << true;
142 QTest::newRow(dataTag: "OpCodeReserved8") << QWebSocketProtocol::OpCodeReservedB << true;
143 QTest::newRow(dataTag: "OpCodeReservedC") << QWebSocketProtocol::OpCodeReservedC << true;
144 QTest::newRow(dataTag: "OpCodeReservedD") << QWebSocketProtocol::OpCodeReservedD << true;
145 QTest::newRow(dataTag: "OpCodeReservedE") << QWebSocketProtocol::OpCodeReservedE << true;
146 QTest::newRow(dataTag: "OpCodeReservedF") << QWebSocketProtocol::OpCodeReservedF << true;
147 QTest::newRow(dataTag: "OpCodeText") << QWebSocketProtocol::OpCodeText << false;
148}
149
150void tst_WebSocketProtocol::tst_opCodes()
151{
152 QFETCH(QWebSocketProtocol::OpCode, opCode);
153 QFETCH(bool, isReserved);
154
155 bool result = QWebSocketProtocol::isOpCodeReserved(code: opCode);
156
157 QCOMPARE(result, isReserved);
158}
159
160void tst_WebSocketProtocol::tst_closeCodes_data()
161{
162 QTest::addColumn<int>(name: "closeCode");
163 QTest::addColumn<bool>(name: "isValid");
164
165 for (int i = 0; i < 1000; ++i)
166 {
167 QTest::newRow(QStringLiteral("Close code %1").arg(a: i).toLatin1().constData()) << i << false;
168 }
169
170 for (int i = 1000; i < 1004; ++i)
171 {
172 QTest::newRow(QStringLiteral("Close code %1").arg(a: i).toLatin1().constData()) << i << true;
173 }
174
175 QTest::newRow(dataTag: "Close code 1004") << 1004 << false;
176 QTest::newRow(dataTag: "Close code 1005") << 1005 << false;
177 QTest::newRow(dataTag: "Close code 1006") << 1006 << false;
178
179 for (int i = 1007; i < 1012; ++i)
180 {
181 QTest::newRow(QStringLiteral("Close code %1").arg(a: i).toLatin1().constData()) << i << true;
182 }
183
184 for (int i = 1013; i < 3000; ++i)
185 {
186 QTest::newRow(QStringLiteral("Close code %1").arg(a: i).toLatin1().constData()) << i << false;
187 }
188
189 for (int i = 3000; i < 5000; ++i)
190 {
191 QTest::newRow(QStringLiteral("Close code %1").arg(a: i).toLatin1().constData()) << i << true;
192 }
193
194 QTest::newRow(dataTag: "Close code 5000") << 1004 << false;
195 QTest::newRow(dataTag: "Close code 6000") << 1004 << false;
196 QTest::newRow(dataTag: "Close code 7000") << 1004 << false;
197}
198
199void tst_WebSocketProtocol::tst_closeCodes()
200{
201 QFETCH(int, closeCode);
202 QFETCH(bool, isValid);
203
204 bool result = QWebSocketProtocol::isCloseCodeValid(closeCode);
205
206 QCOMPARE(result, isValid);
207}
208
209void tst_WebSocketProtocol::tst_versionFromString_data()
210{
211 QTest::addColumn<QWebSocketProtocol::Version>(name: "version");
212 QTest::addColumn<QString>(name: "versionString");
213
214 //happy flow; good data
215 QTest::newRow(dataTag: "Version 0")
216 << QWebSocketProtocol::Version0
217 << QStringLiteral("0");
218 QTest::newRow(dataTag: "Version 4")
219 << QWebSocketProtocol::Version4
220 << QStringLiteral("4");
221 QTest::newRow(dataTag: "Version 5")
222 << QWebSocketProtocol::Version5
223 << QStringLiteral("5");
224 QTest::newRow(dataTag: "Version 6")
225 << QWebSocketProtocol::Version6
226 << QStringLiteral("6");
227 QTest::newRow(dataTag: "Version 7")
228 << QWebSocketProtocol::Version7
229 << QStringLiteral("7");
230 QTest::newRow(dataTag: "Version 8")
231 << QWebSocketProtocol::Version8
232 << QStringLiteral("8");
233 QTest::newRow(dataTag: "Version 13")
234 << QWebSocketProtocol::Version13
235 << QStringLiteral("13");
236
237 //rainy flow; invalid data
238 QTest::newRow(dataTag: "Version -1")
239 << QWebSocketProtocol::VersionUnknown
240 << QStringLiteral("-1");
241 QTest::newRow(dataTag: "Version 1")
242 << QWebSocketProtocol::VersionUnknown
243 << QStringLiteral("1");
244 QTest::newRow(dataTag: "Version 2")
245 << QWebSocketProtocol::VersionUnknown
246 << QStringLiteral("2");
247 QTest::newRow(dataTag: "Version 3")
248 << QWebSocketProtocol::VersionUnknown
249 << QStringLiteral("3");
250 QTest::newRow(dataTag: "Version 9")
251 << QWebSocketProtocol::VersionUnknown
252 << QStringLiteral("9");
253 QTest::newRow(dataTag: "Version 10")
254 << QWebSocketProtocol::VersionUnknown
255 << QStringLiteral("10");
256 QTest::newRow(dataTag: "Version 11")
257 << QWebSocketProtocol::VersionUnknown
258 << QStringLiteral("11");
259 QTest::newRow(dataTag: "Version 12")
260 << QWebSocketProtocol::VersionUnknown
261 << QStringLiteral("12");
262 QTest::newRow(dataTag: "Version abcd")
263 << QWebSocketProtocol::VersionUnknown
264 << QStringLiteral("abcd");
265 QTest::newRow(dataTag: "Version 1.6")
266 << QWebSocketProtocol::VersionUnknown
267 << QStringLiteral("1.6");
268 QTest::newRow(dataTag: "Version empty")
269 << QWebSocketProtocol::VersionUnknown
270 << QString();
271}
272
273void tst_WebSocketProtocol::tst_versionFromString()
274{
275 QFETCH(QWebSocketProtocol::Version, version);
276 QFETCH(QString, versionString);
277
278 QCOMPARE(QWebSocketProtocol::versionFromString(versionString), version);
279}
280
281QTEST_MAIN(tst_WebSocketProtocol)
282
283#include "tst_websocketprotocol.moc"
284
285

source code of qtwebsockets/tests/auto/websockets/websocketprotocol/tst_websocketprotocol.cpp