cc: Stretch textures by .5 texels to prevent out of bounds sampling
[chromium-blink-merge.git] / ppapi / PRESUBMIT.py
blob57278e24a0de49efeb2543b599cf457c1df506c0
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_tests.py']
35 ppapi_dir = input_api.PresubmitLocalPath()
36 results.extend(RunCmdAndCheck(cmd,
37 'PPAPI IDL unittests failed.',
38 output_api,
39 os.path.join(ppapi_dir, 'generators')))
40 return results
43 # Verify that the files do not contain a 'TODO' in them.
44 RE_TODO = re.compile(r'\WTODO\W', flags=re.I)
45 def CheckTODO(input_api, output_api):
46 files = input_api.LocalPaths()
47 todo = []
49 for filename in files:
50 name, ext = os.path.splitext(filename)
51 name_parts = name.split(os.sep)
53 # Only check normal build sources.
54 if ext not in ['.h', '.idl']:
55 continue
57 # Only examine the ppapi directory.
58 if name_parts[0] != 'ppapi':
59 continue
61 # Only examine public plugin facing directories.
62 if name_parts[1] not in ['api', 'c', 'cpp', 'utility']:
63 continue
65 # Only examine public stable interfaces.
66 if name_parts[2] in ['dev', 'private', 'trusted']:
67 continue
69 filepath = os.path.join('..', filename)
70 if RE_TODO.search(open(filepath, 'rb').read()):
71 todo.append(filename)
73 if todo:
74 return [output_api.PresubmitError(
75 'TODOs found in stable public PPAPI files:',
76 long_text='\n'.join(todo))]
77 return []
79 # Verify that no CPP wrappers use un-versioned PPB interface name macros.
80 RE_UNVERSIONED_PPB = re.compile(r'\bPPB_\w+_INTERFACE\b')
81 def CheckUnversionedPPB(input_api, output_api):
82 files = input_api.LocalPaths()
83 todo = []
85 for filename in files:
86 name, ext = os.path.splitext(filename)
87 name_parts = name.split(os.sep)
89 # Only check C++ sources.
90 if ext not in ['.cc']:
91 continue
93 # Only examine the public plugin facing ppapi/cpp directory.
94 if name_parts[0:2] != ['ppapi', 'cpp']:
95 continue
97 # Only examine public stable and trusted interfaces.
98 if name_parts[2] in ['dev', 'private']:
99 continue
101 filepath = os.path.join('..', filename)
102 if RE_UNVERSIONED_PPB.search(open(filepath, 'rb').read()):
103 todo.append(filename)
105 if todo:
106 return [output_api.PresubmitError(
107 'Unversioned PPB interface references found in PPAPI C++ wrappers:',
108 long_text='\n'.join(todo))]
109 return []
111 def CheckChange(input_api, output_api):
112 results = []
114 results.extend(RunUnittests(input_api, output_api))
116 results.extend(CheckTODO(input_api, output_api))
118 results.extend(CheckUnversionedPPB(input_api, output_api))
120 # Verify all modified *.idl have a matching *.h
121 files = input_api.LocalPaths()
122 h_files = []
123 idl_files = []
125 # Find all relevant .h and .idl files.
126 for filename in files:
127 name, ext = os.path.splitext(filename)
128 name_parts = name.split(os.sep)
129 if name_parts[0:2] == ['ppapi', 'c'] and ext == '.h':
130 h_files.append('/'.join(name_parts[2:]))
131 if name_parts[0:2] == ['ppapi', 'api'] and ext == '.idl':
132 idl_files.append('/'.join(name_parts[2:]))
134 # Generate a list of all appropriate *.h and *.idl changes in this CL.
135 both = h_files + idl_files
137 # If there aren't any, we are done checking.
138 if not both: return results
140 missing = []
141 for filename in idl_files:
142 if filename not in set(h_files):
143 missing.append('ppapi/api/%s.idl' % filename)
145 # An IDL change that includes [generate_thunk] doesn't need to have
146 # an update to the corresponding .h file.
147 new_thunk_files = []
148 for filename in missing:
149 lines = input_api.RightHandSideLines(lambda f: f.LocalPath() == filename)
150 for line in lines:
151 if line[2].strip() == '[generate_thunk]':
152 new_thunk_files.append(filename)
153 for filename in new_thunk_files:
154 missing.remove(filename)
156 if missing:
157 results.append(
158 output_api.PresubmitPromptWarning(
159 'Missing PPAPI header, no change or skipped generation?',
160 long_text='\n '.join(missing)))
162 missing_dev = []
163 missing_stable = []
164 missing_priv = []
165 for filename in h_files:
166 if filename not in set(idl_files):
167 name_parts = filename.split(os.sep)
169 if 'trusted' in name_parts:
170 missing_priv.append(' ppapi/c/%s.h' % filename)
171 continue
173 if 'private' in name_parts:
174 missing_priv.append(' ppapi/c/%s.h' % filename)
175 continue
177 if 'dev' in name_parts:
178 missing_dev.append(' ppapi/c/%s.h' % filename)
179 continue
181 missing_stable.append(' ppapi/c/%s.h' % filename)
183 if missing_priv:
184 results.append(
185 output_api.PresubmitPromptWarning(
186 'Missing PPAPI IDL for private interface, please generate IDL:',
187 long_text='\n'.join(missing_priv)))
189 if missing_dev:
190 results.append(
191 output_api.PresubmitPromptWarning(
192 'Missing PPAPI IDL for DEV, required before moving to stable:',
193 long_text='\n'.join(missing_dev)))
195 if missing_stable:
196 results.append(
197 output_api.PresubmitError(
198 'Missing PPAPI IDL for stable interface:',
199 long_text='\n'.join(missing_stable)))
201 # Verify all *.h files match *.idl definitions, use:
202 # --test to prevent output to disk
203 # --diff to generate a unified diff
204 # --out to pick which files to examine (only the ones in the CL)
205 ppapi_dir = input_api.PresubmitLocalPath()
206 cmd = [sys.executable, 'generator.py',
207 '--wnone', '--diff', '--test','--cgen', '--range=start,end']
209 # Only generate output for IDL files references (as *.h or *.idl) in this CL
210 cmd.append('--out=' + ','.join([name + '.idl' for name in both]))
211 cmd_results = RunCmdAndCheck(cmd,
212 'PPAPI IDL Diff detected: Run the generator.',
213 output_api,
214 os.path.join(ppapi_dir, 'generators'))
215 if cmd_results:
216 results.extend(cmd_results)
218 return results
221 def CheckChangeOnUpload(input_api, output_api):
222 return CheckChange(input_api, output_api)
225 def CheckChangeOnCommit(input_api, output_api):
226 return CheckChange(input_api, output_api)