Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: net/websockets/websocket_frame_parser_unittest.cc

Issue 9956013: Add WebSocketFrameParser. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase for try runs. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/websockets/websocket_frame_parser.h"
6
7 #include <vector>
8
9 #include "base/basictypes.h"
10 #include "base/port.h"
11 #include "base/memory/scoped_vector.h"
mmenke 2012/05/02 16:15:41 nit: alphabetize.
Yuta Kitamura 2012/05/08 08:21:58 Done.
12 #include "net/websockets/websocket_frame.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace {
16
17 const char kHello[] = "Hello, world!";
18 const uint64 kHelloLength = arraysize(kHello) - 1;
19 const char kHelloFrame[] = "\x81\x0DHello, world!";
20 const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1;
21 const char kMaskedHelloFrame[] =
22 "\x81\x8d\xDE\xAD\xBE\xEF"
23 "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
24 const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1;
25
26 struct FrameHeaderTestCase {
27 const char* frame_header;
28 size_t frame_header_length;
29 uint64 frame_length;
30 };
31
32 const FrameHeaderTestCase kFrameHeaderTests[] = {
33 { "\x81\x00", 2, GG_UINT64_C(0) },
34 { "\x81\x7D", 2, GG_UINT64_C(125) },
35 { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126) },
36 { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF) },
37 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000) },
38 { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10,
39 GG_UINT64_C(0x7FFFFFFFFFFFFFFF) }
40 };
41 const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests);
42
43 } // Unnamed namespace
44
45 namespace net {
46
47 TEST(WebSocketFrameParserTest, DecodeNormalFrame) {
48 WebSocketFrameParser parser;
49
50 ScopedVector<WebSocketPartialFrame> frames;
51 EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames));
52 EXPECT_FALSE(parser.failed());
53 ASSERT_EQ(1u, frames.size());
54 WebSocketPartialFrame* frame = frames[0];
55 ASSERT_TRUE(frame != NULL);
56 const WebSocketFrameHeader* header = frame->header.get();
57 EXPECT_TRUE(header != NULL);
58 if (header) {
59 EXPECT_TRUE(header->final);
60 EXPECT_FALSE(header->reserved1);
61 EXPECT_FALSE(header->reserved2);
62 EXPECT_FALSE(header->reserved3);
63 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
64 EXPECT_FALSE(header->masked);
65 EXPECT_EQ(kHelloLength, header->payload_length);
66 }
67 EXPECT_TRUE(frame->final_part);
68
69 std::vector<char> expected_data(kHello, kHello + kHelloLength);
70 EXPECT_EQ(expected_data, frame->data);
71 }
72
73 TEST(WebSocketFrameParserTest, DecodeMaskedFrame) {
74 WebSocketFrameParser parser;
75
76 ScopedVector<WebSocketPartialFrame> frames;
77 EXPECT_TRUE(parser.Decode(kMaskedHelloFrame, kMaskedHelloFrameLength,
78 &frames));
79 EXPECT_FALSE(parser.failed());
80 ASSERT_EQ(1u, frames.size());
81 WebSocketPartialFrame* frame = frames[0];
82 ASSERT_TRUE(frame != NULL);
83 const WebSocketFrameHeader* header = frame->header.get();
84 EXPECT_TRUE(header != NULL);
85 if (header) {
86 EXPECT_TRUE(header->final);
87 EXPECT_FALSE(header->reserved1);
88 EXPECT_FALSE(header->reserved2);
89 EXPECT_FALSE(header->reserved3);
90 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
91 EXPECT_TRUE(header->masked);
92 EXPECT_EQ(kHelloLength, header->payload_length);
93 }
94 EXPECT_TRUE(frame->final_part);
95
96 std::vector<char> expected_data(kHello, kHello + kHelloLength);
97 EXPECT_EQ(expected_data, frame->data);
98 }
99
100 TEST(WebSocketFrameParserTest, DecodeManyFrames) {
mmenke 2012/05/02 16:15:41 You might want to make the frames marginally diffe
Yuta Kitamura 2012/05/08 08:21:58 Done.
101 static const int kRepeat = 10;
102
103 std::vector<char> input;
104 for (int i = 0; i < kRepeat; ++i)
105 input.insert(input.end(), kHelloFrame, kHelloFrame + kHelloFrameLength);
106
107 WebSocketFrameParser parser;
108
109 ScopedVector<WebSocketPartialFrame> frames;
110 EXPECT_TRUE(parser.Decode(&input.front(), input.size(), &frames));
111 EXPECT_FALSE(parser.failed());
112 EXPECT_EQ(static_cast<size_t>(kRepeat), frames.size());
113
114 std::vector<char> expected_data(kHello, kHello + kHelloLength);
115
116 for (size_t i = 0; i < frames.size(); ++i) {
117 WebSocketPartialFrame* frame = frames[i];
118 EXPECT_TRUE(frame != NULL);
119 if (!frame)
120 continue;
121 EXPECT_TRUE(frame->final_part);
122 EXPECT_EQ(expected_data, frame->data);
123
124 const WebSocketFrameHeader* header = frame->header.get();
125 EXPECT_TRUE(header != NULL);
126 if (!header)
127 continue;
128 EXPECT_TRUE(header->final);
129 EXPECT_FALSE(header->reserved1);
130 EXPECT_FALSE(header->reserved2);
131 EXPECT_FALSE(header->reserved3);
132 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
133 EXPECT_FALSE(header->masked);
134 EXPECT_EQ(kHelloLength, header->payload_length);
135 }
136 }
137
138 TEST(WebSocketFrameParserTest, DecodePartialFrame) {
139 static const size_t kFrameHeaderSize = 2;
140
141 for (size_t cutting_pos = 0; cutting_pos < kHelloLength - 1; ++cutting_pos) {
mmenke 2012/05/02 16:15:41 Shouldn't this be cutting_pos < kHelloLength, or c
Yuta Kitamura 2012/05/08 08:21:58 Nice catch! Fixed.
142 std::vector<char> input1(kHelloFrame,
143 kHelloFrame + kFrameHeaderSize + cutting_pos);
144 std::vector<char> input2(kHelloFrame + input1.size(),
145 kHelloFrame + kHelloFrameLength);
146
147 std::vector<char> expected1(kHello, kHello + cutting_pos);
148 std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
149
150 WebSocketFrameParser parser;
151
152 ScopedVector<WebSocketPartialFrame> frames1;
153 EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
154 EXPECT_FALSE(parser.failed());
155 EXPECT_EQ(1u, frames1.size());
156 if (frames1.size() != 1u)
157 continue;
158 WebSocketPartialFrame* frame1 = frames1[0];
159 EXPECT_TRUE(frame1 != NULL);
160 if (!frame1)
161 continue;
162 EXPECT_FALSE(frame1->final_part);
163 EXPECT_EQ(expected1, frame1->data);
164 const WebSocketFrameHeader* header1 = frame1->header.get();
165 EXPECT_TRUE(header1 != NULL);
166 if (!header1)
167 continue;
168 EXPECT_TRUE(header1->final);
169 EXPECT_FALSE(header1->reserved1);
170 EXPECT_FALSE(header1->reserved2);
171 EXPECT_FALSE(header1->reserved3);
172 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
173 EXPECT_FALSE(header1->masked);
174 EXPECT_EQ(kHelloLength, header1->payload_length);
175
176 ScopedVector<WebSocketPartialFrame> frames2;
177 EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
178 EXPECT_FALSE(parser.failed());
179 EXPECT_EQ(1u, frames2.size());
180 if (frames2.size() != 1u)
181 continue;
182 WebSocketPartialFrame* frame2 = frames2[0];
183 EXPECT_TRUE(frame2 != NULL);
184 if (!frame2)
185 continue;
186 EXPECT_TRUE(frame2->final_part);
187 EXPECT_EQ(expected2, frame2->data);
188 const WebSocketFrameHeader* header2 = frame2->header.get();
189 EXPECT_TRUE(header2 != NULL);
190 EXPECT_EQ(header1, header2);
191 if (!header2)
192 continue;
193 EXPECT_TRUE(header2->final);
194 EXPECT_FALSE(header2->reserved1);
195 EXPECT_FALSE(header2->reserved2);
196 EXPECT_FALSE(header2->reserved3);
197 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header2->opcode);
198 EXPECT_FALSE(header2->masked);
199 EXPECT_EQ(kHelloLength, header2->payload_length);
200 }
201 }
202
203 TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
204 static const size_t kFrameHeaderSize = 6;
205
206 for (size_t cutting_pos = 0; cutting_pos < kHelloLength - 1; ++cutting_pos) {
mmenke 2012/05/02 16:15:41 Again, this should be cutting_pos < kHelloLength.
Yuta Kitamura 2012/05/08 08:21:58 Done.
207 std::vector<char> input1(
208 kMaskedHelloFrame,
209 kMaskedHelloFrame + kFrameHeaderSize + cutting_pos);
210 std::vector<char> input2(kMaskedHelloFrame + input1.size(),
211 kMaskedHelloFrame + kMaskedHelloFrameLength);
212
213 std::vector<char> expected1(kHello, kHello + cutting_pos);
214 std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
215
216 WebSocketFrameParser parser;
217
218 ScopedVector<WebSocketPartialFrame> frames1;
219 EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
220 EXPECT_FALSE(parser.failed());
221 EXPECT_EQ(1u, frames1.size());
222 if (frames1.size() != 1u)
223 continue;
224 WebSocketPartialFrame* frame1 = frames1[0];
225 EXPECT_TRUE(frame1 != NULL);
226 if (!frame1)
227 continue;
228 EXPECT_FALSE(frame1->final_part);
229 EXPECT_EQ(expected1, frame1->data);
230 const WebSocketFrameHeader* header1 = frame1->header.get();
231 EXPECT_TRUE(header1 != NULL);
232 if (!header1)
233 continue;
234 EXPECT_TRUE(header1->final);
235 EXPECT_FALSE(header1->reserved1);
236 EXPECT_FALSE(header1->reserved2);
237 EXPECT_FALSE(header1->reserved3);
238 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
239 EXPECT_TRUE(header1->masked);
240 EXPECT_EQ(kHelloLength, header1->payload_length);
241
242 ScopedVector<WebSocketPartialFrame> frames2;
243 EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
244 EXPECT_FALSE(parser.failed());
245 EXPECT_EQ(1u, frames2.size());
246 if (frames2.size() != 1u)
247 continue;
248 WebSocketPartialFrame* frame2 = frames2[0];
249 EXPECT_TRUE(frame2 != NULL);
250 if (!frame2)
251 continue;
252 EXPECT_TRUE(frame2->final_part);
253 EXPECT_EQ(expected2, frame2->data);
254 const WebSocketFrameHeader* header2 = frame2->header.get();
255 EXPECT_TRUE(header2 != NULL);
256 EXPECT_EQ(header1, header2);
257 if (!header2)
258 continue;
259 EXPECT_TRUE(header2->final);
260 EXPECT_FALSE(header2->reserved1);
261 EXPECT_FALSE(header2->reserved2);
262 EXPECT_FALSE(header2->reserved3);
263 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header2->opcode);
264 EXPECT_TRUE(header2->masked);
265 EXPECT_EQ(kHelloLength, header2->payload_length);
266 }
267 }
268
269 TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) {
270 for (int i = 0; i < kNumFrameHeaderTests; ++i) {
271 const char* frame_header = kFrameHeaderTests[i].frame_header;
272 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length;
273 uint64 frame_length = kFrameHeaderTests[i].frame_length;
274
275 std::vector<char> input(frame_header, frame_header + frame_header_length);
276 // Limit the payload size not to flood the console on failure.
277 static const uint64 kMaxPayloadSize = 200;
278 uint64 input_payload_size = std::min(frame_length, kMaxPayloadSize);
279 input.insert(input.end(), input_payload_size, 'a');
280
281 WebSocketFrameParser parser;
282
283 ScopedVector<WebSocketPartialFrame> frames;
284 EXPECT_TRUE(parser.Decode(&input.front(), input.size(), &frames));
285 EXPECT_FALSE(parser.failed());
286 EXPECT_EQ(1u, frames.size());
287 if (frames.size() != 1u)
288 continue;
289 WebSocketPartialFrame* frame = frames[0];
290 EXPECT_TRUE(frame != NULL);
291 if (!frame)
292 continue;
293 if (frame_length == input_payload_size)
294 EXPECT_TRUE(frame->final_part);
295 else
296 EXPECT_FALSE(frame->final_part);
297 std::vector<char> expected_payload(input_payload_size, 'a');
298 EXPECT_EQ(expected_payload, frame->data);
299 const WebSocketFrameHeader* header = frame->header.get();
300 EXPECT_TRUE(header != NULL);
301 if (!header)
302 continue;
303 EXPECT_TRUE(header->final);
304 EXPECT_FALSE(header->reserved1);
305 EXPECT_FALSE(header->reserved2);
306 EXPECT_FALSE(header->reserved3);
307 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
308 EXPECT_FALSE(header->masked);
309 EXPECT_EQ(frame_length, header->payload_length);
310 }
311 }
312
313 TEST(WebSocketFrameParserTest, DecodePartialHeader) {
314 for (int i = 0; i < kNumFrameHeaderTests; ++i) {
315 const char* frame_header = kFrameHeaderTests[i].frame_header;
316 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length;
317 uint64 frame_length = kFrameHeaderTests[i].frame_length;
318
319 WebSocketFrameParser parser;
320
321 ScopedVector<WebSocketPartialFrame> frames;
322 // Feed each byte to the parser to see if the parser behaves correctly
323 // when it receives partial frame header.
324 for (size_t j = 0; j < frame_header_length; ++j) {
325 EXPECT_TRUE(parser.Decode(frame_header + j, 1, &frames));
326 EXPECT_FALSE(parser.failed());
327 if (j == frame_header_length - 1)
328 EXPECT_EQ(1u, frames.size());
329 else
330 EXPECT_EQ(0u, frames.size());
331 }
332 if (frames.size() != 1u)
333 continue;
334 WebSocketPartialFrame* frame = frames[0];
335 EXPECT_TRUE(frame != NULL);
336 if (!frame)
337 continue;
338 if (frame_length == 0u)
339 EXPECT_TRUE(frame->final_part);
340 else
341 EXPECT_FALSE(frame->final_part);
342 EXPECT_EQ(std::vector<char>(), frame->data);
343 const WebSocketFrameHeader* header = frame->header.get();
344 EXPECT_TRUE(header != NULL);
345 if (!header)
346 continue;
347 EXPECT_TRUE(header->final);
348 EXPECT_FALSE(header->reserved1);
349 EXPECT_FALSE(header->reserved2);
350 EXPECT_FALSE(header->reserved3);
351 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
352 EXPECT_FALSE(header->masked);
353 EXPECT_EQ(frame_length, header->payload_length);
354 }
355 }
356
357 TEST(WebSocketFrameParserTest, InvalidLengthEncoding) {
358 struct TestCase {
359 const char* frame_header;
360 size_t frame_header_length;
361 };
362 static const TestCase kTests[] = {
363 // For frames with two-byte extended length field, the payload length
364 // should be 126 (0x7E) bytes or more.
365 { "\x81\x7E\x00\x00", 4 },
366 { "\x81\x7E\x00\x7D", 4 },
367 // For frames with eight-byte extended length field, the payload length
368 // should be 0x10000 bytes or more.
369 { "\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10 },
370 { "\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10 },
371 };
372 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
373
374 for (int i = 0; i < kNumTests; ++i) {
375 const char* frame_header = kTests[i].frame_header;
376 size_t frame_header_length = kTests[i].frame_header_length;
377
378 WebSocketFrameParser parser;
379
380 ScopedVector<WebSocketPartialFrame> frames;
381 EXPECT_FALSE(parser.failed());
382 EXPECT_FALSE(parser.Decode(frame_header, frame_header_length, &frames));
383 EXPECT_TRUE(parser.failed());
384 EXPECT_EQ(0u, frames.size());
385
386 // Once the parser has failed, it no longer accepts any input (even if
387 // the input is empty).
388 EXPECT_FALSE(parser.Decode("", 0, &frames));
389 EXPECT_TRUE(parser.failed());
390 EXPECT_EQ(0u, frames.size());
391 }
392 }
393
394 TEST(WebSocketFrameParserTest, FrameTypes) {
395 struct TestCase {
396 const char* frame_header;
397 size_t frame_header_length;
398 WebSocketFrameHeader::OpCode opcode;
399 };
400 static const TestCase kTests[] = {
401 { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation },
402 { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText },
403 { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary },
404 { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose },
405 { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing },
406 { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong },
407 // These are undefined opcodes, but the parser needs to be able to parse
408 // them anyway.
409 { "\x83\x00", 2, 0x3 },
410 { "\x84\x00", 2, 0x4 },
411 { "\x85\x00", 2, 0x5 },
412 { "\x86\x00", 2, 0x6 },
413 { "\x87\x00", 2, 0x7 },
414 { "\x8B\x00", 2, 0xB },
415 { "\x8C\x00", 2, 0xC },
416 { "\x8D\x00", 2, 0xD },
417 { "\x8E\x00", 2, 0xE },
418 { "\x8F\x00", 2, 0xF }
419 };
420 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
421
422 for (int i = 0; i < kNumTests; ++i) {
423 const char* frame_header = kTests[i].frame_header;
424 size_t frame_header_length = kTests[i].frame_header_length;
425 WebSocketFrameHeader::OpCode opcode = kTests[i].opcode;
426
427 WebSocketFrameParser parser;
428
429 ScopedVector<WebSocketPartialFrame> frames;
430 EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
431 EXPECT_FALSE(parser.failed());
432 EXPECT_EQ(1u, frames.size());
433 if (frames.size() != 1u)
434 continue;
435 WebSocketPartialFrame* frame = frames[0];
436 EXPECT_TRUE(frame != NULL);
437 if (!frame)
438 continue;
439 EXPECT_TRUE(frame->final_part);
440 EXPECT_EQ(std::vector<char>(), frame->data);
441 const WebSocketFrameHeader* header = frame->header.get();
442 EXPECT_TRUE(header != NULL);
443 if (!header)
444 continue;
445 EXPECT_TRUE(header->final);
446 EXPECT_FALSE(header->reserved1);
447 EXPECT_FALSE(header->reserved2);
448 EXPECT_FALSE(header->reserved3);
449 EXPECT_EQ(opcode, header->opcode);
450 EXPECT_FALSE(header->masked);
451 EXPECT_EQ(0u, header->payload_length);
452 };
453 }
454
455 TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) {
456 struct TestCase {
457 const char* frame_header;
458 size_t frame_header_length;
459 bool final;
460 bool reserved1;
461 bool reserved2;
462 bool reserved3;
463 };
464 static const TestCase kTests[] = {
465 { "\x81\x00", 2, true, false, false, false },
466 { "\x01\x00", 2, false, false, false, false },
467 { "\xC1\x00", 2, true, true, false, false },
468 { "\xA1\x00", 2, true, false, true, false },
469 { "\x91\x00", 2, true, false, false, true },
470 { "\x71\x00", 2, false, true, true, true },
471 { "\xF1\x00", 2, true, true, true, true }
472 };
473 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
474
475 for (int i = 0; i < kNumTests; ++i) {
476 const char* frame_header = kTests[i].frame_header;
477 size_t frame_header_length = kTests[i].frame_header_length;
478 bool final = kTests[i].final;
479 bool reserved1 = kTests[i].reserved1;
480 bool reserved2 = kTests[i].reserved2;
481 bool reserved3 = kTests[i].reserved3;
482
483 WebSocketFrameParser parser;
484
485 ScopedVector<WebSocketPartialFrame> frames;
486 EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
487 EXPECT_FALSE(parser.failed());
488 EXPECT_EQ(1u, frames.size());
489 if (frames.size() != 1u)
490 continue;
491 WebSocketPartialFrame* frame = frames[0];
492 EXPECT_TRUE(frame != NULL);
493 if (!frame)
494 continue;
495 EXPECT_TRUE(frame->final_part);
496 EXPECT_EQ(std::vector<char>(), frame->data);
497 const WebSocketFrameHeader* header = frame->header.get();
498 EXPECT_TRUE(header != NULL);
499 if (!header)
500 continue;
501 EXPECT_EQ(final, header->final);
502 EXPECT_EQ(reserved1, header->reserved1);
503 EXPECT_EQ(reserved2, header->reserved2);
504 EXPECT_EQ(reserved3, header->reserved3);
505 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
506 EXPECT_FALSE(header->masked);
507 EXPECT_EQ(0u, header->payload_length);
508 }
509 }
510
511 } // namespace net
OLDNEW
« net/websockets/websocket_frame_parser.cc ('K') | « net/websockets/websocket_frame_parser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698