Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1062)

Side by Side Diff: third_party/WebKit/Source/platform/inspector_protocol/CheckProtocolCompatibility.py

Issue 2282283002: [DevTools] Prepare inspector_protocol build to move. (Closed)
Patch Set: NOTREACHED Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 Google Inc. All rights reserved. 2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # 3 #
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 27 matching lines...) Expand all
38 # - Required response parameter was removed or changed to optional 38 # - Required response parameter was removed or changed to optional
39 # - Event has been removed 39 # - Event has been removed
40 # - Required event parameter was removed or changed to optional 40 # - Required event parameter was removed or changed to optional
41 # - Parameter type has changed. 41 # - Parameter type has changed.
42 # 42 #
43 # For the parameters with composite types the above checks are also applied 43 # For the parameters with composite types the above checks are also applied
44 # recursively to every property of the type. 44 # recursively to every property of the type.
45 # 45 #
46 # Adding --show_changes to the command line prints out a list of valid public AP I changes. 46 # Adding --show_changes to the command line prints out a list of valid public AP I changes.
47 47
48 import collections
49 import copy 48 import copy
50 import os.path 49 import os.path
51 import optparse 50 import optparse
52 import re
53 import sys 51 import sys
54 52
55 try: 53 try:
56 import json 54 import json
57 except ImportError: 55 except ImportError:
58 import simplejson as json 56 import simplejson as json
59 57
58
60 def list_to_map(items, key): 59 def list_to_map(items, key):
61 result = {} 60 result = {}
62 for item in items: 61 for item in items:
63 if not "experimental" in item and not "hidden" in item: 62 if "experimental" not in item and "hidden" not in item:
64 result[item[key]] = item 63 result[item[key]] = item
65 return result 64 return result
66 65
67 66
68 def named_list_to_map(container, name, key): 67 def named_list_to_map(container, name, key):
69 if name in container: 68 if name in container:
70 return list_to_map(container[name], key) 69 return list_to_map(container[name], key)
71 return {} 70 return {}
72 71
73 72
(...skipping 14 matching lines...) Expand all
88 domains_1 = copy.deepcopy(d_1) 87 domains_1 = copy.deepcopy(d_1)
89 domains_2 = copy.deepcopy(d_2) 88 domains_2 = copy.deepcopy(d_2)
90 types_1 = normalize_types_in_schema(domains_1) 89 types_1 = normalize_types_in_schema(domains_1)
91 types_2 = normalize_types_in_schema(domains_2) 90 types_2 = normalize_types_in_schema(domains_2)
92 91
93 domains_by_name_1 = list_to_map(domains_1, "domain") 92 domains_by_name_1 = list_to_map(domains_1, "domain")
94 domains_by_name_2 = list_to_map(domains_2, "domain") 93 domains_by_name_2 = list_to_map(domains_2, "domain")
95 94
96 for name in domains_by_name_1: 95 for name in domains_by_name_1:
97 domain_1 = domains_by_name_1[name] 96 domain_1 = domains_by_name_1[name]
98 if not name in domains_by_name_2: 97 if name not in domains_by_name_2:
99 errors.append("%s: domain has been %s" % (name, removed(reverse))) 98 errors.append("%s: domain has been %s" % (name, removed(reverse)))
100 continue 99 continue
101 compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, err ors, reverse) 100 compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, err ors, reverse)
102 return errors 101 return errors
103 102
104 103
105 def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, revers e): 104 def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, revers e):
106 domain_name = domain_1["domain"] 105 domain_name = domain_1["domain"]
107 commands_1 = named_list_to_map(domain_1, "commands", "name") 106 commands_1 = named_list_to_map(domain_1, "commands", "name")
108 commands_2 = named_list_to_map(domain_2, "commands", "name") 107 commands_2 = named_list_to_map(domain_2, "commands", "name")
109 for name in commands_1: 108 for name in commands_1:
110 command_1 = commands_1[name] 109 command_1 = commands_1[name]
111 if not name in commands_2: 110 if name not in commands_2:
112 errors.append("%s.%s: command has been %s" % (domain_1["domain"], na me, removed(reverse))) 111 errors.append("%s.%s: command has been %s" % (domain_1["domain"], na me, removed(reverse)))
113 continue 112 continue
114 compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse) 113 compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse)
115 114
116 events_1 = named_list_to_map(domain_1, "events", "name") 115 events_1 = named_list_to_map(domain_1, "events", "name")
117 events_2 = named_list_to_map(domain_2, "events", "name") 116 events_2 = named_list_to_map(domain_2, "events", "name")
118 for name in events_1: 117 for name in events_1:
119 event_1 = events_1[name] 118 event_1 = events_1[name]
120 if not name in events_2: 119 if name not in events_2:
121 errors.append("%s.%s: event has been %s" % (domain_1["domain"], name , removed(reverse))) 120 errors.append("%s.%s: event has been %s" % (domain_1["domain"], name , removed(reverse)))
122 continue 121 continue
123 compare_events(domain_name, event_1, events_2[name], types_map_1, types_ map_2, errors, reverse) 122 compare_events(domain_name, event_1, events_2[name], types_map_1, types_ map_2, errors, reverse)
124 123
125 124
126 def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2 , errors, reverse): 125 def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2 , errors, reverse):
127 context = domain_name + "." + command_1["name"] 126 context = domain_name + "." + command_1["name"]
128 127
129 params_1 = named_list_to_map(command_1, "parameters", "name") 128 params_1 = named_list_to_map(command_1, "parameters", "name")
130 params_2 = named_list_to_map(command_2, "parameters", "name") 129 params_2 = named_list_to_map(command_2, "parameters", "name")
131 # Note the reversed order: we allow removing but forbid adding parameters. 130 # Note the reversed order: we allow removing but forbid adding parameters.
132 compare_params_list(context, "parameter", params_2, params_1, types_map_2, t ypes_map_1, 0, errors, not reverse) 131 compare_params_list(context, "parameter", params_2, params_1, types_map_2, t ypes_map_1, 0, errors, not reverse)
133 132
134 returns_1 = named_list_to_map(command_1, "returns", "name") 133 returns_1 = named_list_to_map(command_1, "returns", "name")
135 returns_2 = named_list_to_map(command_2, "returns", "name") 134 returns_2 = named_list_to_map(command_2, "returns", "name")
136 compare_params_list(context, "response parameter", returns_1, returns_2, typ es_map_1, types_map_2, 0, errors, reverse) 135 compare_params_list(context, "response parameter", returns_1, returns_2, typ es_map_1, types_map_2, 0, errors, reverse)
137 136
138 137
139 def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, erro rs, reverse): 138 def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, erro rs, reverse):
140 context = domain_name + "." + event_1["name"] 139 context = domain_name + "." + event_1["name"]
141 params_1 = named_list_to_map(event_1, "parameters", "name") 140 params_1 = named_list_to_map(event_1, "parameters", "name")
142 params_2 = named_list_to_map(event_2, "parameters", "name") 141 params_2 = named_list_to_map(event_2, "parameters", "name")
143 compare_params_list(context, "parameter", params_1, params_2, types_map_1, t ypes_map_2, 0, errors, reverse) 142 compare_params_list(context, "parameter", params_1, params_2, types_map_1, t ypes_map_2, 0, errors, reverse)
144 143
145 144
146 def compare_params_list(context, kind, params_1, params_2, types_map_1, types_ma p_2, depth, errors, reverse): 145 def compare_params_list(context, kind, params_1, params_2, types_map_1, types_ma p_2, depth, errors, reverse):
147 for name in params_1: 146 for name in params_1:
148 param_1 = params_1[name] 147 param_1 = params_1[name]
149 if not name in params_2: 148 if name not in params_2:
150 if not "optional" in param_1: 149 if "optional" not in param_1:
151 errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse))) 150 errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse)))
152 continue 151 continue
153 152
154 param_2 = params_2[name] 153 param_2 = params_2[name]
155 if param_2 and "optional" in param_2 and not "optional" in param_1: 154 if param_2 and "optional" in param_2 and "optional" not in param_1:
156 errors.append("%s.%s: %s %s is now %s" % (context, name, required(re verse), kind, required(not reverse))) 155 errors.append("%s.%s: %s %s is now %s" % (context, name, required(re verse), kind, required(not reverse)))
157 continue 156 continue
158 type_1 = extract_type(param_1, types_map_1, errors) 157 type_1 = extract_type(param_1, types_map_1, errors)
159 type_2 = extract_type(param_2, types_map_2, errors) 158 type_2 = extract_type(param_2, types_map_2, errors)
160 compare_types(context + "." + name, kind, type_1, type_2, types_map_1, t ypes_map_2, depth, errors, reverse) 159 compare_types(context + "." + name, kind, type_1, type_2, types_map_1, t ypes_map_2, depth, errors, reverse)
161 160
162 161
163 def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth , errors, reverse): 162 def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth , errors, reverse):
164 if depth > 10: 163 if depth > 10:
165 return 164 return
(...skipping 14 matching lines...) Expand all
180 context += " %s->%s" % (kind, type_name) 179 context += " %s->%s" % (kind, type_name)
181 compare_params_list(context, "property", params_1, params_2, types_map_1 , types_map_2, depth + 1, errors, reverse) 180 compare_params_list(context, "property", params_1, params_2, types_map_1 , types_map_2, depth + 1, errors, reverse)
182 elif base_type_1 == "array": 181 elif base_type_1 == "array":
183 item_type_1 = extract_type(type_1["items"], types_map_1, errors) 182 item_type_1 = extract_type(type_1["items"], types_map_1, errors)
184 item_type_2 = extract_type(type_2["items"], types_map_2, errors) 183 item_type_2 = extract_type(type_2["items"], types_map_2, errors)
185 compare_types(context, kind, item_type_1, item_type_2, types_map_1, type s_map_2, depth + 1, errors, reverse) 184 compare_types(context, kind, item_type_1, item_type_2, types_map_1, type s_map_2, depth + 1, errors, reverse)
186 185
187 186
188 def extract_type(typed_object, types_map, errors): 187 def extract_type(typed_object, types_map, errors):
189 if "type" in typed_object: 188 if "type" in typed_object:
190 result = { "id": "<transient>", "type": typed_object["type"] } 189 result = {"id": "<transient>", "type": typed_object["type"]}
191 if typed_object["type"] == "object": 190 if typed_object["type"] == "object":
192 result["properties"] = [] 191 result["properties"] = []
193 elif typed_object["type"] == "array": 192 elif typed_object["type"] == "array":
194 result["items"] = typed_object["items"] 193 result["items"] = typed_object["items"]
195 return result 194 return result
196 elif "$ref" in typed_object: 195 elif "$ref" in typed_object:
197 ref = typed_object["$ref"] 196 ref = typed_object["$ref"]
198 if not ref in types_map: 197 if ref not in types_map:
199 errors.append("Can not resolve type: %s" % ref) 198 errors.append("Can not resolve type: %s" % ref)
200 types_map[ref] = { "id": "<transient>", "type": "object" } 199 types_map[ref] = {"id": "<transient>", "type": "object"}
201 return types_map[ref] 200 return types_map[ref]
202 201
203 202
204 def normalize_types_in_schema(domains): 203 def normalize_types_in_schema(domains):
205 types = {} 204 types = {}
206 for domain in domains: 205 for domain in domains:
207 domain_name = domain["domain"] 206 domain_name = domain["domain"]
208 normalize_types(domain, domain_name, types) 207 normalize_types(domain, domain_name, types)
209 return types 208 return types
210 209
211 210
212 def normalize_types(obj, domain_name, types): 211 def normalize_types(obj, domain_name, types):
213 if isinstance(obj, list): 212 if isinstance(obj, list):
214 for item in obj: 213 for item in obj:
215 normalize_types(item, domain_name, types) 214 normalize_types(item, domain_name, types)
216 elif isinstance(obj, dict): 215 elif isinstance(obj, dict):
217 for key, value in obj.items(): 216 for key, value in obj.items():
218 if key == "$ref" and value.find(".") == -1: 217 if key == "$ref" and value.find(".") == -1:
219 obj[key] = "%s.%s" % (domain_name, value) 218 obj[key] = "%s.%s" % (domain_name, value)
220 elif key == "id": 219 elif key == "id":
221 obj[key] = "%s.%s" % (domain_name, value) 220 obj[key] = "%s.%s" % (domain_name, value)
222 types[obj[key]] = obj 221 types[obj[key]] = obj
223 else: 222 else:
224 normalize_types(value, domain_name, types) 223 normalize_types(value, domain_name, types)
225 224
226 225
227 def load_schema(file, domains): 226 def load_schema(file_name, domains):
228 if not os.path.isfile(file): 227 # pylint: disable=W0613
228 if not os.path.isfile(file_name):
229 return 229 return
230 input_file = open(file, "r") 230 input_file = open(file_name, "r")
231 json_string = input_file.read() 231 json_string = input_file.read()
232 parsed_json = json.loads(json_string) 232 parsed_json = json.loads(json_string)
233 domains += parsed_json["domains"] 233 domains += parsed_json["domains"]
234 return parsed_json["version"] 234 return parsed_json["version"]
235 235
236 236
237 def self_test(): 237 def self_test():
238 def create_test_schema_1(): 238 def create_test_schema_1():
239 return [ 239 return [
240 { 240 {
241 "domain": "Network", 241 "domain": "Network",
242 "types": [ 242 "types": [
243 { 243 {
244 "id": "LoaderId", 244 "id": "LoaderId",
245 "type": "string" 245 "type": "string"
246 }, 246 },
247 { 247 {
248 "id": "Headers", 248 "id": "Headers",
249 "type": "object" 249 "type": "object"
250 }, 250 },
251 { 251 {
252 "id": "Request", 252 "id": "Request",
253 "type": "object", 253 "type": "object",
254 "properties": [ 254 "properties": [
255 { "name": "url", "type": "string" }, 255 {"name": "url", "type": "string"},
256 { "name": "method", "type": "string" }, 256 {"name": "method", "type": "string"},
257 { "name": "headers", "$ref": "Headers" }, 257 {"name": "headers", "$ref": "Headers"},
258 { "name": "becameOptionalField", "type": "string" }, 258 {"name": "becameOptionalField", "type": "string"},
259 { "name": "removedField", "type": "string" }, 259 {"name": "removedField", "type": "string"},
260 ]
261 }
262 ],
263 "commands": [
264 {
265 "name": "removedCommand",
266 },
267 {
268 "name": "setExtraHTTPHeaders",
269 "parameters": [
270 { "name": "headers", "$ref": "Headers" },
271 { "name": "mismatched", "type": "string" },
272 { "name": "becameOptional", "$ref": "Headers" },
273 { "name": "removedRequired", "$ref": "Headers" },
274 { "name": "becameRequired", "$ref": "Headers", "optional ": True },
275 { "name": "removedOptional", "$ref": "Headers", "optiona l": True },
276 ],
277 "returns": [
278 { "name": "mimeType", "type": "string" },
279 { "name": "becameOptional", "type": "string" },
280 { "name": "removedRequired", "type": "string" },
281 { "name": "becameRequired", "type": "string", "optional" : True },
282 { "name": "removedOptional", "type": "string", "optional ": True },
283 ]
284 }
285 ],
286 "events": [
287 {
288 "name": "requestWillBeSent",
289 "parameters": [
290 { "name": "frameId", "type": "string", "experimental": T rue },
291 { "name": "request", "$ref": "Request" },
292 { "name": "becameOptional", "type": "string" },
293 { "name": "removedRequired", "type": "string" },
294 { "name": "becameRequired", "type": "string", "optional" : True },
295 { "name": "removedOptional", "type": "string", "optional ": True },
296 ] 260 ]
297 }, 261 }
298 { 262 ],
299 "name": "removedEvent", 263 "commands": [
300 "parameters": [ 264 {
301 { "name": "errorText", "type": "string" }, 265 "name": "removedCommand",
302 { "name": "canceled", "type": "boolean", "optional": Tru e } 266 },
303 ] 267 {
304 } 268 "name": "setExtraHTTPHeaders",
305 ] 269 "parameters": [
306 }, 270 {"name": "headers", "$ref": "Headers"},
307 { 271 {"name": "mismatched", "type": "string"},
308 "domain": "removedDomain" 272 {"name": "becameOptional", "$ref": "Headers"},
309 } 273 {"name": "removedRequired", "$ref": "Headers"},
310 ] 274 {"name": "becameRequired", "$ref": "Headers", "optio nal": True},
275 {"name": "removedOptional", "$ref": "Headers", "opti onal": True},
276 ],
277 "returns": [
278 {"name": "mimeType", "type": "string"},
279 {"name": "becameOptional", "type": "string"},
280 {"name": "removedRequired", "type": "string"},
281 {"name": "becameRequired", "type": "string", "option al": True},
282 {"name": "removedOptional", "type": "string", "optio nal": True},
283 ]
284 }
285 ],
286 "events": [
287 {
288 "name": "requestWillBeSent",
289 "parameters": [
290 {"name": "frameId", "type": "string", "experimental" : True},
291 {"name": "request", "$ref": "Request"},
292 {"name": "becameOptional", "type": "string"},
293 {"name": "removedRequired", "type": "string"},
294 {"name": "becameRequired", "type": "string", "option al": True},
295 {"name": "removedOptional", "type": "string", "optio nal": True},
296 ]
297 },
298 {
299 "name": "removedEvent",
300 "parameters": [
301 {"name": "errorText", "type": "string"},
302 {"name": "canceled", "type": "boolean", "optional": True}
303 ]
304 }
305 ]
306 },
307 {
308 "domain": "removedDomain"
309 }
310 ]
311 311
312 def create_test_schema_2(): 312 def create_test_schema_2():
313 return [ 313 return [
314 { 314 {
315 "domain": "Network", 315 "domain": "Network",
316 "types": [ 316 "types": [
317 { 317 {
318 "id": "LoaderId", 318 "id": "LoaderId",
319 "type": "string" 319 "type": "string"
320 }, 320 },
321 { 321 {
322 "id": "Request", 322 "id": "Request",
323 "type": "object", 323 "type": "object",
324 "properties": [ 324 "properties": [
325 { "name": "url", "type": "string" }, 325 {"name": "url", "type": "string"},
326 { "name": "method", "type": "string" }, 326 {"name": "method", "type": "string"},
327 { "name": "headers", "type": "object" }, 327 {"name": "headers", "type": "object"},
328 { "name": "becameOptionalField", "type": "string", "opti onal": True }, 328 {"name": "becameOptionalField", "type": "string", "o ptional": True},
329 ] 329 ]
330 } 330 }
331 ], 331 ],
332 "commands": [ 332 "commands": [
333 { 333 {
334 "name": "addedCommand", 334 "name": "addedCommand",
335 }, 335 },
336 { 336 {
337 "name": "setExtraHTTPHeaders", 337 "name": "setExtraHTTPHeaders",
338 "parameters": [ 338 "parameters": [
339 { "name": "headers", "type": "object" }, 339 {"name": "headers", "type": "object"},
340 { "name": "mismatched", "type": "object" }, 340 {"name": "mismatched", "type": "object"},
341 { "name": "becameOptional", "type": "object" , "optional ": True }, 341 {"name": "becameOptional", "type": "object", "option al": True},
342 { "name": "addedRequired", "type": "object" }, 342 {"name": "addedRequired", "type": "object"},
343 { "name": "becameRequired", "type": "object" }, 343 {"name": "becameRequired", "type": "object"},
344 { "name": "addedOptional", "type": "object", "optional": True }, 344 {"name": "addedOptional", "type": "object", "optiona l": True},
345 ], 345 ],
346 "returns": [ 346 "returns": [
347 { "name": "mimeType", "type": "string" }, 347 {"name": "mimeType", "type": "string"},
348 { "name": "becameOptional", "type": "string", "optional" : True }, 348 {"name": "becameOptional", "type": "string", "option al": True},
349 { "name": "addedRequired", "type": "string"}, 349 {"name": "addedRequired", "type": "string"},
350 { "name": "becameRequired", "type": "string" }, 350 {"name": "becameRequired", "type": "string"},
351 { "name": "addedOptional", "type": "string", "optional": True }, 351 {"name": "addedOptional", "type": "string", "optiona l": True},
352 ] 352 ]
353 } 353 }
354 ], 354 ],
355 "events": [ 355 "events": [
356 { 356 {
357 "name": "requestWillBeSent", 357 "name": "requestWillBeSent",
358 "parameters": [ 358 "parameters": [
359 { "name": "request", "$ref": "Request" }, 359 {"name": "request", "$ref": "Request"},
360 { "name": "becameOptional", "type": "string", "optional" : True }, 360 {"name": "becameOptional", "type": "string", "option al": True},
361 { "name": "addedRequired", "type": "string"}, 361 {"name": "addedRequired", "type": "string"},
362 { "name": "becameRequired", "type": "string" }, 362 {"name": "becameRequired", "type": "string"},
363 { "name": "addedOptional", "type": "string", "optional": True }, 363 {"name": "addedOptional", "type": "string", "optiona l": True},
364 ] 364 ]
365 }, 365 },
366 { 366 {
367 "name": "addedEvent" 367 "name": "addedEvent"
368 } 368 }
369 ] 369 ]
370 }, 370 },
371 { 371 {
372 "domain": "addedDomain" 372 "domain": "addedDomain"
373 } 373 }
374 ] 374 ]
375 375
376 expected_errors = [ 376 expected_errors = [
377 "removedDomain: domain has been removed", 377 "removedDomain: domain has been removed",
378 "Network.removedCommand: command has been removed", 378 "Network.removedCommand: command has been removed",
379 "Network.removedEvent: event has been removed", 379 "Network.removedEvent: event has been removed",
380 "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, ' object' vs 'string'", 380 "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, ' object' vs 'string'",
381 "Network.setExtraHTTPHeaders.addedRequired: required parameter has been added", 381 "Network.setExtraHTTPHeaders.addedRequired: required parameter has been added",
382 "Network.setExtraHTTPHeaders.becameRequired: optional parameter is now r equired", 382 "Network.setExtraHTTPHeaders.becameRequired: optional parameter is now r equired",
383 "Network.setExtraHTTPHeaders.removedRequired: required response paramete r has been removed", 383 "Network.setExtraHTTPHeaders.removedRequired: required response paramete r has been removed",
384 "Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional", 384 "Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional",
385 "Network.requestWillBeSent.removedRequired: required parameter has been removed", 385 "Network.requestWillBeSent.removedRequired: required parameter has been removed",
386 "Network.requestWillBeSent.becameOptional: required parameter is now opt ional", 386 "Network.requestWillBeSent.becameOptional: required parameter is now opt ional",
387 "Network.requestWillBeSent.request parameter->Network.Request.removedFie ld: required property has been removed", 387 "Network.requestWillBeSent.request parameter->Network.Request.removedFie ld: required property has been removed",
388 "Network.requestWillBeSent.request parameter->Network.Request.becameOpti onalField: required property is now optional", 388 "Network.requestWillBeSent.request parameter->Network.Request.becameOpti onalField: required property is now optional",
389 ] 389 ]
390 390
391 expected_errors_reverse = [ 391 expected_errors_reverse = [
392 "addedDomain: domain has been added", 392 "addedDomain: domain has been added",
393 "Network.addedEvent: event has been added", 393 "Network.addedEvent: event has been added",
394 "Network.addedCommand: command has been added", 394 "Network.addedCommand: command has been added",
395 "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 's tring' vs 'object'", 395 "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, ' string' vs 'object'",
396 "Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed", 396 "Network.setExtraHTTPHeaders.removedRequired: required parameter has bee n removed",
397 "Network.setExtraHTTPHeaders.becameOptional: required parameter is now op tional", 397 "Network.setExtraHTTPHeaders.becameOptional: required parameter is now o ptional",
398 "Network.setExtraHTTPHeaders.addedRequired: required response parameter h as been added", 398 "Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added",
399 "Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required", 399 "Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required",
400 "Network.requestWillBeSent.becameRequired: optional parameter is now requ ired", 400 "Network.requestWillBeSent.becameRequired: optional parameter is now req uired",
401 "Network.requestWillBeSent.addedRequired: required parameter has been add ed", 401 "Network.requestWillBeSent.addedRequired: required parameter has been ad ded",
402 ] 402 ]
403 403
404 def is_subset(subset, superset, message): 404 def is_subset(subset, superset, message):
405 for i in range(len(subset)): 405 for i in range(len(subset)):
406 if subset[i] not in superset: 406 if subset[i] not in superset:
407 sys.stderr.write("%s error: %s\n" % (message, subset[i])) 407 sys.stderr.write("%s error: %s\n" % (message, subset[i]))
408 return False 408 return False
409 return True 409 return True
410 410
411 def errors_match(expected, actual): 411 def errors_match(expected, actual):
412 return (is_subset(actual, expected, "Unexpected") and 412 return (is_subset(actual, expected, "Unexpected") and
413 is_subset(expected, actual, "Missing")) 413 is_subset(expected, actual, "Missing"))
414 414
415 return (errors_match(expected_errors, 415 return (errors_match(expected_errors,
416 compare_schemas(create_test_schema_1(), create_test_sch ema_2(), False)) and 416 compare_schemas(create_test_schema_1(), create_test_sch ema_2(), False)) and
417 errors_match(expected_errors_reverse, 417 errors_match(expected_errors_reverse,
418 compare_schemas(create_test_schema_2(), create_test_sch ema_1(), True))) 418 compare_schemas(create_test_schema_2(), create_test_sch ema_1(), True)))
419 419
420 420
421 421 def load_domains_and_baselines(file_name, domains, baseline_domains):
422 def load_domains_and_baselines(file, domains, baseline_domains): 422 version = load_schema(os.path.normpath(file_name), domains)
423 version = load_schema(os.path.normpath(file), domains)
424 suffix = "-%s.%s.json" % (version["major"], version["minor"]) 423 suffix = "-%s.%s.json" % (version["major"], version["minor"])
425 baseline_file = file.replace(".json", suffix) 424 baseline_file = file_name.replace(".json", suffix)
426 load_schema(os.path.normpath(baseline_file), baseline_domains) 425 load_schema(os.path.normpath(baseline_file), baseline_domains)
427 return version 426 return version
428 427
429 428
430 def main(): 429 def main():
431 if not self_test(): 430 if not self_test():
432 sys.stderr.write("Self-test failed") 431 sys.stderr.write("Self-test failed")
433 return 1 432 return 1
434 433
435 cmdline_parser = optparse.OptionParser() 434 cmdline_parser = optparse.OptionParser()
436 cmdline_parser.add_option("--show_changes") 435 cmdline_parser.add_option("--show_changes")
437 cmdline_parser.add_option("--o") 436 cmdline_parser.add_option("--expected_errors")
437 cmdline_parser.add_option("--stamp")
438 arg_options, arg_values = cmdline_parser.parse_args() 438 arg_options, arg_values = cmdline_parser.parse_args()
439 439
440 if len(arg_values) < 1 or not arg_options.o: 440 if len(arg_values) < 1:
441 sys.stderr.write("Usage: %s --o OUTPUT_FILE [--show_changes] PROTOCOL_FO LDER1 ?PROTOCOL_FOLDER2 \n" % sys.argv[0]) 441 sys.stderr.write("Usage: %s [--show_changes] <protocol-1> [, <protocol-2 >...]\n" % sys.argv[0])
442 return 1 442 return 1
443 443
444 output_path = arg_options.o
445 output_file = open(output_path, "w")
446
447 domains = [] 444 domains = []
448 baseline_domains = [] 445 baseline_domains = []
449 version = load_domains_and_baselines(arg_values[0], domains, baseline_domain s) 446 version = load_domains_and_baselines(arg_values[0], domains, baseline_domain s)
450 if len(arg_values) > 1: 447 for dependency in arg_values[1:]:
451 load_domains_and_baselines(arg_values[1], domains, baseline_domains) 448 load_domains_and_baselines(dependency, domains, baseline_domains)
452 449
453 expected_errors = [ 450 expected_errors = []
454 "Debugger.globalObjectCleared: event has been removed", 451 if arg_options.expected_errors:
455 "Runtime.executionContextCreated.context parameter->Runtime.ExecutionCon textDescription.frameId: required property has been removed", 452 expected_errors_file = open(arg_options.expected_errors, "r")
456 "Debugger.canSetScriptSource: command has been removed", 453 expected_errors = json.loads(expected_errors_file.read())["errors"]
457 "Console.messageRepeatCountUpdated: event has been removed", 454 expected_errors_file.close()
458 "Console.messagesCleared: event has been removed"
459 ]
460 455
461 errors = compare_schemas(baseline_domains, domains, False) 456 errors = compare_schemas(baseline_domains, domains, False)
462 unexpected_errors = [] 457 unexpected_errors = []
463 for i in range(len(errors)): 458 for i in range(len(errors)):
464 if errors[i] not in expected_errors: 459 if errors[i] not in expected_errors:
465 unexpected_errors.append(errors[i]) 460 unexpected_errors.append(errors[i])
466 if len(unexpected_errors) > 0: 461 if len(unexpected_errors) > 0:
467 sys.stderr.write(" Compatibility checks FAILED\n") 462 sys.stderr.write(" Compatibility checks FAILED\n")
468 for error in unexpected_errors: 463 for error in unexpected_errors:
469 sys.stderr.write( " %s\n" % error) 464 sys.stderr.write(" %s\n" % error)
470 return 1 465 return 1
471 466
472 if arg_options.show_changes: 467 if arg_options.show_changes:
473 changes = compare_schemas(domains, baseline_domains, True) 468 changes = compare_schemas(domains, baseline_domains, True)
474 if len(changes) > 0: 469 if len(changes) > 0:
475 print " Public changes since %s:" % version 470 print " Public changes since %s:" % version
476 for change in changes: 471 for change in changes:
477 print " %s" % change 472 print " %s" % change
478 473
479 json.dump({"version": version, "domains": domains}, output_file, indent=4, s ort_keys=False, separators=(',', ': ')) 474 if arg_options.stamp:
480 output_file.close() 475 with open(arg_options.stamp, 'a') as _:
476 pass
481 477
482 if __name__ == '__main__': 478 if __name__ == '__main__':
483 sys.exit(main()) 479 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698