158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_frame_parser.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/port.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_frame.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHello[] = "Hello, world!";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kHelloLength = arraysize(kHello) - 1;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHelloFrame[] = "\x81\x0DHello, world!";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMaskedHelloFrame[] =
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\x81\x8D\xDE\xAD\xBE\xEF"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FrameHeaderTestCase {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* frame_header;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t frame_header_length;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 frame_length;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketError error_code;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FrameHeaderTestCase kFrameHeaderTests[] = {
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  { "\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure },
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  { "\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure },
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure },
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure },
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000),
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    kWebSocketNormalClosure },
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF),
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    kWebSocketNormalClosure },
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000),
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    kWebSocketErrorMessageTooBig },
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10,
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeNormalFrame) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketFrameParser parser;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<WebSocketFrameChunk> frames;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames));
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, frames.size());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketFrameChunk* frame = frames[0];
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(frame != NULL);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebSocketFrameHeader* header = frame->header.get();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(header != NULL);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kHelloLength, header->payload_length);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(frame->final_chunk);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data()));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeMaskedFrame) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketFrameParser parser;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<WebSocketFrameChunk> frames;
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      parser.Decode(kMaskedHelloFrame, kMaskedHelloFrameLength, &frames));
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, frames.size());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketFrameChunk* frame = frames[0];
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(frame != NULL);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebSocketFrameHeader* header = frame->header.get();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(header != NULL);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->masked);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kHelloLength, header->payload_length);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(frame->final_chunk);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data()));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeManyFrames) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Input {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_length;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_payload;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_payload_length;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const Input kInputs[] = {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Each |frame| data is split into two string literals because C++ lexers
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // consume unlimited number of hex characters in a hex character escape
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // { '\x5F', '\0' }).
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "First", 7, "First", 5 },
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x06" "Second", 8, "Second", 6 },
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "Third", 7, "Third", 5 },
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x06" "Fourth", 8, "Fourth", 6 },
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "Fifth", 7, "Fifth", 5 },
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "Sixth", 7, "Sixth", 5 },
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x07" "Seventh", 9, "Seventh", 7 },
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x06" "Eighth", 8, "Eighth", 6 },
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "Ninth", 7, "Ninth", 5 },
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x05" "Tenth", 7, "Tenth", 5 }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kNumInputs = ARRAYSIZE_UNSAFE(kInputs);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<char> input;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Concatenate all frames.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumInputs; ++i) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input.insert(input.end(),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 kInputs[i].frame,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 kInputs[i].frame + kInputs[i].frame_length);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketFrameParser parser;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<WebSocketFrameChunk> frames;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.Decode(&input.front(), input.size(), &frames));
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumInputs; ++i) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame = frames[i];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame != NULL);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame->final_chunk);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(kInputs[i].expected_payload_length,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<uint64>(frame->data->size()));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(std::equal(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kInputs[i].expected_payload,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kInputs[i].expected_payload + kInputs[i].expected_payload_length,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        frame->data->data()));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header = frame->header.get();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header != NULL);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kInputs[i].expected_payload_length, header->payload_length);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialFrame) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kFrameHeaderSize = 2;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> input1(kHelloFrame,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHelloFrame + kFrameHeaderSize + cutting_pos);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> input2(kHelloFrame + input1.size(),
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHelloFrame + kHelloFrameLength);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> expected1(kHello, kHello + cutting_pos);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames1;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames1.size());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames1.size() != 1u)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame1 = frames1[0];
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame1 != NULL);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame1)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(frame1->final_chunk);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected1.size() == 0) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(NULL, frame1->data.get());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(cutting_pos, static_cast<size_t>(frame1->data->size()));
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_TRUE(
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          std::equal(expected1.begin(), expected1.end(), frame1->data->data()));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header1 = frame1->header.get();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header1 != NULL);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header1)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header1->final);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved1);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved2);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved3);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->masked);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kHelloLength, header1->payload_length);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames2;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames2.size());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames2.size() != 1u)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame2 = frames2[0];
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame2 != NULL);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame2)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame2->final_chunk);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected2.size() == 0) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(NULL, frame2->data.get());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size()));
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_TRUE(
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          std::equal(expected2.begin(), expected2.end(), frame2->data->data()));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header2 = frame2->header.get();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header2 == NULL);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kFrameHeaderSize = 6;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> input1(
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        kMaskedHelloFrame, kMaskedHelloFrame + kFrameHeaderSize + cutting_pos);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> input2(kMaskedHelloFrame + input1.size(),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kMaskedHelloFrame + kMaskedHelloFrameLength);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> expected1(kHello, kHello + cutting_pos);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames1;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames1.size());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames1.size() != 1u)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame1 = frames1[0];
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame1 != NULL);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame1)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(frame1->final_chunk);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected1.size() == 0) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(NULL, frame1->data.get());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(expected1.size(), static_cast<uint64>(frame1->data->size()));
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_TRUE(
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          std::equal(expected1.begin(), expected1.end(), frame1->data->data()));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header1 = frame1->header.get();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header1 != NULL);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header1)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header1->final);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved1);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved2);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header1->reserved3);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header1->masked);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kHelloLength, header1->payload_length);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames2;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames2.size());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames2.size() != 1u)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame2 = frames2[0];
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame2 != NULL);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame2)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame2->final_chunk);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected2.size() == 0) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(NULL, frame2->data.get());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size()));
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_TRUE(
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          std::equal(expected2.begin(), expected2.end(), frame2->data->data()));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header2 = frame2->header.get();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header2 == NULL);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFrameHeaderTests; ++i) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header = kFrameHeaderTests[i].frame_header;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length = kFrameHeaderTests[i].frame_header_length;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 frame_length = kFrameHeaderTests[i].frame_length;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> input(frame_header, frame_header + frame_header_length);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Limit the payload size not to flood the console on failure.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const uint64 kMaxPayloadSize = 200;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 input_payload_size = std::min(frame_length, kMaxPayloadSize);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input.insert(input.end(), input_payload_size, 'a');
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames;
322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kFrameHeaderTests[i].error_code == kWebSocketNormalClosure,
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              parser.Decode(&input.front(), input.size(), &frames));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (kFrameHeaderTests[i].error_code != kWebSocketNormalClosure) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0u, frames.size());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(1u, frames.size());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames.size() != 1u)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame = frames[0];
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame != NULL);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frame_length == input_payload_size) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(frame->final_chunk);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(frame->final_chunk);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<char> expected_payload(input_payload_size, 'a');
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_payload.size() == 0) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(NULL, frame->data.get());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(expected_payload.size(),
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                static_cast<uint64>(frame->data->size()));
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_TRUE(std::equal(expected_payload.begin(),
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             expected_payload.end(),
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             frame->data->data()));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header = frame->header.get();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header != NULL);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(frame_length, header->payload_length);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialHeader) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFrameHeaderTests; ++i) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header = kFrameHeaderTests[i].frame_header;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length = kFrameHeaderTests[i].frame_header_length;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 frame_length = kFrameHeaderTests[i].frame_length;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Feed each byte to the parser to see if the parser behaves correctly
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when it receives partial frame header.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t last_byte_offset = frame_header_length - 1;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < frame_header_length; ++j) {
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      bool failed =
379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          kFrameHeaderTests[i].error_code != kWebSocketNormalClosure &&
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          j == last_byte_offset;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(!failed, parser.Decode(frame_header + j, 1, &frames));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (failed) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (kFrameHeaderTests[i].error_code == kWebSocketNormalClosure &&
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          j == last_byte_offset) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(1u, frames.size());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0u, frames.size());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames.size() != 1u)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame = frames[0];
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame != NULL);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frame_length == 0u) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(frame->final_chunk);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(frame->final_chunk);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, frame->data.get());
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header = frame->header.get();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header != NULL);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(frame_length, header->payload_length);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, InvalidLengthEncoding) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestCase {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const TestCase kTests[] = {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For frames with two-byte extended length field, the payload length
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should be 126 (0x7E) bytes or more.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x7E\x00\x00", 4 },
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x7E\x00\x7D", 4 },
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For frames with eight-byte extended length field, the payload length
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should be 0x10000 bytes or more.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10 },
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10 },
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumTests; ++i) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header = kTests[i].frame_header;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length = kTests[i].frame_header_length;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames;
444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(parser.Decode(frame_header, frame_header_length, &frames));
446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, frames.size());
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Once the parser has failed, it no longer accepts any input (even if
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the input is empty).
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(parser.Decode("", 0, &frames));
452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, frames.size());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, FrameTypes) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestCase {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameHeader::OpCode opcode;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const TestCase kTests[] = {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation },
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText },
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary },
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose },
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing },
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong },
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These are undefined opcodes, but the parser needs to be able to parse
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // them anyway.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x83\x00", 2, 0x3 },
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x84\x00", 2, 0x4 },
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x85\x00", 2, 0x5 },
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x86\x00", 2, 0x6 },
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x87\x00", 2, 0x7 },
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8B\x00", 2, 0xB },
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8C\x00", 2, 0xC },
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8D\x00", 2, 0xD },
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8E\x00", 2, 0xE },
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x8F\x00", 2, 0xF }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumTests; ++i) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header = kTests[i].frame_header;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length = kTests[i].frame_header_length;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameHeader::OpCode opcode = kTests[i].opcode;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames.size());
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames.size() != 1u)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame = frames[0];
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame != NULL);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame->final_chunk);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, frame->data.get());
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header = frame->header.get();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header != NULL);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header->final);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved1);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved2);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->reserved3);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(opcode, header->opcode);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, header->payload_length);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestCase {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool final;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved1;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved2;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved3;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const TestCase kTests[] = {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x81\x00", 2, true, false, false, false },
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x01\x00", 2, false, false, false, false },
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\xC1\x00", 2, true, true, false, false },
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\xA1\x00", 2, true, false, true, false },
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x91\x00", 2, true, false, false, true },
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\x71\x00", 2, false, true, true, true },
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "\xF1\x00", 2, true, true, true, true }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumTests; ++i) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* frame_header = kTests[i].frame_header;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t frame_header_length = kTests[i].frame_header_length;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool final = kTests[i].final;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved1 = kTests[i].reserved1;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved2 = kTests[i].reserved2;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool reserved3 = kTests[i].reserved3;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameParser parser;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedVector<WebSocketFrameChunk> frames;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(1u, frames.size());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames.size() != 1u)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebSocketFrameChunk* frame = frames[0];
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame != NULL);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!frame)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(frame->final_chunk);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, frame->data.get());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebSocketFrameHeader* header = frame->header.get();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(header != NULL);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(final, header->final);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(reserved1, header->reserved1);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(reserved2, header->reserved2);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(reserved3, header->reserved3);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(header->masked);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, header->payload_length);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // Unnamed namespace
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
577