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

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

Powered by Google App Engine
This is Rietveld 408576698