Roll Skia to r4138.
[chromium-blink-merge.git] / ppapi / PRESUBMIT.py
blobb350003a0b06eb77438c429efa16e85861e313f7
1 # Copyright (c) 2012 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.
5 import os
6 import re
7 import sys
8 import subprocess
11 def RunCmdAndCheck(cmd, err_string, output_api, cwd=None):
12 results = []
13 p = subprocess.Popen(cmd, cwd=cwd,
14 stdout=subprocess.PIPE,
15 stderr=subprocess.PIPE)
16 (p_stdout, p_stderr) = p.communicate()
17 if p.returncode:
18 results.append(
19 output_api.PresubmitError(err_string,
20 long_text=p_stderr))
21 return results
24 def RunUnittests(input_api, output_api):
25 # Run some Generator unittests if the generator source was changed.
26 results = []
27 files = input_api.LocalPaths()
28 generator_files = []
29 for filename in files:
30 name_parts = filename.split(os.sep)
31 if name_parts[0:2] == ['ppapi', 'generators']:
32 generator_files.append(filename)
33 if generator_files != []:
34 cmd = [ sys.executable, 'idl_gen_pnacl.py', '--wnone', '--test']
35 ppapi_dir = input_api.PresubmitLocalPath()
36 results.extend(RunCmdAndCheck(cmd,
37 'PPAPI IDL Pnacl unittest failed.',
38 output_api,
39 os.path.join(ppapi_dir, 'generators')))
40 return results
43 # If any .srpc files were changed, run run_srpcgen.py --diff_mode.
44 def CheckSrpcChange(input_api, output_api):
45 if [True for filename in input_api.LocalPaths() if
46 os.path.splitext(filename)[1] == '.srpc']:
47 return RunCmdAndCheck([sys.executable,
48 os.path.join(input_api.PresubmitLocalPath(),
49 'native_client', 'src',
50 'shared', 'ppapi_proxy',
51 'run_srpcgen.py'),
52 '--diff_mode'],
53 'PPAPI SRPC Diff detected: Run run_srpcgen.py.',
54 output_api)
55 return []
58 # Verify that the files do not contain a 'TODO' in them.
59 RE_TODO = re.compile(r'\WTODO\W', flags=re.I)
60 def CheckTODO(input_api, output_api):
61 files = input_api.LocalPaths()
62 todo = []
64 for filename in files:
65 name, ext = os.path.splitext(filename)
66 name_parts = name.split(os.sep)
68 # Only check normal build sources.
69 if ext not in ['.h', '.cc', '.idl']:
70 continue
72 # Only examine the ppapi directory.
73 if name_parts[0] != 'ppapi':
74 continue
76 # Only examine public plugin facing directories.
77 if name_parts[1] not in ['api', 'c', 'cpp', 'utility']:
78 continue
80 # Only examine public stable interfaces.
81 if name_parts[2] in ['dev', 'private', 'trusted']:
82 continue
84 filepath = os.path.join('..', filename)
85 if RE_TODO.search(open(filepath, 'rb').read()):
86 todo.append(filename)
88 if todo:
89 return [output_api.PresubmitError(
90 'TODOs found in stable public PPAPI files:',
91 long_text='\n'.join(todo))]
92 return []
94 # Verify that no CPP wrappers use un-versioned PPB interface name macros.
95 RE_UNVERSIONED_PPB = re.compile(r'\bPPB_\w+_INTERFACE\b')
96 def CheckUnversionedPPB(input_api, output_api):
97 files = input_api.LocalPaths()
98 todo = []
100 for filename in files:
101 name, ext = os.path.splitext(filename)
102 name_parts = name.split(os.sep)
104 # Only check C++ sources.
105 if ext not in ['.cc']:
106 continue
108 # Only examine the public plugin facing ppapi/cpp directory.
109 if name_parts[0:2] != ['ppapi', 'cpp']:
110 continue
112 # Only examine public stable and trusted interfaces.
113 if name_parts[2] in ['dev', 'private']:
114 continue
116 filepath = os.path.join('..', filename)
117 if RE_UNVERSIONED_PPB.search(open(filepath, 'rb').read()):
118 todo.append(filename)
120 if todo:
121 return [output_api.PresubmitError(
122 'Unversioned PPB interface references found in PPAPI C++ wrappers:',
123 long_text='\n'.join(todo))]
124 return []
126 def CheckChange(input_api, output_api):
127 results = []
129 results.extend(CheckSrpcChange(input_api, output_api))
131 results.extend(RunUnittests(input_api, output_api))
133 results.extend(CheckTODO(input_api, output_api))
135 results.extend(CheckUnversionedPPB(input_api, output_api))
137 # Verify all modified *.idl have a matching *.h
138 files = input_api.LocalPaths()
139 h_files = []
140 idl_files = []
142 # Find all relevant .h and .idl files.
143 for filename in files:
144 name, ext = os.path.splitext(filename)
145 name_parts = name.split(os.sep)
146 if name_parts[0:2] == ['ppapi', 'c'] and ext == '.h':
147 h_files.append('/'.join(name_parts[2:]))
148 if name_parts[0:2] == ['ppapi', 'api'] and ext == '.idl':
149 idl_files.append('/'.join(name_parts[2:]))
151 # Generate a list of all appropriate *.h and *.idl changes in this CL.
152 both = h_files + idl_files
154 # If there aren't any, we are done checking.
155 if not both: return results
157 missing = []
158 for filename in idl_files:
159 if filename not in set(h_files):
160 missing.append(' ppapi/c/%s.idl' % filename)
162 if missing:
163 results.append(
164 output_api.PresubmitPromptWarning(
165 'Missing PPAPI header, no change or skipped generation?',
166 long_text='\n'.join(missing)))
168 missing_dev = []
169 missing_stable = []
170 missing_priv = []
171 for filename in h_files:
172 if filename not in set(idl_files):
173 name_parts = filename.split(os.sep)
175 if 'trusted' in name_parts:
176 missing_priv.append(' ppapi/c/%s.h' % filename)
177 continue
179 if 'private' in name_parts:
180 missing_priv.append(' ppapi/c/%s.h' % filename)
181 continue
183 if 'dev' in name_parts:
184 missing_dev.append(' ppapi/c/%s.h' % filename)
185 continue
187 missing_stable.append(' ppapi/c/%s.h' % filename)
189 if missing_priv:
190 results.append(
191 output_api.PresubmitPromptWarning(
192 'Missing PPAPI IDL for private interface, please generate IDL:',
193 long_text='\n'.join(missing_priv)))
195 if missing_dev:
196 results.append(
197 output_api.PresubmitPromptWarning(
198 'Missing PPAPI IDL for DEV, required before moving to stable:',
199 long_text='\n'.join(missing_dev)))
201 if missing_stable:
202 results.append(
203 output_api.PresubmitError(
204 'Missing PPAPI IDL for stable interface:',
205 long_text='\n'.join(missing_stable)))
207 # Verify all *.h files match *.idl definitions, use:
208 # --test to prevent output to disk
209 # --diff to generate a unified diff
210 # --out to pick which files to examine (only the ones in the CL)
211 ppapi_dir = input_api.PresubmitLocalPath()
212 cmd = [sys.executable, 'generator.py',
213 '--wnone', '--diff', '--test','--cgen', '--range=start,end']
215 # Only generate output for IDL files references (as *.h or *.idl) in this CL
216 cmd.append('--out=' + ','.join([name + '.idl' for name in both]))
217 cmd_results = RunCmdAndCheck(cmd,
218 'PPAPI IDL Diff detected: Run the generator.',
219 output_api,
220 os.path.join(ppapi_dir, 'generators'))
221 if cmd_results:
222 results.extend(cmd_results)
224 return results
227 def CheckChangeOnUpload(input_api, output_api):
228 return CheckChange(input_api, output_api)
231 def CheckChangeOnCommit(input_api, output_api):
232 return CheckChange(input_api, output_api)