Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats_unittest.cc

Issue 577343002: Adds UMA to measure when the data reduction proxy via header is missing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 4
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_sta ts.h" 5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_sta ts.h"
6 6
7 #include <string>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/histogram_samples.h"
13 #include "base/metrics/statistics_recorder.h"
9 #include "net/base/request_priority.h" 14 #include "net/base/request_priority.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/http/http_util.h"
10 #include "net/url_request/url_request.h" 17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_job_factory_impl.h"
11 #include "net/url_request/url_request_status.h" 19 #include "net/url_request/url_request_status.h"
20 #include "net/url_request/url_request_test_job.h"
12 #include "net/url_request/url_request_test_util.h" 21 #include "net/url_request/url_request_test_util.h"
13 #include "testing/gmock/include/gmock/gmock.h" 22 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
15 24
16 using base::MessageLoop; 25 using base::MessageLoop;
17 using base::MessageLoopProxy; 26 using base::MessageLoopProxy;
18 using data_reduction_proxy::DataReductionProxyParams; 27 using data_reduction_proxy::DataReductionProxyParams;
19 using net::TestDelegate; 28 using net::TestDelegate;
20 using net::TestURLRequestContext; 29 using net::TestURLRequestContext;
21 using net::URLRequest; 30 using net::URLRequest;
(...skipping 10 matching lines...) Expand all
32 MOCK_METHOD1(IsDataReductionProxyEligible, bool(const net::URLRequest*)); 41 MOCK_METHOD1(IsDataReductionProxyEligible, bool(const net::URLRequest*));
33 MOCK_CONST_METHOD2( 42 MOCK_CONST_METHOD2(
34 WasDataReductionProxyUsed, 43 WasDataReductionProxyUsed,
35 bool(const net::URLRequest*, 44 bool(const net::URLRequest*,
36 data_reduction_proxy::DataReductionProxyTypeInfo* proxy_servers)); 45 data_reduction_proxy::DataReductionProxyTypeInfo* proxy_servers));
37 46
38 private: 47 private:
39 DISALLOW_COPY_AND_ASSIGN(DataReductionProxyParamsMock); 48 DISALLOW_COPY_AND_ASSIGN(DataReductionProxyParamsMock);
40 }; 49 };
41 50
51 // Transform "normal"-looking headers (\n-separated) to the appropriate
52 // input format for ParseRawHeaders (\0-separated).
53 void HeadersToRaw(std::string* headers) {
bengr 2014/09/18 19:55:57 I think duplicates of this function live elsewhere
sclittle 2014/09/19 01:05:01 Done.
54 std::replace(headers->begin(), headers->end(), '\n', '\0');
55 if (!headers->empty())
56 *headers += '\0';
57 }
58
59 scoped_ptr<base::HistogramSamples> GetHistogramSamples(
60 const char* histogram_name) {
61 base::HistogramBase* histogram =
62 base::StatisticsRecorder::FindHistogram(histogram_name);
63
64 EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram);
65
66 return histogram->SnapshotSamples().Pass();
67 }
68
69 scoped_ptr<base::HistogramSamples> GetDeltaHistogramSamples(
70 const base::HistogramSamples& initial_samples, const char* histogram_name) {
71 scoped_ptr<base::HistogramSamples> delta_samples(
72 GetHistogramSamples(histogram_name));
73 delta_samples->Subtract(initial_samples);
74 return delta_samples.Pass();
75 }
76
77 void ExpectNoNewSamples(const base::HistogramSamples& initial_samples,
78 const char* histogram_name) {
79 scoped_ptr<base::HistogramSamples> delta_samples(
80 GetDeltaHistogramSamples(initial_samples, histogram_name));
81
82 EXPECT_EQ(0, delta_samples->TotalCount());
83 }
84
85 void ExpectOneNewSample(const base::HistogramSamples& initial_samples,
86 const char* histogram_name,
87 base::HistogramBase::Sample sample) {
88 scoped_ptr<base::HistogramSamples> delta_samples(
89 GetDeltaHistogramSamples(initial_samples, histogram_name));
90
bengr 2014/09/18 19:55:57 Here and above, I don't think the blank lines impr
sclittle 2014/09/19 01:05:01 Done.
91 EXPECT_EQ(1, delta_samples->TotalCount());
92 EXPECT_EQ(1, delta_samples->GetCount(sample));
93 }
94
42 } // namespace 95 } // namespace
43 96
44 namespace data_reduction_proxy { 97 namespace data_reduction_proxy {
45 98
46 class DataReductionProxyUsageStatsTest : public testing::Test { 99 class DataReductionProxyUsageStatsTest : public testing::Test {
47 public: 100 public:
48 DataReductionProxyUsageStatsTest() 101 DataReductionProxyUsageStatsTest()
49 : loop_proxy_(MessageLoopProxy::current().get()), 102 : loop_proxy_(MessageLoopProxy::current().get()),
50 context_(true), 103 context_(true),
51 unavailable_(false) { 104 unavailable_(false){
105 base::StatisticsRecorder::Initialize();
52 context_.Init(); 106 context_.Init();
107
108 // The |test_job_factory_| takes ownership of the interceptor.
109 test_job_interceptor_ = new net::TestJobInterceptor();
110 DCHECK(
111 test_job_factory_.SetProtocolHandler(url::kHttpScheme,
112 test_job_interceptor_));
113 context_.set_job_factory(&test_job_factory_);
114
53 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, 115 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_,
54 NULL); 116 NULL);
55 } 117 }
56 118
57 void NotifyUnavailable(bool unavailable) { 119 void NotifyUnavailable(bool unavailable) {
58 unavailable_ = unavailable; 120 unavailable_ = unavailable;
59 } 121 }
60 122
123 scoped_ptr<URLRequest> CreateURLRequestWithResponseHeaders(
124 const GURL& url, const std::string& raw_response_headers) {
125 scoped_ptr<URLRequest> fake_request = context_.CreateRequest(url, net::IDLE,
126 &delegate_,
127 NULL);
128
129 // Create a test job that will fill in the given response headers for the
130 // |fake_request|.
131 scoped_refptr<net::URLRequestTestJob> test_job(
132 new net::URLRequestTestJob(fake_request.get(),
133 context_.network_delegate(),
134 raw_response_headers, std::string(), true));
135
136 // Configure the interceptor to use the test job to handle the next request.
137 test_job_interceptor_->set_main_intercept_job(test_job.get());
138 fake_request->Start();
139 MessageLoop::current()->RunUntilIdle();
140
141 DCHECK(fake_request->response_headers() != NULL);
142 return fake_request.Pass();
143 }
144
61 // Required for MessageLoopProxy::current(). 145 // Required for MessageLoopProxy::current().
62 base::MessageLoopForUI loop_; 146 base::MessageLoopForUI loop_;
63 MessageLoopProxy* loop_proxy_; 147 MessageLoopProxy* loop_proxy_;
64 148
65 protected: 149 protected:
66 TestURLRequestContext context_; 150 TestURLRequestContext context_;
67 TestDelegate delegate_; 151 TestDelegate delegate_;
68 DataReductionProxyParamsMock mock_params_; 152 DataReductionProxyParamsMock mock_params_;
69 scoped_ptr<URLRequest> mock_url_request_; 153 scoped_ptr<URLRequest> mock_url_request_;
154 net::TestJobInterceptor* test_job_interceptor_;
155 net::URLRequestJobFactoryImpl test_job_factory_;
70 bool unavailable_; 156 bool unavailable_;
71 }; 157 };
72 158
73 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { 159 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) {
74 struct TestCase { 160 struct TestCase {
75 bool is_proxy_eligible; 161 bool is_proxy_eligible;
76 bool was_proxy_used; 162 bool was_proxy_used;
77 bool is_unreachable; 163 bool is_unreachable;
78 }; 164 };
79 const TestCase test_cases[] = { 165 const TestCase test_cases[] = {
(...skipping 30 matching lines...) Expand all
110 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, 196 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable,
111 base::Unretained(this))); 197 base::Unretained(this)));
112 198
113 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); 199 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false);
114 MessageLoop::current()->RunUntilIdle(); 200 MessageLoop::current()->RunUntilIdle();
115 201
116 EXPECT_EQ(test_case.is_unreachable, unavailable_); 202 EXPECT_EQ(test_case.is_unreachable, unavailable_);
117 } 203 }
118 } 204 }
119 205
206 TEST_F(DataReductionProxyUsageStatsTest,
207 DetectAndRecordMissingViaHeaderResponseCode) {
208 const char kPrimaryHistogramName[] =
209 "DataReductionProxy.MissingViaHeaderResponseCodePrimary";
210 const char kFallbackHistogramName[] =
211 "DataReductionProxy.MissingViaHeaderResponseCodeFallback";
212
213 // Log a sample for each histogram, to ensure that they are both created.
214 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
215 kPrimaryHistogramName, net::HttpUtil::MapStatusCodeForHistogram(200),
216 net::HttpUtil::GetStatusCodesForHistogram());
217 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
218 kFallbackHistogramName, net::HttpUtil::MapStatusCodeForHistogram(200),
219 net::HttpUtil::GetStatusCodesForHistogram());
220
221 struct TestCase {
222 bool is_primary;
223 const char* headers;
224 int expected_primary_sample; // -1 indicates no expected sample.
225 int expected_fallback_sample; // -1 indicates no expected sample.
226 };
227 const TestCase test_cases[] = {
228 {
229 true,
230 "HTTP/1.1 200 OK\n"
231 "Via: 1.1 Chrome-Compression-Proxy\n",
232 -1,
233 -1
234 },
235 {
236 false,
237 "HTTP/1.1 200 OK\n"
238 "Via: 1.1 Chrome-Compression-Proxy\n",
239 -1,
240 -1
241 },
242 {
243 true,
244 "HTTP/1.1 200 OK\n",
245 200,
246 -1
247 },
248 {
249 false,
250 "HTTP/1.1 200 OK\n",
251 -1,
252 200
253 },
254 {
255 true,
256 "HTTP/1.1 304 Not Modified\n",
257 304,
258 -1
259 },
260 {
261 false,
262 "HTTP/1.1 304 Not Modified\n",
263 -1,
264 304
265 },
266 {
267 true,
268 "HTTP/1.1 404 Not Found\n",
269 404,
270 -1
271 },
272 {
273 false,
274 "HTTP/1.1 404 Not Found\n",
275 -1,
276 404
277 }
278 };
279
280 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
281 scoped_ptr<base::HistogramSamples> initial_primary_samples(
282 GetHistogramSamples(
283 kPrimaryHistogramName));
bengr 2014/09/18 19:55:57 move up a with previous line?
sclittle 2014/09/19 01:05:01 Done.
284 scoped_ptr<base::HistogramSamples> initial_fallback_samples(
285 GetHistogramSamples(
286 kFallbackHistogramName));
bengr 2014/09/18 19:55:57 move up a with previous line?
sclittle 2014/09/19 01:05:01 Done.
287
288 std::string raw_headers(test_cases[i].headers);
289 HeadersToRaw(&raw_headers);
290 scoped_refptr<net::HttpResponseHeaders> headers(
291 new net::HttpResponseHeaders(raw_headers));
292
293 DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode(
294 test_cases[i].is_primary, headers.get());
295
296 if (test_cases[i].expected_primary_sample == -1) {
297 ExpectNoNewSamples(*initial_primary_samples, kPrimaryHistogramName);
298 } else {
299 ExpectOneNewSample(*initial_primary_samples, kPrimaryHistogramName,
300 test_cases[i].expected_primary_sample);
301 }
302
303 if (test_cases[i].expected_fallback_sample == -1) {
304 ExpectNoNewSamples(*initial_fallback_samples, kFallbackHistogramName);
305 } else {
306 ExpectOneNewSample(*initial_fallback_samples, kFallbackHistogramName,
307 test_cases[i].expected_fallback_sample);
308 }
309 }
310 }
311
312 TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) {
313 const char k4xxHistogramName[] =
314 "DataReductionProxy.MissingViaHeader4xxResponseBytes";
315 const char kOtherHistogramName[] =
316 "DataReductionProxy.MissingViaHeaderOtherResponseBytes";
317 const int64 kResponseContentLength = 100;
318
319 // Log a sample for each histogram to ensure that they're created.
320 UMA_HISTOGRAM_COUNTS(k4xxHistogramName, 0);
321 UMA_HISTOGRAM_COUNTS(kOtherHistogramName, 0);
322
323 struct TestCase {
324 bool was_proxy_used;
325 const char* headers;
326 bool is_4xx_sample_expected;
327 bool is_other_sample_expected;
328 };
329 const TestCase test_cases[] = {
330 // Nothing should be recorded for requests that don't use the proxy.
331 {
332 false,
333 "HTTP/1.1 404 Not Found\n",
334 false,
335 false
336 },
337 {
338 false,
339 "HTTP/1.1 200 OK\n",
340 false,
341 false
342 },
343 // Nothing should be recorded for responses that have the via header.
344 {
345 true,
346 "HTTP/1.1 404 Not Found\n"
347 "Via: 1.1 Chrome-Compression-Proxy\n",
348 false,
349 false
350 },
351 {
352 true,
353 "HTTP/1.1 200 OK\n"
354 "Via: 1.1 Chrome-Compression-Proxy\n",
355 false,
356 false
357 },
358 // 4xx responses that used the proxy and don't have the via header should be
359 // recorded.
360 {
361 true,
362 "HTTP/1.1 404 Not Found\n",
363 true,
364 false
365 },
366 {
367 true,
368 "HTTP/1.1 400 Bad Request\n",
369 true,
370 false
371 },
372 {
373 true,
374 "HTTP/1.1 499 Big Client Error Response Code\n",
375 true,
376 false
377 },
378 // Non-4xx responses that used the proxy and don't have the via header
379 // should be recorded.
380 {
381 true,
382 "HTTP/1.1 200 OK\n",
383 false,
384 true
385 },
386 {
387 true,
388 "HTTP/1.1 399 Big Redirection Response Code\n",
389 false,
390 true
391 },
392 {
393 true,
394 "HTTP/1.1 500 Internal Server Error\n",
395 false,
396 true
397 }
398 };
399
400 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
401 scoped_ptr<base::HistogramSamples> initial_4xx_samples(
402 GetHistogramSamples(k4xxHistogramName));
403 scoped_ptr<base::HistogramSamples> initial_other_samples(
404 GetHistogramSamples(kOtherHistogramName));
405
406 scoped_ptr<DataReductionProxyUsageStats> usage_stats(
407 new DataReductionProxyUsageStats(&mock_params_, loop_proxy_));
408
409 std::string raw_headers(test_cases[i].headers);
410 HeadersToRaw(&raw_headers);
411
412 scoped_ptr<URLRequest> fake_request(
413 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"),
414 raw_headers));
415 fake_request->set_received_response_content_length(kResponseContentLength);
416
417 EXPECT_CALL(mock_params_,
418 WasDataReductionProxyUsed(fake_request.get(), NULL))
bengr 2014/09/18 19:55:57 Indentation seems off.
sclittle 2014/09/19 01:05:01 Done.
419 .WillRepeatedly(Return(test_cases[i].was_proxy_used));
420
421 usage_stats->RecordMissingViaHeaderBytes(fake_request.get());
422
423 if (test_cases[i].is_4xx_sample_expected) {
424 ExpectOneNewSample(*initial_4xx_samples, k4xxHistogramName,
425 kResponseContentLength);
426 } else {
427 ExpectNoNewSamples(*initial_4xx_samples, k4xxHistogramName);
428 }
429
430 if (test_cases[i].is_other_sample_expected) {
431 ExpectOneNewSample(*initial_other_samples, kOtherHistogramName,
432 kResponseContentLength);
433 } else {
434 ExpectNoNewSamples(*initial_other_samples, kOtherHistogramName);
435 }
436 }
437 }
438
bengr 2014/09/18 19:55:57 Remove extra blank line
sclittle 2014/09/19 01:05:01 Done.
439
120 } // namespace data_reduction_proxy 440 } // namespace data_reduction_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698