1#!/usr/bin/env python2.7 2# Copyright 2015 gRPC authors. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16 17"""Generates the appropriate build.json data for all the end2end tests.""" 18 19 20import yaml 21import collections 22import hashlib 23 24 25FixtureOptions = collections.namedtuple( 26 'FixtureOptions', 27 'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth supports_write_buffering client_channel') 28default_unsecure_fixture_options = FixtureOptions( 29 True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], 30 True, False, [], [], True, False, True, False, True, False, True, True) 31socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace( 32 fullstack=False, dns_resolver=False, client_channel=False) 33default_secure_fixture_options = default_unsecure_fixture_options._replace( 34 secure=True) 35uds_fixture_options = default_unsecure_fixture_options._replace( 36 dns_resolver=False, platforms=['linux', 'mac', 'posix'], 37 exclude_iomgrs=['uv']) 38local_fixture_options = default_secure_fixture_options._replace( 39 dns_resolver=False, platforms=['linux', 'mac', 'posix'], 40 exclude_iomgrs=['uv']) 41fd_unsecure_fixture_options = default_unsecure_fixture_options._replace( 42 dns_resolver=False, fullstack=False, platforms=['linux', 'mac', 'posix'], 43 exclude_iomgrs=['uv'], client_channel=False) 44inproc_fixture_options = default_unsecure_fixture_options._replace( 45 dns_resolver=False, fullstack=False, name_resolution=False, 46 supports_compression=False, is_inproc=True, is_http2=False, 47 supports_write_buffering=False, client_channel=False) 48 49# maps fixture name to whether it requires the security library 50END2END_FIXTURES = { 51 'h2_compress': default_unsecure_fixture_options._replace(enables_compression=True), 52 'h2_census': default_unsecure_fixture_options, 53 # This cmake target is disabled for now because it depends on OpenCensus, 54 # which is Bazel-only. 55 # 'h2_load_reporting': default_unsecure_fixture_options, 56 'h2_fakesec': default_secure_fixture_options._replace(ci_mac=False), 57 'h2_fd': fd_unsecure_fixture_options, 58 'h2_full': default_unsecure_fixture_options, 59 'h2_full+pipe': default_unsecure_fixture_options._replace( 60 platforms=['linux'], exclude_iomgrs=['uv']), 61 'h2_full+trace': default_unsecure_fixture_options._replace(tracing=True), 62 'h2_full+workarounds': default_unsecure_fixture_options, 63 'h2_http_proxy': default_unsecure_fixture_options._replace( 64 ci_mac=False, exclude_iomgrs=['uv'], supports_proxy_auth=True), 65 'h2_oauth2': default_secure_fixture_options._replace( 66 ci_mac=False, exclude_iomgrs=['uv']), 67 'h2_proxy': default_unsecure_fixture_options._replace( 68 includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']), 69 'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace( 70 ci_mac=False, exclude_configs=['msan'], large_writes=False, 71 exclude_iomgrs=['uv']), 72 'h2_sockpair': socketpair_unsecure_fixture_options._replace( 73 ci_mac=False, exclude_iomgrs=['uv']), 74 'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace( 75 ci_mac=False, tracing=True, large_writes=False, exclude_iomgrs=['uv']), 76 'h2_ssl': default_secure_fixture_options, 77 'h2_local': local_fixture_options, 78 'h2_ssl_proxy': default_secure_fixture_options._replace( 79 includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']), 80 'h2_uds': uds_fixture_options, 81 'inproc': inproc_fixture_options 82} 83 84TestOptions = collections.namedtuple( 85 'TestOptions', 86 'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth needs_write_buffering needs_client_channel') 87default_test_options = TestOptions( 88 False, False, False, True, False, True, 1.0, [], False, False, True, 89 False, False, False, False, False, False) 90connectivity_test_options = default_test_options._replace( 91 needs_fullstack=True) 92 93LOWCPU = 0.1 94 95# maps test names to options 96END2END_TESTS = { 97 'authority_not_supported': default_test_options, 98 'bad_hostname': default_test_options._replace(needs_names=True), 99 'bad_ping': connectivity_test_options._replace(proxyable=False), 100 'binary_metadata': default_test_options._replace(cpu_cost=LOWCPU), 101 'resource_quota_server': default_test_options._replace( 102 large_writes=True, proxyable=False, allows_compression=False), 103 'call_creds': default_test_options._replace(secure=True), 104 'cancel_after_accept': default_test_options._replace(cpu_cost=LOWCPU), 105 'cancel_after_client_done': default_test_options._replace(cpu_cost=LOWCPU), 106 'cancel_after_invoke': default_test_options._replace(cpu_cost=LOWCPU), 107 'cancel_after_round_trip': default_test_options._replace(cpu_cost=LOWCPU), 108 'cancel_before_invoke': default_test_options._replace(cpu_cost=LOWCPU), 109 'cancel_in_a_vacuum': default_test_options._replace(cpu_cost=LOWCPU), 110 'cancel_with_status': default_test_options._replace(cpu_cost=LOWCPU), 111 'compressed_payload': default_test_options._replace(proxyable=False, 112 needs_compression=True), 113 'connectivity': connectivity_test_options._replace(needs_names=True, 114 proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']), 115 'channelz': default_test_options, 116 'default_host': default_test_options._replace( 117 needs_fullstack=True, needs_dns=True, needs_names=True), 118 'call_host_override': default_test_options._replace( 119 needs_fullstack=True, needs_dns=True, needs_names=True), 120 'disappearing_server': connectivity_test_options._replace(flaky=True, 121 needs_names=True), 122 'empty_batch': default_test_options._replace(cpu_cost=LOWCPU), 123 'filter_causes_close': default_test_options._replace(cpu_cost=LOWCPU), 124 'filter_call_init_fails': default_test_options, 125 'filter_latency': default_test_options._replace(cpu_cost=LOWCPU), 126 'filter_status_code': default_test_options._replace(cpu_cost=LOWCPU), 127 'graceful_server_shutdown': default_test_options._replace( 128 cpu_cost=LOWCPU, exclude_inproc=True), 129 'hpack_size': default_test_options._replace(proxyable=False, 130 traceable=False, 131 cpu_cost=LOWCPU), 132 'high_initial_seqno': default_test_options._replace(cpu_cost=LOWCPU), 133 'idempotent_request': default_test_options, 134 'invoke_large_request': default_test_options, 135 'keepalive_timeout': default_test_options._replace(proxyable=False, 136 cpu_cost=LOWCPU, 137 needs_http2=True), 138 'large_metadata': default_test_options, 139 'max_concurrent_streams': default_test_options._replace( 140 proxyable=False, cpu_cost=LOWCPU, exclude_inproc=True), 141 'max_connection_age': default_test_options._replace(cpu_cost=LOWCPU, 142 exclude_inproc=True), 143 'max_connection_idle': connectivity_test_options._replace( 144 proxyable=False, exclude_iomgrs=['uv'], cpu_cost=LOWCPU), 145 'max_message_length': default_test_options._replace(cpu_cost=LOWCPU), 146 'negative_deadline': default_test_options, 147 'network_status_change': default_test_options._replace(cpu_cost=LOWCPU), 148 'no_error_on_hotpath': default_test_options._replace(proxyable=False), 149 'no_logging': default_test_options._replace(traceable=False), 150 'no_op': default_test_options, 151 'payload': default_test_options, 152 # This cmake target is disabled for now because it depends on OpenCensus, 153 # which is Bazel-only. 154 # 'load_reporting_hook': default_test_options, 155 'ping_pong_streaming': default_test_options._replace(cpu_cost=LOWCPU), 156 'ping': connectivity_test_options._replace(proxyable=False, 157 cpu_cost=LOWCPU), 158 'proxy_auth': default_test_options._replace(needs_proxy_auth=True), 159 'registered_call': default_test_options, 160 'request_with_flags': default_test_options._replace( 161 proxyable=False, cpu_cost=LOWCPU), 162 'request_with_payload': default_test_options._replace(cpu_cost=LOWCPU), 163 # TODO(roth): Remove proxyable=False for all retry tests once we 164 # have a way for the proxy to propagate the fact that trailing 165 # metadata is available when initial metadata is returned. 166 # See https://github.com/grpc/grpc/issues/14467 for context. 167 'retry': default_test_options._replace(cpu_cost=LOWCPU, 168 needs_client_channel=True, 169 proxyable=False), 170 'retry_cancellation': default_test_options._replace( 171 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 172 'retry_disabled': default_test_options._replace(cpu_cost=LOWCPU, 173 needs_client_channel=True, 174 proxyable=False), 175 'retry_exceeds_buffer_size_in_initial_batch': default_test_options._replace( 176 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 177 'retry_exceeds_buffer_size_in_subsequent_batch': 178 default_test_options._replace(cpu_cost=LOWCPU, 179 needs_client_channel=True, 180 proxyable=False), 181 'retry_non_retriable_status': default_test_options._replace( 182 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 183 'retry_non_retriable_status_before_recv_trailing_metadata_started': 184 default_test_options._replace( 185 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 186 'retry_recv_initial_metadata': default_test_options._replace( 187 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 188 'retry_recv_message': default_test_options._replace( 189 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 190 'retry_server_pushback_delay': default_test_options._replace( 191 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 192 'retry_server_pushback_disabled': default_test_options._replace( 193 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 194 'retry_streaming': default_test_options._replace(cpu_cost=LOWCPU, 195 needs_client_channel=True, 196 proxyable=False), 197 'retry_streaming_after_commit': default_test_options._replace( 198 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 199 'retry_streaming_succeeds_before_replay_finished': 200 default_test_options._replace(cpu_cost=LOWCPU, 201 needs_client_channel=True, 202 proxyable=False), 203 'retry_throttled': default_test_options._replace(cpu_cost=LOWCPU, 204 needs_client_channel=True, 205 proxyable=False), 206 'retry_too_many_attempts': default_test_options._replace( 207 cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False), 208 'server_finishes_request': default_test_options._replace(cpu_cost=LOWCPU), 209 'shutdown_finishes_calls': default_test_options._replace(cpu_cost=LOWCPU), 210 'shutdown_finishes_tags': default_test_options._replace(cpu_cost=LOWCPU), 211 'simple_cacheable_request': default_test_options._replace(cpu_cost=LOWCPU), 212 'stream_compression_compressed_payload': default_test_options._replace( 213 proxyable=False, exclude_inproc=True), 214 'stream_compression_payload': default_test_options._replace( 215 exclude_inproc=True), 216 'stream_compression_ping_pong_streaming': default_test_options._replace( 217 exclude_inproc=True), 218 'simple_delayed_request': connectivity_test_options, 219 'simple_metadata': default_test_options, 220 'simple_request': default_test_options, 221 'streaming_error_response': default_test_options._replace(cpu_cost=LOWCPU), 222 'trailing_metadata': default_test_options, 223 'workaround_cronet_compression': default_test_options, 224 'write_buffering': default_test_options._replace( 225 cpu_cost=LOWCPU, needs_write_buffering=True), 226 'write_buffering_at_end': default_test_options._replace( 227 cpu_cost=LOWCPU, needs_write_buffering=True), 228} 229 230 231def compatible(f, t): 232 if END2END_TESTS[t].needs_fullstack: 233 if not END2END_FIXTURES[f].fullstack: 234 return False 235 if END2END_TESTS[t].needs_dns: 236 if not END2END_FIXTURES[f].dns_resolver: 237 return False 238 if END2END_TESTS[t].needs_names: 239 if not END2END_FIXTURES[f].name_resolution: 240 return False 241 if not END2END_TESTS[t].proxyable: 242 if END2END_FIXTURES[f].includes_proxy: 243 return False 244 if not END2END_TESTS[t].traceable: 245 if END2END_FIXTURES[f].tracing: 246 return False 247 if END2END_TESTS[t].large_writes: 248 if not END2END_FIXTURES[f].large_writes: 249 return False 250 if not END2END_TESTS[t].allows_compression: 251 if END2END_FIXTURES[f].enables_compression: 252 return False 253 if END2END_TESTS[t].needs_compression: 254 if not END2END_FIXTURES[f].supports_compression: 255 return False 256 if END2END_TESTS[t].exclude_inproc: 257 if END2END_FIXTURES[f].is_inproc: 258 return False 259 if END2END_TESTS[t].needs_http2: 260 if not END2END_FIXTURES[f].is_http2: 261 return False 262 if END2END_TESTS[t].needs_proxy_auth: 263 if not END2END_FIXTURES[f].supports_proxy_auth: 264 return False 265 if END2END_TESTS[t].needs_write_buffering: 266 if not END2END_FIXTURES[f].supports_write_buffering: 267 return False 268 if END2END_TESTS[t].needs_client_channel: 269 if not END2END_FIXTURES[f].client_channel: 270 return False 271 return True 272 273 274def without(l, e): 275 l = l[:] 276 l.remove(e) 277 return l 278 279 280def main(): 281 sec_deps = [ 282 'grpc_test_util', 283 'grpc', 284 'gpr_test_util', 285 'gpr' 286 ] 287 unsec_deps = [ 288 'grpc_test_util_unsecure', 289 'grpc_unsecure', 290 'gpr_test_util', 291 'gpr' 292 ] 293 json = { 294 '#': 'generated with test/end2end/gen_build_json.py', 295 'libs': [ 296 { 297 'name': 'end2end_tests', 298 'build': 'private', 299 'language': 'c', 300 'secure': True, 301 'src': ['test/core/end2end/end2end_tests.cc', 302 'test/core/end2end/end2end_test_utils.cc'] + [ 303 'test/core/end2end/tests/%s.cc' % t 304 for t in sorted(END2END_TESTS.keys())], 305 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', 306 'test/core/end2end/end2end_tests.h'], 307 'deps': sec_deps, 308 'vs_proj_dir': 'test/end2end/tests', 309 } 310 ] + [ 311 { 312 'name': 'end2end_nosec_tests', 313 'build': 'private', 314 'language': 'c', 315 'secure': False, 316 'src': ['test/core/end2end/end2end_nosec_tests.cc', 317 'test/core/end2end/end2end_test_utils.cc'] + [ 318 'test/core/end2end/tests/%s.cc' % t 319 for t in sorted(END2END_TESTS.keys()) 320 if not END2END_TESTS[t].secure], 321 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', 322 'test/core/end2end/end2end_tests.h'], 323 'deps': unsec_deps, 324 'vs_proj_dir': 'test/end2end/tests', 325 } 326 ], 327 'targets': [ 328 { 329 'name': '%s_test' % f, 330 'build': 'test', 331 'language': 'c', 332 'run': False, 333 'src': ['test/core/end2end/fixtures/%s.cc' % f], 334 'platforms': END2END_FIXTURES[f].platforms, 335 'ci_platforms': (END2END_FIXTURES[f].platforms 336 if END2END_FIXTURES[f].ci_mac else without( 337 END2END_FIXTURES[f].platforms, 'mac')), 338 'deps': [ 339 'end2end_tests' 340 ] + sec_deps, 341 'vs_proj_dir': 'test/end2end/fixtures', 342 } 343 for f in sorted(END2END_FIXTURES.keys()) 344 ] + [ 345 { 346 'name': '%s_nosec_test' % f, 347 'build': 'test', 348 'language': 'c', 349 'secure': False, 350 'src': ['test/core/end2end/fixtures/%s.cc' % f], 351 'run': False, 352 'platforms': END2END_FIXTURES[f].platforms, 353 'ci_platforms': (END2END_FIXTURES[f].platforms 354 if END2END_FIXTURES[f].ci_mac else without( 355 END2END_FIXTURES[f].platforms, 'mac')), 356 'deps': [ 357 'end2end_nosec_tests' 358 ] + unsec_deps, 359 'vs_proj_dir': 'test/end2end/fixtures', 360 } 361 for f in sorted(END2END_FIXTURES.keys()) 362 if not END2END_FIXTURES[f].secure 363 ], 364 'tests': [ 365 { 366 'name': '%s_test' % f, 367 'args': [t], 368 'exclude_configs': END2END_FIXTURES[f].exclude_configs, 369 'exclude_iomgrs': list(set(END2END_FIXTURES[f].exclude_iomgrs) | 370 set(END2END_TESTS[t].exclude_iomgrs)), 371 'platforms': END2END_FIXTURES[f].platforms, 372 'ci_platforms': (END2END_FIXTURES[f].platforms 373 if END2END_FIXTURES[f].ci_mac else without( 374 END2END_FIXTURES[f].platforms, 'mac')), 375 'flaky': END2END_TESTS[t].flaky, 376 'language': 'c', 377 'cpu_cost': END2END_TESTS[t].cpu_cost, 378 } 379 for f in sorted(END2END_FIXTURES.keys()) 380 for t in sorted(END2END_TESTS.keys()) if compatible(f, t) 381 ] + [ 382 { 383 'name': '%s_nosec_test' % f, 384 'args': [t], 385 'exclude_configs': END2END_FIXTURES[f].exclude_configs, 386 'exclude_iomgrs': list(set(END2END_FIXTURES[f].exclude_iomgrs) | 387 set(END2END_TESTS[t].exclude_iomgrs)), 388 'platforms': END2END_FIXTURES[f].platforms, 389 'ci_platforms': (END2END_FIXTURES[f].platforms 390 if END2END_FIXTURES[f].ci_mac else without( 391 END2END_FIXTURES[f].platforms, 'mac')), 392 'flaky': END2END_TESTS[t].flaky, 393 'language': 'c', 394 'cpu_cost': END2END_TESTS[t].cpu_cost, 395 } 396 for f in sorted(END2END_FIXTURES.keys()) 397 if not END2END_FIXTURES[f].secure 398 for t in sorted(END2END_TESTS.keys()) 399 if compatible(f, t) and not END2END_TESTS[t].secure 400 ], 401 'core_end2end_tests': dict( 402 (t, END2END_TESTS[t].secure) 403 for t in END2END_TESTS.keys() 404 ) 405 } 406 print yaml.dump(json) 407 408 409if __name__ == '__main__': 410 main() 411