OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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 <string> |
| 6 |
| 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" |
| 9 #include "base/compiler_specific.h" |
| 10 #include "base/files/file_path.h" |
| 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/memory/weak_ptr.h" |
| 13 #include "base/message_loop.h" |
| 14 #include "base/path_service.h" |
| 15 #include "base/stringprintf.h" |
| 16 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 18 #include "chrome/common/chrome_paths.h" |
| 19 #include "chrome/test/base/in_process_browser_test.h" |
| 20 #include "chrome/test/base/ui_test_utils.h" |
| 21 #include "content/public/browser/browser_thread.h" |
| 22 #include "content/public/test/browser_test_utils.h" |
| 23 #include "googleurl/src/gurl.h" |
| 24 #include "net/base/load_timing_info.h" |
| 25 #include "net/test/test_server.h" |
| 26 #include "net/url_request/url_request_file_job.h" |
| 27 #include "net/url_request/url_request_filter.h" |
| 28 #include "net/url_request/url_request_job_factory.h" |
| 29 |
| 30 // This file tests that net::LoadTimingInfo is correctly hooked up to the |
| 31 // NavigationTiming API. It depends on behavior in a large number of files |
| 32 // spread across multiple projects, so is somewhat arbitrarily put in |
| 33 // chrome/browser/net. |
| 34 |
| 35 using content::BrowserThread; |
| 36 |
| 37 namespace { |
| 38 |
| 39 const char kTestDomain[] = "test.com"; |
| 40 const char kTestUrl[] = "http://test.com/"; |
| 41 |
| 42 // Relative times need to be used because: |
| 43 // 1) ExecuteScriptAndExtractInt does not support 64-bit integers. |
| 44 // 2) Times for tests are set before the request has been started, but need to |
| 45 // be set relative to the start time. |
| 46 // |
| 47 // Since some tests need to test negative time deltas (preconnected sockets) |
| 48 // and others need to test NULL times (events that don't apply), this class has |
| 49 // to be able to handle all cases: positive deltas, negative deltas, no |
| 50 // delta, and null times. |
| 51 class RelativeTime { |
| 52 public: |
| 53 // Constructor for null RelativeTimes. |
| 54 RelativeTime() : is_null_(true) { |
| 55 } |
| 56 |
| 57 // Constructor for non-null RelativeTimes. |
| 58 explicit RelativeTime(int delta_ms) |
| 59 : is_null_(false), |
| 60 delta_(base::TimeDelta::FromMilliseconds(delta_ms)) { |
| 61 } |
| 62 |
| 63 // Given a base time, returns the TimeTicks |this| identifies. |
| 64 base::TimeTicks ToTimeTicks(base::TimeTicks base_time) const { |
| 65 if (is_null_) |
| 66 return base::TimeTicks(); |
| 67 return base_time + delta_; |
| 68 } |
| 69 |
| 70 bool is_null() const { return is_null_; } |
| 71 |
| 72 base::TimeDelta GetDelta() const { |
| 73 // This allows tests to compare times that shouldn't be null without |
| 74 // explicitly null-testing them all first. |
| 75 EXPECT_FALSE(is_null_); |
| 76 return delta_; |
| 77 } |
| 78 |
| 79 private: |
| 80 bool is_null_; |
| 81 |
| 82 // Must be 0 when |is_null| is true. |
| 83 base::TimeDelta delta_; |
| 84 |
| 85 // This class is copyable and assignable. |
| 86 }; |
| 87 |
| 88 // Structure used for both setting the LoadTimingInfo used by mock requests |
| 89 // and for times retrieved from the renderer process. |
| 90 // |
| 91 // Times used for mock requests are all expressed as TimeDeltas relative to |
| 92 // request_start. Null RelativeTimes correspond to null TimeTicks(). |
| 93 // |
| 94 // Times read from the renderer are expressed relative to fetchStart (Which is |
| 95 // not the same as request_start). Null RelativeTimes correspond to times that |
| 96 // either cannot be retrieved (proxy times, send end) or times that are 0 (SSL |
| 97 // time when no new SSL connection was established). |
| 98 struct TimingDeltas { |
| 99 RelativeTime proxy_resolve_start; |
| 100 RelativeTime proxy_resolve_end; |
| 101 RelativeTime dns_start; |
| 102 RelativeTime dns_end; |
| 103 RelativeTime connect_start; |
| 104 RelativeTime ssl_start; |
| 105 RelativeTime connect_end; |
| 106 RelativeTime send_start; |
| 107 RelativeTime send_end; |
| 108 |
| 109 // Must be non-negative and greater than all other times. May only be null if |
| 110 // all other times are as well. |
| 111 RelativeTime receive_headers_end; |
| 112 }; |
| 113 |
| 114 // Mock UrlRequestJob that returns the contents of a specified file and |
| 115 // provides the specified load timing information when queried. |
| 116 class MockUrlRequestJobWithTiming : public net::URLRequestFileJob { |
| 117 public: |
| 118 MockUrlRequestJobWithTiming(net::URLRequest* request, |
| 119 net::NetworkDelegate* network_delegate, |
| 120 const base::FilePath& path, |
| 121 const TimingDeltas& load_timing_deltas) |
| 122 : net::URLRequestFileJob(request, network_delegate, path), |
| 123 load_timing_deltas_(load_timing_deltas), |
| 124 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 125 } |
| 126 |
| 127 // net::URLRequestFileJob implementation: |
| 128 virtual void Start() OVERRIDE { |
| 129 base::TimeDelta time_to_wait; |
| 130 if (!load_timing_deltas_.receive_headers_end.is_null()) { |
| 131 // Need to delay starting until the largest of the times has elapsed. |
| 132 // Wait a little longer than necessary, to be on the safe side. |
| 133 time_to_wait = load_timing_deltas_.receive_headers_end.GetDelta() + |
| 134 base::TimeDelta::FromMilliseconds(100); |
| 135 } |
| 136 |
| 137 MessageLoop::current()->PostDelayedTask( |
| 138 FROM_HERE, |
| 139 base::Bind(&MockUrlRequestJobWithTiming::DelayedStart, |
| 140 weak_factory_.GetWeakPtr()), |
| 141 time_to_wait); |
| 142 } |
| 143 |
| 144 virtual void GetLoadTimingInfo( |
| 145 net::LoadTimingInfo* load_timing_info) const OVERRIDE { |
| 146 // This should have been set by the URLRequest. |
| 147 base::TimeTicks request_start = load_timing_info->request_start; |
| 148 ASSERT_FALSE(request_start.is_null()); |
| 149 |
| 150 // Make sure enough time has elapsed since start was called. If this |
| 151 // fails, the test fixture itself is flaky. |
| 152 if (!load_timing_deltas_.receive_headers_end.is_null()) { |
| 153 EXPECT_LE( |
| 154 request_start + load_timing_deltas_.receive_headers_end.GetDelta(), |
| 155 base::TimeTicks::Now()); |
| 156 } |
| 157 |
| 158 // If there are no connect times, but there is a receive headers end time, |
| 159 // then assume the socket is reused. This shouldn't affect the load timing |
| 160 // information the test checks, just done for completeness. |
| 161 load_timing_info->socket_reused = false; |
| 162 if (load_timing_deltas_.connect_start.is_null() && |
| 163 !load_timing_deltas_.receive_headers_end.is_null()) { |
| 164 load_timing_info->socket_reused = true; |
| 165 } |
| 166 |
| 167 load_timing_info->proxy_resolve_start = |
| 168 load_timing_deltas_.proxy_resolve_start.ToTimeTicks(request_start); |
| 169 load_timing_info->proxy_resolve_end = |
| 170 load_timing_deltas_.proxy_resolve_end.ToTimeTicks(request_start); |
| 171 |
| 172 load_timing_info->connect_timing.dns_start = |
| 173 load_timing_deltas_.dns_start.ToTimeTicks(request_start); |
| 174 load_timing_info->connect_timing.dns_end = |
| 175 load_timing_deltas_.dns_end.ToTimeTicks(request_start); |
| 176 load_timing_info->connect_timing.connect_start = |
| 177 load_timing_deltas_.connect_start.ToTimeTicks(request_start); |
| 178 load_timing_info->connect_timing.ssl_start = |
| 179 load_timing_deltas_.ssl_start.ToTimeTicks(request_start); |
| 180 load_timing_info->connect_timing.connect_end = |
| 181 load_timing_deltas_.connect_end.ToTimeTicks(request_start); |
| 182 |
| 183 // If there's an SSL start time, use connect end as the SSL end time. |
| 184 // The NavigationTiming API does not have a corresponding field, and there's |
| 185 // no need to test the case when the values are both non-NULL and different. |
| 186 if (!load_timing_deltas_.ssl_start.is_null()) { |
| 187 load_timing_info->connect_timing.ssl_end = |
| 188 load_timing_info->connect_timing.connect_end; |
| 189 } |
| 190 |
| 191 load_timing_info->send_start = |
| 192 load_timing_deltas_.send_start.ToTimeTicks(request_start); |
| 193 load_timing_info->send_end= |
| 194 load_timing_deltas_.send_end.ToTimeTicks(request_start); |
| 195 load_timing_info->receive_headers_end = |
| 196 load_timing_deltas_.receive_headers_end.ToTimeTicks(request_start); |
| 197 } |
| 198 |
| 199 private: |
| 200 // Parent class is reference counted, so need to have a private destructor. |
| 201 virtual ~MockUrlRequestJobWithTiming() {} |
| 202 |
| 203 void DelayedStart() { |
| 204 net::URLRequestFileJob::Start(); |
| 205 } |
| 206 |
| 207 // Load times to use, relative to request_start from the URLRequest. |
| 208 const TimingDeltas load_timing_deltas_; |
| 209 |
| 210 base::WeakPtrFactory<MockUrlRequestJobWithTiming> weak_factory_; |
| 211 |
| 212 DISALLOW_COPY_AND_ASSIGN(MockUrlRequestJobWithTiming); |
| 213 }; |
| 214 |
| 215 // A protocol handler that returns mock URLRequestJobs that return the specified |
| 216 // file with the given timings. Constructed on the UI thread, but after that, |
| 217 // lives and is destroyed on the IO thread. |
| 218 class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { |
| 219 public: |
| 220 TestProtocolHandler(const base::FilePath& path, |
| 221 const TimingDeltas& load_timing_deltas) |
| 222 : path_(path), load_timing_deltas_(load_timing_deltas) { |
| 223 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 224 } |
| 225 |
| 226 virtual ~TestProtocolHandler() { |
| 227 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 228 } |
| 229 |
| 230 // Registers |this| with the URLRequestFilter, which takes ownership of it. |
| 231 void Register() { |
| 232 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 233 net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler( |
| 234 "http", kTestDomain, |
| 235 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this)); |
| 236 } |
| 237 |
| 238 // Unregisters |this| with the URLRequestFilter, which should then delete |
| 239 // |this|. |
| 240 void Unregister() { |
| 241 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 242 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler( |
| 243 "http", kTestDomain); |
| 244 } |
| 245 |
| 246 // net::URLRequestJobFactory::ProtocolHandler implementation: |
| 247 virtual net::URLRequestJob* MaybeCreateJob( |
| 248 net::URLRequest* request, |
| 249 net::NetworkDelegate* network_delegate) const OVERRIDE { |
| 250 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 251 |
| 252 return new MockUrlRequestJobWithTiming(request, network_delegate, path_, |
| 253 load_timing_deltas_); |
| 254 } |
| 255 |
| 256 private: |
| 257 // Path of the file to use as the response body. |
| 258 const base::FilePath path_; |
| 259 |
| 260 // Load times for each request to use, relative to their request_start times. |
| 261 const TimingDeltas load_timing_deltas_; |
| 262 |
| 263 DISALLOW_COPY_AND_ASSIGN(TestProtocolHandler); |
| 264 }; |
| 265 |
| 266 class LoadTimingBrowserTest : public InProcessBrowserTest { |
| 267 public: |
| 268 LoadTimingBrowserTest() { |
| 269 } |
| 270 |
| 271 virtual ~LoadTimingBrowserTest() { |
| 272 } |
| 273 |
| 274 // Navigates to |url| and writes the resulting navigation timings to |
| 275 // |navigation_deltas|. |
| 276 void RunTestWithUrl(const GURL& url, TimingDeltas* navigation_deltas) { |
| 277 ui_test_utils::NavigateToURL(browser(), url); |
| 278 GetResultDeltas(navigation_deltas); |
| 279 } |
| 280 |
| 281 // Navigates to a url that returns the timings indicated by |
| 282 // |load_timing_deltas| and writes the resulting navigation timings to |
| 283 // |navigation_deltas|. Uses a generic test page. |
| 284 void RunTest(const TimingDeltas& load_timing_deltas, |
| 285 TimingDeltas* navigation_deltas) { |
| 286 // None of the tests care about the contents of the test page. Just do |
| 287 // this here because PathService has thread restrictions on some platforms. |
| 288 base::FilePath path; |
| 289 PathService::Get(chrome::DIR_TEST_DATA, &path); |
| 290 path = path.AppendASCII("title1.html"); |
| 291 |
| 292 // Create and register protocol handler. |
| 293 TestProtocolHandler* protocol_handler = |
| 294 new TestProtocolHandler(path, load_timing_deltas); |
| 295 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 296 base::Bind(&TestProtocolHandler::Register, |
| 297 base::Unretained(protocol_handler))); |
| 298 |
| 299 // Navigate to the page. |
| 300 RunTestWithUrl(GURL(kTestUrl), navigation_deltas); |
| 301 |
| 302 // Once navigation is complete, unregister the protocol handler. |
| 303 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 304 base::Bind(&TestProtocolHandler::Unregister, |
| 305 base::Unretained(protocol_handler))); |
| 306 } |
| 307 |
| 308 private: |
| 309 // Reads applicable times from performance.timing and writes them to |
| 310 // |navigation_deltas|. Proxy times and send end cannot be read from the |
| 311 // Navigation Timing API, so those are all left as null. |
| 312 void GetResultDeltas(TimingDeltas* navigation_deltas) { |
| 313 *navigation_deltas = TimingDeltas(); |
| 314 |
| 315 navigation_deltas->dns_start = GetResultDelta("domainLookupStart"); |
| 316 navigation_deltas->dns_end = GetResultDelta("domainLookupEnd"); |
| 317 navigation_deltas->connect_start = GetResultDelta("connectStart"); |
| 318 navigation_deltas->connect_end = GetResultDelta("connectEnd"); |
| 319 navigation_deltas->send_start = GetResultDelta("requestStart"); |
| 320 navigation_deltas->receive_headers_end = GetResultDelta("responseStart"); |
| 321 |
| 322 // Unlike the above times, secureConnectionStart will be zero when not |
| 323 // applicable. In that case, leave ssl_start as null. |
| 324 bool ssl_start_zero = false; |
| 325 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( |
| 326 browser()->tab_strip_model()->GetActiveWebContents(), |
| 327 "window.domAutomationController.send(" |
| 328 "performance.timing.secureConnectionStart == 0);", |
| 329 &ssl_start_zero)); |
| 330 if (!ssl_start_zero) |
| 331 navigation_deltas->ssl_start = GetResultDelta("secureConnectionStart"); |
| 332 |
| 333 // Simple sanity checks. Make sure times that correspond to LoadTimingInfo |
| 334 // occur between fetchStart and loadEventEnd. Relationships between |
| 335 // intervening times are handled by the test bodies. |
| 336 |
| 337 RelativeTime fetch_start = GetResultDelta("fetchStart"); |
| 338 // While the input dns_start is sometimes null, when read from the |
| 339 // NavigationTiming API, it's always non-null. |
| 340 EXPECT_LE(fetch_start.GetDelta(), navigation_deltas->dns_start.GetDelta()); |
| 341 |
| 342 RelativeTime load_event_end = GetResultDelta("loadEventEnd"); |
| 343 EXPECT_LE(navigation_deltas->receive_headers_end.GetDelta(), |
| 344 load_event_end.GetDelta()); |
| 345 } |
| 346 |
| 347 // Returns the time between performance.timing.fetchStart and the time with |
| 348 // the specified name. This time must be non-negative. |
| 349 RelativeTime GetResultDelta(const std::string& name) { |
| 350 int time_ms = 0; |
| 351 std::string command(base::StringPrintf( |
| 352 "window.domAutomationController.send(" |
| 353 "performance.timing.%s - performance.timing.fetchStart);", |
| 354 name.c_str())); |
| 355 EXPECT_TRUE(content::ExecuteScriptAndExtractInt( |
| 356 browser()->tab_strip_model()->GetActiveWebContents(), |
| 357 command.c_str(), |
| 358 &time_ms)); |
| 359 |
| 360 // Basic sanity check. |
| 361 EXPECT_GE(time_ms, 0); |
| 362 |
| 363 return RelativeTime(time_ms); |
| 364 } |
| 365 }; |
| 366 |
| 367 // Test case when no times are given, except the request start times. This |
| 368 // happens with FTP, cached responses, responses handled by something other than |
| 369 // the network stack, RedirectJobs, HSTs, etc. |
| 370 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, NoTimes) { |
| 371 TimingDeltas load_timing_deltas; |
| 372 TimingDeltas navigation_deltas; |
| 373 RunTest(load_timing_deltas, &navigation_deltas); |
| 374 |
| 375 // When there are no times, all read times should be the same as fetchStart, |
| 376 // except SSL start, which should be 0. |
| 377 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta()); |
| 378 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta()); |
| 379 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta()); |
| 380 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta()); |
| 381 EXPECT_EQ(base::TimeDelta(), navigation_deltas.send_start.GetDelta()); |
| 382 EXPECT_EQ(base::TimeDelta(), |
| 383 navigation_deltas.receive_headers_end.GetDelta()); |
| 384 |
| 385 EXPECT_TRUE(navigation_deltas.ssl_start.is_null()); |
| 386 } |
| 387 |
| 388 // Standard case - new socket, no PAC, no preconnect, no SSL. |
| 389 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Basic) { |
| 390 TimingDeltas load_timing_deltas; |
| 391 load_timing_deltas.dns_start = RelativeTime(0); |
| 392 load_timing_deltas.dns_end = RelativeTime(100); |
| 393 load_timing_deltas.connect_start = RelativeTime(200); |
| 394 load_timing_deltas.connect_end = RelativeTime(300); |
| 395 load_timing_deltas.send_start = RelativeTime(400); |
| 396 load_timing_deltas.send_end = RelativeTime(500); |
| 397 load_timing_deltas.receive_headers_end = RelativeTime(600); |
| 398 |
| 399 TimingDeltas navigation_deltas; |
| 400 RunTest(load_timing_deltas, &navigation_deltas); |
| 401 |
| 402 // Due to potential roundoff issues, never check exact differences. |
| 403 EXPECT_LT(navigation_deltas.dns_start.GetDelta(), |
| 404 navigation_deltas.dns_end.GetDelta()); |
| 405 EXPECT_LT(navigation_deltas.dns_end.GetDelta(), |
| 406 navigation_deltas.connect_start.GetDelta()); |
| 407 EXPECT_LT(navigation_deltas.connect_start.GetDelta(), |
| 408 navigation_deltas.connect_end.GetDelta()); |
| 409 EXPECT_LT(navigation_deltas.connect_end.GetDelta(), |
| 410 navigation_deltas.send_start.GetDelta()); |
| 411 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 412 navigation_deltas.receive_headers_end.GetDelta()); |
| 413 |
| 414 EXPECT_TRUE(navigation_deltas.ssl_start.is_null()); |
| 415 } |
| 416 |
| 417 // Basic SSL case. |
| 418 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Ssl) { |
| 419 TimingDeltas load_timing_deltas; |
| 420 load_timing_deltas.dns_start = RelativeTime(0); |
| 421 load_timing_deltas.dns_end = RelativeTime(100); |
| 422 load_timing_deltas.connect_start = RelativeTime(200); |
| 423 load_timing_deltas.ssl_start = RelativeTime(300); |
| 424 load_timing_deltas.connect_end = RelativeTime(400); |
| 425 load_timing_deltas.send_start = RelativeTime(500); |
| 426 load_timing_deltas.send_end = RelativeTime(600); |
| 427 load_timing_deltas.receive_headers_end = RelativeTime(700); |
| 428 |
| 429 TimingDeltas navigation_deltas; |
| 430 RunTest(load_timing_deltas, &navigation_deltas); |
| 431 |
| 432 // Due to potential roundoff issues, never check exact differences. |
| 433 EXPECT_LT(navigation_deltas.dns_start.GetDelta(), |
| 434 navigation_deltas.dns_end.GetDelta()); |
| 435 EXPECT_LT(navigation_deltas.dns_end.GetDelta(), |
| 436 navigation_deltas.connect_start.GetDelta()); |
| 437 EXPECT_LT(navigation_deltas.connect_start.GetDelta(), |
| 438 navigation_deltas.ssl_start.GetDelta()); |
| 439 EXPECT_LT(navigation_deltas.ssl_start.GetDelta(), |
| 440 navigation_deltas.connect_end.GetDelta()); |
| 441 EXPECT_LT(navigation_deltas.connect_end.GetDelta(), |
| 442 navigation_deltas.send_start.GetDelta()); |
| 443 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 444 navigation_deltas.receive_headers_end.GetDelta()); |
| 445 } |
| 446 |
| 447 // All times are the same. |
| 448 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, EverythingAtOnce) { |
| 449 TimingDeltas load_timing_deltas; |
| 450 load_timing_deltas.dns_start = RelativeTime(100); |
| 451 load_timing_deltas.dns_end = RelativeTime(100); |
| 452 load_timing_deltas.connect_start = RelativeTime(100); |
| 453 load_timing_deltas.ssl_start = RelativeTime(100); |
| 454 load_timing_deltas.connect_end = RelativeTime(100); |
| 455 load_timing_deltas.send_start = RelativeTime(100); |
| 456 load_timing_deltas.send_end = RelativeTime(100); |
| 457 load_timing_deltas.receive_headers_end = RelativeTime(100); |
| 458 |
| 459 TimingDeltas navigation_deltas; |
| 460 RunTest(load_timing_deltas, &navigation_deltas); |
| 461 |
| 462 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 463 navigation_deltas.dns_end.GetDelta()); |
| 464 EXPECT_EQ(navigation_deltas.dns_end.GetDelta(), |
| 465 navigation_deltas.connect_start.GetDelta()); |
| 466 EXPECT_EQ(navigation_deltas.connect_start.GetDelta(), |
| 467 navigation_deltas.ssl_start.GetDelta()); |
| 468 EXPECT_EQ(navigation_deltas.ssl_start.GetDelta(), |
| 469 navigation_deltas.connect_end.GetDelta()); |
| 470 EXPECT_EQ(navigation_deltas.connect_end.GetDelta(), |
| 471 navigation_deltas.send_start.GetDelta()); |
| 472 EXPECT_EQ(navigation_deltas.send_start.GetDelta(), |
| 473 navigation_deltas.receive_headers_end.GetDelta()); |
| 474 } |
| 475 |
| 476 // Reuse case. |
| 477 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, ReuseSocket) { |
| 478 TimingDeltas load_timing_deltas; |
| 479 load_timing_deltas.send_start = RelativeTime(0); |
| 480 load_timing_deltas.send_end = RelativeTime(100); |
| 481 load_timing_deltas.receive_headers_end = RelativeTime(200); |
| 482 |
| 483 TimingDeltas navigation_deltas; |
| 484 RunTest(load_timing_deltas, &navigation_deltas); |
| 485 |
| 486 // Connect times should all be the same as fetchStart. |
| 487 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta()); |
| 488 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta()); |
| 489 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta()); |
| 490 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta()); |
| 491 |
| 492 // Connect end may be less than send start, since connect end defaults to |
| 493 // fetchStart, which is often less than request_start. |
| 494 EXPECT_LE(navigation_deltas.connect_end.GetDelta(), |
| 495 navigation_deltas.send_start.GetDelta()); |
| 496 |
| 497 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 498 navigation_deltas.receive_headers_end.GetDelta()); |
| 499 |
| 500 EXPECT_TRUE(navigation_deltas.ssl_start.is_null()); |
| 501 } |
| 502 |
| 503 // Preconnect case. Connect times are all before the request was started. |
| 504 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Preconnect) { |
| 505 TimingDeltas load_timing_deltas; |
| 506 load_timing_deltas.dns_start = RelativeTime(-100300); |
| 507 load_timing_deltas.dns_end = RelativeTime(-100200); |
| 508 load_timing_deltas.connect_start = RelativeTime(-100100); |
| 509 load_timing_deltas.connect_end = RelativeTime(-100000); |
| 510 load_timing_deltas.send_start = RelativeTime(0); |
| 511 load_timing_deltas.send_end = RelativeTime(100); |
| 512 load_timing_deltas.receive_headers_end = RelativeTime(200); |
| 513 |
| 514 TimingDeltas navigation_deltas; |
| 515 RunTest(load_timing_deltas, &navigation_deltas); |
| 516 |
| 517 // Connect times should all be the same as request_start, which is also the |
| 518 // same as send_start (Since send_start is 0). |
| 519 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 520 navigation_deltas.dns_end.GetDelta()); |
| 521 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 522 navigation_deltas.connect_start.GetDelta()); |
| 523 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 524 navigation_deltas.connect_end.GetDelta()); |
| 525 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 526 navigation_deltas.send_start.GetDelta()); |
| 527 |
| 528 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 529 navigation_deltas.receive_headers_end.GetDelta()); |
| 530 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 531 navigation_deltas.receive_headers_end.GetDelta()); |
| 532 |
| 533 EXPECT_TRUE(navigation_deltas.ssl_start.is_null()); |
| 534 } |
| 535 |
| 536 // Preconnect case with a proxy. Connect times are all before the proxy lookup |
| 537 // finished (Or at the same time). |
| 538 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, PreconnectProxySsl) { |
| 539 TimingDeltas load_timing_deltas; |
| 540 load_timing_deltas.proxy_resolve_start = RelativeTime(0); |
| 541 load_timing_deltas.proxy_resolve_end = RelativeTime(100); |
| 542 load_timing_deltas.dns_start = RelativeTime(-300); |
| 543 load_timing_deltas.dns_end = RelativeTime(-200); |
| 544 load_timing_deltas.connect_start = RelativeTime(-100); |
| 545 load_timing_deltas.ssl_start = RelativeTime(0); |
| 546 load_timing_deltas.connect_end = RelativeTime(100); |
| 547 load_timing_deltas.send_start = RelativeTime(100); |
| 548 load_timing_deltas.send_end = RelativeTime(200); |
| 549 load_timing_deltas.receive_headers_end = RelativeTime(300); |
| 550 |
| 551 TimingDeltas navigation_deltas; |
| 552 RunTest(load_timing_deltas, &navigation_deltas); |
| 553 |
| 554 // Connect times should all be the same as proxy_end, which is also the |
| 555 // same as send_start. |
| 556 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 557 navigation_deltas.dns_end.GetDelta()); |
| 558 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 559 navigation_deltas.connect_start.GetDelta()); |
| 560 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 561 navigation_deltas.ssl_start.GetDelta()); |
| 562 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 563 navigation_deltas.connect_end.GetDelta()); |
| 564 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(), |
| 565 navigation_deltas.send_start.GetDelta()); |
| 566 |
| 567 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 568 navigation_deltas.receive_headers_end.GetDelta()); |
| 569 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 570 navigation_deltas.receive_headers_end.GetDelta()); |
| 571 } |
| 572 |
| 573 // Integration test with a real network response. |
| 574 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Integration) { |
| 575 ASSERT_TRUE(test_server()->Start()); |
| 576 TimingDeltas navigation_deltas; |
| 577 RunTestWithUrl(test_server()->GetURL("chunked?waitBeforeHeaders=100"), |
| 578 &navigation_deltas); |
| 579 |
| 580 // Due to potential roundoff issues, never check exact differences. |
| 581 EXPECT_LE(navigation_deltas.dns_start.GetDelta(), |
| 582 navigation_deltas.dns_end.GetDelta()); |
| 583 EXPECT_LE(navigation_deltas.dns_end.GetDelta(), |
| 584 navigation_deltas.connect_start.GetDelta()); |
| 585 EXPECT_LE(navigation_deltas.connect_start.GetDelta(), |
| 586 navigation_deltas.connect_end.GetDelta()); |
| 587 EXPECT_LE(navigation_deltas.connect_end.GetDelta(), |
| 588 navigation_deltas.send_start.GetDelta()); |
| 589 // The only times that are guaranteed to be distinct are send_start and |
| 590 // received_headers end. |
| 591 EXPECT_LT(navigation_deltas.send_start.GetDelta(), |
| 592 navigation_deltas.receive_headers_end.GetDelta()); |
| 593 |
| 594 EXPECT_TRUE(navigation_deltas.ssl_start.is_null()); |
| 595 } |
| 596 |
| 597 } // namespace |
OLD | NEW |