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