- add sources.
[platform/framework/web/crosswalk.git] / src / net / websockets / websocket_frame_parser_test.cc
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.
4
5 #include "net/websockets/websocket_frame_parser.h"
6
7 #include <algorithm>
8 #include <vector>
9
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"
16
17 namespace net {
18
19 namespace {
20
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;
29
30 struct FrameHeaderTestCase {
31   const char* frame_header;
32   size_t frame_header_length;
33   uint64 frame_length;
34   WebSocketError error_code;
35 };
36
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 }
50 };
51 const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests);
52
53 TEST(WebSocketFrameParserTest, DecodeNormalFrame) {
54   WebSocketFrameParser parser;
55
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);
64   if (header) {
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);
72   }
73   EXPECT_TRUE(frame->final_chunk);
74
75   ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size());
76   EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data()));
77 }
78
79 TEST(WebSocketFrameParserTest, DecodeMaskedFrame) {
80   WebSocketFrameParser parser;
81
82   ScopedVector<WebSocketFrameChunk> frames;
83   EXPECT_TRUE(
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);
91   if (header) {
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);
99   }
100   EXPECT_TRUE(frame->final_chunk);
101
102   ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size());
103   EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data()));
104 }
105
106 TEST(WebSocketFrameParserTest, DecodeManyFrames) {
107   struct Input {
108     const char* frame;
109     size_t frame_length;
110     const char* expected_payload;
111     size_t expected_payload_length;
112   };
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 }
128   };
129   static const int kNumInputs = ARRAYSIZE_UNSAFE(kInputs);
130
131   std::vector<char> input;
132   // Concatenate all frames.
133   for (int i = 0; i < kNumInputs; ++i) {
134     input.insert(input.end(),
135                  kInputs[i].frame,
136                  kInputs[i].frame + kInputs[i].frame_length);
137   }
138
139   WebSocketFrameParser parser;
140
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());
145
146   for (int i = 0; i < kNumInputs; ++i) {
147     WebSocketFrameChunk* frame = frames[i];
148     EXPECT_TRUE(frame != NULL);
149     if (!frame)
150       continue;
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()));
158
159     const WebSocketFrameHeader* header = frame->header.get();
160     EXPECT_TRUE(header != NULL);
161     if (!header)
162       continue;
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);
170   }
171 }
172
173 TEST(WebSocketFrameParserTest, DecodePartialFrame) {
174   static const size_t kFrameHeaderSize = 2;
175
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);
181
182     std::vector<char> expected1(kHello, kHello + cutting_pos);
183     std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
184
185     WebSocketFrameParser parser;
186
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)
192       continue;
193     WebSocketFrameChunk* frame1 = frames1[0];
194     EXPECT_TRUE(frame1 != NULL);
195     if (!frame1)
196       continue;
197     EXPECT_FALSE(frame1->final_chunk);
198     if (expected1.size() == 0) {
199       EXPECT_EQ(NULL, frame1->data.get());
200     } else {
201       ASSERT_EQ(cutting_pos, static_cast<size_t>(frame1->data->size()));
202       EXPECT_TRUE(
203           std::equal(expected1.begin(), expected1.end(), frame1->data->data()));
204     }
205     const WebSocketFrameHeader* header1 = frame1->header.get();
206     EXPECT_TRUE(header1 != NULL);
207     if (!header1)
208       continue;
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);
216
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)
222       continue;
223     WebSocketFrameChunk* frame2 = frames2[0];
224     EXPECT_TRUE(frame2 != NULL);
225     if (!frame2)
226       continue;
227     EXPECT_TRUE(frame2->final_chunk);
228     if (expected2.size() == 0) {
229       EXPECT_EQ(NULL, frame2->data.get());
230     } else {
231       ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size()));
232       EXPECT_TRUE(
233           std::equal(expected2.begin(), expected2.end(), frame2->data->data()));
234     }
235     const WebSocketFrameHeader* header2 = frame2->header.get();
236     EXPECT_TRUE(header2 == NULL);
237   }
238 }
239
240 TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
241   static const size_t kFrameHeaderSize = 6;
242
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);
248
249     std::vector<char> expected1(kHello, kHello + cutting_pos);
250     std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
251
252     WebSocketFrameParser parser;
253
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)
259       continue;
260     WebSocketFrameChunk* frame1 = frames1[0];
261     EXPECT_TRUE(frame1 != NULL);
262     if (!frame1)
263       continue;
264     EXPECT_FALSE(frame1->final_chunk);
265     if (expected1.size() == 0) {
266       EXPECT_EQ(NULL, frame1->data.get());
267     } else {
268       ASSERT_EQ(expected1.size(), static_cast<uint64>(frame1->data->size()));
269       EXPECT_TRUE(
270           std::equal(expected1.begin(), expected1.end(), frame1->data->data()));
271     }
272     const WebSocketFrameHeader* header1 = frame1->header.get();
273     EXPECT_TRUE(header1 != NULL);
274     if (!header1)
275       continue;
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);
283
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)
289       continue;
290     WebSocketFrameChunk* frame2 = frames2[0];
291     EXPECT_TRUE(frame2 != NULL);
292     if (!frame2)
293       continue;
294     EXPECT_TRUE(frame2->final_chunk);
295     if (expected2.size() == 0) {
296       EXPECT_EQ(NULL, frame2->data.get());
297     } else {
298       ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size()));
299       EXPECT_TRUE(
300           std::equal(expected2.begin(), expected2.end(), frame2->data->data()));
301     }
302     const WebSocketFrameHeader* header2 = frame2->header.get();
303     EXPECT_TRUE(header2 == NULL);
304   }
305 }
306
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;
312
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');
318
319     WebSocketFrameParser parser;
320
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());
327     } else {
328       EXPECT_EQ(1u, frames.size());
329     }
330     if (frames.size() != 1u)
331       continue;
332     WebSocketFrameChunk* frame = frames[0];
333     EXPECT_TRUE(frame != NULL);
334     if (!frame)
335       continue;
336     if (frame_length == input_payload_size) {
337       EXPECT_TRUE(frame->final_chunk);
338     } else {
339       EXPECT_FALSE(frame->final_chunk);
340     }
341     std::vector<char> expected_payload(input_payload_size, 'a');
342     if (expected_payload.size() == 0) {
343       EXPECT_EQ(NULL, frame->data.get());
344     } else {
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()));
350     }
351     const WebSocketFrameHeader* header = frame->header.get();
352     EXPECT_TRUE(header != NULL);
353     if (!header)
354       continue;
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);
362   }
363 }
364
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;
370
371     WebSocketFrameParser parser;
372
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) {
378       bool failed =
379           kFrameHeaderTests[i].error_code != kWebSocketNormalClosure &&
380           j == last_byte_offset;
381       EXPECT_EQ(!failed, parser.Decode(frame_header + j, 1, &frames));
382       if (failed) {
383         EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
384       } else {
385         EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
386       }
387       if (kFrameHeaderTests[i].error_code == kWebSocketNormalClosure &&
388           j == last_byte_offset) {
389         EXPECT_EQ(1u, frames.size());
390       } else {
391         EXPECT_EQ(0u, frames.size());
392       }
393     }
394     if (frames.size() != 1u)
395       continue;
396     WebSocketFrameChunk* frame = frames[0];
397     EXPECT_TRUE(frame != NULL);
398     if (!frame)
399       continue;
400     if (frame_length == 0u) {
401       EXPECT_TRUE(frame->final_chunk);
402     } else {
403       EXPECT_FALSE(frame->final_chunk);
404     }
405     EXPECT_EQ(NULL, frame->data.get());
406     const WebSocketFrameHeader* header = frame->header.get();
407     EXPECT_TRUE(header != NULL);
408     if (!header)
409       continue;
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);
417   }
418 }
419
420 TEST(WebSocketFrameParserTest, InvalidLengthEncoding) {
421   struct TestCase {
422     const char* frame_header;
423     size_t frame_header_length;
424   };
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 },
434   };
435   static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
436
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;
440
441     WebSocketFrameParser parser;
442
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());
448
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());
454   }
455 }
456
457 TEST(WebSocketFrameParserTest, FrameTypes) {
458   struct TestCase {
459     const char* frame_header;
460     size_t frame_header_length;
461     WebSocketFrameHeader::OpCode opcode;
462   };
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
471     // them anyway.
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 }
482   };
483   static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
484
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;
489
490     WebSocketFrameParser parser;
491
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)
497       continue;
498     WebSocketFrameChunk* frame = frames[0];
499     EXPECT_TRUE(frame != NULL);
500     if (!frame)
501       continue;
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);
506     if (!header)
507       continue;
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);
515   }
516 }
517
518 TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) {
519   struct TestCase {
520     const char* frame_header;
521     size_t frame_header_length;
522     bool final;
523     bool reserved1;
524     bool reserved2;
525     bool reserved3;
526   };
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 }
535   };
536   static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
537
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;
545
546     WebSocketFrameParser parser;
547
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)
553       continue;
554     WebSocketFrameChunk* frame = frames[0];
555     EXPECT_TRUE(frame != NULL);
556     if (!frame)
557       continue;
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);
562     if (!header)
563       continue;
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);
571   }
572 }
573
574 }  // Unnamed namespace
575
576 }  // namespace net