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
17namespace net {
18
19namespace {
20
21const char kHello[] = "Hello, world!";
22const uint64 kHelloLength = arraysize(kHello) - 1;
23const char kHelloFrame[] = "\x81\x0DHello, world!";
24const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1;
25const char kMaskedHelloFrame[] =
26    "\x81\x8D\xDE\xAD\xBE\xEF"
27    "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
28const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1;
29
30struct FrameHeaderTestCase {
31  const char* frame_header;
32  size_t frame_header_length;
33  uint64 frame_length;
34  WebSocketError error_code;
35};
36
37const 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};
51const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests);
52
53TEST(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
79TEST(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
106TEST(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
173TEST(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
240TEST(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
307TEST(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
365TEST(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
420TEST(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
457TEST(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
518TEST(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
577