1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_reliable_server_stream.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_spdy_compressor.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_utils.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/flip_server/epoll_server.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_in_memory_cache.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_spdy_server_stream.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/spdy_utils.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/test_tools/quic_test_utils.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StringPiece;
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::tools::test::MockConnection;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::test::MockSession;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::string;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::_;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::AnyNumber;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::Invoke;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::InvokeArgument;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::InSequence;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::Return;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::StrEq;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::StrictMock;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::WithArgs;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicReliableServerStreamPeer {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static BalsaHeaders* GetMutableHeaders(
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      QuicReliableServerStream* stream) {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return &(stream->headers_);
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicReliableServerStreamTest : public ::testing::Test {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicReliableServerStreamTest()
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : session_(new MockConnection(1, IPEndPoint(), 0, &eps_, true), true),
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        body_("hello world") {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BalsaHeaders request_headers;
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    request_headers.SetRequestFirstlineFromStringPieces(
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "POST", "https://www.google.com/", "HTTP/1.1");
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    request_headers.ReplaceOrAppendHeader("content-length", "11");
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers);
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_.reset(new QuicSpdyServerStream(3, &session_));
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicConsumedData ValidateHeaders(StringPiece headers) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    headers_string_ = SpdyUtils::SerializeResponseHeaders(
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_headers_);
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    QuicSpdyDecompressor decompressor;
65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    TestDecompressorVisitor visitor;
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // First the header id, then the compressed data.
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(1, headers[0]);
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(0, headers[1]);
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(0, headers[2]);
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(0, headers[3]);
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(static_cast<size_t>(headers.length() - 4),
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              decompressor.DecompressData(headers.substr(4), &visitor));
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(headers_string_, visitor.data());
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return QuicConsumedData(headers.size(), false);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static void SetUpTestCase() {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicInMemoryCache::GetInstance()->ResetForTests();
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() {
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BalsaHeaders request_headers, response_headers;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringPiece body("Yum");
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    request_headers.SetRequestFirstlineFromStringPieces(
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "GET",
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "https://www.google.com/foo",
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "HTTP/1.1");
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_headers.SetRequestFirstlineFromStringPieces("HTTP/1.1",
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                         "200",
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                         "OK");
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_headers.AppendHeader("content-length",
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  base::IntToString(body.length()));
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check if response already exists and matches.
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const QuicInMemoryCache::Response* cached_response =
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cache->GetResponse(request_headers);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (cached_response != NULL) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      string cached_response_headers_str, response_headers_str;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cached_response->headers().DumpToString(&cached_response_headers_str);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      response_headers.DumpToString(&response_headers_str);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_EQ(cached_response_headers_str, response_headers_str);
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_EQ(cached_response->body(), body);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cache->AddResponse(request_headers, response_headers, body);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BalsaHeaders response_headers_;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EpollServer eps_;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StrictMock<MockSession> session_;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<QuicReliableServerStream> stream_;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string headers_string_;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string body_;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicConsumedData ConsumeAllData(QuicStreamId id, StringPiece data,
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                QuicStreamOffset offset, bool fin) {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return QuicConsumedData(data.size(), fin);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicReliableServerStreamTest, TestFraming) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, _, _, _)).Times(AnyNumber()).
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillRepeatedly(Invoke(ConsumeAllData));
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      headers_string_.c_str(), headers_string_.size()));
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size()));
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(11u, stream_->headers().content_length());
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("POST", stream_->headers().request_method());
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(body_, stream_->body());
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicReliableServerStreamTest, TestFramingOnePacket) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, _, _, _)).Times(AnyNumber()).
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillRepeatedly(Invoke(ConsumeAllData));
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string message = headers_string_ + body_;
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(message.size(), stream_->ProcessData(
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      message.c_str(), message.size()));
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(11u, stream_->headers().content_length());
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("https://www.google.com/",
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            stream_->headers().request_uri());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("POST", stream_->headers().request_method());
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(body_, stream_->body());
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicReliableServerStreamTest, TestFramingExtraData) {
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string large_body = "hello world!!!!!!";
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We'll automatically write out an error (headers + body)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, _, _, _)).Times(2).
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillRepeatedly(Invoke(ConsumeAllData));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      headers_string_.c_str(), headers_string_.size()));
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Content length is still 11.  This will register as an error and we won't
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // accept the bytes.
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_->ProcessData(large_body.c_str(), large_body.size());
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_->TerminateFromPeer(true);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(11u, stream_->headers().content_length());
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("POST", stream_->headers().request_method());
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicReliableServerStreamTest, TestSendResponse) {
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BalsaHeaders* request_headers =
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      QuicReliableServerStreamPeer::GetMutableHeaders(stream_.get());
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  request_headers->SetRequestFirstlineFromStringPieces(
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "GET",
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "https://www.google.com/foo",
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "HTTP/1.1");
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_headers_.SetResponseFirstlineFromStringPieces(
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "HTTP/1.1", "200", "OK");
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_headers_.ReplaceOrAppendHeader("content-length", "3");
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, _, _, _)).Times(1)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(WithArgs<1>(Invoke(
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this, &QuicReliableServerStreamTest::ValidateHeaders)));
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringPiece kBody = "Yum";
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, kBody, _, _)).Times(1).
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillOnce(Return(QuicConsumedData(3, true)));
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_->SendResponse();
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(stream_->read_side_closed());
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(stream_->write_side_closed());
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicReliableServerStreamTest, TestSendErrorResponse) {
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_headers_.SetResponseFirstlineFromStringPieces(
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "HTTP/1.1", "500", "Server Error");
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_headers_.ReplaceOrAppendHeader("content-length", "3");
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, _, _, _)).Times(1)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(WithArgs<1>(Invoke(
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this, &QuicReliableServerStreamTest::ValidateHeaders)));
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringPiece kBody = "bad";
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(session_, WriteData(_, kBody, _, _)).Times(1).
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillOnce(Return(QuicConsumedData(3, true)));
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_->SendErrorResponse();
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(stream_->read_side_closed());
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(stream_->write_side_closed());
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace test
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
220