diff options
author | Craig Tiller <craig.tiller@gmail.com> | 2015-12-16 19:25:58 -0800 |
---|---|---|
committer | Craig Tiller <craig.tiller@gmail.com> | 2015-12-16 19:25:58 -0800 |
commit | 86e8ad8ddf6bbbb59327cee2383d7ec414e06c71 (patch) | |
tree | 1eacf02d534f6c246597c800988f7091306d558b /test/core | |
parent | c8b7013be30f003e501e743cec856c739db3e160 (diff) | |
parent | 788767a18f918131268ca88985b3547a8257e973 (diff) |
Merge github.com:grpc/grpc into big_data
Diffstat (limited to 'test/core')
93 files changed, 3630 insertions, 434 deletions
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index e1a4b8ed90..5aceac6cac 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -49,13 +49,14 @@ typedef struct { grpc_server *server; grpc_completion_queue *cq; grpc_bad_client_server_side_validator validator; + void *registered_method; gpr_event done_thd; gpr_event done_write; } thd_args; static void thd_func(void *arg) { thd_args *a = arg; - a->validator(a->server, a->cq); + a->validator(a->server, a->cq, a->registered_method); gpr_event_set(&a->done_thd, (void *)1); } @@ -110,6 +111,9 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, gpr_event_init(&a.done_write); a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); + a.registered_method = + grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD, + GRPC_BAD_CLIENT_REGISTERED_HOST); grpc_server_start(a.server); transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0); server_setup_transport(&a, transport); diff --git a/test/core/bad_client/bad_client.h b/test/core/bad_client/bad_client.h index 01beda60ee..2dd100a3db 100644 --- a/test/core/bad_client/bad_client.h +++ b/test/core/bad_client/bad_client.h @@ -37,8 +37,12 @@ #include <grpc/grpc.h> #include "test/core/util/test_config.h" -typedef void (*grpc_bad_client_server_side_validator)( - grpc_server *server, grpc_completion_queue *cq); +#define GRPC_BAD_CLIENT_REGISTERED_METHOD "/registered/bar" +#define GRPC_BAD_CLIENT_REGISTERED_HOST "localhost" + +typedef void (*grpc_bad_client_server_side_validator)(grpc_server *server, + grpc_completion_queue *cq, + void *registered_method); #define GRPC_BAD_CLIENT_DISCONNECT 1 diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index 62b2c26796..22b99e7cb4 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -40,9 +40,11 @@ default_test_options = TestOptions(False) # maps test names to options BAD_CLIENT_TESTS = { + 'badreq': default_test_options, 'connection_prefix': default_test_options, 'headers': default_test_options, 'initial_settings_frame': default_test_options, + 'server_registered_method': default_test_options, 'simple_request': default_test_options, 'window_overflow': default_test_options, 'unknown_frame': default_test_options, diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c new file mode 100644 index 0000000000..6d59d25b92 --- /dev/null +++ b/test/core/bad_client/tests/badreq.c @@ -0,0 +1,140 @@ +/* + * + * Copyright 2015, 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 "test/core/bad_client/bad_client.h" + +#include <string.h> + +#include "test/core/end2end/cq_verifier.h" +#include "src/core/surface/server.h" + +#define PFX_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next(cq, + GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), + NULL).type == GRPC_QUEUE_TIMEOUT); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + /* invalid content type */ + GRPC_RUN_BAD_CLIENT_TEST( + verifier, PFX_STR + "\x00\x00\xc2\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x08/foo/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x09text/html" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)", + GRPC_BAD_CLIENT_DISCONNECT); + + /* invalid te */ + GRPC_RUN_BAD_CLIENT_TEST( + verifier, PFX_STR + "\x00\x00\xcb\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x08/foo/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x02te\x0a" + "frobnicate" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)", + GRPC_BAD_CLIENT_DISCONNECT); + + /* two path headers */ + GRPC_RUN_BAD_CLIENT_TEST( + verifier, PFX_STR + "\x00\x00\xd9\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x08/foo/bar" + "\x10\x05:path\x08/foo/bah" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)", + GRPC_BAD_CLIENT_DISCONNECT); + + /* bad accept-encoding algorithm */ + GRPC_RUN_BAD_CLIENT_TEST( + verifier, PFX_STR + "\x00\x00\xd2\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x08/foo/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x1enobody-knows-the-trouble-i-see" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)", + GRPC_BAD_CLIENT_DISCONNECT); + + /* bad grpc-encoding algorithm */ + GRPC_RUN_BAD_CLIENT_TEST( + verifier, PFX_STR + "\x00\x00\xf5\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x08/foo/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x0dgrpc-encoding\x1cyou-dont-know-how-to-do-this" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)", + GRPC_BAD_CLIENT_DISCONNECT); + + return 0; +} diff --git a/test/core/bad_client/tests/badreq_2path.headers b/test/core/bad_client/tests/badreq_2path.headers new file mode 100644 index 0000000000..0441e50c8c --- /dev/null +++ b/test/core/bad_client/tests/badreq_2path.headers @@ -0,0 +1,13 @@ +# headers used in badreq.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /foo/bar +:path: /foo/bah +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) + diff --git a/test/core/bad_client/tests/badreq_algorithm.headers b/test/core/bad_client/tests/badreq_algorithm.headers new file mode 100644 index 0000000000..ff3e613f93 --- /dev/null +++ b/test/core/bad_client/tests/badreq_algorithm.headers @@ -0,0 +1,11 @@ +# headers used in badreq.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /foo/bar +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: nobody-knows-the-trouble-i-see +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) diff --git a/test/core/bad_client/tests/badreq_content_type.headers b/test/core/bad_client/tests/badreq_content_type.headers new file mode 100644 index 0000000000..ed8d798f19 --- /dev/null +++ b/test/core/bad_client/tests/badreq_content_type.headers @@ -0,0 +1,11 @@ +# headers used in badreq.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /foo/bar +:scheme: http +:method: POST +:authority: localhost +content-type: text/html +grpc-accept-encoding: identity,deflate,gzip +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) diff --git a/test/core/bad_client/tests/badreq_encoding.headers b/test/core/bad_client/tests/badreq_encoding.headers new file mode 100644 index 0000000000..5639c1fd71 --- /dev/null +++ b/test/core/bad_client/tests/badreq_encoding.headers @@ -0,0 +1,12 @@ +# headers used in badreq.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /foo/bar +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip +grpc-encoding: you-dont-know-how-to-do-this +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) diff --git a/test/core/bad_client/tests/badreq_te.headers b/test/core/bad_client/tests/badreq_te.headers new file mode 100644 index 0000000000..012810e77d --- /dev/null +++ b/test/core/bad_client/tests/badreq_te.headers @@ -0,0 +1,11 @@ +# headers used in badreq.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /foo/bar +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip +te: frobnicate +user-agent: bad-client grpc-c/0.12.0.0 (linux) diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c index 90d37a3735..66ff8c2936 100644 --- a/test/core/bad_client/tests/connection_prefix.c +++ b/test/core/bad_client/tests/connection_prefix.c @@ -34,7 +34,8 @@ #include "test/core/bad_client/bad_client.h" #include "src/core/surface/server.h" -static void verifier(grpc_server *server, grpc_completion_queue *cq) { +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { while (grpc_server_has_open_connections(server)) { GPR_ASSERT(grpc_completion_queue_next(cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c index abd2826111..2186a4ffcb 100644 --- a/test/core/bad_client/tests/headers.c +++ b/test/core/bad_client/tests/headers.c @@ -38,11 +38,12 @@ "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ "\x00\x00\x00\x04\x00\x00\x00\x00\x00" -static void verifier(grpc_server *server, grpc_completion_queue *cq) { +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(grpc_completion_queue_next(cq, + GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), + NULL).type == GRPC_QUEUE_TIMEOUT); } } @@ -126,24 +127,29 @@ int main(int argc, char **argv) { 0); GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\x7f\x7f\x01""a", + "\x7f\x7f\x01" + "a", 0); GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\x0f\x7f\x01""a", + "\x0f\x7f\x01" + "a", 0); GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\x1f\x7f\x01""a", + "\x1f\x7f\x01" + "a", 0); /* test nvr, not indexed in static table */ GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" - "\x01\x01""a", + "\x01\x01" + "a", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" - "\x11\x01""a", + "\x11\x01" + "a", GRPC_BAD_CLIENT_DISCONNECT); /* illegal op code */ GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR @@ -228,14 +234,12 @@ int main(int argc, char **argv) { GRPC_BAD_CLIENT_DISCONNECT); /* dynamic table size update: set to default */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x3f\xe1\x1f", GRPC_BAD_CLIENT_DISCONNECT); /* dynamic table size update: set too large */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x03\x01\x04\x00\x00\x00\x01" "\x3f\xf1\x1f", 0); @@ -251,42 +255,35 @@ int main(int argc, char **argv) { 0); /* non-ending header followed by continuation frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x00\x00\x00\x00\x01" "\x00\x00\x00\x09\x04\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); /* non-ending header followed by non-continuation frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x00\x00\x00\x00\x01" "\x00\x00\x00\x00\x04\x00\x00\x00\x01", 0); - /* non-ending header followed by a continuation frame for a different stream */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + /* non-ending header followed by a continuation frame for a different stream + */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x00\x00\x00\x00\x03" "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); /* opening with a continuation frame */ GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR - "\x00\x00\x00\x09\x04\x00\x00\x00\x01", - 0); + PFX_STR "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); /* three header frames */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x04\x00\x00\x00\x01" "\x00\x00\x00\x01\x04\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); - /* an invalid header found with fuzzing */ GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR - "\x00\x00\x00\x01\x39\x67\xed\x1d\x64", + PFX_STR "\x00\x00\x00\x01\x39\x67\xed\x1d\x64", GRPC_BAD_CLIENT_DISCONNECT); /* a badly encoded timeout value */ diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c index 129c667f71..fb6149cc3b 100644 --- a/test/core/bad_client/tests/initial_settings_frame.c +++ b/test/core/bad_client/tests/initial_settings_frame.c @@ -37,7 +37,8 @@ #define PFX_STR "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" #define ONE_SETTING_HDR "\x00\x00\x06\x04\x00\x00\x00\x00\x00" -static void verifier(grpc_server *server, grpc_completion_queue *cq) { +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { while (grpc_server_has_open_connections(server)) { GPR_ASSERT(grpc_completion_queue_next(cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), @@ -94,14 +95,26 @@ int main(int argc, char **argv) { /* some settings values are illegal */ /* max frame size = 0 */ GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", + PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR ONE_SETTING_HDR "\x00\x06\xff\xff\xff\xff", + PFX_STR ONE_SETTING_HDR "\x00\x06\xff\xff\xff\xff", GRPC_BAD_CLIENT_DISCONNECT); /* update intiial window size */ GRPC_RUN_BAD_CLIENT_TEST(verifier, - PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", + PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + /* ack with data */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" + "\x00\x00\x01\x04\x01\x00\x00\x00\x00", + 0); + /* settings frame with invalid flags */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR "\x00\x00\x00\x04\x10\x00\x00\x00\x00", 0); + /* unknown settings should be ignored */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR ONE_SETTING_HDR "\x00\x99\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); return 0; diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c new file mode 100644 index 0000000000..d2876ffa93 --- /dev/null +++ b/test/core/bad_client/tests/server_registered_method.c @@ -0,0 +1,155 @@ +/* + * + * Copyright 2015, 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 "test/core/bad_client/bad_client.h" + +#include <string.h> + +#include "test/core/end2end/cq_verifier.h" +#include "src/core/surface/server.h" + +#define PFX_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \ + "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" \ + "\x10\x05:path\x0f/registered/bar" \ + "\x10\x07:scheme\x04http" \ + "\x10\x07:method\x04POST" \ + "\x10\x0a:authority\x09localhost" \ + "\x10\x0c" \ + "content-type\x10" \ + "application/grpc" \ + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +static void *tag(gpr_intptr t) { return (void *)t; } + +static void verifier_succeeds(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + gpr_timespec deadline; + grpc_byte_buffer *payload = NULL; + + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_registered_call(server, registered_method, &s, + &deadline, &request_metadata_recv, + &payload, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(payload != NULL); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_destroy(s); + grpc_byte_buffer_destroy(payload); + cq_verifier_destroy(cqv); +} + +static void verifier_fails(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + gpr_timespec deadline; + grpc_byte_buffer *payload = NULL; + + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_registered_call(server, registered_method, &s, + &deadline, &request_metadata_recv, + &payload, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(payload == NULL); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_destroy(s); + cq_verifier_destroy(cqv); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + /* body generated with + * tools/codegen/core/gen_server_registered_method_bad_client_test_body.py */ + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, + PFX_STR "\x00\x00\x00\x00\x00\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, + PFX_STR "\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR + "\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR + "\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, + PFX_STR "\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, + PFX_STR "\x00\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, + PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, + PFX_STR "\x00\x00\x06\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, + PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, + PFX_STR "\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, PFX_STR + "\x00\x00\x07\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\x00", + 0); + + return 0; +} diff --git a/test/core/bad_client/tests/server_registered_method.headers b/test/core/bad_client/tests/server_registered_method.headers new file mode 100644 index 0000000000..06ee73c82e --- /dev/null +++ b/test/core/bad_client/tests/server_registered_method.headers @@ -0,0 +1,12 @@ +# headers used in simple_request.c +# use tools/codegen/core/gen_header_frame.py to generate the binary strings +# contained in the source code +:path: /registered/bar +:scheme: http +:method: POST +:authority: localhost +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) + diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c index 5cddafc0b5..4df586e0e4 100644 --- a/test/core/bad_client/tests/simple_request.c +++ b/test/core/bad_client/tests/simple_request.c @@ -51,7 +51,8 @@ "\x10\x0c" \ "content-type\x10" \ "application/grpc" \ - "\x10\x14grpc-accept-encoding\x15""deflate,identity,gzip" \ + "\x10\x14grpc-accept-encoding\x15" \ + "deflate,identity,gzip" \ "\x10\x02te\x08trailers" \ "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" @@ -65,16 +66,21 @@ "\x10\x07:scheme\x04http" \ "\x10\x07:method\x04POST" \ "\x10\x04host\x09localhost" \ - "\x10\x0c""content-type\x1e""application/grpc+this-is-valid" \ + "\x10\x0c" \ + "content-type\x1e" \ + "application/grpc+this-is-valid" \ "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \ "\x10\x02te\x08trailers" \ "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" \ - "\x10\x0cgrpc-timeout\x03""10S" \ - "\x10\x0cgrpc-timeout\x02""5S" + "\x10\x0cgrpc-timeout\x03" \ + "10S" \ + "\x10\x0cgrpc-timeout\x02" \ + "5S" static void *tag(gpr_intptr t) { return (void *)t; } -static void verifier(grpc_server *server, grpc_completion_queue *cq) { +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { grpc_call_error error; grpc_call *s; grpc_call_details call_details; @@ -99,6 +105,15 @@ static void verifier(grpc_server *server, grpc_completion_queue *cq) { cq_verifier_destroy(cqv); } +static void failure_verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next(cq, + GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), + NULL).type == GRPC_QUEUE_TIMEOUT); + } +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); @@ -115,6 +130,30 @@ int main(int argc, char **argv) { /* push a data frame with bad flags */ GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x00\x02\x00\x00\x00\x01", 0); + /* push a window update with a bad length */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x00\x01\x08\x00\x00\x00\x00\x01", 0); + /* push a window update with bad flags */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x00\x00\x08\x10\x00\x00\x00\x01", 0); + /* push a window update with bad data */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, PFX_STR + "\x00\x00\x04\x08\x00\x00\x00\x00\x01" + "\xff\xff\xff\xff", + 0); + /* push a short goaway */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0); + /* disconnect before sending goaway */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x01\x12\x07\x00\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + /* push a rst_stream with a bad length */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x00\x01\x03\x00\x00\x00\x00\x01", 0); + /* push a rst_stream with bad flags */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, + PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0); return 0; } diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c index 8ea81390c9..2ef340eeb5 100644 --- a/test/core/bad_client/tests/unknown_frame.c +++ b/test/core/bad_client/tests/unknown_frame.c @@ -38,11 +38,12 @@ "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ "\x00\x00\x00\x04\x00\x00\x00\x00\x00" -static void verifier(grpc_server *server, grpc_completion_queue *cq) { +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(grpc_completion_queue_next(cq, + GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), + NULL).type == GRPC_QUEUE_TIMEOUT); } } @@ -50,8 +51,8 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); /* test adding prioritization data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR - "\x00\x00\x00\x88\x00\x00\x00\x00\x01", + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR "\x00\x00\x00\x88\x00\x00\x00\x00\x01", GRPC_BAD_CLIENT_DISCONNECT); return 0; diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c new file mode 100644 index 0000000000..54ac6d0e1c --- /dev/null +++ b/test/core/bad_ssl/bad_ssl_test.c @@ -0,0 +1,171 @@ +/* + * + * Copyright 2015, 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 <string.h> +#include <stdio.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/subprocess.h> +#include "src/core/support/string.h" +#include "test/core/util/port.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/test_config.h" + +static void *tag(gpr_intptr t) { return (void *)t; } + +static void run_test(const char *target, size_t nops) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + grpc_channel *channel; + grpc_call *c; + + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + char *details = NULL; + size_t details_capacity = 0; + grpc_status_code status; + grpc_call_error error; + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); + grpc_completion_queue *cq = grpc_completion_queue_create(NULL); + cq_verifier *cqv = cq_verifier_create(cq); + + grpc_op ops[6]; + grpc_op *op; + + grpc_arg ssl_name_override = {GRPC_ARG_STRING, + GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, + {"foo.test.google.fr"}}; + grpc_channel_args args; + + args.num_args = 1; + args.args = &ssl_name_override; + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + channel = grpc_secure_channel_create(ssl_creds, target, &args, NULL); + c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + "/foo", "foo.test.google.fr:1234", deadline, + NULL); + + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, nops, tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + cq_expect_completion(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status != GRPC_STATUS_OK); + + grpc_call_destroy(c); + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_channel_destroy(channel); + grpc_completion_queue_destroy(cq); + cq_verifier_destroy(cqv); + grpc_channel_credentials_release(ssl_creds); +} + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char *lunder = strrchr(me, '_'); + char *tmp; + char root[1024]; + char test[64]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + size_t i; + gpr_subprocess *svr; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* figure out our test name */ + tmp = lunder - 1; + while (*tmp != '_') tmp--; + tmp++; + memcpy(test, tmp, (size_t)(lunder - tmp)); + /* start the server */ + gpr_asprintf(&args[0], "%s/bad_ssl_%s_server%s", root, test, + gpr_subprocess_binary_extension()); + args[1] = "--bind"; + gpr_join_host_port(&args[2], "::", port); + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + + for (i = 3; i <= 4; i++) { + grpc_init(); + run_test(args[2], i); + grpc_shutdown(); + } + gpr_free(args[2]); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/bad_ssl/gen_build_yaml.py b/test/core/bad_ssl/gen_build_yaml.py new file mode 100755 index 0000000000..d12722439e --- /dev/null +++ b/test/core/bad_ssl/gen_build_yaml.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python2.7 +# Copyright 2015, 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. + + +"""Generates the appropriate build.json data for all the end2end tests.""" + + +import collections +import yaml + +TestOptions = collections.namedtuple('TestOptions', 'flaky') +default_test_options = TestOptions(False) + +# maps test names to options +BAD_CLIENT_TESTS = { + 'cert': default_test_options, + 'alpn': default_test_options, +} + +def main(): + json = { + '#': 'generated with test/bad_ssl/gen_build_json.py', + 'libs': [ + { + 'name': 'bad_ssl_test_server', + 'build': 'private', + 'language': 'c', + 'src': ['test/core/bad_ssl/server.c'], + 'headers': ['test/core/bad_ssl/server.h'], + 'vs_proj_dir': 'test', + 'platforms': ['linux', 'posix', 'mac'], + 'deps': [ + 'grpc_test_util', + 'grpc', + 'gpr_test_util', + 'gpr' + ] + } + ], + 'targets': [ + { + 'name': 'bad_ssl_%s_server' % t, + 'build': 'test', + 'language': 'c', + 'run': False, + 'src': ['test/core/bad_ssl/servers/%s.c' % t], + 'vs_proj_dir': 'test', + 'platforms': ['linux', 'posix', 'mac'], + 'deps': [ + 'bad_ssl_test_server', + 'grpc_test_util', + 'grpc', + 'gpr_test_util', + 'gpr' + ] + } + for t in sorted(BAD_CLIENT_TESTS.keys())] + [ + { + 'name': 'bad_ssl_%s_test' % t, + 'build': 'test', + 'language': 'c', + 'src': ['test/core/bad_ssl/bad_ssl_test.c'], + 'vs_proj_dir': 'test', + 'platforms': ['linux', 'posix', 'mac'], + 'deps': [ + 'grpc_test_util', + 'grpc', + 'gpr_test_util', + 'gpr' + ] + } + for t in sorted(BAD_CLIENT_TESTS.keys())]} + print yaml.dump(json) + + +if __name__ == '__main__': + main() diff --git a/test/core/bad_ssl/server.c b/test/core/bad_ssl/server.c new file mode 100644 index 0000000000..2ed94de099 --- /dev/null +++ b/test/core/bad_ssl/server.c @@ -0,0 +1,114 @@ +/* + * + * Copyright 2015, 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 <grpc/support/cmdline.h> +#include <grpc/support/log.h> +#include <signal.h> + +#include "test/core/bad_ssl/server.h" +#include "test/core/util/test_config.h" + +/* Common server implementation details for all servers in servers/. + * There's nothing *wrong* with these servers per-se, but they are + * configured to cause some failure case in the SSL connection path. + */ + +static int got_sigint = 0; + +static void sigint_handler(int x) { got_sigint = 1; } + +const char *bad_ssl_addr(int argc, char **argv) { + gpr_cmdline *cl; + char *addr = NULL; + cl = gpr_cmdline_create("test server"); + gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + GPR_ASSERT(addr); + return addr; +} + +void bad_ssl_run(grpc_server *server) { + int shutdown_started = 0; + int shutdown_finished = 0; + grpc_event ev; + grpc_call_error error; + grpc_call *s = NULL; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_completion_queue *cq = grpc_completion_queue_create(NULL); + + grpc_call_details_init(&call_details); + grpc_metadata_array_init(&request_metadata_recv); + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + error = + grpc_server_request_call(server, &s, &call_details, + &request_metadata_recv, cq, cq, (void*)1); + GPR_ASSERT(GRPC_CALL_OK == error); + + signal(SIGINT, sigint_handler); + while (!shutdown_finished) { + if (got_sigint && !shutdown_started) { + gpr_log(GPR_INFO, "Shutting down due to SIGINT"); + grpc_server_shutdown_and_notify(server, cq, NULL); + GPR_ASSERT(grpc_completion_queue_pluck( + cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_shutdown(cq); + shutdown_started = 1; + } + ev = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000000, GPR_TIMESPAN)), + NULL); + switch (ev.type) { + case GRPC_OP_COMPLETE: + GPR_ASSERT(ev.tag == (void*)1); + GPR_ASSERT(ev.success == 0); + break; + case GRPC_QUEUE_SHUTDOWN: + GPR_ASSERT(shutdown_started); + shutdown_finished = 1; + break; + case GRPC_QUEUE_TIMEOUT: + break; + } + } + + GPR_ASSERT(s == NULL); + grpc_call_details_destroy(&call_details); + grpc_metadata_array_destroy(&request_metadata_recv); +} diff --git a/test/core/bad_ssl/server.h b/test/core/bad_ssl/server.h new file mode 100644 index 0000000000..8ec7755503 --- /dev/null +++ b/test/core/bad_ssl/server.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2015, 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_CORE_BAD_SSL_SERVER_H +#define GRPC_TEST_CORE_BAD_SSL_SERVER_H + +#include <grpc/grpc.h> + +const char *bad_ssl_addr(int argc, char **argv); +void bad_ssl_run(grpc_server *server); + +#endif /* GRPC_TEST_CORE_BAD_SSL_SERVER_H */ diff --git a/test/core/bad_ssl/servers/alpn.c b/test/core/bad_ssl/servers/alpn.c new file mode 100644 index 0000000000..7d70690e52 --- /dev/null +++ b/test/core/bad_ssl/servers/alpn.c @@ -0,0 +1,86 @@ +/* + * + * Copyright 2015, 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 <string.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/log.h> +#include <grpc/support/useful.h> + +#include "src/core/transport/chttp2/alpn.h" +#include "test/core/bad_ssl/server.h" +#include "test/core/end2end/data/ssl_test_data.h" + +/* This test starts a server that is configured to advertise (via alpn and npn) + * a protocol that the connecting client does not support. It does this by + * overriding the functions declared in alpn.c from the core library. */ + +static const char *const fake_versions[] = {"not-h2"}; + +int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size) { + size_t i; + for (i = 0; i < GPR_ARRAY_SIZE(fake_versions); i++) { + if (!strncmp(version, fake_versions[i], size)) return 1; + } + return 0; +} + +size_t grpc_chttp2_num_alpn_versions(void) { + return GPR_ARRAY_SIZE(fake_versions); +} + +const char *grpc_chttp2_get_alpn_version_index(size_t i) { + GPR_ASSERT(i < GPR_ARRAY_SIZE(fake_versions)); + return fake_versions[i]; +} + +int main(int argc, char **argv) { + const char *addr = bad_ssl_addr(argc, argv); + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds; + grpc_server *server; + + grpc_init(); + ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + + bad_ssl_run(server); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/bad_ssl/servers/cert.c b/test/core/bad_ssl/servers/cert.c new file mode 100644 index 0000000000..d67a6ca1d4 --- /dev/null +++ b/test/core/bad_ssl/servers/cert.c @@ -0,0 +1,79 @@ +/* + * + * Copyright 2015, 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 <string.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/log.h> +#include <grpc/support/useful.h> + +#include "src/core/support/file.h" + +#include "test/core/bad_ssl/server.h" +#include "test/core/end2end/data/ssl_test_data.h" + +/* This server will present an untrusted cert to the connecting client, + * causing the SSL handshake to fail */ + +int main(int argc, char **argv) { + const char *addr = bad_ssl_addr(argc, argv); + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_server_credentials *ssl_creds; + grpc_server *server; + gpr_slice cert_slice, key_slice; + int ok; + + grpc_init(); + + cert_slice = gpr_load_file("src/core/tsi/test_creds/badserver.pem", 1, &ok); + GPR_ASSERT(ok); + key_slice = gpr_load_file("src/core/tsi/test_creds/badserver.key", 1, &ok); + GPR_ASSERT(ok); + pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice); + + ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + + gpr_slice_unref(cert_slice); + gpr_slice_unref(key_slice); + + bad_ssl_run(server); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c index 9dbb879300..f1bb37c0bf 100644 --- a/test/core/channel/channel_stack_test.c +++ b/test/core/channel/channel_stack_test.c @@ -81,6 +81,16 @@ static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { return gpr_strdup("peer"); } +static void free_channel(grpc_exec_ctx *exec_ctx, void *arg, int success) { + grpc_channel_stack_destroy(exec_ctx, arg); + gpr_free(arg); +} + +static void free_call(grpc_exec_ctx *exec_ctx, void *arg, int success) { + grpc_call_stack_destroy(exec_ctx, arg); + gpr_free(arg); +} + static void test_create_channel_stack(void) { const grpc_channel_filter filter = { call_func, channel_func, sizeof(int), call_init_func, @@ -105,16 +115,16 @@ static void test_create_channel_stack(void) { chan_args.args = &arg; channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); - grpc_channel_stack_init(&exec_ctx, &filters, 1, NULL, &chan_args, - channel_stack); + grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, + 1, &chan_args, "test", channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; GPR_ASSERT(*channel_data == 0); call_stack = gpr_malloc(channel_stack->call_stack_size); - grpc_call_stack_init(&exec_ctx, channel_stack, 0, NULL, NULL, NULL, NULL, - call_stack); + grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL, + NULL, call_stack); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); @@ -123,12 +133,11 @@ static void test_create_channel_stack(void) { GPR_ASSERT(*call_data == 0); GPR_ASSERT(*channel_data == 1); - grpc_call_stack_destroy(&exec_ctx, call_stack); - gpr_free(call_stack); + GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); + grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(*channel_data == 2); - grpc_channel_stack_destroy(&exec_ctx, channel_stack); - gpr_free(channel_stack); + GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c index 175ebb6375..c088fe2c09 100644 --- a/test/core/client_config/lb_policies_test.c +++ b/test/core/client_config/lb_policies_test.c @@ -38,18 +38,19 @@ #include <grpc/support/alloc.h> #include <grpc/support/host_port.h> #include <grpc/support/log.h> -#include <grpc/support/time.h> #include <grpc/support/string_util.h> +#include <grpc/support/time.h> #include "src/core/channel/channel_stack.h" #include "src/core/channel/client_channel.h" +#include "src/core/client_config/lb_policies/round_robin.h" #include "src/core/client_config/lb_policy_registry.h" -#include "src/core/surface/channel.h" #include "src/core/support/string.h" +#include "src/core/surface/channel.h" #include "src/core/surface/server.h" -#include "test/core/util/test_config.h" -#include "test/core/util/port.h" #include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" typedef struct servers_fixture { size_t num_servers; @@ -226,8 +227,8 @@ static void teardown_servers(servers_fixture *f) { } /** Returns connection sequence (server indices), which must be freed */ -int *perform_request(servers_fixture *f, grpc_channel *client, - request_data *rdata, const test_spec *spec) { +static int *perform_request(servers_fixture *f, grpc_channel *client, + request_data *rdata, const test_spec *spec) { grpc_call *c; int s_idx; int *s_valid; @@ -243,8 +244,6 @@ int *perform_request(servers_fixture *f, grpc_channel *client, s_valid = gpr_malloc(sizeof(int) * f->num_servers); connection_sequence = gpr_malloc(sizeof(int) * spec->num_iters); - /* Send a trivial request. */ - for (iter_num = 0; iter_num < spec->num_iters; iter_num++) { cq_verifier *cqv = cq_verifier_create(f->cq); rdata->details = NULL; @@ -325,8 +324,6 @@ int *perform_request(servers_fixture *f, grpc_channel *client, } } - gpr_log(GPR_DEBUG, "s_idx=%d", s_idx); - if (s_idx >= 0) { op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; @@ -372,7 +369,7 @@ int *perform_request(servers_fixture *f, grpc_channel *client, &rdata->call_details[s_idx], &f->request_metadata_recv[s_idx], f->cq, f->cq, tag(1000 + (int)s_idx))); - } else { + } else { /* no response from server */ grpc_call_cancel(c, NULL); if (!completed_client) { cq_expect_completion(cqv, tag(1), 1); @@ -380,6 +377,9 @@ int *perform_request(servers_fixture *f, grpc_channel *client, } } + GPR_ASSERT(grpc_completion_queue_next( + f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(200), NULL).type == GRPC_QUEUE_TIMEOUT); + grpc_metadata_array_destroy(&rdata->initial_metadata_recv); grpc_metadata_array_destroy(&rdata->trailing_metadata_recv); @@ -398,6 +398,42 @@ int *perform_request(servers_fixture *f, grpc_channel *client, return connection_sequence; } +static grpc_call **perform_multirequest(servers_fixture *f, + grpc_channel *client, + size_t concurrent_calls) { + grpc_call **calls; + grpc_op ops[6]; + grpc_op *op; + size_t i; + + calls = gpr_malloc(sizeof(grpc_call *) * concurrent_calls); + for (i = 0; i < f->num_servers; i++) { + kill_server(f, i); + } + + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + + for (i = 0; i < concurrent_calls; i++) { + calls[i] = grpc_channel_create_call( + client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo", + "foo.test.google.fr", gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(calls[i]); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[i], ops, + (size_t)(op - ops), tag(1), + NULL)); + } + + return calls; +} + static void assert_channel_connectivity( grpc_channel *ch, size_t num_accepted_conn_states, grpc_connectivity_state accepted_conn_state, ...) { @@ -488,8 +524,110 @@ void run_spec(const test_spec *spec) { gpr_free(actual_connection_sequence); gpr_free(rdata.call_details); + grpc_channel_destroy(client); /* calls the LB's shutdown func */ + teardown_servers(f); +} + +static grpc_channel *create_client(const servers_fixture *f) { + grpc_channel *client; + char *client_hostport; + char *servers_hostports_str; + grpc_arg arg; + grpc_channel_args args; + + servers_hostports_str = gpr_strjoin_sep((const char **)f->servers_hostports, + f->num_servers, ",", NULL); + gpr_asprintf(&client_hostport, "ipv4:%s?lb_policy=round_robin", + servers_hostports_str); + + arg.type = GRPC_ARG_INTEGER; + arg.key = "grpc.testing.fixed_reconnect_backoff"; + arg.value.integer = 100; + args.num_args = 1; + args.args = &arg; + + client = grpc_insecure_channel_create(client_hostport, &args, NULL); + gpr_free(client_hostport); + gpr_free(servers_hostports_str); + + return client; +} + +static void test_ping() { + grpc_channel *client; + request_data rdata; + servers_fixture *f; + cq_verifier *cqv; + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + const size_t num_servers = 1; + int i; + + rdata.call_details = gpr_malloc(sizeof(grpc_call_details) * num_servers); + f = setup_servers("127.0.0.1", &rdata, num_servers); + cqv = cq_verifier_create(f->cq); + + client = create_client(f); + + grpc_channel_ping(client, f->cq, tag(0), NULL); + cq_expect_completion(cqv, tag(0), 0); + + /* check that we're still in idle, and start connecting */ + GPR_ASSERT(grpc_channel_check_connectivity_state(client, 1) == + GRPC_CHANNEL_IDLE); + /* we'll go through some set of transitions (some might be missed), until + READY is reached */ + while (state != GRPC_CHANNEL_READY) { + grpc_channel_watch_connectivity_state( + client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f->cq, tag(99)); + cq_expect_completion(cqv, tag(99), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_READY || + state == GRPC_CHANNEL_CONNECTING || + state == GRPC_CHANNEL_TRANSIENT_FAILURE); + } + + for (i = 1; i <= 5; i++) { + grpc_channel_ping(client, f->cq, tag(i), NULL); + cq_expect_completion(cqv, tag(i), 1); + cq_verify(cqv); + } + gpr_free(rdata.call_details); + grpc_channel_destroy(client); teardown_servers(f); + + cq_verifier_destroy(cqv); +} + +static void test_pending_calls(size_t concurrent_calls) { + size_t i; + grpc_call **calls; + grpc_channel *client; + request_data rdata; + servers_fixture *f; + test_spec *spec = test_spec_create(0, 4); + rdata.call_details = + gpr_malloc(sizeof(grpc_call_details) * spec->num_servers); + f = setup_servers("127.0.0.1", &rdata, spec->num_servers); + + client = create_client(f); + calls = perform_multirequest(f, client, concurrent_calls); + grpc_call_cancel( + calls[0], + NULL); /* exercise the cancel pick path whilst there are pending picks */ + + gpr_free(rdata.call_details); + + grpc_channel_destroy(client); /* calls the LB's shutdown func */ + /* destroy the calls after the channel so that they are still around for the + * LB's shutdown func to process */ + for (i = 0; i < concurrent_calls; i++) { + grpc_call_destroy(calls[i]); + } + gpr_free(calls); + teardown_servers(f); + test_spec_destroy(spec); } static void print_failed_expectations(const int *expected_connection_sequence, @@ -636,6 +774,23 @@ static void verify_partial_carnage_round_robin( gpr_free(expected_connection_sequence); } +static void dump_array(const char *desc, const int *data, const size_t count) { + gpr_strvec s; + char *tmp; + size_t i; + gpr_strvec_init(&s); + gpr_strvec_add(&s, gpr_strdup(desc)); + gpr_strvec_add(&s, gpr_strdup(":")); + for (i = 0; i < count; i++) { + gpr_asprintf(&tmp, " %d", data[i]); + gpr_strvec_add(&s, tmp); + } + tmp = gpr_strvec_flatten(&s, NULL); + gpr_strvec_destroy(&s); + gpr_log(GPR_DEBUG, "%s", tmp); + gpr_free(tmp); +} + static void verify_rebirth_round_robin(const servers_fixture *f, grpc_channel *client, const int *actual_connection_sequence, @@ -643,7 +798,9 @@ static void verify_rebirth_round_robin(const servers_fixture *f, int *expected_connection_sequence; size_t i, j, unique_seq_last_idx, unique_seq_first_idx; const size_t expected_seq_length = f->num_servers; - uint8_t *seen_elements; + int *seen_elements; + + dump_array("actual_connection_sequence", actual_connection_sequence, num_iters); /* verify conn. seq. expectation */ /* get the first unique run of length "num_servers". */ @@ -652,12 +809,12 @@ static void verify_rebirth_round_robin(const servers_fixture *f, unique_seq_last_idx = ~(size_t)0; - memset(seen_elements, 0, sizeof(uint8_t) * expected_seq_length); + memset(seen_elements, 0, sizeof(int) * expected_seq_length); for (i = 0; i < num_iters; i++) { if (actual_connection_sequence[i] < 0 || seen_elements[actual_connection_sequence[i]] != 0) { /* if anything breaks the uniqueness of the run, back to square zero */ - memset(seen_elements, 0, sizeof(uint8_t) * expected_seq_length); + memset(seen_elements, 0, sizeof(int) * expected_seq_length); continue; } seen_elements[actual_connection_sequence[i]] = 1; @@ -670,6 +827,7 @@ static void verify_rebirth_round_robin(const servers_fixture *f, } } /* make sure we found a valid run */ + dump_array("seen_elements", seen_elements, expected_seq_length); for (j = 0; j < expected_seq_length; j++) { GPR_ASSERT(seen_elements[j] != 0); } @@ -716,12 +874,14 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); + grpc_lb_round_robin_trace = 1; - GPR_ASSERT(grpc_lb_policy_create("this-lb-policy-does-not-exist", NULL) == NULL); + GPR_ASSERT(grpc_lb_policy_create("this-lb-policy-does-not-exist", NULL) == + NULL); GPR_ASSERT(grpc_lb_policy_create(NULL, NULL) == NULL); - /* everything is fine, all servers stay up the whole time and life's peachy */ spec = test_spec_create(NUM_ITERS, NUM_SERVERS); + /* everything is fine, all servers stay up the whole time and life's peachy */ spec->verifier = verify_vanilla_round_robin; spec->description = "test_all_server_up"; run_spec(spec); @@ -735,7 +895,8 @@ int main(int argc, char **argv) { } run_spec(spec); - /* at the start of the 2nd iteration, kill all but the first and last servers. + /* at the start of the 2nd iteration, kill all but the first and last + * servers. * This should knock down the server bound to be selected next */ test_spec_reset(spec); spec->verifier = verify_vanishing_floor_round_robin; @@ -764,9 +925,11 @@ int main(int argc, char **argv) { spec->revive_at[3][i] = 1; } run_spec(spec); - test_spec_destroy(spec); + test_pending_calls(4); + test_ping(); + grpc_shutdown(); return 0; } diff --git a/test/core/client_config/resolvers/dns_resolver_test.c b/test/core/client_config/resolvers/dns_resolver_test.c new file mode 100644 index 0000000000..38e76d5342 --- /dev/null +++ b/test/core/client_config/resolvers/dns_resolver_test.c @@ -0,0 +1,106 @@ +/* + * + * Copyright 2015, 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 "src/core/client_config/resolvers/dns_resolver.h" + +#include <string.h> + +#include <grpc/support/log.h> + +#include "src/core/client_config/resolver.h" +#include "test/core/util/test_config.h" + +static void subchannel_factory_ref(grpc_subchannel_factory *scv) {} +static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_subchannel_factory *scv) {} +static grpc_subchannel *subchannel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, + grpc_subchannel_args *args) { + GPR_UNREACHABLE_CODE(return NULL); +} + +static const grpc_subchannel_factory_vtable sc_vtable = { + subchannel_factory_ref, subchannel_factory_unref, + subchannel_factory_create_subchannel}; + +static grpc_subchannel_factory sc_factory = {&sc_vtable}; + +static void test_succeeds(grpc_resolver_factory *factory, const char *string) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(string, 0); + grpc_resolver_args args; + grpc_resolver *resolver; + gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string, + factory->vtable->scheme); + GPR_ASSERT(uri); + memset(&args, 0, sizeof(args)); + args.uri = uri; + args.subchannel_factory = &sc_factory; + resolver = grpc_resolver_factory_create_resolver(factory, &args); + GPR_ASSERT(resolver != NULL); + GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_fails(grpc_resolver_factory *factory, const char *string) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(string, 0); + grpc_resolver_args args; + grpc_resolver *resolver; + gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string, + factory->vtable->scheme); + GPR_ASSERT(uri); + memset(&args, 0, sizeof(args)); + args.uri = uri; + resolver = grpc_resolver_factory_create_resolver(factory, &args); + GPR_ASSERT(resolver == NULL); + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_resolver_factory *dns; + grpc_test_init(argc, argv); + + dns = grpc_dns_resolver_factory_create(); + + test_succeeds(dns, "dns:10.2.1.1"); + test_succeeds(dns, "dns:10.2.1.1:1234"); + test_succeeds(dns, "ipv4:www.google.com"); + test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); + + grpc_resolver_factory_unref(dns); + + return 0; +} diff --git a/test/core/client_config/resolvers/sockaddr_resolver_test.c b/test/core/client_config/resolvers/sockaddr_resolver_test.c new file mode 100644 index 0000000000..8856c85449 --- /dev/null +++ b/test/core/client_config/resolvers/sockaddr_resolver_test.c @@ -0,0 +1,116 @@ +/* + * + * Copyright 2015, 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 "src/core/client_config/resolvers/sockaddr_resolver.h" + +#include <string.h> + +#include <grpc/support/log.h> + +#include "src/core/client_config/resolver.h" +#include "test/core/util/test_config.h" + +static void subchannel_factory_ref(grpc_subchannel_factory *scv) {} +static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_subchannel_factory *scv) {} +static grpc_subchannel *subchannel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, + grpc_subchannel_args *args) { + GPR_UNREACHABLE_CODE(return NULL); +} + +static const grpc_subchannel_factory_vtable sc_vtable = { + subchannel_factory_ref, subchannel_factory_unref, + subchannel_factory_create_subchannel}; + +static grpc_subchannel_factory sc_factory = {&sc_vtable}; + +static void test_succeeds(grpc_resolver_factory *factory, const char *string) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(string, 0); + grpc_resolver_args args; + grpc_resolver *resolver; + gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string, + factory->vtable->scheme); + GPR_ASSERT(uri); + memset(&args, 0, sizeof(args)); + args.uri = uri; + args.subchannel_factory = &sc_factory; + resolver = grpc_resolver_factory_create_resolver(factory, &args); + GPR_ASSERT(resolver != NULL); + GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_fails(grpc_resolver_factory *factory, const char *string) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(string, 0); + grpc_resolver_args args; + grpc_resolver *resolver; + gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string, + factory->vtable->scheme); + GPR_ASSERT(uri); + memset(&args, 0, sizeof(args)); + args.uri = uri; + resolver = grpc_resolver_factory_create_resolver(factory, &args); + GPR_ASSERT(resolver == NULL); + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_resolver_factory *ipv4, *ipv6; + grpc_test_init(argc, argv); + + ipv4 = grpc_ipv4_resolver_factory_create(); + ipv6 = grpc_ipv6_resolver_factory_create(); + + test_fails(ipv4, "ipv4:10.2.1.1"); + test_succeeds(ipv4, "ipv4:10.2.1.1:1234"); + test_fails(ipv4, "ipv4:10.2.1.1:123456"); + test_fails(ipv4, "ipv4:www.google.com"); + test_fails(ipv4, "ipv4:["); + test_fails(ipv4, "ipv4://8.8.8.8/8.8.8.8:8888"); + + test_fails(ipv6, "ipv6:["); + test_fails(ipv6, "ipv6:[::]"); + test_succeeds(ipv6, "ipv6:[::]:1234"); + test_fails(ipv6, "ipv6:[::]:123456"); + test_fails(ipv6, "ipv6:www.google.com"); + + grpc_resolver_factory_unref(ipv4); + grpc_resolver_factory_unref(ipv6); + + return 0; +} diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c new file mode 100644 index 0000000000..7de7e11a94 --- /dev/null +++ b/test/core/compression/algorithm_test.c @@ -0,0 +1,104 @@ +/* + * + * Copyright 2015, 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 "src/core/compression/algorithm_metadata.h" + +#include <stdlib.h> +#include <string.h> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc/support/useful.h> + +#include "src/core/transport/static_metadata.h" +#include "test/core/util/test_config.h" + +static void test_algorithm_mesh(void) { + int i; + + gpr_log(GPR_DEBUG, "test_algorithm_mesh"); + + for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + char *name; + grpc_compression_algorithm parsed; + grpc_mdstr *mdstr; + grpc_mdelem *mdelem; + GPR_ASSERT( + grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name)); + GPR_ASSERT(grpc_compression_algorithm_parse(name, strlen(name), &parsed)); + GPR_ASSERT((int)parsed == i); + mdstr = grpc_mdstr_from_string(name); + GPR_ASSERT(mdstr == grpc_compression_algorithm_mdstr(parsed)); + GPR_ASSERT(parsed == grpc_compression_algorithm_from_mdstr(mdstr)); + mdelem = grpc_compression_encoding_mdelem(parsed); + GPR_ASSERT(mdelem->value == mdstr); + GPR_ASSERT(mdelem->key == GRPC_MDSTR_GRPC_ENCODING); + GRPC_MDSTR_UNREF(mdstr); + GRPC_MDELEM_UNREF(mdelem); + } + + /* test failure */ + GPR_ASSERT(NULL == + grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT)); +} + +static void test_algorithm_failure(void) { + grpc_mdstr *mdstr; + + gpr_log(GPR_DEBUG, "test_algorithm_failure"); + + GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT, + NULL) == 0); + GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1, + NULL) == 0); + mdstr = grpc_mdstr_from_string("this-is-an-invalid-algorithm"); + GPR_ASSERT(grpc_compression_algorithm_from_mdstr(mdstr) == + GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT) == + NULL); + GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT + + 1) == NULL); + GRPC_MDSTR_UNREF(mdstr); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_algorithm_mesh(); + test_algorithm_failure(); + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/compression/compression_test.c b/test/core/compression/compression_test.c index 35fadc00c0..26d7b2b6cc 100644 --- a/test/core/compression/compression_test.c +++ b/test/core/compression/compression_test.c @@ -53,9 +53,8 @@ static void test_compression_algorithm_parse(void) { for (i = 0; i < GPR_ARRAY_SIZE(valid_names); i++) { const char *valid_name = valid_names[i]; grpc_compression_algorithm algorithm; - int success; - success = grpc_compression_algorithm_parse(valid_name, strlen(valid_name), - &algorithm); + const int success = grpc_compression_algorithm_parse( + valid_name, strlen(valid_name), &algorithm); GPR_ASSERT(success != 0); GPR_ASSERT(algorithm == valid_algorithms[i]); } @@ -71,9 +70,79 @@ static void test_compression_algorithm_parse(void) { } } +static void test_compression_algorithm_name(void) { + int success; + char *name; + size_t i; + const char *valid_names[] = {"identity", "gzip", "deflate"}; + const grpc_compression_algorithm valid_algorithms[] = { + GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_DEFLATE}; + + gpr_log(GPR_DEBUG, "test_compression_algorithm_name"); + + for (i = 0; i < GPR_ARRAY_SIZE(valid_algorithms); i++) { + success = grpc_compression_algorithm_name(valid_algorithms[i], &name); + GPR_ASSERT(success != 0); + GPR_ASSERT(strcmp(name, valid_names[i]) == 0); + } + + success = + grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT, &name); + GPR_ASSERT(success == 0); + /* the value of "name" is undefined upon failure */ +} + +static void test_compression_algorithm_for_level(void) { + size_t i; + grpc_compression_level levels[] = { + GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_LOW, + GRPC_COMPRESS_LEVEL_MED, GRPC_COMPRESS_LEVEL_HIGH}; + grpc_compression_algorithm algorithms[] = { + GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_DEFLATE, + GRPC_COMPRESS_DEFLATE}; + gpr_log(GPR_DEBUG, "test_compression_algorithm_for_level"); + + for (i = 0; i < GPR_ARRAY_SIZE(levels); i++) { + GPR_ASSERT(algorithms[i] == + grpc_compression_algorithm_for_level(levels[i])); + } +} + +static void test_compression_enable_disable_algorithm(void) { + grpc_compression_options options; + grpc_compression_algorithm algorithm; + + gpr_log(GPR_DEBUG, "test_compression_enable_disable_algorithm"); + + grpc_compression_options_init(&options); + for (algorithm = GRPC_COMPRESS_NONE; + algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT; algorithm++) { + /* all algorithms are enabled by default */ + GPR_ASSERT(grpc_compression_options_is_algorithm_enabled(&options, + algorithm) != 0); + } + /* disable one by one */ + for (algorithm = GRPC_COMPRESS_NONE; + algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT; algorithm++) { + grpc_compression_options_disable_algorithm(&options, algorithm); + GPR_ASSERT(grpc_compression_options_is_algorithm_enabled(&options, + algorithm) == 0); + } + /* re-enable one by one */ + for (algorithm = GRPC_COMPRESS_NONE; + algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT; algorithm++) { + grpc_compression_options_enable_algorithm(&options, algorithm); + GPR_ASSERT(grpc_compression_options_is_algorithm_enabled(&options, + algorithm) != 0); + } +} + int main(int argc, char **argv) { grpc_init(); test_compression_algorithm_parse(); + test_compression_algorithm_name(); + test_compression_algorithm_for_level(); + test_compression_enable_disable_algorithm(); grpc_shutdown(); return 0; diff --git a/test/core/compression/message_compress_test.c b/test/core/compression/message_compress_test.c index 70359a3f69..e5a01ef69e 100644 --- a/test/core/compression/message_compress_test.c +++ b/test/core/compression/message_compress_test.c @@ -148,26 +148,87 @@ static gpr_slice create_test_value(test_value id) { return gpr_slice_from_copied_string("bad value"); } -static void test_bad_data(void) { +static void test_tiny_data_compress(void) { gpr_slice_buffer input; gpr_slice_buffer output; grpc_compression_algorithm i; gpr_slice_buffer_init(&input); gpr_slice_buffer_init(&output); - gpr_slice_buffer_add(&input, gpr_slice_from_copied_string( - "this is not valid compressed input")); + gpr_slice_buffer_add(&input, create_test_value(ONE_A)); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { if (i == GRPC_COMPRESS_NONE) continue; - GPR_ASSERT(0 == grpc_msg_decompress(i, &input, &output)); - GPR_ASSERT(0 == output.count); + GPR_ASSERT(0 == grpc_msg_compress(i, &input, &output)); + GPR_ASSERT(1 == output.count); } gpr_slice_buffer_destroy(&input); gpr_slice_buffer_destroy(&output); } +static void test_bad_decompression_data_crc(void) { + gpr_slice_buffer input; + gpr_slice_buffer corrupted; + gpr_slice_buffer output; + size_t idx; + const gpr_uint32 bad = 0xdeadbeef; + + gpr_slice_buffer_init(&input); + gpr_slice_buffer_init(&corrupted); + gpr_slice_buffer_init(&output); + gpr_slice_buffer_add(&input, create_test_value(ONE_MB_A)); + + /* compress it */ + grpc_msg_compress(GRPC_COMPRESS_GZIP, &input, &corrupted); + /* corrupt the output by smashing the CRC */ + GPR_ASSERT(corrupted.count > 1); + GPR_ASSERT(GPR_SLICE_LENGTH(corrupted.slices[1]) > 8); + idx = GPR_SLICE_LENGTH(corrupted.slices[1]) - 8; + memcpy(GPR_SLICE_START_PTR(corrupted.slices[1]) + idx, &bad, 4); + + /* try (and fail) to decompress the corrupted compresed buffer */ + GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_GZIP, &corrupted, &output)); + + gpr_slice_buffer_destroy(&input); + gpr_slice_buffer_destroy(&corrupted); + gpr_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_data_trailing_garbage(void) { + gpr_slice_buffer input; + gpr_slice_buffer output; + + gpr_slice_buffer_init(&input); + gpr_slice_buffer_init(&output); + /* append 0x99 to the end of an otherwise valid stream */ + gpr_slice_buffer_add( + &input, gpr_slice_from_copied_buffer( + "\x78\xda\x63\x60\x60\x60\x00\x00\x00\x04\x00\x01\x99", 13)); + + /* try (and fail) to decompress the invalid compresed buffer */ + GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_DEFLATE, &input, &output)); + + gpr_slice_buffer_destroy(&input); + gpr_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_data_stream(void) { + gpr_slice_buffer input; + gpr_slice_buffer output; + + gpr_slice_buffer_init(&input); + gpr_slice_buffer_init(&output); + gpr_slice_buffer_add(&input, + gpr_slice_from_copied_buffer("\x78\xda\xff\xff", 4)); + + /* try (and fail) to decompress the invalid compresed buffer */ + GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_DEFLATE, &input, &output)); + + gpr_slice_buffer_destroy(&input); + gpr_slice_buffer_destroy(&output); +} + static void test_bad_compression_algorithm(void) { gpr_slice_buffer input; gpr_slice_buffer output; @@ -175,8 +236,8 @@ static void test_bad_compression_algorithm(void) { gpr_slice_buffer_init(&input); gpr_slice_buffer_init(&output); - gpr_slice_buffer_add(&input, gpr_slice_from_copied_string( - "Never gonna give you up")); + gpr_slice_buffer_add(&input, + gpr_slice_from_copied_string("Never gonna give you up")); was_compressed = grpc_msg_compress(GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); GPR_ASSERT(0 == was_compressed); @@ -203,8 +264,8 @@ static void test_bad_decompression_algorithm(void) { grpc_msg_decompress(GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); GPR_ASSERT(0 == was_decompressed); - was_decompressed = - grpc_msg_decompress(GRPC_COMPRESS_ALGORITHMS_COUNT + 123, &input, &output); + was_decompressed = grpc_msg_decompress(GRPC_COMPRESS_ALGORITHMS_COUNT + 123, + &input, &output); GPR_ASSERT(0 == was_decompressed); gpr_slice_buffer_destroy(&input); @@ -234,7 +295,10 @@ int main(int argc, char **argv) { } } - test_bad_data(); + test_tiny_data_compress(); + test_bad_decompression_data_crc(); + test_bad_decompression_data_stream(); + test_bad_decompression_data_trailing_garbage(); test_bad_compression_algorithm(); test_bad_decompression_algorithm(); grpc_shutdown(); diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c new file mode 100644 index 0000000000..90f3713cc8 --- /dev/null +++ b/test/core/end2end/fixtures/h2_census.c @@ -0,0 +1,132 @@ +/* + * + * Copyright 2015, 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 "test/core/end2end/end2end_tests.h" + +#include <string.h> + +#include "src/core/channel/channel_args.h" +#include "src/core/channel/client_channel.h" +#include "src/core/channel/connected_channel.h" +#include "src/core/channel/http_server_filter.h" +#include "src/core/surface/channel.h" +#include "src/core/surface/server.h" +#include "src/core/transport/chttp2_transport.h" +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include <grpc/support/useful.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_fixture_data { + char *localaddr; +} fullstack_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); + memset(&f, 0, sizeof(f)); + + gpr_join_host_port(&ffd->localaddr, "localhost", port); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create(NULL); + + return f; +} + +static grpc_arg make_census_enable_arg(void) { + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = GRPC_ARG_ENABLE_CENSUS; + arg.value.integer = 1; + return arg; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = f->fixture_data; + grpc_arg arg = make_census_enable_arg(); + client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1); + f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL); + grpc_channel_args_destroy(client_args); + GPR_ASSERT(f->client); +} + +void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + fullstack_fixture_data *ffd = f->fixture_data; + grpc_arg arg = make_census_enable_arg(); + if (f->server) { + grpc_server_destroy(f->server); + } + server_args = grpc_channel_args_copy_and_add(server_args, &arg, 1); + f->server = grpc_server_create(server_args, NULL); + grpc_channel_args_destroy(server_args); + grpc_server_register_completion_queue(f->server, f->cq, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr)); + grpc_server_start(f->server); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = f->fixture_data; + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + chttp2_create_fixture_fullstack, chttp2_init_client_fullstack, + chttp2_init_server_fullstack, chttp2_tear_down_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_full+pipe.c b/test/core/end2end/fixtures/h2_full+pipe.c new file mode 100644 index 0000000000..83cde49305 --- /dev/null +++ b/test/core/end2end/fixtures/h2_full+pipe.c @@ -0,0 +1,120 @@ +/* + * + * Copyright 2015, 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 "test/core/end2end/end2end_tests.h" + +#include <string.h> + +#include "src/core/channel/client_channel.h" +#include "src/core/channel/connected_channel.h" +#include "src/core/channel/http_server_filter.h" +#include "src/core/surface/channel.h" +#include "src/core/surface/server.h" +#include "src/core/transport/chttp2_transport.h" +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include <grpc/support/useful.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "src/core/iomgr/wakeup_fd_posix.h" + +typedef struct fullstack_fixture_data { + char *localaddr; +} fullstack_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); + memset(&f, 0, sizeof(f)); + + gpr_join_host_port(&ffd->localaddr, "localhost", port); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = f->fixture_data; + f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL); + GPR_ASSERT(f->client); +} + +void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + fullstack_fixture_data *ffd = f->fixture_data; + if (f->server) { + grpc_server_destroy(f->server); + } + f->server = grpc_server_create(server_args, NULL); + grpc_server_register_completion_queue(f->server, f->cq, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr)); + grpc_server_start(f->server); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = f->fixture_data; + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + chttp2_create_fixture_fullstack, chttp2_init_client_fullstack, + chttp2_init_server_fullstack, chttp2_tear_down_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_allow_specialized_wakeup_fd = 0; + + grpc_test_init(argc, argv); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_full+poll+pipe.c b/test/core/end2end/fixtures/h2_full+poll+pipe.c new file mode 100644 index 0000000000..ffae11f90d --- /dev/null +++ b/test/core/end2end/fixtures/h2_full+poll+pipe.c @@ -0,0 +1,120 @@ +/* + * + * Copyright 2015, 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 "test/core/end2end/end2end_tests.h" + +#include <string.h> + +#include "src/core/channel/client_channel.h" +#include "src/core/channel/connected_channel.h" +#include "src/core/channel/http_server_filter.h" +#include "src/core/surface/channel.h" +#include "src/core/surface/server.h" +#include "src/core/transport/chttp2_transport.h" +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include <grpc/support/useful.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "src/core/iomgr/wakeup_fd_posix.h" + +typedef struct fullstack_fixture_data { + char *localaddr; +} fullstack_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); + memset(&f, 0, sizeof(f)); + + gpr_join_host_port(&ffd->localaddr, "localhost", port); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = f->fixture_data; + f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL); +} + +void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + fullstack_fixture_data *ffd = f->fixture_data; + if (f->server) { + grpc_server_destroy(f->server); + } + f->server = grpc_server_create(server_args, NULL); + grpc_server_register_completion_queue(f->server, f->cq, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr)); + grpc_server_start(f->server); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = f->fixture_data; + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + chttp2_create_fixture_fullstack, chttp2_init_client_fullstack, + chttp2_init_server_fullstack, chttp2_tear_down_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_allow_specialized_wakeup_fd = 0; + grpc_platform_become_multipoller = grpc_poll_become_multipoller; + + grpc_test_init(argc, argv); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_uchannel.c b/test/core/end2end/fixtures/h2_uchannel.c index ee4a60c29a..ea630c3275 100644 --- a/test/core/end2end/fixtures/h2_uchannel.c +++ b/test/core/end2end/fixtures/h2_uchannel.c @@ -159,11 +159,14 @@ static grpc_subchannel *subchannel_factory_create_subchannel( c->base.vtable = &connector_vtable; gpr_ref_init(&c->refs, 1); args->args = final_args; - args->master = f->master; s = grpc_subchannel_create(&c->base, args); grpc_connector_unref(exec_ctx, &c->base); grpc_channel_args_destroy(final_args); + if (*f->sniffed_subchannel) { + GRPC_SUBCHANNEL_UNREF(exec_ctx, *f->sniffed_subchannel, "sniffed"); + } *f->sniffed_subchannel = s; + GRPC_SUBCHANNEL_REF(s, "sniffed"); return s; } @@ -224,6 +227,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_micro_fullstack( micro_fullstack_fixture_data *ffd = gpr_malloc(sizeof(micro_fullstack_fixture_data)); memset(&f, 0, sizeof(f)); + memset(ffd, 0, sizeof(*ffd)); gpr_join_host_port(&ffd->localaddr, "127.0.0.1", port); @@ -233,10 +237,54 @@ static grpc_end2end_test_fixture chttp2_create_fixture_micro_fullstack( return f; } +grpc_connectivity_state g_state = GRPC_CHANNEL_IDLE; +grpc_pollset_set g_interested_parties; + +static void state_changed(grpc_exec_ctx *exec_ctx, void *arg, int success) { + if (g_state != GRPC_CHANNEL_READY) { + grpc_subchannel_notify_on_state_change( + exec_ctx, arg, &g_interested_parties, &g_state, + grpc_closure_create(state_changed, arg)); + } +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *arg, int success) { + grpc_pollset_destroy(arg); +} + +static grpc_connected_subchannel *connect_subchannel(grpc_subchannel *c) { + grpc_pollset pollset; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_init(&pollset); + grpc_pollset_set_init(&g_interested_parties); + grpc_pollset_set_add_pollset(&exec_ctx, &g_interested_parties, &pollset); + grpc_subchannel_notify_on_state_change(&exec_ctx, c, &g_interested_parties, + &g_state, + grpc_closure_create(state_changed, c)); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&pollset)); + while (g_state != GRPC_CHANNEL_READY) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), + GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)); + gpr_mu_unlock(GRPC_POLLSET_MU(&pollset)); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&pollset)); + } + grpc_pollset_shutdown(&exec_ctx, &pollset, + grpc_closure_create(destroy_pollset, &pollset)); + grpc_pollset_set_destroy(&g_interested_parties); + gpr_mu_unlock(GRPC_POLLSET_MU(&pollset)); + grpc_exec_ctx_finish(&exec_ctx); + return grpc_subchannel_get_connected_subchannel(c); +} + static void chttp2_init_client_micro_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { micro_fullstack_fixture_data *ffd = f->fixture_data; grpc_connectivity_state conn_state; + grpc_connected_subchannel *connected; char *ipv4_localaddr; gpr_asprintf(&ipv4_localaddr, "ipv4:%s", ffd->localaddr); @@ -252,8 +300,10 @@ static void chttp2_init_client_micro_fullstack(grpc_end2end_test_fixture *f, /* here sniffed_subchannel should be ready to use */ GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE); GPR_ASSERT(ffd->sniffed_subchannel != NULL); + + connected = connect_subchannel(ffd->sniffed_subchannel); f->client = grpc_client_uchannel_create(ffd->sniffed_subchannel, client_args); - grpc_client_uchannel_set_subchannel(f->client, ffd->sniffed_subchannel); + grpc_client_uchannel_set_connected_subchannel(f->client, connected); gpr_log(GPR_INFO, "CHANNEL WRAPPING SUBCHANNEL: %p(%p)", f->client, ffd->sniffed_subchannel); @@ -273,18 +323,22 @@ static void chttp2_init_server_micro_fullstack(grpc_end2end_test_fixture *f, } static void chttp2_tear_down_micro_fullstack(grpc_end2end_test_fixture *f) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; micro_fullstack_fixture_data *ffd = f->fixture_data; grpc_channel_destroy(ffd->master_channel); - ffd->master_channel = NULL; + if (ffd->sniffed_subchannel) { + GRPC_SUBCHANNEL_UNREF(&exec_ctx, ffd->sniffed_subchannel, "sniffed"); + } gpr_free(ffd->localaddr); gpr_free(ffd); + grpc_exec_ctx_finish(&exec_ctx); } /* All test configurations */ static grpc_end2end_test_config configs[] = { - {"chttp2/micro_fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, - chttp2_create_fixture_micro_fullstack, chttp2_init_client_micro_fullstack, - chttp2_init_server_micro_fullstack, chttp2_tear_down_micro_fullstack}, + {"chttp2/micro_fullstack", 0, chttp2_create_fixture_micro_fullstack, + chttp2_init_client_micro_fullstack, chttp2_init_server_micro_fullstack, + chttp2_tear_down_micro_fullstack}, }; int main(int argc, char **argv) { diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 6cb4a7a91d..9f94cfe6be 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -50,10 +50,15 @@ uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=Fal # maps fixture name to whether it requires the security library END2END_FIXTURES = { 'h2_compress': default_unsecure_fixture_options, + 'h2_census': default_unsecure_fixture_options, 'h2_fakesec': default_secure_fixture_options._replace(ci_mac=False), 'h2_full': default_unsecure_fixture_options, 'h2_full+poll': default_unsecure_fixture_options._replace( platforms=['linux']), + 'h2_full+pipe': default_unsecure_fixture_options._replace( + platforms=['linux']), + 'h2_full+poll+pipe': default_unsecure_fixture_options._replace( + platforms=['linux']), 'h2_oauth2': default_secure_fixture_options._replace(ci_mac=False), 'h2_proxy': default_unsecure_fixture_options._replace(includes_proxy=True, ci_mac=False), @@ -66,7 +71,7 @@ END2END_FIXTURES = { 'h2_ssl+poll': default_secure_fixture_options._replace(platforms=['linux']), 'h2_ssl_proxy': default_secure_fixture_options._replace(includes_proxy=True, ci_mac=False), - 'h2_uchannel': default_unsecure_fixture_options, + 'h2_uchannel': default_unsecure_fixture_options._replace(fullstack=False), 'h2_uds+poll': uds_fixture_options._replace(platforms=['linux']), 'h2_uds': uds_fixture_options, } @@ -87,8 +92,8 @@ END2END_TESTS = { 'cancel_before_invoke': default_test_options, 'cancel_in_a_vacuum': default_test_options, 'cancel_with_status': default_test_options, - 'census_simple_request': default_test_options, 'channel_connectivity': connectivity_test_options._replace(proxyable=False), + 'channel_ping': connectivity_test_options._replace(proxyable=False), 'compressed_payload': default_test_options._replace(proxyable=False), 'default_host': default_test_options._replace(needs_fullstack=True, needs_dns=True), diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c index 58aeef18f7..1fd4c0145a 100644 --- a/test/core/end2end/invalid_call_argument_test.c +++ b/test/core/end2end/invalid_call_argument_test.c @@ -131,16 +131,15 @@ static void cleanup_test() { grpc_server_shutdown_and_notify(g_state.server, g_state.cq, tag(1000)); GPR_ASSERT(grpc_completion_queue_pluck(g_state.cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), - NULL) - .type == GRPC_OP_COMPLETE); + NULL).type == GRPC_OP_COMPLETE); grpc_server_destroy(g_state.server); grpc_call_details_destroy(&g_state.call_details); grpc_metadata_array_destroy(&g_state.server_initial_metadata_recv); } grpc_completion_queue_shutdown(g_state.cq); while (grpc_completion_queue_next(g_state.cq, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type != GRPC_QUEUE_SHUTDOWN) + gpr_inf_future(GPR_CLOCK_REALTIME), + NULL).type != GRPC_QUEUE_SHUTDOWN) ; grpc_completion_queue_destroy(g_state.cq); } @@ -300,9 +299,9 @@ static void test_receive_initial_metadata_twice_at_client() { op->flags = 0; op->reserved = NULL; op++; - GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == grpc_call_start_batch(g_state.call, g_state.ops, - (size_t)(op - g_state.ops), - tag(1), NULL)); + GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); cleanup_test(); } @@ -316,9 +315,9 @@ static void test_receive_message_with_invalid_flags() { op->flags = 1; op->reserved = NULL; op++; - GPR_ASSERT(GRPC_CALL_ERROR_INVALID_FLAGS == grpc_call_start_batch(g_state.call, g_state.ops, - (size_t)(op - g_state.ops), - tag(1), NULL)); + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_FLAGS == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); cleanup_test(); } @@ -337,9 +336,9 @@ static void test_receive_two_messages_at_the_same_time() { op->flags = 0; op->reserved = NULL; op++; - GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == grpc_call_start_batch(g_state.call, g_state.ops, - (size_t)(op - g_state.ops), - tag(1), NULL)); + GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); cleanup_test(); } diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c index 58636ac2a2..e6404d6f51 100644 --- a/test/core/end2end/tests/binary_metadata.c +++ b/test/core/end2end/tests/binary_metadata.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index d384cd1150..68bd4bc36e 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -55,8 +55,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c index e267d80493..1e919ce19e 100644 --- a/test/core/end2end/tests/cancel_after_client_done.c +++ b/test/core/end2end/tests/cancel_after_client_done.c @@ -55,8 +55,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index ef9165ee25..a84f9be14e 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s/%s", test_name, config.name, mode.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index ce2b402f1b..61574df3d0 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index 6c57299e1a..6435d22ee9 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -55,8 +55,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c index 2005e5f881..2e36902a51 100644 --- a/test/core/end2end/tests/cancel_with_status.c +++ b/test/core/end2end/tests/cancel_with_status.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c deleted file mode 100644 index 29f52ed35a..0000000000 --- a/test/core/end2end/tests/census_simple_request.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * - * Copyright 2015, 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 "test/core/end2end/end2end_tests.h" - -#include <stdio.h> -#include <string.h> - -#include "src/core/support/string.h" -#include <grpc/byte_buffer.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/time.h> -#include <grpc/support/useful.h> -#include "test/core/end2end/cq_verifier.h" - -static gpr_timespec n_seconds_time(int n) { - return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); -} - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "%s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); - config.init_server(&f, server_args); - return f; -} - -static void *tag(gpr_intptr t) { return (void *)t; } - -static void shutdown_server(grpc_end2end_test_fixture *f) { - if (!f->server) return; - grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000), - GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), - NULL).type == GRPC_OP_COMPLETE); - grpc_server_destroy(f->server); - f->server = NULL; -} - -static void shutdown_client(grpc_end2end_test_fixture *f) { - if (!f->client) return; - grpc_channel_destroy(f->client); - f->client = NULL; -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, n_seconds_time(5), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void end_test(grpc_end2end_test_fixture *f) { - shutdown_server(f); - shutdown_client(f); - - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); -} - -static void test_body(grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - gpr_timespec deadline = n_seconds_time(5); - cq_verifier *cqv = cq_verifier_create(f.cq); - grpc_op ops[6]; - grpc_op *op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - char *details = NULL; - size_t details_capacity = 0; - int was_cancelled = 2; - - c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - "/foo", "foo.test.google.fr:1234", deadline, - NULL); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->data.recv_status_on_client.status_details_capacity = &details_capacity; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = - grpc_server_request_call(f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cq_expect_completion(cqv, tag(101), 1); - cq_verify(cqv); - - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - op->data.send_status_from_server.status_details = "xyz"; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - cq_expect_completion(cqv, tag(102), 1); - cq_expect_completion(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == strcmp(details, "xyz")); - GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234")); - GPR_ASSERT(was_cancelled == 1); - - gpr_free(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_destroy(c); - grpc_call_destroy(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_request_with_census( - grpc_end2end_test_config config, const char *name, - void (*body)(grpc_end2end_test_fixture f)) { - char *fullname; - grpc_end2end_test_fixture f; - grpc_arg client_arg, server_arg; - grpc_channel_args client_args, server_args; - - client_arg.type = GRPC_ARG_INTEGER; - client_arg.key = GRPC_ARG_ENABLE_CENSUS; - client_arg.value.integer = 1; - - client_args.num_args = 1; - client_args.args = &client_arg; - - server_arg.type = GRPC_ARG_INTEGER; - server_arg.key = GRPC_ARG_ENABLE_CENSUS; - server_arg.value.integer = 1; - server_args.num_args = 1; - server_args.args = &server_arg; - - gpr_asprintf(&fullname, "%s/%s", "test_invoke_request_with_census", name); - f = begin_test(config, fullname, &client_args, &server_args); - body(f); - end_test(&f); - config.tear_down_data(&f); - gpr_free(fullname); -} - -void grpc_end2end_tests(grpc_end2end_test_config config) { - test_invoke_request_with_census(config, "census_simple_request", test_body); -} diff --git a/test/core/end2end/tests/channel_connectivity.c b/test/core/end2end/tests/channel_connectivity.c index 46085bbdaf..0e0ac03015 100644 --- a/test/core/end2end/tests/channel_connectivity.c +++ b/test/core/end2end/tests/channel_connectivity.c @@ -153,7 +153,7 @@ static void test_connectivity(grpc_end2end_test_config config) { cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING); + state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); /* cleanup server */ grpc_server_destroy(f.server); diff --git a/test/core/end2end/tests/channel_ping.c b/test/core/end2end/tests/channel_ping.c new file mode 100644 index 0000000000..441e49ee7a --- /dev/null +++ b/test/core/end2end/tests/channel_ping.c @@ -0,0 +1,97 @@ +/* + * + * Copyright 2015, 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 "test/core/end2end/end2end_tests.h" + +#include <grpc/support/log.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> +#include <grpc/support/time.h> + +#include "test/core/end2end/cq_verifier.h" + +static void *tag(gpr_intptr t) { return (void *)t; } + +static void test_ping(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + int i; + + config.init_client(&f, NULL); + config.init_server(&f, NULL); + + grpc_channel_ping(f.client, f.cq, tag(0), NULL); + cq_expect_completion(cqv, tag(0), 0); + + /* check that we're still in idle, and start connecting */ + GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == + GRPC_CHANNEL_IDLE); + /* we'll go through some set of transitions (some might be missed), until + READY is reached */ + while (state != GRPC_CHANNEL_READY) { + grpc_channel_watch_connectivity_state( + f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(99)); + cq_expect_completion(cqv, tag(99), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(f.client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_READY || + state == GRPC_CHANNEL_CONNECTING || + state == GRPC_CHANNEL_TRANSIENT_FAILURE); + } + + for (i = 1; i <= 5; i++) { + grpc_channel_ping(f.client, f.cq, tag(i), NULL); + cq_expect_completion(cqv, tag(i), 1); + cq_verify(cqv); + } + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + cq_expect_completion(cqv, tag(0xdead), 1); + cq_verify(cqv); + + /* cleanup server */ + grpc_server_destroy(f.server); + + grpc_channel_destroy(f.client); + grpc_completion_queue_shutdown(f.cq); + grpc_completion_queue_destroy(f.cq); + config.tear_down_data(&f); + + cq_verifier_destroy(cqv); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + test_ping(config); +} diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c index f321fe1e7c..0d07110aef 100644 --- a/test/core/end2end/tests/compressed_payload.c +++ b/test/core/end2end/tests/compressed_payload.c @@ -59,8 +59,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c index 59eb8f18f9..f331aa92e0 100644 --- a/test/core/end2end/tests/empty_batch.c +++ b/test/core/end2end/tests/empty_batch.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c index 6b786aa89a..8efa5a34d0 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ b/test/core/end2end/tests/graceful_server_shutdown.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c index 75bb133439..399b6e2183 100644 --- a/test/core/end2end/tests/high_initial_seqno.c +++ b/test/core/end2end/tests/high_initial_seqno.c @@ -36,13 +36,15 @@ #include <stdio.h> #include <string.h> -#include "src/core/support/string.h" #include <grpc/byte_buffer.h> #include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/string_util.h> #include <grpc/support/time.h> #include <grpc/support/useful.h> + +#include "src/core/support/string.h" #include "test/core/end2end/cq_verifier.h" enum { TIMEOUT = 200000 }; @@ -56,8 +58,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } @@ -208,6 +210,7 @@ static void test_invoke_10_simple_requests(grpc_end2end_test_config config, grpc_end2end_test_fixture f; grpc_arg client_arg; grpc_channel_args client_args; + char *name; client_arg.type = GRPC_ARG_INTEGER; client_arg.key = GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER; @@ -216,13 +219,16 @@ static void test_invoke_10_simple_requests(grpc_end2end_test_config config, client_args.num_args = 1; client_args.args = &client_arg; - f = begin_test(config, "test_invoke_10_simple_requests", &client_args, NULL); + gpr_asprintf(&name, "test_invoke_requests first_seqno=%d", + initial_sequence_number); + f = begin_test(config, name, &client_args, NULL); for (i = 0; i < 10; i++) { simple_request_body(f); gpr_log(GPR_INFO, "Passed simple request %d", i); } end_test(&f); config.tear_down_data(&f); + gpr_free(name); } void grpc_end2end_tests(grpc_end2end_test_config config) { diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c index 297ea8d542..f16883ecfd 100644 --- a/test/core/end2end/tests/hpack_size.c +++ b/test/core/end2end/tests/hpack_size.c @@ -241,8 +241,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } @@ -262,9 +262,9 @@ static void drain_cq(grpc_completion_queue *cq) { static void shutdown_server(grpc_end2end_test_fixture *f) { if (!f->server) return; grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck( - f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) - .type == GRPC_OP_COMPLETE); + GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000), + GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), + NULL).type == GRPC_OP_COMPLETE); grpc_server_destroy(f->server); f->server = NULL; } diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index 67cd303fa6..c612af91e3 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c index 75d3f71cae..763f75d59d 100644 --- a/test/core/end2end/tests/large_metadata.c +++ b/test/core/end2end/tests/large_metadata.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index bb64200d9e..d39aabaf70 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index b3d8304d0b..c311f0a44e 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/metadata.c b/test/core/end2end/tests/metadata.c index c325d5a37c..2593cde027 100644 --- a/test/core/end2end/tests/metadata.c +++ b/test/core/end2end/tests/metadata.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c index 8fe9e7bcc5..23b8591e25 100644 --- a/test/core/end2end/tests/negative_deadline.c +++ b/test/core/end2end/tests/negative_deadline.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/no_op.c b/test/core/end2end/tests/no_op.c index ec33af78ef..dbaad3004e 100644 --- a/test/core/end2end/tests/no_op.c +++ b/test/core/end2end/tests/no_op.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c index b440fbab21..df44c0de1e 100644 --- a/test/core/end2end/tests/payload.c +++ b/test/core/end2end/tests/payload.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c index 804862ff58..27180dd679 100644 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ b/test/core/end2end/tests/ping_pong_streaming.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c index eea91e6c3b..ef4d5063b5 100644 --- a/test/core/end2end/tests/registered_call.c +++ b/test/core/end2end/tests/registered_call.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c index 5ea845e0e5..0ad5a4612e 100644 --- a/test/core/end2end/tests/request_with_flags.c +++ b/test/core/end2end/tests/request_with_flags.c @@ -55,8 +55,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c index 56c199baf3..ee5b071372 100644 --- a/test/core/end2end/tests/request_with_payload.c +++ b/test/core/end2end/tests/request_with_payload.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c index c77e31bca3..94863e7280 100644 --- a/test/core/end2end/tests/server_finishes_request.c +++ b/test/core/end2end/tests/server_finishes_request.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c index ad7def09a9..aa679081ec 100644 --- a/test/core/end2end/tests/shutdown_finishes_calls.c +++ b/test/core/end2end/tests/shutdown_finishes_calls.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/shutdown_finishes_tags.c b/test/core/end2end/tests/shutdown_finishes_tags.c index 9b678a1754..53a1573e16 100644 --- a/test/core/end2end/tests/shutdown_finishes_tags.c +++ b/test/core/end2end/tests/shutdown_finishes_tags.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index e9965a91ba..ce5df86a92 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -56,8 +56,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c index 306ef7e3aa..71f10eb8f5 100644 --- a/test/core/end2end/tests/trailing_metadata.c +++ b/test/core/end2end/tests/trailing_metadata.c @@ -54,8 +54,8 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, grpc_end2end_test_fixture f; gpr_log(GPR_INFO, "%s/%s", test_name, config.name); f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); config.init_server(&f, server_args); + config.init_client(&f, client_args); return f; } diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c index 4012f995c7..612388c61d 100644 --- a/test/core/httpcli/httpcli_test.c +++ b/test/core/httpcli/httpcli_test.c @@ -69,13 +69,13 @@ static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } -static void test_get(int use_ssl, int port) { +static void test_get(int port) { grpc_httpcli_request req; char *host; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; g_done = 0; - gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_get", use_ssl); + gpr_log(GPR_INFO, "test_get"); gpr_asprintf(&host, "localhost:%d", port); gpr_log(GPR_INFO, "requesting from %s", host); @@ -83,7 +83,7 @@ static void test_get(int use_ssl, int port) { memset(&req, 0, sizeof(req)); req.host = host; req.path = "/get"; - req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext; + req.handshaker = &grpc_httpcli_plaintext; grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15), on_finish, (void *)42); @@ -100,13 +100,13 @@ static void test_get(int use_ssl, int port) { gpr_free(host); } -static void test_post(int use_ssl, int port) { +static void test_post(int port) { grpc_httpcli_request req; char *host; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; g_done = 0; - gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_post", (int)use_ssl); + gpr_log(GPR_INFO, "test_post"); gpr_asprintf(&host, "localhost:%d", port); gpr_log(GPR_INFO, "posting to %s", host); @@ -114,7 +114,7 @@ static void test_post(int use_ssl, int port) { memset(&req, 0, sizeof(req)); req.host = host; req.path = "/post"; - req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext; + req.handshaker = &grpc_httpcli_plaintext; grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5, n_seconds_time(15), on_finish, (void *)42); @@ -142,19 +142,26 @@ int main(int argc, char **argv) { char *me = argv[0]; char *lslash = strrchr(me, '/'); char *args[4]; - char root[1024]; int port = grpc_pick_unused_port_or_die(); - /* figure out where we are */ - if (lslash) { - memcpy(root, me, (size_t)(lslash - me)); - root[lslash - me] = 0; + GPR_ASSERT(argc <= 2); + if (argc == 2) { + args[0] = gpr_strdup(argv[1]); } else { - strcpy(root, "."); + /* figure out where we are */ + char *root; + if (lslash) { + root = gpr_malloc((size_t)(lslash - me + 1)); + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + root = gpr_strdup("."); + } + gpr_asprintf(&args[0], "%s/../../test/core/httpcli/test_server.py", root); + gpr_free(root); } /* start the server */ - gpr_asprintf(&args[0], "%s/../../test/core/httpcli/test_server.py", root); args[1] = "--port"; gpr_asprintf(&args[2], "%d", port); server = gpr_subprocess_create(3, (const char **)args); @@ -170,8 +177,8 @@ int main(int argc, char **argv) { grpc_httpcli_context_init(&g_context); grpc_pollset_init(&g_pollset); - test_get(0, port); - test_post(0, port); + test_get(port); + test_post(port); grpc_httpcli_context_destroy(&g_context); grpc_closure_init(&destroyed, destroy_pollset, &g_pollset); diff --git a/test/core/httpcli/httpscli_test.c b/test/core/httpcli/httpscli_test.c new file mode 100644 index 0000000000..ba5660bd18 --- /dev/null +++ b/test/core/httpcli/httpscli_test.c @@ -0,0 +1,195 @@ +/* + * + * Copyright 2015, 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 "src/core/httpcli/httpcli.h" + +#include <string.h> + +#include <grpc/grpc.h> +#include "src/core/iomgr/iomgr.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/subprocess.h> +#include <grpc/support/sync.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static int g_done = 0; +static grpc_httpcli_context g_context; +static grpc_pollset g_pollset; + +static gpr_timespec n_seconds_time(int seconds) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds); +} + +static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, + const grpc_httpcli_response *response) { + const char *expect = + "<html><head><title>Hello world!</title></head>" + "<body><p>This is a test</p></body></html>"; + GPR_ASSERT(arg == (void *)42); + GPR_ASSERT(response); + GPR_ASSERT(response->status == 200); + GPR_ASSERT(response->body_length == strlen(expect)); + GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length)); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + g_done = 1; + grpc_pollset_kick(&g_pollset, NULL); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); +} + +static void test_get(int port) { + grpc_httpcli_request req; + char *host; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + g_done = 0; + gpr_log(GPR_INFO, "test_get"); + + gpr_asprintf(&host, "localhost:%d", port); + gpr_log(GPR_INFO, "requesting from %s", host); + + memset(&req, 0, sizeof(req)); + req.host = host; + req.ssl_host_override = "foo.test.google.fr"; + req.path = "/get"; + req.handshaker = &grpc_httpcli_ssl; + + grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15), + on_finish, (void *)42); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (!g_done) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20)); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_free(host); +} + +static void test_post(int port) { + grpc_httpcli_request req; + char *host; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + g_done = 0; + gpr_log(GPR_INFO, "test_post"); + + gpr_asprintf(&host, "localhost:%d", port); + gpr_log(GPR_INFO, "posting to %s", host); + + memset(&req, 0, sizeof(req)); + req.host = host; + req.ssl_host_override = "foo.test.google.fr"; + req.path = "/post"; + req.handshaker = &grpc_httpcli_ssl; + + grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5, + n_seconds_time(15), on_finish, (void *)42); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (!g_done) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20)); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_free(host); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, int success) { + grpc_pollset_destroy(p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_subprocess *server; + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char *args[5]; + int port = grpc_pick_unused_port_or_die(); + + GPR_ASSERT(argc <= 2); + if (argc == 2) { + args[0] = gpr_strdup(argv[1]); + } else { + /* figure out where we are */ + char *root; + if (lslash) { + root = gpr_malloc((size_t)(lslash - me + 1)); + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + root = gpr_strdup("."); + } + gpr_asprintf(&args[0], "%s/../../test/core/httpcli/test_server.py", root); + gpr_free(root); + } + + /* start the server */ + args[1] = "--port"; + gpr_asprintf(&args[2], "%d", port); + args[3] = "--ssl"; + server = gpr_subprocess_create(4, (const char **)args); + GPR_ASSERT(server); + gpr_free(args[0]); + gpr_free(args[2]); + + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(5, GPR_TIMESPAN))); + + grpc_test_init(argc, argv); + grpc_init(); + grpc_httpcli_context_init(&g_context); + grpc_pollset_init(&g_pollset); + + test_get(port); + test_post(port); + + grpc_httpcli_context_destroy(&g_context); + grpc_closure_init(&destroyed, destroy_pollset, &g_pollset); + grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_subprocess_destroy(server); + + return 0; +} diff --git a/test/core/httpcli/parser_test.c b/test/core/httpcli/parser_test.c index dacec0f72f..a26ddd2821 100644 --- a/test/core/httpcli/parser_test.c +++ b/test/core/httpcli/parser_test.c @@ -38,6 +38,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/string_util.h> #include <grpc/support/useful.h> #include "test/core/util/slice_splitter.h" #include "test/core/util/test_config.h" @@ -123,6 +124,7 @@ int main(int argc, char **argv) { size_t i; const grpc_slice_split_mode split_modes[] = {GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; + char *tmp1, *tmp2; grpc_test_init(argc, argv); @@ -149,6 +151,20 @@ int main(int argc, char **argv) { test_fails(split_modes[i], "HTTP/1.0 200 OK\n"); test_fails(split_modes[i], "HTTP/1.0 200 OK\r\n"); test_fails(split_modes[i], "HTTP/1.0 200 OK\r\nFoo x\r\n"); + test_fails(split_modes[i], + "HTTP/1.0 200 OK\r\n" + "xyz: abc\r\n" + " def\r\n" + "\r\n" + "hello world!"); + + tmp1 = gpr_malloc(2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH); + memset(tmp1, 'a', 2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH - 1); + tmp1[2 * GRPC_HTTPCLI_MAX_HEADER_LENGTH - 1] = 0; + gpr_asprintf(&tmp2, "HTTP/1.0 200 OK\r\nxyz: %s\r\n\r\n", tmp1); + test_fails(split_modes[i], tmp2); + gpr_free(tmp1); + gpr_free(tmp2); } return 0; diff --git a/test/core/httpcli/test_server.py b/test/core/httpcli/test_server.py index 4aaf5e30f8..225c2a6b0f 100755 --- a/test/core/httpcli/test_server.py +++ b/test/core/httpcli/test_server.py @@ -4,9 +4,18 @@ import argparse import BaseHTTPServer +import os +import ssl +import sys + +_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.pem')) +_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.key')) +print _PEM +open(_PEM).close() argp = argparse.ArgumentParser(description='Server for httpcli_test') argp.add_argument('-p', '--port', default=10080, type=int) +argp.add_argument('-s', '--ssl', default=False, action='store_true') args = argp.parse_args() print 'server running on port %d' % args.port @@ -28,4 +37,7 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler): if self.path == '/post' and content == 'hello': self.good() -BaseHTTPServer.HTTPServer(('', args.port), Handler).serve_forever() +httpd = BaseHTTPServer.HTTPServer(('localhost', args.port), Handler) +if args.ssl: + httpd.socket = ssl.wrap_socket(httpd.socket, certfile=_PEM, keyfile=_KEY, server_side=True) +httpd.serve_forever() diff --git a/test/core/iomgr/sockaddr_utils_test.c b/test/core/iomgr/sockaddr_utils_test.c index 5009a641ea..5cf0994f39 100644 --- a/test/core/iomgr/sockaddr_utils_test.c +++ b/test/core/iomgr/sockaddr_utils_test.c @@ -236,6 +236,29 @@ static void test_sockaddr_to_string(void) { GPR_ASSERT(errno == 0x7EADBEEF); } +static void test_sockaddr_set_get_port(void) { + struct sockaddr_in input4; + struct sockaddr_in6 input6; + struct sockaddr dummy; + + gpr_log(GPR_DEBUG, "test_sockaddr_set_get_port"); + + input4 = make_addr4(kIPv4, sizeof(kIPv4)); + GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input4) == 12345); + GPR_ASSERT(grpc_sockaddr_set_port((struct sockaddr *)&input4, 54321)); + GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input4) == 54321); + + input6 = make_addr6(kIPv6, sizeof(kIPv6)); + GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input6) == 12345); + GPR_ASSERT(grpc_sockaddr_set_port((struct sockaddr *)&input6, 54321)); + GPR_ASSERT(grpc_sockaddr_get_port((struct sockaddr *)&input6) == 54321); + + memset(&dummy, 0, sizeof(dummy)); + dummy.sa_family = 123; + GPR_ASSERT(grpc_sockaddr_get_port(&dummy) == 0); + GPR_ASSERT(grpc_sockaddr_set_port(&dummy, 1234) == 0); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); @@ -243,6 +266,7 @@ int main(int argc, char **argv) { test_sockaddr_to_v4mapped(); test_sockaddr_is_wildcard(); test_sockaddr_to_string(); + test_sockaddr_set_get_port(); return 0; } diff --git a/test/core/iomgr/socket_utils_test.c b/test/core/iomgr/socket_utils_test.c new file mode 100644 index 0000000000..58c3fbc0ae --- /dev/null +++ b/test/core/iomgr/socket_utils_test.c @@ -0,0 +1,62 @@ +/* + * + * Copyright 2015, 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 <grpc/support/port_platform.h> +#include "src/core/iomgr/socket_utils_posix.h" + +#include <errno.h> +#include <string.h> + +#include <grpc/support/log.h> +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + int sock; + grpc_test_init(argc, argv); + + sock = socket(PF_INET, SOCK_STREAM, 0); + GPR_ASSERT(sock > 0); + + GPR_ASSERT(grpc_set_socket_nonblocking(sock, 1)); + GPR_ASSERT(grpc_set_socket_nonblocking(sock, 0)); + GPR_ASSERT(grpc_set_socket_cloexec(sock, 1)); + GPR_ASSERT(grpc_set_socket_cloexec(sock, 0)); + GPR_ASSERT(grpc_set_socket_reuse_addr(sock, 1)); + GPR_ASSERT(grpc_set_socket_reuse_addr(sock, 0)); + GPR_ASSERT(grpc_set_socket_low_latency(sock, 1)); + GPR_ASSERT(grpc_set_socket_low_latency(sock, 0)); + + close(sock); + + return 0; +} diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index a61cccdb02..833ceace54 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -234,8 +234,9 @@ void test_times_out(void) { if (gpr_time_cmp(now, finish_time) > 0) { break; } - gpr_log(GPR_DEBUG, "now=%d.%09d connect_deadline=%d.%09d", now.tv_sec, - now.tv_nsec, connect_deadline.tv_sec, connect_deadline.tv_nsec); + gpr_log(GPR_DEBUG, "now=%lld.%09d connect_deadline=%lld.%09d", + (long long)now.tv_sec, (int)now.tv_nsec, + (long long)connect_deadline.tv_sec, (int)connect_deadline.tv_nsec); if (is_after_deadline && gpr_time_cmp(now, restart_verifying_time) <= 0) { /* allow some slack before insisting that things be done */ } else { diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c index 86e8767937..85e28732e4 100644 --- a/test/core/iomgr/udp_server_test.c +++ b/test/core/iomgr/udp_server_test.c @@ -43,6 +43,8 @@ #include <string.h> #include <unistd.h> +#ifdef GRPC_NEED_UDP + #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) static grpc_pollset g_pollset; @@ -195,3 +197,9 @@ int main(int argc, char **argv) { grpc_iomgr_shutdown(); return 0; } + +#else + +int main(int argc, char **argv) { return 0; } + +#endif diff --git a/test/core/iomgr/workqueue_test.c b/test/core/iomgr/workqueue_test.c index 90f7ba7a83..d1f9dabc57 100644 --- a/test/core/iomgr/workqueue_test.c +++ b/test/core/iomgr/workqueue_test.c @@ -48,6 +48,15 @@ static void must_succeed(grpc_exec_ctx *exec_ctx, void *p, int success) { gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } +static void test_ref_unref(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx); + GRPC_WORKQUEUE_REF(wq, "test"); + GRPC_WORKQUEUE_UNREF(&exec_ctx, wq, "test"); + GRPC_WORKQUEUE_UNREF(&exec_ctx, wq, "destroy"); + grpc_exec_ctx_finish(&exec_ctx); +} + static void test_add_closure(void) { grpc_closure c; int done = 0; @@ -72,6 +81,31 @@ static void test_add_closure(void) { grpc_exec_ctx_finish(&exec_ctx); } +static void test_flush(void) { + grpc_closure c; + int done = 0; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx); + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); + grpc_pollset_worker worker; + grpc_closure_init(&c, must_succeed, &done); + + grpc_exec_ctx_enqueue(&exec_ctx, &c, 1); + grpc_workqueue_flush(&exec_ctx, wq); + grpc_workqueue_add_to_pollset(&exec_ctx, wq, &g_pollset); + + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + GPR_ASSERT(!done); + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(deadline.clock_type), deadline); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(done); + + GRPC_WORKQUEUE_UNREF(&exec_ctx, wq, "destroy"); + grpc_exec_ctx_finish(&exec_ctx); +} + static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, int success) { grpc_pollset_destroy(p); } @@ -83,7 +117,9 @@ int main(int argc, char **argv) { grpc_init(); grpc_pollset_init(&g_pollset); + test_ref_unref(); test_add_closure(); + test_flush(); grpc_closure_init(&destroyed, destroy_pollset, &g_pollset); grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed); diff --git a/test/core/json/json_stream_error_test.c b/test/core/json/json_stream_error_test.c new file mode 100644 index 0000000000..3464eb2a9c --- /dev/null +++ b/test/core/json/json_stream_error_test.c @@ -0,0 +1,74 @@ +/* + * + * Copyright 2015, 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 <stdio.h> +#include <stdlib.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/useful.h> +#include <grpc/support/log.h> +#include "test/core/util/test_config.h" + +#include "src/core/json/json_reader.h" +#include "src/core/json/json_writer.h" + +static int g_string_clear_once = 0; + +static void string_clear(void *userdata) { + GPR_ASSERT(!g_string_clear_once); + g_string_clear_once = 1; +} + +static gpr_uint32 read_char(void *userdata) { + return GRPC_JSON_READ_CHAR_ERROR; +} + +static grpc_json_reader_vtable reader_vtable = { + string_clear, NULL, NULL, read_char, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL}; + +static void read_error() { + grpc_json_reader reader; + grpc_json_reader_status status; + grpc_json_reader_init(&reader, &reader_vtable, NULL); + + status = grpc_json_reader_run(&reader); + GPR_ASSERT(status == GRPC_JSON_READ_ERROR); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + read_error(); + gpr_log(GPR_INFO, "json_stream_error success"); + return 0; +} diff --git a/test/core/json/json_test.c b/test/core/json/json_test.c index 15019913da..5add80d753 100644 --- a/test/core/json/json_test.c +++ b/test/core/json/json_test.c @@ -49,10 +49,10 @@ typedef struct testing_pair { static testing_pair testing_pairs[] = { /* Testing valid parsing. */ - /* Testing trivial parses, with de-indentation. */ {" 0 ", "0"}, {" 1 ", "1"}, + {" \" \" ", "\" \""}, {" \"a\" ", "\"a\""}, {" true ", "true"}, /* Testing the parser's ability to decode trivial UTF-16. */ @@ -69,8 +69,8 @@ static testing_pair testing_pairs[] = { " [ [ ] , { } , [ ] ] ", "[[],{},[]]", }, /* Testing escapes and control chars in key strings. */ - {" { \"\x7f\\n\\\\a , b\": 1, \"\": 0 } ", - "{\"\\u007f\\n\\\\a , b\":1,\"\":0}"}, + {" { \"\\u007f\x7f\\n\\r\\\"\\f\\b\\\\a , b\": 1, \"\": 0 } ", + "{\"\\u007f\\u007f\\n\\r\\\"\\f\\b\\\\a , b\":1,\"\":0}"}, /* Testing the writer's ability to cut off invalid UTF-8 sequences. */ {"\"abc\xf0\x9d\x24\"", "\"abc\""}, {"\"\xff\"", "\"\""}, @@ -96,6 +96,9 @@ static testing_pair testing_pairs[] = { {"\"\\udd1ef", NULL}, {"\"\\ud834\\ud834\"", NULL}, {"\"\\ud834\\u1234\"", NULL}, + {"\"\\ud834]\"", NULL}, + {"\"\\ud834 \"", NULL}, + {"\"\\ud834\\\\\"", NULL}, /* Testing embedded invalid whitechars. */ {"\"\n\"", NULL}, {"\"\t\"", NULL}, @@ -110,9 +113,15 @@ static testing_pair testing_pairs[] = { {"[[]", NULL}, {"[}", NULL}, {"{]", NULL}, - /*Testing trailing comma. */ + /* Testing bad containers. */ + {"{x}", NULL}, + {"{x=0,y}", NULL}, + /* Testing trailing comma. */ {"{,}", NULL}, {"[1,2,3,4,]", NULL}, + {"{\"a\": 1, }", NULL}, + /* Testing after-ending characters. */ + {"{}x", NULL}, /* Testing having a key syntax in an array. */ {"[\"x\":0]", NULL}, /* Testing invalid numbers. */ @@ -160,7 +169,7 @@ static void test_pairs() { } static void test_atypical() { - char *scratchpad = gpr_strdup("[[],[]]"); + char *scratchpad = gpr_strdup("[[],[],[]]"); grpc_json *json = grpc_json_parse_string(scratchpad); grpc_json *brother; @@ -168,7 +177,8 @@ static void test_atypical() { GPR_ASSERT(json->child); brother = json->child->next; grpc_json_destroy(json->child); - json->child = brother; + GPR_ASSERT(json->child == brother); + grpc_json_destroy(json->child->next); grpc_json_destroy(json); gpr_free(scratchpad); } diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 834113488c..a32ddd2ec7 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -878,7 +878,7 @@ static void test_google_default_creds_auth_key(void) { gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ } -static void test_google_default_creds_access_token(void) { +static void test_google_default_creds_refresh_token(void) { grpc_google_refresh_token_credentials *refresh; grpc_composite_channel_credentials *creds; grpc_flush_cached_google_default_credentials(); @@ -894,6 +894,102 @@ static void test_google_default_creds_access_token(void) { gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ } +static int default_creds_gce_detection_httpcli_get_success_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + gpr_timespec deadline, grpc_httpcli_response_cb on_response, + void *user_data) { + grpc_httpcli_response response = http_response(200, ""); + grpc_httpcli_header header; + header.key = "Metadata-Flavor"; + header.value = "Google"; + response.hdr_count = 1; + response.hdrs = &header; + GPR_ASSERT(strcmp(request->path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + on_response(exec_ctx, user_data, &response); + return 1; +} + +static char *null_well_known_creds_path_getter(void) { return NULL; } + +static void test_google_default_creds_gce(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_composite_channel_credentials *creds; + grpc_channel_credentials *cached_creds; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_flush_cached_google_default_credentials(); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_override_well_known_credentials_path_getter( + null_well_known_creds_path_getter); + + /* Simulate a successful detection of GCE. */ + grpc_httpcli_set_override( + default_creds_gce_detection_httpcli_get_success_override, + httpcli_post_should_not_be_called); + creds = (grpc_composite_channel_credentials *) + grpc_google_default_credentials_create(); + + /* Verify that the default creds actually embeds a GCE creds. */ + GPR_ASSERT(creds != NULL); + GPR_ASSERT(creds->call_creds != NULL); + grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, + httpcli_post_should_not_be_called); + grpc_call_credentials_get_request_metadata( + &exec_ctx, creds->call_creds, NULL, auth_md_ctx, + on_oauth2_creds_get_metadata_success, (void *)test_user_data); + grpc_exec_ctx_flush(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + + /* Check that we get a cached creds if we call + grpc_google_default_credentials_create again. + GCE detection should not occur anymore either. */ + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + httpcli_post_should_not_be_called); + cached_creds = grpc_google_default_credentials_create(); + GPR_ASSERT(cached_creds == &creds->base); + + /* Cleanup. */ + grpc_channel_credentials_release(cached_creds); + grpc_channel_credentials_release(&creds->base); + grpc_httpcli_set_override(NULL, NULL); + grpc_override_well_known_credentials_path_getter(NULL); +} + +static int default_creds_gce_detection_httpcli_get_failure_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + gpr_timespec deadline, grpc_httpcli_response_cb on_response, + void *user_data) { + /* No magic header. */ + grpc_httpcli_response response = http_response(200, ""); + GPR_ASSERT(strcmp(request->path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + on_response(exec_ctx, user_data, &response); + return 1; +} + +static void test_no_google_default_creds(void) { + grpc_flush_cached_google_default_credentials(); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_override_well_known_credentials_path_getter( + null_well_known_creds_path_getter); + + /* Simulate a successful detection of GCE. */ + grpc_httpcli_set_override( + default_creds_gce_detection_httpcli_get_failure_override, + httpcli_post_should_not_be_called); + GPR_ASSERT(grpc_google_default_credentials_create() == NULL); + + /* Try a cached one. GCE detection should not occur anymore. */ + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + httpcli_post_should_not_be_called); + GPR_ASSERT(grpc_google_default_credentials_create() == NULL); + + /* Cleanup. */ + grpc_httpcli_set_override(NULL, NULL); + grpc_override_well_known_credentials_path_getter(NULL); +} + typedef enum { PLUGIN_INITIAL_STATE, PLUGIN_GET_METADATA_CALLED_STATE, @@ -1042,6 +1138,7 @@ static void test_get_well_known_google_credentials_file_path(void) { int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_empty_md_store(); test_ref_unref_empty_md_store(); test_add_to_empty_md_store(); @@ -1067,9 +1164,12 @@ int main(int argc, char **argv) { test_jwt_creds_success(); test_jwt_creds_signing_failure(); test_google_default_creds_auth_key(); - test_google_default_creds_access_token(); + test_google_default_creds_refresh_token(); + test_google_default_creds_gce(); + test_no_google_default_creds(); test_metadata_plugin_success(); test_metadata_plugin_failure(); test_get_well_known_google_credentials_file_path(); + grpc_shutdown(); return 0; } diff --git a/test/core/support/alloc_test.c b/test/core/support/alloc_test.c index 289b2b0c87..b950f0ab49 100644 --- a/test/core/support/alloc_test.c +++ b/test/core/support/alloc_test.c @@ -35,17 +35,11 @@ #include <grpc/support/alloc.h> #include "test/core/util/test_config.h" -static void *fake_malloc(size_t size) { - return (void*)size; -} +static void *fake_malloc(size_t size) { return (void *)size; } -static void *fake_realloc(void *addr, size_t size) { - return (void*)size; -} +static void *fake_realloc(void *addr, size_t size) { return (void *)size; } -static void fake_free(void *addr) { - *((gpr_intptr*)addr) = 0xdeadd00d; -} +static void fake_free(void *addr) { *((gpr_intptr *)addr) = 0xdeadd00d; } static void test_custom_allocs() { const gpr_allocation_functions default_fns = gpr_get_allocation_functions(); @@ -54,16 +48,16 @@ static void test_custom_allocs() { gpr_allocation_functions fns = {fake_malloc, fake_realloc, fake_free}; gpr_set_allocation_functions(fns); - GPR_ASSERT((void*)0xdeadbeef == gpr_malloc(0xdeadbeef)); - GPR_ASSERT((void*)0xcafed00d == gpr_realloc(0, 0xcafed00d)); + GPR_ASSERT((void *)0xdeadbeef == gpr_malloc(0xdeadbeef)); + GPR_ASSERT((void *)0xcafed00d == gpr_realloc(0, 0xcafed00d)); gpr_free(&addr_to_free); GPR_ASSERT(addr_to_free == 0xdeadd00d); /* Restore and check we don't get funky values and that we don't leak */ gpr_set_allocation_functions(default_fns); - GPR_ASSERT((void*)1 != (i = gpr_malloc(sizeof(*i)))); - GPR_ASSERT((void*)2 != (i = gpr_realloc(i, 2))); + GPR_ASSERT((void *)1 != (i = gpr_malloc(sizeof(*i)))); + GPR_ASSERT((void *)2 != (i = gpr_realloc(i, 2))); gpr_free(i); } diff --git a/test/core/support/cmdline_test.c b/test/core/support/cmdline_test.c index 1c77c15233..4730fcc1b5 100644 --- a/test/core/support/cmdline_test.c +++ b/test/core/support/cmdline_test.c @@ -40,7 +40,7 @@ #include <grpc/support/useful.h> #include "test/core/util/test_config.h" -#define LOG_TEST() gpr_log(GPR_INFO, "%s", __FILE__) +#define LOG_TEST() gpr_log(GPR_INFO, "test at %s:%d", __FILE__, __LINE__) static void test_simple_int(void) { int x = 1; @@ -273,6 +273,44 @@ static void test_many(void) { gpr_cmdline_destroy(cl); } +static void extra_arg_cb(void *user_data, const char *arg) { + int *count = user_data; + GPR_ASSERT(arg != NULL); + GPR_ASSERT(strlen(arg) == 1); + GPR_ASSERT(arg[0] == 'a' + *count); + ++*count; +} + +static void test_extra(void) { + gpr_cmdline *cl; + int count = 0; + char *args[] = {(char *)__FILE__, "a", "b", "c"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + &count); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(count == 3); + gpr_cmdline_destroy(cl); +} + +static void test_extra_dashdash(void) { + gpr_cmdline *cl; + int count = 0; + char *args[] = {(char *)__FILE__, "--", "a", "b", "c"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + &count); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(count == 3); + gpr_cmdline_destroy(cl); +} + static void test_usage(void) { gpr_cmdline *cl; char *usage; @@ -281,20 +319,154 @@ static void test_usage(void) { int x = 0; int flag = 2; + LOG_TEST(); + cl = gpr_cmdline_create(NULL); gpr_cmdline_add_string(cl, "str", NULL, &str); gpr_cmdline_add_int(cl, "x", NULL, &x); gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); usage = gpr_cmdline_usage_string(cl, "test"); - GPR_ASSERT( - 0 == strcmp(usage, - "Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n")); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] " + "[--flag|--no-flag] [file...]\n")); + gpr_free(usage); + + usage = gpr_cmdline_usage_string(cl, "/foo/test"); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] " + "[--flag|--no-flag] [file...]\n")); gpr_free(usage); gpr_cmdline_destroy(cl); } +static void test_help(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *help[] = {(char *)__FILE__, "-h"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(help), help)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs1(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_arg_name[] = {(char *)__FILE__, "--y"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_arg_name), bad_arg_name)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs2(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_int_value[] = {(char *)__FILE__, "--x", "henry"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT( + 0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_int_value), bad_int_value)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs3(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, "--flag=henry"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value), + bad_bool_value)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs4(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, "--no-str"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value), + bad_bool_value)); + + gpr_cmdline_destroy(cl); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_simple_int(); @@ -312,6 +484,13 @@ int main(int argc, char **argv) { test_flag_val_true(); test_flag_val_false(); test_many(); + test_extra(); + test_extra_dashdash(); test_usage(); + test_help(); + test_badargs1(); + test_badargs2(); + test_badargs3(); + test_badargs4(); return 0; } diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c index f62cbe3435..c97d3176c5 100644 --- a/test/core/support/string_test.c +++ b/test/core/support/string_test.c @@ -33,6 +33,7 @@ #include "src/core/support/string.h" +#include <limits.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -286,6 +287,53 @@ static void test_strsplit(void) { gpr_free(parts); } +static void test_ltoa() { + char *str; + char buf[GPR_LTOA_MIN_BUFSIZE]; + + LOG_TEST_NAME("test_ltoa"); + + /* zero */ + GPR_ASSERT(1 == gpr_ltoa(0, buf)); + GPR_ASSERT(0 == strcmp("0", buf)); + + /* positive number */ + GPR_ASSERT(3 == gpr_ltoa(123, buf)); + GPR_ASSERT(0 == strcmp("123", buf)); + + /* negative number */ + GPR_ASSERT(6 == gpr_ltoa(-12345, buf)); + GPR_ASSERT(0 == strcmp("-12345", buf)); + + /* large negative - we don't know the size of long in advance */ + GPR_ASSERT(gpr_asprintf(&str, "%lld", (long long)LONG_MIN)); + GPR_ASSERT(strlen(str) == (size_t)gpr_ltoa(LONG_MIN, buf)); + GPR_ASSERT(0 == strcmp(str, buf)); + gpr_free(str); +} + +static void test_int64toa() { + char buf[GPR_INT64TOA_MIN_BUFSIZE]; + + LOG_TEST_NAME("test_int64toa"); + + /* zero */ + GPR_ASSERT(1 == gpr_int64toa(0, buf)); + GPR_ASSERT(0 == strcmp("0", buf)); + + /* positive */ + GPR_ASSERT(3 == gpr_int64toa(123, buf)); + GPR_ASSERT(0 == strcmp("123", buf)); + + /* large positive */ + GPR_ASSERT(19 == gpr_int64toa(9223372036854775807LL, buf)); + GPR_ASSERT(0 == strcmp("9223372036854775807", buf)); + + /* large negative */ + GPR_ASSERT(20 == gpr_int64toa(-9223372036854775807LL - 1, buf)); + GPR_ASSERT(0 == strcmp("-9223372036854775808", buf)); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_strdup(); @@ -296,5 +344,7 @@ int main(int argc, char **argv) { test_strjoin(); test_strjoin_sep(); test_strsplit(); + test_ltoa(); + test_int64toa(); return 0; } diff --git a/test/core/support/sync_test.c b/test/core/support/sync_test.c index 6bc5f792e5..73f68e4dbd 100644 --- a/test/core/support/sync_test.c +++ b/test/core/support/sync_test.c @@ -272,7 +272,7 @@ static void test(const char *name, void (*body)(void *m), test_destroy(m); } time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); - fprintf(stderr, " done %ld.%09d s\n", (long)time_taken.tv_sec, + fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, (int)time_taken.tv_nsec); } @@ -430,7 +430,6 @@ static void refinc(void *v /*=m*/) { mark_thread_done(m); } - /* Wait until m->event is set to (void *)1, then decrement m->refcount by 1 (m->threads * m->iterations * m->incr_step) times, and ensure that the last decrement caused the counter to reach zero, then mark thread as done. */ diff --git a/test/core/support/thd_test.c b/test/core/support/thd_test.c index faba33c5e8..f7807d280a 100644 --- a/test/core/support/thd_test.c +++ b/test/core/support/thd_test.c @@ -62,6 +62,19 @@ static void thd_body(void *v) { static void thd_body_joinable(void *v) {} +/* Test thread options work as expected */ +static void test_options(void) { + gpr_thd_options options = gpr_thd_options_default(); + GPR_ASSERT(!gpr_thd_options_is_joinable(&options)); + GPR_ASSERT(gpr_thd_options_is_detached(&options)); + gpr_thd_options_set_joinable(&options); + GPR_ASSERT(gpr_thd_options_is_joinable(&options)); + GPR_ASSERT(!gpr_thd_options_is_detached(&options)); + gpr_thd_options_set_detached(&options); + GPR_ASSERT(!gpr_thd_options_is_joinable(&options)); + GPR_ASSERT(gpr_thd_options_is_detached(&options)); +} + /* Test that we can create a number of threads and wait for them. */ static void test(void) { int i; @@ -96,6 +109,7 @@ static void test(void) { int main(int argc, char *argv[]) { grpc_test_init(argc, argv); + test_options(); test(); return 0; } diff --git a/test/core/support/time_test.c b/test/core/support/time_test.c index ce35edd83c..b921052e7b 100644 --- a/test/core/support/time_test.c +++ b/test/core/support/time_test.c @@ -98,7 +98,7 @@ static void test_values(void) { fprintf(stderr, "far future "); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); - GPR_ASSERT(x.tv_sec >= INT_MAX); + GPR_ASSERT(x.tv_sec == INT64_MAX); fprintf(stderr, "far future "); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); @@ -107,7 +107,7 @@ static void test_values(void) { fprintf(stderr, "far past "); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); - GPR_ASSERT(x.tv_sec <= INT_MIN); + GPR_ASSERT(x.tv_sec == INT64_MIN); fprintf(stderr, "far past "); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index 5cf6bfec29..8a24d826bb 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -89,7 +89,7 @@ static void test_cq_end_op(void) { cc = grpc_completion_queue_create(NULL); - grpc_cq_begin_op(cc); + grpc_cq_begin_op(cc, tag); grpc_cq_end_op(&exec_ctx, cc, tag, 1, do_nothing_end_completion, NULL, &completion); @@ -148,7 +148,7 @@ static void test_pluck(void) { cc = grpc_completion_queue_create(NULL); for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - grpc_cq_begin_op(cc); + grpc_cq_begin_op(cc, tags[i]); grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL, &completions[i]); } @@ -160,7 +160,7 @@ static void test_pluck(void) { } for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - grpc_cq_begin_op(cc); + grpc_cq_begin_op(cc, tags[i]); grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL, &completions[i]); } @@ -226,14 +226,14 @@ static void test_too_many_plucks(void) { } /* wait until all other threads are plucking */ - gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000)); ev = grpc_completion_queue_pluck(cc, create_test_tag(), gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - grpc_cq_begin_op(cc); + grpc_cq_begin_op(cc, tags[i]); grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL, &completions[i]); } @@ -279,7 +279,7 @@ static void producer_thread(void *arg) { gpr_log(GPR_INFO, "producer %d phase 1", opt->id); for (i = 0; i < TEST_THREAD_EVENTS; i++) { - grpc_cq_begin_op(opt->cc); + grpc_cq_begin_op(opt->cc, (void *)(gpr_intptr)1); } gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id); diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 0d29bea555..35b0212fcf 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -31,15 +31,52 @@ * */ -#include <grpc/grpc.h> +#include <string.h> -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/test_config.h" +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include "src/core/channel/channel_stack.h" +#include "src/core/iomgr/closure.h" +#include "src/core/surface/channel.h" +#include "src/core/transport/transport.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/test_config.h" + +grpc_closure transport_op_cb; static void *tag(gpr_intptr x) { return (void *)x; } +void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, int success) { + grpc_transport_op *op = arg; + GPR_ASSERT(GRPC_CHANNEL_FATAL_FAILURE == *op->connectivity_state); + GPR_ASSERT(success); +} + +void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {} + +void test_transport_op(grpc_channel *channel) { + grpc_transport_op op; + grpc_channel_element *elem; + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + memset(&op, 0, sizeof(op)); + grpc_closure_init(&transport_op_cb, verify_connectivity, &op); + + op.on_connectivity_state_change = &transport_op_cb; + op.connectivity_state = &state; + elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); + elem->filter->start_transport_op(&exec_ctx, elem, &op); + grpc_exec_ctx_finish(&exec_ctx); + + memset(&op, 0, sizeof(op)); + grpc_closure_init(&transport_op_cb, do_nothing, NULL); + op.on_consumed = &transport_op_cb; + elem->filter->start_transport_op(&exec_ctx, elem, &op); + grpc_exec_ctx_finish(&exec_ctx); +} + int main(int argc, char **argv) { grpc_channel *chan; grpc_call *call; @@ -47,21 +84,31 @@ int main(int argc, char **argv) { cq_verifier *cqv; grpc_op ops[6]; grpc_op *op; + grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_status_code status; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; + char *peer; grpc_test_init(argc, argv); grpc_init(); + grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); chan = grpc_lame_client_channel_create( "lampoon:national", GRPC_STATUS_UNKNOWN, "Rpc sent on a lame channel."); GPR_ASSERT(chan); + + test_transport_op(chan); + + GPR_ASSERT(GRPC_CHANNEL_FATAL_FAILURE == + grpc_channel_check_connectivity_state(chan, 0)); + cq = grpc_completion_queue_create(NULL); + call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Foo", "anywhere", GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100), NULL); @@ -74,6 +121,19 @@ int main(int argc, char **argv) { op->flags = 0; op->reserved = NULL; op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* the call should immediately fail */ + cq_expect_completion(cqv, tag(1), 0); + cq_verify(cqv); + + op = ops; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; @@ -82,18 +142,23 @@ int main(int argc, char **argv) { op->flags = 0; op->reserved = NULL; op++; - error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); + error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* the call should immediately fail */ - cq_expect_completion(cqv, tag(1), 1); + cq_expect_completion(cqv, tag(2), 1); cq_verify(cqv); + peer = grpc_call_get_peer(call); + GPR_ASSERT(strcmp(peer, "lampoon:national") == 0); + gpr_free(peer); + grpc_call_destroy(call); grpc_channel_destroy(chan); cq_verifier_destroy(cqv); grpc_completion_queue_destroy(cq); + grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); gpr_free(details); diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c new file mode 100644 index 0000000000..f3e5fefaf0 --- /dev/null +++ b/test/core/surface/secure_channel_create_test.c @@ -0,0 +1,95 @@ +/* + * + * Copyright 2015, 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 <string.h> + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> +#include <grpc/support/log.h> +#include "src/core/client_config/resolver_registry.h" +#include "src/core/security/credentials.h" +#include "src/core/security/security_connector.h" +#include "src/core/surface/channel.h" +#include "test/core/util/test_config.h" + +void test_unknown_scheme_target(void) { + grpc_channel *chan; + grpc_channel_credentials *creds; + grpc_resolver_registry_shutdown(); + grpc_resolver_registry_init(""); + + creds = grpc_fake_transport_security_credentials_create(); + chan = grpc_secure_channel_create(creds, "blah://blah", NULL, NULL); + GPR_ASSERT(chan == NULL); + grpc_channel_credentials_unref(creds); +} + +void test_security_connector_already_in_arg(void) { + grpc_channel *chan; + grpc_channel_element *elem; + grpc_channel_args args; + grpc_arg arg; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + arg.type = GRPC_ARG_POINTER; + arg.value.pointer.p = NULL; + arg.key = GRPC_SECURITY_CONNECTOR_ARG; + args.num_args = 1; + args.args = &arg; + chan = grpc_secure_channel_create(NULL, NULL, &args, NULL); + elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_null_creds(void) { + grpc_channel *chan; + grpc_channel_element *elem; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + chan = grpc_secure_channel_create(NULL, NULL, NULL, NULL); + elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_security_connector_already_in_arg(); + test_null_creds(); + test_unknown_scheme_target(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c new file mode 100644 index 0000000000..ec7df6f0e3 --- /dev/null +++ b/test/core/surface/server_chttp2_test.c @@ -0,0 +1,49 @@ +/* + * + * Copyright 2015, 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 <grpc/grpc.h> +#include <grpc/support/log.h> +#include "test/core/util/test_config.h" + +void test_unparsable_target(void) { + int port = grpc_server_add_insecure_http2_port(NULL, "["); + GPR_ASSERT(port == 0); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_unparsable_target(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c new file mode 100644 index 0000000000..1d5211d225 --- /dev/null +++ b/test/core/surface/server_test.c @@ -0,0 +1,93 @@ +/* + * + * Copyright 2015, 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 <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +void test_register_method_fail(void) { + grpc_server *server = grpc_server_create(NULL, NULL); + void *method; + void *method_old; + method = grpc_server_register_method(server, NULL, NULL); + GPR_ASSERT(method == NULL); + method_old = grpc_server_register_method(server, "m", "h"); + GPR_ASSERT(method_old != NULL); + method = grpc_server_register_method(server, "m", "h"); + GPR_ASSERT(method == NULL); + grpc_server_destroy(server); +} + +void test_request_call_on_no_server_cq(void) { + grpc_completion_queue *cc = grpc_completion_queue_create(NULL); + GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == + grpc_server_request_call(NULL, NULL, NULL, NULL, cc, cc, NULL)); + GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == + grpc_server_request_registered_call(NULL, NULL, NULL, NULL, NULL, + NULL, cc, cc, NULL)); + grpc_completion_queue_destroy(cc); +} + +void test_bind_server_twice(void) { + char *addr; + grpc_server *server1 = grpc_server_create(NULL, NULL); + grpc_server *server2 = grpc_server_create(NULL, NULL); + grpc_completion_queue *cq = grpc_completion_queue_create(NULL); + int port = grpc_pick_unused_port_or_die(); + gpr_asprintf(&addr, "[::]:%d", port); + grpc_server_register_completion_queue(server1, cq, NULL); + grpc_server_register_completion_queue(server2, cq, NULL); + GPR_ASSERT(port == grpc_server_add_insecure_http2_port(server1, addr)); + GPR_ASSERT(0 == grpc_server_add_insecure_http2_port(server2, addr)); + grpc_server_shutdown_and_notify(server1, cq, NULL); + grpc_server_shutdown_and_notify(server2, cq, NULL); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); + grpc_server_destroy(server1); + grpc_server_destroy(server2); + grpc_completion_queue_destroy(cq); + gpr_free(addr); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_register_method_fail(); + test_request_call_on_no_server_cq(); + test_bind_server_twice(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c index e5c5d9a35e..31fcb7e182 100644 --- a/test/core/transport/chttp2/varint_test.c +++ b/test/core/transport/chttp2/varint_test.c @@ -47,14 +47,15 @@ static void test_varint(gpr_uint32 value, gpr_uint32 prefix_bits, gpr_log(GPR_DEBUG, "Test: 0x%08x", value); GPR_ASSERT(nbytes == expect_length); slice = gpr_slice_malloc(nbytes); - GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or, GPR_SLICE_START_PTR(slice), nbytes); + GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or, + GPR_SLICE_START_PTR(slice), nbytes); GPR_ASSERT(gpr_slice_cmp(expect, slice) == 0); gpr_slice_unref(expect); gpr_slice_unref(slice); } #define TEST_VARINT(value, prefix_bits, prefix_or, expect) \ - test_varint(value, prefix_bits, prefix_or, expect, sizeof(expect)-1) + test_varint(value, prefix_bits, prefix_or, expect, sizeof(expect) - 1) int main(int argc, char **argv) { grpc_test_init(argc, argv); diff --git a/test/core/transport/connectivity_state_test.c b/test/core/transport/connectivity_state_test.c new file mode 100644 index 0000000000..1f23221812 --- /dev/null +++ b/test/core/transport/connectivity_state_test.c @@ -0,0 +1,154 @@ +/* + * + * Copyright 2015, 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 "src/core/transport/connectivity_state.h" + +#include <string.h> + +#include <grpc/support/log.h> + +#include "test/core/util/test_config.h" + +#define THE_ARG ((void *)0xcafebabe) + +int g_counter; + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, int success) { + GPR_ASSERT(success); + GPR_ASSERT(arg == THE_ARG); + g_counter++; +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, int success) { + GPR_ASSERT(!success); + GPR_ASSERT(arg == THE_ARG); + g_counter++; +} + +static void test_connectivity_state_name(void) { + gpr_log(GPR_DEBUG, "test_connectivity_state_name"); + GPR_ASSERT(0 == + strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_IDLE), "IDLE")); + GPR_ASSERT(0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_CONNECTING), + "CONNECTING")); + GPR_ASSERT(0 == + strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_READY), "READY")); + GPR_ASSERT( + 0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_TRANSIENT_FAILURE), + "TRANSIENT_FAILURE")); + GPR_ASSERT(0 == + strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_FATAL_FAILURE), + "FATAL_FAILURE")); +} + +static void test_check(void) { + grpc_connectivity_state_tracker tracker; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_DEBUG, "test_check"); + grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); + GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE); + grpc_connectivity_state_destroy(&exec_ctx, &tracker); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_subscribe_then_unsubscribe(void) { + grpc_connectivity_state_tracker tracker; + grpc_closure *closure = grpc_closure_create(must_fail, THE_ARG); + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_DEBUG, "test_subscribe_then_unsubscribe"); + g_counter = 0; + grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); + GPR_ASSERT(grpc_connectivity_state_notify_on_state_change(&exec_ctx, &tracker, + &state, closure)); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_IDLE); + GPR_ASSERT(g_counter == 0); + grpc_connectivity_state_notify_on_state_change(&exec_ctx, &tracker, NULL, + closure); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_IDLE); + GPR_ASSERT(g_counter == 1); + + grpc_connectivity_state_destroy(&exec_ctx, &tracker); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_subscribe_then_destroy(void) { + grpc_connectivity_state_tracker tracker; + grpc_closure *closure = grpc_closure_create(must_succeed, THE_ARG); + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_DEBUG, "test_subscribe_then_destroy"); + g_counter = 0; + grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); + GPR_ASSERT(grpc_connectivity_state_notify_on_state_change(&exec_ctx, &tracker, + &state, closure)); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_IDLE); + GPR_ASSERT(g_counter == 0); + grpc_connectivity_state_destroy(&exec_ctx, &tracker); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_FATAL_FAILURE); + GPR_ASSERT(g_counter == 1); +} + +static void test_subscribe_with_failure_then_destroy(void) { + grpc_connectivity_state_tracker tracker; + grpc_closure *closure = grpc_closure_create(must_fail, THE_ARG); + grpc_connectivity_state state = GRPC_CHANNEL_FATAL_FAILURE; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_log(GPR_DEBUG, "test_subscribe_with_failure_then_destroy"); + g_counter = 0; + grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_FATAL_FAILURE, "xxx"); + GPR_ASSERT(0 == grpc_connectivity_state_notify_on_state_change( + &exec_ctx, &tracker, &state, closure)); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_FATAL_FAILURE); + GPR_ASSERT(g_counter == 0); + grpc_connectivity_state_destroy(&exec_ctx, &tracker); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_FATAL_FAILURE); + GPR_ASSERT(g_counter == 1); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_connectivity_state_trace = 1; + test_connectivity_state_name(); + test_check(); + test_subscribe_then_unsubscribe(); + test_subscribe_then_destroy(); + test_subscribe_with_failure_then_destroy(); + return 0; +} diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c index 84b376ad3e..14bfc957cb 100644 --- a/test/core/util/test_config.c +++ b/test/core/util/test_config.c @@ -127,6 +127,8 @@ static void crash_handler(int signum, siginfo_t *info, void *data) { backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO); } + /* try to get a core dump for SIGTERM */ + if (signum == SIGTERM) signum = SIGQUIT; raise(signum); } @@ -145,6 +147,8 @@ static void install_crash_handler() { GPR_ASSERT(sigaction(SIGABRT, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0); GPR_ASSERT(sigaction(SIGSEGV, &sa, NULL) == 0); + GPR_ASSERT(sigaction(SIGTERM, &sa, NULL) == 0); + GPR_ASSERT(sigaction(SIGQUIT, &sa, NULL) == 0); } #else static void install_crash_handler() {} |