OLD | NEW |
| (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() | |
OLD | NEW |