1 // Copyright 2013 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.
5 #include "net/websockets/websocket_frame_parser.h"
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/port.h"
13 #include "net/base/io_buffer.h"
14 #include "net/websockets/websocket_frame.h"
15 #include "testing/gtest/include/gtest/gtest.h"
21 const char kHello
[] = "Hello, world!";
22 const uint64 kHelloLength
= arraysize(kHello
) - 1;
23 const char kHelloFrame
[] = "\x81\x0DHello, world!";
24 const uint64 kHelloFrameLength
= arraysize(kHelloFrame
) - 1;
25 const char kMaskedHelloFrame
[] =
26 "\x81\x8D\xDE\xAD\xBE\xEF"
27 "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
28 const uint64 kMaskedHelloFrameLength
= arraysize(kMaskedHelloFrame
) - 1;
30 struct FrameHeaderTestCase
{
31 const char* frame_header
;
32 size_t frame_header_length
;
34 WebSocketError error_code
;
37 const FrameHeaderTestCase kFrameHeaderTests
[] = {
38 { "\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure
},
39 { "\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure
},
40 { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure
},
41 { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure
},
42 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000),
43 kWebSocketNormalClosure
},
44 { "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF),
45 kWebSocketNormalClosure
},
46 { "\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000),
47 kWebSocketErrorMessageTooBig
},
48 { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10,
49 GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig
}
51 const int kNumFrameHeaderTests
= arraysize(kFrameHeaderTests
);
53 TEST(WebSocketFrameParserTest
, DecodeNormalFrame
) {
54 WebSocketFrameParser parser
;
56 ScopedVector
<WebSocketFrameChunk
> frames
;
57 EXPECT_TRUE(parser
.Decode(kHelloFrame
, kHelloFrameLength
, &frames
));
58 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
59 ASSERT_EQ(1u, frames
.size());
60 WebSocketFrameChunk
* frame
= frames
[0];
61 ASSERT_TRUE(frame
!= NULL
);
62 const WebSocketFrameHeader
* header
= frame
->header
.get();
63 EXPECT_TRUE(header
!= NULL
);
65 EXPECT_TRUE(header
->final
);
66 EXPECT_FALSE(header
->reserved1
);
67 EXPECT_FALSE(header
->reserved2
);
68 EXPECT_FALSE(header
->reserved3
);
69 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
70 EXPECT_FALSE(header
->masked
);
71 EXPECT_EQ(kHelloLength
, header
->payload_length
);
73 EXPECT_TRUE(frame
->final_chunk
);
75 ASSERT_EQ(static_cast<int>(kHelloLength
), frame
->data
->size());
76 EXPECT_TRUE(std::equal(kHello
, kHello
+ kHelloLength
, frame
->data
->data()));
79 TEST(WebSocketFrameParserTest
, DecodeMaskedFrame
) {
80 WebSocketFrameParser parser
;
82 ScopedVector
<WebSocketFrameChunk
> frames
;
84 parser
.Decode(kMaskedHelloFrame
, kMaskedHelloFrameLength
, &frames
));
85 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
86 ASSERT_EQ(1u, frames
.size());
87 WebSocketFrameChunk
* frame
= frames
[0];
88 ASSERT_TRUE(frame
!= NULL
);
89 const WebSocketFrameHeader
* header
= frame
->header
.get();
90 EXPECT_TRUE(header
!= NULL
);
92 EXPECT_TRUE(header
->final
);
93 EXPECT_FALSE(header
->reserved1
);
94 EXPECT_FALSE(header
->reserved2
);
95 EXPECT_FALSE(header
->reserved3
);
96 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
97 EXPECT_TRUE(header
->masked
);
98 EXPECT_EQ(kHelloLength
, header
->payload_length
);
100 EXPECT_TRUE(frame
->final_chunk
);
102 ASSERT_EQ(static_cast<int>(kHelloLength
), frame
->data
->size());
103 EXPECT_TRUE(std::equal(kHello
, kHello
+ kHelloLength
, frame
->data
->data()));
106 TEST(WebSocketFrameParserTest
, DecodeManyFrames
) {
110 const char* expected_payload
;
111 size_t expected_payload_length
;
113 static const Input kInputs
[] = {
114 // Each |frame| data is split into two string literals because C++ lexers
115 // consume unlimited number of hex characters in a hex character escape
116 // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as
117 // { '\x5F', '\0' }).
118 { "\x81\x05" "First", 7, "First", 5 },
119 { "\x81\x06" "Second", 8, "Second", 6 },
120 { "\x81\x05" "Third", 7, "Third", 5 },
121 { "\x81\x06" "Fourth", 8, "Fourth", 6 },
122 { "\x81\x05" "Fifth", 7, "Fifth", 5 },
123 { "\x81\x05" "Sixth", 7, "Sixth", 5 },
124 { "\x81\x07" "Seventh", 9, "Seventh", 7 },
125 { "\x81\x06" "Eighth", 8, "Eighth", 6 },
126 { "\x81\x05" "Ninth", 7, "Ninth", 5 },
127 { "\x81\x05" "Tenth", 7, "Tenth", 5 }
129 static const int kNumInputs
= ARRAYSIZE_UNSAFE(kInputs
);
131 std::vector
<char> input
;
132 // Concatenate all frames.
133 for (int i
= 0; i
< kNumInputs
; ++i
) {
134 input
.insert(input
.end(),
136 kInputs
[i
].frame
+ kInputs
[i
].frame_length
);
139 WebSocketFrameParser parser
;
141 ScopedVector
<WebSocketFrameChunk
> frames
;
142 EXPECT_TRUE(parser
.Decode(&input
.front(), input
.size(), &frames
));
143 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
144 ASSERT_EQ(static_cast<size_t>(kNumInputs
), frames
.size());
146 for (int i
= 0; i
< kNumInputs
; ++i
) {
147 WebSocketFrameChunk
* frame
= frames
[i
];
148 EXPECT_TRUE(frame
!= NULL
);
151 EXPECT_TRUE(frame
->final_chunk
);
152 ASSERT_EQ(kInputs
[i
].expected_payload_length
,
153 static_cast<uint64
>(frame
->data
->size()));
154 EXPECT_TRUE(std::equal(
155 kInputs
[i
].expected_payload
,
156 kInputs
[i
].expected_payload
+ kInputs
[i
].expected_payload_length
,
157 frame
->data
->data()));
159 const WebSocketFrameHeader
* header
= frame
->header
.get();
160 EXPECT_TRUE(header
!= NULL
);
163 EXPECT_TRUE(header
->final
);
164 EXPECT_FALSE(header
->reserved1
);
165 EXPECT_FALSE(header
->reserved2
);
166 EXPECT_FALSE(header
->reserved3
);
167 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
168 EXPECT_FALSE(header
->masked
);
169 EXPECT_EQ(kInputs
[i
].expected_payload_length
, header
->payload_length
);
173 TEST(WebSocketFrameParserTest
, DecodePartialFrame
) {
174 static const size_t kFrameHeaderSize
= 2;
176 for (size_t cutting_pos
= 0; cutting_pos
< kHelloLength
; ++cutting_pos
) {
177 std::vector
<char> input1(kHelloFrame
,
178 kHelloFrame
+ kFrameHeaderSize
+ cutting_pos
);
179 std::vector
<char> input2(kHelloFrame
+ input1
.size(),
180 kHelloFrame
+ kHelloFrameLength
);
182 std::vector
<char> expected1(kHello
, kHello
+ cutting_pos
);
183 std::vector
<char> expected2(kHello
+ cutting_pos
, kHello
+ kHelloLength
);
185 WebSocketFrameParser parser
;
187 ScopedVector
<WebSocketFrameChunk
> frames1
;
188 EXPECT_TRUE(parser
.Decode(&input1
.front(), input1
.size(), &frames1
));
189 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
190 EXPECT_EQ(1u, frames1
.size());
191 if (frames1
.size() != 1u)
193 WebSocketFrameChunk
* frame1
= frames1
[0];
194 EXPECT_TRUE(frame1
!= NULL
);
197 EXPECT_FALSE(frame1
->final_chunk
);
198 if (expected1
.size() == 0) {
199 EXPECT_EQ(NULL
, frame1
->data
.get());
201 ASSERT_EQ(cutting_pos
, static_cast<size_t>(frame1
->data
->size()));
203 std::equal(expected1
.begin(), expected1
.end(), frame1
->data
->data()));
205 const WebSocketFrameHeader
* header1
= frame1
->header
.get();
206 EXPECT_TRUE(header1
!= NULL
);
209 EXPECT_TRUE(header1
->final
);
210 EXPECT_FALSE(header1
->reserved1
);
211 EXPECT_FALSE(header1
->reserved2
);
212 EXPECT_FALSE(header1
->reserved3
);
213 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header1
->opcode
);
214 EXPECT_FALSE(header1
->masked
);
215 EXPECT_EQ(kHelloLength
, header1
->payload_length
);
217 ScopedVector
<WebSocketFrameChunk
> frames2
;
218 EXPECT_TRUE(parser
.Decode(&input2
.front(), input2
.size(), &frames2
));
219 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
220 EXPECT_EQ(1u, frames2
.size());
221 if (frames2
.size() != 1u)
223 WebSocketFrameChunk
* frame2
= frames2
[0];
224 EXPECT_TRUE(frame2
!= NULL
);
227 EXPECT_TRUE(frame2
->final_chunk
);
228 if (expected2
.size() == 0) {
229 EXPECT_EQ(NULL
, frame2
->data
.get());
231 ASSERT_EQ(expected2
.size(), static_cast<uint64
>(frame2
->data
->size()));
233 std::equal(expected2
.begin(), expected2
.end(), frame2
->data
->data()));
235 const WebSocketFrameHeader
* header2
= frame2
->header
.get();
236 EXPECT_TRUE(header2
== NULL
);
240 TEST(WebSocketFrameParserTest
, DecodePartialMaskedFrame
) {
241 static const size_t kFrameHeaderSize
= 6;
243 for (size_t cutting_pos
= 0; cutting_pos
< kHelloLength
; ++cutting_pos
) {
244 std::vector
<char> input1(
245 kMaskedHelloFrame
, kMaskedHelloFrame
+ kFrameHeaderSize
+ cutting_pos
);
246 std::vector
<char> input2(kMaskedHelloFrame
+ input1
.size(),
247 kMaskedHelloFrame
+ kMaskedHelloFrameLength
);
249 std::vector
<char> expected1(kHello
, kHello
+ cutting_pos
);
250 std::vector
<char> expected2(kHello
+ cutting_pos
, kHello
+ kHelloLength
);
252 WebSocketFrameParser parser
;
254 ScopedVector
<WebSocketFrameChunk
> frames1
;
255 EXPECT_TRUE(parser
.Decode(&input1
.front(), input1
.size(), &frames1
));
256 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
257 EXPECT_EQ(1u, frames1
.size());
258 if (frames1
.size() != 1u)
260 WebSocketFrameChunk
* frame1
= frames1
[0];
261 EXPECT_TRUE(frame1
!= NULL
);
264 EXPECT_FALSE(frame1
->final_chunk
);
265 if (expected1
.size() == 0) {
266 EXPECT_EQ(NULL
, frame1
->data
.get());
268 ASSERT_EQ(expected1
.size(), static_cast<uint64
>(frame1
->data
->size()));
270 std::equal(expected1
.begin(), expected1
.end(), frame1
->data
->data()));
272 const WebSocketFrameHeader
* header1
= frame1
->header
.get();
273 EXPECT_TRUE(header1
!= NULL
);
276 EXPECT_TRUE(header1
->final
);
277 EXPECT_FALSE(header1
->reserved1
);
278 EXPECT_FALSE(header1
->reserved2
);
279 EXPECT_FALSE(header1
->reserved3
);
280 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header1
->opcode
);
281 EXPECT_TRUE(header1
->masked
);
282 EXPECT_EQ(kHelloLength
, header1
->payload_length
);
284 ScopedVector
<WebSocketFrameChunk
> frames2
;
285 EXPECT_TRUE(parser
.Decode(&input2
.front(), input2
.size(), &frames2
));
286 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
287 EXPECT_EQ(1u, frames2
.size());
288 if (frames2
.size() != 1u)
290 WebSocketFrameChunk
* frame2
= frames2
[0];
291 EXPECT_TRUE(frame2
!= NULL
);
294 EXPECT_TRUE(frame2
->final_chunk
);
295 if (expected2
.size() == 0) {
296 EXPECT_EQ(NULL
, frame2
->data
.get());
298 ASSERT_EQ(expected2
.size(), static_cast<uint64
>(frame2
->data
->size()));
300 std::equal(expected2
.begin(), expected2
.end(), frame2
->data
->data()));
302 const WebSocketFrameHeader
* header2
= frame2
->header
.get();
303 EXPECT_TRUE(header2
== NULL
);
307 TEST(WebSocketFrameParserTest
, DecodeFramesOfVariousLengths
) {
308 for (int i
= 0; i
< kNumFrameHeaderTests
; ++i
) {
309 const char* frame_header
= kFrameHeaderTests
[i
].frame_header
;
310 size_t frame_header_length
= kFrameHeaderTests
[i
].frame_header_length
;
311 uint64 frame_length
= kFrameHeaderTests
[i
].frame_length
;
313 std::vector
<char> input(frame_header
, frame_header
+ frame_header_length
);
314 // Limit the payload size not to flood the console on failure.
315 static const uint64 kMaxPayloadSize
= 200;
316 uint64 input_payload_size
= std::min(frame_length
, kMaxPayloadSize
);
317 input
.insert(input
.end(), input_payload_size
, 'a');
319 WebSocketFrameParser parser
;
321 ScopedVector
<WebSocketFrameChunk
> frames
;
322 EXPECT_EQ(kFrameHeaderTests
[i
].error_code
== kWebSocketNormalClosure
,
323 parser
.Decode(&input
.front(), input
.size(), &frames
));
324 EXPECT_EQ(kFrameHeaderTests
[i
].error_code
, parser
.websocket_error());
325 if (kFrameHeaderTests
[i
].error_code
!= kWebSocketNormalClosure
) {
326 EXPECT_EQ(0u, frames
.size());
328 EXPECT_EQ(1u, frames
.size());
330 if (frames
.size() != 1u)
332 WebSocketFrameChunk
* frame
= frames
[0];
333 EXPECT_TRUE(frame
!= NULL
);
336 if (frame_length
== input_payload_size
) {
337 EXPECT_TRUE(frame
->final_chunk
);
339 EXPECT_FALSE(frame
->final_chunk
);
341 std::vector
<char> expected_payload(input_payload_size
, 'a');
342 if (expected_payload
.size() == 0) {
343 EXPECT_EQ(NULL
, frame
->data
.get());
345 ASSERT_EQ(expected_payload
.size(),
346 static_cast<uint64
>(frame
->data
->size()));
347 EXPECT_TRUE(std::equal(expected_payload
.begin(),
348 expected_payload
.end(),
349 frame
->data
->data()));
351 const WebSocketFrameHeader
* header
= frame
->header
.get();
352 EXPECT_TRUE(header
!= NULL
);
355 EXPECT_TRUE(header
->final
);
356 EXPECT_FALSE(header
->reserved1
);
357 EXPECT_FALSE(header
->reserved2
);
358 EXPECT_FALSE(header
->reserved3
);
359 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
360 EXPECT_FALSE(header
->masked
);
361 EXPECT_EQ(frame_length
, header
->payload_length
);
365 TEST(WebSocketFrameParserTest
, DecodePartialHeader
) {
366 for (int i
= 0; i
< kNumFrameHeaderTests
; ++i
) {
367 const char* frame_header
= kFrameHeaderTests
[i
].frame_header
;
368 size_t frame_header_length
= kFrameHeaderTests
[i
].frame_header_length
;
369 uint64 frame_length
= kFrameHeaderTests
[i
].frame_length
;
371 WebSocketFrameParser parser
;
373 ScopedVector
<WebSocketFrameChunk
> frames
;
374 // Feed each byte to the parser to see if the parser behaves correctly
375 // when it receives partial frame header.
376 size_t last_byte_offset
= frame_header_length
- 1;
377 for (size_t j
= 0; j
< frame_header_length
; ++j
) {
379 kFrameHeaderTests
[i
].error_code
!= kWebSocketNormalClosure
&&
380 j
== last_byte_offset
;
381 EXPECT_EQ(!failed
, parser
.Decode(frame_header
+ j
, 1, &frames
));
383 EXPECT_EQ(kFrameHeaderTests
[i
].error_code
, parser
.websocket_error());
385 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
387 if (kFrameHeaderTests
[i
].error_code
== kWebSocketNormalClosure
&&
388 j
== last_byte_offset
) {
389 EXPECT_EQ(1u, frames
.size());
391 EXPECT_EQ(0u, frames
.size());
394 if (frames
.size() != 1u)
396 WebSocketFrameChunk
* frame
= frames
[0];
397 EXPECT_TRUE(frame
!= NULL
);
400 if (frame_length
== 0u) {
401 EXPECT_TRUE(frame
->final_chunk
);
403 EXPECT_FALSE(frame
->final_chunk
);
405 EXPECT_EQ(NULL
, frame
->data
.get());
406 const WebSocketFrameHeader
* header
= frame
->header
.get();
407 EXPECT_TRUE(header
!= NULL
);
410 EXPECT_TRUE(header
->final
);
411 EXPECT_FALSE(header
->reserved1
);
412 EXPECT_FALSE(header
->reserved2
);
413 EXPECT_FALSE(header
->reserved3
);
414 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
415 EXPECT_FALSE(header
->masked
);
416 EXPECT_EQ(frame_length
, header
->payload_length
);
420 TEST(WebSocketFrameParserTest
, InvalidLengthEncoding
) {
422 const char* frame_header
;
423 size_t frame_header_length
;
425 static const TestCase kTests
[] = {
426 // For frames with two-byte extended length field, the payload length
427 // should be 126 (0x7E) bytes or more.
428 { "\x81\x7E\x00\x00", 4 },
429 { "\x81\x7E\x00\x7D", 4 },
430 // For frames with eight-byte extended length field, the payload length
431 // should be 0x10000 bytes or more.
432 { "\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10 },
433 { "\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10 },
435 static const int kNumTests
= ARRAYSIZE_UNSAFE(kTests
);
437 for (int i
= 0; i
< kNumTests
; ++i
) {
438 const char* frame_header
= kTests
[i
].frame_header
;
439 size_t frame_header_length
= kTests
[i
].frame_header_length
;
441 WebSocketFrameParser parser
;
443 ScopedVector
<WebSocketFrameChunk
> frames
;
444 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
445 EXPECT_FALSE(parser
.Decode(frame_header
, frame_header_length
, &frames
));
446 EXPECT_EQ(kWebSocketErrorProtocolError
, parser
.websocket_error());
447 EXPECT_EQ(0u, frames
.size());
449 // Once the parser has failed, it no longer accepts any input (even if
450 // the input is empty).
451 EXPECT_FALSE(parser
.Decode("", 0, &frames
));
452 EXPECT_EQ(kWebSocketErrorProtocolError
, parser
.websocket_error());
453 EXPECT_EQ(0u, frames
.size());
457 TEST(WebSocketFrameParserTest
, FrameTypes
) {
459 const char* frame_header
;
460 size_t frame_header_length
;
461 WebSocketFrameHeader::OpCode opcode
;
463 static const TestCase kTests
[] = {
464 { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation
},
465 { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText
},
466 { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary
},
467 { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose
},
468 { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing
},
469 { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong
},
470 // These are undefined opcodes, but the parser needs to be able to parse
472 { "\x83\x00", 2, 0x3 },
473 { "\x84\x00", 2, 0x4 },
474 { "\x85\x00", 2, 0x5 },
475 { "\x86\x00", 2, 0x6 },
476 { "\x87\x00", 2, 0x7 },
477 { "\x8B\x00", 2, 0xB },
478 { "\x8C\x00", 2, 0xC },
479 { "\x8D\x00", 2, 0xD },
480 { "\x8E\x00", 2, 0xE },
481 { "\x8F\x00", 2, 0xF }
483 static const int kNumTests
= ARRAYSIZE_UNSAFE(kTests
);
485 for (int i
= 0; i
< kNumTests
; ++i
) {
486 const char* frame_header
= kTests
[i
].frame_header
;
487 size_t frame_header_length
= kTests
[i
].frame_header_length
;
488 WebSocketFrameHeader::OpCode opcode
= kTests
[i
].opcode
;
490 WebSocketFrameParser parser
;
492 ScopedVector
<WebSocketFrameChunk
> frames
;
493 EXPECT_TRUE(parser
.Decode(frame_header
, frame_header_length
, &frames
));
494 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
495 EXPECT_EQ(1u, frames
.size());
496 if (frames
.size() != 1u)
498 WebSocketFrameChunk
* frame
= frames
[0];
499 EXPECT_TRUE(frame
!= NULL
);
502 EXPECT_TRUE(frame
->final_chunk
);
503 EXPECT_EQ(NULL
, frame
->data
.get());
504 const WebSocketFrameHeader
* header
= frame
->header
.get();
505 EXPECT_TRUE(header
!= NULL
);
508 EXPECT_TRUE(header
->final
);
509 EXPECT_FALSE(header
->reserved1
);
510 EXPECT_FALSE(header
->reserved2
);
511 EXPECT_FALSE(header
->reserved3
);
512 EXPECT_EQ(opcode
, header
->opcode
);
513 EXPECT_FALSE(header
->masked
);
514 EXPECT_EQ(0u, header
->payload_length
);
518 TEST(WebSocketFrameParserTest
, FinalBitAndReservedBits
) {
520 const char* frame_header
;
521 size_t frame_header_length
;
527 static const TestCase kTests
[] = {
528 { "\x81\x00", 2, true, false, false, false },
529 { "\x01\x00", 2, false, false, false, false },
530 { "\xC1\x00", 2, true, true, false, false },
531 { "\xA1\x00", 2, true, false, true, false },
532 { "\x91\x00", 2, true, false, false, true },
533 { "\x71\x00", 2, false, true, true, true },
534 { "\xF1\x00", 2, true, true, true, true }
536 static const int kNumTests
= ARRAYSIZE_UNSAFE(kTests
);
538 for (int i
= 0; i
< kNumTests
; ++i
) {
539 const char* frame_header
= kTests
[i
].frame_header
;
540 size_t frame_header_length
= kTests
[i
].frame_header_length
;
541 bool final
= kTests
[i
].final
;
542 bool reserved1
= kTests
[i
].reserved1
;
543 bool reserved2
= kTests
[i
].reserved2
;
544 bool reserved3
= kTests
[i
].reserved3
;
546 WebSocketFrameParser parser
;
548 ScopedVector
<WebSocketFrameChunk
> frames
;
549 EXPECT_TRUE(parser
.Decode(frame_header
, frame_header_length
, &frames
));
550 EXPECT_EQ(kWebSocketNormalClosure
, parser
.websocket_error());
551 EXPECT_EQ(1u, frames
.size());
552 if (frames
.size() != 1u)
554 WebSocketFrameChunk
* frame
= frames
[0];
555 EXPECT_TRUE(frame
!= NULL
);
558 EXPECT_TRUE(frame
->final_chunk
);
559 EXPECT_EQ(NULL
, frame
->data
.get());
560 const WebSocketFrameHeader
* header
= frame
->header
.get();
561 EXPECT_TRUE(header
!= NULL
);
564 EXPECT_EQ(final
, header
->final
);
565 EXPECT_EQ(reserved1
, header
->reserved1
);
566 EXPECT_EQ(reserved2
, header
->reserved2
);
567 EXPECT_EQ(reserved3
, header
->reserved3
);
568 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, header
->opcode
);
569 EXPECT_FALSE(header
->masked
);
570 EXPECT_EQ(0u, header
->payload_length
);
574 } // Unnamed namespace