[go: nahoru, domu]

blob: ff33c212105d054523ee98a110f5d7694dddfc29 [file] [log] [blame]
mcgrathr@chromium.orge4f373e2012-01-10 23:18:241# Copyright (c) 2012 The Chromium Authors. All rights reserved.
noelallen@google.com39375782011-09-14 16:55:092# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
noelallen@chromium.orgc7db6e92012-03-14 06:58:146import re
noelallen@google.com39375782011-09-14 16:55:097import sys
8import subprocess
9
noelallen@chromium.orgc7db6e92012-03-14 06:58:1410
binji@chromium.orgbfe75742014-07-11 16:43:5711def RunCmdAndCheck(cmd, err_string, output_api, cwd=None, warning=False):
jvoung@google.com2978339a72011-11-30 17:59:1412 results = []
mcgrathr@chromium.orge4f373e2012-01-10 23:18:2413 p = subprocess.Popen(cmd, cwd=cwd,
jvoung@google.com2978339a72011-11-30 17:59:1414 stdout=subprocess.PIPE,
15 stderr=subprocess.PIPE)
16 (p_stdout, p_stderr) = p.communicate()
17 if p.returncode:
binji@chromium.orgbfe75742014-07-11 16:43:5718 if warning:
19 results.append(output_api.PresubmitPromptWarning(
20 '%s\n\n%s' % (err_string, p_stderr)))
21 else:
22 results.append(
23 output_api.PresubmitError(err_string,
24 long_text=p_stderr))
jvoung@google.com2978339a72011-11-30 17:59:1425 return results
26
27
28def RunUnittests(input_api, output_api):
29 # Run some Generator unittests if the generator source was changed.
30 results = []
31 files = input_api.LocalPaths()
32 generator_files = []
33 for filename in files:
34 name_parts = filename.split(os.sep)
35 if name_parts[0:2] == ['ppapi', 'generators']:
36 generator_files.append(filename)
37 if generator_files != []:
noelallen@chromium.org6faeb202012-12-06 15:43:0538 cmd = [ sys.executable, 'idl_tests.py']
jvoung@google.com2978339a72011-11-30 17:59:1439 ppapi_dir = input_api.PresubmitLocalPath()
40 results.extend(RunCmdAndCheck(cmd,
noelallen@chromium.org6faeb202012-12-06 15:43:0541 'PPAPI IDL unittests failed.',
mcgrathr@chromium.orge4f373e2012-01-10 23:18:2442 output_api,
43 os.path.join(ppapi_dir, 'generators')))
jvoung@google.com2978339a72011-11-30 17:59:1444 return results
45
46
noelallen@chromium.orgc7db6e92012-03-14 06:58:1447# Verify that the files do not contain a 'TODO' in them.
48RE_TODO = re.compile(r'\WTODO\W', flags=re.I)
49def CheckTODO(input_api, output_api):
teravest@chromium.org4d60dcd82013-10-08 21:33:5150 live_files = input_api.AffectedFiles(include_deletes=False)
51 files = [f.LocalPath() for f in live_files]
noelallen@chromium.orgc7db6e92012-03-14 06:58:1452 todo = []
53
54 for filename in files:
55 name, ext = os.path.splitext(filename)
56 name_parts = name.split(os.sep)
57
58 # Only check normal build sources.
ncbray@chromium.org620446f72012-12-12 22:21:0359 if ext not in ['.h', '.idl']:
noelallen@chromium.orgc7db6e92012-03-14 06:58:1460 continue
61
62 # Only examine the ppapi directory.
63 if name_parts[0] != 'ppapi':
64 continue
65
66 # Only examine public plugin facing directories.
67 if name_parts[1] not in ['api', 'c', 'cpp', 'utility']:
68 continue
69
70 # Only examine public stable interfaces.
71 if name_parts[2] in ['dev', 'private', 'trusted']:
72 continue
73
74 filepath = os.path.join('..', filename)
75 if RE_TODO.search(open(filepath, 'rb').read()):
76 todo.append(filename)
77
78 if todo:
79 return [output_api.PresubmitError(
80 'TODOs found in stable public PPAPI files:',
81 long_text='\n'.join(todo))]
82 return []
83
wez@chromium.org1594f572012-06-01 18:33:1484# Verify that no CPP wrappers use un-versioned PPB interface name macros.
85RE_UNVERSIONED_PPB = re.compile(r'\bPPB_\w+_INTERFACE\b')
86def CheckUnversionedPPB(input_api, output_api):
teravest@chromium.org4d60dcd82013-10-08 21:33:5187 live_files = input_api.AffectedFiles(include_deletes=False)
88 files = [f.LocalPath() for f in live_files]
wez@chromium.org1594f572012-06-01 18:33:1489 todo = []
90
91 for filename in files:
92 name, ext = os.path.splitext(filename)
93 name_parts = name.split(os.sep)
94
95 # Only check C++ sources.
96 if ext not in ['.cc']:
97 continue
98
99 # Only examine the public plugin facing ppapi/cpp directory.
100 if name_parts[0:2] != ['ppapi', 'cpp']:
101 continue
102
103 # Only examine public stable and trusted interfaces.
104 if name_parts[2] in ['dev', 'private']:
105 continue
106
107 filepath = os.path.join('..', filename)
108 if RE_UNVERSIONED_PPB.search(open(filepath, 'rb').read()):
109 todo.append(filename)
110
111 if todo:
112 return [output_api.PresubmitError(
113 'Unversioned PPB interface references found in PPAPI C++ wrappers:',
114 long_text='\n'.join(todo))]
115 return []
noelallen@chromium.orgc7db6e92012-03-14 06:58:14116
binji@chromium.org183dea02013-07-17 19:15:19117# Verify that changes to ppapi headers/sources are also made to NaCl SDK.
118def CheckUpdatedNaClSDK(input_api, output_api):
119 files = input_api.LocalPaths()
120
121 # PPAPI files the Native Client SDK cares about.
122 nacl_sdk_files = []
123
124 for filename in files:
125 name, ext = os.path.splitext(filename)
126 name_parts = name.split(os.sep)
127
128 if len(name_parts) <= 2:
129 continue
130
131 if name_parts[0] != 'ppapi':
132 continue
133
134 if ((name_parts[1] == 'c' and ext == '.h') or
135 (name_parts[1] in ('cpp', 'utility') and ext in ('.h', '.cc'))):
136 if name_parts[2] in ('documentation', 'trusted'):
137 continue
138 nacl_sdk_files.append(filename)
139
140 if not nacl_sdk_files:
141 return []
142
143 verify_ppapi_py = os.path.join(input_api.change.RepositoryRoot(),
144 'native_client_sdk', 'src', 'build_tools',
145 'verify_ppapi.py')
146 cmd = [sys.executable, verify_ppapi_py] + nacl_sdk_files
147 return RunCmdAndCheck(cmd,
binji@chromium.orgbfe75742014-07-11 16:43:57148 'PPAPI Interface modified without updating NaCl SDK.\n'
149 '(note that some dev interfaces should not be added '
binji@chromium.org72412cf82014-08-15 00:37:03150 'the NaCl SDK; when in doubt, ask a ppapi OWNER.\n'
151 'To ignore a file, add it to IGNORED_FILES in '
152 'native_client_sdk/src/build_tools/verify_ppapi.py)',
binji@chromium.orgbfe75742014-07-11 16:43:57153 output_api,
154 warning=True)
binji@chromium.org183dea02013-07-17 19:15:19155
teravest@chromium.orgea441832014-02-05 15:34:21156# Verify that changes to ppapi/thunk/interfaces_* files have a corresponding
Steven Holted79dbde02017-05-04 00:05:48157# change to tools/metrics/histograms/enums.xml for UMA tracking.
teravest@chromium.orgea441832014-02-05 15:34:21158def CheckHistogramXml(input_api, output_api):
159 # We can't use input_api.LocalPaths() here because we need to know about
160 # changes outside of ppapi/. See tools/depot_tools/presubmit_support.py for
161 # details on input_api.
162 files = input_api.change.AffectedFiles()
163
164 INTERFACE_FILES = ('ppapi/thunk/interfaces_legacy.h',
165 'ppapi/thunk/interfaces_ppb_private_flash.h',
166 'ppapi/thunk/interfaces_ppb_private.h',
167 'ppapi/thunk/interfaces_ppb_private_no_permissions.h',
168 'ppapi/thunk/interfaces_ppb_public_dev_channel.h',
169 'ppapi/thunk/interfaces_ppb_public_dev.h',
170 'ppapi/thunk/interfaces_ppb_public_stable.h')
Steven Holted79dbde02017-05-04 00:05:48171 HISTOGRAM_XML_FILE = 'tools/metrics/histograms/enums.xml'
teravest@chromium.orgea441832014-02-05 15:34:21172 interface_changes = []
173 has_histogram_xml_change = False
174 for filename in files:
175 path = filename.LocalPath()
176 if path in INTERFACE_FILES:
177 interface_changes.append(path)
178 if path == HISTOGRAM_XML_FILE:
179 has_histogram_xml_change = True
180
181 if interface_changes and not has_histogram_xml_change:
teravest@chromium.org29ab1d92014-04-03 15:34:41182 return [output_api.PresubmitNotifyResult(
Steven Holted79dbde02017-05-04 00:05:48183 'Missing change to tools/metrics/histograms/enums.xml.\n' +
teravest@chromium.orgea441832014-02-05 15:34:21184 'Run pepper_hash_for_uma to make get values for new interfaces.\n' +
185 'Interface changes:\n' + '\n'.join(interface_changes))]
186 return []
187
noelallen@google.com39375782011-09-14 16:55:09188def CheckChange(input_api, output_api):
189 results = []
190
jvoung@google.com2978339a72011-11-30 17:59:14191 results.extend(RunUnittests(input_api, output_api))
192
noelallen@chromium.orgc7db6e92012-03-14 06:58:14193 results.extend(CheckTODO(input_api, output_api))
wez@chromium.org1594f572012-06-01 18:33:14194
195 results.extend(CheckUnversionedPPB(input_api, output_api))
196
binji@chromium.org183dea02013-07-17 19:15:19197 results.extend(CheckUpdatedNaClSDK(input_api, output_api))
198
teravest@chromium.orgea441832014-02-05 15:34:21199 results.extend(CheckHistogramXml(input_api, output_api))
200
noelallen@google.com39375782011-09-14 16:55:09201 # Verify all modified *.idl have a matching *.h
202 files = input_api.LocalPaths()
203 h_files = []
204 idl_files = []
dmichael@chromium.org60902e72013-09-10 02:31:51205 generators_changed = False
noelallen@google.com39375782011-09-14 16:55:09206
piman@chromium.org3992b9e2014-01-23 01:55:45207 # These are autogenerated by the command buffer generator, they don't go
208 # through idl.
209 whitelist = ['ppb_opengles2', 'ppb_opengles2ext_dev']
210
koz@chromium.org2c0b8c92014-01-31 05:33:26211 # The PDF interface is hand-written.
koz@chromium.orgec158402014-02-06 11:40:25212 whitelist += ['ppb_pdf', 'ppp_pdf']
koz@chromium.org2c0b8c92014-01-31 05:33:26213
noelallen@chromium.orgc7db6e92012-03-14 06:58:14214 # Find all relevant .h and .idl files.
noelallen@google.com39375782011-09-14 16:55:09215 for filename in files:
216 name, ext = os.path.splitext(filename)
217 name_parts = name.split(os.sep)
piman@chromium.org3992b9e2014-01-23 01:55:45218 if name_parts[-1] in whitelist:
219 continue
noelallen@google.com39375782011-09-14 16:55:09220 if name_parts[0:2] == ['ppapi', 'c'] and ext == '.h':
221 h_files.append('/'.join(name_parts[2:]))
dmichael@chromium.org60902e72013-09-10 02:31:51222 elif name_parts[0:2] == ['ppapi', 'api'] and ext == '.idl':
noelallen@google.com39375782011-09-14 16:55:09223 idl_files.append('/'.join(name_parts[2:]))
dmichael@chromium.org60902e72013-09-10 02:31:51224 elif name_parts[0:2] == ['ppapi', 'generators']:
225 generators_changed = True
noelallen@google.com39375782011-09-14 16:55:09226
227 # Generate a list of all appropriate *.h and *.idl changes in this CL.
228 both = h_files + idl_files
229
230 # If there aren't any, we are done checking.
231 if not both: return results
232
233 missing = []
234 for filename in idl_files:
235 if filename not in set(h_files):
teravest@chromium.org8c311f02012-11-17 16:01:32236 missing.append('ppapi/api/%s.idl' % filename)
237
238 # An IDL change that includes [generate_thunk] doesn't need to have
239 # an update to the corresponding .h file.
240 new_thunk_files = []
241 for filename in missing:
242 lines = input_api.RightHandSideLines(lambda f: f.LocalPath() == filename)
243 for line in lines:
244 if line[2].strip() == '[generate_thunk]':
245 new_thunk_files.append(filename)
246 for filename in new_thunk_files:
247 missing.remove(filename)
noelallen@google.com39375782011-09-14 16:55:09248
249 if missing:
250 results.append(
noelallen@chromium.orgc7db6e92012-03-14 06:58:14251 output_api.PresubmitPromptWarning(
252 'Missing PPAPI header, no change or skipped generation?',
teravest@chromium.org8c311f02012-11-17 16:01:32253 long_text='\n '.join(missing)))
noelallen@chromium.orgc7db6e92012-03-14 06:58:14254
255 missing_dev = []
256 missing_stable = []
257 missing_priv = []
258 for filename in h_files:
259 if filename not in set(idl_files):
260 name_parts = filename.split(os.sep)
261
wez@chromium.orge12f4cc2013-02-21 03:24:34262 if name_parts[-1] == 'pp_macros':
263 # The C header generator adds a PPAPI_RELEASE macro based on all the
264 # IDL files, so pp_macros.h may change while its IDL does not.
265 lines = input_api.RightHandSideLines(
266 lambda f: f.LocalPath() == 'ppapi/c/%s.h' % filename)
267 releaseChanged = False
268 for line in lines:
269 if line[2].split()[:2] == ['#define', 'PPAPI_RELEASE']:
270 results.append(
wez@chromium.orgf7051d52013-04-02 18:31:42271 output_api.PresubmitPromptOrNotify(
wez@chromium.orge12f4cc2013-02-21 03:24:34272 'PPAPI_RELEASE has changed', long_text=line[2]))
273 releaseChanged = True
274 break
275 if releaseChanged:
276 continue
277
noelallen@chromium.orgc7db6e92012-03-14 06:58:14278 if 'trusted' in name_parts:
279 missing_priv.append(' ppapi/c/%s.h' % filename)
280 continue
281
282 if 'private' in name_parts:
283 missing_priv.append(' ppapi/c/%s.h' % filename)
284 continue
285
286 if 'dev' in name_parts:
287 missing_dev.append(' ppapi/c/%s.h' % filename)
288 continue
289
290 missing_stable.append(' ppapi/c/%s.h' % filename)
291
292 if missing_priv:
293 results.append(
294 output_api.PresubmitPromptWarning(
295 'Missing PPAPI IDL for private interface, please generate IDL:',
296 long_text='\n'.join(missing_priv)))
297
298 if missing_dev:
299 results.append(
300 output_api.PresubmitPromptWarning(
301 'Missing PPAPI IDL for DEV, required before moving to stable:',
302 long_text='\n'.join(missing_dev)))
303
304 if missing_stable:
dmichael@chromium.org60902e72013-09-10 02:31:51305 # It might be okay that the header changed without a corresponding IDL
306 # change. E.g., comment indenting may have been changed. Treat this as a
307 # warning.
308 if generators_changed:
309 results.append(
310 output_api.PresubmitPromptWarning(
311 'Missing PPAPI IDL for stable interface (due to change in ' +
312 'generators?):',
313 long_text='\n'.join(missing_stable)))
314 else:
315 results.append(
316 output_api.PresubmitError(
317 'Missing PPAPI IDL for stable interface:',
318 long_text='\n'.join(missing_stable)))
noelallen@google.com39375782011-09-14 16:55:09319
320 # Verify all *.h files match *.idl definitions, use:
321 # --test to prevent output to disk
322 # --diff to generate a unified diff
323 # --out to pick which files to examine (only the ones in the CL)
324 ppapi_dir = input_api.PresubmitLocalPath()
noelallen@chromium.orgc7db6e92012-03-14 06:58:14325 cmd = [sys.executable, 'generator.py',
326 '--wnone', '--diff', '--test','--cgen', '--range=start,end']
noelallen@google.com39375782011-09-14 16:55:09327
328 # Only generate output for IDL files references (as *.h or *.idl) in this CL
329 cmd.append('--out=' + ','.join([name + '.idl' for name in both]))
noelallen@chromium.orgc7db6e92012-03-14 06:58:14330 cmd_results = RunCmdAndCheck(cmd,
331 'PPAPI IDL Diff detected: Run the generator.',
332 output_api,
333 os.path.join(ppapi_dir, 'generators'))
334 if cmd_results:
335 results.extend(cmd_results)
336
noelallen@google.com39375782011-09-14 16:55:09337 return results
338
noelallen@chromium.orgc7db6e92012-03-14 06:58:14339
noelallen@google.com39375782011-09-14 16:55:09340def CheckChangeOnUpload(input_api, output_api):
noelallen@google.com39375782011-09-14 16:55:09341 return CheckChange(input_api, output_api)
342
noelallen@chromium.orgc7db6e92012-03-14 06:58:14343
noelallen@google.com39375782011-09-14 16:55:09344def CheckChangeOnCommit(input_api, output_api):
noelallen@google.com39375782011-09-14 16:55:09345 return CheckChange(input_api, output_api)