| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 #include "net/spdy/hpack_huffman_aggregator.h" | 4 #include "net/spdy/hpack_huffman_aggregator.h" |
| 5 | 5 |
| 6 #include "base/metrics/histogram.h" | 6 #include "base/metrics/histogram.h" |
| 7 #include "base/metrics/statistics_recorder.h" | 7 #include "base/metrics/statistics_recorder.h" |
| 8 #include "net/base/load_flags.h" | 8 #include "net/base/load_flags.h" |
| 9 #include "net/http/http_request_headers.h" | 9 #include "net/http/http_request_headers.h" |
| 10 #include "net/http/http_request_info.h" | 10 #include "net/http/http_request_info.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 const char kHistogramName[] = "Net.SpdyHpackEncodedCharacterFrequency"; | 23 const char kHistogramName[] = "Net.SpdyHpackEncodedCharacterFrequency"; |
| 24 } // namespace | 24 } // namespace |
| 25 | 25 |
| 26 namespace test { | 26 namespace test { |
| 27 | 27 |
| 28 class HpackHuffmanAggregatorPeer { | 28 class HpackHuffmanAggregatorPeer { |
| 29 public: | 29 public: |
| 30 explicit HpackHuffmanAggregatorPeer(HpackHuffmanAggregator* agg) | 30 explicit HpackHuffmanAggregatorPeer(HpackHuffmanAggregator* agg) |
| 31 : agg_(agg) {} | 31 : agg_(agg) {} |
| 32 | 32 |
| 33 std::vector<size_t>* counts() { | 33 std::vector<size_t>* counts() { return &agg_->counts_; } |
| 34 return &agg_->counts_; | |
| 35 } | |
| 36 HpackHuffmanAggregator::OriginEncoders* encoders() { | 34 HpackHuffmanAggregator::OriginEncoders* encoders() { |
| 37 return &agg_->encoders_; | 35 return &agg_->encoders_; |
| 38 } | 36 } |
| 39 size_t total_counts() { | 37 size_t total_counts() { return agg_->total_counts_; } |
| 40 return agg_->total_counts_; | |
| 41 } | |
| 42 void set_total_counts(size_t total_counts) { | 38 void set_total_counts(size_t total_counts) { |
| 43 agg_->total_counts_ = total_counts; | 39 agg_->total_counts_ = total_counts; |
| 44 } | 40 } |
| 45 void set_max_encoders(size_t max_encoders) { | 41 void set_max_encoders(size_t max_encoders) { |
| 46 agg_->max_encoders_ = max_encoders; | 42 agg_->max_encoders_ = max_encoders; |
| 47 } | 43 } |
| 48 static bool IsCrossOrigin(const HttpRequestInfo& request) { | 44 static bool IsCrossOrigin(const HttpRequestInfo& request) { |
| 49 return HpackHuffmanAggregator::IsCrossOrigin(request); | 45 return HpackHuffmanAggregator::IsCrossOrigin(request); |
| 50 } | 46 } |
| 51 static void CreateSpdyHeadersFromHttpResponse( | 47 static void CreateSpdyHeadersFromHttpResponse( |
| 52 const HttpResponseHeaders& headers, | 48 const HttpResponseHeaders& headers, |
| 53 SpdyHeaderBlock* headers_out) { | 49 SpdyHeaderBlock* headers_out) { |
| 54 HpackHuffmanAggregator::CreateSpdyHeadersFromHttpResponse( | 50 HpackHuffmanAggregator::CreateSpdyHeadersFromHttpResponse(headers, |
| 55 headers, headers_out); | 51 headers_out); |
| 56 } | 52 } |
| 57 HpackEncoder* ObtainEncoder(const SpdySessionKey& key) { | 53 HpackEncoder* ObtainEncoder(const SpdySessionKey& key) { |
| 58 return agg_->ObtainEncoder(key); | 54 return agg_->ObtainEncoder(key); |
| 59 } | 55 } |
| 60 void PublishCounts() { | 56 void PublishCounts() { agg_->PublishCounts(); } |
| 61 agg_->PublishCounts(); | |
| 62 } | |
| 63 | 57 |
| 64 private: | 58 private: |
| 65 HpackHuffmanAggregator* agg_; | 59 HpackHuffmanAggregator* agg_; |
| 66 }; | 60 }; |
| 67 | 61 |
| 68 } // namespace test | 62 } // namespace test |
| 69 | 63 |
| 70 class HpackHuffmanAggregatorTest : public ::testing::Test { | 64 class HpackHuffmanAggregatorTest : public ::testing::Test { |
| 71 protected: | 65 protected: |
| 72 HpackHuffmanAggregatorTest() | 66 HpackHuffmanAggregatorTest() : peer_(&agg_) {} |
| 73 : peer_(&agg_) {} | |
| 74 | 67 |
| 75 HpackHuffmanAggregator agg_; | 68 HpackHuffmanAggregator agg_; |
| 76 test::HpackHuffmanAggregatorPeer peer_; | 69 test::HpackHuffmanAggregatorPeer peer_; |
| 77 }; | 70 }; |
| 78 | 71 |
| 79 TEST_F(HpackHuffmanAggregatorTest, CrossOriginDetermination) { | 72 TEST_F(HpackHuffmanAggregatorTest, CrossOriginDetermination) { |
| 80 HttpRequestInfo request; | 73 HttpRequestInfo request; |
| 81 request.url = GURL("https://www.foo.com/a/page"); | 74 request.url = GURL("https://www.foo.com/a/page"); |
| 82 | 75 |
| 83 // Main load without referer. | 76 // Main load without referer. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 105 | 98 |
| 106 // Non-main load with same referer host but different schemes. | 99 // Non-main load with same referer host but different schemes. |
| 107 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, | 100 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, |
| 108 "http://www.foo.com/other/page"); | 101 "http://www.foo.com/other/page"); |
| 109 EXPECT_TRUE(peer_.IsCrossOrigin(request)); | 102 EXPECT_TRUE(peer_.IsCrossOrigin(request)); |
| 110 } | 103 } |
| 111 | 104 |
| 112 TEST_F(HpackHuffmanAggregatorTest, EncoderLRUQueue) { | 105 TEST_F(HpackHuffmanAggregatorTest, EncoderLRUQueue) { |
| 113 peer_.set_max_encoders(2); | 106 peer_.set_max_encoders(2); |
| 114 | 107 |
| 115 SpdySessionKey key1(HostPortPair("one.com", 443), ProxyServer::Direct(), | 108 SpdySessionKey key1(HostPortPair("one.com", 443), |
| 109 ProxyServer::Direct(), |
| 116 PRIVACY_MODE_ENABLED); | 110 PRIVACY_MODE_ENABLED); |
| 117 SpdySessionKey key2(HostPortPair("two.com", 443), ProxyServer::Direct(), | 111 SpdySessionKey key2(HostPortPair("two.com", 443), |
| 112 ProxyServer::Direct(), |
| 118 PRIVACY_MODE_ENABLED); | 113 PRIVACY_MODE_ENABLED); |
| 119 SpdySessionKey key3(HostPortPair("three.com", 443), ProxyServer::Direct(), | 114 SpdySessionKey key3(HostPortPair("three.com", 443), |
| 115 ProxyServer::Direct(), |
| 120 PRIVACY_MODE_ENABLED); | 116 PRIVACY_MODE_ENABLED); |
| 121 | 117 |
| 122 // Creates one.com. | 118 // Creates one.com. |
| 123 HpackEncoder* one = peer_.ObtainEncoder(key1); | 119 HpackEncoder* one = peer_.ObtainEncoder(key1); |
| 124 EXPECT_EQ(1u, peer_.encoders()->size()); | 120 EXPECT_EQ(1u, peer_.encoders()->size()); |
| 125 | 121 |
| 126 // Creates two.com. No evictions. | 122 // Creates two.com. No evictions. |
| 127 HpackEncoder* two = peer_.ObtainEncoder(key2); | 123 HpackEncoder* two = peer_.ObtainEncoder(key2); |
| 128 EXPECT_EQ(2u, peer_.encoders()->size()); | 124 EXPECT_EQ(2u, peer_.encoders()->size()); |
| 129 EXPECT_NE(one, two); | 125 EXPECT_NE(one, two); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 146 | 142 |
| 147 peer_.PublishCounts(); | 143 peer_.PublishCounts(); |
| 148 | 144 |
| 149 // Internal counts were reset after being published. | 145 // Internal counts were reset after being published. |
| 150 EXPECT_THAT(*peer_.counts(), Each(Eq(0u))); | 146 EXPECT_THAT(*peer_.counts(), Each(Eq(0u))); |
| 151 EXPECT_EQ(0u, peer_.total_counts()); | 147 EXPECT_EQ(0u, peer_.total_counts()); |
| 152 | 148 |
| 153 // Verify histogram counts match the expectation. | 149 // Verify histogram counts match the expectation. |
| 154 scoped_ptr<base::HistogramSamples> samples = | 150 scoped_ptr<base::HistogramSamples> samples = |
| 155 base::StatisticsRecorder::FindHistogram(kHistogramName) | 151 base::StatisticsRecorder::FindHistogram(kHistogramName) |
| 156 ->SnapshotSamples(); | 152 ->SnapshotSamples(); |
| 157 | 153 |
| 158 EXPECT_EQ(0, samples->GetCount(0)); | 154 EXPECT_EQ(0, samples->GetCount(0)); |
| 159 EXPECT_EQ(1, samples->GetCount(1)); | 155 EXPECT_EQ(1, samples->GetCount(1)); |
| 160 EXPECT_EQ(101, samples->GetCount(129)); | 156 EXPECT_EQ(101, samples->GetCount(129)); |
| 161 EXPECT_EQ(10, samples->GetCount(256)); | 157 EXPECT_EQ(10, samples->GetCount(256)); |
| 162 EXPECT_EQ(112, samples->TotalCount()); | 158 EXPECT_EQ(112, samples->TotalCount()); |
| 163 | 159 |
| 164 // Publish a second round of counts; | 160 // Publish a second round of counts; |
| 165 (*peer_.counts())[1] = 32; | 161 (*peer_.counts())[1] = 32; |
| 166 (*peer_.counts())[128] = 5; | 162 (*peer_.counts())[128] = 5; |
| 167 peer_.set_total_counts(37); | 163 peer_.set_total_counts(37); |
| 168 | 164 |
| 169 peer_.PublishCounts(); | 165 peer_.PublishCounts(); |
| 170 | 166 |
| 171 // Verify they've been aggregated into the previous counts. | 167 // Verify they've been aggregated into the previous counts. |
| 172 samples = base::StatisticsRecorder::FindHistogram(kHistogramName) | 168 samples = base::StatisticsRecorder::FindHistogram(kHistogramName) |
| 173 ->SnapshotSamples(); | 169 ->SnapshotSamples(); |
| 174 | 170 |
| 175 EXPECT_EQ(0, samples->GetCount(0)); | 171 EXPECT_EQ(0, samples->GetCount(0)); |
| 176 EXPECT_EQ(1, samples->GetCount(1)); | 172 EXPECT_EQ(1, samples->GetCount(1)); |
| 177 EXPECT_EQ(32, samples->GetCount(2)); | 173 EXPECT_EQ(32, samples->GetCount(2)); |
| 178 EXPECT_EQ(106, samples->GetCount(129)); | 174 EXPECT_EQ(106, samples->GetCount(129)); |
| 179 EXPECT_EQ(10, samples->GetCount(256)); | 175 EXPECT_EQ(10, samples->GetCount(256)); |
| 180 EXPECT_EQ(149, samples->TotalCount()); | 176 EXPECT_EQ(149, samples->TotalCount()); |
| 181 } | 177 } |
| 182 | 178 |
| 183 TEST_F(HpackHuffmanAggregatorTest, CreateSpdyResponseHeaders) { | 179 TEST_F(HpackHuffmanAggregatorTest, CreateSpdyResponseHeaders) { |
| 184 char kRawHeaders[] = | 180 char kRawHeaders[] = |
| 185 "HTTP/1.1 202 Accepted \0" | 181 "HTTP/1.1 202 Accepted \0" |
| 186 "Content-TYPE : text/html; charset=utf-8 \0" | 182 "Content-TYPE : text/html; charset=utf-8 \0" |
| 187 "Set-Cookie: foo=bar \0" | 183 "Set-Cookie: foo=bar \0" |
| 188 "Set-Cookie: baz=bing \0" | 184 "Set-Cookie: baz=bing \0" |
| 189 "Cache-Control: pragma=no-cache \0" | 185 "Cache-Control: pragma=no-cache \0" |
| 190 "Cache-CONTROL: expires=12345 \0\0"; | 186 "Cache-CONTROL: expires=12345 \0\0"; |
| 191 | 187 |
| 192 scoped_refptr<HttpResponseHeaders> parsed_headers(new HttpResponseHeaders( | 188 scoped_refptr<HttpResponseHeaders> parsed_headers(new HttpResponseHeaders( |
| 193 std::string(kRawHeaders, arraysize(kRawHeaders) - 1))); | 189 std::string(kRawHeaders, arraysize(kRawHeaders) - 1))); |
| 194 | 190 |
| 195 SpdyHeaderBlock headers; | 191 SpdyHeaderBlock headers; |
| 196 peer_.CreateSpdyHeadersFromHttpResponse(*parsed_headers, &headers); | 192 peer_.CreateSpdyHeadersFromHttpResponse(*parsed_headers, &headers); |
| 197 EXPECT_THAT(headers, ElementsAre( | 193 EXPECT_THAT( |
| 198 Pair(":status", "202"), | 194 headers, |
| 199 Pair("cache-control", std::string("pragma=no-cache\0expires=12345", 29)), | 195 ElementsAre(Pair(":status", "202"), |
| 200 Pair("content-type", "text/html; charset=utf-8"), | 196 Pair("cache-control", |
| 201 Pair("set-cookie", std::string("foo=bar\0baz=bing", 16)))); | 197 std::string("pragma=no-cache\0expires=12345", 29)), |
| 198 Pair("content-type", "text/html; charset=utf-8"), |
| 199 Pair("set-cookie", std::string("foo=bar\0baz=bing", 16)))); |
| 202 } | 200 } |
| 203 | 201 |
| 204 } // namespace net | 202 } // namespace net |
| OLD | NEW |