OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import os | 5 import os |
6 import sys | 6 import sys |
7 import unittest | 7 import unittest |
8 | 8 |
9 import dag | 9 import dag |
10 import loading_model | 10 import loading_model |
11 import log_parser | 11 import loading_trace |
| 12 import request_track |
| 13 import request_dependencies_lens |
| 14 |
| 15 |
| 16 class SimpleLens(object): |
| 17 def __init__(self, trace): |
| 18 self._trace = trace |
| 19 |
| 20 def GetRequestDependencies(self): |
| 21 url_to_rq = {} |
| 22 deps = [] |
| 23 for rq in self._trace.request_track.GetEvents(): |
| 24 assert rq.url not in url_to_rq |
| 25 url_to_rq[rq.url] = rq |
| 26 for rq in self._trace.request_track.GetEvents(): |
| 27 if rq.initiator in url_to_rq: |
| 28 deps.append((rq, url_to_rq[rq.initiator], '')) |
| 29 return deps |
| 30 |
| 31 |
| 32 class MockRequestTrack(object): |
| 33 def __init__(self, requests): |
| 34 self._requests = requests |
| 35 |
| 36 def GetEvents(self): |
| 37 return self._requests |
| 38 |
12 | 39 |
13 class LoadingModelTestCase(unittest.TestCase): | 40 class LoadingModelTestCase(unittest.TestCase): |
14 | 41 |
| 42 def setUp(self): |
| 43 request_dependencies_lens.RequestDependencyLens = SimpleLens |
| 44 self._next_request_id = 0 |
| 45 |
15 def MakeParserRequest(self, url, source_url, start_time, end_time, | 46 def MakeParserRequest(self, url, source_url, start_time, end_time, |
16 magic_content_type=False): | 47 magic_content_type=False): |
17 timing_data = {f: -1 for f in log_parser.Timing._fields} | 48 rq = request_track.Request.FromJsonDict({ |
18 # We should ignore connectEnd. | 49 'request_id': self._next_request_id, |
19 timing_data['connectEnd'] = (end_time - start_time) / 2 | 50 'url': 'http://' + str(url), |
20 timing_data['receiveHeadersEnd'] = end_time - start_time | 51 'initiator': 'http://' + str(source_url), |
21 timing_data['requestTime'] = start_time / 1000.0 | 52 'response_headers': {'Content-Type': |
22 return log_parser.RequestData( | 53 'null' if not magic_content_type |
23 None, {'Content-Type': 'null' if not magic_content_type | 54 else 'magic-debug-content' }, |
24 else 'magic-debug-content' }, | 55 'timing': request_track.TimingFromDict({ |
25 None, start_time, timing_data, 'http://' + str(url), False, | 56 # connectEnd should be ignored. |
26 {'type': 'parser', 'url': 'http://' + str(source_url)}) | 57 'connectEnd': (end_time - start_time) / 2, |
| 58 'receiveHeadersEnd': end_time - start_time, |
| 59 'requestTime': start_time / 1000.0}) |
| 60 }) |
| 61 self._next_request_id += 1 |
| 62 return rq |
| 63 |
| 64 def MakeGraph(self, requests): |
| 65 return loading_model.ResourceGraph(loading_trace.LoadingTrace( |
| 66 None, None, None, MockRequestTrack(requests), None)) |
27 | 67 |
28 def SortedIndicies(self, graph): | 68 def SortedIndicies(self, graph): |
29 return [n.Index() for n in dag.TopologicalSort(graph._nodes)] | 69 return [n.Index() for n in dag.TopologicalSort(graph._nodes)] |
30 | 70 |
31 def SuccessorIndicies(self, node): | 71 def SuccessorIndicies(self, node): |
32 return [c.Index() for c in node.SortedSuccessors()] | 72 return [c.Index() for c in node.SortedSuccessors()] |
33 | 73 |
34 def test_Costing(self): | 74 def test_Costing(self): |
35 requests = [self.MakeParserRequest(0, 'null', 100, 110), | 75 requests = [self.MakeParserRequest(0, 'null', 100, 110), |
36 self.MakeParserRequest(1, 0, 115, 120), | 76 self.MakeParserRequest(1, 0, 115, 120), |
37 self.MakeParserRequest(2, 0, 112, 120), | 77 self.MakeParserRequest(2, 0, 112, 120), |
38 self.MakeParserRequest(3, 1, 122, 126), | 78 self.MakeParserRequest(3, 1, 122, 126), |
39 self.MakeParserRequest(4, 3, 127, 128), | 79 self.MakeParserRequest(4, 3, 127, 128), |
40 self.MakeParserRequest(5, 'null', 100, 105), | 80 self.MakeParserRequest(5, 'null', 100, 105), |
41 self.MakeParserRequest(6, 5, 105, 110)] | 81 self.MakeParserRequest(6, 5, 105, 110)] |
42 graph = loading_model.ResourceGraph(requests) | 82 graph = self.MakeGraph(requests) |
43 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 2]) | 83 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 2]) |
44 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [3]) | 84 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [3]) |
45 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), []) | 85 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), []) |
46 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [4]) | 86 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [4]) |
47 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) | 87 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) |
48 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), [6]) | 88 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), [6]) |
49 self.assertEqual(self.SuccessorIndicies(graph._nodes[6]), []) | 89 self.assertEqual(self.SuccessorIndicies(graph._nodes[6]), []) |
50 self.assertEqual(self.SortedIndicies(graph), [0, 5, 1, 2, 6, 3, 4]) | 90 self.assertEqual(self.SortedIndicies(graph), [0, 5, 1, 2, 6, 3, 4]) |
51 self.assertEqual(28, graph.Cost()) | 91 self.assertEqual(28, graph.Cost()) |
52 graph.Set(cache_all=True) | 92 graph.Set(cache_all=True) |
53 self.assertEqual(8, graph.Cost()) | 93 self.assertEqual(8, graph.Cost()) |
54 | 94 |
55 def test_MaxPath(self): | 95 def test_MaxPath(self): |
56 requests = [self.MakeParserRequest(0, 'null', 100, 110), | 96 requests = [self.MakeParserRequest(0, 'null', 100, 110), |
57 self.MakeParserRequest(1, 0, 115, 120), | 97 self.MakeParserRequest(1, 0, 115, 120), |
58 self.MakeParserRequest(2, 0, 112, 120), | 98 self.MakeParserRequest(2, 0, 112, 120), |
59 self.MakeParserRequest(3, 1, 122, 126), | 99 self.MakeParserRequest(3, 1, 122, 126), |
60 self.MakeParserRequest(4, 3, 127, 128), | 100 self.MakeParserRequest(4, 3, 127, 128), |
61 self.MakeParserRequest(5, 'null', 100, 105), | 101 self.MakeParserRequest(5, 'null', 100, 105), |
62 self.MakeParserRequest(6, 5, 105, 110)] | 102 self.MakeParserRequest(6, 5, 105, 110)] |
63 graph = loading_model.ResourceGraph(requests) | 103 graph = self.MakeGraph(requests) |
64 path_list = [] | 104 path_list = [] |
65 self.assertEqual(28, graph.Cost(path_list)) | 105 self.assertEqual(28, graph.Cost(path_list)) |
66 self.assertEqual([0, 1, 3, 4], [n.Index() for n in path_list]) | 106 self.assertEqual([0, 1, 3, 4], [n.Index() for n in path_list]) |
67 | 107 |
68 # More interesting would be a test when a node has multiple predecessors, | 108 # More interesting would be a test when a node has multiple predecessors, |
69 # but it's not possible for us to construct such a graph from requests yet. | 109 # but it's not possible for us to construct such a graph from requests yet. |
70 | 110 |
71 def test_TimingSplit(self): | 111 def test_TimingSplit(self): |
72 # Timing adds node 1 as a parent to 2 but not 3. | 112 # Timing adds node 1 as a parent to 2 but not 3. |
73 requests = [self.MakeParserRequest(0, 'null', 100, 110, | 113 requests = [self.MakeParserRequest(0, 'null', 100, 110, |
74 magic_content_type=True), | 114 magic_content_type=True), |
75 self.MakeParserRequest(1, 0, 115, 120, | 115 self.MakeParserRequest(1, 0, 115, 120, |
76 magic_content_type=True), | 116 magic_content_type=True), |
77 self.MakeParserRequest(2, 0, 121, 122, | 117 self.MakeParserRequest(2, 0, 121, 122, |
78 magic_content_type=True), | 118 magic_content_type=True), |
79 self.MakeParserRequest(3, 0, 112, 119), | 119 self.MakeParserRequest(3, 0, 112, 119, |
| 120 magic_content_type=True), |
80 self.MakeParserRequest(4, 2, 122, 126), | 121 self.MakeParserRequest(4, 2, 122, 126), |
81 self.MakeParserRequest(5, 2, 122, 126)] | 122 self.MakeParserRequest(5, 2, 122, 126)] |
82 graph = loading_model.ResourceGraph(requests) | 123 graph = self.MakeGraph(requests) |
83 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 3]) | 124 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 3]) |
84 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [2]) | 125 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [2]) |
85 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) | 126 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) |
86 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), []) | 127 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), []) |
87 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) | 128 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) |
88 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) | 129 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) |
89 self.assertEqual(self.SortedIndicies(graph), [0, 1, 3, 2, 4, 5]) | 130 self.assertEqual(self.SortedIndicies(graph), [0, 1, 3, 2, 4, 5]) |
90 | 131 |
91 # Change node 1 so it is a parent of 3, which become parent of 2. | 132 # Change node 1 so it is a parent of 3, which becomes the parent of 2. |
92 requests[1] = self.MakeParserRequest(1, 0, 110, 111, | 133 requests[1] = self.MakeParserRequest(1, 0, 110, 111, |
93 magic_content_type=True) | 134 magic_content_type=True) |
94 graph = loading_model.ResourceGraph(requests) | 135 graph = self.MakeGraph(requests) |
95 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1]) | 136 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1]) |
96 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [3]) | 137 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [3]) |
97 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) | 138 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) |
98 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [2]) | 139 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [2]) |
99 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) | 140 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) |
100 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) | 141 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) |
101 self.assertEqual(self.SortedIndicies(graph), [0, 1, 3, 2, 4, 5]) | 142 self.assertEqual(self.SortedIndicies(graph), [0, 1, 3, 2, 4, 5]) |
102 | 143 |
103 # Add an initiator dependence to 1 that will become the parent of 3. | 144 # Add an initiator dependence to 1 that will become the parent of 3. |
104 requests[1] = self.MakeParserRequest(1, 0, 110, 111) | |
105 requests.append(self.MakeParserRequest(6, 1, 111, 112)) | |
106 graph = loading_model.ResourceGraph(requests) | |
107 # Check it doesn't change until we change the content type of 1. | |
108 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [3, 6]) | |
109 requests[1] = self.MakeParserRequest(1, 0, 110, 111, | 145 requests[1] = self.MakeParserRequest(1, 0, 110, 111, |
110 magic_content_type=True) | 146 magic_content_type=True) |
111 graph = loading_model.ResourceGraph(requests) | 147 requests.append(self.MakeParserRequest(6, 1, 111, 112)) |
| 148 graph = self.MakeGraph(requests) |
| 149 # Check it doesn't change until we change the content type of 6. |
| 150 self.assertEqual(self.SuccessorIndicies(graph._nodes[6]), []) |
| 151 requests[6] = self.MakeParserRequest(6, 1, 111, 112, |
| 152 magic_content_type=True) |
| 153 graph = self.MakeGraph(requests) |
112 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1]) | 154 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1]) |
113 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [6]) | 155 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), [6]) |
114 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) | 156 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) |
115 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [2]) | 157 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), [2]) |
116 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) | 158 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) |
117 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) | 159 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) |
118 self.assertEqual(self.SuccessorIndicies(graph._nodes[6]), [3]) | 160 self.assertEqual(self.SuccessorIndicies(graph._nodes[6]), [3]) |
119 self.assertEqual(self.SortedIndicies(graph), [0, 1, 6, 3, 2, 4, 5]) | 161 self.assertEqual(self.SortedIndicies(graph), [0, 1, 6, 3, 2, 4, 5]) |
120 | 162 |
121 def test_TimingSplitImage(self): | 163 def test_TimingSplitImage(self): |
122 # If we're all image types, then we shouldn't split by timing. | 164 # If we're all image types, then we shouldn't split by timing. |
123 requests = [self.MakeParserRequest(0, 'null', 100, 110), | 165 requests = [self.MakeParserRequest(0, 'null', 100, 110), |
124 self.MakeParserRequest(1, 0, 115, 120), | 166 self.MakeParserRequest(1, 0, 115, 120), |
125 self.MakeParserRequest(2, 0, 121, 122), | 167 self.MakeParserRequest(2, 0, 121, 122), |
126 self.MakeParserRequest(3, 0, 112, 119), | 168 self.MakeParserRequest(3, 0, 112, 119), |
127 self.MakeParserRequest(4, 2, 122, 126), | 169 self.MakeParserRequest(4, 2, 122, 126), |
128 self.MakeParserRequest(5, 2, 122, 126)] | 170 self.MakeParserRequest(5, 2, 122, 126)] |
129 for r in requests: | 171 for r in requests: |
130 r.headers['Content-Type'] = 'image/gif' | 172 r.response_headers['Content-Type'] = 'image/gif' |
131 graph = loading_model.ResourceGraph(requests) | 173 graph = self.MakeGraph(requests) |
132 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 2, 3]) | 174 self.assertEqual(self.SuccessorIndicies(graph._nodes[0]), [1, 2, 3]) |
133 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), []) | 175 self.assertEqual(self.SuccessorIndicies(graph._nodes[1]), []) |
134 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) | 176 self.assertEqual(self.SuccessorIndicies(graph._nodes[2]), [4, 5]) |
135 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), []) | 177 self.assertEqual(self.SuccessorIndicies(graph._nodes[3]), []) |
136 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) | 178 self.assertEqual(self.SuccessorIndicies(graph._nodes[4]), []) |
137 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) | 179 self.assertEqual(self.SuccessorIndicies(graph._nodes[5]), []) |
138 self.assertEqual(self.SortedIndicies(graph), [0, 1, 2, 3, 4, 5]) | 180 self.assertEqual(self.SortedIndicies(graph), [0, 1, 2, 3, 4, 5]) |
139 | 181 |
140 def test_AdUrl(self): | 182 def test_AdUrl(self): |
141 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( | 183 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( |
142 'http://afae61024b33032ef.profile.sfo20.cloudfront.net/test.png')) | 184 'http://afae61024b33032ef.profile.sfo20.cloudfront.net/test.png')) |
143 self.assertFalse(loading_model.ResourceGraph._IsAdUrl( | 185 self.assertFalse(loading_model.ResourceGraph._IsAdUrl( |
144 'http://afae61024b33032ef.profile.sfo20.cloudfront.net/tst.png')) | 186 'http://afae61024b33032ef.profile.sfo20.cloudfront.net/tst.png')) |
145 | 187 |
146 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( | 188 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( |
147 'http://ums.adtechus.com/mapuser?providerid=1003;' | 189 'http://ums.adtechus.com/mapuser?providerid=1003;' |
148 'userid=RUmecco4z3o====')) | 190 'userid=RUmecco4z3o====')) |
149 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( | 191 self.assertTrue(loading_model.ResourceGraph._IsAdUrl( |
150 'http://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js')) | 192 'http://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js')) |
151 | 193 |
152 | 194 |
153 if __name__ == '__main__': | 195 if __name__ == '__main__': |
154 unittest.main() | 196 unittest.main() |
OLD | NEW |