blob: 05fd0bb27bb2c2b221baa9483034b1cb07c793a1 [file] [log] [blame]
Jan Tattermusch320bd612015-09-15 12:44:35 -07001#!/usr/bin/env python
2# Copyright 2015, 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
33import argparse
34import itertools
35import xml.etree.cElementTree as ET
36import jobset
37
Jan Tattermuschf49936a2015-09-16 15:44:26 -070038
39_CLOUD_TO_PROD_BASE_ARGS = [
40 '--server_host_override=grpc-test.sandbox.google.com',
41 '--server_host=grpc-test.sandbox.google.com',
42 '--server_port=443']
43
44# TOOD(jtattermusch) wrapped languages use this variable for location
45# of roots.pem. We might want to use GRPC_DEFAULT_SSL_ROOTS_FILE_PATH
46# supported by C core SslCredentials instead.
47_SSL_CERT_ENV = { 'SSL_CERT_FILE':'/usr/local/share/grpc/roots.pem' }
48
49# TODO(jtatttermusch) unify usage of --enable_ssl, --use_tls and --use_tls=true
50
51class CXXLanguage:
52
53 def __init__(self):
54 self.client_cmdline_base = ['bins/opt/interop_client']
55 self.client_cwd = None
56
57 def cloud_to_prod_args(self):
58 return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
59 ['--enable_ssl','--use_prod_roots'])
60
61 def cloud_to_prod_env(self):
62 return None
63
64 def __str__(self):
65 return 'c++'
66
67
68class CSharpLanguage:
69
70 def __init__(self):
71 self.client_cmdline_base = ['mono', 'Grpc.IntegrationTesting.Client.exe']
72 self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug'
73
74 def cloud_to_prod_args(self):
75 return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
76 ['--use_tls'])
77
78 def cloud_to_prod_env(self):
79 return _SSL_CERT_ENV
80
81 def __str__(self):
82 return 'csharp'
83
84
85class NodeLanguage:
86
87 def __init__(self):
88 self.client_cmdline_base = ['node', 'src/node/interop/interop_client.js']
89 self.client_cwd = None
90
91 def cloud_to_prod_args(self):
92 return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
93 ['--use_tls=true'])
94
95 def cloud_to_prod_env(self):
96 return _SSL_CERT_ENV
97
98 def __str__(self):
99 return 'node'
100
101class RubyLanguage:
102
103 def __init__(self):
104 self.client_cmdline_base = ['ruby', 'src/ruby/bin/interop/interop_client.rb']
105 self.client_cwd = None
106
107 def cloud_to_prod_args(self):
108 return (self.client_cmdline_base + _CLOUD_TO_PROD_BASE_ARGS +
109 ['--use_tls'])
110
111 def cloud_to_prod_env(self):
112 return _SSL_CERT_ENV
113
114 def __str__(self):
115 return 'ruby'
116
117
Jan Tattermusch320bd612015-09-15 12:44:35 -0700118# TODO(jtattermusch): add php and python once we get them working
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700119_LANGUAGES = {
120 'c++' : CXXLanguage(),
121 'csharp' : CSharpLanguage(),
122 'node' : NodeLanguage(),
123 'ruby' : RubyLanguage(),
124}
Jan Tattermusch320bd612015-09-15 12:44:35 -0700125
126# TODO(jtattermusch): add empty_stream once C++ start supporting it.
127# TODO(jtattermusch): add support for auth tests.
128_TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
129 'client_streaming', 'server_streaming',
130 'cancel_after_begin', 'cancel_after_first_response',
131 'timeout_on_sleeping_server']
132
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700133def cloud_to_prod_jobspec(language, test_case):
134 """Creates jobspec for cloud-to-prod interop test"""
135 cmdline = language.cloud_to_prod_args() + ['--test_case=%s' % test_case]
136 test_job = jobset.JobSpec(
137 cmdline=cmdline,
138 cwd=language.client_cwd,
139 shortname="cloud_to_prod:%s:%s" % (language, test_case),
140 environ=language.cloud_to_prod_env(),
141 timeout_seconds=60)
142 return test_job
143
Jan Tattermusch320bd612015-09-15 12:44:35 -0700144argp = argparse.ArgumentParser(description='Run interop tests.')
145argp.add_argument('-l', '--language',
146 choices=['all'] + sorted(_LANGUAGES),
147 nargs='+',
148 default=['all'])
149args = argp.parse_args()
150
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700151languages = set(_LANGUAGES[l]
152 for l in itertools.chain.from_iterable(
153 _LANGUAGES.iterkeys() if x == 'all' else [x]
154 for x in args.language))
Jan Tattermusch320bd612015-09-15 12:44:35 -0700155
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700156# TODO(jtattermusch): make python script generate cmdline params for interop
157# tests. It's easier to manage than in a shell script.
Jan Tattermusch320bd612015-09-15 12:44:35 -0700158jobs = []
159jobNumber = 0
160for language in languages:
Jan Tattermuschf49936a2015-09-16 15:44:26 -0700161 for test_case in _TEST_CASES:
162 test_job = cloud_to_prod_jobspec(language, test_case)
Jan Tattermusch320bd612015-09-15 12:44:35 -0700163 jobs.append(test_job)
164 jobNumber+=1
165
166root = ET.Element('testsuites')
167testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', name='tests')
168
169jobset.run(jobs, maxjobs=jobNumber, xml_report=testsuite)
170
171tree = ET.ElementTree(root)
172tree.write('report.xml', encoding='UTF-8')
173
174