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

Side by Side Diff: swarm_client/tests/swarming_test.py

Issue 69143004: Delete swarm_client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 1 month 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 | « swarm_client/tests/swarming_smoke_test.py ('k') | swarm_client/tests/threading_utils_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
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import hashlib
7 import json
8 import logging
9 import os
10 import StringIO
11 import sys
12 import threading
13 import unittest
14
15 import auto_stub
16
17 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18 sys.path.insert(0, ROOT_DIR)
19
20 import swarming
21 from utils import net
22
23
24 ALGO = hashlib.sha1
25 FILE_NAME = u'test.isolated'
26 FILE_HASH = u'1' * 40
27 TEST_NAME = u'unit_tests'
28 STDOUT_FOR_TRIGGER_LEN = 180
29
30
31 TEST_CASE_SUCCESS = (
32 '[----------] 2 tests from StaticCookiePolicyTest\n'
33 '[ RUN ] StaticCookiePolicyTest.AllowAllCookiesTest\n'
34 '[ OK ] StaticCookiePolicyTest.AllowAllCookiesTest (0 ms)\n'
35 '[ RUN ] StaticCookiePolicyTest.BlockAllCookiesTest\n'
36 '[ OK ] StaticCookiePolicyTest.BlockAllCookiesTest (0 ms)\n'
37 '[----------] 2 tests from StaticCookiePolicyTest (0 ms total)\n'
38 '\n'
39 '[----------] 1 test from TCPListenSocketTest\n'
40 '[ RUN ] TCPListenSocketTest.ServerSend\n'
41 '[ OK ] TCPListenSocketTest.ServerSend (1 ms)\n'
42 '[----------] 1 test from TCPListenSocketTest (1 ms total)\n')
43
44
45 TEST_CASE_FAILURE = (
46 '[----------] 2 tests from StaticCookiePolicyTest\n'
47 '[ RUN ] StaticCookiePolicyTest.AllowAllCookiesTest\n'
48 '[ OK ] StaticCookiePolicyTest.AllowAllCookiesTest (0 ms)\n'
49 '[ RUN ] StaticCookiePolicyTest.BlockAllCookiesTest\n'
50 'C:\\win\\build\\src\\chrome\\test.cc: error: Value of: result()\n'
51 ' Actual: false\n'
52 'Expected: true\n'
53 '[ FAILED ] StaticCookiePolicyTest.BlockAllCookiesTest (0 ms)\n'
54 '[----------] 2 tests from StaticCookiePolicyTest (0 ms total)\n'
55 '\n'
56 '[----------] 1 test from TCPListenSocketTest\n'
57 '[ RUN ] TCPListenSocketTest.ServerSend\n'
58 '[ OK ] TCPListenSocketTest.ServerSend (1 ms)\n'
59 '[----------] 1 test from TCPListenSocketTest (1 ms total)\n')
60
61
62 SWARM_OUTPUT_SUCCESS = (
63 '[ RUN ] unittests.Run Test\n' +
64 TEST_CASE_SUCCESS +
65 '[ OK ] unittests.Run Test (2549 ms)\n'
66 '[ RUN ] unittests.Clean Up\n'
67 'No output!\n'
68 '[ OK ] unittests.Clean Up (6 ms)\n'
69 '\n'
70 '[----------] unittests summary\n'
71 '[==========] 2 tests ran. (2556 ms total)\n')
72
73
74 SWARM_OUTPUT_FAILURE = (
75 '[ RUN ] unittests.Run Test\n' +
76 TEST_CASE_FAILURE +
77 '[ OK ] unittests.Run Test (2549 ms)\n'
78 '[ RUN ] unittests.Clean Up\n'
79 'No output!\n'
80 '[ OK ] unittests.Clean Up (6 ms)\n'
81 '\n'
82 '[----------] unittests summary\n'
83 '[==========] 2 tests ran. (2556 ms total)\n')
84
85
86 SWARM_OUTPUT_WITH_NO_TEST_OUTPUT = (
87 '\n'
88 'Unable to connection to swarm machine.\n')
89
90
91 TEST_SHARD_1 = 'Note: This is test shard 1 of 3.'
92 TEST_SHARD_2 = 'Note: This is test shard 2 of 3.'
93 TEST_SHARD_3 = 'Note: This is test shard 3 of 3.'
94
95
96 SWARM_SHARD_OUTPUT = (
97 '[ RUN ] unittests.Run Test\n'
98 '%s\n'
99 '[ OK ] unittests.Run Test (2549 ms)\n'
100 '[ RUN ] unittests.Clean Up\n'
101 'No output!\n'
102 '[ OK ] unittests.Clean Up (6 ms)\n'
103 '\n'
104 '[----------] unittests summary\n'
105 '[==========] 2 tests ran. (2556 ms total)\n')
106
107
108 TEST_SHARD_OUTPUT_1 = SWARM_SHARD_OUTPUT % TEST_SHARD_1
109 TEST_SHARD_OUTPUT_2 = SWARM_SHARD_OUTPUT % TEST_SHARD_2
110 TEST_SHARD_OUTPUT_3 = SWARM_SHARD_OUTPUT % TEST_SHARD_3
111
112
113 def gen_data(index, shard_output, exit_codes):
114 return {
115 u'config_instance_index': index,
116 u'exit_codes': unicode(exit_codes),
117 u'machine_id': u'host',
118 u'machine_tag': u'localhost',
119 u'output': unicode(shard_output),
120 }
121
122
123 def gen_yielded_data(index, shard_output, exit_codes):
124 """Returns an entry as it would be yielded by yield_results()."""
125 return index, gen_data(index, shard_output, exit_codes)
126
127
128 def generate_url_response(index, shard_output, exit_codes):
129 return net.HttpResponse.get_fake_response(
130 json.dumps(gen_data(index, shard_output, exit_codes)), 'mocked_url')
131
132
133 def get_swarm_results(keys):
134 """Simplifies the call to yield_results().
135
136 The timeout is hard-coded to 10 seconds.
137 """
138 return list(swarming.yield_results('http://host:9001', keys, 10., None))
139
140
141 class TestCase(auto_stub.TestCase):
142 """Base class that defines the url_open mock."""
143 def setUp(self):
144 super(TestCase, self).setUp()
145 self._lock = threading.Lock()
146 self.requests = []
147 self.mock(swarming.net, 'url_open', self._url_open)
148
149 def tearDown(self):
150 try:
151 if not self.has_failed():
152 self.assertEqual([], self.requests)
153 finally:
154 super(TestCase, self).tearDown()
155
156 def _url_open(self, url, **kwargs):
157 logging.info('url_open(%s)', url)
158 with self._lock:
159 # Ignore 'stream' argument, it's not important for these tests.
160 kwargs.pop('stream')
161 # Since the client is multi-threaded, requests can be processed out of
162 # order.
163 for index, r in enumerate(self.requests):
164 if r[0] == url and r[1] == kwargs:
165 _, _, returned = self.requests.pop(index)
166 break
167 else:
168 self.fail('Failed to find url %s' % url)
169 return returned
170
171
172 class TestGetTestKeys(TestCase):
173 def test_no_keys(self):
174 self.mock(swarming.time, 'sleep', lambda x: x)
175 self.requests = [
176 (
177 'http://host:9001/get_matching_test_cases?name=my_test',
178 {'retry_404': True},
179 StringIO.StringIO('No matching Test Cases'),
180 ) for _ in range(net.URL_OPEN_MAX_ATTEMPTS)
181 ]
182 try:
183 swarming.get_test_keys('http://host:9001', 'my_test')
184 self.fail()
185 except swarming.Failure as e:
186 msg = (
187 'Error: Unable to find any tests with the name, my_test, on swarm '
188 'server')
189 self.assertEqual(msg, e.args[0])
190
191 def test_no_keys_on_first_attempt(self):
192 self.mock(swarming.time, 'sleep', lambda x: x)
193 keys = ['key_1', 'key_2']
194 self.requests = [
195 (
196 'http://host:9001/get_matching_test_cases?name=my_test',
197 {'retry_404': True},
198 StringIO.StringIO('No matching Test Cases'),
199 ),
200 (
201 'http://host:9001/get_matching_test_cases?name=my_test',
202 {'retry_404': True},
203 StringIO.StringIO(json.dumps(keys)),
204 ),
205 ]
206 actual = swarming.get_test_keys('http://host:9001', 'my_test')
207 self.assertEqual(keys, actual)
208
209 def test_find_keys(self):
210 keys = ['key_1', 'key_2']
211 self.requests = [
212 (
213 'http://host:9001/get_matching_test_cases?name=my_test',
214 {'retry_404': True},
215 StringIO.StringIO(json.dumps(keys)),
216 ),
217 ]
218 actual = swarming.get_test_keys('http://host:9001', 'my_test')
219 self.assertEqual(keys, actual)
220
221
222 class TestGetSwarmResults(TestCase):
223 def test_success(self):
224 self.requests = [
225 (
226 'http://host:9001/get_result?r=key1',
227 {'retry_404': False, 'retry_50x': False},
228 generate_url_response(0, SWARM_OUTPUT_SUCCESS, '0, 0'),
229 ),
230 ]
231 expected = [gen_yielded_data(0, SWARM_OUTPUT_SUCCESS, '0, 0')]
232 actual = get_swarm_results(['key1'])
233 self.assertEqual(expected, actual)
234
235 def test_failure(self):
236 self.requests = [
237 (
238 'http://host:9001/get_result?r=key1',
239 {'retry_404': False, 'retry_50x': False},
240 generate_url_response(0, SWARM_OUTPUT_FAILURE, '0, 1'),
241 ),
242 ]
243 expected = [gen_yielded_data(0, SWARM_OUTPUT_FAILURE, '0, 1')]
244 actual = get_swarm_results(['key1'])
245 self.assertEqual(expected, actual)
246
247 def test_no_test_output(self):
248 self.requests = [
249 (
250 'http://host:9001/get_result?r=key1',
251 {'retry_404': False, 'retry_50x': False},
252 generate_url_response(0, SWARM_OUTPUT_WITH_NO_TEST_OUTPUT, '0, 0'),
253 ),
254 ]
255 expected = [gen_yielded_data(0, SWARM_OUTPUT_WITH_NO_TEST_OUTPUT, '0, 0')]
256 actual = get_swarm_results(['key1'])
257 self.assertEqual(expected, actual)
258
259 def test_no_keys(self):
260 actual = get_swarm_results([])
261 self.assertEqual([], actual)
262
263 def test_url_errors(self):
264 self.mock(logging, 'error', lambda *_: None)
265 # NOTE: get_swarm_results() hardcodes timeout=10. range(12) is because of an
266 # additional time.time() call deep in net.url_open().
267 now = {}
268 lock = threading.Lock()
269 def get_now():
270 t = threading.current_thread()
271 with lock:
272 return now.setdefault(t, range(12)).pop(0)
273 self.mock(swarming.net, 'sleep_before_retry', lambda _x, _y: None)
274 self.mock(swarming, 'now', get_now)
275 # The actual number of requests here depends on 'now' progressing to 10
276 # seconds. It's called twice per loop.
277 self.requests = [
278 (
279 'http://host:9001/get_result?r=key1',
280 {'retry_404': False, 'retry_50x': False},
281 None,
282 ),
283 (
284 'http://host:9001/get_result?r=key1',
285 {'retry_404': False, 'retry_50x': False},
286 None,
287 ),
288 (
289 'http://host:9001/get_result?r=key1',
290 {'retry_404': False, 'retry_50x': False},
291 None,
292 ),
293 (
294 'http://host:9001/get_result?r=key1',
295 {'retry_404': False, 'retry_50x': False},
296 None,
297 ),
298 (
299 'http://host:9001/get_result?r=key1',
300 {'retry_404': False, 'retry_50x': False},
301 None,
302 ),
303 ]
304 actual = get_swarm_results(['key1'])
305 self.assertEqual([], actual)
306 self.assertTrue(all(not v for v in now.itervalues()), now)
307
308 def test_shard_repeated(self):
309 self.requests = [
310 (
311 'http://host:9001/get_result?r=key1',
312 {'retry_404': False, 'retry_50x': False},
313 generate_url_response(0, SWARM_OUTPUT_SUCCESS, '0, 0'),
314 ),
315 (
316 'http://host:9001/get_result?r=key1-repeat',
317 {'retry_404': False, 'retry_50x': False},
318 generate_url_response(0, SWARM_OUTPUT_SUCCESS, '0, 0'),
319 ),
320 ]
321 expected = [gen_yielded_data(0, SWARM_OUTPUT_SUCCESS, '0, 0')]
322 actual = get_swarm_results(['key1', 'key1-repeat'])
323 self.assertEqual(expected, actual)
324
325 def test_one_shard_repeated(self):
326 """Have shard 1 repeated twice, then shard 2 and 3."""
327 self.requests = [
328 (
329 'http://host:9001/get_result?r=key1',
330 {'retry_404': False, 'retry_50x': False},
331 generate_url_response(0, TEST_SHARD_OUTPUT_1, '0, 0'),
332 ),
333 (
334 'http://host:9001/get_result?r=key1-repeat',
335 {'retry_404': False, 'retry_50x': False},
336 generate_url_response(0, TEST_SHARD_OUTPUT_1, '0, 0'),
337 ),
338 (
339 'http://host:9001/get_result?r=key2',
340 {'retry_404': False, 'retry_50x': False},
341 generate_url_response(1, TEST_SHARD_OUTPUT_2, '0, 0'),
342 ),
343 (
344 'http://host:9001/get_result?r=key3',
345 {'retry_404': False, 'retry_50x': False},
346 generate_url_response(2, TEST_SHARD_OUTPUT_3, '0, 0'),
347 ),
348 ]
349 expected = [
350 gen_yielded_data(0, TEST_SHARD_OUTPUT_1, '0, 0'),
351 gen_yielded_data(1, TEST_SHARD_OUTPUT_2, '0, 0'),
352 gen_yielded_data(2, TEST_SHARD_OUTPUT_3, '0, 0'),
353 ]
354 actual = get_swarm_results(['key1', 'key1-repeat', 'key2', 'key3'])
355 self.assertEqual(expected, sorted(actual))
356
357 def test_collect_nothing(self):
358 self.mock(swarming, 'get_test_keys', lambda *_: [1, 2])
359 self.mock(swarming, 'yield_results', lambda *_: [])
360 self.assertEquals(
361 1, swarming.collect('url', 'test_name', 'timeout', 'decorate'))
362
363 def test_collect_success(self):
364 self.mock(swarming, 'get_test_keys', lambda *_: [1, 2])
365 self.mock(sys, 'stdout', StringIO.StringIO())
366 data = {
367 'config_instance_index': 0,
368 'exit_codes': '0',
369 'machine_id': 0,
370 'output': 'Foo',
371 }
372 self.mock(swarming, 'yield_results', lambda *_: [(0, data)])
373 self.assertEquals(
374 0, swarming.collect('url', 'test_name', 'timeout', 'decorate'))
375
376 def test_collect_fail(self):
377 self.mock(swarming, 'get_test_keys', lambda *_: [1, 2])
378 self.mock(sys, 'stdout', StringIO.StringIO())
379 data = {
380 'config_instance_index': 0,
381 'exit_codes': '0,8',
382 'machine_id': 0,
383 'output': 'Foo',
384 }
385 self.mock(swarming, 'yield_results', lambda *_: [(0, data)])
386 self.assertEquals(
387 8, swarming.collect('url', 'test_name', 'timeout', 'decorate'))
388
389
390 def chromium_tasks(retrieval_url):
391 return [
392 {
393 u'action': [
394 u'python', u'run_isolated.zip',
395 u'--hash', FILE_HASH,
396 u'--isolate-server', retrieval_url,
397 ],
398 u'decorate_output': False,
399 u'test_name': u'Run Test',
400 u'time_out': 600,
401 },
402 {
403 u'action' : [
404 u'python', u'swarm_cleanup.py',
405 ],
406 u'decorate_output': False,
407 u'test_name': u'Clean Up',
408 u'time_out': 600,
409 }
410 ]
411
412
413 def generate_expected_json(
414 shards,
415 slave_os,
416 working_dir,
417 isolate_server,
418 profile):
419 os_value = unicode(swarming.PLATFORM_MAPPING_SWARMING[slave_os])
420 expected = {
421 u'cleanup': u'root',
422 u'configurations': [
423 {
424 u'config_name': os_value,
425 u'dimensions': {
426 u'os': os_value,
427 },
428 u'min_instances': shards,
429 u'priority': 101,
430 },
431 ],
432 u'data': [],
433 u'encoding': 'UTF-8',
434 u'env_vars': {},
435 u'restart_on_failure': True,
436 u'test_case_name': TEST_NAME,
437 u'tests': chromium_tasks(isolate_server),
438 u'working_dir': unicode(working_dir),
439 }
440 if shards > 1:
441 expected[u'env_vars'][u'GTEST_SHARD_INDEX'] = u'%(instance_index)s'
442 expected[u'env_vars'][u'GTEST_TOTAL_SHARDS'] = u'%(num_instances)s'
443 if profile:
444 expected[u'tests'][0][u'action'].append(u'--verbose')
445 return expected
446
447
448 class MockedStorage(object):
449 def __init__(self, warm_cache):
450 self._warm_cache = warm_cache
451
452 def upload_items(self, items):
453 return [] if self._warm_cache else items
454
455 def get_fetch_url(self, _digest): # pylint: disable=R0201
456 return 'http://localhost:8081/fetch_url'
457
458
459 class ManifestTest(auto_stub.TestCase):
460 def setUp(self):
461 self.mock(swarming.time, 'sleep', lambda x: None)
462 self.mock(sys, 'stdout', StringIO.StringIO())
463 self.mock(sys, 'stderr', StringIO.StringIO())
464
465 def tearDown(self):
466 if not self.has_failed():
467 self._check_output('', '')
468 super(ManifestTest, self).tearDown()
469
470 def _check_output(self, out, err):
471 self.assertEqual(out, sys.stdout.getvalue())
472 self.assertEqual(err, sys.stderr.getvalue())
473
474 # Flush their content by mocking them again.
475 self.mock(sys, 'stdout', StringIO.StringIO())
476 self.mock(sys, 'stderr', StringIO.StringIO())
477
478 def test_basic_manifest(self):
479 manifest = swarming.Manifest(
480 isolated_hash=FILE_HASH,
481 test_name=TEST_NAME,
482 shards=2,
483 test_filter='*',
484 slave_os='Windows',
485 working_dir='swarm_tests',
486 isolate_server='http://localhost:8081',
487 verbose=False,
488 profile=False,
489 priority=101,
490 algo=ALGO)
491
492 swarming.chromium_setup(manifest)
493 manifest_json = json.loads(manifest.to_json())
494
495 expected = generate_expected_json(
496 shards=2,
497 slave_os='win32',
498 working_dir='swarm_tests',
499 isolate_server=u'http://localhost:8081',
500 profile=False)
501 self.assertEqual(expected, manifest_json)
502
503 def test_basic_linux(self):
504 """A basic linux manifest test to ensure that windows specific values
505 aren't used.
506 """
507 manifest = swarming.Manifest(
508 isolated_hash=FILE_HASH,
509 test_name=TEST_NAME,
510 shards=1,
511 test_filter='*',
512 slave_os='Linux',
513 working_dir='swarm_tests',
514 isolate_server='http://localhost:8081',
515 verbose=False,
516 profile=False,
517 priority=101,
518 algo=ALGO)
519
520 swarming.chromium_setup(manifest)
521 manifest_json = json.loads(manifest.to_json())
522
523 expected = generate_expected_json(
524 shards=1,
525 slave_os='linux2',
526 working_dir='swarm_tests',
527 isolate_server=u'http://localhost:8081',
528 profile=False)
529 self.assertEqual(expected, manifest_json)
530
531 def test_basic_linux_profile(self):
532 manifest = swarming.Manifest(
533 isolated_hash=FILE_HASH,
534 test_name=TEST_NAME,
535 shards=1,
536 test_filter='*',
537 slave_os='Linux',
538 working_dir='swarm_tests',
539 isolate_server='http://localhost:8081',
540 verbose=False,
541 profile=True,
542 priority=101,
543 algo=ALGO)
544
545 swarming.chromium_setup(manifest)
546 manifest_json = json.loads(manifest.to_json())
547
548 expected = generate_expected_json(
549 shards=1,
550 slave_os='linux2',
551 working_dir='swarm_tests',
552 isolate_server=u'http://localhost:8081',
553 profile=True)
554 self.assertEqual(expected, manifest_json)
555
556 def test_process_manifest_success(self):
557 self.mock(swarming.net, 'url_read', lambda url, data=None: '{}')
558 self.mock(swarming.isolateserver, 'get_storage',
559 lambda *_: MockedStorage(warm_cache=False))
560
561 result = swarming.process_manifest(
562 file_hash_or_isolated=FILE_HASH,
563 test_name=TEST_NAME,
564 shards=1,
565 test_filter='*',
566 slave_os='linux2',
567 working_dir='swarm_tests',
568 isolate_server='http://localhost:8081',
569 swarming='http://localhost:8082',
570 verbose=False,
571 profile=False,
572 priority=101,
573 algo=ALGO)
574 self.assertEqual(0, result)
575
576 # Just assert it printed enough, since it contains variable output.
577 out = sys.stdout.getvalue()
578 self.assertTrue(
579 len(out) > STDOUT_FOR_TRIGGER_LEN,
580 (out, sys.stderr.getvalue()))
581 self.assertTrue('Upload complete' in out)
582 self.mock(sys, 'stdout', StringIO.StringIO())
583
584 def test_process_manifest_success_zip_already_uploaded(self):
585 self.mock(swarming.net, 'url_read', lambda url, data=None: '{}')
586 self.mock(swarming.isolateserver, 'get_storage',
587 lambda *_: MockedStorage(warm_cache=True))
588
589 result = swarming.process_manifest(
590 file_hash_or_isolated=FILE_HASH,
591 test_name=TEST_NAME,
592 shards=1,
593 test_filter='*',
594 slave_os='linux2',
595 working_dir='swarm_tests',
596 isolate_server='http://localhost:8081',
597 swarming='http://localhost:8082',
598 verbose=False,
599 profile=False,
600 priority=101,
601 algo=ALGO)
602 self.assertEqual(0, result)
603
604 # Just assert it printed enough, since it contains variable output.
605 out = sys.stdout.getvalue()
606 self.assertTrue(len(out) > STDOUT_FOR_TRIGGER_LEN)
607 self.assertTrue('Zip file already on server' in out)
608 self.mock(sys, 'stdout', StringIO.StringIO())
609
610 def test_no_request(self):
611 try:
612 swarming.main([
613 'trigger', '--swarming', 'https://example.com',
614 '--isolate-server', 'https://example.com'])
615 self.fail()
616 except SystemExit as e:
617 self.assertEqual(2, e.code)
618 self._check_output(
619 '',
620 'Usage: swarming.py trigger [options]\n\n'
621 'swarming.py: error: At least one --task is required.\n')
622
623
624 if __name__ == '__main__':
625 logging.basicConfig(
626 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
627 if '-v' in sys.argv:
628 unittest.TestCase.maxDiff = None
629 unittest.main()
OLDNEW
« no previous file with comments | « swarm_client/tests/swarming_smoke_test.py ('k') | swarm_client/tests/threading_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698