15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/spdy/hpack_huffman_aggregator.h"
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/metrics/histogram.h"
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/metrics/statistics_recorder.h"
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/load_flags.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/http/http_request_headers.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/http/http_request_info.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/http/http_response_headers.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gmock/include/gmock/gmock.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gtest/include/gtest/gtest.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace net {
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::testing::Each;
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::testing::ElementsAre;
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::testing::Eq;
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::testing::Pair;
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kHistogramName[] = "Net.SpdyHpackEncodedCharacterFrequency";
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace test {
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass HpackHuffmanAggregatorPeer {
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  explicit HpackHuffmanAggregatorPeer(HpackHuffmanAggregator* agg)
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : agg_(agg) {}
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<size_t>* counts() {
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return &agg_->counts_;
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackHuffmanAggregator::OriginEncoders* encoders() {
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return &agg_->encoders_;
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t total_counts() {
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return agg_->total_counts_;
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void set_total_counts(size_t total_counts) {
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    agg_->total_counts_ = total_counts;
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void set_max_encoders(size_t max_encoders) {
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    agg_->max_encoders_ = max_encoders;
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static bool IsCrossOrigin(const HttpRequestInfo& request) {
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return HpackHuffmanAggregator::IsCrossOrigin(request);
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static void CreateSpdyHeadersFromHttpResponse(
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const HttpResponseHeaders& headers,
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SpdyHeaderBlock* headers_out) {
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    HpackHuffmanAggregator::CreateSpdyHeadersFromHttpResponse(
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        headers, headers_out);
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackEncoder* ObtainEncoder(const SpdySessionKey& key) {
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return agg_->ObtainEncoder(key);
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void PublishCounts() {
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    agg_->PublishCounts();
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackHuffmanAggregator* agg_;
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace test
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass HpackHuffmanAggregatorTest : public ::testing::Test {
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected:
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackHuffmanAggregatorTest()
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : peer_(&agg_) {}
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackHuffmanAggregator agg_;
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  test::HpackHuffmanAggregatorPeer peer_;
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(HpackHuffmanAggregatorTest, CrossOriginDetermination) {
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HttpRequestInfo request;
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.url = GURL("https://www.foo.com/a/page");
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Main load without referer.
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.load_flags = LOAD_MAIN_FRAME;
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(peer_.IsCrossOrigin(request));
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Non-main load without referer. Treated as cross-origin.
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.load_flags = 0;
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(peer_.IsCrossOrigin(request));
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Main load with different referer origin.
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.load_flags = LOAD_MAIN_FRAME;
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  "https://www.bar.com/other/page");
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(peer_.IsCrossOrigin(request));
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Non-main load with different referer orign.
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.load_flags = 0;
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(peer_.IsCrossOrigin(request));
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Non-main load with same referer orign.
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  "https://www.foo.com/other/page");
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(peer_.IsCrossOrigin(request));
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Non-main load with same referer host but different schemes.
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  "http://www.foo.com/other/page");
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(peer_.IsCrossOrigin(request));
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(HpackHuffmanAggregatorTest, EncoderLRUQueue) {
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.set_max_encoders(2);
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdySessionKey key1(HostPortPair("one.com", 443), ProxyServer::Direct(),
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                      PRIVACY_MODE_ENABLED);
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdySessionKey key2(HostPortPair("two.com", 443), ProxyServer::Direct(),
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                      PRIVACY_MODE_ENABLED);
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdySessionKey key3(HostPortPair("three.com", 443), ProxyServer::Direct(),
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                      PRIVACY_MODE_ENABLED);
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Creates one.com.
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackEncoder* one = peer_.ObtainEncoder(key1);
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(1u, peer_.encoders()->size());
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Creates two.com. No evictions.
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackEncoder* two = peer_.ObtainEncoder(key2);
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(2u, peer_.encoders()->size());
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_NE(one, two);
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Touch one.com.
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(one, peer_.ObtainEncoder(key1));
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Creates three.com. Evicts two.com, as it's least-recently used.
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackEncoder* three = peer_.ObtainEncoder(key3);
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(one, peer_.ObtainEncoder(key1));
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_NE(one, three);
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(2u, peer_.encoders()->size());
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(HpackHuffmanAggregatorTest, PublishCounts) {
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  (*peer_.counts())[0] = 1;
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  (*peer_.counts())[255] = 10;
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  (*peer_.counts())[128] = 101;
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.set_total_counts(112);
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.PublishCounts();
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Internal counts were reset after being published.
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_THAT(*peer_.counts(), Each(Eq(0u)));
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(0u, peer_.total_counts());
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Verify histogram counts match the expectation.
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<base::HistogramSamples> samples =
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::StatisticsRecorder::FindHistogram(kHistogramName)
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ->SnapshotSamples();
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(0, samples->GetCount(0));
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(1, samples->GetCount(1));
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(101, samples->GetCount(129));
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(10, samples->GetCount(256));
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(112, samples->TotalCount());
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Publish a second round of counts;
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  (*peer_.counts())[1] = 32;
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  (*peer_.counts())[128] = 5;
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.set_total_counts(37);
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.PublishCounts();
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Verify they've been aggregated into the previous counts.
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  samples = base::StatisticsRecorder::FindHistogram(kHistogramName)
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ->SnapshotSamples();
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(0, samples->GetCount(0));
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(1, samples->GetCount(1));
1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(32, samples->GetCount(2));
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(106, samples->GetCount(129));
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(10, samples->GetCount(256));
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(149, samples->TotalCount());
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(HpackHuffmanAggregatorTest, CreateSpdyResponseHeaders) {
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  char kRawHeaders[] =
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "HTTP/1.1    202   Accepted  \0"
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Content-TYPE  : text/html; charset=utf-8  \0"
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Set-Cookie: foo=bar \0"
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Set-Cookie:   baz=bing \0"
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Cache-Control: pragma=no-cache \0"
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Cache-CONTROL: expires=12345 \0\0";
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<HttpResponseHeaders> parsed_headers(new HttpResponseHeaders(
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::string(kRawHeaders, arraysize(kRawHeaders) - 1)));
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyHeaderBlock headers;
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  peer_.CreateSpdyHeadersFromHttpResponse(*parsed_headers, &headers);
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_THAT(headers, ElementsAre(
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Pair(":status", "202"),
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Pair("cache-control", std::string("pragma=no-cache\0expires=12345", 29)),
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Pair("content-type", "text/html; charset=utf-8"),
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Pair("set-cookie", std::string("foo=bar\0baz=bing", 16))));
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace net
205