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

Side by Side Diff: trunk/test/lib/TestGyp.py

Issue 160351: Test infrastructure for end-to-end tests of GYP generators, and... (Closed) Base URL: http://gyp.googlecode.com/svn/
Patch Set: '' Created 11 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « trunk/test/lib/TestCommon.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Name: svn:eol-style
+ LF
OLDNEW
(Empty)
1 #!/usr/bin/python
2
3 """
4 TestGyp.py: a testing framework for GYP integration tests.
5 """
6
7 import os
8 import shutil
9 import stat
10 import sys
11
12 import TestCommon
13 from TestCommon import __all__
14
15 __all__.extend([
16 'TestGyp',
17 ])
18
19
20 class TestGypBase(TestCommon.TestCommon):
21 """
22 Class for controlling end-to-end tests of gyp generators.
23
24 Instantiating this class will create a temporary directory and
25 arrange for its destruction (via the TestCmd superclass) and
26 copy all of the non-gyptest files in the directory hierarchy of the
27 executing script.
28
29 The default behavior is to test the 'gyp' or 'gyp.bat' file in the
30 current directory. An alternative may be specified explicitly on
31 instantiation, or by setting the TESTGYP_GYP environment variable.
32
33 This class should be subclassed for each supported gyp generator
34 (format). Various abstract methods below define calling signatures
35 used by the test scripts to invoke builds on the generated build
36 configuration and to run executables generated by those builds.
37 """
38
39 build_tool = None
40
41 def __init__(self, gyp=None, *args, **kw):
42 self.origin_cwd = os.path.abspath(os.path.dirname(sys.argv[0]))
43
44 if not gyp:
45 gyp = os.environ.get('TESTGYP_GYP')
46 if not gyp:
47 if sys.platform == 'win32':
48 gyp = 'gyp.bat'
49 else:
50 gyp = 'gyp'
51 self.gyp = os.path.abspath(gyp)
52
53 self.initialize_build_tool()
54
55 if not kw.has_key('match'):
56 kw['match'] = TestCommon.match_exact
57
58 if not kw.has_key('workdir'):
59 # Default behavior: the null string causes TestCmd to create
60 # a temporary directory for us.
61 kw['workdir'] = ''
62
63 super(TestGypBase, self).__init__(*args, **kw)
64
65 self.copy_test_configuration(self.origin_cwd, self.workdir)
66
67 def copy_test_configuration(self, source_dir, dest_dir):
68 """
69 Copies the test configuration from the specified source_dir
70 (the directory in which the test script lives) to the
71 specified dest_dir (a temporary working directory).
72
73 This ignores all files and directories that begin with
74 the string 'gyptest', and all '.svn' subdirectories.
75 """
76 for root, dirs, files in os.walk(source_dir):
77 if '.svn' in dirs:
78 dirs.remove('.svn')
79 dirs = [ d for d in dirs if not d.startswith('gyptest') ]
80 files = [ f for f in files if not f.startswith('gyptest') ]
81 for dirname in dirs:
82 source = os.path.join(root, dirname)
83 destination = source.replace(source_dir, dest_dir)
84 os.mkdir(destination)
85 if sys.platform != 'win32':
86 shutil.copystat(source, destination)
87 for filename in files:
88 source = os.path.join(root, filename)
89 destination = source.replace(source_dir, dest_dir)
90 shutil.copy2(source, destination)
91
92 def initialize_build_tool(self):
93 """
94 Initializes the .build_tool attribute to the absolute path of
95 an actual executable on the user's $PATH.
96 """
97 if self.build_tool and not os.path.isabs(self.build_tool):
98 build_tool = self.where_is(self.build_tool)
99 if build_tool:
100 self.build_tool = build_tool
101
102 def run_gyp(self, gyp_file, *args, **kw):
103 """
104 Runs gyp against the specified gyp_file with the specified args.
105 """
106 # TODO: --depth=. works around Chromium-specific tree climbing.
107 args = ('--depth=.', '--format='+self.format) + args
108 return self.run(program=self.gyp, arguments=args, **kw)
109
110 #
111 # Abstract methods to be defined by format-specific subclasses.
112 #
113
114 def build_all(self, gyp_file):
115 """
116 Runs an "all" build of the configuration generated from the
117 specified gyp_file.
118 """
119 raise NotImplementeError
120
121 def build_default(self, gyp_file):
122 """
123 Runs the default build of the configuration generated from the
124 specified gyp_file.
125 """
126 raise NotImplementeError
127
128 def build_target(self, gyp_file, target):
129 """
130 Runs a build of the specified target against the configuration
131 generated from the specified gyp_file.
132 """
133 raise NotImplementeError
134
135 def run_built_executable(self, name, *args, **kw):
136 """
137 Runs an executable program built from a gyp-generated configuration.
138
139 The specified name should be independent of any particular generator.
140 Subclasses should find the output executable in the appropriate
141 output build directory, tack on any necessary executable suffix, etc.
142 """
143 raise NotImplementeError
144
145
146 class TestGypMake(TestGypBase):
147 """
148 Subclass for testing the GYP Make generator.
149 """
150 format = 'make'
151 build_tool = 'make'
152 def build_all(self, gyp_file):
153 """
154 Builds the Make 'all' target to build all targets for the Makefiles
155 generated from the specified gyp_file.
156 """
157 self.run_build(gyp_file, 'all')
158 def build_default(self, gyp_file):
159 """
160 Runs Make with no additional command-line arguments to get the
161 default build for the Makefiles generated from the specified gyp_file.
162 """
163 self.run_build(gyp_file)
164 def build_target(self, gyp_file, target):
165 """
166 Runs a Make build with the specified target on the command line
167 to build just that target using the Makefile generated from the
168 specified gyp_file.
169 """
170 self.run_build(gyp_file, target)
171 def run_build(self, gyp_file, *args):
172 """
173 Runs a Make build using the Makefiles generated from the specified
174 gyp_file.
175 """
176 return self.run(program=self.build_tool, arguments=args)
177 def run_built_executable(self, name, *args, **kw):
178 """
179 Runs an executable built by Make.
180 """
181 # TODO: generalize to different configurations.
182 program = self.workpath('out/Debug/' + name)
183 return self.run(program=program, *args, **kw)
184
185
186 class TestGypMSVS(TestGypBase):
187 """
188 Subclass for testing the GYP Visual Studio generator.
189 """
190 format = 'msvs'
191 build_tool = 'devenv'
192 def build_all(self, gyp_file):
193 """
194 Runs devenv.exe with no target-specific options to get the "all"
195 build for the Visual Studio configuration generated from the
196 specified gyp_file.
197
198 (NOTE: This is the same as the default, our generated Visual Studio
199 configuration doesn't create an explicit "all" target.)
200 """
201 return self.run_build(gyp_file)
202 def build_default(self, gyp_file):
203 """
204 Runs devenv.exe with no target-specific options to get the default
205 build for the Visual Studio configuration generated from the
206 specified gyp_file.
207 """
208 return self.run_build(gyp_file)
209 def build_target(self, gyp_file, target):
210 """
211 Uses the devenv.exe /Project option to build the specified target with
212 the Visual Studio configuration generated from the specified gyp_file.
213 """
214 return self.run_build(gyp_file, '/Project', target)
215 def initialize_build_tool(self):
216 """
217 Initializes the Visual Studio .build_tool parameter, searching %PATH%
218 and %PATHEXT% for a devenv.{exe,bat,...} executable, and falling
219 back to a hard-coded default (on the current drive) if necessary.
220 """
221 build_tool = self.where_is(self.build_tool)
222 if build_tool:
223 self.build_tool = build_tool
224 return
225 # We didn't find 'devenv' on the path. Just hard-code a default,
226 # and revisit this if it becomes important.
227 self.build_tool = os.path.join('\\Program Files',
228 'Microsoft Visual Studio 8',
229 'Common7',
230 'IDE',
231 'devenv.exe')
232 def run_build(self, gyp_file, *args):
233 """
234 Runs a Visual Studio build using the configuration generated
235 from the specified gyp_file.
236 """
237 # TODO: generalize to different configurations.
238 args = (gyp_file.replace('.gyp', '.sln'), '/Build', 'Default') + args
239 return self.run(program=self.build_tool, arguments=args)
240 def run_built_executable(self, name, *args, **kw):
241 """
242 Runs an executable built by Visual Studio.
243 """
244 # TODO: generalize to different configurations.
245 program = self.workpath('Default/%s.exe' % name)
246 return self.run(program=program, *args, **kw)
247
248
249 class TestGypSCons(TestGypBase):
250 """
251 Subclass for testing the GYP SCons generator.
252 """
253 format = 'scons'
254 build_tool = 'scons'
255 def build_all(self, gyp_file):
256 """
257 Builds the scons 'all' target to build all targets for the
258 SCons configuration generated from the specified gyp_file.
259 """
260 self.run_build(gyp_file, 'all')
261 def build_default(self, gyp_file):
262 """
263 Runs scons with no additional command-line arguments to get the
264 default build for the SCons configuration generated from the
265 specified gyp_file.
266 """
267 self.run_build(gyp_file)
268 def build_target(self, gyp_file, target):
269 """
270 Runs a scons build with the specified target on the command line to
271 build just that target using the SCons configuration generated from
272 the specified gyp_file.
273 """
274 self.run_build(gyp_file, target)
275 def run_build(self, gyp_file, *args):
276 """
277 Runs a scons build using the SCons configuration generated from the
278 specified gyp_file.
279 """
280 return self.run(program=self.build_tool, arguments=args)
281 def run_built_executable(self, name, *args, **kw):
282 """
283 Runs an executable built by scons.
284 """
285 # TODO: generalize to different configurations.
286 program = self.workpath('Default/' + name)
287 return self.run(program=program, *args, **kw)
288
289
290 class TestGypXcode(TestGypBase):
291 """
292 Subclass for testing the GYP Xcode generator.
293 """
294 format = 'xcode'
295 build_tool = 'xcodebuild'
296 def build_all(self, gyp_file):
297 """
298 Uses the xcodebuild -alltargets option to build all targets for the
299 .xcodeproj generated from the specified gyp_file.
300 """
301 return self.run_build(gyp_file, '-alltargets')
302 def build_default(self, gyp_file):
303 """
304 Runs xcodebuild with no target-specific options to get the default
305 build for the .xcodeproj generated from the specified gyp_file.
306 """
307 return self.run_build(gyp_file)
308 def build_target(self, gyp_file, target):
309 """
310 Uses the xcodebuild -target option to build the specified target
311 with the .xcodeproj generated from the specified gyp_file.
312 """
313 return self.run_build(gyp_file, '-target', target)
314 def run_build(self, gyp_file, *args):
315 """
316 Runs an xcodebuild using the .xcodeproj generated from the specified
317 gyp_file.
318 """
319 args = ('-project', gyp_file.replace('.gyp', '.xcodeproj')) + args
320 return self.run(program=self.build_tool, arguments=args)
321 def run_built_executable(self, name, *args, **kw):
322 """
323 Runs an executable built by xcodebuild.
324 """
325 # TODO: generalize to different configurations.
326 program = self.workpath('build/Default/' + name)
327 return self.run(program=program, *args, **kw)
328
329
330 format_class_list = [
331 TestGypMake,
332 TestGypMSVS,
333 TestGypSCons,
334 TestGypXcode,
335 ]
336
337 def TestGyp(*args, **kw):
338 """
339 Returns an appropriate TestGyp* instance for a specified GYP format.
340 """
341 format = kw.get('format')
342 if not format:
343 format = os.environ.get('TESTGYP_FORMAT')
344 for format_class in format_class_list:
345 if format == format_class.format:
346 return format_class(*args, **kw)
347 raise Exception, "unknown format %r" % format
OLDNEW
« no previous file with comments | « trunk/test/lib/TestCommon.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698