1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4from telemetry.core.backends.chrome import inspector_network
5from telemetry.timeline import recording_options
6from telemetry.unittest import tab_test_case
7
8
9class InspectorNetworkTabTest(tab_test_case.TabTestCase):
10  class TestCase(object):
11    def __init__(self, monitoring = False, responses_count = 0,
12                 subresources = None):
13      # Whether to monitor network for this case.
14      self.monitoring = monitoring
15      # Number of responses expected for this case.
16      self.responses_count = responses_count
17      # List of subresource links for this case.
18      self.subresources = subresources
19
20  def __init__(self, *args):
21    super(InspectorNetworkTabTest, self).__init__(*args)
22
23  def _NavigateAndGetHTTPResponseEvents(self, page, record_network=True):
24    opts = recording_options.TimelineRecordingOptions()
25    opts.record_network = record_network
26    self._tab.StartTimelineRecording(opts)
27    self.Navigate(page)
28    self._tab.StopTimelineRecording()
29
30    self.assertTrue(self._tab.timeline_model)
31    return self._tab.timeline_model.GetAllEventsOfName('HTTPResponse')
32
33  def testHTTPResponseTimelineRecorder(self):
34    tests = {
35        'blank.html': InspectorNetworkTabTest.TestCase(),
36        'green_rect.html': InspectorNetworkTabTest.TestCase(
37            monitoring=True, responses_count=1),
38        'image_decoding.html': InspectorNetworkTabTest.TestCase(
39            monitoring=True, responses_count=2, subresources=['image.png']),
40        }
41    for page, test in tests.iteritems():
42      events = self._NavigateAndGetHTTPResponseEvents(page, test.monitoring)
43      self.assertEqual(test.responses_count, len(events))
44      if not test.monitoring:
45        continue
46
47      # Verify required event fields
48      for event in events:
49        self.assertEqual('HTTPResponse', event.name)
50        resp = inspector_network.InspectorNetworkResponseData.FromTimelineEvent(
51            event)
52        self.assertLess(0.0, resp.timestamp)
53
54        self.assertTrue(resp.headers)
55        self.assertTrue(resp.headers['Content-Length'])
56        body, base64_encoded = resp.GetBody()
57
58        link = resp.url[resp.url.rfind('/') + 1 :]
59        self.assertTrue(link == page or link in test.subresources)
60        if link == page:
61          self.assertEqual(resp.GetHeader('Content-Type'), 'text/html')
62          self.assertTrue('<!DOCTYPE HTML>' in body)
63          self.assertFalse(base64_encoded)
64        else:
65          # We know this is the only subresource type in our setup.
66          self.assertEqual(resp.GetHeader('Content-Type'), 'image/png')
67          self.assertFalse('<!DOCTYPE HTML>' in body)
68          self.assertTrue(base64_encoded)
69
70  def testCacheableHTTPResponse(self):
71    # We know this page has one PNG image and its cacheable.
72    events = self._NavigateAndGetHTTPResponseEvents('image_decoding.html')
73    images_first = []
74    for event in events:
75      resp = inspector_network.InspectorNetworkResponseData.FromTimelineEvent(
76          event)
77      if resp.GetHeader('Content-Type') == 'image/png':
78        images_first.append(resp)
79
80    self.assertEqual(1, len(images_first))
81    self.assertFalse(images_first[0].served_from_cache)
82
83    events = self._NavigateAndGetHTTPResponseEvents('image_decoding.html')
84    images_second = []
85    for event in events:
86      resp = inspector_network.InspectorNetworkResponseData.FromTimelineEvent(
87          event)
88      if resp.GetHeader('Content-Type') == 'image/png':
89        images_second.append(resp)
90    self.assertEqual(1, len(images_second))
91    # On the second fetch, the image is served from cache.
92    self.assertTrue(images_second[0].served_from_cache)
93