|
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/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 retriever from the renderer process. | |
eroman
2013/02/13 02:07:20
retriever ---> retrieved ?
mmenke
2013/02/13 02:26:46
Done.
| |
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 ellapsed. | |
eroman
2013/02/13 02:07:20
nit: ellapsed -> elapsed
mmenke
2013/02/13 02:26:46
Done.
| |
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 ellapsed since start was called. If this | |
eroman
2013/02/13 02:07:20
elapsed
mmenke
2013/02/13 02:26:46
Done.
| |
151 // fails, the text fixture itself is flaky. | |
eroman
2013/02/13 02:07:20
"text fixture" --> test fixture?
mmenke
2013/02/13 02:26:46
Done (That's one typo I make a lot, for some odd r
| |
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 |