Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / net / load_timing_browsertest.cc
blob51963fe5bf4f119659cab9fad0716adbe67e99a8
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.
5 #include <string>
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_job_factory.h"
29 #include "url/gurl.h"
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.
36 using content::BrowserThread;
38 namespace {
40 const char kTestDomain[] = "test.com";
41 const char kTestUrl[] = "http://test.com/";
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.
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.
52 class RelativeTime {
53 public:
54 // Constructor for null RelativeTimes.
55 RelativeTime() : is_null_(true) {
58 // Constructor for non-null RelativeTimes.
59 explicit RelativeTime(int delta_ms)
60 : is_null_(false),
61 delta_(base::TimeDelta::FromMilliseconds(delta_ms)) {
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_;
71 bool is_null() const { return is_null_; }
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_;
80 private:
81 bool is_null_;
83 // Must be 0 when |is_null| is true.
84 base::TimeDelta delta_;
86 // This class is copyable and assignable.
89 // Structure used for both setting the LoadTimingInfo used by mock requests
90 // and for times retrieved from the renderer process.
92 // Times used for mock requests are all expressed as TimeDeltas relative to
93 // when the Job starts. Null RelativeTimes correspond to null TimeTicks().
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).
99 struct 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;
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;
115 // Mock UrlRequestJob that returns the contents of a specified file and
116 // provides the specified load timing information when queried.
117 class 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) {}
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);
142 base::MessageLoop::current()->PostDelayedTask(
143 FROM_HERE,
144 base::Bind(&MockUrlRequestJobWithTiming::DelayedStart,
145 weak_factory_.GetWeakPtr()),
146 time_to_wait);
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());
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;
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_);
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_);
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;
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_);
200 private:
201 // Parent class is reference counted, so need to have a private destructor.
202 virtual ~MockUrlRequestJobWithTiming() {}
204 void DelayedStart() {
205 net::URLRequestFileJob::Start();
208 // Load times to use, relative to |start_time_|.
209 const TimingDeltas load_timing_deltas_;
210 base::TimeTicks start_time_;
212 base::WeakPtrFactory<MockUrlRequestJobWithTiming> weak_factory_;
214 DISALLOW_COPY_AND_ASSIGN(MockUrlRequestJobWithTiming);
217 // A protocol handler that returns mock URLRequestJobs that return the specified
218 // file with the given timings. Constructed on the UI thread, but after that,
219 // lives and is destroyed on the IO thread.
220 class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
221 public:
222 TestProtocolHandler(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));
228 virtual ~TestProtocolHandler() {
229 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
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()->AddHostnameProtocolHandler(
236 "http", kTestDomain,
237 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this));
240 // Unregisters |this| with the URLRequestFilter, which should then delete
241 // |this|.
242 void Unregister() {
243 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
244 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(
245 "http", kTestDomain);
248 // net::URLRequestJobFactory::ProtocolHandler implementation:
249 virtual net::URLRequestJob* MaybeCreateJob(
250 net::URLRequest* request,
251 net::NetworkDelegate* network_delegate) const OVERRIDE {
252 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
254 return new MockUrlRequestJobWithTiming(request, network_delegate, path_,
255 load_timing_deltas_);
258 private:
259 // Path of the file to use as the response body.
260 const base::FilePath path_;
262 // Load times for each request to use, relative to when the Job starts.
263 const TimingDeltas load_timing_deltas_;
265 DISALLOW_COPY_AND_ASSIGN(TestProtocolHandler);
268 class LoadTimingBrowserTest : public InProcessBrowserTest {
269 public:
270 LoadTimingBrowserTest() {
273 virtual ~LoadTimingBrowserTest() {
276 // Navigates to |url| and writes the resulting navigation timings to
277 // |navigation_deltas|.
278 void RunTestWithUrl(const GURL& url, TimingDeltas* navigation_deltas) {
279 ui_test_utils::NavigateToURL(browser(), url);
280 GetResultDeltas(navigation_deltas);
283 // Navigates to a url that returns the timings indicated by
284 // |load_timing_deltas| and writes the resulting navigation timings to
285 // |navigation_deltas|. Uses a generic test page.
286 void RunTest(const TimingDeltas& load_timing_deltas,
287 TimingDeltas* navigation_deltas) {
288 // None of the tests care about the contents of the test page. Just do
289 // this here because PathService has thread restrictions on some platforms.
290 base::FilePath path;
291 PathService::Get(chrome::DIR_TEST_DATA, &path);
292 path = path.AppendASCII("title1.html");
294 // Create and register protocol handler.
295 TestProtocolHandler* protocol_handler =
296 new TestProtocolHandler(path, load_timing_deltas);
297 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
298 base::Bind(&TestProtocolHandler::Register,
299 base::Unretained(protocol_handler)));
301 // Navigate to the page.
302 RunTestWithUrl(GURL(kTestUrl), navigation_deltas);
304 // Once navigation is complete, unregister the protocol handler.
305 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
306 base::Bind(&TestProtocolHandler::Unregister,
307 base::Unretained(protocol_handler)));
310 private:
311 // Reads applicable times from performance.timing and writes them to
312 // |navigation_deltas|. Proxy times and send end cannot be read from the
313 // Navigation Timing API, so those are all left as null.
314 void GetResultDeltas(TimingDeltas* navigation_deltas) {
315 *navigation_deltas = TimingDeltas();
317 navigation_deltas->dns_start = GetResultDelta("domainLookupStart");
318 navigation_deltas->dns_end = GetResultDelta("domainLookupEnd");
319 navigation_deltas->connect_start = GetResultDelta("connectStart");
320 navigation_deltas->connect_end = GetResultDelta("connectEnd");
321 navigation_deltas->send_start = GetResultDelta("requestStart");
322 navigation_deltas->receive_headers_end = GetResultDelta("responseStart");
324 // Unlike the above times, secureConnectionStart will be zero when not
325 // applicable. In that case, leave ssl_start as null.
326 bool ssl_start_zero = false;
327 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
328 browser()->tab_strip_model()->GetActiveWebContents(),
329 "window.domAutomationController.send("
330 "performance.timing.secureConnectionStart == 0);",
331 &ssl_start_zero));
332 if (!ssl_start_zero)
333 navigation_deltas->ssl_start = GetResultDelta("secureConnectionStart");
335 // Simple sanity checks. Make sure times that correspond to LoadTimingInfo
336 // occur between fetchStart and loadEventEnd. Relationships between
337 // intervening times are handled by the test bodies.
339 RelativeTime fetch_start = GetResultDelta("fetchStart");
340 // While the input dns_start is sometimes null, when read from the
341 // NavigationTiming API, it's always non-null.
342 EXPECT_LE(fetch_start.GetDelta(), navigation_deltas->dns_start.GetDelta());
344 RelativeTime load_event_end = GetResultDelta("loadEventEnd");
345 EXPECT_LE(navigation_deltas->receive_headers_end.GetDelta(),
346 load_event_end.GetDelta());
349 // Returns the time between performance.timing.fetchStart and the time with
350 // the specified name. This time must be non-negative.
351 RelativeTime GetResultDelta(const std::string& name) {
352 int time_ms = 0;
353 std::string command(base::StringPrintf(
354 "window.domAutomationController.send("
355 "performance.timing.%s - performance.timing.fetchStart);",
356 name.c_str()));
357 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
358 browser()->tab_strip_model()->GetActiveWebContents(),
359 command.c_str(),
360 &time_ms));
362 // Basic sanity check.
363 EXPECT_GE(time_ms, 0);
365 return RelativeTime(time_ms);
369 // Test case when no times are given, except the request start times. This
370 // happens with FTP, cached responses, responses handled by something other than
371 // the network stack, RedirectJobs, HSTs, etc.
372 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, NoTimes) {
373 TimingDeltas load_timing_deltas;
374 TimingDeltas navigation_deltas;
375 RunTest(load_timing_deltas, &navigation_deltas);
377 // When there are no times, all read times should be the same as fetchStart,
378 // except SSL start, which should be 0.
379 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
380 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
381 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
382 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
383 EXPECT_EQ(base::TimeDelta(), navigation_deltas.send_start.GetDelta());
384 EXPECT_EQ(base::TimeDelta(),
385 navigation_deltas.receive_headers_end.GetDelta());
387 EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
390 // Standard case - new socket, no PAC, no preconnect, no SSL.
391 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Basic) {
392 TimingDeltas load_timing_deltas;
393 load_timing_deltas.dns_start = RelativeTime(0);
394 load_timing_deltas.dns_end = RelativeTime(100);
395 load_timing_deltas.connect_start = RelativeTime(200);
396 load_timing_deltas.connect_end = RelativeTime(300);
397 load_timing_deltas.send_start = RelativeTime(400);
398 load_timing_deltas.send_end = RelativeTime(500);
399 load_timing_deltas.receive_headers_end = RelativeTime(600);
401 TimingDeltas navigation_deltas;
402 RunTest(load_timing_deltas, &navigation_deltas);
404 // Due to potential roundoff issues, never check exact differences.
405 EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
406 navigation_deltas.dns_end.GetDelta());
407 EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
408 navigation_deltas.connect_start.GetDelta());
409 EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
410 navigation_deltas.connect_end.GetDelta());
411 EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
412 navigation_deltas.send_start.GetDelta());
413 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
414 navigation_deltas.receive_headers_end.GetDelta());
416 EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
419 // Basic SSL case.
420 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Ssl) {
421 TimingDeltas load_timing_deltas;
422 load_timing_deltas.dns_start = RelativeTime(0);
423 load_timing_deltas.dns_end = RelativeTime(100);
424 load_timing_deltas.connect_start = RelativeTime(200);
425 load_timing_deltas.ssl_start = RelativeTime(300);
426 load_timing_deltas.connect_end = RelativeTime(400);
427 load_timing_deltas.send_start = RelativeTime(500);
428 load_timing_deltas.send_end = RelativeTime(600);
429 load_timing_deltas.receive_headers_end = RelativeTime(700);
431 TimingDeltas navigation_deltas;
432 RunTest(load_timing_deltas, &navigation_deltas);
434 // Due to potential roundoff issues, never check exact differences.
435 EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
436 navigation_deltas.dns_end.GetDelta());
437 EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
438 navigation_deltas.connect_start.GetDelta());
439 EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
440 navigation_deltas.ssl_start.GetDelta());
441 EXPECT_LT(navigation_deltas.ssl_start.GetDelta(),
442 navigation_deltas.connect_end.GetDelta());
443 EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
444 navigation_deltas.send_start.GetDelta());
445 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
446 navigation_deltas.receive_headers_end.GetDelta());
449 // All times are the same.
450 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, EverythingAtOnce) {
451 TimingDeltas load_timing_deltas;
452 load_timing_deltas.dns_start = RelativeTime(100);
453 load_timing_deltas.dns_end = RelativeTime(100);
454 load_timing_deltas.connect_start = RelativeTime(100);
455 load_timing_deltas.ssl_start = RelativeTime(100);
456 load_timing_deltas.connect_end = RelativeTime(100);
457 load_timing_deltas.send_start = RelativeTime(100);
458 load_timing_deltas.send_end = RelativeTime(100);
459 load_timing_deltas.receive_headers_end = RelativeTime(100);
461 TimingDeltas navigation_deltas;
462 RunTest(load_timing_deltas, &navigation_deltas);
464 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
465 navigation_deltas.dns_end.GetDelta());
466 EXPECT_EQ(navigation_deltas.dns_end.GetDelta(),
467 navigation_deltas.connect_start.GetDelta());
468 EXPECT_EQ(navigation_deltas.connect_start.GetDelta(),
469 navigation_deltas.ssl_start.GetDelta());
470 EXPECT_EQ(navigation_deltas.ssl_start.GetDelta(),
471 navigation_deltas.connect_end.GetDelta());
472 EXPECT_EQ(navigation_deltas.connect_end.GetDelta(),
473 navigation_deltas.send_start.GetDelta());
474 EXPECT_EQ(navigation_deltas.send_start.GetDelta(),
475 navigation_deltas.receive_headers_end.GetDelta());
478 // Reuse case.
479 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, ReuseSocket) {
480 TimingDeltas load_timing_deltas;
481 load_timing_deltas.send_start = RelativeTime(0);
482 load_timing_deltas.send_end = RelativeTime(100);
483 load_timing_deltas.receive_headers_end = RelativeTime(200);
485 TimingDeltas navigation_deltas;
486 RunTest(load_timing_deltas, &navigation_deltas);
488 // Connect times should all be the same as fetchStart.
489 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
490 EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
491 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
492 EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
494 // Connect end may be less than send start, since connect end defaults to
495 // fetchStart, which is often less than request_start.
496 EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
497 navigation_deltas.send_start.GetDelta());
499 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
500 navigation_deltas.receive_headers_end.GetDelta());
502 EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
505 // Preconnect case. Connect times are all before the request was started.
506 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Preconnect) {
507 TimingDeltas load_timing_deltas;
508 load_timing_deltas.dns_start = RelativeTime(-1000300);
509 load_timing_deltas.dns_end = RelativeTime(-1000200);
510 load_timing_deltas.connect_start = RelativeTime(-1000100);
511 load_timing_deltas.connect_end = RelativeTime(-1000000);
512 load_timing_deltas.send_start = RelativeTime(0);
513 load_timing_deltas.send_end = RelativeTime(100);
514 load_timing_deltas.receive_headers_end = RelativeTime(200);
516 TimingDeltas navigation_deltas;
517 RunTest(load_timing_deltas, &navigation_deltas);
519 // Connect times should all be the same as request_start.
520 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
521 navigation_deltas.dns_end.GetDelta());
522 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
523 navigation_deltas.connect_start.GetDelta());
524 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
525 navigation_deltas.connect_end.GetDelta());
527 EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
528 navigation_deltas.send_start.GetDelta());
530 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
531 navigation_deltas.receive_headers_end.GetDelta());
532 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
533 navigation_deltas.receive_headers_end.GetDelta());
535 EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
538 // Preconnect case with a proxy. Connect times are all before the proxy lookup
539 // finished (Or at the same time).
540 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, PreconnectProxySsl) {
541 TimingDeltas load_timing_deltas;
542 load_timing_deltas.proxy_resolve_start = RelativeTime(0);
543 load_timing_deltas.proxy_resolve_end = RelativeTime(100);
544 load_timing_deltas.dns_start = RelativeTime(-3000000);
545 load_timing_deltas.dns_end = RelativeTime(-2000000);
546 load_timing_deltas.connect_start = RelativeTime(-1000000);
547 load_timing_deltas.ssl_start = RelativeTime(0);
548 load_timing_deltas.connect_end = RelativeTime(100);
549 load_timing_deltas.send_start = RelativeTime(100);
550 load_timing_deltas.send_end = RelativeTime(200);
551 load_timing_deltas.receive_headers_end = RelativeTime(300);
553 TimingDeltas navigation_deltas;
554 RunTest(load_timing_deltas, &navigation_deltas);
556 // Connect times should all be the same as proxy_end, which is also the
557 // same as send_start.
558 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
559 navigation_deltas.dns_end.GetDelta());
560 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
561 navigation_deltas.connect_start.GetDelta());
562 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
563 navigation_deltas.ssl_start.GetDelta());
564 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
565 navigation_deltas.connect_end.GetDelta());
566 EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
567 navigation_deltas.send_start.GetDelta());
569 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
570 navigation_deltas.receive_headers_end.GetDelta());
571 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
572 navigation_deltas.receive_headers_end.GetDelta());
575 // Integration test with a real network response.
576 IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Integration) {
577 ASSERT_TRUE(test_server()->Start());
578 TimingDeltas navigation_deltas;
579 RunTestWithUrl(test_server()->GetURL("chunked?waitBeforeHeaders=100"),
580 &navigation_deltas);
582 // Due to potential roundoff issues, never check exact differences.
583 EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
584 navigation_deltas.dns_end.GetDelta());
585 EXPECT_LE(navigation_deltas.dns_end.GetDelta(),
586 navigation_deltas.connect_start.GetDelta());
587 EXPECT_LE(navigation_deltas.connect_start.GetDelta(),
588 navigation_deltas.connect_end.GetDelta());
589 EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
590 navigation_deltas.send_start.GetDelta());
591 // The only times that are guaranteed to be distinct are send_start and
592 // received_headers_end.
593 EXPECT_LT(navigation_deltas.send_start.GetDelta(),
594 navigation_deltas.receive_headers_end.GetDelta());
596 EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
599 } // namespace