1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <iostream> 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_framer.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_protocol.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_frame_builder.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy { 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace test { 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string HexDumpWithMarks(const unsigned char* data, int length, 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool* marks, int mark_length) { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char kHexChars[] = "0123456789ABCDEF"; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kColumns = 4; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string hex; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (const unsigned char* row = data; length > 0; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row += kColumns, length -= kColumns) { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (const unsigned char *p = row; p < row + 4; ++p) { 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (p < row + length) { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool mark = 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (marks && (p - data) < mark_length && marks[p - data]); 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += mark ? '*' : ' '; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += kHexChars[(*p & 0xf0) >> 4]; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += kHexChars[*p & 0x0f]; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += mark ? '*' : ' '; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += " "; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex = hex + " "; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p) 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.'; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hex = hex + '\n'; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return hex; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CompareCharArraysWithHexError( 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& description, 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char* actual, 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int actual_len, 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char* expected, 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int expected_len) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int min_len = actual_len > expected_len ? expected_len : actual_len; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int max_len = actual_len > expected_len ? actual_len : expected_len; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_array<bool> marks(new bool[max_len]); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool identical = (actual_len == expected_len); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < min_len; ++i) { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (actual[i] != expected[i]) { 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch marks[i] = true; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch identical = false; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch marks[i] = false; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = min_len; i < max_len; ++i) { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch marks[i] = true; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (identical) return; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ADD_FAILURE() 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "Description:\n" 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << description 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "\n\nExpected:\n" 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << HexDumpWithMarks(expected, expected_len, marks.get(), max_len) 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "\nActual:\n" 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << HexDumpWithMarks(actual, actual_len, marks.get(), max_len); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FramerSetEnableCompressionHelper(SpdyFramer* framer, bool compress) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer->set_enable_compression(compress); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TestSpdyVisitor : public SpdyFramerVisitorInterface { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestSpdyVisitor() 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : error_count_(0), 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syn_frame_count_(0), 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syn_reply_frame_count_(0), 89201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers_frame_count_(0), 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_bytes_(0), 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fin_frame_count_(0), 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fin_flag_count_(0), 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch zero_length_data_frame_count_(0) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnError(SpdyFramer* f) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_count_++; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnStreamFrameData(SpdyStreamId stream_id, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t len) { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (len == 0) 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++zero_length_data_frame_count_; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_bytes_ += len; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::cerr << "OnStreamFrameData(" << stream_id << ", \""; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (len > 0) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0 ; i < len; ++i) { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::cerr << "\", " << len << ")\n"; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnControl(const SpdyControlFrame* frame) { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool parsed_headers = false; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (frame->type()) { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SYN_STREAM: 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parsed_headers = framer_.ParseHeaderBlock(frame, &headers); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(parsed_headers); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syn_frame_count_++; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SYN_REPLY: 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parsed_headers = framer_.ParseHeaderBlock(frame, &headers); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(parsed_headers); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syn_reply_frame_count_++; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case RST_STREAM: 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fin_frame_count_++; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case HEADERS: 134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch parsed_headers = framer_.ParseHeaderBlock(frame, &headers); 135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(parsed_headers); 136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers_frame_count_++; 137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch break; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false); // Error! 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame->flags() & CONTROL_FLAG_FIN) 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++fin_flag_count_; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool OnControlFrameHeaderData(SpdyStreamId stream_id, 1462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* header_data, 1472c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len) { 1482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(false); 1492c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 1502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun void OnDataFrameHeader(const SpdyDataFrame* frame) { 1532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(false); 1542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Convenience function which runs a framer simulation with particular input. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SimulateInFramer(const unsigned char* input, size_t size) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_.set_enable_compression(false); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_.set_visitor(this); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t input_remaining = size; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* input_ptr = reinterpret_cast<const char*>(input); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (input_remaining > 0 && 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To make the tests more interesting, we feed random (amd small) chunks 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // into the framer. This simulates getting strange-sized reads from 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the socket. 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kMaxReadSize = 32; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t bytes_read = 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (rand() % std::min(input_remaining, kMaxReadSize)) + 1; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch input_remaining -= bytes_processed; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch input_ptr += bytes_processed; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (framer_.state() == SpdyFramer::SPDY_DONE) 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_.Reset(); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer_; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Counters from the visitor callbacks. 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int error_count_; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int syn_frame_count_; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int syn_reply_frame_count_; 183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int headers_frame_count_; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int data_bytes_; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int fin_frame_count_; // The count of RST_STREAM type frames received. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int fin_flag_count_; // The count of frames with the FIN flag set. 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int zero_length_data_frame_count_; // The count of zero-length data frames. 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace test 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace spdy 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyControlFlags; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyControlFrame; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyDataFrame; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFrame; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFrameBuilder; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFramer; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyHeaderBlock; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdySynStreamControlFrame; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::kControlFlagMask; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::CONTROL_FLAG_NONE; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::DATA_FLAG_COMPRESSED; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::DATA_FLAG_FIN; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SYN_STREAM; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::test::CompareCharArraysWithHexError; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::test::FramerSetEnableCompressionHelper; 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::test::TestSpdyVisitor; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy { 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFramerTest : public PlatformTest { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void TearDown() {} 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CompareFrame(const std::string& description, 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdyFrame& actual_frame, 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char* expected, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int expected_len) { 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char* actual = 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const unsigned char*>(actual_frame.data()); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int actual_len = actual_frame.length() + SpdyFrame::size(); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareCharArraysWithHexError( 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch description, actual, actual_len, expected, expected_len); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we can encode and decode a SpdyHeaderBlock. 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, HeaderBlock) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["alpha"] = "beta"; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["gamma"] = "charlie"; 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Encode the header block into a SynStream frame. 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> frame( 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, &headers)); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(frame.get() != NULL); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock new_headers; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(framer.ParseHeaderBlock(frame.get(), &new_headers)); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(headers.size(), new_headers.size()); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(headers["alpha"], new_headers["alpha"]); 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(headers["gamma"], new_headers["gamma"]); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, OutOfOrderHeaders) { 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(kControlFlagMask | 1); 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(SYN_STREAM); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // Placeholder for the length. 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(3); // stream_id 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // associated stream id 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(0); // Priority. 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(2); // Number of headers. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator it; 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("gamma"); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("gamma"); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("alpha"); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("alpha"); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // write the length 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::size()); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock new_headers; 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> control_frame(frame.take()); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(framer.ParseHeaderBlock(control_frame.get(), &new_headers)); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, WrongNumberOfHeaders) { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame1; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame2; 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a frame with smaller number of actual headers 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt16(kControlFlagMask | 1); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt16(SYN_STREAM); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt32(0); // Placeholder for the length. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt32(3); // stream_id 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt16(0); // Priority. 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt16(1); // Wrong number of headers (underflow) 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteString("gamma"); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteString("gamma"); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteString("alpha"); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteString("alpha"); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // write the length 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1.WriteUInt32ToOffset(4, frame1.length() - SpdyFrame::size()); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a frame with larger number of actual headers 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt16(kControlFlagMask | 1); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt16(SYN_STREAM); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt32(0); // Placeholder for the length. 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt32(3); // stream_id 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt16(0); // Priority. 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt16(100); // Wrong number of headers (overflow) 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteString("gamma"); 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteString("gamma"); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteString("alpha"); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteString("alpha"); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // write the length 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2.WriteUInt32ToOffset(4, frame2.length() - SpdyFrame::size()); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock new_headers; 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> syn_frame1(frame1.take()); 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> syn_frame2(frame2.take()); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(syn_frame1.get(), &new_headers)); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(syn_frame2.get(), &new_headers)); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, DuplicateHeader) { 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(kControlFlagMask | 1); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(SYN_STREAM); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // Placeholder for the length. 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(3); // stream_id 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // associated stream id 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(0); // Priority. 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(2); // Number of headers. 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator it; 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("name"); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("value1"); 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("name"); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("value2"); 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // write the length 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::size()); 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock new_headers; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> control_frame(frame.take()); 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This should fail because duplicate headers are verboten by the spec. 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(control_frame.get(), &new_headers)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, MultiValueHeader) { 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(kControlFlagMask | 1); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(SYN_STREAM); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // Placeholder for the length. 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(3); // stream_id 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // associated stream id 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(0); // Priority. 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(1); // Number of headers. 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator it; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString("name"); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string value("value1\0value2"); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteString(value); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // write the length 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::size()); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock new_headers; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> control_frame(frame.take()); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(framer.ParseHeaderBlock(control_frame.get(), &new_headers)); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(new_headers.find("name") != new_headers.end()); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(value, new_headers.find("name")->second); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, ZeroLengthHeader) { 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock header1; 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock header2; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock header3; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header1[""] = "value2"; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header2["name3"] = ""; 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header3[""] = ""; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock parsed_headers; 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> frame1( 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, &header1)); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(frame1.get() != NULL); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(frame1.get(), &parsed_headers)); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> frame2( 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, &header2)); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(frame2.get() != NULL); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(frame2.get(), &parsed_headers)); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> frame3( 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, &header3)); 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(frame3.get() != NULL); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(framer.ParseHeaderBlock(frame3.get(), &parsed_headers)); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, BasicCompression) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["server"] = "SpdyServer 1.0"; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["date"] = "Mon 12 Jan 2009 12:12:12 PST"; 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["status"] = "200"; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["version"] = "HTTP/1.1"; 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["content-type"] = "text/html"; 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["content-length"] = "12"; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, true); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &headers)); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame2(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true, 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &headers)); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Expect the second frame to be more compact than the first. 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_LE(frame2->length(), frame1->length()); 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Decompress the first frame 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame3(framer.DecompressFrame(*frame1.get())); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Decompress the second frame 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame4(framer.DecompressFrame(*frame2.get())); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Expect frames 3 & 4 to be the same. 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcmp(frame3->data(), frame4->data(), 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame::size() + frame3->length())); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, DecompressUncompressedFrame) { 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["server"] = "SpdyServer 1.0"; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["date"] = "Mon 12 Jan 2009 12:12:12 PST"; 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["status"] = "200"; 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["version"] = "HTTP/1.1"; 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["content-type"] = "text/html"; 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["content-length"] = "12"; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, true); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdySynStreamControlFrame> 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false, 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &headers)); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Decompress the frame 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame2(framer.DecompressFrame(*frame1.get())); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(NULL, frame2.get()); 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, Basic) { 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char input[] = { 4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, // SYN Stream #1 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x14, 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'h', 'h', 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'v', 'v', 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x80, 0x02, 0x00, 0x08, // HEADERS on Stream #1 466201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x18, 467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x01, 468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x02, 469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x02, 'h', '2', 470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x02, 'v', '2', 471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x02, 'h', '3', 472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x02, 'v', '3', 473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x0c, 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, // SYN Stream #3 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x0c, 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x04, 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #1 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #3 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestSpdyVisitor visitor; 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor.SimulateInFramer(input, sizeof(input)); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.error_count_); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(2, visitor.syn_frame_count_); 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.syn_reply_frame_count_); 515201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_EQ(1, visitor.headers_frame_count_); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(24, visitor.data_bytes_); 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(2, visitor.fin_frame_count_); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_flag_count_); 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.zero_length_data_frame_count_); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the FIN flag on a data frame signifies EOF. 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, FinOnDataFrame) { 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char input[] = { 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, // SYN Stream #1 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x14, 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'h', 'h', 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'v', 'v', 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x10, 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'a', 'a', 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'b', 'b', 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x0c, 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x04, 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xde, 0xad, 0xbe, 0xef, 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestSpdyVisitor visitor; 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor.SimulateInFramer(input, sizeof(input)); 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.error_count_); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.syn_frame_count_); 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.syn_reply_frame_count_); 557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_EQ(0, visitor.headers_frame_count_); 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(16, visitor.data_bytes_); 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_frame_count_); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_flag_count_); 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the FIN flag on a SYN reply frame signifies EOF. 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, FinOnSynReplyFrame) { 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char input[] = { 5673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, // SYN Stream #1 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x14, 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'h', 'h', 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'v', 'v', 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x10, 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'a', 'a', 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x02, 'b', 'b', 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestSpdyVisitor visitor; 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor.SimulateInFramer(input, sizeof(input)); 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.error_count_); 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.syn_frame_count_); 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.syn_reply_frame_count_); 589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_EQ(0, visitor.headers_frame_count_); 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.data_bytes_); 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_frame_count_); 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.fin_flag_count_); 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Basic compression & decompression 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, DataCompression) { 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer send_framer; 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer recv_framer; 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&send_framer, true); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&recv_framer, true); 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Mix up some SYNs and DATA frames since they use different compressors. 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kHeader1[] = "header1"; 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kHeader2[] = "header2"; 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kHeader3[] = "header3"; 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kValue1[] = "value1"; 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kValue2[] = "value2"; 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kValue3[] = "value3"; 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SYN_STREAM #1 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock block; 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch block[kHeader1] = kValue1; 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch block[kHeader2] = kValue2; 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFlags flags(CONTROL_FLAG_NONE); 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<spdy::SpdyFrame> syn_frame_1( 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_framer.CreateSynStream(1, 0, 0, flags, true, &block)); 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(syn_frame_1.get() != NULL); 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DATA #1 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char bytes[] = "this is a test test test test test!"; 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> data_frame_1( 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_framer.CreateDataFrame(1, bytes, arraysize(bytes), 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DATA_FLAG_COMPRESSED)); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(data_frame_1.get() != NULL); 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SYN_STREAM #2 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch block[kHeader3] = kValue3; 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> syn_frame_2( 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_framer.CreateSynStream(3, 0, 0, flags, true, &block)); 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(syn_frame_2.get() != NULL); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DATA #2 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> data_frame_2( 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_framer.CreateDataFrame(3, bytes, arraysize(bytes), 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DATA_FLAG_COMPRESSED)); 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(data_frame_2.get() != NULL); 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now start decompressing 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> decompressed; 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFrame* control_frame; 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* data_frame; 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock decompressed_headers; 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed.reset(recv_framer.DuplicateFrame(*syn_frame_1.get())); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed.get() != NULL); 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed->is_control_frame()); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch control_frame = reinterpret_cast<SpdyControlFrame*>(decompressed.get()); 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(SYN_STREAM, control_frame->type()); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(recv_framer.ParseHeaderBlock( 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch control_frame, &decompressed_headers)); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(2u, decompressed_headers.size()); 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(SYN_STREAM, control_frame->type()); 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(kValue1, decompressed_headers[kHeader1]); 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(kValue2, decompressed_headers[kHeader2]); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed.reset(recv_framer.DecompressFrame(*data_frame_1.get())); 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed.get() != NULL); 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(decompressed->is_control_frame()); 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_frame = reinterpret_cast<SpdyDataFrame*>(decompressed.get()); 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(arraysize(bytes), data_frame->length()); 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, memcmp(data_frame->payload(), bytes, data_frame->length())); 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed.reset(recv_framer.DuplicateFrame(*syn_frame_2.get())); 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed.get() != NULL); 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed->is_control_frame()); 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch control_frame = reinterpret_cast<SpdyControlFrame*>(decompressed.get()); 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(control_frame->type(), SYN_STREAM); 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed_headers.clear(); 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(recv_framer.ParseHeaderBlock( 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch control_frame, &decompressed_headers)); 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(3u, decompressed_headers.size()); 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(SYN_STREAM, control_frame->type()); 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(kValue1, decompressed_headers[kHeader1]); 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(kValue2, decompressed_headers[kHeader2]); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(kValue3, decompressed_headers[kHeader3]); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed.reset(recv_framer.DecompressFrame(*data_frame_2.get())); 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(decompressed.get() != NULL); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(decompressed->is_control_frame()); 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_frame = reinterpret_cast<SpdyDataFrame*>(decompressed.get()); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(arraysize(bytes), data_frame->length()); 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, memcmp(data_frame->payload(), bytes, data_frame->length())); 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We didn't close these streams, so the compressors should be active. 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(2, send_framer.num_stream_compressors()); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, send_framer.num_stream_decompressors()); 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, recv_framer.num_stream_compressors()); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(2, recv_framer.num_stream_decompressors()); 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify we don't leak when we leave streams unclosed 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, UnclosedStreamDataCompressors) { 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer send_framer; 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&send_framer, false); 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kHeader1[] = "header1"; 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kHeader2[] = "header2"; 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kValue1[] = "value1"; 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kValue2[] = "value2"; 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock block; 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch block[kHeader1] = kValue1; 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch block[kHeader2] = kValue2; 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFlags flags(CONTROL_FLAG_NONE); 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<spdy::SpdyFrame> syn_frame( 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch send_framer.CreateSynStream(1, 0, 0, flags, true, &block)); 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(syn_frame.get() != NULL); 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char bytes[] = "this is a test test test test test!"; 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> send_frame( 714201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch send_framer.CreateDataFrame(1, 715201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bytes, 716201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch arraysize(bytes), 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DATA_FLAG_FIN)); 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(send_frame.get() != NULL); 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Run the inputs through the framer. 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestSpdyVisitor visitor; 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char* data; 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data = reinterpret_cast<const unsigned char*>(syn_frame->data()); 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor.SimulateInFramer(data, syn_frame->length() + SpdyFrame::size()); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data = reinterpret_cast<const unsigned char*>(send_frame->data()); 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor.SimulateInFramer(data, send_frame->length() + SpdyFrame::size()); 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.error_count_); 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.syn_frame_count_); 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.syn_reply_frame_count_); 731201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_EQ(0, visitor.headers_frame_count_); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_)); 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_frame_count_); 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.fin_flag_count_); 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, visitor.zero_length_data_frame_count_); 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We closed the streams, so all compressors should be down. 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.framer_.num_stream_compressors()); 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, visitor.framer_.num_stream_decompressors()); 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, send_framer.num_stream_compressors()); 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, send_framer.num_stream_decompressors()); 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateDataFrame) { 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "'hello' data frame, no FIN"; 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x05, 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'h', 'e', 'l', 'l', 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o' 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, "hello", 5, DATA_FLAG_NONE)); 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "Data frame with negative data byte, no FIN"; 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, "\xff", 1, DATA_FLAG_NONE)); 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "'hello' data frame, with FIN"; 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x05, 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'h', 'e', 'l', 'l', 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o' 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, "hello", 5, DATA_FLAG_FIN)); 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "Empty data frame"; 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, "", 0, DATA_FLAG_NONE)); 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "Data frame with max stream ID"; 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x05, 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'h', 'e', 'l', 'l', 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o' 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame( 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7fffffff, "hello", 5, DATA_FLAG_FIN)); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateSynStreamUncompressed) { 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN"; 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 8223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x20, 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xC0, 0x00, 0x00, 0x02, 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r', 0x00, 0x03, 'f', 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o', 'o', 0x00, 0x03, 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x03, 'b', 'a', 'r' 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynStream( 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, 0, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE, 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch false, &headers)); 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SYN_STREAM frame with a 0-length header name, highest pri, FIN, " 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "max stream ID"; 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers[""] = "foo"; 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 8493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x1D, 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x03, 'f', 'o', 'o', 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r' 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynStream( 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7fffffff, 0x7fffffff, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN, 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch false, &headers)); 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SYN_STREAM frame with a 0-length header val, highest pri, FIN, " 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "max stream ID"; 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = ""; 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 8763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x1D, 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r', 0x00, 0x03, 'f', 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o', 'o', 0x00, 0x03, 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynStream( 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7fffffff, 0x7fffffff, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN, 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch false, &headers)); 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateSynStreamCompressed) { 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, true); 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SYN_STREAM frame, lowest pri, no FIN"; 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 9073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x01, 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x25, 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xC0, 0x00, 0x38, 0xea, 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xdf, 0xa2, 0x51, 0xb2, 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x62, 0x60, 0x62, 0x60, 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x4e, 0x4a, 0x2c, 0x62, 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x60, 0x4e, 0xcb, 0xcf, 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x87, 0x12, 0x40, 0x2e, 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0xff, 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynStream( 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, 0, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE, 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true, &headers)); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateSynReplyUncompressed) { 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, false); 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "SYN_REPLY frame, no FIN"; 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x1C, 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r', 0x00, 0x03, 'f', 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o', 'o', 0x00, 0x03, 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x03, 'b', 'a', 'r' 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, CONTROL_FLAG_NONE, false, &headers)); 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SYN_REPLY frame with a 0-length header name, FIN, max stream ID"; 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers[""] = "foo"; 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 9633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x19, 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x03, 'f', 'o', 'o', 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r' 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SYN_REPLY frame with a 0-length header val, FIN, max stream ID"; 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = ""; 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 9873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x19, 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x03, 'b', 'a', 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'r', 0x00, 0x03, 'f', 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'o', 'o', 0x00, 0x03, 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'f', 'o', 'o', 0x00, 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateSynReplyCompressed) { 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FramerSetEnableCompressionHelper(&framer, true); 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "SYN_REPLY frame, no FIN"; 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["bar"] = "foo"; 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers["foo"] = "bar"; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x02, 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x21, 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x38, 0xea, 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xdf, 0xa2, 0x51, 0xb2, 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x62, 0x60, 0x62, 0x60, 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x4e, 0x4a, 0x2c, 0x62, 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x60, 0x4e, 0xcb, 0xcf, 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x87, 0x12, 0x40, 0x2e, 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0xff, 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1, CONTROL_FLAG_NONE, true, &headers)); 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateRstStream) { 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "RST_STREAM frame"; 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 10393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x03, 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(1, PROTOCOL_ERROR)); 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "RST_STREAM frame with max stream ID"; 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 10513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x03, 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF, 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROTOCOL_ERROR)); 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "RST_STREAM frame with max status code"; 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x03, 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x06, 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF, 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INTERNAL_ERROR)); 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateSettings) { 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "Basic SETTINGS frame"; 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySettings settings; 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x00000000, 0x00000000)); 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0xffffffff, 0x00000001)); 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0xff000001, 0x00000002)); 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Duplicates allowed 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x01000002, 0x00000003)); 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x01000002, 0x00000003)); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x01000003, 0x000000ff)); 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x01000004, 0xff000001)); 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch settings.push_back(SpdySetting(0x01000004, 0xffffffff)); 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 10953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x04, 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x44, 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff, 0xff, 0xff, 0xff, 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff, 0x00, 0x00, 0x01, 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x02, 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x02, 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x02, 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x03, 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x03, 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0xff, 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x04, 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff, 0x00, 0x00, 0x01, 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x01, 0x00, 0x00, 0x04, 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0xff, 0xff, 0xff, 0xff, 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "Empty SETTINGS frame"; 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySettings settings; 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 11253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x04, 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x04, 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings)); 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateNopFrame) { 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "NOOP frame"; 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 11403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x05, 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateNopFrame()); 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateGoAway) { 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "GOAWAY frame"; 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 11543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x07, 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x04, 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x00, 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0)); 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "GOAWAY frame with max stream ID"; 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 11653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x07, 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x04, 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF)); 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_F(SpdyFramerTest, CreateHeadersUncompressed) { 1175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFramer framer; 1176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FramerSetEnableCompressionHelper(&framer, false); 1177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch { 1179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const char kDescription[] = "HEADERS frame, no FIN"; 1180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["bar"] = "foo"; 1183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["foo"] = "bar"; 1184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const unsigned char kFrameData[] = { 1186201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x80, 0x02, 0x00, 0x08, 1187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x1C, 1188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x01, 1189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x02, 1190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x03, 'b', 'a', 1191201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'r', 0x00, 0x03, 'f', 1192201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'o', 'o', 0x00, 0x03, 1193201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'f', 'o', 'o', 0x00, 1194201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x03, 'b', 'a', 'r' 1195201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch }; 1196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 1197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1, CONTROL_FLAG_NONE, false, &headers)); 1198201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1199201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch { 1202201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const char kDescription[] = 1203201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch "HEADERS frame with a 0-length header name, FIN, max stream ID"; 1204201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1205201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers[""] = "foo"; 1207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["foo"] = "bar"; 1208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const unsigned char kFrameData[] = { 1210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x80, 0x02, 0x00, 0x08, 1211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x01, 0x00, 0x00, 0x19, 1212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x7f, 0xff, 0xff, 0xff, 1213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x02, 1214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x03, 1215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'f', 'o', 'o', 0x00, 1216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x03, 'f', 'o', 'o', 1217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x03, 'b', 'a', 1218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'r' 1219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch }; 1220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 1221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 1222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch { 1226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const char kDescription[] = 1227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch "HEADERS frame with a 0-length header val, FIN, max stream ID"; 1228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["bar"] = "foo"; 1231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["foo"] = ""; 1232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const unsigned char kFrameData[] = { 1234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x80, 0x02, 0x00, 0x08, 1235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x01, 0x00, 0x00, 0x19, 1236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x7f, 0xff, 0xff, 0xff, 1237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x02, 1238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x03, 'b', 'a', 1239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'r', 0x00, 0x03, 'f', 1240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'o', 'o', 0x00, 0x03, 1241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'f', 'o', 'o', 0x00, 1242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00 1243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch }; 1244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 1245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x7fffffff, CONTROL_FLAG_FIN, false, &headers)); 1246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 1249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_F(SpdyFramerTest, CreateHeadersCompressed) { 1251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFramer framer; 1252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FramerSetEnableCompressionHelper(&framer, true); 1253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch { 1255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const char kDescription[] = "HEADERS frame, no FIN"; 1256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["bar"] = "foo"; 1259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["foo"] = "bar"; 1260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const unsigned char kFrameData[] = { 1262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x80, 0x02, 0x00, 0x08, 1263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x21, 1264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0x01, 1265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x38, 0xea, 1266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0xdf, 0xa2, 0x51, 0xb2, 1267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x62, 0x60, 0x62, 0x60, 1268201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x4e, 0x4a, 0x2c, 0x62, 1269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x60, 0x4e, 0xcb, 0xcf, 1270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x87, 0x12, 0x40, 0x2e, 1271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0x00, 0x00, 0x00, 0xff, 1272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0xff 1273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch }; 1274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 1275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1, CONTROL_FLAG_NONE, true, &headers)); 1276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 1279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyFramerTest, CreateWindowUpdate) { 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer framer; 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "WINDOW_UPDATE frame"; 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 12863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x09, 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 1)); 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "WINDOW_UPDATE frame with max stream ID"; 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 12983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x09, 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1)); 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kDescription[] = "WINDOW_UPDATE frame with max window delta"; 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const unsigned char kFrameData[] = { 13103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0x80, 0x02, 0x00, 0x09, 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x08, 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x00, 0x00, 0x00, 0x01, 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0x7f, 0xff, 0xff, 0xff, 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF)); 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// This test case reproduces conditions that caused ExpandControlFrameBuffer to 1321201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// fail to expand the buffer control frame buffer when it should have, allowing 1322201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// the framer to overrun the buffer, and smash other heap contents. This test 1323201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// relies on the debug version of the heap manager, which checks for buffer 1324201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// overrun errors during delete processing. Regression test for b/2974814. 1325201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_F(SpdyFramerTest, ExpandBuffer_HeapSmash) { 1326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Sweep through the area of problematic values, to make sure we always cover 1327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // the danger zone, even if it moves around at bit due to SPDY changes. 1328201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (uint16 val2_len = SpdyFramer::kControlFrameBufferInitialSize - 50; 1329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch val2_len < SpdyFramer::kControlFrameBufferInitialSize; 1330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch val2_len++) { 1331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string val2 = std::string(val2_len, 'a'); 1332201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["bar"] = "foo"; 1334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["foo"] = "baz"; 1335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers["grue"] = val2.c_str(); 1336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFramer framer; 1337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdySynStreamControlFrame> template_frame( 1338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch framer.CreateSynStream(1, // stream_id 1339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0, // associated_stream_id 1340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1, // priority 1341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CONTROL_FLAG_NONE, 1342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch false, // compress 1343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &headers)); 1344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_TRUE(template_frame.get() != NULL); 1345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TestSpdyVisitor visitor; 1346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch visitor.SimulateInFramer( 1347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch reinterpret_cast<unsigned char*>(template_frame.get()->data()), 1348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch template_frame.get()->length() + SpdyControlFrame::size()); 1349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch EXPECT_EQ(1, visitor.syn_frame_count_); 1350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 1352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1353201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::string RandomString(int length) { 1354201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string rv; 1355201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (int index = 0; index < length; index++) 1356201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch rv += static_cast<char>('a' + (rand() % 26)); 1357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return rv; 1358201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 1359201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1360201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Stress that we can handle a really large header block compression and 1361201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// decompression. 1362201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_F(SpdyFramerTest, HugeHeaderBlock) { 1363201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Loop targetting various sizes which will potentially jam up the 1364201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // frame compressor/decompressor. 1365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFramer compress_framer; 1366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFramer decompress_framer; 1367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (size_t target_size = 1024; 1368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch target_size < SpdyFramer::kControlFrameBufferInitialSize; 1369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch target_size += 1024) { 1370201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock headers; 1371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (size_t index = 0; index < target_size; ++index) { 1372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string name = RandomString(4); 1373201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string value = RandomString(8); 1374201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch headers[name] = value; 1375201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1376201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1377201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Encode the header block into a SynStream frame. 1378201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<SpdySynStreamControlFrame> frame( 1379201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch compress_framer.CreateSynStream(1, 1380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 0, 1381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1, 1382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CONTROL_FLAG_NONE, 1383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch true, 1384201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &headers)); 1385201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The point of this test is to exercise the limits. So, it is ok if the 1386201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // frame was too large to encode, or if the decompress fails. We just want 1387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // to make sure we don't crash. 1388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (frame.get() != NULL) { 1389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Now that same header block should decompress just fine. 1390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeaderBlock new_headers; 1391201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch decompress_framer.ParseHeaderBlock(frame.get(), &new_headers); 1392201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1394201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 1395201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 1397