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

Side by Side Diff: third_party/grpc/tools/run_tests/run_interop_tests.py

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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
(Empty)
1 #!/usr/bin/env python2.7
2 # Copyright 2015-2016, Google Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 """Run interop (cross-language) tests in parallel."""
32
33 import argparse
34 import atexit
35 import dockerjob
36 import itertools
37 import jobset
38 import json
39 import multiprocessing
40 import os
41 import re
42 import report_utils
43 import subprocess
44 import sys
45 import tempfile
46 import time
47 import uuid
48
49 # Docker doesn't clean up after itself, so we do it on exit.
50 atexit.register(lambda: subprocess.call(['stty', 'echo']))
51
52 ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
53 os.chdir(ROOT)
54
55 _DEFAULT_SERVER_PORT=8080
56
57 _SKIP_COMPRESSION = ['large_compressed_unary',
58 'server_compressed_streaming']
59
60 _SKIP_ADVANCED = ['custom_metadata', 'status_code_and_message',
61 'unimplemented_method']
62
63 _TEST_TIMEOUT = 3*60
64
65 class CXXLanguage:
66
67 def __init__(self):
68 self.client_cwd = None
69 self.server_cwd = None
70 self.safename = 'cxx'
71
72 def client_cmd(self, args):
73 return ['bins/opt/interop_client'] + args
74
75 def cloud_to_prod_env(self):
76 return {}
77
78 def server_cmd(self, args):
79 return ['bins/opt/interop_server', '--use_tls=true'] + args
80
81 def global_env(self):
82 return {}
83
84 def unimplemented_test_cases(self):
85 return _SKIP_ADVANCED + _SKIP_COMPRESSION
86
87 def unimplemented_test_cases_server(self):
88 return _SKIP_ADVANCED + _SKIP_COMPRESSION
89
90 def __str__(self):
91 return 'c++'
92
93
94 class CSharpLanguage:
95
96 def __init__(self):
97 self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug'
98 self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug'
99 self.safename = str(self)
100
101 def client_cmd(self, args):
102 return ['mono', 'Grpc.IntegrationTesting.Client.exe'] + args
103
104 def cloud_to_prod_env(self):
105 return {}
106
107 def server_cmd(self, args):
108 return ['mono', 'Grpc.IntegrationTesting.Server.exe', '--use_tls=true'] + ar gs
109
110 def global_env(self):
111 return {}
112
113 def unimplemented_test_cases(self):
114 # TODO: status_code_and_message doesn't work against node_server
115 return _SKIP_COMPRESSION + ['status_code_and_message']
116
117 def unimplemented_test_cases_server(self):
118 return _SKIP_COMPRESSION
119
120 def __str__(self):
121 return 'csharp'
122
123
124 class JavaLanguage:
125
126 def __init__(self):
127 self.client_cwd = '../grpc-java'
128 self.server_cwd = '../grpc-java'
129 self.safename = str(self)
130
131 def client_cmd(self, args):
132 return ['./run-test-client.sh'] + args
133
134 def cloud_to_prod_env(self):
135 return {}
136
137 def server_cmd(self, args):
138 return ['./run-test-server.sh', '--use_tls=true'] + args
139
140 def global_env(self):
141 return {}
142
143 def unimplemented_test_cases(self):
144 return _SKIP_ADVANCED + _SKIP_COMPRESSION
145
146 def unimplemented_test_cases_server(self):
147 return _SKIP_ADVANCED + _SKIP_COMPRESSION
148
149 def __str__(self):
150 return 'java'
151
152
153 class GoLanguage:
154
155 def __init__(self):
156 # TODO: this relies on running inside docker
157 self.client_cwd = '/go/src/google.golang.org/grpc/interop/client'
158 self.server_cwd = '/go/src/google.golang.org/grpc/interop/server'
159 self.safename = str(self)
160
161 def client_cmd(self, args):
162 return ['go', 'run', 'client.go'] + args
163
164 def cloud_to_prod_env(self):
165 return {}
166
167 def server_cmd(self, args):
168 return ['go', 'run', 'server.go', '--use_tls=true'] + args
169
170 def global_env(self):
171 return {}
172
173 def unimplemented_test_cases(self):
174 return _SKIP_ADVANCED + _SKIP_COMPRESSION
175
176 def unimplemented_test_cases_server(self):
177 return _SKIP_ADVANCED + _SKIP_COMPRESSION
178
179 def __str__(self):
180 return 'go'
181
182
183 class Http2Client:
184 """Represents the HTTP/2 Interop Test
185
186 This pretends to be a language in order to be built and run, but really it
187 isn't.
188 """
189 def __init__(self):
190 self.client_cwd = None
191 self.safename = str(self)
192
193 def client_cmd(self, args):
194 return ['tools/http2_interop/http2_interop.test', '-test.v'] + args
195
196 def cloud_to_prod_env(self):
197 return {}
198
199 def global_env(self):
200 return {}
201
202 def unimplemented_test_cases(self):
203 return _TEST_CASES
204
205 def unimplemented_test_cases_server(self):
206 return []
207
208 def __str__(self):
209 return 'http2'
210
211 class NodeLanguage:
212
213 def __init__(self):
214 self.client_cwd = None
215 self.server_cwd = None
216 self.safename = str(self)
217
218 def client_cmd(self, args):
219 return ['node', 'src/node/interop/interop_client.js'] + args
220
221 def cloud_to_prod_env(self):
222 return {}
223
224 def server_cmd(self, args):
225 return ['node', 'src/node/interop/interop_server.js', '--use_tls=true'] + ar gs
226
227 def global_env(self):
228 return {}
229
230 def unimplemented_test_cases(self):
231 return _SKIP_COMPRESSION
232
233 def unimplemented_test_cases_server(self):
234 return _SKIP_COMPRESSION
235
236 def __str__(self):
237 return 'node'
238
239
240 class PHPLanguage:
241
242 def __init__(self):
243 self.client_cwd = None
244 self.safename = str(self)
245
246 def client_cmd(self, args):
247 return ['src/php/bin/interop_client.sh'] + args
248
249 def cloud_to_prod_env(self):
250 return {}
251
252 def global_env(self):
253 return {}
254
255 def unimplemented_test_cases(self):
256 return _SKIP_ADVANCED + _SKIP_COMPRESSION
257
258 def unimplemented_test_cases_server(self):
259 return []
260
261 def __str__(self):
262 return 'php'
263
264
265 class RubyLanguage:
266
267 def __init__(self):
268 self.client_cwd = None
269 self.server_cwd = None
270 self.safename = str(self)
271
272 def client_cmd(self, args):
273 return ['ruby', 'src/ruby/bin/interop/interop_client.rb'] + args
274
275 def cloud_to_prod_env(self):
276 return {}
277
278 def server_cmd(self, args):
279 return ['ruby', 'src/ruby/bin/interop/interop_server.rb', '--use_tls=true'] + args
280
281 def global_env(self):
282 return {}
283
284 def unimplemented_test_cases(self):
285 return _SKIP_ADVANCED + _SKIP_COMPRESSION
286
287 def unimplemented_test_cases_server(self):
288 return _SKIP_ADVANCED + _SKIP_COMPRESSION
289
290 def __str__(self):
291 return 'ruby'
292
293
294 class PythonLanguage:
295
296 def __init__(self):
297 self.client_cwd = None
298 self.server_cwd = None
299 self.safename = str(self)
300
301 def client_cmd(self, args):
302 return [
303 'tox -einterop_client --',
304 ' '.join(args)
305 ]
306
307 def cloud_to_prod_env(self):
308 return {}
309
310 def server_cmd(self, args):
311 return [
312 'tox -einterop_server --',
313 ' '.join(args) + ' --use_tls=true'
314 ]
315
316 def global_env(self):
317 return {'LD_LIBRARY_PATH': '{}/libs/opt'.format(DOCKER_WORKDIR_ROOT)}
318
319 def unimplemented_test_cases(self):
320 return _SKIP_ADVANCED + _SKIP_COMPRESSION + ['jwt_token_creds',
321 'per_rpc_creds']
322
323 def unimplemented_test_cases_server(self):
324 return _SKIP_ADVANCED + _SKIP_COMPRESSION
325
326 def __str__(self):
327 return 'python'
328
329
330 _LANGUAGES = {
331 'c++' : CXXLanguage(),
332 'csharp' : CSharpLanguage(),
333 'go' : GoLanguage(),
334 'java' : JavaLanguage(),
335 'node' : NodeLanguage(),
336 'php' : PHPLanguage(),
337 'ruby' : RubyLanguage(),
338 'python' : PythonLanguage(),
339 }
340
341 # languages supported as cloud_to_cloud servers
342 _SERVERS = ['c++', 'node', 'csharp', 'java', 'go', 'ruby', 'python']
343
344 _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
345 'empty_stream', 'client_streaming', 'server_streaming',
346 'cancel_after_begin', 'cancel_after_first_response',
347 'timeout_on_sleeping_server', 'custom_metadata',
348 'status_code_and_message', 'unimplemented_method',
349 'large_compressed_unary', 'server_compressed_streaming']
350
351 _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds',
352 'oauth2_auth_token', 'per_rpc_creds']
353
354 _HTTP2_TEST_CASES = ["tls", "framing"]
355
356 DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
357
358 def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
359 """Wraps given cmdline array to create 'docker run' cmdline from it."""
360 docker_cmdline = ['docker', 'run', '-i', '--rm=true']
361
362 # turn environ into -e docker args
363 if environ:
364 for k,v in environ.iteritems():
365 docker_cmdline += ['-e', '%s=%s' % (k,v)]
366
367 # set working directory
368 workdir = DOCKER_WORKDIR_ROOT
369 if cwd:
370 workdir = os.path.join(workdir, cwd)
371 docker_cmdline += ['-w', workdir]
372
373 docker_cmdline += docker_args + [image] + cmdline
374 return docker_cmdline
375
376
377 def bash_login_cmdline(cmdline):
378 """Creates bash -l -c cmdline from args list."""
379 # Use login shell:
380 # * rvm and nvm require it
381 # * makes error messages clearer if executables are missing
382 return ['bash', '-l', '-c', ' '.join(cmdline)]
383
384
385 def auth_options(language, test_case):
386 """Returns (cmdline, env) tuple with cloud_to_prod_auth test options."""
387
388 language = str(language)
389 cmdargs = []
390 env = {}
391
392 # TODO(jtattermusch): this file path only works inside docker
393 key_filepath = '/root/service_account/stubbyCloudTestingTest-ee3fce360ac5.json '
394 oauth_scope_arg = '--oauth_scope=https://www.googleapis.com/auth/xapi.zoo'
395 key_file_arg = '--service_account_key_file=%s' % key_filepath
396 default_account_arg = '--default_service_account=830293263384-compute@develope r.gserviceaccount.com'
397
398 if test_case in ['jwt_token_creds', 'per_rpc_creds', 'oauth2_auth_token']:
399 if language in ['csharp', 'node', 'php', 'python', 'ruby']:
400 env['GOOGLE_APPLICATION_CREDENTIALS'] = key_filepath
401 else:
402 cmdargs += [key_file_arg]
403
404 if test_case in ['per_rpc_creds', 'oauth2_auth_token']:
405 cmdargs += [oauth_scope_arg]
406
407 if test_case == 'oauth2_auth_token' and language == 'c++':
408 # C++ oauth2 test uses GCE creds and thus needs to know the default account
409 cmdargs += [default_account_arg]
410
411 if test_case == 'compute_engine_creds':
412 cmdargs += [oauth_scope_arg, default_account_arg]
413
414 return (cmdargs, env)
415
416
417 def _job_kill_handler(job):
418 if job._spec.container_name:
419 dockerjob.docker_kill(job._spec.container_name)
420 # When the job times out and we decide to kill it,
421 # we need to wait a before restarting the job
422 # to prevent "container name already in use" error.
423 # TODO(jtattermusch): figure out a cleaner way to to this.
424 time.sleep(2)
425
426
427 def cloud_to_prod_jobspec(language, test_case, server_host_name,
428 server_host_detail, docker_image=None, auth=False):
429 """Creates jobspec for cloud-to-prod interop test"""
430 container_name = None
431 cmdargs = [
432 '--server_host=%s' % server_host_detail[0],
433 '--server_host_override=%s' % server_host_detail[1],
434 '--server_port=443',
435 '--use_tls=true',
436 '--test_case=%s' % test_case]
437 environ = dict(language.cloud_to_prod_env(), **language.global_env())
438 if auth:
439 auth_cmdargs, auth_env = auth_options(language, test_case)
440 cmdargs += auth_cmdargs
441 environ.update(auth_env)
442 cmdline = bash_login_cmdline(language.client_cmd(cmdargs))
443 cwd = language.client_cwd
444
445 if docker_image:
446 container_name = dockerjob.random_name('interop_client_%s' %
447 language.safename)
448 cmdline = docker_run_cmdline(cmdline,
449 image=docker_image,
450 cwd=cwd,
451 environ=environ,
452 docker_args=['--net=host',
453 '--name', container_name])
454 cwd = None
455 environ = None
456
457 suite_name='cloud_to_prod_auth' if auth else 'cloud_to_prod'
458 test_job = jobset.JobSpec(
459 cmdline=cmdline,
460 cwd=cwd,
461 environ=environ,
462 shortname='%s:%s:%s:%s' % (suite_name, server_host_name, language,
463 test_case),
464 timeout_seconds=_TEST_TIMEOUT,
465 flake_retries=5 if args.allow_flakes else 0,
466 timeout_retries=2 if args.allow_flakes else 0,
467 kill_handler=_job_kill_handler)
468 test_job.container_name = container_name
469 return test_job
470
471
472 def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
473 server_port, docker_image=None):
474 """Creates jobspec for cloud-to-cloud interop test"""
475 cmdline = bash_login_cmdline(language.client_cmd([
476 '--server_host_override=foo.test.google.fr',
477 '--use_tls=true',
478 '--use_test_ca=true',
479 '--test_case=%s' % test_case,
480 '--server_host=%s' % server_host,
481 '--server_port=%s' % server_port]))
482 cwd = language.client_cwd
483 environ = language.global_env()
484 if docker_image:
485 container_name = dockerjob.random_name('interop_client_%s' % language.safena me)
486 cmdline = docker_run_cmdline(cmdline,
487 image=docker_image,
488 environ=environ,
489 cwd=cwd,
490 docker_args=['--net=host',
491 '--name', container_name])
492 cwd = None
493
494 test_job = jobset.JobSpec(
495 cmdline=cmdline,
496 cwd=cwd,
497 environ=environ,
498 shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
499 test_case),
500 timeout_seconds=_TEST_TIMEOUT,
501 flake_retries=5 if args.allow_flakes else 0,
502 timeout_retries=2 if args.allow_flakes else 0,
503 kill_handler=_job_kill_handler)
504 test_job.container_name = container_name
505 return test_job
506
507
508 def server_jobspec(language, docker_image):
509 """Create jobspec for running a server"""
510 container_name = dockerjob.random_name('interop_server_%s' % language.safename )
511 cmdline = bash_login_cmdline(
512 language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT]))
513 environ = language.global_env()
514 docker_cmdline = docker_run_cmdline(cmdline,
515 image=docker_image,
516 cwd=language.server_cwd,
517 environ=environ,
518 docker_args=['-p', str(_DEFAULT_SERVER_POR T),
519 '--name', container_name])
520
521 server_job = jobset.JobSpec(
522 cmdline=docker_cmdline,
523 environ=environ,
524 shortname='interop_server_%s' % language,
525 timeout_seconds=30*60)
526 server_job.container_name = container_name
527 return server_job
528
529
530 def build_interop_image_jobspec(language, tag=None):
531 """Creates jobspec for building interop docker image for a language"""
532 if not tag:
533 tag = 'grpc_interop_%s:%s' % (language.safename, uuid.uuid4())
534 env = {'INTEROP_IMAGE': tag,
535 'BASE_NAME': 'grpc_interop_%s' % language.safename}
536 if not args.travis:
537 env['TTY_FLAG'] = '-t'
538 # This env variable is used to get around the github rate limit
539 # error when running the PHP `composer install` command
540 host_file = '%s/.composer/auth.json' % os.environ['HOME']
541 if language.safename == 'php' and os.path.exists(host_file):
542 env['BUILD_INTEROP_DOCKER_EXTRA_ARGS'] = \
543 '-v %s:/root/.composer/auth.json:ro' % host_file
544 build_job = jobset.JobSpec(
545 cmdline=['tools/jenkins/build_interop_image.sh'],
546 environ=env,
547 shortname='build_docker_%s' % (language),
548 timeout_seconds=30*60)
549 build_job.tag = tag
550 return build_job
551
552
553 def aggregate_http2_results(stdout):
554 match = re.search(r'\{"cases[^\]]*\]\}', stdout)
555 if not match:
556 return None
557
558 results = json.loads(match.group(0))
559 skipped = 0
560 passed = 0
561 failed = 0
562 failed_cases = []
563 for case in results['cases']:
564 if case.get('skipped', False):
565 skipped += 1
566 else:
567 if case.get('passed', False):
568 passed += 1
569 else:
570 failed += 1
571 failed_cases.append(case.get('name', "NONAME"))
572 return {
573 'passed': passed,
574 'failed': failed,
575 'skipped': skipped,
576 'failed_cases': ', '.join(failed_cases),
577 'percent': 1.0 * passed / (passed + failed)
578 }
579
580 # A dictionary of prod servers to test.
581 # Format: server_name: (server_host, server_host_override, errors_allowed)
582 # TODO(adelez): implement logic for errors_allowed where if the indicated tests
583 # fail, they don't impact the overall test result.
584 prod_servers = {
585 'default': ('grpc-test.sandbox.googleapis.com',
586 'grpc-test.sandbox.googleapis.com', False),
587 'gateway_v2': ('grpc-test2.sandbox.googleapis.com',
588 'grpc-test2.sandbox.googleapis.com', True),
589 'cloud_gateway': ('216.239.32.255', 'grpc-test.sandbox.googleapis.com',
590 False),
591 'cloud_gateway_v2': ('216.239.32.255', 'grpc-test2.sandbox.googleapis.com',
592 True)
593 }
594
595 argp = argparse.ArgumentParser(description='Run interop tests.')
596 argp.add_argument('-l', '--language',
597 choices=['all'] + sorted(_LANGUAGES),
598 nargs='+',
599 default=['all'],
600 help='Clients to run.')
601 argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
602 argp.add_argument('--cloud_to_prod',
603 default=False,
604 action='store_const',
605 const=True,
606 help='Run cloud_to_prod tests.')
607 argp.add_argument('--cloud_to_prod_auth',
608 default=False,
609 action='store_const',
610 const=True,
611 help='Run cloud_to_prod_auth tests.')
612 argp.add_argument('--prod_servers',
613 choices=prod_servers.keys(),
614 default=['default'],
615 nargs='+',
616 help=('The servers to run cloud_to_prod and '
617 'cloud_to_prod_auth tests against.'))
618 argp.add_argument('-s', '--server',
619 choices=['all'] + sorted(_SERVERS),
620 action='append',
621 help='Run cloud_to_cloud servers in a separate docker ' +
622 'image. Servers can only be started automatically if ' +
623 '--use_docker option is enabled.',
624 default=[])
625 argp.add_argument('--override_server',
626 action='append',
627 type=lambda kv: kv.split('='),
628 help='Use servername=HOST:PORT to explicitly specify a server. E.g. csharp=localhost:50000',
629 default=[])
630 argp.add_argument('-t', '--travis',
631 default=False,
632 action='store_const',
633 const=True)
634 argp.add_argument('--use_docker',
635 default=False,
636 action='store_const',
637 const=True,
638 help='Run all the interop tests under docker. That provides ' +
639 'additional isolation and prevents the need to install ' +
640 'language specific prerequisites. Only available on Linux.')
641 argp.add_argument('--allow_flakes',
642 default=False,
643 action='store_const',
644 const=True,
645 help='Allow flaky tests to show as passing (re-runs failed tes ts up to five times)')
646 argp.add_argument('--http2_interop',
647 default=False,
648 action='store_const',
649 const=True,
650 help='Enable HTTP/2 interop tests')
651
652 args = argp.parse_args()
653
654 servers = set(s for s in itertools.chain.from_iterable(_SERVERS
655 if x == 'all' else [x]
656 for x in args.server))
657
658 if args.use_docker:
659 if not args.travis:
660 print 'Seen --use_docker flag, will run interop tests under docker.'
661 print
662 print 'IMPORTANT: The changes you are testing need to be locally committed'
663 print 'because only the committed changes in the current branch will be'
664 print 'copied to the docker environment.'
665 time.sleep(5)
666
667 if not args.use_docker and servers:
668 print 'Running interop servers is only supported with --use_docker option enab led.'
669 sys.exit(1)
670
671 languages = set(_LANGUAGES[l]
672 for l in itertools.chain.from_iterable(
673 _LANGUAGES.iterkeys() if x == 'all' else [x]
674 for x in args.language))
675
676 http2Interop = Http2Client() if args.http2_interop else None
677
678 docker_images={}
679 if args.use_docker:
680 # languages for which to build docker images
681 languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages ] +
682 [s for s in servers]))
683 if args.http2_interop:
684 languages_to_build.add(http2Interop)
685
686 build_jobs = []
687 for l in languages_to_build:
688 job = build_interop_image_jobspec(l)
689 docker_images[str(l)] = job.tag
690 build_jobs.append(job)
691
692 if build_jobs:
693 jobset.message('START', 'Building interop docker images.', do_newline=True)
694 num_failures, _ = jobset.run(
695 build_jobs, newline_on_success=True, maxjobs=args.jobs)
696 if num_failures == 0:
697 jobset.message('SUCCESS', 'All docker images built successfully.',
698 do_newline=True)
699 else:
700 jobset.message('FAILED', 'Failed to build interop docker images.',
701 do_newline=True)
702 for image in docker_images.itervalues():
703 dockerjob.remove_image(image, skip_nonexistent=True)
704 sys.exit(1)
705
706 # Start interop servers.
707 server_jobs={}
708 server_addresses={}
709 try:
710 for s in servers:
711 lang = str(s)
712 spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang))
713 job = dockerjob.DockerJob(spec)
714 server_jobs[lang] = job
715 server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT) )
716
717 jobs = []
718 if args.cloud_to_prod:
719 for server_host_name in args.prod_servers:
720 for language in languages:
721 for test_case in _TEST_CASES:
722 if not test_case in language.unimplemented_test_cases():
723 if not test_case in _SKIP_ADVANCED + _SKIP_COMPRESSION:
724 test_job = cloud_to_prod_jobspec(
725 language, test_case, server_host_name,
726 prod_servers[server_host_name],
727 docker_image=docker_images.get(str(language)))
728 jobs.append(test_job)
729
730 if args.http2_interop:
731 for test_case in _HTTP2_TEST_CASES:
732 test_job = cloud_to_prod_jobspec(
733 http2Interop, test_case, server_host_name,
734 prod_servers[server_host_name],
735 docker_image=docker_images.get(str(http2Interop)))
736 jobs.append(test_job)
737
738 if args.cloud_to_prod_auth:
739 for server_host_name in args.prod_servers:
740 for language in languages:
741 for test_case in _AUTH_TEST_CASES:
742 if not test_case in language.unimplemented_test_cases():
743 test_job = cloud_to_prod_jobspec(
744 language, test_case, server_host_name,
745 prod_servers[server_host_name],
746 docker_image=docker_images.get(str(language)), auth=True)
747 jobs.append(test_job)
748
749 for server in args.override_server:
750 server_name = server[0]
751 (server_host, server_port) = server[1].split(':')
752 server_addresses[server_name] = (server_host, server_port)
753
754 for server_name, server_address in server_addresses.iteritems():
755 (server_host, server_port) = server_address
756 server_language = _LANGUAGES.get(server_name, None)
757 skip_server = [] # test cases unimplemented by server
758 if server_language:
759 skip_server = server_language.unimplemented_test_cases_server()
760 for language in languages:
761 for test_case in _TEST_CASES:
762 if not test_case in language.unimplemented_test_cases():
763 if not test_case in skip_server:
764 test_job = cloud_to_cloud_jobspec(language,
765 test_case,
766 server_name,
767 server_host,
768 server_port,
769 docker_image=docker_images.get(str (language)))
770 jobs.append(test_job)
771
772 if args.http2_interop:
773 for test_case in _HTTP2_TEST_CASES:
774 if server_name == "go":
775 # TODO(carl-mastrangelo): Reenable after https://github.com/grpc/grpc- go/issues/434
776 continue
777 test_job = cloud_to_cloud_jobspec(http2Interop,
778 test_case,
779 server_name,
780 server_host,
781 server_port,
782 docker_image=docker_images.get(str(htt p2Interop)))
783 jobs.append(test_job)
784
785 if not jobs:
786 print 'No jobs to run.'
787 for image in docker_images.itervalues():
788 dockerjob.remove_image(image, skip_nonexistent=True)
789 sys.exit(1)
790
791 num_failures, resultset = jobset.run(jobs, newline_on_success=True,
792 maxjobs=args.jobs)
793 if num_failures:
794 jobset.message('FAILED', 'Some tests failed', do_newline=True)
795 else:
796 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
797
798 report_utils.render_junit_xml_report(resultset, 'report.xml')
799
800 for name, job in resultset.iteritems():
801 if "http2" in name:
802 job[0].http2results = aggregate_http2_results(job[0].message)
803
804 report_utils.render_interop_html_report(
805 set([str(l) for l in languages]), servers, _TEST_CASES, _AUTH_TEST_CASES,
806 _HTTP2_TEST_CASES, resultset, num_failures,
807 args.cloud_to_prod_auth or args.cloud_to_prod, args.prod_servers,
808 args.http2_interop)
809
810 finally:
811 # Check if servers are still running.
812 for server, job in server_jobs.iteritems():
813 if not job.is_running():
814 print 'Server "%s" has exited prematurely.' % server
815
816 dockerjob.finish_jobs([j for j in server_jobs.itervalues()])
817
818 for image in docker_images.itervalues():
819 print 'Removing docker image %s' % image
820 dockerjob.remove_image(image)
OLDNEW
« no previous file with comments | « third_party/grpc/tools/run_tests/run_csharp.sh ('k') | third_party/grpc/tools/run_tests/run_lcov.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698