monitor_unittest.cc revision ab8f6f0bd665d3c1ff476eb06c58c42630e462d4
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 3// found in the LICENSE file. 4 5#include "components/domain_reliability/monitor.h" 6 7#include <map> 8#include <string> 9#include <vector> 10 11#include "base/bind.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/message_loop/message_loop_proxy.h" 14#include "base/test/test_simple_task_runner.h" 15#include "components/domain_reliability/baked_in_configs.h" 16#include "components/domain_reliability/beacon.h" 17#include "components/domain_reliability/config.h" 18#include "components/domain_reliability/test_util.h" 19#include "net/base/host_port_pair.h" 20#include "net/base/load_flags.h" 21#include "net/http/http_response_headers.h" 22#include "net/http/http_util.h" 23#include "net/url_request/url_request_context_getter.h" 24#include "net/url_request/url_request_status.h" 25#include "net/url_request/url_request_test_util.h" 26#include "testing/gtest/include/gtest/gtest.h" 27 28namespace domain_reliability { 29 30namespace { 31 32typedef std::vector<DomainReliabilityBeacon> BeaconVector; 33 34static const size_t kAlwaysReportIndex = 0u; 35static const size_t kNeverReportIndex = 1u; 36 37scoped_refptr<net::HttpResponseHeaders> MakeHttpResponseHeaders( 38 const std::string& headers) { 39 return scoped_refptr<net::HttpResponseHeaders>( 40 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders( 41 headers.c_str(), headers.length()))); 42} 43 44} // namespace 45 46class DomainReliabilityMonitorTest : public testing::Test { 47 protected: 48 typedef DomainReliabilityMonitor::RequestInfo RequestInfo; 49 50 DomainReliabilityMonitorTest() 51 : pref_task_runner_(new base::TestSimpleTaskRunner()), 52 network_task_runner_(new base::TestSimpleTaskRunner()), 53 url_request_context_getter_( 54 new net::TestURLRequestContextGetter(network_task_runner_)), 55 time_(new MockTime()), 56 monitor_("test-reporter", 57 pref_task_runner_, 58 network_task_runner_, 59 scoped_ptr<MockableTime>(time_)), 60 context_(NULL) { 61 monitor_.MoveToNetworkThread(); 62 monitor_.InitURLRequestContext(url_request_context_getter_); 63 monitor_.SetDiscardUploads(false); 64 context_ = monitor_.AddContextForTesting(MakeTestConfig()); 65 } 66 67 static RequestInfo MakeRequestInfo() { 68 RequestInfo request; 69 request.status = net::URLRequestStatus(); 70 request.status.set_status(net::URLRequestStatus::SUCCESS); 71 request.status.set_error(net::OK); 72 request.response_info.socket_address = 73 net::HostPortPair::FromString("12.34.56.78:80"); 74 request.response_info.headers = MakeHttpResponseHeaders( 75 "HTTP/1.1 200 OK\n\n"); 76 request.response_info.network_accessed = true; 77 request.response_info.was_fetched_via_proxy = false; 78 request.load_flags = 0; 79 request.is_upload = false; 80 return request; 81 } 82 83 void OnRequestLegComplete(const RequestInfo& info) { 84 monitor_.OnRequestLegComplete(info); 85 } 86 87 size_t CountPendingBeacons() { 88 BeaconVector beacons; 89 context_->GetQueuedBeaconsForTesting(&beacons); 90 return beacons.size(); 91 } 92 93 bool CheckRequestCounts(size_t index, 94 uint32 expected_successful, 95 uint32 expected_failed) { 96 return CheckRequestCounts(context_, 97 index, 98 expected_successful, 99 expected_failed); 100 } 101 102 bool CheckRequestCounts(DomainReliabilityContext* context, 103 size_t index, 104 uint32 expected_successful, 105 uint32 expected_failed) { 106 uint32 successful, failed; 107 context->GetRequestCountsForTesting(index, &successful, &failed); 108 EXPECT_EQ(expected_successful, successful); 109 EXPECT_EQ(expected_failed, failed); 110 return expected_successful == successful && expected_failed == failed; 111 } 112 113 DomainReliabilityContext* CreateAndAddContext(const std::string& domain) { 114 return monitor_.AddContextForTesting(MakeTestConfigWithDomain(domain)); 115 } 116 117 scoped_refptr<base::TestSimpleTaskRunner> pref_task_runner_; 118 scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_; 119 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 120 MockTime* time_; 121 DomainReliabilityMonitor monitor_; 122 DomainReliabilityContext* context_; 123 DomainReliabilityMonitor::RequestInfo request_; 124}; 125 126namespace { 127 128TEST_F(DomainReliabilityMonitorTest, Create) { 129 EXPECT_EQ(0u, CountPendingBeacons()); 130 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 131 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 132} 133 134TEST_F(DomainReliabilityMonitorTest, NoContext) { 135 RequestInfo request = MakeRequestInfo(); 136 request.url = GURL("http://no-context/"); 137 OnRequestLegComplete(request); 138 139 EXPECT_EQ(0u, CountPendingBeacons()); 140 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 141 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 142} 143 144TEST_F(DomainReliabilityMonitorTest, NotReported) { 145 RequestInfo request = MakeRequestInfo(); 146 request.url = GURL("http://example/never_report"); 147 OnRequestLegComplete(request); 148 149 EXPECT_EQ(0u, CountPendingBeacons()); 150 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 1u, 0u)); 151} 152 153TEST_F(DomainReliabilityMonitorTest, NetworkFailure) { 154 RequestInfo request = MakeRequestInfo(); 155 request.url = GURL("http://example/always_report"); 156 request.status.set_status(net::URLRequestStatus::FAILED); 157 request.status.set_error(net::ERR_CONNECTION_RESET); 158 request.response_info.headers = NULL; 159 OnRequestLegComplete(request); 160 161 EXPECT_EQ(1u, CountPendingBeacons()); 162 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u)); 163} 164 165TEST_F(DomainReliabilityMonitorTest, ServerFailure) { 166 RequestInfo request = MakeRequestInfo(); 167 request.url = GURL("http://example/always_report"); 168 request.response_info.headers = 169 MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n"); 170 OnRequestLegComplete(request); 171 172 EXPECT_EQ(1u, CountPendingBeacons()); 173 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u)); 174} 175 176TEST_F(DomainReliabilityMonitorTest, NotReportedFailure) { 177 RequestInfo request = MakeRequestInfo(); 178 request.url = GURL("http://example/never_report"); 179 request.status.set_status(net::URLRequestStatus::FAILED); 180 request.status.set_error(net::ERR_CONNECTION_RESET); 181 OnRequestLegComplete(request); 182 183 EXPECT_EQ(0u, CountPendingBeacons()); 184 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 1u)); 185} 186 187TEST_F(DomainReliabilityMonitorTest, Request) { 188 RequestInfo request = MakeRequestInfo(); 189 request.url = GURL("http://example/always_report"); 190 OnRequestLegComplete(request); 191 192 EXPECT_EQ(1u, CountPendingBeacons()); 193 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 194} 195 196// Make sure the monitor does not log requests that did not access the network. 197TEST_F(DomainReliabilityMonitorTest, DidNotAccessNetwork) { 198 RequestInfo request = MakeRequestInfo(); 199 request.url = GURL("http://example/always_report"); 200 request.response_info.network_accessed = false; 201 OnRequestLegComplete(request); 202 203 EXPECT_EQ(0u, CountPendingBeacons()); 204 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 205} 206 207// Make sure the monitor does not log requests that don't send cookies. 208TEST_F(DomainReliabilityMonitorTest, DoNotSendCookies) { 209 RequestInfo request = MakeRequestInfo(); 210 request.url = GURL("http://example/always_report"); 211 request.load_flags = net::LOAD_DO_NOT_SEND_COOKIES; 212 OnRequestLegComplete(request); 213 214 EXPECT_EQ(0u, CountPendingBeacons()); 215 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 216} 217 218// Make sure the monitor does not log upload requests. 219TEST_F(DomainReliabilityMonitorTest, IsUpload) { 220 RequestInfo request = MakeRequestInfo(); 221 request.url = GURL("http://example/always_report"); 222 request.is_upload = true; 223 OnRequestLegComplete(request); 224 225 EXPECT_EQ(0u, CountPendingBeacons()); 226 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 227} 228 229// Make sure the monitor does not log a network-local error. 230TEST_F(DomainReliabilityMonitorTest, LocalError) { 231 RequestInfo request = MakeRequestInfo(); 232 request.url = GURL("http://example/always_report"); 233 request.status.set_status(net::URLRequestStatus::FAILED); 234 request.status.set_error(net::ERR_PROXY_CONNECTION_FAILED); 235 OnRequestLegComplete(request); 236 237 EXPECT_EQ(0u, CountPendingBeacons()); 238 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 239} 240 241// Make sure the monitor does not log the proxy's IP if one was used. 242TEST_F(DomainReliabilityMonitorTest, WasFetchedViaProxy) { 243 RequestInfo request = MakeRequestInfo(); 244 request.url = GURL("http://example/always_report"); 245 request.response_info.socket_address = 246 net::HostPortPair::FromString("127.0.0.1:3128"); 247 request.response_info.was_fetched_via_proxy = true; 248 OnRequestLegComplete(request); 249 250 BeaconVector beacons; 251 context_->GetQueuedBeaconsForTesting(&beacons); 252 EXPECT_EQ(1u, beacons.size()); 253 EXPECT_TRUE(beacons[0].server_ip.empty()); 254 255 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 256} 257 258// Will fail when baked-in configs expire, as a reminder to update them. 259// (Contact ttuttle@chromium.org if this starts failing.) 260TEST_F(DomainReliabilityMonitorTest, AddBakedInConfigs) { 261 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so 262 // this unittest will fail if someone tries to add an invalid config to the 263 // source tree. 264 monitor_.AddBakedInConfigs(); 265 266 // Count the number of baked-in configs. 267 size_t num_baked_in_configs = 0; 268 for (const char* const* p = kBakedInJsonConfigs; *p; ++p) 269 ++num_baked_in_configs; 270 271 // The monitor should have contexts for all of the baked-in configs, plus the 272 // test one added in the test constructor. 273 EXPECT_EQ(num_baked_in_configs + 1, monitor_.contexts_size_for_testing()); 274} 275 276TEST_F(DomainReliabilityMonitorTest, ClearBeacons) { 277 // Initially the monitor should have just the test context, with no beacons. 278 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 279 EXPECT_EQ(0u, CountPendingBeacons()); 280 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 281 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 282 283 // Add a beacon. 284 RequestInfo request = MakeRequestInfo(); 285 request.url = GURL("http://example/always_report"); 286 OnRequestLegComplete(request); 287 288 // Make sure it was added. 289 EXPECT_EQ(1u, CountPendingBeacons()); 290 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 291 292 monitor_.ClearBrowsingData(CLEAR_BEACONS); 293 294 // Make sure the beacon was cleared, but not the contexts. 295 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 296 EXPECT_EQ(0u, CountPendingBeacons()); 297 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 298 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 299} 300 301TEST_F(DomainReliabilityMonitorTest, ClearContexts) { 302 // Initially the monitor should have just the test context. 303 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 304 305 monitor_.ClearBrowsingData(CLEAR_CONTEXTS); 306 307 // Clearing contexts should leave the monitor with none. 308 EXPECT_EQ(0u, monitor_.contexts_size_for_testing()); 309} 310 311TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) { 312 RequestInfo request = MakeRequestInfo(); 313 request.url = GURL("http://example/always_report"); 314 request.status.set_error(net::ERR_QUIC_PROTOCOL_ERROR); 315 OnRequestLegComplete(request); 316 317 BeaconVector beacons; 318 context_->GetQueuedBeaconsForTesting(&beacons); 319 EXPECT_EQ(1u, beacons.size()); 320 EXPECT_EQ(net::OK, beacons[0].chrome_error); 321 322 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 323} 324 325TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSelf) { 326 DomainReliabilityContext* context = CreateAndAddContext("*.wildcard"); 327 328 RequestInfo request = MakeRequestInfo(); 329 request.url = GURL("http://wildcard/always_report"); 330 OnRequestLegComplete(request); 331 EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u)); 332} 333 334TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSubdomain) { 335 DomainReliabilityContext* context = CreateAndAddContext("*.wildcard"); 336 337 RequestInfo request = MakeRequestInfo(); 338 request.url = GURL("http://test.wildcard/always_report"); 339 OnRequestLegComplete(request); 340 EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u)); 341} 342 343TEST_F(DomainReliabilityMonitorTest, WildcardDoesntMatchSubsubdomain) { 344 DomainReliabilityContext* context = CreateAndAddContext("*.wildcard"); 345 346 RequestInfo request = MakeRequestInfo(); 347 request.url = GURL("http://test.test.wildcard/always_report"); 348 OnRequestLegComplete(request); 349 EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 0u, 0u)); 350} 351 352TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToSelfWildcard) { 353 DomainReliabilityContext* context1 = CreateAndAddContext("wildcard"); 354 DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard"); 355 356 RequestInfo request = MakeRequestInfo(); 357 request.url = GURL("http://wildcard/always_report"); 358 OnRequestLegComplete(request); 359 360 EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u)); 361 EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u)); 362} 363 364TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToParentWildcard) { 365 DomainReliabilityContext* context1 = CreateAndAddContext("test.wildcard"); 366 DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard"); 367 368 RequestInfo request = MakeRequestInfo(); 369 request.url = GURL("http://test.wildcard/always_report"); 370 OnRequestLegComplete(request); 371 372 EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u)); 373 EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u)); 374} 375 376TEST_F(DomainReliabilityMonitorTest, 377 WildcardPrefersSelfWildcardToParentWildcard) { 378 DomainReliabilityContext* context1 = CreateAndAddContext("*.test.wildcard"); 379 DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard"); 380 381 RequestInfo request = MakeRequestInfo(); 382 request.url = GURL("http://test.wildcard/always_report"); 383 OnRequestLegComplete(request); 384 385 EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u)); 386 EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u)); 387} 388 389} // namespace 390 391} // namespace domain_reliability 392