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

Side by Side Diff: tests/swarming_test.py

Issue 22980008: Merge all swarm_*.py scripts into swarming.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/swarm_client
Patch Set: Created 7 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
« swarming.py ('K') | « tests/swarming_smoke_test.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 # Copyright (c) 2013 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 StringIO
6 import json 7 import json
7 import logging 8 import logging
8 import os 9 import os
9 import StringIO
10 import sys 10 import sys
11 import threading 11 import threading
12 import unittest 12 import unittest
13 import urllib2 13 import urllib2
14 14
15 import auto_stub 15 import auto_stub
16 16
17 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18 sys.path.insert(0, ROOT_DIR) 18 sys.path.insert(0, ROOT_DIR)
19 19
20 import run_isolated 20 import run_isolated
21 import swarm_get_results 21 import swarming
22
23
24 FILE_NAME = u'test.isolated'
25 FILE_HASH = u'brodoyouevenhash'
26 TEST_NAME = u'unit_tests'
27 STDOUT_FOR_TRIGGER_LEN = 188
22 28
23 29
24 TEST_CASE_SUCCESS = ( 30 TEST_CASE_SUCCESS = (
25 '[----------] 2 tests from StaticCookiePolicyTest\n' 31 '[----------] 2 tests from StaticCookiePolicyTest\n'
26 '[ RUN ] StaticCookiePolicyTest.AllowAllCookiesTest\n' 32 '[ RUN ] StaticCookiePolicyTest.AllowAllCookiesTest\n'
27 '[ OK ] StaticCookiePolicyTest.AllowAllCookiesTest (0 ms)\n' 33 '[ OK ] StaticCookiePolicyTest.AllowAllCookiesTest (0 ms)\n'
28 '[ RUN ] StaticCookiePolicyTest.BlockAllCookiesTest\n' 34 '[ RUN ] StaticCookiePolicyTest.BlockAllCookiesTest\n'
29 '[ OK ] StaticCookiePolicyTest.BlockAllCookiesTest (0 ms)\n' 35 '[ OK ] StaticCookiePolicyTest.BlockAllCookiesTest (0 ms)\n'
30 '[----------] 2 tests from StaticCookiePolicyTest (0 ms total)\n' 36 '[----------] 2 tests from StaticCookiePolicyTest (0 ms total)\n'
31 '\n' 37 '\n'
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 url_response.msg = 'OK' 133 url_response.msg = 'OK'
128 return url_response 134 return url_response
129 135
130 136
131 def get_swarm_results(keys): 137 def get_swarm_results(keys):
132 """Simplifies the call to yield_results(). 138 """Simplifies the call to yield_results().
133 139
134 The timeout is hard-coded to 10 seconds. 140 The timeout is hard-coded to 10 seconds.
135 """ 141 """
136 return list( 142 return list(
137 swarm_get_results.yield_results( 143 swarming.yield_results(
138 'http://host:9001', keys, 10., None)) 144 'http://host:9001', keys, 10., None))
139 145
140 146
141 class TestCase(auto_stub.TestCase): 147 class TestCase(auto_stub.TestCase):
142 """Base class that defines the url_open mock.""" 148 """Base class that defines the url_open mock."""
143 def setUp(self): 149 def setUp(self):
144 super(TestCase, self).setUp() 150 super(TestCase, self).setUp()
145 self._lock = threading.Lock() 151 self._lock = threading.Lock()
146 self.requests = [] 152 self.requests = []
147 self.mock( 153 self.mock(
148 swarm_get_results.run_isolated, 'url_open', 154 swarming.run_isolated, 'url_open',
149 self._url_open) 155 self._url_open)
150 156
151 def tearDown(self): 157 def tearDown(self):
152 try: 158 try:
153 if not self.has_failed(): 159 if not self.has_failed():
154 self.assertEqual([], self.requests) 160 self.assertEqual([], self.requests)
155 finally: 161 finally:
156 super(TestCase, self).tearDown() 162 super(TestCase, self).tearDown()
157 163
158 def _url_open(self, url, **kwargs): 164 def _url_open(self, url, **kwargs):
159 logging.info('url_open(%s)', url) 165 logging.info('url_open(%s)', url)
160 with self._lock: 166 with self._lock:
161 # Since the client is multi-threaded, requests can be processed out of 167 # Since the client is multi-threaded, requests can be processed out of
162 # order. 168 # order.
163 for index, r in enumerate(self.requests): 169 for index, r in enumerate(self.requests):
164 if r[0] == url and r[1] == kwargs: 170 if r[0] == url and r[1] == kwargs:
165 _, _, returned = self.requests.pop(index) 171 _, _, returned = self.requests.pop(index)
166 break 172 break
167 else: 173 else:
168 self.fail('Failed to find url %s' % url) 174 self.fail('Failed to find url %s' % url)
169 return returned 175 return returned
170 176
171 177
172 class TestGetTestKeys(TestCase): 178 class TestGetTestKeys(TestCase):
173 def test_no_keys(self): 179 def test_no_keys(self):
174 old_sleep = swarm_get_results.time.sleep 180 self.mock(swarming.time, 'sleep', lambda x: x)
175 swarm_get_results.time.sleep = lambda x: x 181 self.requests = [
182 (
183 'http://host:9001/get_matching_test_cases?name=my_test',
184 {'retry_404': True},
185 StringIO.StringIO('No matching Test Cases'),
186 ) for _ in range(run_isolated.URL_OPEN_MAX_ATTEMPTS)
187 ]
176 try: 188 try:
177 self.requests = [ 189 swarming.get_test_keys('http://host:9001', 'my_test')
178 ( 190 self.fail()
179 'http://host:9001/get_matching_test_cases?name=my_test', 191 except swarming.Failure as e:
180 {'retry_404': True}, 192 msg = (
181 StringIO.StringIO('No matching Test Cases'), 193 'Error: Unable to find any tests with the name, my_test, on swarm '
182 ) for _ in range(run_isolated.URL_OPEN_MAX_ATTEMPTS) 194 'server')
183 ] 195 self.assertEqual(msg, e.args[0])
184 try:
185 swarm_get_results.get_test_keys('http://host:9001', 'my_test')
186 self.fail()
187 except swarm_get_results.Failure as e:
188 msg = (
189 'Error: Unable to find any tests with the name, my_test, on swarm '
190 'server')
191 self.assertEqual(msg, e.args[0])
192 finally:
193 swarm_get_results.time.sleep = old_sleep
194 196
195 def test_no_keys_on_first_attempt(self): 197 def test_no_keys_on_first_attempt(self):
196 old_sleep = swarm_get_results.time.sleep 198 self.mock(swarming.time, 'sleep', lambda x: x)
197 swarm_get_results.time.sleep = lambda x: x 199 keys = ['key_1', 'key_2']
198 try: 200 self.requests = [
199 keys = ['key_1', 'key_2'] 201 (
200 self.requests = [ 202 'http://host:9001/get_matching_test_cases?name=my_test',
201 ( 203 {'retry_404': True},
202 'http://host:9001/get_matching_test_cases?name=my_test', 204 StringIO.StringIO('No matching Test Cases'),
203 {'retry_404': True}, 205 ),
204 StringIO.StringIO('No matching Test Cases'), 206 (
205 ), 207 'http://host:9001/get_matching_test_cases?name=my_test',
206 ( 208 {'retry_404': True},
207 'http://host:9001/get_matching_test_cases?name=my_test', 209 StringIO.StringIO(json.dumps(keys)),
208 {'retry_404': True}, 210 ),
209 StringIO.StringIO(json.dumps(keys)), 211 ]
210 ), 212 actual = swarming.get_test_keys('http://host:9001', 'my_test')
211 ] 213 self.assertEqual(keys, actual)
212 actual = swarm_get_results.get_test_keys('http://host:9001', 'my_test')
213 self.assertEqual(keys, actual)
214 finally:
215 swarm_get_results.time.sleep = old_sleep
216 214
217 def test_find_keys(self): 215 def test_find_keys(self):
218 keys = ['key_1', 'key_2'] 216 keys = ['key_1', 'key_2']
219 self.requests = [ 217 self.requests = [
220 ( 218 (
221 'http://host:9001/get_matching_test_cases?name=my_test', 219 'http://host:9001/get_matching_test_cases?name=my_test',
222 {'retry_404': True}, 220 {'retry_404': True},
223 StringIO.StringIO(json.dumps(keys)), 221 StringIO.StringIO(json.dumps(keys)),
224 ), 222 ),
225 ] 223 ]
226 actual = swarm_get_results.get_test_keys('http://host:9001', 'my_test') 224 actual = swarming.get_test_keys('http://host:9001', 'my_test')
227 self.assertEqual(keys, actual) 225 self.assertEqual(keys, actual)
228 226
229 227
230 class TestGetSwarmResults(TestCase): 228 class TestGetSwarmResults(TestCase):
231 def test_success(self): 229 def test_success(self):
232 self.requests = [ 230 self.requests = [
233 ( 231 (
234 'http://host:9001/get_result?r=key1', 232 'http://host:9001/get_result?r=key1',
235 {'retry_404': False, 'retry_50x': False}, 233 {'retry_404': False, 'retry_50x': False},
236 generate_url_response(0, SWARM_OUTPUT_SUCCESS, '0, 0'), 234 generate_url_response(0, SWARM_OUTPUT_SUCCESS, '0, 0'),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 def test_url_errors(self): 269 def test_url_errors(self):
272 # NOTE: get_swarm_results() hardcodes timeout=10. range(12) is because of an 270 # NOTE: get_swarm_results() hardcodes timeout=10. range(12) is because of an
273 # additional time.time() call deep in run_isolated.url_open(). 271 # additional time.time() call deep in run_isolated.url_open().
274 now = {} 272 now = {}
275 lock = threading.Lock() 273 lock = threading.Lock()
276 def get_now(): 274 def get_now():
277 t = threading.current_thread() 275 t = threading.current_thread()
278 with lock: 276 with lock:
279 return now.setdefault(t, range(12)).pop(0) 277 return now.setdefault(t, range(12)).pop(0)
280 self.mock( 278 self.mock(
281 swarm_get_results.run_isolated.HttpService, 279 swarming.run_isolated.HttpService,
282 'sleep_before_retry', 280 'sleep_before_retry',
283 staticmethod(lambda _x, _y: None)) 281 staticmethod(lambda _x, _y: None))
284 self.mock(swarm_get_results, 'now', get_now) 282 self.mock(swarming, 'now', get_now)
285 # The actual number of requests here depends on 'now' progressing to 10 283 # The actual number of requests here depends on 'now' progressing to 10
286 # seconds. It's called twice per loop. 284 # seconds. It's called twice per loop.
287 self.requests = [ 285 self.requests = [
288 ( 286 (
289 'http://host:9001/get_result?r=key1', 287 'http://host:9001/get_result?r=key1',
290 {'retry_404': False, 'retry_50x': False}, 288 {'retry_404': False, 'retry_50x': False},
291 None, 289 None,
292 ), 290 ),
293 ( 291 (
294 'http://host:9001/get_result?r=key1', 292 'http://host:9001/get_result?r=key1',
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 ] 356 ]
359 expected = [ 357 expected = [
360 gen_yielded_data(0, TEST_SHARD_OUTPUT_1, '0, 0'), 358 gen_yielded_data(0, TEST_SHARD_OUTPUT_1, '0, 0'),
361 gen_yielded_data(1, TEST_SHARD_OUTPUT_2, '0, 0'), 359 gen_yielded_data(1, TEST_SHARD_OUTPUT_2, '0, 0'),
362 gen_yielded_data(2, TEST_SHARD_OUTPUT_3, '0, 0'), 360 gen_yielded_data(2, TEST_SHARD_OUTPUT_3, '0, 0'),
363 ] 361 ]
364 actual = get_swarm_results(['key1', 'key1-repeat', 'key2', 'key3']) 362 actual = get_swarm_results(['key1', 'key1-repeat', 'key2', 'key3'])
365 self.assertEqual(expected, sorted(actual)) 363 self.assertEqual(expected, sorted(actual))
366 364
367 365
366 def chromium_tasks(retrieval_url):
367 return [
368 {
369 u'action': [
370 u'python', u'run_isolated.py',
371 u'--hash', FILE_HASH,
372 u'--remote', retrieval_url + u'default-gzip/',
373 ],
374 u'decorate_output': False,
375 u'test_name': u'Run Test',
376 u'time_out': 600,
377 },
378 {
379 u'action' : [
380 u'python', u'swarm_cleanup.py',
381 ],
382 u'decorate_output': False,
383 u'test_name': u'Clean Up',
384 u'time_out': 600,
385 }
386 ]
387
388
389 def generate_expected_json(
390 shards,
391 os_image,
392 working_dir,
393 data_server,
394 profile):
395 retrieval_url = data_server + '/content/retrieve/'
396 os_value = unicode(swarming.PLATFORM_MAPPING[os_image])
397 expected = {
398 u'cleanup': u'root',
399 u'configurations': [
400 {
401 u'config_name': os_value,
402 u'dimensions': {
403 u'os': os_value,
404 },
405 u'min_instances': shards,
406 },
407 ],
408 u'data': [[retrieval_url + u'default/', u'swarm_data.zip']],
409 u'env_vars': {},
410 u'restart_on_failure': True,
411 u'test_case_name': TEST_NAME,
412 u'tests': chromium_tasks(retrieval_url),
413 u'working_dir': unicode(working_dir),
414 u'priority': 101,
415 }
416 if shards > 1:
417 expected[u'env_vars'][u'GTEST_SHARD_INDEX'] = u'%(instance_index)s'
418 expected[u'env_vars'][u'GTEST_TOTAL_SHARDS'] = u'%(num_instances)s'
419 if profile:
420 expected[u'tests'][0][u'action'].append(u'--verbose')
421 return expected
422
423
424 class MockZipFile(object):
425 def __init__(self, filename, mode):
426 pass
427
428 def write(self, source, dest=None):
429 pass
430
431 def close(self):
432 pass
433
434
435 def MockUrlOpen(url, _data, has_return_value):
436 if '/content/contains' in url:
437 return StringIO.StringIO(has_return_value)
438 return StringIO.StringIO('{}')
439
440
441 def MockUrlOpenHasZip(url, data=None, content_type=None):
442 assert content_type in (None, 'application/json', 'application/octet-stream')
443 return MockUrlOpen(url, data, has_return_value=chr(1))
444
445
446 def MockUrlOpenNoZip(url, data=None, content_type=None):
447 assert content_type in (None, 'application/json', 'application/octet-stream')
448 return MockUrlOpen(url, data, has_return_value=chr(0))
449
450
451 class ManifestTest(auto_stub.TestCase):
452 def setUp(self):
453 self.mock(swarming.time, 'sleep', lambda x: None)
454 self.mock(swarming.zipfile, 'ZipFile', MockZipFile)
455 self.mock(sys, 'stdout', StringIO.StringIO())
456 self.mock(sys, 'stderr', StringIO.StringIO())
457
458 def tearDown(self):
459 if not self.has_failed():
460 self._check_output('', '')
461 super(ManifestTest, self).tearDown()
462
463 def _check_output(self, out, err):
464 self.assertEqual(out, sys.stdout.getvalue())
465 self.assertEqual(err, sys.stderr.getvalue())
466
467 # Flush their content by mocking them again.
468 self.mock(sys, 'stdout', StringIO.StringIO())
469 self.mock(sys, 'stderr', StringIO.StringIO())
470
471 def test_basic_manifest(self):
472 manifest = swarming.Manifest(
473 manifest_hash=FILE_HASH,
474 test_name=TEST_NAME,
475 shards=2,
476 test_filter='*',
477 os_image='win32',
478 working_dir='swarm_tests',
479 data_server='http://localhost:8081',
480 verbose=False,
481 profile=False,
482 priority=101)
483
484 swarming.chromium_setup(manifest)
485 manifest_json = json.loads(manifest.to_json())
486
487 expected = generate_expected_json(
488 shards=2,
489 os_image='win32',
490 working_dir='swarm_tests',
491 data_server='http://localhost:8081',
492 profile=False)
493 self.assertEqual(expected, manifest_json)
494
495 def test_basic_linux(self):
496 """A basic linux manifest test to ensure that windows specific values
497 aren't used.
498 """
499 manifest = swarming.Manifest(
500 manifest_hash=FILE_HASH,
501 test_name=TEST_NAME,
502 shards=1,
503 test_filter='*',
504 os_image='linux2',
505 working_dir='swarm_tests',
506 data_server='http://localhost:8081',
507 verbose=False,
508 profile=False,
509 priority=101)
510
511 swarming.chromium_setup(manifest)
512 manifest_json = json.loads(manifest.to_json())
513
514 expected = generate_expected_json(
515 shards=1,
516 os_image='linux2',
517 working_dir='swarm_tests',
518 data_server='http://localhost:8081',
519 profile=False)
520 self.assertEqual(expected, manifest_json)
521
522 def test_basic_linux_profile(self):
523 manifest = swarming.Manifest(
524 manifest_hash=FILE_HASH,
525 test_name=TEST_NAME,
526 shards=1,
527 test_filter='*',
528 os_image='linux2',
529 working_dir='swarm_tests',
530 data_server='http://localhost:8081',
531 verbose=False,
532 profile=True,
533 priority=101)
534
535 swarming.chromium_setup(manifest)
536 manifest_json = json.loads(manifest.to_json())
537
538 expected = generate_expected_json(
539 shards=1,
540 os_image='linux2',
541 working_dir='swarm_tests',
542 data_server='http://localhost:8081',
543 profile=True)
544 self.assertEqual(expected, manifest_json)
545
546 def test_process_manifest_success(self):
547 self.mock(swarming.run_isolated, 'url_open', MockUrlOpenNoZip)
548
549 result = swarming.process_manifest(
550 file_sha1=FILE_HASH,
551 test_name=TEST_NAME,
552 shards=1,
553 test_filter='*',
554 os_image='linux2',
555 working_dir='swarm_tests',
556 data_server='http://localhost:8081',
557 swarm_url='http://localhost:8082',
558 verbose=False,
559 profile=False,
560 priority=101)
561 self.assertEqual(0, result)
562
563 # Just assert it printed enough, since it contains variable output.
564 out = sys.stdout.getvalue()
565 self.assertTrue(len(out) > STDOUT_FOR_TRIGGER_LEN)
566 self.assertTrue('Zip file not on server, starting uploading.' in out)
567 self.mock(sys, 'stdout', StringIO.StringIO())
568
569 def test_process_manifest_success_zip_already_uploaded(self):
570 self.mock(swarming.run_isolated, 'url_open', MockUrlOpenHasZip)
571
572 result = swarming.process_manifest(
573 file_sha1=FILE_HASH,
574 test_name=TEST_NAME,
575 shards=1,
576 test_filter='*',
577 os_image='linux2',
578 working_dir='swarm_tests',
579 data_server='http://localhost:8081',
580 swarm_url='http://localhost:8082',
581 verbose=False,
582 profile=False,
583 priority=101)
584 self.assertEqual(0, result)
585
586 # Just assert it printed enough, since it contains variable output.
587 out = sys.stdout.getvalue()
588 self.assertTrue(len(out) > STDOUT_FOR_TRIGGER_LEN)
589 self.assertTrue('Zip file already on server, no need to reupload.' in out)
590 self.mock(sys, 'stdout', StringIO.StringIO())
591
592 def test_no_dir(self):
593 try:
594 swarming.main(['trigger'])
595 self.fail()
596 except SystemExit as e:
597 self.assertEqual(2, e.code)
598 self._check_output(
599 '',
600 'Usage: swarming.py trigger [options]\n\n'
601 'swarming.py: error: Must specify the data directory\n')
602
603 def test_no_request(self):
604 try:
605 swarming.main(['trigger', '-d', '.'])
606 self.fail()
607 except SystemExit as e:
608 self.assertEqual(2, e.code)
609 self._check_output(
610 '',
611 'Usage: swarming.py trigger [options]\n\n'
612 'swarming.py: error: At least one --run_from_hash is required.\n')
613
614
368 if __name__ == '__main__': 615 if __name__ == '__main__':
369 logging.basicConfig( 616 logging.basicConfig(
370 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR) 617 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
371 if '-v' in sys.argv: 618 if '-v' in sys.argv:
372 unittest.TestCase.maxDiff = None 619 unittest.TestCase.maxDiff = None
373 unittest.main() 620 unittest.main()
OLDNEW
« swarming.py ('K') | « tests/swarming_smoke_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698