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 28 namespace domain_reliability { 29 30 namespace { 31 32 typedef std::vector<DomainReliabilityBeacon> BeaconVector; 33 34 static const size_t kAlwaysReportIndex = 0u; 35 static const size_t kNeverReportIndex = 1u; 36 37 scoped_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 46 class DomainReliabilityMonitorTest : public testing::Test { 47 protected: 48 typedef DomainReliabilityMonitor::RequestInfo RequestInfo; 49 50 DomainReliabilityMonitorTest() 51 : network_task_runner_(new base::TestSimpleTaskRunner()), 52 url_request_context_getter_( 53 new net::TestURLRequestContextGetter(network_task_runner_)), 54 time_(new MockTime()), 55 monitor_("test-reporter", scoped_ptr<MockableTime>(time_)), 56 context_(NULL) { 57 monitor_.Init(url_request_context_getter_); 58 context_ = monitor_.AddContextForTesting(MakeTestConfig()); 59 } 60 61 static RequestInfo MakeRequestInfo() { 62 RequestInfo request; 63 request.status = net::URLRequestStatus(); 64 request.status.set_status(net::URLRequestStatus::SUCCESS); 65 request.status.set_error(net::OK); 66 request.response_info.socket_address = 67 net::HostPortPair::FromString("12.34.56.78:80"); 68 request.response_info.headers = MakeHttpResponseHeaders( 69 "HTTP/1.1 200 OK\n\n"); 70 request.response_info.network_accessed = true; 71 request.response_info.was_fetched_via_proxy = false; 72 request.load_flags = 0; 73 request.is_upload = false; 74 return request; 75 } 76 77 void OnRequestLegComplete(const RequestInfo& info) { 78 monitor_.OnRequestLegComplete(info); 79 } 80 81 size_t CountPendingBeacons(size_t index) { 82 BeaconVector beacons; 83 context_->GetQueuedDataForTesting(index, &beacons, NULL, NULL); 84 return beacons.size(); 85 } 86 87 bool CheckRequestCounts(size_t index, 88 uint32 expected_successful, 89 uint32 expected_failed) { 90 uint32 successful, failed; 91 context_->GetQueuedDataForTesting(index, NULL, &successful, &failed); 92 EXPECT_EQ(expected_successful, successful); 93 EXPECT_EQ(expected_failed, failed); 94 return expected_successful == successful && expected_failed == failed; 95 } 96 97 scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_; 98 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 99 MockTime* time_; 100 DomainReliabilityMonitor monitor_; 101 DomainReliabilityContext* context_; 102 DomainReliabilityMonitor::RequestInfo request_; 103 }; 104 105 namespace { 106 107 TEST_F(DomainReliabilityMonitorTest, Create) { 108 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 109 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 110 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 111 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 112 } 113 114 TEST_F(DomainReliabilityMonitorTest, NoContext) { 115 RequestInfo request = MakeRequestInfo(); 116 request.url = GURL("http://no-context/"); 117 OnRequestLegComplete(request); 118 119 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 120 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 121 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 122 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 123 } 124 125 TEST_F(DomainReliabilityMonitorTest, NotReported) { 126 RequestInfo request = MakeRequestInfo(); 127 request.url = GURL("http://example/never_report"); 128 OnRequestLegComplete(request); 129 130 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 131 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 1u, 0u)); 132 } 133 134 TEST_F(DomainReliabilityMonitorTest, NetworkFailure) { 135 RequestInfo request = MakeRequestInfo(); 136 request.url = GURL("http://example/always_report"); 137 request.status.set_status(net::URLRequestStatus::FAILED); 138 request.status.set_error(net::ERR_CONNECTION_RESET); 139 request.response_info.headers = NULL; 140 OnRequestLegComplete(request); 141 142 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 143 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u)); 144 } 145 146 TEST_F(DomainReliabilityMonitorTest, ServerFailure) { 147 RequestInfo request = MakeRequestInfo(); 148 request.url = GURL("http://example/always_report"); 149 request.response_info.headers = 150 MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n"); 151 OnRequestLegComplete(request); 152 153 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 154 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u)); 155 } 156 157 TEST_F(DomainReliabilityMonitorTest, NotReportedFailure) { 158 RequestInfo request = MakeRequestInfo(); 159 request.url = GURL("http://example/never_report"); 160 request.status.set_status(net::URLRequestStatus::FAILED); 161 request.status.set_error(net::ERR_CONNECTION_RESET); 162 OnRequestLegComplete(request); 163 164 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 165 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 1u)); 166 } 167 168 TEST_F(DomainReliabilityMonitorTest, Request) { 169 RequestInfo request = MakeRequestInfo(); 170 request.url = GURL("http://example/always_report"); 171 OnRequestLegComplete(request); 172 173 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 174 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 175 } 176 177 // Make sure the monitor does not log requests that did not access the network. 178 TEST_F(DomainReliabilityMonitorTest, DidNotAccessNetwork) { 179 RequestInfo request = MakeRequestInfo(); 180 request.url = GURL("http://example/always_report"); 181 request.response_info.network_accessed = false; 182 OnRequestLegComplete(request); 183 184 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 185 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 186 } 187 188 // Make sure the monitor does not log requests that don't send cookies. 189 TEST_F(DomainReliabilityMonitorTest, DoNotSendCookies) { 190 RequestInfo request = MakeRequestInfo(); 191 request.url = GURL("http://example/always_report"); 192 request.load_flags = net::LOAD_DO_NOT_SEND_COOKIES; 193 OnRequestLegComplete(request); 194 195 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 196 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 197 } 198 199 // Make sure the monitor does not log upload requests. 200 TEST_F(DomainReliabilityMonitorTest, IsUpload) { 201 RequestInfo request = MakeRequestInfo(); 202 request.url = GURL("http://example/always_report"); 203 request.is_upload = true; 204 OnRequestLegComplete(request); 205 206 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 207 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 208 } 209 210 // Make sure the monitor does not log a network-local error. 211 TEST_F(DomainReliabilityMonitorTest, LocalError) { 212 RequestInfo request = MakeRequestInfo(); 213 request.url = GURL("http://example/always_report"); 214 request.status.set_status(net::URLRequestStatus::FAILED); 215 request.status.set_error(net::ERR_PROXY_CONNECTION_FAILED); 216 OnRequestLegComplete(request); 217 218 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 219 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 220 } 221 222 // Make sure the monitor does not log the proxy's IP if one was used. 223 TEST_F(DomainReliabilityMonitorTest, WasFetchedViaProxy) { 224 RequestInfo request = MakeRequestInfo(); 225 request.url = GURL("http://example/always_report"); 226 request.response_info.socket_address = 227 net::HostPortPair::FromString("127.0.0.1:3128"); 228 request.response_info.was_fetched_via_proxy = true; 229 OnRequestLegComplete(request); 230 231 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 232 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 233 234 BeaconVector beacons; 235 context_->GetQueuedDataForTesting(kAlwaysReportIndex, &beacons, NULL, NULL); 236 EXPECT_TRUE(beacons[0].server_ip.empty()); 237 } 238 239 TEST_F(DomainReliabilityMonitorTest, AddBakedInConfigs) { 240 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so 241 // this unittest will fail if someone tries to add an invalid config to the 242 // source tree. 243 monitor_.AddBakedInConfigs(); 244 245 // Count the number of baked-in configs. 246 size_t num_baked_in_configs = 0; 247 for (const char* const* p = kBakedInJsonConfigs; *p; ++p) 248 ++num_baked_in_configs; 249 250 // The monitor should have contexts for all of the baked-in configs, plus the 251 // test one added in the test constructor. 252 EXPECT_EQ(num_baked_in_configs + 1, monitor_.contexts_size_for_testing()); 253 } 254 255 TEST_F(DomainReliabilityMonitorTest, ClearBeacons) { 256 // Initially the monitor should have just the test context, with no beacons. 257 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 258 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 259 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 260 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 261 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 262 263 // Add a beacon. 264 RequestInfo request = MakeRequestInfo(); 265 request.url = GURL("http://example/always_report"); 266 OnRequestLegComplete(request); 267 268 // Make sure it was added. 269 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 270 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 271 272 monitor_.ClearBrowsingData(CLEAR_BEACONS); 273 274 // Make sure the beacon was cleared, but not the contexts. 275 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 276 EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex)); 277 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u)); 278 EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex)); 279 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u)); 280 } 281 282 TEST_F(DomainReliabilityMonitorTest, ClearContexts) { 283 // Initially the monitor should have just the test context. 284 EXPECT_EQ(1u, monitor_.contexts_size_for_testing()); 285 286 monitor_.ClearBrowsingData(CLEAR_CONTEXTS); 287 288 // Clearing contexts should leave the monitor with none. 289 EXPECT_EQ(0u, monitor_.contexts_size_for_testing()); 290 } 291 292 TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) { 293 RequestInfo request = MakeRequestInfo(); 294 request.url = GURL("http://example/always_report"); 295 request.status.set_error(net::ERR_QUIC_PROTOCOL_ERROR); 296 OnRequestLegComplete(request); 297 298 EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex)); 299 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u)); 300 301 BeaconVector beacons; 302 context_->GetQueuedDataForTesting(kAlwaysReportIndex, &beacons, NULL, NULL); 303 EXPECT_EQ(net::OK, beacons[0].chrome_error); 304 } 305 306 } // namespace 307 308 } // namespace domain_reliability 309