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

Side by Side Diff: appengine/swarming/swarming_bot/bot_code/task_runner_test.py

Issue 2300543002: Minor refactoring in task_runner.py in preparation for adding more code. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: Minor refactoring in task_runner.py in preparation for adding more code. Created 4 years, 3 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
« no previous file with comments | « appengine/swarming/swarming_bot/bot_code/task_runner.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')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # coding=utf-8 2 # coding=utf-8
3 # Copyright 2013 The LUCI Authors. All rights reserved. 3 # Copyright 2013 The LUCI Authors. All rights reserved.
4 # Use of this source code is governed under the Apache License, Version 2.0 4 # Use of this source code is governed under the Apache License, Version 2.0
5 # that can be found in the LICENSE file. 5 # that can be found in the LICENSE file.
6 6
7 import base64 7 import base64
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 signal 12 import signal
13 import sys 13 import sys
14 import tempfile 14 import tempfile
15 import time 15 import time
16 import unittest 16 import unittest
17 17
18 import test_env_bot_code 18 import test_env_bot_code
19 test_env_bot_code.setup_test_env() 19 test_env_bot_code.setup_test_env()
20 20
21 # Creates a server mock for functions in net.py. 21 # Creates a server mock for functions in net.py.
22 import net_utils 22 import net_utils
23 23
24 from depot_tools import fix_encoding 24 from depot_tools import fix_encoding
25 from utils import file_path 25 from utils import file_path
26 from utils import large 26 from utils import large
27 from utils import logging_utils 27 from utils import logging_utils
28 from utils import subprocess42 28 from utils import subprocess42
29 import bot_auth
29 import fake_swarming 30 import fake_swarming
30 import task_runner 31 import task_runner
31 32
32 CLIENT_DIR = os.path.normpath( 33 CLIENT_DIR = os.path.normpath(
33 os.path.join(test_env_bot_code.BOT_DIR, '..', '..', '..', 'client')) 34 os.path.join(test_env_bot_code.BOT_DIR, '..', '..', '..', 'client'))
34 35
35 sys.path.insert(0, os.path.join(CLIENT_DIR, 'tests')) 36 sys.path.insert(0, os.path.join(CLIENT_DIR, 'tests'))
36 import isolateserver_mock 37 import isolateserver_mock
37 38
38 39
39 def get_manifest(script=None, isolated=None, **kwargs): 40 def get_manifest(script=None, isolated=None, **kwargs):
40 isolated_input = isolated and isolated.get('input') 41 isolated_input = isolated and isolated.get('input')
41 out = { 42 out = {
42 'bot_id': 'localhost', 43 'bot_id': 'localhost',
43 'command': 44 'command':
44 [sys.executable, '-u', '-c', script] if not isolated_input else None, 45 [sys.executable, '-u', '-c', script] if not isolated_input else None,
45 'env': {}, 46 'env': {},
46 'extra_args': [], 47 'extra_args': [],
47 'grace_period': 30., 48 'grace_period': 30.,
48 'hard_timeout': 10., 49 'hard_timeout': 10.,
49 'io_timeout': 10., 50 'io_timeout': 10.,
50 'isolated': isolated, 51 'isolated': isolated,
51 'task_id': 23, 52 'task_id': 23,
52 } 53 }
53 out.update(kwargs) 54 out.update(kwargs)
54 return out 55 return out
55 56
56 57
58 class FakeAuthSystem(object):
59 def __init__(self):
60 self._running = False
61
62 def start(self, auth_params_file):
63 assert auth_params_file == '/path/to/auth-params-file'
64 assert not self._running
65 self._running = True
66
67 def stop(self):
68 self._running = False
69
70 @property
71 def bot_headers(self):
72 assert self._running
73 return {'Fake': 'Header'}
74
75
57 class TestTaskRunnerBase(net_utils.TestCase): 76 class TestTaskRunnerBase(net_utils.TestCase):
58 def setUp(self): 77 def setUp(self):
59 super(TestTaskRunnerBase, self).setUp() 78 super(TestTaskRunnerBase, self).setUp()
60 self.root_dir = tempfile.mkdtemp(prefix='task_runner') 79 self.root_dir = tempfile.mkdtemp(prefix='task_runner')
61 logging.info('Temp: %s', self.root_dir) 80 logging.info('Temp: %s', self.root_dir)
62 self.work_dir = os.path.join(self.root_dir, 'w') 81 self.work_dir = os.path.join(self.root_dir, 'w')
63 os.chdir(self.root_dir) 82 os.chdir(self.root_dir)
64 os.mkdir(self.work_dir) 83 os.mkdir(self.work_dir)
65 # Create the logs directory so run_isolated.py can put its log there. 84 # Create the logs directory so run_isolated.py can put its log there.
66 self._logs = os.path.join(self.root_dir, 'logs') 85 self._logs = os.path.join(self.root_dir, 'logs')
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 'task_id': 23, 174 'task_id': 23,
156 }, 175 },
157 'follow_redirects': False, 176 'follow_redirects': False,
158 'headers': auth_headers or {}, 177 'headers': auth_headers or {},
159 } 178 }
160 if outputs_ref: 179 if outputs_ref:
161 expected['data']['outputs_ref'] = outputs_ref 180 expected['data']['outputs_ref'] = outputs_ref
162 self.assertEqual(expected, kwargs) 181 self.assertEqual(expected, kwargs)
163 return check_final 182 return check_final
164 183
165 def _run_command(self, task_details, auth_params_file=None): 184 def _run_command(self, task_details, headers_cb=None):
166 start = time.time() 185 start = time.time()
167 self.mock(time, 'time', lambda: start + 10) 186 self.mock(time, 'time', lambda: start + 10)
168 server = 'https://localhost:1' 187 server = 'https://localhost:1'
169 return task_runner.run_command( 188 return task_runner.run_command(
170 server, task_details, self.work_dir, 3600., start, 1, 189 server, task_details, self.work_dir, 3600., start, 1,
171 '/path/to/file', auth_params_file) 190 '/path/to/file', headers_cb or (lambda: {}))
172 191
173 def test_load_and_run_raw(self): 192 def test_load_and_run_raw(self):
174 server = 'https://localhost:1' 193 server = 'https://localhost:1'
175 194
195 self.mock(bot_auth, 'AuthSystem', FakeAuthSystem)
196
176 def run_command( 197 def run_command(
177 swarming_server, task_details, work_dir, 198 swarming_server, task_details, work_dir,
178 cost_usd_hour, start, min_free_space, bot_file, auth_params_file): 199 cost_usd_hour, start, min_free_space, bot_file, headers_cb):
179 self.assertEqual(server, swarming_server) 200 self.assertEqual(server, swarming_server)
180 self.assertTrue(isinstance(task_details, task_runner.TaskDetails)) 201 self.assertTrue(isinstance(task_details, task_runner.TaskDetails))
181 # Necessary for OSX. 202 # Necessary for OSX.
182 self.assertEqual( 203 self.assertEqual(
183 os.path.realpath(self.work_dir), os.path.realpath(work_dir)) 204 os.path.realpath(self.work_dir), os.path.realpath(work_dir))
184 self.assertEqual(3600., cost_usd_hour) 205 self.assertEqual(3600., cost_usd_hour)
185 self.assertEqual(time.time(), start) 206 self.assertEqual(time.time(), start)
186 self.assertEqual(1, min_free_space) 207 self.assertEqual(1, min_free_space)
187 self.assertEqual('/path/to/bot-file', bot_file) 208 self.assertEqual('/path/to/bot-file', bot_file)
188 self.assertEqual('/path/to/auth-params-file', auth_params_file) 209 self.assertEqual({'Fake': 'Header'}, headers_cb())
189 return { 210 return {
190 u'exit_code': 1, 211 u'exit_code': 1,
191 u'hard_timeout': False, 212 u'hard_timeout': False,
192 u'io_timeout': False, 213 u'io_timeout': False,
193 u'must_signal_internal_failure': None, 214 u'must_signal_internal_failure': None,
194 u'version': task_runner.OUT_VERSION, 215 u'version': task_runner.OUT_VERSION,
195 } 216 }
196 self.mock(task_runner, 'run_command', run_command) 217 self.mock(task_runner, 'run_command', run_command)
197 218
198 manifest = os.path.join(self.root_dir, 'manifest') 219 manifest = os.path.join(self.root_dir, 'manifest')
(...skipping 22 matching lines...) Expand all
221 u'must_signal_internal_failure': None, 242 u'must_signal_internal_failure': None,
222 u'version': task_runner.OUT_VERSION, 243 u'version': task_runner.OUT_VERSION,
223 } 244 }
224 with open(out_file, 'rb') as f: 245 with open(out_file, 'rb') as f:
225 self.assertEqual(expected, json.load(f)) 246 self.assertEqual(expected, json.load(f))
226 247
227 def test_load_and_run_isolated(self): 248 def test_load_and_run_isolated(self):
228 self.expected_requests([]) 249 self.expected_requests([])
229 server = 'https://localhost:1' 250 server = 'https://localhost:1'
230 251
252 self.mock(bot_auth, 'AuthSystem', FakeAuthSystem)
253
231 def run_command( 254 def run_command(
232 swarming_server, task_details, work_dir, 255 swarming_server, task_details, work_dir,
233 cost_usd_hour, start, min_free_space, bot_file, auth_params_file): 256 cost_usd_hour, start, min_free_space, bot_file, headers_cb):
234 self.assertEqual(server, swarming_server) 257 self.assertEqual(server, swarming_server)
235 self.assertTrue(isinstance(task_details, task_runner.TaskDetails)) 258 self.assertTrue(isinstance(task_details, task_runner.TaskDetails))
236 # Necessary for OSX. 259 # Necessary for OSX.
237 self.assertEqual( 260 self.assertEqual(
238 os.path.realpath(self.work_dir), os.path.realpath(work_dir)) 261 os.path.realpath(self.work_dir), os.path.realpath(work_dir))
239 self.assertEqual(3600., cost_usd_hour) 262 self.assertEqual(3600., cost_usd_hour)
240 self.assertEqual(time.time(), start) 263 self.assertEqual(time.time(), start)
241 self.assertEqual(1, min_free_space) 264 self.assertEqual(1, min_free_space)
242 self.assertEqual('/path/to/bot-file', bot_file) 265 self.assertEqual('/path/to/bot-file', bot_file)
243 self.assertEqual('/path/to/auth-params-file', auth_params_file) 266 self.assertEqual({'Fake': 'Header'}, headers_cb())
244 return { 267 return {
245 u'exit_code': 0, 268 u'exit_code': 0,
246 u'hard_timeout': False, 269 u'hard_timeout': False,
247 u'io_timeout': False, 270 u'io_timeout': False,
248 u'must_signal_internal_failure': None, 271 u'must_signal_internal_failure': None,
249 u'version': task_runner.OUT_VERSION, 272 u'version': task_runner.OUT_VERSION,
250 } 273 }
251 self.mock(task_runner, 'run_command', run_command) 274 self.mock(task_runner, 'run_command', run_command)
252 275
253 manifest = os.path.join(self.root_dir, 'manifest') 276 manifest = os.path.join(self.root_dir, 'manifest')
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 expected = { 313 expected = {
291 u'exit_code': 0, 314 u'exit_code': 0,
292 u'hard_timeout': False, 315 u'hard_timeout': False,
293 u'io_timeout': False, 316 u'io_timeout': False,
294 u'must_signal_internal_failure': None, 317 u'must_signal_internal_failure': None,
295 u'version': task_runner.OUT_VERSION, 318 u'version': task_runner.OUT_VERSION,
296 } 319 }
297 self.assertEqual(expected, self._run_command(task_details)) 320 self.assertEqual(expected, self._run_command(task_details))
298 321
299 def test_run_command_raw_with_auth(self): 322 def test_run_command_raw_with_auth(self):
300 auth_params_file = os.path.join(self.root_dir, 'auth_params.json')
301 with open(auth_params_file, 'wb') as f:
302 json.dump({'swarming_http_headers': {'A': 'a'}}, f)
303
304 # This runs the command for real. 323 # This runs the command for real.
305 self.requests(cost_usd=1, exit_code=0, auth_headers={'A': 'a'}) 324 self.requests(cost_usd=1, exit_code=0, auth_headers={'A': 'a'})
306 task_details = self.get_task_details('print(\'hi\')') 325 task_details = self.get_task_details('print(\'hi\')')
307 expected = { 326 expected = {
308 u'exit_code': 0, 327 u'exit_code': 0,
309 u'hard_timeout': False, 328 u'hard_timeout': False,
310 u'io_timeout': False, 329 u'io_timeout': False,
311 u'must_signal_internal_failure': None, 330 u'must_signal_internal_failure': None,
312 u'version': task_runner.OUT_VERSION, 331 u'version': task_runner.OUT_VERSION,
313 } 332 }
314 self.assertEqual( 333 self.assertEqual(
315 expected, 334 expected,
316 self._run_command(task_details, auth_params_file=auth_params_file)) 335 self._run_command(task_details, headers_cb=lambda: {'A': 'a'}))
317 336
318 def test_run_command_isolated(self): 337 def test_run_command_isolated(self):
319 # This runs the command for real. 338 # This runs the command for real.
320 self.requests( 339 self.requests(
321 cost_usd=1, exit_code=0, 340 cost_usd=1, exit_code=0,
322 outputs_ref={ 341 outputs_ref={
323 u'isolated': u'123', 342 u'isolated': u'123',
324 u'isolatedserver': u'http://localhost:1', 343 u'isolatedserver': u'http://localhost:1',
325 u'namespace': u'default-gzip', 344 u'namespace': u'default-gzip',
326 }) 345 })
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 task_runner.load_and_run( 681 task_runner.load_and_run(
663 in_file, server, 3600., time.time(), out_file, 1, None, None) 682 in_file, server, 3600., time.time(), out_file, 1, None, None)
664 with open(out_file, 'rb') as f: 683 with open(out_file, 'rb') as f:
665 return json.load(f) 684 return json.load(f)
666 685
667 def _run_command(self, task_details): 686 def _run_command(self, task_details):
668 # Dot not mock time since this test class is testing timeouts. 687 # Dot not mock time since this test class is testing timeouts.
669 server = 'https://localhost:1' 688 server = 'https://localhost:1'
670 return task_runner.run_command( 689 return task_runner.run_command(
671 server, task_details, self.work_dir, 3600., time.time(), 1, 690 server, task_details, self.work_dir, 3600., time.time(), 1,
672 '/path/to/file', None) 691 '/path/to/file', lambda: {})
673 692
674 def test_hard(self): 693 def test_hard(self):
675 # Actually 0xc000013a 694 # Actually 0xc000013a
676 sig = -1073741510 if sys.platform == 'win32' else -signal.SIGTERM 695 sig = -1073741510 if sys.platform == 'win32' else -signal.SIGTERM
677 self.requests(hard_timeout=True, exit_code=sig) 696 self.requests(hard_timeout=True, exit_code=sig)
678 task_details = self.get_task_details( 697 task_details = self.get_task_details(
679 self.SCRIPT_HANG, hard_timeout=self.SHORT_TIME_OUT) 698 self.SCRIPT_HANG, hard_timeout=self.SHORT_TIME_OUT)
680 expected = { 699 expected = {
681 u'exit_code': sig, 700 u'exit_code': sig,
682 u'hard_timeout': True, 701 u'hard_timeout': True,
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 fix_encoding.fix_encoding() 1176 fix_encoding.fix_encoding()
1158 if '-v' in sys.argv: 1177 if '-v' in sys.argv:
1159 unittest.TestCase.maxDiff = None 1178 unittest.TestCase.maxDiff = None
1160 logging_utils.prepare_logging(None) 1179 logging_utils.prepare_logging(None)
1161 logging_utils.set_console_level( 1180 logging_utils.set_console_level(
1162 logging.DEBUG if '-v' in sys.argv else logging.CRITICAL+1) 1181 logging.DEBUG if '-v' in sys.argv else logging.CRITICAL+1)
1163 # Fix litteral text expectation. 1182 # Fix litteral text expectation.
1164 os.environ['LANG'] = 'en_US.UTF-8' 1183 os.environ['LANG'] = 'en_US.UTF-8'
1165 os.environ['LANGUAGE'] = 'en_US.UTF-8' 1184 os.environ['LANGUAGE'] = 'en_US.UTF-8'
1166 unittest.main() 1185 unittest.main()
OLDNEW
« no previous file with comments | « appengine/swarming/swarming_bot/bot_code/task_runner.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698