blob: cc146f800ac26ec1b2b8771171abc6dcad33ad5a [file] [log] [blame]
Nathaniel Manistacbf21da2016-02-02 22:17:44 +00001#!/usr/bin/env python2.7
Craig Tiller6169d5f2016-03-31 07:46:18 -07002# Copyright 2015, Google Inc.
Jan Tattermusch320bd612015-09-15 12:44:35 -07003# 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
33import argparse
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080034import atexit
Jan Tattermusch91ad0182015-10-01 09:22:03 -070035import dockerjob
Jan Tattermusch320bd612015-09-15 12:44:35 -070036import itertools
Jan Tattermusch320bd612015-09-15 12:44:35 -070037import jobset
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080038import json
Jan Tattermusch210a0ea2015-10-02 15:05:36 -070039import multiprocessing
Jan Tattermusch8266c672015-09-17 09:18:03 -070040import os
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080041import re
Adele Zhoua30f8292015-11-02 13:15:46 -080042import report_utils
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080043import subprocess
Jan Tattermusch8266c672015-09-17 09:18:03 -070044import sys
Jan Tattermusch91ad0182015-10-01 09:22:03 -070045import tempfile
Jan Tattermusch8266c672015-09-17 09:18:03 -070046import time
Jan Tattermusch91ad0182015-10-01 09:22:03 -070047import uuid
Jan Tattermusch320bd612015-09-15 12:44:35 -070048
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080049# Docker doesn't clean up after itself, so we do it on exit.
50atexit.register(lambda: subprocess.call(['stty', 'echo']))
51
Jan Tattermusch91ad0182015-10-01 09:22:03 -070052ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
53os.chdir(ROOT)
54
55_DEFAULT_SERVER_PORT=8080
Jan Tattermuschf49936a2015-09-16 15:44:26 -070056
David Garcia Quintasff32a862016-06-21 17:07:20 -070057_SKIP_COMPRESSION = ['client_compressed_unary',
58 'client_compressed_streaming'
59 'server_compressed_unary',
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -080060 'server_compressed_streaming']
61
62_SKIP_ADVANCED = ['custom_metadata', 'status_code_and_message',
63 'unimplemented_method']
Jan Tattermusch8266c672015-09-17 09:18:03 -070064
Jan Tattermusch19f703d2016-03-03 15:33:29 -080065_TEST_TIMEOUT = 3*60
66
Jan Tattermuschf49936a2015-09-16 15:44:26 -070067class CXXLanguage:
68
69 def __init__(self):
Jan Tattermuschf49936a2015-09-16 15:44:26 -070070 self.client_cwd = None
Jan Tattermusch91ad0182015-10-01 09:22:03 -070071 self.server_cwd = None
Jan Tattermusch0a14f622015-10-09 14:34:29 -070072 self.safename = 'cxx'
Jan Tattermuschf49936a2015-09-16 15:44:26 -070073
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -070074 def client_cmd(self, args):
75 return ['bins/opt/interop_client'] + args
Jan Tattermusch8266c672015-09-17 09:18:03 -070076
Jan Tattermuschf49936a2015-09-16 15:44:26 -070077 def cloud_to_prod_env(self):
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -070078 return {}
Jan Tattermuschf49936a2015-09-16 15:44:26 -070079
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -070080 def server_cmd(self, args):
81 return ['bins/opt/interop_server', '--use_tls=true'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -070082
Masood Malekghassemi18cc8422015-10-09 17:55:45 -070083 def global_env(self):
84 return {}
85
Jan Tattermusch289b7b92015-10-21 18:09:59 -070086 def unimplemented_test_cases(self):
David Garcia Quintas303d3082016-05-05 18:25:34 -070087 return _SKIP_ADVANCED
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -080088
89 def unimplemented_test_cases_server(self):
David Garcia Quintas303d3082016-05-05 18:25:34 -070090 return _SKIP_ADVANCED
Jan Tattermusch289b7b92015-10-21 18:09:59 -070091
Jan Tattermuschf49936a2015-09-16 15:44:26 -070092 def __str__(self):
93 return 'c++'
94
95
96class CSharpLanguage:
97
98 def __init__(self):
Jan Tattermuschf49936a2015-09-16 15:44:26 -070099 self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug'
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700100 self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug'
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700101 self.safename = str(self)
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700102
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700103 def client_cmd(self, args):
104 return ['mono', 'Grpc.IntegrationTesting.Client.exe'] + args
Jan Tattermusch8266c672015-09-17 09:18:03 -0700105
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700106 def cloud_to_prod_env(self):
Jan Tattermuscha6b2c4c2015-12-10 16:41:11 -0800107 return {}
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700108
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700109 def server_cmd(self, args):
110 return ['mono', 'Grpc.IntegrationTesting.Server.exe', '--use_tls=true'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700111
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700112 def global_env(self):
113 return {}
114
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700115 def unimplemented_test_cases(self):
Jan Tattermusch85a93832016-04-27 11:11:41 -0700116 return _SKIP_COMPRESSION
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800117
118 def unimplemented_test_cases_server(self):
119 return _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700120
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700121 def __str__(self):
122 return 'csharp'
123
124
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700125class JavaLanguage:
126
127 def __init__(self):
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700128 self.client_cwd = '../grpc-java'
129 self.server_cwd = '../grpc-java'
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700130 self.safename = str(self)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700131
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700132 def client_cmd(self, args):
133 return ['./run-test-client.sh'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700134
135 def cloud_to_prod_env(self):
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700136 return {}
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700137
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700138 def server_cmd(self, args):
139 return ['./run-test-server.sh', '--use_tls=true'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700140
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700141 def global_env(self):
142 return {}
143
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700144 def unimplemented_test_cases(self):
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800145 return _SKIP_ADVANCED + _SKIP_COMPRESSION
146
147 def unimplemented_test_cases_server(self):
148 return _SKIP_ADVANCED + _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700149
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700150 def __str__(self):
151 return 'java'
152
153
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700154class GoLanguage:
155
156 def __init__(self):
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700157 # TODO: this relies on running inside docker
158 self.client_cwd = '/go/src/google.golang.org/grpc/interop/client'
159 self.server_cwd = '/go/src/google.golang.org/grpc/interop/server'
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700160 self.safename = str(self)
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700161
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700162 def client_cmd(self, args):
163 return ['go', 'run', 'client.go'] + args
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700164
165 def cloud_to_prod_env(self):
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700166 return {}
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700167
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700168 def server_cmd(self, args):
169 return ['go', 'run', 'server.go', '--use_tls=true'] + args
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700170
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700171 def global_env(self):
172 return {}
173
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700174 def unimplemented_test_cases(self):
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800175 return _SKIP_ADVANCED + _SKIP_COMPRESSION
176
177 def unimplemented_test_cases_server(self):
178 return _SKIP_ADVANCED + _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700179
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700180 def __str__(self):
181 return 'go'
182
183
Carl Mastrangelode449102015-10-28 11:05:49 -0700184class Http2Client:
185 """Represents the HTTP/2 Interop Test
186
187 This pretends to be a language in order to be built and run, but really it
188 isn't.
189 """
190 def __init__(self):
191 self.client_cwd = None
192 self.safename = str(self)
193
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800194 def client_cmd(self, args):
195 return ['tools/http2_interop/http2_interop.test', '-test.v'] + args
Carl Mastrangelode449102015-10-28 11:05:49 -0700196
197 def cloud_to_prod_env(self):
198 return {}
199
200 def global_env(self):
201 return {}
202
203 def unimplemented_test_cases(self):
204 return _TEST_CASES
205
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800206 def unimplemented_test_cases_server(self):
207 return []
208
Carl Mastrangelode449102015-10-28 11:05:49 -0700209 def __str__(self):
210 return 'http2'
211
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700212class NodeLanguage:
213
214 def __init__(self):
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700215 self.client_cwd = None
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700216 self.server_cwd = None
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700217 self.safename = str(self)
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700218
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700219 def client_cmd(self, args):
220 return ['node', 'src/node/interop/interop_client.js'] + args
Jan Tattermusch8266c672015-09-17 09:18:03 -0700221
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700222 def cloud_to_prod_env(self):
Jan Tattermuscha6b2c4c2015-12-10 16:41:11 -0800223 return {}
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700224
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700225 def server_cmd(self, args):
226 return ['node', 'src/node/interop/interop_server.js', '--use_tls=true'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700227
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700228 def global_env(self):
229 return {}
230
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700231 def unimplemented_test_cases(self):
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800232 return _SKIP_COMPRESSION
233
234 def unimplemented_test_cases_server(self):
235 return _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700236
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700237 def __str__(self):
238 return 'node'
239
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700240
241class PHPLanguage:
242
243 def __init__(self):
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700244 self.client_cwd = None
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700245 self.safename = str(self)
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700246
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700247 def client_cmd(self, args):
248 return ['src/php/bin/interop_client.sh'] + args
Jan Tattermusch8266c672015-09-17 09:18:03 -0700249
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700250 def cloud_to_prod_env(self):
Jan Tattermuscha6b2c4c2015-12-10 16:41:11 -0800251 return {}
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700252
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700253 def global_env(self):
Stanley Cheung22b6bed2015-10-15 16:54:52 -0700254 return {}
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700255
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700256 def unimplemented_test_cases(self):
Stanley Cheung83d8e372016-06-17 11:53:33 -0700257 return _SKIP_COMPRESSION
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800258
259 def unimplemented_test_cases_server(self):
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700260 return []
261
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700262 def __str__(self):
263 return 'php'
264
265
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700266class RubyLanguage:
267
268 def __init__(self):
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700269 self.client_cwd = None
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700270 self.server_cwd = None
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700271 self.safename = str(self)
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700272
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700273 def client_cmd(self, args):
murgatroid99e621f132016-04-21 14:28:00 -0700274 return ['ruby', 'src/ruby/pb/test/client.rb'] + args
Jan Tattermusch8266c672015-09-17 09:18:03 -0700275
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700276 def cloud_to_prod_env(self):
Jan Tattermuscha6b2c4c2015-12-10 16:41:11 -0800277 return {}
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700278
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700279 def server_cmd(self, args):
murgatroid99e621f132016-04-21 14:28:00 -0700280 return ['ruby', 'src/ruby/pb/test/server.rb', '--use_tls=true'] + args
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700281
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700282 def global_env(self):
283 return {}
284
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700285 def unimplemented_test_cases(self):
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800286 return _SKIP_ADVANCED + _SKIP_COMPRESSION
287
288 def unimplemented_test_cases_server(self):
289 return _SKIP_ADVANCED + _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700290
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700291 def __str__(self):
292 return 'ruby'
293
294
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700295class PythonLanguage:
296
297 def __init__(self):
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700298 self.client_cwd = None
299 self.server_cwd = None
300 self.safename = str(self)
301
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700302 def client_cmd(self, args):
303 return [
Masood Malekghassemiccc16102015-12-17 14:32:44 -0800304 'tox -einterop_client --',
305 ' '.join(args)
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700306 ]
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700307
308 def cloud_to_prod_env(self):
Jan Tattermuscha6b2c4c2015-12-10 16:41:11 -0800309 return {}
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700310
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700311 def server_cmd(self, args):
312 return [
Masood Malekghassemiccc16102015-12-17 14:32:44 -0800313 'tox -einterop_server --',
314 ' '.join(args) + ' --use_tls=true'
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700315 ]
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700316
317 def global_env(self):
Ken Payson707c9e22016-04-20 09:42:19 -0700318 return {'LD_LIBRARY_PATH': '{}/libs/opt'.format(DOCKER_WORKDIR_ROOT),
319 'PYTHONPATH': '{}/src/python/gens'.format(DOCKER_WORKDIR_ROOT)}
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700320
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700321 def unimplemented_test_cases(self):
Ken Payson22a65e12016-06-07 19:06:05 -0700322 return _SKIP_ADVANCED + _SKIP_COMPRESSION
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800323
324 def unimplemented_test_cases_server(self):
325 return _SKIP_ADVANCED + _SKIP_COMPRESSION
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700326
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700327 def __str__(self):
328 return 'python'
329
330
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700331_LANGUAGES = {
332 'c++' : CXXLanguage(),
333 'csharp' : CSharpLanguage(),
Jan Tattermuschcc1bde72015-10-05 12:47:45 -0700334 'go' : GoLanguage(),
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700335 'java' : JavaLanguage(),
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700336 'node' : NodeLanguage(),
Jan Tattermuschf88f3e22015-09-16 17:50:45 -0700337 'php' : PHPLanguage(),
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700338 'ruby' : RubyLanguage(),
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700339 'python' : PythonLanguage(),
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700340}
Jan Tattermusch320bd612015-09-15 12:44:35 -0700341
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700342# languages supported as cloud_to_cloud servers
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700343_SERVERS = ['c++', 'node', 'csharp', 'java', 'go', 'ruby', 'python']
Jan Tattermusch8266c672015-09-17 09:18:03 -0700344
Jan Tattermusch320bd612015-09-15 12:44:35 -0700345_TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
Jan Tattermusch1f1c5c52015-10-09 14:36:28 -0700346 'empty_stream', 'client_streaming', 'server_streaming',
Jan Tattermusch13bf36a2015-10-14 17:01:00 -0700347 'cancel_after_begin', 'cancel_after_first_response',
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800348 'timeout_on_sleeping_server', 'custom_metadata',
349 'status_code_and_message', 'unimplemented_method',
David Garcia Quintasff32a862016-06-21 17:07:20 -0700350 'client_compressed_unary', 'server_compressed_unary',
351 'client_compressed_streaming', 'server_compressed_streaming']
Jan Tattermusch320bd612015-09-15 12:44:35 -0700352
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700353_AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds',
354 'oauth2_auth_token', 'per_rpc_creds']
355
Carl Mastrangelo2dd55db2015-11-19 10:51:48 -0800356_HTTP2_TEST_CASES = ["tls", "framing"]
Jan Tattermusch8266c672015-09-17 09:18:03 -0700357
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700358DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
359
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700360def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
361 """Wraps given cmdline array to create 'docker run' cmdline from it."""
362 docker_cmdline = ['docker', 'run', '-i', '--rm=true']
363
364 # turn environ into -e docker args
365 if environ:
366 for k,v in environ.iteritems():
367 docker_cmdline += ['-e', '%s=%s' % (k,v)]
368
369 # set working directory
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700370 workdir = DOCKER_WORKDIR_ROOT
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700371 if cwd:
372 workdir = os.path.join(workdir, cwd)
373 docker_cmdline += ['-w', workdir]
374
375 docker_cmdline += docker_args + [image] + cmdline
376 return docker_cmdline
377
378
379def bash_login_cmdline(cmdline):
380 """Creates bash -l -c cmdline from args list."""
381 # Use login shell:
382 # * rvm and nvm require it
383 # * makes error messages clearer if executables are missing
384 return ['bash', '-l', '-c', ' '.join(cmdline)]
385
386
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800387def auth_options(language, test_case):
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700388 """Returns (cmdline, env) tuple with cloud_to_prod_auth test options."""
389
390 language = str(language)
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800391 cmdargs = []
392 env = {}
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700393
394 # TODO(jtattermusch): this file path only works inside docker
395 key_filepath = '/root/service_account/stubbyCloudTestingTest-ee3fce360ac5.json'
396 oauth_scope_arg = '--oauth_scope=https://www.googleapis.com/auth/xapi.zoo'
397 key_file_arg = '--service_account_key_file=%s' % key_filepath
398 default_account_arg = '--default_service_account=830293263384-compute@developer.gserviceaccount.com'
399
400 if test_case in ['jwt_token_creds', 'per_rpc_creds', 'oauth2_auth_token']:
Jan Tattermusch3b6fef12015-10-19 19:33:24 -0700401 if language in ['csharp', 'node', 'php', 'python', 'ruby']:
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700402 env['GOOGLE_APPLICATION_CREDENTIALS'] = key_filepath
403 else:
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800404 cmdargs += [key_file_arg]
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700405
406 if test_case in ['per_rpc_creds', 'oauth2_auth_token']:
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800407 cmdargs += [oauth_scope_arg]
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700408
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700409 if test_case == 'oauth2_auth_token' and language == 'c++':
410 # C++ oauth2 test uses GCE creds and thus needs to know the default account
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800411 cmdargs += [default_account_arg]
Jan Tattermusch64d7c242015-10-08 08:02:27 -0700412
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700413 if test_case == 'compute_engine_creds':
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800414 cmdargs += [oauth_scope_arg, default_account_arg]
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700415
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800416 return (cmdargs, env)
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700417
418
Jan Tattermusche2686282015-10-08 16:27:07 -0700419def _job_kill_handler(job):
420 if job._spec.container_name:
421 dockerjob.docker_kill(job._spec.container_name)
Jan Tattermusch39e3cb32015-10-22 18:21:08 -0700422 # When the job times out and we decide to kill it,
423 # we need to wait a before restarting the job
424 # to prevent "container name already in use" error.
425 # TODO(jtattermusch): figure out a cleaner way to to this.
426 time.sleep(2)
Jan Tattermusche2686282015-10-08 16:27:07 -0700427
428
murgatroid99090a2512016-02-19 11:32:31 -0800429def cloud_to_prod_jobspec(language, test_case, server_host_name,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800430 server_host_detail, docker_image=None, auth=False):
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700431 """Creates jobspec for cloud-to-prod interop test"""
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800432 container_name = None
433 cmdargs = [
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800434 '--server_host=%s' % server_host_detail[0],
435 '--server_host_override=%s' % server_host_detail[1],
Jan Tattermuschc8b94412015-10-21 17:57:28 -0700436 '--server_port=443',
437 '--use_tls=true',
438 '--test_case=%s' % test_case]
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700439 environ = dict(language.cloud_to_prod_env(), **language.global_env())
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700440 if auth:
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800441 auth_cmdargs, auth_env = auth_options(language, test_case)
442 cmdargs += auth_cmdargs
443 environ.update(auth_env)
444 cmdline = bash_login_cmdline(language.client_cmd(cmdargs))
445 cwd = language.client_cwd
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700446
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700447 if docker_image:
murgatroid99090a2512016-02-19 11:32:31 -0800448 container_name = dockerjob.random_name('interop_client_%s' %
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800449 language.safename)
Jan Tattermusche2686282015-10-08 16:27:07 -0700450 cmdline = docker_run_cmdline(cmdline,
451 image=docker_image,
452 cwd=cwd,
453 environ=environ,
454 docker_args=['--net=host',
455 '--name', container_name])
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700456 cwd = None
457 environ = None
458
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700459 suite_name='cloud_to_prod_auth' if auth else 'cloud_to_prod'
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700460 test_job = jobset.JobSpec(
461 cmdline=cmdline,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700462 cwd=cwd,
463 environ=environ,
murgatroid99090a2512016-02-19 11:32:31 -0800464 shortname='%s:%s:%s:%s' % (suite_name, server_host_name, language,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800465 test_case),
Jan Tattermusch19f703d2016-03-03 15:33:29 -0800466 timeout_seconds=_TEST_TIMEOUT,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700467 flake_retries=5 if args.allow_flakes else 0,
Jan Tattermusche2686282015-10-08 16:27:07 -0700468 timeout_retries=2 if args.allow_flakes else 0,
469 kill_handler=_job_kill_handler)
470 test_job.container_name = container_name
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700471 return test_job
472
Jan Tattermusch8266c672015-09-17 09:18:03 -0700473
474def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700475 server_port, docker_image=None):
Jan Tattermusch8266c672015-09-17 09:18:03 -0700476 """Creates jobspec for cloud-to-cloud interop test"""
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700477 cmdline = bash_login_cmdline(language.client_cmd([
478 '--server_host_override=foo.test.google.fr',
479 '--use_tls=true',
480 '--use_test_ca=true',
481 '--test_case=%s' % test_case,
482 '--server_host=%s' % server_host,
483 '--server_port=%s' % server_port]))
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700484 cwd = language.client_cwd
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700485 environ = language.global_env()
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700486 if docker_image:
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700487 container_name = dockerjob.random_name('interop_client_%s' % language.safename)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700488 cmdline = docker_run_cmdline(cmdline,
489 image=docker_image,
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700490 environ=environ,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700491 cwd=cwd,
Jan Tattermusche2686282015-10-08 16:27:07 -0700492 docker_args=['--net=host',
493 '--name', container_name])
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700494 cwd = None
Jan Tattermusche2686282015-10-08 16:27:07 -0700495
Jan Tattermusch8266c672015-09-17 09:18:03 -0700496 test_job = jobset.JobSpec(
497 cmdline=cmdline,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700498 cwd=cwd,
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700499 environ=environ,
Adele Zhoue4c35612015-10-16 15:34:23 -0700500 shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800501 test_case),
Jan Tattermusch19f703d2016-03-03 15:33:29 -0800502 timeout_seconds=_TEST_TIMEOUT,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700503 flake_retries=5 if args.allow_flakes else 0,
Jan Tattermusche2686282015-10-08 16:27:07 -0700504 timeout_retries=2 if args.allow_flakes else 0,
505 kill_handler=_job_kill_handler)
506 test_job.container_name = container_name
Jan Tattermusch8266c672015-09-17 09:18:03 -0700507 return test_job
508
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700509
510def server_jobspec(language, docker_image):
511 """Create jobspec for running a server"""
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700512 container_name = dockerjob.random_name('interop_server_%s' % language.safename)
Masood Malekghassemi7566c9a2015-10-21 20:29:23 -0700513 cmdline = bash_login_cmdline(
514 language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT]))
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700515 environ = language.global_env()
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700516 docker_cmdline = docker_run_cmdline(cmdline,
517 image=docker_image,
518 cwd=language.server_cwd,
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700519 environ=environ,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700520 docker_args=['-p', str(_DEFAULT_SERVER_PORT),
Jan Tattermusche2686282015-10-08 16:27:07 -0700521 '--name', container_name])
Carl Mastrangelode449102015-10-28 11:05:49 -0700522
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700523 server_job = jobset.JobSpec(
524 cmdline=docker_cmdline,
Masood Malekghassemi18cc8422015-10-09 17:55:45 -0700525 environ=environ,
Adele Zhoue4c35612015-10-16 15:34:23 -0700526 shortname='interop_server_%s' % language,
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700527 timeout_seconds=30*60)
Jan Tattermusche2686282015-10-08 16:27:07 -0700528 server_job.container_name = container_name
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700529 return server_job
530
531
532def build_interop_image_jobspec(language, tag=None):
533 """Creates jobspec for building interop docker image for a language"""
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700534 if not tag:
Jan Tattermusch0a14f622015-10-09 14:34:29 -0700535 tag = 'grpc_interop_%s:%s' % (language.safename, uuid.uuid4())
Stanley Cheung22b6bed2015-10-15 16:54:52 -0700536 env = {'INTEROP_IMAGE': tag,
537 'BASE_NAME': 'grpc_interop_%s' % language.safename}
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700538 if not args.travis:
Stanley Cheung22b6bed2015-10-15 16:54:52 -0700539 env['TTY_FLAG'] = '-t'
540 # This env variable is used to get around the github rate limit
541 # error when running the PHP `composer install` command
Stanley Cheungd82efd82016-02-10 10:36:20 -0800542 host_file = '%s/.composer/auth.json' % os.environ['HOME']
543 if language.safename == 'php' and os.path.exists(host_file):
Stanley Cheung22b6bed2015-10-15 16:54:52 -0700544 env['BUILD_INTEROP_DOCKER_EXTRA_ARGS'] = \
Stanley Cheungd82efd82016-02-10 10:36:20 -0800545 '-v %s:/root/.composer/auth.json:ro' % host_file
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700546 build_job = jobset.JobSpec(
Jan Tattermusch9835d4b2016-04-29 15:05:05 -0700547 cmdline=['tools/run_tests/dockerize/build_interop_image.sh'],
Stanley Cheung22b6bed2015-10-15 16:54:52 -0700548 environ=env,
Adele Zhoue4c35612015-10-16 15:34:23 -0700549 shortname='build_docker_%s' % (language),
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700550 timeout_seconds=30*60)
551 build_job.tag = tag
552 return build_job
553
554
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -0800555def aggregate_http2_results(stdout):
556 match = re.search(r'\{"cases[^\]]*\]\}', stdout)
557 if not match:
558 return None
murgatroid99c3910ca2016-01-06 13:14:23 -0800559
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -0800560 results = json.loads(match.group(0))
561 skipped = 0
562 passed = 0
563 failed = 0
564 failed_cases = []
565 for case in results['cases']:
566 if case.get('skipped', False):
567 skipped += 1
568 else:
569 if case.get('passed', False):
570 passed += 1
571 else:
572 failed += 1
573 failed_cases.append(case.get('name', "NONAME"))
574 return {
575 'passed': passed,
576 'failed': failed,
577 'skipped': skipped,
578 'failed_cases': ', '.join(failed_cases),
579 'percent': 1.0 * passed / (passed + failed)
580 }
581
murgatroid99090a2512016-02-19 11:32:31 -0800582# A dictionary of prod servers to test.
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800583# Format: server_name: (server_host, server_host_override, errors_allowed)
584# TODO(adelez): implement logic for errors_allowed where if the indicated tests
585# fail, they don't impact the overall test result.
586prod_servers = {
murgatroid99090a2512016-02-19 11:32:31 -0800587 'default': ('grpc-test.sandbox.googleapis.com',
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800588 'grpc-test.sandbox.googleapis.com', False),
murgatroid99090a2512016-02-19 11:32:31 -0800589 'gateway_v2': ('grpc-test2.sandbox.googleapis.com',
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800590 'grpc-test2.sandbox.googleapis.com', True),
murgatroid99090a2512016-02-19 11:32:31 -0800591 'cloud_gateway': ('216.239.32.255', 'grpc-test.sandbox.googleapis.com',
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800592 False),
murgatroid99090a2512016-02-19 11:32:31 -0800593 'cloud_gateway_v2': ('216.239.32.255', 'grpc-test2.sandbox.googleapis.com',
Adele Zhou2480f982016-02-26 14:18:46 -0800594 True),
murgatroid99e621f132016-04-21 14:28:00 -0700595 'gateway_v4': ('grpc-test4.sandbox.googleapis.com',
596 'grpc-test4.sandbox.googleapis.com', True),
Adele Zhou2480f982016-02-26 14:18:46 -0800597 'cloud_gateway_v4': ('216.239.32.255', 'grpc-test4.sandbox.googleapis.com',
598 True),
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800599}
600
Jan Tattermusch320bd612015-09-15 12:44:35 -0700601argp = argparse.ArgumentParser(description='Run interop tests.')
602argp.add_argument('-l', '--language',
603 choices=['all'] + sorted(_LANGUAGES),
604 nargs='+',
Jan Tattermusch8266c672015-09-17 09:18:03 -0700605 default=['all'],
606 help='Clients to run.')
Jan Tattermusch210a0ea2015-10-02 15:05:36 -0700607argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
Jan Tattermusch8266c672015-09-17 09:18:03 -0700608argp.add_argument('--cloud_to_prod',
609 default=False,
610 action='store_const',
611 const=True,
612 help='Run cloud_to_prod tests.')
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700613argp.add_argument('--cloud_to_prod_auth',
614 default=False,
615 action='store_const',
616 const=True,
617 help='Run cloud_to_prod_auth tests.')
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800618argp.add_argument('--prod_servers',
619 choices=prod_servers.keys(),
620 default=['default'],
621 nargs='+',
622 help=('The servers to run cloud_to_prod and '
623 'cloud_to_prod_auth tests against.'))
Jan Tattermusch8266c672015-09-17 09:18:03 -0700624argp.add_argument('-s', '--server',
625 choices=['all'] + sorted(_SERVERS),
626 action='append',
627 help='Run cloud_to_cloud servers in a separate docker ' +
628 'image. Servers can only be started automatically if ' +
629 '--use_docker option is enabled.',
630 default=[])
631argp.add_argument('--override_server',
632 action='append',
Adele Zhoue4c35612015-10-16 15:34:23 -0700633 type=lambda kv: kv.split('='),
Jan Tattermusch8266c672015-09-17 09:18:03 -0700634 help='Use servername=HOST:PORT to explicitly specify a server. E.g. csharp=localhost:50000',
635 default=[])
636argp.add_argument('-t', '--travis',
637 default=False,
638 action='store_const',
639 const=True)
640argp.add_argument('--use_docker',
641 default=False,
642 action='store_const',
643 const=True,
644 help='Run all the interop tests under docker. That provides ' +
645 'additional isolation and prevents the need to install ' +
646 'language specific prerequisites. Only available on Linux.')
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700647argp.add_argument('--allow_flakes',
648 default=False,
649 action='store_const',
650 const=True,
Adele Zhoue4c35612015-10-16 15:34:23 -0700651 help='Allow flaky tests to show as passing (re-runs failed tests up to five times)')
Carl Mastrangelode449102015-10-28 11:05:49 -0700652argp.add_argument('--http2_interop',
653 default=False,
654 action='store_const',
655 const=True,
656 help='Enable HTTP/2 interop tests')
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800657
Jan Tattermusch320bd612015-09-15 12:44:35 -0700658args = argp.parse_args()
659
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700660servers = set(s for s in itertools.chain.from_iterable(_SERVERS
Jan Tattermusch8266c672015-09-17 09:18:03 -0700661 if x == 'all' else [x]
662 for x in args.server))
663
664if args.use_docker:
665 if not args.travis:
666 print 'Seen --use_docker flag, will run interop tests under docker.'
667 print
668 print 'IMPORTANT: The changes you are testing need to be locally committed'
669 print 'because only the committed changes in the current branch will be'
670 print 'copied to the docker environment.'
671 time.sleep(5)
672
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700673if not args.use_docker and servers:
Adele Zhoue4c35612015-10-16 15:34:23 -0700674 print 'Running interop servers is only supported with --use_docker option enabled.'
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700675 sys.exit(1)
Jan Tattermusch8266c672015-09-17 09:18:03 -0700676
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700677languages = set(_LANGUAGES[l]
678 for l in itertools.chain.from_iterable(
679 _LANGUAGES.iterkeys() if x == 'all' else [x]
680 for x in args.language))
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800681
Carl Mastrangelode449102015-10-28 11:05:49 -0700682http2Interop = Http2Client() if args.http2_interop else None
Jan Tattermusch320bd612015-09-15 12:44:35 -0700683
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700684docker_images={}
685if args.use_docker:
686 # languages for which to build docker images
687 languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] +
688 [s for s in servers]))
Carl Mastrangelode449102015-10-28 11:05:49 -0700689 if args.http2_interop:
690 languages_to_build.add(http2Interop)
Jan Tattermusch8266c672015-09-17 09:18:03 -0700691
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700692 build_jobs = []
693 for l in languages_to_build:
694 job = build_interop_image_jobspec(l)
695 docker_images[str(l)] = job.tag
696 build_jobs.append(job)
Jan Tattermusch8266c672015-09-17 09:18:03 -0700697
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700698 if build_jobs:
699 jobset.message('START', 'Building interop docker images.', do_newline=True)
Adele Zhoue4c35612015-10-16 15:34:23 -0700700 num_failures, _ = jobset.run(
701 build_jobs, newline_on_success=True, maxjobs=args.jobs)
702 if num_failures == 0:
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800703 jobset.message('SUCCESS', 'All docker images built successfully.',
Adele Zhoue4c35612015-10-16 15:34:23 -0700704 do_newline=True)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700705 else:
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800706 jobset.message('FAILED', 'Failed to build interop docker images.',
Adele Zhoue4c35612015-10-16 15:34:23 -0700707 do_newline=True)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700708 for image in docker_images.itervalues():
709 dockerjob.remove_image(image, skip_nonexistent=True)
Carl Mastrangelo7a171402015-10-26 14:01:03 -0700710 sys.exit(1)
Jan Tattermusch8266c672015-09-17 09:18:03 -0700711
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700712# Start interop servers.
713server_jobs={}
714server_addresses={}
715try:
716 for s in servers:
717 lang = str(s)
718 spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang))
719 job = dockerjob.DockerJob(spec)
720 server_jobs[lang] = job
721 server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT))
Jan Tattermusch8266c672015-09-17 09:18:03 -0700722
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700723 jobs = []
724 if args.cloud_to_prod:
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800725 for server_host_name in args.prod_servers:
726 for language in languages:
727 for test_case in _TEST_CASES:
728 if not test_case in language.unimplemented_test_cases():
729 if not test_case in _SKIP_ADVANCED + _SKIP_COMPRESSION:
730 test_job = cloud_to_prod_jobspec(
murgatroid99090a2512016-02-19 11:32:31 -0800731 language, test_case, server_host_name,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800732 prod_servers[server_host_name],
733 docker_image=docker_images.get(str(language)))
734 jobs.append(test_job)
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800735
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800736 if args.http2_interop:
737 for test_case in _HTTP2_TEST_CASES:
738 test_job = cloud_to_prod_jobspec(
murgatroid99090a2512016-02-19 11:32:31 -0800739 http2Interop, test_case, server_host_name,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800740 prod_servers[server_host_name],
741 docker_image=docker_images.get(str(http2Interop)))
742 jobs.append(test_job)
Jan Tattermusch320bd612015-09-15 12:44:35 -0700743
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700744 if args.cloud_to_prod_auth:
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800745 for server_host_name in args.prod_servers:
746 for language in languages:
747 for test_case in _AUTH_TEST_CASES:
748 if not test_case in language.unimplemented_test_cases():
749 test_job = cloud_to_prod_jobspec(
murgatroid99090a2512016-02-19 11:32:31 -0800750 language, test_case, server_host_name,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800751 prod_servers[server_host_name],
752 docker_image=docker_images.get(str(language)), auth=True)
753 jobs.append(test_job)
Jan Tattermuschfb8c77d2015-10-06 09:33:37 -0700754
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700755 for server in args.override_server:
756 server_name = server[0]
757 (server_host, server_port) = server[1].split(':')
758 server_addresses[server_name] = (server_host, server_port)
Jan Tattermusch320bd612015-09-15 12:44:35 -0700759
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700760 for server_name, server_address in server_addresses.iteritems():
761 (server_host, server_port) = server_address
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800762 server_language = _LANGUAGES.get(server_name, None)
763 skip_server = [] # test cases unimplemented by server
764 if server_language:
765 skip_server = server_language.unimplemented_test_cases_server()
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700766 for language in languages:
767 for test_case in _TEST_CASES:
Jan Tattermusch289b7b92015-10-21 18:09:59 -0700768 if not test_case in language.unimplemented_test_cases():
Jan Tattermusch5c7a1c82015-12-09 19:56:51 -0800769 if not test_case in skip_server:
770 test_job = cloud_to_cloud_jobspec(language,
771 test_case,
772 server_name,
773 server_host,
774 server_port,
775 docker_image=docker_images.get(str(language)))
776 jobs.append(test_job)
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800777
Carl Mastrangelode449102015-10-28 11:05:49 -0700778 if args.http2_interop:
779 for test_case in _HTTP2_TEST_CASES:
Carl Mastrangelo3b2e1bd2015-11-06 14:31:55 -0800780 if server_name == "go":
781 # TODO(carl-mastrangelo): Reenable after https://github.com/grpc/grpc-go/issues/434
murgatroid99c3910ca2016-01-06 13:14:23 -0800782 continue
Carl Mastrangelode449102015-10-28 11:05:49 -0700783 test_job = cloud_to_cloud_jobspec(http2Interop,
784 test_case,
785 server_name,
786 server_host,
787 server_port,
788 docker_image=docker_images.get(str(http2Interop)))
789 jobs.append(test_job)
Jan Tattermusch320bd612015-09-15 12:44:35 -0700790
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700791 if not jobs:
Adele Zhoue4c35612015-10-16 15:34:23 -0700792 print 'No jobs to run.'
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700793 for image in docker_images.itervalues():
794 dockerjob.remove_image(image, skip_nonexistent=True)
795 sys.exit(1)
796
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800797 num_failures, resultset = jobset.run(jobs, newline_on_success=True,
Adele Zhou2271ab52015-10-28 13:59:14 -0700798 maxjobs=args.jobs)
Adele Zhoue4c35612015-10-16 15:34:23 -0700799 if num_failures:
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700800 jobset.message('FAILED', 'Some tests failed', do_newline=True)
Adele Zhoue4c35612015-10-16 15:34:23 -0700801 else:
802 jobset.message('SUCCESS', 'All tests passed', do_newline=True)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700803
Adele Zhou3bc7ba42015-11-05 10:21:58 -0800804 report_utils.render_junit_xml_report(resultset, 'report.xml')
Masood Malekghassemi0a9cc3c2015-11-09 12:24:05 -0800805
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -0800806 for name, job in resultset.iteritems():
807 if "http2" in name:
808 job[0].http2results = aggregate_http2_results(job[0].message)
809
Adele Zhou3bc7ba42015-11-05 10:21:58 -0800810 report_utils.render_interop_html_report(
murgatroid99c3910ca2016-01-06 13:14:23 -0800811 set([str(l) for l in languages]), servers, _TEST_CASES, _AUTH_TEST_CASES,
Carl Mastrangelode449102015-10-28 11:05:49 -0700812 _HTTP2_TEST_CASES, resultset, num_failures,
murgatroid99090a2512016-02-19 11:32:31 -0800813 args.cloud_to_prod_auth or args.cloud_to_prod, args.prod_servers,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800814 args.http2_interop)
Jan Tattermusch91ad0182015-10-01 09:22:03 -0700815
816finally:
817 # Check if servers are still running.
818 for server, job in server_jobs.iteritems():
819 if not job.is_running():
820 print 'Server "%s" has exited prematurely.' % server
821
822 dockerjob.finish_jobs([j for j in server_jobs.itervalues()])
823
824 for image in docker_images.itervalues():
825 print 'Removing docker image %s' % image
David Garcia Quintas2bf574f2016-01-14 15:27:08 -0800826 dockerjob.remove_image(image)