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

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, 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"
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) {
54 base::HistogramBase* histogram =
55 base::StatisticsRecorder::FindHistogram(histogram_name);
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) {
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(
bengr 2014/09/19 21:42:56 Strange indentation. How about: DCHECK(test_job..
sclittle 2014/09/19 22:38:11 Done.
100 test_job_factory_.SetProtocolHandler(url::kHttpScheme,
101 test_job_interceptor_));
102 context_.set_job_factory(&test_job_factory_);
103
53 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, 104 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_,
54 NULL); 105 NULL);
55 } 106 }
56 107
57 void NotifyUnavailable(bool unavailable) { 108 void NotifyUnavailable(bool unavailable) {
58 unavailable_ = unavailable; 109 unavailable_ = unavailable;
59 } 110 }
60 111
112 scoped_ptr<URLRequest> CreateURLRequestWithResponseHeaders(
113 const GURL& url, const std::string& raw_response_headers) {
114 scoped_ptr<URLRequest> fake_request = context_.CreateRequest(url, net::IDLE,
115 &delegate_,
116 NULL);
117
118 // Create a test job that will fill in the given response headers for the
119 // |fake_request|.
120 scoped_refptr<net::URLRequestTestJob> test_job(
121 new net::URLRequestTestJob(fake_request.get(),
122 context_.network_delegate(),
123 raw_response_headers, std::string(), true));
124
125 // Configure the interceptor to use the test job to handle the next request.
126 test_job_interceptor_->set_main_intercept_job(test_job.get());
127 fake_request->Start();
128 MessageLoop::current()->RunUntilIdle();
129
130 DCHECK(fake_request->response_headers() != NULL);
131 return fake_request.Pass();
132 }
133
61 // Required for MessageLoopProxy::current(). 134 // Required for MessageLoopProxy::current().
62 base::MessageLoopForUI loop_; 135 base::MessageLoopForUI loop_;
63 MessageLoopProxy* loop_proxy_; 136 MessageLoopProxy* loop_proxy_;
64 137
65 protected: 138 protected:
66 TestURLRequestContext context_; 139 TestURLRequestContext context_;
67 TestDelegate delegate_; 140 TestDelegate delegate_;
68 DataReductionProxyParamsMock mock_params_; 141 DataReductionProxyParamsMock mock_params_;
69 scoped_ptr<URLRequest> mock_url_request_; 142 scoped_ptr<URLRequest> mock_url_request_;
143 net::TestJobInterceptor* test_job_interceptor_;
144 net::URLRequestJobFactoryImpl test_job_factory_;
70 bool unavailable_; 145 bool unavailable_;
71 }; 146 };
72 147
73 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { 148 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) {
74 struct TestCase { 149 struct TestCase {
75 bool is_proxy_eligible; 150 bool is_proxy_eligible;
76 bool was_proxy_used; 151 bool was_proxy_used;
77 bool is_unreachable; 152 bool is_unreachable;
78 }; 153 };
79 const TestCase test_cases[] = { 154 const TestCase test_cases[] = {
(...skipping 30 matching lines...) Expand all
110 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, 185 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable,
111 base::Unretained(this))); 186 base::Unretained(this)));
112 187
113 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); 188 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false);
114 MessageLoop::current()->RunUntilIdle(); 189 MessageLoop::current()->RunUntilIdle();
115 190
116 EXPECT_EQ(test_case.is_unreachable, unavailable_); 191 EXPECT_EQ(test_case.is_unreachable, unavailable_);
117 } 192 }
118 } 193 }
119 194
195 TEST_F(DataReductionProxyUsageStatsTest,
196 DetectAndRecordMissingViaHeaderResponseCode) {
197 const char kPrimaryHistogramName[] =
198 "DataReductionProxy.MissingViaHeaderResponseCodePrimary";
199 const char kFallbackHistogramName[] =
200 "DataReductionProxy.MissingViaHeaderResponseCodeFallback";
201
202 // Log a sample for each histogram, to ensure that they are both created.
203 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
204 kPrimaryHistogramName, net::HttpUtil::MapStatusCodeForHistogram(200),
205 net::HttpUtil::GetStatusCodesForHistogram());
206 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
207 kFallbackHistogramName, net::HttpUtil::MapStatusCodeForHistogram(200),
208 net::HttpUtil::GetStatusCodesForHistogram());
209
210 struct TestCase {
211 bool is_primary;
212 const char* headers;
213 int expected_primary_sample; // -1 indicates no expected sample.
214 int expected_fallback_sample; // -1 indicates no expected sample.
215 };
216 const TestCase test_cases[] = {
217 {
218 true,
219 "HTTP/1.1 200 OK\n"
220 "Via: 1.1 Chrome-Compression-Proxy\n",
221 -1,
222 -1
223 },
224 {
225 false,
226 "HTTP/1.1 200 OK\n"
227 "Via: 1.1 Chrome-Compression-Proxy\n",
228 -1,
229 -1
230 },
231 {
232 true,
233 "HTTP/1.1 200 OK\n",
234 200,
235 -1
236 },
237 {
238 false,
239 "HTTP/1.1 200 OK\n",
240 -1,
241 200
242 },
243 {
244 true,
245 "HTTP/1.1 304 Not Modified\n",
246 304,
247 -1
248 },
249 {
250 false,
251 "HTTP/1.1 304 Not Modified\n",
252 -1,
253 304
254 },
255 {
256 true,
257 "HTTP/1.1 404 Not Found\n",
258 404,
259 -1
260 },
261 {
262 false,
263 "HTTP/1.1 404 Not Found\n",
264 -1,
265 404
266 }
267 };
268
269 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
270 scoped_ptr<base::HistogramSamples> initial_primary_samples(
271 GetHistogramSamples(kPrimaryHistogramName));
272 scoped_ptr<base::HistogramSamples> initial_fallback_samples(
273 GetHistogramSamples(kFallbackHistogramName));
274
275 std::string raw_headers(test_cases[i].headers);
276 HeadersToRaw(&raw_headers);
277 scoped_refptr<net::HttpResponseHeaders> headers(
278 new net::HttpResponseHeaders(raw_headers));
279
280 DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode(
281 test_cases[i].is_primary, headers.get());
282
283 if (test_cases[i].expected_primary_sample == -1) {
284 ExpectNoNewSamples(*initial_primary_samples, kPrimaryHistogramName);
285 } else {
286 ExpectOneNewSample(*initial_primary_samples, kPrimaryHistogramName,
287 test_cases[i].expected_primary_sample);
288 }
289
290 if (test_cases[i].expected_fallback_sample == -1) {
291 ExpectNoNewSamples(*initial_fallback_samples, kFallbackHistogramName);
292 } else {
293 ExpectOneNewSample(*initial_fallback_samples, kFallbackHistogramName,
294 test_cases[i].expected_fallback_sample);
295 }
296 }
297 }
298
299 TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) {
300 const char k4xxHistogramName[] =
301 "DataReductionProxy.MissingViaHeader4xxResponseBytes";
302 const char kOtherHistogramName[] =
303 "DataReductionProxy.MissingViaHeaderOtherResponseBytes";
304 const int64 kResponseContentLength = 100;
305
306 // Log a sample for each histogram to ensure that they're created.
307 UMA_HISTOGRAM_COUNTS(k4xxHistogramName, 0);
308 UMA_HISTOGRAM_COUNTS(kOtherHistogramName, 0);
309
310 struct TestCase {
311 bool was_proxy_used;
312 const char* headers;
313 bool is_4xx_sample_expected;
314 bool is_other_sample_expected;
315 };
316 const TestCase test_cases[] = {
317 // Nothing should be recorded for requests that don't use the proxy.
318 {
319 false,
320 "HTTP/1.1 404 Not Found\n",
321 false,
322 false
323 },
324 {
325 false,
326 "HTTP/1.1 200 OK\n",
327 false,
328 false
329 },
330 // Nothing should be recorded for responses that have the via header.
331 {
332 true,
333 "HTTP/1.1 404 Not Found\n"
334 "Via: 1.1 Chrome-Compression-Proxy\n",
335 false,
336 false
337 },
338 {
339 true,
340 "HTTP/1.1 200 OK\n"
341 "Via: 1.1 Chrome-Compression-Proxy\n",
342 false,
343 false
344 },
345 // 4xx responses that used the proxy and don't have the via header should be
346 // recorded.
347 {
348 true,
349 "HTTP/1.1 404 Not Found\n",
350 true,
351 false
352 },
353 {
354 true,
355 "HTTP/1.1 400 Bad Request\n",
356 true,
357 false
358 },
359 {
360 true,
361 "HTTP/1.1 499 Big Client Error Response Code\n",
362 true,
363 false
364 },
365 // Non-4xx responses that used the proxy and don't have the via header
366 // should be recorded.
367 {
368 true,
369 "HTTP/1.1 200 OK\n",
370 false,
371 true
372 },
373 {
374 true,
375 "HTTP/1.1 399 Big Redirection Response Code\n",
376 false,
377 true
378 },
379 {
380 true,
381 "HTTP/1.1 500 Internal Server Error\n",
382 false,
383 true
384 }
385 };
386
387 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
388 scoped_ptr<base::HistogramSamples> initial_4xx_samples(
389 GetHistogramSamples(k4xxHistogramName));
390 scoped_ptr<base::HistogramSamples> initial_other_samples(
391 GetHistogramSamples(kOtherHistogramName));
392
393 scoped_ptr<DataReductionProxyUsageStats> usage_stats(
394 new DataReductionProxyUsageStats(&mock_params_, loop_proxy_));
395
396 std::string raw_headers(test_cases[i].headers);
397 HeadersToRaw(&raw_headers);
398
399 scoped_ptr<URLRequest> fake_request(
400 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"),
401 raw_headers));
402 fake_request->set_received_response_content_length(kResponseContentLength);
403
404 EXPECT_CALL(mock_params_,
405 WasDataReductionProxyUsed(fake_request.get(), NULL)).WillRepeatedly(
bengr 2014/09/19 21:42:56 Indentation seems wrong.
sclittle 2014/09/19 22:38:11 Done.
406 Return(test_cases[i].was_proxy_used));
407
408 usage_stats->RecordMissingViaHeaderBytes(*fake_request);
409
410 if (test_cases[i].is_4xx_sample_expected) {
411 ExpectOneNewSample(*initial_4xx_samples, k4xxHistogramName,
412 kResponseContentLength);
413 } else {
414 ExpectNoNewSamples(*initial_4xx_samples, k4xxHistogramName);
415 }
416
417 if (test_cases[i].is_other_sample_expected) {
418 ExpectOneNewSample(*initial_other_samples, kOtherHistogramName,
419 kResponseContentLength);
420 } else {
421 ExpectNoNewSamples(*initial_other_samples, kOtherHistogramName);
422 }
423 }
424 }
425
120 } // namespace data_reduction_proxy 426 } // namespace data_reduction_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698