From 07639b972538dda9bebfad2e0da95d99da42b91f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 28 Nov 2016 14:26:11 -0800 Subject: [PATCH 01/22] Drop support for Node 0.12 and io.js 1.0 --- tools/run_tests/build_artifact_node.bat | 2 +- tools/run_tests/build_artifact_node.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/build_artifact_node.bat b/tools/run_tests/build_artifact_node.bat index 57d55ef19ec..833cb8171d9 100644 --- a/tools/run_tests/build_artifact_node.bat +++ b/tools/run_tests/build_artifact_node.bat @@ -27,7 +27,7 @@ @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 +set node_versions=1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm diff --git a/tools/run_tests/build_artifact_node.sh b/tools/run_tests/build_artifact_node.sh index 9d06472aa49..6a9caa9ca9b 100755 --- a/tools/run_tests/build_artifact_node.sh +++ b/tools/run_tests/build_artifact_node.sh @@ -42,7 +42,7 @@ mkdir -p artifacts npm update -node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) +node_versions=( 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) for version in ${node_versions[@]} do From d6c93802fff2dc3db004828a6ea4ff5b25383ee4 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 29 Nov 2016 09:17:57 -0800 Subject: [PATCH 02/22] Update package.json with version compatibility changes --- package.json | 2 +- templates/package.json.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5506e9bbdf8..6fd799cbab0 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "poisson-process": "^0.2.1" }, "engines": { - "node": ">=0.12.0" + "node": ">=1.1.0" }, "binary": { "module_name": "grpc_node", diff --git a/templates/package.json.template b/templates/package.json.template index 81f39d27f51..eb85c06590e 100644 --- a/templates/package.json.template +++ b/templates/package.json.template @@ -52,7 +52,7 @@ "poisson-process": "^0.2.1" }, "engines": { - "node": ">=0.12.0" + "node": ">=1.1.0" }, "binary": { "module_name": "grpc_node", From d803b805aef97a03bd5873c1a8c3e534bd22feb7 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 16 Dec 2016 13:59:04 -0800 Subject: [PATCH 03/22] Fix RST_STREAM(0) inconsistency --- src/core/ext/transport/chttp2/transport/frame_rst_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c index b4c5ed769b9..20043f5fbf4 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c @@ -109,7 +109,7 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx, (((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[3])); grpc_error *error = GRPC_ERROR_NONE; - if (reason != GRPC_CHTTP2_NO_ERROR) { + if (reason != GRPC_CHTTP2_NO_ERROR || s->header_frames_received < 2) { error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"), GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status( From 8d770144c259abbd7a307e96f9aec5e9bda1c4ea Mon Sep 17 00:00:00 2001 From: thinkerou Date: Tue, 10 Jan 2017 13:26:42 +0800 Subject: [PATCH 04/22] attempt to fix mem leaks --- src/php/ext/grpc/call.c | 2 ++ src/php/ext/grpc/call_credentials.c | 10 +++--- src/php/ext/grpc/channel_credentials.c | 12 ++------ src/php/ext/grpc/php7_wrapper.h | 12 ++++++++ src/php/ext/grpc/php_grpc.h | 4 --- src/php/ext/grpc/server_credentials.c | 4 +-- src/php/ext/grpc/timeval.c | 42 +++++++++----------------- 7 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index 3a49ea87081..64b1137c2a4 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -478,6 +478,7 @@ PHP_METHOD(Call, startBatch) { true); add_property_zval(result, "status", recv_status); PHP_GRPC_DELREF(recv_status); + PHP_GRPC_FREE_STD_ZVAL(recv_status); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: add_property_bool(result, "cancelled", cancelled); @@ -501,6 +502,7 @@ cleanup: } if (ops[i].op == GRPC_OP_RECV_MESSAGE) { grpc_byte_buffer_destroy(message); + PHP_GRPC_FREE_STD_ZVAL(message_str); } } RETURN_DESTROY_ZVAL(result); diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c index 3aafc3a19b6..043817facd1 100644 --- a/src/php/ext/grpc/call_credentials.c +++ b/src/php/ext/grpc/call_credentials.c @@ -111,9 +111,7 @@ PHP_METHOD(CallCredentials, createComposite) { grpc_call_credentials *creds = grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -155,9 +153,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) { grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -211,6 +207,8 @@ void plugin_destroy_state(void *ptr) { plugin_state *state = (plugin_state *)ptr; efree(state->fci); efree(state->fci_cache); + PHP_GRPC_FREE_STD_ZVAL(state->fci->params); + PHP_GRPC_FREE_STD_ZVAL(state->fci->retval); efree(state); } diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index a32c4a4ea24..36a8223b880 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -121,9 +121,7 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -160,9 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) { grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -191,9 +187,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h index 1d7824113fa..72e982d6fc9 100644 --- a/src/php/ext/grpc/php7_wrapper.h +++ b/src/php/ext/grpc/php7_wrapper.h @@ -50,8 +50,13 @@ #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv) +#define PHP_GRPC_FREE_STD_ZVAL(pzv) #define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv) +#define RETURN_DESTROY_ZVAL(val) \ + RETURN_ZVAL(val, false /* Don't execute copy constructor */, \ + true /* Dealloc original before returning */) + #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { \ zend_object std; @@ -144,8 +149,15 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) \ pzv = (zval *)emalloc(sizeof(zval)); +#define PHP_GRPC_FREE_STD_ZVAL(pzv) efree(pzv); #define PHP_GRPC_DELREF(zv) +#define RETURN_DESTROY_ZVAL(val) \ + RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \ + true /* Dealloc original before returning */); \ + efree(val); \ + return + #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { #define PHP_GRPC_WRAP_OBJECT_END(name) \ diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index e57a06545e6..13083b0bc71 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -61,10 +61,6 @@ extern zend_module_entry grpc_module_entry; #include "grpc/grpc.h" -#define RETURN_DESTROY_ZVAL(val) \ - RETURN_ZVAL(val, false /* Don't execute copy constructor */, \ - true /* Dealloc original before returning */) - /* These are all function declarations */ /* Code that runs at module initialization */ PHP_MINIT_FUNCTION(grpc); diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 1610c8ebb09..3e39fee246c 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -113,9 +113,7 @@ PHP_METHOD(ServerCredentials, createSsl) { grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 945231b47fe..7ada915aadd 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -115,11 +115,9 @@ PHP_METHOD(Timeval, add) { } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - zval *sum; - PHP_GRPC_MAKE_STD_ZVAL(sum); - sum = - grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) - TSRMLS_CC); + zval *sum = + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); } @@ -141,11 +139,9 @@ PHP_METHOD(Timeval, subtract) { } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - zval *diff; - PHP_GRPC_MAKE_STD_ZVAL(diff); - diff = - grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) - TSRMLS_CC); + zval *diff = + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); } @@ -206,9 +202,7 @@ PHP_METHOD(Timeval, similar) { * @return Timeval The current time */ PHP_METHOD(Timeval, now) { - zval *now; - PHP_GRPC_MAKE_STD_ZVAL(now); - now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); } @@ -217,13 +211,9 @@ PHP_METHOD(Timeval, now) { * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { - zval *grpc_php_timeval_zero; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_zero); - grpc_php_timeval_zero = - grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); - RETURN_ZVAL(grpc_php_timeval_zero, - false, /* Copy original before returning? */ - true /* Destroy original before returning */); + zval *grpc_php_timeval_zero = + grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); + RETURN_DESTROY_ZVAL(grpc_php_timeval_zero); } /** @@ -231,10 +221,8 @@ PHP_METHOD(Timeval, zero) { * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { - zval *grpc_php_timeval_inf_future; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_future); - grpc_php_timeval_inf_future = - grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *grpc_php_timeval_inf_future = + grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); } @@ -243,10 +231,8 @@ PHP_METHOD(Timeval, infFuture) { * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { - zval *grpc_php_timeval_inf_past; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_past); - grpc_php_timeval_inf_past = - grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *grpc_php_timeval_inf_past = + grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); } From d383e4aa886d6a8191b4f7be987eba57c82ec2b4 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 10 Jan 2017 13:58:07 -0800 Subject: [PATCH 05/22] added ability to run bad-server http2 tests --- tools/run_tests/run_interop_tests.py | 94 ++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 981e38b813d..02694c89228 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -169,6 +169,9 @@ class JavaLanguage: def client_cmd(self, args): return ['./run-test-client.sh'] + args + def client_cmd_http2interop(self, args): + return ['./run-http2-client.sh'] + args + def cloud_to_prod_env(self): return {} @@ -179,10 +182,10 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + return _SKIP_ADVANCED + _SKIP_COMPRESSION def unimplemented_test_cases_server(self): - return _SKIP_COMPRESSION + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'java' @@ -226,11 +229,15 @@ class Http2Client: """ def __init__(self): self.client_cwd = None + self.server_cwd = None self.safename = str(self) def client_cmd(self, args): return ['tools/http2_interop/http2_interop.test', '-test.v'] + args + def server_cmd(self, args): + return ['python test/http2_test/http2_test_server.py'] + def cloud_to_prod_env(self): return {} @@ -375,6 +382,11 @@ class PythonLanguage: '--args="{}"'.format(' '.join(args)) ] + def client_cmd_http2interop(self, args): + return [ 'py27/bin/python', + 'src/python/grpcio_tests/tests/http2/_negative_http2_client.py', + ] + args + def cloud_to_prod_env(self): return {} @@ -429,7 +441,10 @@ _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong', _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds', 'oauth2_auth_token', 'per_rpc_creds'] -_HTTP2_TEST_CASES = ["tls", "framing"] +_HTTP2_TEST_CASES = ['tls', 'framing'] + +_HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data', + 'goaway', 'ping', 'max_streams'] DOCKER_WORKDIR_ROOT = '/var/local/git/grpc' @@ -550,13 +565,26 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name, def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, server_port, docker_image=None): """Creates jobspec for cloud-to-cloud interop test""" - cmdline = bash_cmdline(language.client_cmd([ + interop_only_options = [ '--server_host_override=foo.test.google.fr', '--use_tls=true', '--use_test_ca=true', + ] + common_options = [ '--test_case=%s' % test_case, '--server_host=%s' % server_host, - '--server_port=%s' % server_port])) + ] + if test_case in sorted(_HTTP2_BADSERVER_TEST_CASES): + # We are running the http2_badserver_interop test. Adjust command line accordingly. + offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case) + client_options = common_options + ['--server_port=%s' % + (int(server_port)+offset)] + cmdline = bash_cmdline(language.client_cmd_http2interop(client_options)) + else: + client_options = interop_only_options + common_options + ['--server_port=%s' % server_port] + cmdline = bash_cmdline(language.client_cmd(client_options)) + + print('Client_CMD = %s'%cmdline) cwd = language.client_cwd environ = language.global_env() if docker_image: @@ -590,13 +618,30 @@ def server_jobspec(language, docker_image): cmdline = bash_cmdline( language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT])) environ = language.global_env() + if language.safename == 'http2': + # we are running the http2 interop server. Open next N ports beginning + # with the server port. These ports are used for http2 interop test + # (one test case per port). We also attach the docker container running + # the server to local network, so we don't have to mess with port mapping + port_args = [ + '-p', str(_DEFAULT_SERVER_PORT+0), + '-p', str(_DEFAULT_SERVER_PORT+1), + '-p', str(_DEFAULT_SERVER_PORT+2), + '-p', str(_DEFAULT_SERVER_PORT+3), + '-p', str(_DEFAULT_SERVER_PORT+4), + '-p', str(_DEFAULT_SERVER_PORT+5), + '-p', str(_DEFAULT_SERVER_PORT+6), + '--net=host', + ] + else: + port_args = ['-p', str(_DEFAULT_SERVER_PORT)] + docker_cmdline = docker_run_cmdline(cmdline, image=docker_image, cwd=language.server_cwd, environ=environ, - docker_args=['-p', str(_DEFAULT_SERVER_PORT), - '--name', container_name]) - + docker_args=port_args + + ['--name', container_name]) server_job = jobset.JobSpec( cmdline=docker_cmdline, environ=environ, @@ -730,7 +775,12 @@ argp.add_argument('--http2_interop', default=False, action='store_const', const=True, - help='Enable HTTP/2 interop tests') + help='Enable HTTP/2 client edge case testing. (Bad client, good server)') +argp.add_argument('--http2_badserver_interop', + default=False, + action='store_const', + const=True, + help='Enable HTTP/2 server edge case testing. (Good client, bad server)') args = argp.parse_args() @@ -756,14 +806,15 @@ languages = set(_LANGUAGES[l] _LANGUAGES.iterkeys() if x == 'all' else [x] for x in args.language)) -http2Interop = Http2Client() if args.http2_interop else None +http2Interop = Http2Client() if (args.http2_badserver_interop + or args.http2_interop) else None docker_images={} if args.use_docker: # languages for which to build docker images languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] + [s for s in servers])) - if args.http2_interop: + if args.http2_interop or args.http2_badserver_interop: languages_to_build.add(http2Interop) build_jobs = [] @@ -797,6 +848,14 @@ try: server_jobs[lang] = job server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT)) + if args.http2_badserver_interop: + # launch a HTTP2 server emulator that creates edge cases + lang = str(http2Interop) + spec = server_jobspec(Http2Client(), docker_images.get(lang)) + job = dockerjob.DockerJob(spec) + server_jobs[lang] = job + server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) + jobs = [] if args.cloud_to_prod: for server_host_name in args.prod_servers: @@ -843,7 +902,7 @@ try: for language in languages: for test_case in _TEST_CASES: if not test_case in language.unimplemented_test_cases(): - if not test_case in skip_server: + if not test_case in skip_server and not args.http2_badserver_interop: test_job = cloud_to_cloud_jobspec(language, test_case, server_name, @@ -865,6 +924,17 @@ try: docker_image=docker_images.get(str(http2Interop))) jobs.append(test_job) + if args.http2_badserver_interop: + for language in languages: + for test_case in _HTTP2_BADSERVER_TEST_CASES: + test_job = cloud_to_cloud_jobspec(language, + test_case, + server_name, + server_host, + server_port, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) + if not jobs: print('No jobs to run.') for image in docker_images.itervalues(): From a0d639dae9b53f3adb2c722789948bbf32dacd8a Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 14:46:10 -0800 Subject: [PATCH 06/22] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 5ea3a96dff1..65ee2cd32d6 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -61,14 +61,14 @@ Client Procedure: ``` Client asserts: -* Call was successful. +* Both calls are successful. * Response payload body is 314159 bytes in size. Server Procedure: 1. Server sends a GOAWAY after receiving the first UnaryCall. Server asserts: -* The second UnaryCall has a different stream_id than the first one. +* Two different were used from the client. ### rst_after_header From 9fafc034659e0f218fcafd61a0b3e53d8b28991f Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 14:47:02 -0800 Subject: [PATCH 07/22] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 65ee2cd32d6..e4717888914 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -68,7 +68,7 @@ Server Procedure: 1. Server sends a GOAWAY after receiving the first UnaryCall. Server asserts: -* Two different were used from the client. +* Two different connections were used from the client. ### rst_after_header From 850ed9b5d0c8766a29cd795e48f5eed1337bf892 Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 15:00:53 -0800 Subject: [PATCH 08/22] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index e4717888914..1ded97b5037 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -49,7 +49,7 @@ server. The client should handle the goaway by switching to a new stream without the user application having to do a thing. Client Procedure: - 1. Client sends two UnaryCall requests with: + 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between). ``` { From 078e4210fdd3410581c38f449a527fd947dfcecc Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 10 Jan 2017 15:09:21 -0800 Subject: [PATCH 09/22] addressed feedback created separate class for Http2Server. --- tools/run_tests/run_interop_tests.py | 74 +++++++++++++++++++--------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 02694c89228..d25da0b2fa9 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -182,10 +182,10 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_ADVANCED + _SKIP_COMPRESSION + return _SKIP_COMPRESSION def unimplemented_test_cases_server(self): - return _SKIP_ADVANCED + _SKIP_COMPRESSION + return _SKIP_COMPRESSION def __str__(self): return 'java' @@ -220,6 +220,33 @@ class GoLanguage: def __str__(self): return 'go' +class Http2Server: + """Represents the HTTP/2 Interop Test server + + This pretends to be a language in order to be built and run, but really it + isn't. + """ + def __init__(self): + self.server_cwd = None + self.safename = str(self) + + def server_cmd(self, args): + return ['python test/http2_test/http2_test_server.py'] + + def cloud_to_prod_env(self): + return {} + + def global_env(self): + return {} + + def unimplemented_test_cases(self): + return _TEST_CASES + + def unimplemented_test_cases_server(self): + return _TEST_CASES + + def __str__(self): + return 'http2' class Http2Client: """Represents the HTTP/2 Interop Test @@ -229,15 +256,11 @@ class Http2Client: """ def __init__(self): self.client_cwd = None - self.server_cwd = None self.safename = str(self) def client_cmd(self, args): return ['tools/http2_interop/http2_interop.test', '-test.v'] + args - def server_cmd(self, args): - return ['python test/http2_test/http2_test_server.py'] - def cloud_to_prod_env(self): return {} @@ -574,7 +597,7 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, '--test_case=%s' % test_case, '--server_host=%s' % server_host, ] - if test_case in sorted(_HTTP2_BADSERVER_TEST_CASES): + if test_case in _HTTP2_BADSERVER_TEST_CASES: # We are running the http2_badserver_interop test. Adjust command line accordingly. offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case) client_options = common_options + ['--server_port=%s' % @@ -584,7 +607,6 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, client_options = interop_only_options + common_options + ['--server_port=%s' % server_port] cmdline = bash_cmdline(language.client_cmd(client_options)) - print('Client_CMD = %s'%cmdline) cwd = language.client_cwd environ = language.global_env() if docker_image: @@ -806,17 +828,20 @@ languages = set(_LANGUAGES[l] _LANGUAGES.iterkeys() if x == 'all' else [x] for x in args.language)) -http2Interop = Http2Client() if (args.http2_badserver_interop - or args.http2_interop) else None +http2Interop = Http2Client() if args.http2_interop else None +http2InteropServer = Http2Server() if args.http2_badserver_interop else None docker_images={} if args.use_docker: # languages for which to build docker images languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] + [s for s in servers])) - if args.http2_interop or args.http2_badserver_interop: + if args.http2_interop: languages_to_build.add(http2Interop) + if args.http2_badserver_interop: + languages_to_build.add(http2InteropServer) + build_jobs = [] for l in languages_to_build: job = build_interop_image_jobspec(l) @@ -850,8 +875,8 @@ try: if args.http2_badserver_interop: # launch a HTTP2 server emulator that creates edge cases - lang = str(http2Interop) - spec = server_jobspec(Http2Client(), docker_images.get(lang)) + lang = str(http2InteropServer) + spec = server_jobspec(Http2Server(), docker_images.get(lang)) job = dockerjob.DockerJob(spec) server_jobs[lang] = job server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) @@ -899,17 +924,18 @@ try: skip_server = [] # test cases unimplemented by server if server_language: skip_server = server_language.unimplemented_test_cases_server() - for language in languages: - for test_case in _TEST_CASES: - if not test_case in language.unimplemented_test_cases(): - if not test_case in skip_server and not args.http2_badserver_interop: - test_job = cloud_to_cloud_jobspec(language, - test_case, - server_name, - server_host, - server_port, - docker_image=docker_images.get(str(language))) - jobs.append(test_job) + if not args.http2_badserver_interop: + for language in languages: + for test_case in _TEST_CASES: + if not test_case in language.unimplemented_test_cases(): + if not test_case in skip_server: + test_job = cloud_to_cloud_jobspec(language, + test_case, + server_name, + server_host, + server_port, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) if args.http2_interop: for test_case in _HTTP2_TEST_CASES: From 98c0bd7c829c4932ac12ebbe6687f0fc5380e866 Mon Sep 17 00:00:00 2001 From: Yuxuan Li Date: Tue, 15 Nov 2016 13:31:36 -0800 Subject: [PATCH 10/22] add setting channel args functionality to performance tesing setting channel args --draft clang-format --- src/proto/grpc/testing/control.proto | 10 ++++++++++ test/cpp/qps/client.h | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto index be387cf7869..529313cfb1e 100644 --- a/src/proto/grpc/testing/control.proto +++ b/src/proto/grpc/testing/control.proto @@ -78,6 +78,14 @@ message SecurityParams { string server_host_override = 2; } +message ChannelArg { + string name = 1; + oneof value { + string str_value = 2; + int32 int_value = 3; + } +} + message ClientConfig { // List of targets to connect to. At least one target needs to be specified. repeated string server_targets = 1; @@ -103,6 +111,8 @@ message ClientConfig { // If we use an OTHER_CLIENT client_type, this string gives more detail string other_client_api = 15; + + repeated ChannelArg channel_args = 16; } message ClientStatus { ClientStats stats = 1; } diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index fdd78ebb899..18f9778fc6f 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -409,6 +409,7 @@ class ClientImpl : public Client { // old compilers happy with using this in std::vector ChannelArguments args; args.SetInt("shard_to_ensure_no_subchannel_merges", shard); + set_channel_args(config, &args); channel_ = CreateTestChannel( target, config.security_params().server_host_override(), config.has_security_params(), !config.security_params().use_test_ca(), @@ -423,6 +424,18 @@ class ClientImpl : public Client { StubType* get_stub() { return stub_.get(); } private: + void set_channel_args(const ClientConfig& config, ChannelArguments* args) { + for (auto channel_arg : config.channel_args()) { + if (channel_arg.value_case() == ChannelArg::kStrValue) { + args->SetString(channel_arg.name(), channel_arg.str_value()); + } else if (channel_arg.value_case() == ChannelArg::kIntValue) { + args->SetInt(channel_arg.name(), channel_arg.int_value()); + } else { + gpr_log(GPR_ERROR, "Empty channel arg value."); + } + } + } + std::shared_ptr channel_; std::unique_ptr stub_; }; From ac87a46225128f2c92e9d2cb8522b4b88d5abde8 Mon Sep 17 00:00:00 2001 From: Yuxuan Li Date: Fri, 11 Nov 2016 12:05:11 -0800 Subject: [PATCH 11/22] enable uploading server cpu usage data from performance tests to big query --- test/cpp/qps/qps_json_driver.cc | 1 + .../run_tests/performance/bq_upload_result.py | 8 ++++--- .../performance/scenario_result_schema.json | 22 +++++++++++++++++++ tools/run_tests/run_performance_tests.py | 20 +++++++++++------ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index da835b995ab..57ee5ef63cd 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -212,6 +212,7 @@ static bool QpsDriver() { SearchOfferedLoad(FLAGS_initial_search_value, FLAGS_targeted_cpu_load, scenario, &success); gpr_log(GPR_INFO, "targeted_offered_load %f", targeted_offered_load); + GetCpuLoad(scenario, targeted_offered_load, &success); } else { gpr_log(GPR_ERROR, "Unimplemented search param"); } diff --git a/tools/run_tests/performance/bq_upload_result.py b/tools/run_tests/performance/bq_upload_result.py index ddcf053ae5e..89d2a9b320f 100755 --- a/tools/run_tests/performance/bq_upload_result.py +++ b/tools/run_tests/performance/bq_upload_result.py @@ -115,9 +115,11 @@ def _flatten_result_inplace(scenario_result): scenario_result['scenario']['clientConfig'] = json.dumps(scenario_result['scenario']['clientConfig']) scenario_result['scenario']['serverConfig'] = json.dumps(scenario_result['scenario']['serverConfig']) scenario_result['latencies'] = json.dumps(scenario_result['latencies']) + scenario_result['serverCpuStats'] = [] for stats in scenario_result['serverStats']: - stats.pop('totalCpuTime', None) - stats.pop('idleCpuTime', None) + scenario_result['serverCpuStats'].append(dict()) + scenario_result['serverCpuStats'][-1]['totalCpuTime'] = stats.pop('totalCpuTime', None) + scenario_result['serverCpuStats'][-1]['idleCpuTime'] = stats.pop('idleCpuTime', None) for stats in scenario_result['clientStats']: stats['latencies'] = json.dumps(stats['latencies']) stats.pop('requestResults', None) @@ -125,7 +127,7 @@ def _flatten_result_inplace(scenario_result): scenario_result['clientSuccess'] = json.dumps(scenario_result['clientSuccess']) scenario_result['serverSuccess'] = json.dumps(scenario_result['serverSuccess']) scenario_result['requestResults'] = json.dumps(scenario_result.get('requestResults', [])) - scenario_result['summary'].pop('serverCpuUsage', None) + scenario_result['serverCpuUsage'] = scenario_result['summary'].pop('serverCpuUsage', None) scenario_result['summary'].pop('successfulRequestsPerSecond', None) scenario_result['summary'].pop('failedRequestsPerSecond', None) diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json index 3285f212d77..8ec41c377c5 100644 --- a/tools/run_tests/performance/scenario_result_schema.json +++ b/tools/run_tests/performance/scenario_result_schema.json @@ -213,5 +213,27 @@ "name": "requestResults", "type": "STRING", "mode": "NULLABLE" + }, + { + "name": "serverCpuStats", + "type": "RECORD", + "mode": "REPEATED", + "fields": [ + { + "name": "totalCpuTime", + "type": "INTEGER", + "mode": "NULLABLE" + }, + { + "name": "idleCpuTime", + "type": "INTEGER", + "mode": "NULLABLE" + } + ] + }, + { + "name": "serverCpuUsage", + "type": "FLOAT", + "mode": "NULLABLE" } ] diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py index b7b742d7af2..d6eed3f5bdd 100755 --- a/tools/run_tests/run_performance_tests.py +++ b/tools/run_tests/run_performance_tests.py @@ -113,7 +113,7 @@ def create_qpsworker_job(language, shortname=None, port=10000, remote_host=None, def create_scenario_jobspec(scenario_json, workers, remote_host=None, - bq_result_table=None): + bq_result_table=None, server_cpu_load=0): """Runs one scenario using QPS driver.""" # setting QPS_WORKERS env variable here makes sure it works with SSH too. cmd = 'QPS_WORKERS="%s" ' % ','.join(workers) @@ -121,7 +121,9 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None, cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table cmd += 'tools/run_tests/performance/run_qps_driver.sh ' cmd += '--scenarios_json=%s ' % pipes.quote(json.dumps({'scenarios': [scenario_json]})) - cmd += '--scenario_result_file=scenario_result.json' + cmd += '--scenario_result_file=scenario_result.json ' + if server_cpu_load != 0: + cmd += '--search_param=offered_load --initial_search_value=1000 --targeted_cpu_load=%d --stride=500 --error_tolerance=0.01' % server_cpu_load if remote_host: user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host) cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (user_at_host, pipes.quote(cmd)) @@ -129,7 +131,7 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None, return jobset.JobSpec( cmdline=[cmd], shortname='qps_json_driver.%s' % scenario_json['name'], - timeout_seconds=3*60, + timeout_seconds=12*60, shell=True, verbose_success=True) @@ -318,7 +320,7 @@ Scenario = collections.namedtuple('Scenario', 'jobspec workers name') def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', category='all', bq_result_table=None, - netperf=False, netperf_hosts=[]): + netperf=False, netperf_hosts=[], server_cpu_load=0): """Create jobspecs for scenarios to run.""" all_workers = [worker for workers in workers_by_lang.values() @@ -379,7 +381,8 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', create_scenario_jobspec(scenario_json, [w.host_and_port for w in workers], remote_host=remote_host, - bq_result_table=bq_result_table), + bq_result_table=bq_result_table, + server_cpu_load=server_cpu_load), workers, scenario_json['name']) scenarios.append(scenario) @@ -461,6 +464,9 @@ argp.add_argument('--netperf', action='store_const', const=True, help='Run netperf benchmark as one of the scenarios.') +argp.add_argument('--server_cpu_load', + default=0, type=int, + help='Select a targeted server cpu load to run. 0 means ignore this flag') argp.add_argument('-x', '--xml_report', default='report.xml', type=str, help='Name of XML report file to generate.') argp.add_argument('--perf_args', @@ -490,7 +496,6 @@ argp.add_argument('--skip_generate_flamegraphs', 'May be useful if "perf_args" arguments do not make sense for ' 'generating flamegraphs (e.g., "--perf_args=stat ...")')) - args = argp.parse_args() languages = set(scenario_config.LANGUAGES[l] @@ -540,7 +545,8 @@ scenarios = create_scenarios(languages, category=args.category, bq_result_table=args.bq_result_table, netperf=args.netperf, - netperf_hosts=args.remote_worker_host) + netperf_hosts=args.remote_worker_host, + server_cpu_load=args.server_cpu_load) if not scenarios: raise Exception('No scenarios to run') From c344e87449cb23fa03977c6a8dbdedfba8730296 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Mon, 9 Jan 2017 10:53:50 -0800 Subject: [PATCH 12/22] Adds HTTP/2 interop test client --- Makefile | 92 +++++- build.yaml | 32 +++ test/cpp/interop/http2_client.cc | 272 ++++++++++++++++++ test/cpp/interop/http2_client.h | 80 ++++++ .../generated/sources_and_headers.json | 44 +++ .../http2_client_main.vcxproj | 206 +++++++++++++ .../http2_client_main.vcxproj.filters | 47 +++ 7 files changed, 771 insertions(+), 2 deletions(-) create mode 100644 test/cpp/interop/http2_client.cc create mode 100644 test/cpp/interop/http2_client.h create mode 100644 vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj create mode 100644 vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters diff --git a/Makefile b/Makefile index 024ca8f12af..fdeb389a80c 100644 --- a/Makefile +++ b/Makefile @@ -1095,6 +1095,7 @@ grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test +http2_client: $(BINDIR)/$(CONFIG)/http2_client hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test interop_client: $(BINDIR)/$(CONFIG)/interop_client interop_server: $(BINDIR)/$(CONFIG)/interop_server @@ -1270,9 +1271,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a else -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a endif @@ -1477,6 +1478,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ + $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ @@ -1570,6 +1572,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ + $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ @@ -4958,6 +4961,59 @@ ifneq ($(NO_DEPS),true) endif +LIBHTTP2_CLIENT_MAIN_SRC = \ + $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ + test/cpp/interop/http2_client.cc \ + +PUBLIC_HEADERS_CXX += \ + +LIBHTTP2_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBHTTP2_CLIENT_MAIN_SRC)))) + + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL. + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: openssl_dep_error + + +else + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: protobuf_dep_error + + +else + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBHTTP2_CLIENT_MAIN_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a + $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBHTTP2_CLIENT_MAIN_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a +endif + + + + +endif + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBHTTP2_CLIENT_MAIN_OBJS:.o=.dep) +endif +endif +$(OBJDIR)/$(CONFIG)/test/cpp/interop/http2_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc + + LIBINTEROP_CLIENT_HELPER_SRC = \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ test/cpp/interop/client_helper.cc \ @@ -12912,6 +12968,37 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/http2_client: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/http2_client: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/http2_client: $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/http2_client + +endif + +endif + + + + HYBRID_END2END_TEST_SRC = \ test/cpp/end2end/hybrid_end2end_test.cc \ @@ -16829,6 +16916,7 @@ test/core/util/test_tcp_server.c: $(OPENSSL_DEP) test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP) test/cpp/interop/client.cc: $(OPENSSL_DEP) test/cpp/interop/client_helper.cc: $(OPENSSL_DEP) +test/cpp/interop/http2_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server_bootstrap.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index 55aca52f680..1f90d26804f 100644 --- a/build.yaml +++ b/build.yaml @@ -1217,6 +1217,22 @@ libs: vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}' vs_props: - protoc +- name: http2_client_main + build: private + language: c++ + headers: + - test/cpp/interop/http2_client.h + src: + - src/proto/grpc/testing/empty.proto + - src/proto/grpc/testing/messages.proto + - src/proto/grpc/testing/test.proto + - test/cpp/interop/http2_client.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - grpc++_test_config - name: interop_client_helper build: private language: c++ @@ -3191,6 +3207,22 @@ targets: - grpc++ - grpc++_test_util - grpc_test_util +- name: http2_client + build: test + run: false + language: c++ + src: [] + deps: + - http2_client_main + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - grpc++_test_config + platforms: + - mac + - linux + - posix - name: hybrid_end2end_test gtest: true build: test diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc new file mode 100644 index 00000000000..38aee43b26a --- /dev/null +++ b/test/cpp/interop/http2_client.cc @@ -0,0 +1,272 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/transport/byte_stream.h" +#include "src/proto/grpc/testing/messages.grpc.pb.h" +#include "src/proto/grpc/testing/test.grpc.pb.h" +#include "test/cpp/interop/http2_client.h" + +#include "src/core/lib/support/string.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/util/test_config.h" + +namespace grpc { +namespace testing { + +namespace { +const int kLargeRequestSize = 271828; +const int kLargeResponseSize = 314159; +} // namespace + +Http2Client::ServiceStub::ServiceStub(std::shared_ptr channel) + : channel_(channel) { + stub_ = TestService::NewStub(channel); +} + +TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); } + +Http2Client::Http2Client(std::shared_ptr channel) + : serviceStub_(channel), channel_(channel) {} + +bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) { + if (s.error_code() == expected_code) { + return true; + } + + gpr_log(GPR_ERROR, "Error status code: %d (expected: %d), message: %s", + s.error_code(), expected_code, s.error_message().c_str()); + abort(); +} + +bool Http2Client::DoRstAfterHeader() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(!response.has_payload()); // no data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream after header"); + return true; +} + +bool Http2Client::DoRstAfterData() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(response.has_payload()); // data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream after data"); + return true; +} + +bool Http2Client::DoRstDuringData() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(!response.has_payload()); // no data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream during data"); + return true; +} + +bool Http2Client::DoGoaway() { + gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway"); + + int numCalls = 2; + for (int i = 0; i < numCalls; i++) { + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + } + + gpr_log(GPR_DEBUG, "Done testing goaway"); + return true; +} + +bool Http2Client::DoPing() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting ping"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + + gpr_log(GPR_DEBUG, "Done testing ping"); + return true; +} + +void Http2Client::MaxStreamsWorker(std::shared_ptr channel) { + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = + TestService::NewStub(channel)->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); +} + +bool Http2Client::DoMaxStreams() { + gpr_log(GPR_DEBUG, "Testing max streams"); + + // Make an initial call on the channel to ensure the server's max streams + // setting is received + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + Status s = + TestService::NewStub(channel_)->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + + std::vector test_threads; + + for (int i = 0; i < 10; i++) { + test_threads.emplace_back( + std::thread(&Http2Client::MaxStreamsWorker, this, channel_)); + } + + for (auto it = test_threads.begin(); it != test_threads.end(); it++) { + it->join(); + } + + gpr_log(GPR_DEBUG, "Done testing max streams"); + return true; +} + +} // namespace testing +} // namespace grpc + +DEFINE_int32(server_port, 0, "Server port."); +DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); +DEFINE_string(test_case, "rst_after_header", + "Configure different test cases. Valid options are:\n\n" + "goaway\n" + "max_streams\n" + "ping\n" + "rst_after_data\n" + "rst_after_header\n" + "rst_during_data\n"); + +int main(int argc, char** argv) { + grpc::testing::InitTest(&argc, &argv, true); + GPR_ASSERT(FLAGS_server_port); + const int host_port_buf_size = 1024; + char host_port[host_port_buf_size]; + snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), + FLAGS_server_port); + grpc::testing::Http2Client client(grpc::CreateTestChannel(host_port, false)); + gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str()); + int ret = 0; + if (FLAGS_test_case == "rst_after_header") { + client.DoRstAfterHeader(); + } else if (FLAGS_test_case == "rst_after_data") { + client.DoRstAfterData(); + } else if (FLAGS_test_case == "rst_during_data") { + client.DoRstDuringData(); + } else if (FLAGS_test_case == "goaway") { + client.DoGoaway(); + } else if (FLAGS_test_case == "ping") { + client.DoPing(); + } else if (FLAGS_test_case == "max_streams") { + client.DoMaxStreams(); + } else { + const char* testcases[] = { + "goaway", "max_streams", "ping", + "rst_after_data", "rst_after_header", "rst_during_data"}; + char* joined_testcases = + gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL); + + gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s", + FLAGS_test_case.c_str(), joined_testcases); + gpr_free(joined_testcases); + ret = 1; + } + + return ret; +} diff --git a/test/cpp/interop/http2_client.h b/test/cpp/interop/http2_client.h new file mode 100644 index 00000000000..6a315f5abba --- /dev/null +++ b/test/cpp/interop/http2_client.h @@ -0,0 +1,80 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H +#define GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H + +#include + +#include +#include +#include "src/proto/grpc/testing/messages.grpc.pb.h" +#include "src/proto/grpc/testing/test.grpc.pb.h" + +namespace grpc { +namespace testing { + +class Http2Client { + public: + explicit Http2Client(std::shared_ptr channel); + ~Http2Client() {} + + bool DoRstAfterHeader(); + bool DoRstAfterData(); + bool DoRstDuringData(); + bool DoGoaway(); + bool DoPing(); + bool DoMaxStreams(); + + private: + class ServiceStub { + public: + ServiceStub(std::shared_ptr channel); + + TestService::Stub* Get(); + + private: + std::unique_ptr stub_; + std::shared_ptr channel_; + }; + + void MaxStreamsWorker(std::shared_ptr channel); + bool AssertStatusCode(const Status& s, StatusCode expected_code); + ServiceStub serviceStub_; + std::shared_ptr channel_; +}; + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8849dcc600c..0c007672000 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -2772,6 +2772,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "grpc", + "grpc++", + "grpc++_test_config", + "grpc++_test_util", + "grpc_test_util", + "http2_client_main" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "http2_client", + "src": [], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -5388,6 +5405,33 @@ "third_party": false, "type": "lib" }, + { + "deps": [ + "grpc", + "grpc++", + "grpc++_test_config", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [ + "src/proto/grpc/testing/empty.grpc.pb.h", + "src/proto/grpc/testing/empty.pb.h", + "src/proto/grpc/testing/messages.grpc.pb.h", + "src/proto/grpc/testing/messages.pb.h", + "src/proto/grpc/testing/test.grpc.pb.h", + "src/proto/grpc/testing/test.pb.h", + "test/cpp/interop/http2_client.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "http2_client_main", + "src": [ + "test/cpp/interop/http2_client.cc", + "test/cpp/interop/http2_client.h" + ], + "third_party": false, + "type": "lib" + }, { "deps": [ "gpr", diff --git a/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj new file mode 100644 index 00000000000..c94c346ed99 --- /dev/null +++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8008C126-4B35-5A76-A795-39DA13DA57F4} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + http2_client_main + + + http2_client_main + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Windows + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Windows + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Windows + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Windows + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0BE77741-552A-929B-A497-4EF7ECE17A64} + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {3F7D093D-11F9-C4BC-BEB7-18EB28E3F290} + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + diff --git a/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters new file mode 100644 index 00000000000..40e41913451 --- /dev/null +++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + src\proto\grpc\testing + + + src\proto\grpc\testing + + + src\proto\grpc\testing + + + test\cpp\interop + + + + + test\cpp\interop + + + + + + {8f01743f-58cf-2127-20d1-21303c8e0e8e} + + + {219dd0bc-d605-d0fa-cca4-460276dd64cf} + + + {7ee50971-dbc6-3240-e6a2-a432dac43e90} + + + {66289b19-9541-151c-03a1-771101833b4e} + + + {18fdd193-31a2-a622-980e-df055c23af50} + + + {f6da8892-ac51-d835-468a-b3b093df4baa} + + + {e32cff29-3247-cece-56cf-8fd16a1a79fe} + + + + From 6bbd95e4a319495a7ad6c70b93b0f7984b6cc891 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Wed, 11 Jan 2017 09:35:09 -0800 Subject: [PATCH 13/22] minor fix --- tools/run_tests/run_interop_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index d25da0b2fa9..a33ff55ca35 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -876,7 +876,7 @@ try: if args.http2_badserver_interop: # launch a HTTP2 server emulator that creates edge cases lang = str(http2InteropServer) - spec = server_jobspec(Http2Server(), docker_images.get(lang)) + spec = server_jobspec(http2InteropServer, docker_images.get(lang)) job = dockerjob.DockerJob(spec) server_jobs[lang] = job server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) From b8c5fe1e621dd804b3aec1175b6a8c23637de0ef Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 10:47:35 -0800 Subject: [PATCH 14/22] Promote dns resolution failure message to INFO --- src/core/ext/resolver/dns/native/dns_resolver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index bb2b0125072..655d9dc586c 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -189,7 +189,7 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec timeout = gpr_time_sub(next_try, now); const char *msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg); + gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", msg); grpc_error_free_string(msg); GPR_ASSERT(!r->have_retry_timer); r->have_retry_timer = true; From 1da20c10b0f56e83364045445be0fb4f0c44b4cd Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 10:50:26 -0800 Subject: [PATCH 15/22] Remove unused load --- test/core/support/BUILD | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/core/support/BUILD b/test/core/support/BUILD index 77f0a9a0480..dfe952eb373 100644 --- a/test/core/support/BUILD +++ b/test/core/support/BUILD @@ -27,8 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") - cc_test( name = "alloc_test", srcs = ["alloc_test.c"], From cc5910228d84561d40cd8f0513faddc1e0100275 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 11:10:43 -0800 Subject: [PATCH 16/22] manual revert of #8901 --- build.yaml | 1 + test/cpp/end2end/async_end2end_test.cc | 19 ++++-- test/cpp/end2end/end2end_test.cc | 20 ++++-- test/cpp/interop/client.cc | 1 + test/cpp/interop/client_helper.cc | 10 ++- test/cpp/interop/interop_server.cc | 1 + test/cpp/interop/server_helper.cc | 18 +++--- test/cpp/interop/stress_test.cc | 1 + test/cpp/util/create_test_channel.cc | 64 ++++++++++++++++--- test/cpp/util/create_test_channel.h | 4 ++ test/cpp/util/test_credentials_provider.cc | 52 +++------------ test/cpp/util/test_credentials_provider.h | 50 ++++++++++----- .../generated/sources_and_headers.json | 1 + .../interop_server_helper.vcxproj | 3 + 14 files changed, 153 insertions(+), 92 deletions(-) diff --git a/build.yaml b/build.yaml index 55aca52f680..64b2a6e01ce 100644 --- a/build.yaml +++ b/build.yaml @@ -1259,6 +1259,7 @@ libs: src: - test/cpp/interop/server_helper.cc deps: + - grpc++_test_util - grpc_test_util - grpc++ - grpc diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 8e385d100c1..2ce3f2f7bd9 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -254,7 +254,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { // Setup server ServerBuilder builder; - auto server_creds = GetServerCredentials(GetParam().credentials_type); + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); builder.AddListeningPort(server_address_.str(), server_creds); builder.RegisterService(&service_); cq_ = builder.AddCompletionQueue(); @@ -283,8 +284,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { void ResetStub() { ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); std::shared_ptr channel = CreateCustomChannel(server_address_.str(), channel_creds, args); stub_ = grpc::testing::EchoTestService::NewStub(channel); @@ -892,8 +893,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { TEST_P(AsyncEnd2endTest, UnimplementedRpc) { ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); std::shared_ptr channel = CreateCustomChannel(server_address_.str(), channel_creds, args); std::unique_ptr stub; @@ -1404,11 +1405,15 @@ std::vector CreateTestScenarios(bool test_disable_blocking, std::vector credentials_types; std::vector messages; - credentials_types.push_back(kInsecureCredentialsType); - auto sec_list = GetSecureCredentialsTypeList(); + if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType, + nullptr) != nullptr) { + credentials_types.push_back(kInsecureCredentialsType); + } + auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { credentials_types.push_back(*sec); } + GPR_ASSERT(!credentials_types.empty()); messages.push_back("Hello"); for (int sz = 1; sz < test_big_limit; sz *= 2) { diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 9bb892c694b..1a1a94e87c7 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -242,7 +242,8 @@ class End2endTest : public ::testing::TestWithParam { // Setup server ServerBuilder builder; ConfigureServerBuilder(&builder); - auto server_creds = GetServerCredentials(GetParam().credentials_type); + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); if (GetParam().credentials_type != kInsecureCredentialsType) { server_creds->SetAuthMetadataProcessor(processor); } @@ -270,8 +271,8 @@ class End2endTest : public ::testing::TestWithParam { } EXPECT_TRUE(is_server_started_); ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); if (!user_agent_prefix_.empty()) { args.SetUserAgentPrefix(user_agent_prefix_); } @@ -1520,11 +1521,18 @@ std::vector CreateTestScenarios(bool use_proxy, std::vector scenarios; std::vector credentials_types; if (test_secure) { - credentials_types = GetSecureCredentialsTypeList(); + credentials_types = + GetCredentialsProvider()->GetSecureCredentialsTypeList(); } if (test_insecure) { - credentials_types.push_back(kInsecureCredentialsType); + // Only add insecure credentials type when it is registered with the + // provider. User may create providers that do not have insecure. + if (GetCredentialsProvider()->GetChannelCredentials( + kInsecureCredentialsType, nullptr) != nullptr) { + credentials_types.push_back(kInsecureCredentialsType); + } } + GPR_ASSERT(!credentials_types.empty()); for (auto it = credentials_types.begin(); it != credentials_types.end(); ++it) { scenarios.emplace_back(false, *it); @@ -1541,7 +1549,7 @@ INSTANTIATE_TEST_CASE_P(End2end, End2endTest, INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest, ::testing::ValuesIn(CreateTestScenarios(false, true, - false))); + true))); INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest, ::testing::ValuesIn(CreateTestScenarios(true, true, diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index c58910abc3f..3265554444b 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -49,6 +49,7 @@ #include "test/cpp/util/test_config.h" DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_bool(use_test_ca, false, "False to use SSL roots for google"); DEFINE_int32(server_port, 0, "Server port."); DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index c171969e147..91564e5dcef 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -50,8 +50,10 @@ #include "src/cpp/client/secure_credentials.h" #include "test/core/security/oauth2_utils.h" #include "test/cpp/util/create_test_channel.h" +#include "test/cpp/util/test_credentials_provider.h" DECLARE_bool(use_tls); +DECLARE_string(custom_credentials_type); DECLARE_bool(use_test_ca); DECLARE_int32(server_port); DECLARE_string(server_host); @@ -114,8 +116,12 @@ std::shared_ptr CreateChannelForTestCase( creds = AccessTokenCredentials(raw_token); GPR_ASSERT(creds); } - return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls, - !FLAGS_use_test_ca, creds); + if (FLAGS_custom_credentials_type.empty()) { + return CreateTestChannel(host_port, FLAGS_server_host_override, + FLAGS_use_tls, !FLAGS_use_test_ca, creds); + } else { + return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds); + } } } // namespace testing diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc index 67456ce18bb..956840ba709 100644 --- a/test/cpp/interop/interop_server.cc +++ b/test/cpp/interop/interop_server.cc @@ -56,6 +56,7 @@ #include "test/cpp/util/test_config.h" DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_int32(port, 0, "Server port."); DEFINE_int32(max_send_message_size, -1, "The maximum send message size."); diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc index 8b0b511bcb8..d395f50fa59 100644 --- a/test/cpp/interop/server_helper.cc +++ b/test/cpp/interop/server_helper.cc @@ -39,23 +39,23 @@ #include #include "src/core/lib/surface/call_test_only.h" -#include "test/core/end2end/data/ssl_test_data.h" +#include "test/cpp/util/test_credentials_provider.h" DECLARE_bool(use_tls); +DECLARE_string(custom_credentials_type); namespace grpc { namespace testing { std::shared_ptr CreateInteropServerCredentials() { - if (FLAGS_use_tls) { - SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, - test_server1_cert}; - SslServerCredentialsOptions ssl_opts; - ssl_opts.pem_root_certs = ""; - ssl_opts.pem_key_cert_pairs.push_back(pkcp); - return SslServerCredentials(ssl_opts); + if (!FLAGS_custom_credentials_type.empty()) { + return GetCredentialsProvider()->GetServerCredentials( + FLAGS_custom_credentials_type); + } else if (FLAGS_use_tls) { + return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType); } else { - return InsecureServerCredentials(); + return GetCredentialsProvider()->GetServerCredentials( + kInsecureCredentialsType); } } diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc index 97e658869fe..562522de779 100644 --- a/test/cpp/interop/stress_test.cc +++ b/test/cpp/interop/stress_test.cc @@ -147,6 +147,7 @@ DEFINE_bool(do_not_abort_on_transient_failures, true, // Options from client.cc (for compatibility with interop test). // TODO(sreek): Consolidate overlapping options DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_bool(use_test_ca, false, "False to use SSL roots for google"); DEFINE_int32(server_port, 0, "Server port."); DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index fe8b5d54235..ad62e03490e 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -35,11 +35,37 @@ #include #include +#include -#include "test/core/end2end/data/ssl_test_data.h" +#include "test/cpp/util/test_credentials_provider.h" namespace grpc { +namespace { + +const char kProdTlsCredentialsType[] = "prod_ssl"; + +class SslCredentialProvider : public testing::CredentialTypeProvider { + public: + std::shared_ptr GetChannelCredentials( + grpc::ChannelArguments* args) override { + return SslCredentials(SslCredentialsOptions()); + } + std::shared_ptr GetServerCredentials() override { + return nullptr; + } +}; + +gpr_once g_once_init_add_prod_ssl_provider = GPR_ONCE_INIT; +// Register ssl with non-test roots type to the credentials provider. +void AddProdSslType() { + testing::GetCredentialsProvider()->AddSecureType( + kProdTlsCredentialsType, std::unique_ptr( + new SslCredentialProvider)); +} + +} // namespace + // When ssl is enabled, if server is empty, override_hostname is used to // create channel. Otherwise, connect to server and override hostname if // override_hostname is provided. @@ -61,16 +87,22 @@ std::shared_ptr CreateTestChannel( const std::shared_ptr& creds, const ChannelArguments& args) { ChannelArguments channel_args(args); + std::shared_ptr channel_creds; if (enable_ssl) { - const char* roots_certs = use_prod_roots ? "" : test_root_cert; - SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - - std::shared_ptr channel_creds = - SslCredentials(ssl_opts); - - if (!server.empty() && !override_hostname.empty()) { - channel_args.SetSslTargetNameOverride(override_hostname); + if (use_prod_roots) { + gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType); + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + kProdTlsCredentialsType, &channel_args); + if (!server.empty() && !override_hostname.empty()) { + channel_args.SetSslTargetNameOverride(override_hostname); + } + } else { + // override_hostname is discarded as the provider handles it. + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + testing::kTlsCredentialsType, &channel_args); } + GPR_ASSERT(channel_creds != nullptr); + const grpc::string& connect_to = server.empty() ? override_hostname : server; if (creds.get()) { @@ -103,4 +135,18 @@ std::shared_ptr CreateTestChannel(const grpc::string& server, return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false); } +std::shared_ptr CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr& creds) { + ChannelArguments channel_args; + std::shared_ptr channel_creds = + testing::GetCredentialsProvider()->GetChannelCredentials(credential_type, + &channel_args); + GPR_ASSERT(channel_creds != nullptr); + if (creds.get()) { + channel_creds = CompositeChannelCredentials(channel_creds, creds); + } + return CreateCustomChannel(server, channel_creds, channel_args); +} + } // namespace grpc diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 4ff666dc1bc..ce71a97edbb 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -59,6 +59,10 @@ std::shared_ptr CreateTestChannel( const std::shared_ptr& creds, const ChannelArguments& args); +std::shared_ptr CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr& creds); + } // namespace grpc #endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0456b966671..909b02a7019 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -43,25 +43,9 @@ #include "test/core/end2end/data/ssl_test_data.h" namespace grpc { +namespace testing { namespace { -using grpc::testing::CredentialTypeProvider; - -// Provide test credentials. Thread-safe. -class CredentialsProvider { - public: - virtual ~CredentialsProvider() {} - - virtual void AddSecureType( - const grpc::string& type, - std::unique_ptr type_provider) = 0; - virtual std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) = 0; - virtual std::shared_ptr GetServerCredentials( - const grpc::string& type) = 0; - virtual std::vector GetSecureCredentialsTypeList() = 0; -}; - class DefaultCredentialsProvider : public CredentialsProvider { public: ~DefaultCredentialsProvider() override {} @@ -145,37 +129,21 @@ class DefaultCredentialsProvider : public CredentialsProvider { added_secure_type_providers_; }; -gpr_once g_once_init_provider = GPR_ONCE_INIT; CredentialsProvider* g_provider = nullptr; -void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; } - -CredentialsProvider* GetProvider() { - gpr_once_init(&g_once_init_provider, &CreateDefaultProvider); - return g_provider; -} - } // namespace -namespace testing { - -void AddSecureType(const grpc::string& type, - std::unique_ptr type_provider) { - GetProvider()->AddSecureType(type, std::move(type_provider)); -} - -std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) { - return GetProvider()->GetChannelCredentials(type, args); -} - -std::shared_ptr GetServerCredentials( - const grpc::string& type) { - return GetProvider()->GetServerCredentials(type); +CredentialsProvider* GetCredentialsProvider() { + if (g_provider == nullptr) { + g_provider = new DefaultCredentialsProvider; + } + return g_provider; } -std::vector GetSecureCredentialsTypeList() { - return GetProvider()->GetSecureCredentialsTypeList(); +void SetCredentialsProvider(CredentialsProvider* provider) { + // For now, forbids overriding provider. + GPR_ASSERT(g_provider == nullptr); + g_provider = provider; } } // namespace testing diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h index 1fb311e556e..0bc52ebe4df 100644 --- a/test/cpp/util/test_credentials_provider.h +++ b/test/cpp/util/test_credentials_provider.h @@ -59,23 +59,39 @@ class CredentialTypeProvider { virtual std::shared_ptr GetServerCredentials() = 0; }; -// Add a secure type in addition to the defaults above -// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the -// functions below. -void AddSecureType(const grpc::string& type, - std::unique_ptr type_provider); - -// Provide channel credentials according to the given type. Alter the channel -// arguments if needed. -std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args); - -// Provide server credentials according to the given type. -std::shared_ptr GetServerCredentials( - const grpc::string& type); - -// Provide a list of secure credentials type. -std::vector GetSecureCredentialsTypeList(); +// Provide test credentials. Thread-safe. +class CredentialsProvider { + public: + virtual ~CredentialsProvider() {} + + // Add a secure type in addition to the defaults. The default provider has + // (kInsecureCredentialsType, kTlsCredentialsType). + virtual void AddSecureType( + const grpc::string& type, + std::unique_ptr type_provider) = 0; + + // Provide channel credentials according to the given type. Alter the channel + // arguments if needed. Return nullptr if type is not registered. + virtual std::shared_ptr GetChannelCredentials( + const grpc::string& type, ChannelArguments* args) = 0; + + // Provide server credentials according to the given type. + // Return nullptr if type is not registered. + virtual std::shared_ptr GetServerCredentials( + const grpc::string& type) = 0; + + // Provide a list of secure credentials type. + virtual std::vector GetSecureCredentialsTypeList() = 0; +}; + +// Get the current provider. Create a default one if not set. +// Not thread-safe. +CredentialsProvider* GetCredentialsProvider(); + +// Set the global provider. Takes ownership. The previous set provider will be +// destroyed. +// Not thread-safe. +void SetCredentialsProvider(CredentialsProvider* provider); } // namespace testing } // namespace grpc diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8849dcc600c..72f0b08d9e4 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5447,6 +5447,7 @@ "gpr", "grpc", "grpc++", + "grpc++_test_util", "grpc_test_util" ], "headers": [ diff --git a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj index 4c99988a34c..377cadc1a1e 100644 --- a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj +++ b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj @@ -154,6 +154,9 @@ + + {0BE77741-552A-929B-A497-4EF7ECE17A64} + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} From 8ad258a450cd7800984be3da48e21bd1484c9673 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 15:22:29 -0800 Subject: [PATCH 17/22] Add missing include for GPRAPI --- include/grpc/support/log_windows.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/grpc/support/log_windows.h b/include/grpc/support/log_windows.h index 12bf8cc1f5e..943a8e908b3 100644 --- a/include/grpc/support/log_windows.h +++ b/include/grpc/support/log_windows.h @@ -34,6 +34,8 @@ #ifndef GRPC_SUPPORT_LOG_WINDOWS_H #define GRPC_SUPPORT_LOG_WINDOWS_H +#include + #ifdef __cplusplus extern "C" { #endif From 4314043e407763918de6696366919d0fa8afac83 Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Wed, 11 Jan 2017 15:59:33 -0800 Subject: [PATCH 18/22] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 1ded97b5037..b64fe6a024d 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -50,6 +50,7 @@ the user application having to do a thing. Client Procedure: 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between). + TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep ``` { From d36a53156c9591cd68e5ea17d7579cda896e2840 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 16:14:44 -0800 Subject: [PATCH 19/22] Add missing include for size_t --- test/core/util/memory_counters.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/core/util/memory_counters.h b/test/core/util/memory_counters.h index f3328165014..b9b2b3adda5 100644 --- a/test/core/util/memory_counters.h +++ b/test/core/util/memory_counters.h @@ -34,6 +34,8 @@ #ifndef GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H #define GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H +#include + struct grpc_memory_counters { size_t total_size_relative; size_t total_size_absolute; From 015998f7708843ead6379ac5e6d6963603d200ea Mon Sep 17 00:00:00 2001 From: Adele Zhou Date: Tue, 6 Dec 2016 16:05:07 -0800 Subject: [PATCH 20/22] Add perf link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 70cf9fcc30e..174e861f594 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ See [INSTALL](INSTALL.md) for installation instructions for various platforms. See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks) +See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5712453606309888) for the performance numbers for v1.0.x. + #Repository Structure & Status This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core). From 90cd2789457a466c208a46bbaf413cfe2af57bd8 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Wed, 11 Jan 2017 21:38:33 -0800 Subject: [PATCH 21/22] PHP: use a macro to specify extension src dir --- config.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index 12b10578e89..85549e5f427 100644 --- a/config.m4 +++ b/config.m4 @@ -5,9 +5,9 @@ if test "$PHP_GRPC" != "no"; then dnl Write more examples of tests here... dnl # --with-grpc -> add include path - PHP_ADD_INCLUDE(../../grpc/include) - PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc) - PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include) LIBS="-lpthread $LIBS" From fe71d7fc5fb9d730cda1579baba65da7389ecb49 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 12 Jan 2017 11:13:23 -0800 Subject: [PATCH 22/22] Fix the template as well --- templates/config.m4.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/config.m4.template b/templates/config.m4.template index 5847d456f51..f5f1d23088d 100644 --- a/templates/config.m4.template +++ b/templates/config.m4.template @@ -7,9 +7,9 @@ dnl Write more examples of tests here... dnl # --with-grpc -> add include path - PHP_ADD_INCLUDE(../../grpc/include) - PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc) - PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include) LIBS="-lpthread $LIBS"