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: client/tests/run_isolated_test.py

Issue 2037253002: run_isolated.py: install CIPD packages (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: Created 4 years, 6 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
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2013 The LUCI Authors. All rights reserved. 2 # Copyright 2013 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 # pylint: disable=R0201 6 # pylint: disable=R0201
7 7
8 import StringIO 8 import StringIO
9 import base64 9 import base64
10 import functools 10 import functools
11 import json 11 import json
12 import logging 12 import logging
13 import os 13 import os
14 import sys 14 import sys
15 import tempfile 15 import tempfile
16 import unittest 16 import unittest
17 17
18 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 18 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 sys.path.insert(0, ROOT_DIR) 19 sys.path.insert(0, ROOT_DIR)
20 sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party')) 20 sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party'))
21 21
22 import isolated_format 22 import isolated_format
23 import isolateserver 23 import isolateserver
24 import run_isolated 24 import run_isolated
25 from depot_tools import auto_stub 25 from depot_tools import auto_stub
26 from depot_tools import fix_encoding 26 from depot_tools import fix_encoding
27 from utils import file_path 27 from utils import file_path
28 from utils import fs
28 from utils import large 29 from utils import large
29 from utils import logging_utils 30 from utils import logging_utils
30 from utils import on_error 31 from utils import on_error
31 from utils import subprocess42 32 from utils import subprocess42
32 from utils import tools 33 from utils import tools
33 34
34 import isolateserver_mock 35 import isolateserver_mock
36 import cipdserver_mock
35 37
36 38
37 def write_content(filepath, content): 39 def write_content(filepath, content):
38 with open(filepath, 'wb') as f: 40 with open(filepath, 'wb') as f:
39 f.write(content) 41 f.write(content)
40 42
41 43
42 def json_dumps(data): 44 def json_dumps(data):
43 return json.dumps(data, sort_keys=True, separators=(',', ':')) 45 return json.dumps(data, sort_keys=True, separators=(',', ':'))
44 46
(...skipping 27 matching lines...) Expand all
72 def setUp(self): 74 def setUp(self):
73 super(RunIsolatedTestBase, self).setUp() 75 super(RunIsolatedTestBase, self).setUp()
74 self.tempdir = tempfile.mkdtemp(prefix=u'run_isolated_test') 76 self.tempdir = tempfile.mkdtemp(prefix=u'run_isolated_test')
75 logging.debug(self.tempdir) 77 logging.debug(self.tempdir)
76 self.mock(run_isolated, 'make_temp_dir', self.fake_make_temp_dir) 78 self.mock(run_isolated, 'make_temp_dir', self.fake_make_temp_dir)
77 self.mock(run_isolated.auth, 'ensure_logged_in', lambda _: None) 79 self.mock(run_isolated.auth, 'ensure_logged_in', lambda _: None)
78 self.mock( 80 self.mock(
79 logging_utils.OptionParserWithLogging, 'logger_root', 81 logging_utils.OptionParserWithLogging, 'logger_root',
80 logging.Logger('unittest')) 82 logging.Logger('unittest'))
81 83
84 self.cipd_server = cipdserver_mock.MockCipdServer()
85
82 def tearDown(self): 86 def tearDown(self):
83 for dirpath, dirnames, filenames in os.walk(self.tempdir, topdown=True): 87 for dirpath, dirnames, filenames in os.walk(self.tempdir, topdown=True):
84 for filename in filenames: 88 for filename in filenames:
85 file_path.set_read_only(os.path.join(dirpath, filename), False) 89 file_path.set_read_only(os.path.join(dirpath, filename), False)
86 for dirname in dirnames: 90 for dirname in dirnames:
87 file_path.set_read_only(os.path.join(dirpath, dirname), False) 91 file_path.set_read_only(os.path.join(dirpath, dirname), False)
88 file_path.rmtree(self.tempdir) 92 file_path.rmtree(self.tempdir)
93 self.cipd_server.close()
89 super(RunIsolatedTestBase, self).tearDown() 94 super(RunIsolatedTestBase, self).tearDown()
90 95
91 @property 96 @property
92 def run_test_temp_dir(self): 97 def run_test_temp_dir(self):
93 """Where to map all files in run_isolated.run_tha_test.""" 98 """Where to map all files in run_isolated.run_tha_test."""
94 return os.path.join(self.tempdir, 'isolated_run') 99 return os.path.join(self.tempdir, 'isolated_run')
95 100
96 def fake_make_temp_dir(self, prefix, _root_dir=None): 101 def fake_make_temp_dir(self, prefix, _root_dir=None):
97 """Predictably returns directory for run_tha_test (one per test case).""" 102 """Predictably returns directory for run_tha_test (one per test case)."""
98 self.assertIn(prefix, ('isolated_out', 'isolated_run', 'isolated_tmp')) 103 self.assertIn(
104 prefix,
105 ('isolated_out', 'isolated_run', 'isolated_tmp', 'cipd_site_root'))
99 temp_dir = os.path.join(self.tempdir, prefix) 106 temp_dir = os.path.join(self.tempdir, prefix)
100 self.assertFalse(os.path.isdir(temp_dir)) 107 self.assertFalse(os.path.isdir(temp_dir))
101 os.makedirs(temp_dir) 108 os.makedirs(temp_dir)
102 return temp_dir 109 return temp_dir
103 110
104 def temp_join(self, *args): 111 def temp_join(self, *args):
105 """Shortcut for joining path with self.run_test_temp_dir.""" 112 """Shortcut for joining path with self.run_test_temp_dir."""
106 return os.path.join(self.run_test_temp_dir, *args) 113 return os.path.join(self.run_test_temp_dir, *args)
107 114
108 115
109 class RunIsolatedTest(RunIsolatedTestBase): 116 class RunIsolatedTest(RunIsolatedTestBase):
110 def setUp(self): 117 def setUp(self):
111 super(RunIsolatedTest, self).setUp() 118 super(RunIsolatedTest, self).setUp()
112 self.popen_calls = [] 119 self.popen_calls = []
113 # pylint: disable=no-self-argument 120 # pylint: disable=no-self-argument
114 class Popen(object): 121 class Popen(object):
115 def __init__(self2, args, **kwargs): 122 def __init__(self2, args, **kwargs):
116 kwargs.pop('cwd', None) 123 kwargs.pop('cwd', None)
117 kwargs.pop('env', None) 124 kwargs.pop('env', None)
118 self.popen_calls.append((args, kwargs)) 125 self.popen_calls.append((args, kwargs))
119 self2.returncode = None 126 self2.returncode = None
120 127
128 def yield_any_line(self, timeout=None): # pylint: disable=unused-argument
129 return ()
130
121 def wait(self, timeout=None): # pylint: disable=unused-argument 131 def wait(self, timeout=None): # pylint: disable=unused-argument
122 self.returncode = 0 132 self.returncode = 0
123 return self.returncode 133 return self.returncode
124 134
125 def kill(self): 135 def kill(self):
126 pass 136 pass
127 137
128 self.mock(subprocess42, 'Popen', Popen) 138 self.mock(subprocess42, 'Popen', Popen)
129 139
130 def test_main(self): 140 def test_main(self):
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 ret = run_isolated.run_tha_test( 198 ret = run_isolated.run_tha_test(
189 command, 199 command,
190 isolated_hash, 200 isolated_hash,
191 StorageFake(files), 201 StorageFake(files),
192 isolateserver.MemoryCache(), 202 isolateserver.MemoryCache(),
193 False, 203 False,
194 None, 204 None,
195 None, 205 None,
196 None, 206 None,
197 None, 207 None,
208 None,
209 None,
198 None) 210 None)
199 self.assertEqual(0, ret) 211 self.assertEqual(0, ret)
200 return make_tree_call 212 return make_tree_call
201 213
202 def test_run_tha_test_naked(self): 214 def test_run_tha_test_naked(self):
203 isolated = json_dumps({'command': ['invalid', 'command']}) 215 isolated = json_dumps({'command': ['invalid', 'command']})
204 isolated_hash = isolateserver_mock.hash_content(isolated) 216 isolated_hash = isolateserver_mock.hash_content(isolated)
205 files = {isolated_hash:isolated} 217 files = {isolated_hash:isolated}
206 make_tree_call = self._run_tha_test(isolated_hash, files) 218 make_tree_call = self._run_tha_test(isolated_hash, files)
207 self.assertEqual( 219 self.assertEqual(
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 'hello', 325 'hello',
314 'world', 326 'world',
315 ] 327 ]
316 ret = run_isolated.main(cmd) 328 ret = run_isolated.main(cmd)
317 self.assertEqual(1, ret) 329 self.assertEqual(1, ret)
318 self.assertEqual(1, len(self.popen_calls)) 330 self.assertEqual(1, len(self.popen_calls))
319 self.assertEqual( 331 self.assertEqual(
320 [([u'/bin/echo', u'hello', u'world'], {'detached': True})], 332 [([u'/bin/echo', u'hello', u'world'], {'detached': True})],
321 self.popen_calls) 333 self.popen_calls)
322 334
335 def test_main_naked_with_packages(self):
336 cmd = [
337 '--no-log',
338 '--cipd-package', 'infra/tools/echo/${PLATFORM}:latest',
339 '--cipd-server', self.cipd_server.url,
340 '${CIPD_PATH}/echo',
341 'hello',
342 'world',
343 ]
344 ret = run_isolated.main(cmd)
345 self.assertEqual(0, ret)
346
347 self.assertEqual(2, len(self.popen_calls))
348
349 # Test cipd-ensure command.
350 cipd_ensure_cmd, _ = self.popen_calls[0]
351 self.assertEqual(cipd_ensure_cmd[:2], [
352 os.path.abspath(
353 'cipd_cache/clients/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
354 'ensure',
355 ])
356 cache_dir_index = cipd_ensure_cmd.index('-cache-dir')
357 self.assertEqual(
358 cipd_ensure_cmd[cache_dir_index+1],
359 os.path.abspath('cipd_cache/cipd_internal'))
360
361 # Test cipd cache.
362 version_file = unicode(os.path.abspath(
363 'cipd_cache/versions/1481d0a0ceb16ea4672fed76a0710306eb9f3a33'))
364 self.assertTrue(fs.isfile(version_file))
365 with open(version_file) as f:
366 self.assertEqual(f.read(), 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
367
368 client_binary_file = unicode(os.path.abspath(
369 'cipd_cache/clients/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))
370 self.assertTrue(fs.isfile(client_binary_file))
371
372 # Test echo call.
373 echo_cmd, _ = self.popen_calls[1]
374 self.assertTrue(echo_cmd[0].endswith('cipd_site_root/echo'))
375 self.assertEqual(echo_cmd[1:], ['hello', 'world'])
376
323 def test_modified_cwd(self): 377 def test_modified_cwd(self):
324 isolated = json_dumps({ 378 isolated = json_dumps({
325 'command': ['../out/some.exe', 'arg'], 379 'command': ['../out/some.exe', 'arg'],
326 'relative_cwd': 'some', 380 'relative_cwd': 'some',
327 }) 381 })
328 isolated_hash = isolateserver_mock.hash_content(isolated) 382 isolated_hash = isolateserver_mock.hash_content(isolated)
329 files = {isolated_hash:isolated} 383 files = {isolated_hash:isolated}
330 _ = self._run_tha_test(isolated_hash, files) 384 _ = self._run_tha_test(isolated_hash, files)
331 self.assertEqual(1, len(self.popen_calls)) 385 self.assertEqual(1, len(self.popen_calls))
332 self.assertEqual( 386 self.assertEqual(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 ret = run_isolated.run_tha_test( 445 ret = run_isolated.run_tha_test(
392 None, 446 None,
393 isolated_hash, 447 isolated_hash,
394 store, 448 store,
395 isolateserver.MemoryCache(), 449 isolateserver.MemoryCache(),
396 False, 450 False,
397 None, 451 None,
398 None, 452 None,
399 None, 453 None,
400 None, 454 None,
401 []) 455 [],
456 None,
457 None)
402 self.assertEqual(0, ret) 458 self.assertEqual(0, ret)
403 459
404 # It uploaded back. Assert the store has a new item containing foo. 460 # It uploaded back. Assert the store has a new item containing foo.
405 hashes = {isolated_hash, script_hash} 461 hashes = {isolated_hash, script_hash}
406 output_hash = isolateserver_mock.hash_content('bar') 462 output_hash = isolateserver_mock.hash_content('bar')
407 hashes.add(output_hash) 463 hashes.add(output_hash)
408 isolated = { 464 isolated = {
409 'algo': 'sha-1', 465 'algo': 'sha-1',
410 'files': { 466 'files': {
411 'foo': { 467 'foo': {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 u'initial_size': 0, 578 u'initial_size': 0,
523 u'items_cold': [len(isolated_in_json)], 579 u'items_cold': [len(isolated_in_json)],
524 u'items_hot': [], 580 u'items_hot': [],
525 }, 581 },
526 u'upload': { 582 u'upload': {
527 u'items_cold': [len(isolated_out_json)], 583 u'items_cold': [len(isolated_out_json)],
528 u'items_hot': [15], 584 u'items_hot': [15],
529 }, 585 },
530 }, 586 },
531 }, 587 },
532 u'version': 4, 588 u'version': 5,
533 } 589 }
534 actual = tools.read_json(out) 590 actual = tools.read_json(out)
535 # duration can be exactly 0 due to low timer resolution, especially but not 591 # duration can be exactly 0 due to low timer resolution, especially but not
536 # exclusively on Windows. 592 # exclusively on Windows.
537 self.assertLessEqual(0, actual.pop(u'duration')) 593 self.assertLessEqual(0, actual.pop(u'duration'))
538 actual_isolated_stats = actual[u'stats'][u'isolated'] 594 actual_isolated_stats = actual[u'stats'][u'isolated']
539 self.assertLessEqual(0, actual_isolated_stats[u'download'].pop(u'duration')) 595 self.assertLessEqual(0, actual_isolated_stats[u'download'].pop(u'duration'))
540 self.assertLessEqual(0, actual_isolated_stats[u'upload'].pop(u'duration')) 596 self.assertLessEqual(0, actual_isolated_stats[u'upload'].pop(u'duration'))
541 for i in (u'download', u'upload'): 597 for i in (u'download', u'upload'):
542 for j in (u'items_cold', u'items_hot'): 598 for j in (u'items_cold', u'items_hot'):
543 actual_isolated_stats[i][j] = large.unpack( 599 actual_isolated_stats[i][j] = large.unpack(
544 base64.b64decode(actual_isolated_stats[i][j])) 600 base64.b64decode(actual_isolated_stats[i][j]))
545 self.assertEqual(expected, actual) 601 self.assertEqual(expected, actual)
546 602
547 603
548 if __name__ == '__main__': 604 if __name__ == '__main__':
549 fix_encoding.fix_encoding() 605 fix_encoding.fix_encoding()
550 if '-v' in sys.argv: 606 if '-v' in sys.argv:
551 unittest.TestCase.maxDiff = None 607 unittest.TestCase.maxDiff = None
552 logging.basicConfig( 608 logging.basicConfig(
553 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR) 609 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
554 unittest.main() 610 unittest.main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698