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

Side by Side Diff: tools/isolate/isolate_smoke_test.py

Issue 10019014: Convert isolate.py to exclusively use .isolate files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Do not read as binary Created 8 years, 8 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 | « tools/isolate/isolate.py ('k') | tools/isolate/isolate_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import cStringIO 6 import cStringIO
7 import hashlib 7 import hashlib
8 import json 8 import json
9 import logging 9 import logging
10 import os 10 import os
11 import re 11 import re
12 import shutil 12 import shutil
13 import subprocess 13 import subprocess
14 import sys 14 import sys
15 import tempfile 15 import tempfile
16 import unittest 16 import unittest
17 17
18 import isolate
19
18 ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) 20 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
19 VERBOSE = False 21 VERBOSE = False
20 FILENAME = os.path.basename(__file__) 22
21 23
22 24
23 class CalledProcessError(subprocess.CalledProcessError): 25 class CalledProcessError(subprocess.CalledProcessError):
24 """Makes 2.6 version act like 2.7""" 26 """Makes 2.6 version act like 2.7"""
25 def __init__(self, returncode, cmd, output, cwd): 27 def __init__(self, returncode, cmd, output, cwd):
26 super(CalledProcessError, self).__init__(returncode, cmd) 28 super(CalledProcessError, self).__init__(returncode, cmd)
27 self.output = output 29 self.output = output
28 self.cwd = cwd 30 self.cwd = cwd
29 31
30 def __str__(self): 32 def __str__(self):
31 return super(CalledProcessError, self).__str__() + ( 33 return super(CalledProcessError, self).__str__() + (
32 '\n' 34 '\n'
33 'cwd=%s\n%s') % (self.cwd, self.output) 35 'cwd=%s\n%s') % (self.cwd, self.output)
34 36
35 37
36 class Isolate(unittest.TestCase): 38 class Isolate(unittest.TestCase):
37 def setUp(self): 39 def setUp(self):
38 # The reason is that FILENAME --ok is run in a temporary directory 40 # The tests assume the current directory is the file's directory.
39 # without access to isolate.py 41 os.chdir(ROOT_DIR)
40 import isolate
41 self.isolate = isolate
42 self.tempdir = tempfile.mkdtemp() 42 self.tempdir = tempfile.mkdtemp()
43 self.result = os.path.join(self.tempdir, 'result') 43 self.result = os.path.join(self.tempdir, 'result')
44 self.child = os.path.join('data', 'isolate', 'child.py')
44 if VERBOSE: 45 if VERBOSE:
45 print 46 print
47 self.files = [
48 self.child,
49 os.path.join('data', 'isolate', 'files1', 'test_file1.txt'),
50 os.path.join('data', 'isolate', 'files1', 'test_file2.txt'),
51 ]
46 52
47 def tearDown(self): 53 def tearDown(self):
48 shutil.rmtree(self.tempdir) 54 shutil.rmtree(self.tempdir)
49 55
50 def _expected_tree(self, files): 56 def _expected_tree(self, files):
51 self.assertEquals(sorted(files), sorted(os.listdir(self.tempdir))) 57 self.assertEquals(sorted(files), sorted(os.listdir(self.tempdir)))
52 58
53 def _expected_result(self, with_hash, files, args, read_only): 59 def _expected_result(self, with_hash, files, args, read_only):
54 if sys.platform == 'win32': 60 if sys.platform == 'win32':
55 mode = lambda _: 420 61 mode = lambda _: 420
56 else: 62 else:
57 # 4 modes are supported, 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r) 63 # 4 modes are supported, 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r)
58 min_mode = 0444 64 min_mode = 0444
59 if not read_only: 65 if not read_only:
60 min_mode |= 0200 66 min_mode |= 0200
61 def mode(filename): 67 def mode(filename):
62 return (min_mode | 0111) if filename.endswith('.py') else min_mode 68 return (min_mode | 0111) if filename.endswith('.py') else min_mode
69
70 if not isinstance(files, dict):
71 # Update files to dict.
72 files = dict((unicode(f), {u'mode': mode(f)}) for f in files)
73 # Add size and timestamp.
74 files = files.copy()
75 for k, v in files.iteritems():
76 if v:
77 filestats = os.stat(k)
78 v[u'size'] = filestats.st_size
79 # Used the skip recalculating the hash. Use the most recent update
80 # time.
81 v[u'timestamp'] = int(round(
82 max(filestats.st_mtime, filestats.st_ctime)))
83
63 expected = { 84 expected = {
64 u'command': 85 u'files': files,
65 [unicode(sys.executable)] + 86 u'relative_cwd': u'data/isolate',
66 [unicode(x) for x in args], 87 u'read_only': None,
67 u'files': dict((unicode(f), {u'mode': mode(f)}) for f in files),
68 u'relative_cwd': u'.',
69 u'read_only': False,
70 } 88 }
89 if args:
90 expected[u'command'] = [u'python'] + [unicode(x) for x in args]
91 else:
92 expected[u'command'] = []
71 if with_hash: 93 if with_hash:
72 for filename in expected[u'files']: 94 for filename in expected[u'files']:
73 # Calculate our hash. 95 # Calculate our hash.
74 h = hashlib.sha1() 96 h = hashlib.sha1()
75 h.update(open(os.path.join(ROOT_DIR, filename), 'rb').read()) 97 h.update(open(os.path.join(ROOT_DIR, filename), 'rb').read())
76 expected[u'files'][filename][u'sha-1'] = h.hexdigest() 98 expected[u'files'][filename][u'sha-1'] = unicode(h.hexdigest())
77 99
78 actual = json.load(open(self.result, 'rb')) 100 actual = json.load(open(self.result, 'rb'))
79 self.assertEquals(expected, actual) 101 self.assertEquals(expected, actual)
80 return expected 102 return expected
81 103
82 def _execute(self, args, need_output=False): 104 def _execute(self, filename, args, need_output=False):
83 cmd = [ 105 cmd = [
84 sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), 106 sys.executable, os.path.join(ROOT_DIR, 'isolate.py'),
85 '--root', ROOT_DIR, 107 '--variable', 'DEPTH=%s' % ROOT_DIR,
86 '--result', self.result, 108 '--result', self.result,
87 ] 109 os.path.join(ROOT_DIR, 'data', 'isolate', filename),
110 ] + args
111 env = os.environ.copy()
112 if 'ISOLATE_DEBUG' in env:
113 del env['ISOLATE_DEBUG']
88 if need_output or not VERBOSE: 114 if need_output or not VERBOSE:
89 stdout = subprocess.PIPE 115 stdout = subprocess.PIPE
90 stderr = subprocess.STDOUT 116 stderr = subprocess.STDOUT
91 else: 117 else:
92 cmd.extend(['-v'] * 3) 118 cmd.extend(['-v'] * 3)
93 stdout = None 119 stdout = None
94 stderr = None 120 stderr = None
95 cwd = ROOT_DIR 121 cwd = ROOT_DIR
96 p = subprocess.Popen( 122 p = subprocess.Popen(
97 cmd + args, 123 cmd + args,
98 stdout=stdout, 124 stdout=stdout,
99 stderr=stderr, 125 stderr=stderr,
100 cwd=cwd, 126 cwd=cwd,
127 env=env,
101 universal_newlines=True) 128 universal_newlines=True)
102 out = p.communicate()[0] 129 out = p.communicate()[0]
103 if p.returncode: 130 if p.returncode:
104 raise CalledProcessError(p.returncode, cmd, out, cwd) 131 raise CalledProcessError(p.returncode, cmd, out, cwd)
105 return out 132 return out
106 133
107 def test_help_modes(self): 134 def test_help_modes(self):
108 # Check coherency in the help and implemented modes. 135 # Check coherency in the help and implemented modes.
109 p = subprocess.Popen( 136 p = subprocess.Popen(
110 [sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), '--help'], 137 [sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), '--help'],
111 stdout=subprocess.PIPE, 138 stdout=subprocess.PIPE,
112 stderr=subprocess.STDOUT, 139 stderr=subprocess.STDOUT,
113 cwd=ROOT_DIR) 140 cwd=ROOT_DIR)
114 out = p.communicate()[0].splitlines() 141 out = p.communicate()[0].splitlines()
115 self.assertEquals(0, p.returncode) 142 self.assertEquals(0, p.returncode)
116 out = out[out.index('') + 1:] 143 out = out[out.index('') + 1:]
117 out = out[:out.index('')] 144 out = out[:out.index('')]
118 modes = [re.match(r'^ (\w+) .+', l) for l in out] 145 modes = [re.match(r'^ (\w+) .+', l) for l in out]
119 modes = tuple(m.group(1) for m in modes if m) 146 modes = tuple(m.group(1) for m in modes if m)
120 # Keep the list hard coded. 147 # Keep the list hard coded.
121 expected = ('check', 'hashtable', 'remap', 'run', 'trace') 148 expected = ('check', 'hashtable', 'remap', 'run', 'trace')
122 self.assertEquals(expected, modes) 149 self.assertEquals(expected, modes)
123 self.assertEquals(expected, modes) 150 self.assertEquals(expected, modes)
124 for mode in modes: 151 for mode in modes:
125 self.assertTrue(hasattr(self, 'test_%s' % mode), mode) 152 self.assertTrue(hasattr(self, 'test_%s' % mode), mode)
126 self._expected_tree([]) 153 self._expected_tree([])
127 154
128 def test_check(self): 155 def test_check(self):
129 cmd = [ 156 self._execute('fail.isolate', ['--mode', 'check'])
130 '--mode', 'check',
131 FILENAME,
132 ]
133 self._execute(cmd)
134 self._expected_tree(['result']) 157 self._expected_tree(['result'])
135 self._expected_result( 158 self._expected_result(
136 False, 159 False, dict((f, {}) for f in self.files), ['child.py', '--fail'], False)
137 [FILENAME],
138 [os.path.join('.', FILENAME)],
139 False)
140 160
141 def test_check_non_existant(self): 161 def test_check_no_run(self):
142 cmd = [ 162 self._execute('no_run.isolate', ['--mode', 'check'])
143 '--mode', 'check', 163 self._expected_tree(['result'])
144 'NonExistentFile', 164 self._expected_result(
145 ] 165 False, dict((f, {}) for f in self.files), None, False)
166
167 def test_check_non_existent(self):
146 try: 168 try:
147 self._execute(cmd) 169 self._execute('non_existent.isolate', ['--mode', 'check'])
148 self.fail() 170 self.fail()
149 except subprocess.CalledProcessError: 171 except subprocess.CalledProcessError:
150 pass 172 pass
151 self._expected_tree([]) 173 self._expected_tree([])
152 174
153 def test_check_directory_no_slash(self): 175 def test_check_directory_no_slash(self):
154 cmd = [
155 '--mode', 'check',
156 # Trailing slash missing.
157 os.path.join('data', 'isolate'),
158 ]
159 try: 176 try:
160 self._execute(cmd) 177 self._execute('missing_trailing_slash.isolate', ['--mode', 'check'])
161 self.fail() 178 self.fail()
162 except subprocess.CalledProcessError: 179 except subprocess.CalledProcessError:
163 pass 180 pass
164 self._expected_tree([]) 181 self._expected_tree([])
165 182
166 def test_check_abs_path(self):
167 cmd = [
168 '--mode', 'check',
169 FILENAME,
170 '--',
171 os.path.join(ROOT_DIR, FILENAME),
172 ]
173 self._execute(cmd)
174 self._expected_tree(['result'])
175 self._expected_result(
176 False, [FILENAME], [FILENAME], False)
177
178 def test_hashtable(self): 183 def test_hashtable(self):
179 cmd = [ 184 cmd = [
180 '--mode', 'hashtable', 185 '--mode', 'hashtable',
181 '--outdir', self.tempdir, 186 '--outdir', self.tempdir,
182 FILENAME,
183 os.path.join('data', 'isolate') + os.path.sep,
184 ] 187 ]
185 self._execute(cmd) 188 self._execute('no_run.isolate', cmd)
186 files = [ 189 data = self._expected_result(True, self.files, None, False)
187 FILENAME,
188 os.path.join('data', 'isolate', 'test_file1.txt'),
189 os.path.join('data', 'isolate', 'test_file2.txt'),
190 ]
191 data = self._expected_result(
192 True, files, [os.path.join('.', FILENAME)], False)
193 self._expected_tree( 190 self._expected_tree(
194 [f['sha-1'] for f in data['files'].itervalues()] + ['result']) 191 [f['sha-1'] for f in data['files'].itervalues()] + ['result'])
195 192
196 def test_remap(self): 193 def test_remap(self):
197 cmd = [ 194 cmd = [
198 '--mode', 'remap', 195 '--mode', 'remap',
199 '--outdir', self.tempdir, 196 '--outdir', self.tempdir,
200 FILENAME,
201 ] 197 ]
202 self._execute(cmd) 198 self._execute('no_run.isolate', cmd)
203 self._expected_tree([FILENAME, 'result']) 199 self._expected_tree(['data', 'result'])
204 self._expected_result( 200 self._expected_result(
205 False, 201 False,
206 [FILENAME], 202 self.files,
207 [os.path.join('.', FILENAME)], 203 None,
208 False) 204 False)
209 205
210 def test_run(self): 206 def test_run(self):
211 cmd = [ 207 self._execute('ok.isolate', ['--mode', 'run'])
212 '--mode', 'run',
213 FILENAME,
214 '--',
215 sys.executable, FILENAME, '--ok',
216 ]
217 self._execute(cmd)
218 self._expected_tree(['result']) 208 self._expected_tree(['result'])
219 # cmd[0] is not generated from infiles[0] so it's not using a relative path. 209 # cmd[0] is not generated from infiles[0] so it's not using a relative path.
220 self._expected_result( 210 self._expected_result(
221 False, [FILENAME], [FILENAME, '--ok'], False) 211 False, self.files, ['child.py', '--ok'], False)
222 212
223 def test_run_fail(self): 213 def test_run_fail(self):
224 cmd = [
225 '--mode', 'run',
226 FILENAME,
227 '--',
228 sys.executable, FILENAME, '--fail',
229 ]
230 try: 214 try:
231 self._execute(cmd) 215 self._execute('fail.isolate', ['--mode', 'run'])
232 self.fail() 216 self.fail()
233 except subprocess.CalledProcessError: 217 except subprocess.CalledProcessError:
234 pass 218 pass
235 self._expected_tree([]) 219 self._expected_tree(['result'])
236 220
237 def test_trace(self): 221 def test_trace(self):
238 cmd = [ 222 out = self._execute('ok.isolate', ['--mode', 'trace'], True)
239 '--mode', 'trace', 223 self._expected_tree(['result', 'result.log'])
240 FILENAME,
241 '--',
242 sys.executable, os.path.join(ROOT_DIR, FILENAME), '--ok',
243 ]
244 out = self._execute(cmd, True)
245 expected_tree = ['result', 'result.log']
246 if sys.platform == 'win32':
247 expected_tree.append('result.log.etl')
248 self._expected_tree(expected_tree)
249 # The 'result.log' log is OS-specific so we can't read it but we can read 224 # The 'result.log' log is OS-specific so we can't read it but we can read
250 # the gyp result. 225 # the gyp result.
251 # cmd[0] is not generated from infiles[0] so it's not using a relative path. 226 # cmd[0] is not generated from infiles[0] so it's not using a relative path.
252 self._expected_result( 227 self._expected_result(
253 False, [FILENAME], [FILENAME, '--ok'], False) 228 False, self.files, ['child.py', '--ok'], False)
254 229
255 expected_value = { 230 expected_value = {
256 'conditions': [ 231 'conditions': [
257 ['OS=="%s"' % self.isolate.trace_inputs.get_flavor(), { 232 ['OS=="%s"' % isolate.trace_inputs.get_flavor(), {
258 'variables': { 233 'variables': {
259 'isolate_files': [ 234 isolate.trace_inputs.KEY_TRACKED: [
260 '<(DEPTH)/%s' % FILENAME, 235 'child.py',
236 ],
237 isolate.trace_inputs.KEY_UNTRACKED: [
238 'files1/',
261 ], 239 ],
262 }, 240 },
263 }], 241 }],
264 ], 242 ],
265 } 243 }
266 expected_buffer = cStringIO.StringIO() 244 expected_buffer = cStringIO.StringIO()
267 self.isolate.trace_inputs.pretty_print(expected_value, expected_buffer) 245 isolate.trace_inputs.pretty_print(expected_value, expected_buffer)
268 self.assertEquals(expected_buffer.getvalue(), out) 246 self.assertEquals(expected_buffer.getvalue(), out)
269 247
270 248
271 def main():
272 global VERBOSE
273 VERBOSE = '-v' in sys.argv
274 level = logging.DEBUG if VERBOSE else logging.ERROR
275 logging.basicConfig(level=level)
276 if len(sys.argv) == 1:
277 unittest.main()
278 if sys.argv[1] == '--ok':
279 return 0
280 if sys.argv[1] == '--fail':
281 return 1
282
283 unittest.main()
284
285 249
286 if __name__ == '__main__': 250 if __name__ == '__main__':
287 sys.exit(main()) 251 VERBOSE = '-v' in sys.argv
252 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
253 unittest.main()
OLDNEW
« no previous file with comments | « tools/isolate/isolate.py ('k') | tools/isolate/isolate_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698