diff options
Diffstat (limited to 'test/core')
117 files changed, 10576 insertions, 1069 deletions
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index ed46e7b009..e1a4b8ed90 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -64,14 +64,13 @@ static void done_write(grpc_exec_ctx *exec_ctx, void *arg, int success) { gpr_event_set(&a->done_write, (void *)1); } -static void server_setup_transport(void *ts, grpc_transport *transport, - grpc_mdctx *mdctx) { +static void server_setup_transport(void *ts, grpc_transport *transport) { thd_args *a = ts; static grpc_channel_filter const *extra_filters[] = { &grpc_http_server_filter}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_server_setup_transport(&exec_ctx, a->server, transport, extra_filters, - GPR_ARRAY_SIZE(extra_filters), mdctx, + GPR_ARRAY_SIZE(extra_filters), grpc_server_get_channel_args(a->server)); grpc_exec_ctx_finish(&exec_ctx); } @@ -84,7 +83,6 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, gpr_thd_id id; char *hex; grpc_transport *transport; - grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); gpr_slice_buffer outgoing; @@ -113,9 +111,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); grpc_server_start(a.server); - transport = - grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, mdctx, 0); - server_setup_transport(&a, transport, mdctx); + transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0); + server_setup_transport(&a, transport); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index 3df889ecda..386a8965db 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -40,8 +40,12 @@ 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, + 'simple_request': default_test_options, + 'unknown_frame': default_test_options, } def main(): diff --git a/test/core/bad_client/tests/bad_timeout.headers b/test/core/bad_client/tests/bad_timeout.headers new file mode 100644 index 0000000000..60c37b9ff6 --- /dev/null +++ b/test/core/bad_client/tests/bad_timeout.headers @@ -0,0 +1,2 @@ +# a badly encoded timeout value +grpc-timeout: 15 seconds
\ No newline at end of file diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c new file mode 100644 index 0000000000..f0d7dac0f5 --- /dev/null +++ b/test/core/bad_client/tests/badreq.c @@ -0,0 +1,139 @@ +/* + * + * 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) { + 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/headers.c b/test/core/bad_client/tests/headers.c new file mode 100644 index 0000000000..c404fd2d67 --- /dev/null +++ b/test/core/bad_client/tests/headers.c @@ -0,0 +1,305 @@ +/* + * + * 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 "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" + +static void verifier(grpc_server *server, grpc_completion_queue *cq) { + 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); + + /* partial http2 header prefixes */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x05", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + + /* test adding prioritization data */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x01\x01\x24\x00\x00\x00\x01" + "\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x02\x01\x24\x00\x00\x00\x01" + "\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x03\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x04\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + + /* test looking up an invalid index */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x01\x01\x04\x00\x00\x00\x01" + "\xfe", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\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", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\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", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\x11\x01" + "a", + GRPC_BAD_CLIENT_DISCONNECT); + /* illegal op code */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x01\x01\x04\x00\x00\x00\x01" + "\x80", + 0); + /* parse some long indices */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x02\x01\x04\x00\x00\x00\x01" + "\xff\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\xff\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x06\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x07\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x80\x80\x00", + 0); + /* overflow on byte 4 */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x06\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x7f", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x06\x01\x04\x00\x00\x00\x01" + "\xff\xff\xff\xff\xff\x0f", + GRPC_BAD_CLIENT_DISCONNECT); + /* overflow after byte 4 */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x80\x80\x02", + 0); + /* end of headers mid-opcode */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x01\x01\x04\x00\x00\x00\x01" + "\x01", + GRPC_BAD_CLIENT_DISCONNECT); + + /* dynamic table size update: set to default */ + 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 + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\x3f\xf1\x1f", + 0); + /* dynamic table size update: set twice */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\x20\x3f\xe1\x1f", + GRPC_BAD_CLIENT_DISCONNECT); + /* dynamic table size update: set thrice */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\x20\x20\x20", + 0); + + /* non-ending header followed by continuation frame */ + 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 + "\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 + "\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); + /* three header frames */ + 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", + GRPC_BAD_CLIENT_DISCONNECT); + + /* a badly encoded timeout value */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x19\x01\x04\x00\x00\x00\x01" + "\x10\x0cgrpc-timeout\x0a" + "15 seconds", + GRPC_BAD_CLIENT_DISCONNECT); + /* a badly encoded timeout value: twice (catches caching) */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x19\x01\x04\x00\x00\x00\x01" + "\x10\x0cgrpc-timeout\x0a" + "15 seconds" + "\x00\x00\x19\x01\x04\x00\x00\x00\x03" + "\x10\x0cgrpc-timeout\x0a" + "15 seconds", + GRPC_BAD_CLIENT_DISCONNECT); + + return 0; +} diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c index 827e93b67c..cd8771e88e 100644 --- a/test/core/bad_client/tests/initial_settings_frame.c +++ b/test/core/bad_client/tests/initial_settings_frame.c @@ -35,6 +35,7 @@ #include "src/core/surface/server.h" #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) { while (grpc_server_has_open_connections(server)) { @@ -90,6 +91,30 @@ int main(int argc, char **argv) { PFX_STR "\x00\x00\x04\x04\x00\x00\x00\x00\x00", 0); GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR "\x00\x00\x05\x04\x00\x00\x00\x00\x00", 0); + /* 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", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, + 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", + 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/simple_request.c b/test/core/bad_client/tests/simple_request.c new file mode 100644 index 0000000000..125a9fa1f2 --- /dev/null +++ b/test/core/bad_client/tests/simple_request.c @@ -0,0 +1,157 @@ +/* + * + * 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\xc9\x01\x04\x00\x00\x00\x01" /* headers: generated from \ + simple_request.headers in this \ + directory */ \ + "\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\x15" \ + "deflate,identity,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +#define PFX_STR_UNUSUAL \ + "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\xf4\x01\x04\x00\x00\x00\x01" /* headers: generated from \ + simple_request_unusual.headers \ + in this directory */ \ + "\x10\x05:path\x08/foo/bar" \ + "\x10\x07:scheme\x04http" \ + "\x10\x07:method\x04POST" \ + "\x10\x04host\x09localhost" \ + "\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" + +static void *tag(gpr_intptr t) { return (void *)t; } + +static void verifier(grpc_server *server, grpc_completion_queue *cq) { + grpc_call_error error; + grpc_call *s; + grpc_call_details call_details; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + + grpc_call_details_init(&call_details); + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_call(server, &s, &call_details, + &request_metadata_recv, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_expect_completion(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(0 == strcmp(call_details.host, "localhost")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar")); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_destroy(s); + cq_verifier_destroy(cqv); +} + +static void failure_verifier(grpc_server *server, grpc_completion_queue *cq) { + 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); + + /* basic request: check that things are working */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR_UNUSUAL, 0); + + /* push an illegal data frame */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR + "\x00\x00\x05\x00\x00\x00\x00\x00\x01" + "\x34\x00\x00\x00\x00", + 0); + + /* 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/simple_request.headers b/test/core/bad_client/tests/simple_request.headers new file mode 100644 index 0000000000..691fac161a --- /dev/null +++ b/test/core/bad_client/tests/simple_request.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: /foo/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_unusual.headers b/test/core/bad_client/tests/simple_request_unusual.headers new file mode 100644 index 0000000000..f36e1dfc9f --- /dev/null +++ b/test/core/bad_client/tests/simple_request_unusual.headers @@ -0,0 +1,13 @@ +# 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: /foo/bar +:scheme: http +:method: POST +host: localhost +content-type: application/grpc+this-is-valid +grpc-accept-encoding: deflate,identity,gzip +te: trailers +user-agent: bad-client grpc-c/0.12.0.0 (linux) +grpc-timeout: 10S +grpc-timeout: 5S diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c new file mode 100644 index 0000000000..3f8658b337 --- /dev/null +++ b/test/core/bad_client/tests/unknown_frame.c @@ -0,0 +1,58 @@ +/* + * + * 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 "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" + +static void verifier(grpc_server *server, grpc_completion_queue *cq) { + 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); + + /* test adding prioritization data */ + 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 076a122e20..f1bb37c0bf 100644 --- a/test/core/channel/channel_stack_test.c +++ b/test/core/channel/channel_stack_test.c @@ -42,22 +42,19 @@ #include "test/core/util/test_config.h" static void channel_init_func(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, grpc_channel *master, - const grpc_channel_args *args, - grpc_mdctx *metadata_context, int is_first, - int is_last) { - GPR_ASSERT(args->num_args == 1); - GPR_ASSERT(args->args[0].type == GRPC_ARG_INTEGER); - GPR_ASSERT(0 == strcmp(args->args[0].key, "test_key")); - GPR_ASSERT(args->args[0].value.integer == 42); - GPR_ASSERT(is_first); - GPR_ASSERT(is_last); + grpc_channel_element *elem, + grpc_channel_element_args *args) { + GPR_ASSERT(args->channel_args->num_args == 1); + GPR_ASSERT(args->channel_args->args[0].type == GRPC_ARG_INTEGER); + GPR_ASSERT(0 == strcmp(args->channel_args->args[0].key, "test_key")); + GPR_ASSERT(args->channel_args->args[0].value.integer == 42); + GPR_ASSERT(args->is_first); + GPR_ASSERT(args->is_last); *(int *)(elem->channel_data) = 0; } static void call_init_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const void *server_transport_data, - grpc_transport_stream_op *initial_op) { + grpc_call_element_args *args) { ++*(int *)(elem->channel_data); *(int *)(elem->call_data) = 0; } @@ -84,11 +81,21 @@ 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, call_destroy_func, - sizeof(int), channel_init_func, channel_destroy_func, get_peer, - "some_test_filter"}; + call_func, channel_func, sizeof(int), call_init_func, + grpc_call_stack_ignore_set_pollset, call_destroy_func, sizeof(int), + channel_init_func, channel_destroy_func, get_peer, "some_test_filter"}; const grpc_channel_filter *filters = &filter; grpc_channel_stack *channel_stack; grpc_call_stack *call_stack; @@ -96,13 +103,10 @@ static void test_create_channel_stack(void) { grpc_call_element *call_elem; grpc_arg arg; grpc_channel_args chan_args; - grpc_mdctx *metadata_context; int *channel_data; int *call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - metadata_context = grpc_mdctx_create(); - arg.type = GRPC_ARG_INTEGER; arg.key = "test_key"; arg.value.integer = 42; @@ -111,15 +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, - metadata_context, 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, 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); @@ -128,20 +133,19 @@ 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_mdctx_unref(metadata_context); + GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); grpc_exec_ctx_finish(&exec_ctx); } int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_create_channel_stack(); + grpc_shutdown(); return 0; } diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c index 02d3314eb8..9da4a4eec7 100644 --- a/test/core/client_config/lb_policies_test.c +++ b/test/core/client_config/lb_policies_test.c @@ -38,17 +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/surface/channel.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/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; @@ -119,14 +121,15 @@ static void test_spec_destroy(test_spec *spec) { static void *tag(gpr_intptr t) { return (void *)t; } -static gpr_timespec n_seconds_time(int n) { - return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +static gpr_timespec n_millis_time(int n) { + return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(n, GPR_TIMESPAN)); } static void drain_cq(grpc_completion_queue *cq) { grpc_event ev; do { - ev = grpc_completion_queue_next(cq, n_seconds_time(5), NULL); + ev = grpc_completion_queue_next(cq, n_millis_time(5000), NULL); } while (ev.type != GRPC_QUEUE_SHUTDOWN); } @@ -134,29 +137,47 @@ static void kill_server(const servers_fixture *f, size_t i) { gpr_log(GPR_INFO, "KILLING SERVER %d", i); GPR_ASSERT(f->servers[i] != NULL); grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), - GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), - NULL).type == GRPC_OP_COMPLETE); + GPR_ASSERT( + grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL) + .type == GRPC_OP_COMPLETE); grpc_server_destroy(f->servers[i]); f->servers[i] = NULL; } -static void revive_server(const servers_fixture *f, size_t i) { +typedef struct request_data { + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + char *details; + size_t details_capacity; + grpc_status_code status; + grpc_call_details *call_details; +} request_data; + +static void revive_server(const servers_fixture *f, request_data *rdata, + size_t i) { int got_port; gpr_log(GPR_INFO, "RAISE AGAIN SERVER %d", i); GPR_ASSERT(f->servers[i] == NULL); + + gpr_log(GPR_DEBUG, "revive: %s", f->servers_hostports[i]); + f->servers[i] = grpc_server_create(NULL, NULL); grpc_server_register_completion_queue(f->servers[i], f->cq, NULL); GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port( f->servers[i], f->servers_hostports[i])) > 0); grpc_server_start(f->servers[i]); + + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(f->servers[i], &f->server_calls[i], + &rdata->call_details[i], + &f->request_metadata_recv[i], f->cq, + f->cq, tag(1000 + (int)i))); } static servers_fixture *setup_servers(const char *server_host, + request_data *rdata, const size_t num_servers) { servers_fixture *f = gpr_malloc(sizeof(servers_fixture)); - int *ports; - int got_port; size_t i; f->num_servers = num_servers; @@ -164,23 +185,16 @@ static servers_fixture *setup_servers(const char *server_host, f->request_metadata_recv = gpr_malloc(sizeof(grpc_metadata_array) * num_servers); /* Create servers. */ - ports = gpr_malloc(sizeof(int *) * num_servers); f->servers = gpr_malloc(sizeof(grpc_server *) * num_servers); f->servers_hostports = gpr_malloc(sizeof(char *) * num_servers); f->cq = grpc_completion_queue_create(NULL); for (i = 0; i < num_servers; i++) { - ports[i] = grpc_pick_unused_port_or_die(); - - gpr_join_host_port(&f->servers_hostports[i], server_host, ports[i]); - - f->servers[i] = grpc_server_create(NULL, NULL); - grpc_server_register_completion_queue(f->servers[i], f->cq, NULL); - GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port( - f->servers[i], f->servers_hostports[i])) > 0); - GPR_ASSERT(ports[i] == got_port); - grpc_server_start(f->servers[i]); + grpc_metadata_array_init(&f->request_metadata_recv[i]); + gpr_join_host_port(&f->servers_hostports[i], server_host, + grpc_pick_unused_port_or_die()); + f->servers[i] = 0; + revive_server(f, rdata, i); } - gpr_free(ports); return f; } @@ -191,8 +205,8 @@ static void teardown_servers(servers_fixture *f) { if (f->servers[i] == NULL) continue; grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000)); GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), - GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), - NULL).type == GRPC_OP_COMPLETE); + n_millis_time(5000), NULL) + .type == GRPC_OP_COMPLETE); grpc_server_destroy(f->servers[i]); } grpc_completion_queue_shutdown(f->cq); @@ -203,6 +217,7 @@ static void teardown_servers(servers_fixture *f) { for (i = 0; i < f->num_servers; i++) { gpr_free(f->servers_hostports[i]); + grpc_metadata_array_destroy(&f->request_metadata_recv[i]); } gpr_free(f->servers_hostports); @@ -211,22 +226,12 @@ static void teardown_servers(servers_fixture *f) { gpr_free(f); } -typedef struct request_data { - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - char *details; - size_t details_capacity; - grpc_status_code status; - grpc_call_details *call_details; -} request_data; - /** 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; - gpr_timespec deadline; grpc_op ops[6]; grpc_op *op; int was_cancelled; @@ -234,14 +239,11 @@ int *perform_request(servers_fixture *f, grpc_channel *client, grpc_event ev; int read_tag; int *connection_sequence; + int completed_client; s_valid = gpr_malloc(sizeof(int) * f->num_servers); - rdata->call_details = gpr_malloc(sizeof(grpc_call_details) * f->num_servers); connection_sequence = gpr_malloc(sizeof(int) * spec->num_iters); - /* Send a trivial request. */ - deadline = n_seconds_time(60); - for (iter_num = 0; iter_num < spec->num_iters; iter_num++) { cq_verifier *cqv = cq_verifier_create(f->cq); rdata->details = NULL; @@ -253,7 +255,7 @@ int *perform_request(servers_fixture *f, grpc_channel *client, kill_server(f, i); } else if (spec->revive_at[iter_num][i] != 0) { /* killing takes precedence */ - revive_server(f, i); + revive_server(f, rdata, i); } } @@ -267,8 +269,10 @@ int *perform_request(servers_fixture *f, grpc_channel *client, memset(s_valid, 0, f->num_servers * sizeof(int)); c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - "/foo", "foo.test.google.fr", deadline, NULL); + "/foo", "foo.test.google.fr", + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GPR_ASSERT(c); + completed_client = 0; op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; @@ -298,22 +302,11 @@ int *perform_request(servers_fixture *f, grpc_channel *client, GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL)); - /* "listen" on all servers */ - for (i = 0; i < f->num_servers; i++) { - grpc_metadata_array_init(&f->request_metadata_recv[i]); - if (f->servers[i] != NULL) { - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->servers[i], &f->server_calls[i], - &rdata->call_details[i], - &f->request_metadata_recv[i], f->cq, - f->cq, tag(1000 + (int)i))); - } - } - s_idx = -1; while ((ev = grpc_completion_queue_next( - f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type != - GRPC_QUEUE_TIMEOUT) { + f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)) + .type != GRPC_QUEUE_TIMEOUT) { + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); read_tag = ((int)(gpr_intptr)ev.tag); gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d", ev.success, ev.type, read_tag, iter_num); @@ -323,6 +316,11 @@ int *perform_request(servers_fixture *f, grpc_channel *client, s_idx = read_tag - 1000; s_valid[s_idx] = 1; connection_sequence[iter_num] = s_idx; + break; + } else if (read_tag == 1) { + gpr_log(GPR_DEBUG, "client timed out"); + GPR_ASSERT(ev.success); + completed_client = 1; } } @@ -350,24 +348,35 @@ int *perform_request(servers_fixture *f, grpc_channel *client, tag(102), NULL)); cq_expect_completion(cqv, tag(102), 1); - cq_expect_completion(cqv, tag(1), 1); + if (!completed_client) { + cq_expect_completion(cqv, tag(1), 1); + } cq_verify(cqv); + gpr_log(GPR_DEBUG, "status=%d; %s", rdata->status, rdata->details); GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(rdata->details, "xyz")); GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].method, "/foo")); GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 1); - } else { - } - for (i = 0; i < f->num_servers; i++) { - if (s_valid[i] != 0) { - grpc_call_destroy(f->server_calls[i]); + grpc_call_destroy(f->server_calls[s_idx]); + + /* ask for the next request on this server */ + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f->servers[s_idx], &f->server_calls[s_idx], + &rdata->call_details[s_idx], + &f->request_metadata_recv[s_idx], f->cq, + f->cq, tag(1000 + (int)s_idx))); + } else { /* no response from server */ + grpc_call_cancel(c, NULL); + if (!completed_client) { + cq_expect_completion(cqv, tag(1), 1); + cq_verify(cqv); } - grpc_metadata_array_destroy(&f->request_metadata_recv[i]); } + grpc_metadata_array_destroy(&rdata->initial_metadata_recv); grpc_metadata_array_destroy(&rdata->trailing_metadata_recv); @@ -381,12 +390,47 @@ int *perform_request(servers_fixture *f, grpc_channel *client, gpr_free(rdata->details); } - gpr_free(rdata->call_details); gpr_free(s_valid); 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, ...) { @@ -444,14 +488,26 @@ void run_spec(const test_spec *spec) { char *servers_hostports_str; int *actual_connection_sequence; request_data rdata; - servers_fixture *f = setup_servers("127.0.0.1", spec->num_servers); + servers_fixture *f; + grpc_channel_args args; + grpc_arg arg; + rdata.call_details = + gpr_malloc(sizeof(grpc_call_details) * spec->num_servers); + f = setup_servers("127.0.0.1", &rdata, spec->num_servers); /* Create client. */ 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); - client = grpc_insecure_channel_create(client_hostport, NULL, NULL); + + 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_log(GPR_INFO, "Testing '%s' with servers=%s client=%s", spec->description, servers_hostports_str, client_hostport); @@ -463,9 +519,112 @@ void run_spec(const test_spec *spec) { gpr_free(client_hostport); gpr_free(servers_hostports_str); 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, @@ -692,9 +851,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(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); @@ -708,7 +872,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; @@ -737,9 +902,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/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c new file mode 100644 index 0000000000..ceca56c833 --- /dev/null +++ b/test/core/client_config/set_initial_connect_string_test.c @@ -0,0 +1,221 @@ +/* + * + * 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/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/slice.h> + +#include "src/core/client_config/initial_connect_string.h" +#include "src/core/iomgr/sockaddr.h" +#include "src/core/security/credentials.h" +#include "src/core/support/string.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/core/util/test_tcp_server.h" + +struct rpc_state { + char *target; + grpc_channel_credentials *creds; + grpc_completion_queue *cq; + grpc_channel *channel; + grpc_call *call; + grpc_op op; + gpr_slice_buffer incoming_buffer; + gpr_slice_buffer temp_incoming_buffer; + grpc_endpoint *tcp; + int done; +}; + +static const char *magic_connect_string = "magic initial string"; +static int server_port; +static struct rpc_state state; +static grpc_closure on_read; + +static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, int success) { + GPR_ASSERT(success); + gpr_slice_buffer_move_into(&state.temp_incoming_buffer, + &state.incoming_buffer); + if (state.incoming_buffer.length > strlen(magic_connect_string)) { + state.done = 1; + grpc_endpoint_shutdown(exec_ctx, state.tcp); + grpc_endpoint_destroy(exec_ctx, state.tcp); + } else { + grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer, + &on_read); + } +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp) { + test_tcp_server *server = arg; + grpc_closure_init(&on_read, handle_read, NULL); + gpr_slice_buffer_init(&state.incoming_buffer); + gpr_slice_buffer_init(&state.temp_incoming_buffer); + state.tcp = tcp; + grpc_endpoint_add_to_pollset(exec_ctx, tcp, &server->pollset); + grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read); +} + +static void set_magic_initial_string(struct sockaddr **addr, size_t *addr_len, + gpr_slice *connect_string) { + GPR_ASSERT(addr); + GPR_ASSERT(addr_len); + *connect_string = gpr_slice_from_copied_string(magic_connect_string); +} + +static void reset_addr_and_set_magic_string(struct sockaddr **addr, + size_t *addr_len, + gpr_slice *connect_string) { + struct sockaddr_in target; + *connect_string = gpr_slice_from_copied_string(magic_connect_string); + gpr_free(*addr); + target.sin_family = AF_INET; + target.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + target.sin_port = htons((uint16_t)server_port); + *addr_len = sizeof(target); + *addr = (struct sockaddr *)gpr_malloc(sizeof(target)); + memcpy(*addr, &target, sizeof(target)); +} + +static gpr_timespec n_sec_deadline(int seconds) { + return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(seconds, GPR_TIMESPAN)); +} + +static void start_rpc(int use_creds, int target_port) { + state.done = 0; + state.cq = grpc_completion_queue_create(NULL); + if (use_creds) { + state.creds = grpc_fake_transport_security_credentials_create(); + } else { + state.creds = NULL; + } + gpr_join_host_port(&state.target, "127.0.0.1", target_port); + if (use_creds) { + state.channel = + grpc_secure_channel_create(state.creds, state.target, NULL, NULL); + } else { + state.channel = grpc_insecure_channel_create(state.target, NULL, NULL); + } + state.call = grpc_channel_create_call( + state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method", + "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + state.op.op = GRPC_OP_SEND_INITIAL_METADATA; + state.op.data.send_initial_metadata.count = 0; + state.op.flags = 0; + state.op.reserved = NULL; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(state.call, &state.op, + (size_t)(1), NULL, NULL)); + grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL); +} + +static void cleanup_rpc(void) { + grpc_event ev; + gpr_slice_buffer_destroy(&state.incoming_buffer); + gpr_slice_buffer_destroy(&state.temp_incoming_buffer); + grpc_channel_credentials_unref(state.creds); + grpc_call_destroy(state.call); + grpc_completion_queue_shutdown(state.cq); + do { + ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(state.cq); + grpc_channel_destroy(state.channel); + gpr_free(state.target); +} + +static void poll_server_until_read_done(test_tcp_server *server) { + gpr_timespec deadline = n_sec_deadline(5); + while (state.done == 0 && + gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { + test_tcp_server_poll(server, 1); + } +} + +static void match_initial_magic_string(gpr_slice_buffer *buffer) { + size_t i, j, cmp_length; + size_t magic_length = strlen(magic_connect_string); + GPR_ASSERT(buffer->length >= magic_length); + for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) { + char *dump = + gpr_dump_slice(state.incoming_buffer.slices[i], GPR_DUMP_ASCII); + cmp_length = GPR_MIN(strlen(dump), magic_length - j); + GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0); + j += cmp_length; + gpr_free(dump); + } +} + +static void test_initial_string(test_tcp_server *server, int secure) { + grpc_test_set_initial_connect_string_function(set_magic_initial_string); + start_rpc(secure, server_port); + poll_server_until_read_done(server); + match_initial_magic_string(&state.incoming_buffer); + cleanup_rpc(); +} + +static void test_initial_string_with_redirect(test_tcp_server *server, + int secure) { + int another_port = grpc_pick_unused_port_or_die(); + grpc_test_set_initial_connect_string_function( + reset_addr_and_set_magic_string); + start_rpc(secure, another_port); + poll_server_until_read_done(server); + match_initial_magic_string(&state.incoming_buffer); + cleanup_rpc(); +} + +static void run_test(void (*test)(test_tcp_server *server, int secure), + int secure) { + test_tcp_server test_server; + server_port = grpc_pick_unused_port_or_die(); + test_tcp_server_init(&test_server, on_connect, &test_server); + test_tcp_server_start(&test_server, server_port); + test(&test_server, secure); + test_tcp_server_destroy(&test_server); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + run_test(test_initial_string, 0); + run_test(test_initial_string, 1); + run_test(test_initial_string_with_redirect, 0); + run_test(test_initial_string_with_redirect, 1); + + grpc_shutdown(); + 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 633fbd97f4..26d7b2b6cc 100644 --- a/test/core/compression/compression_test.c +++ b/test/core/compression/compression_test.c @@ -35,6 +35,7 @@ #include <string.h> #include <grpc/compression.h> +#include <grpc/grpc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> @@ -52,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]); } @@ -70,8 +70,80 @@ 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 98da6a1eaa..e5a01ef69e 100644 --- a/test/core/compression/message_compress_test.c +++ b/test/core/compression/message_compress_test.c @@ -36,11 +36,13 @@ #include <stdlib.h> #include <string.h> -#include "test/core/util/test_config.h" -#include "src/core/support/murmur_hash.h" +#include <grpc/grpc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> + +#include "src/core/support/murmur_hash.h" #include "test/core/util/slice_splitter.h" +#include "test/core/util/test_config.h" typedef enum { ONE_A = 0, ONE_KB_A, ONE_MB_A, TEST_VALUE_COUNT } test_value; @@ -146,26 +148,130 @@ 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; + int was_compressed; + + 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")); + was_compressed = + grpc_msg_compress(GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); + GPR_ASSERT(0 == was_compressed); + + was_compressed = + grpc_msg_compress(GRPC_COMPRESS_ALGORITHMS_COUNT + 123, &input, &output); + GPR_ASSERT(0 == was_compressed); + + gpr_slice_buffer_destroy(&input); + gpr_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_algorithm(void) { + gpr_slice_buffer input; + gpr_slice_buffer output; + int was_decompressed; + + gpr_slice_buffer_init(&input); + gpr_slice_buffer_init(&output); + gpr_slice_buffer_add(&input, + gpr_slice_from_copied_string( + "I'm not really compressed but it doesn't matter")); + was_decompressed = + 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); + GPR_ASSERT(0 == was_decompressed); + + gpr_slice_buffer_destroy(&input); + gpr_slice_buffer_destroy(&output); +} + int main(int argc, char **argv) { unsigned i, j, k, m; grpc_slice_split_mode uncompressed_split_modes[] = { @@ -175,6 +281,7 @@ int main(int argc, char **argv) { GRPC_SLICE_SPLIT_ONE_BYTE}; grpc_test_init(argc, argv); + grpc_init(); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { for (j = 0; j < GPR_ARRAY_SIZE(uncompressed_split_modes); j++) { @@ -188,7 +295,13 @@ 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(); return 0; } 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_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c index 1f5051f0ab..ccc8631d94 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.c +++ b/test/core/end2end/fixtures/h2_sockpair+trace.c @@ -57,14 +57,13 @@ /* chttp2 transport that is immediately available (used for testing connected_channel without a client_channel */ -static void server_setup_transport(void *ts, grpc_transport *transport, - grpc_mdctx *mdctx) { +static void server_setup_transport(void *ts, grpc_transport *transport) { grpc_end2end_test_fixture *f = ts; static grpc_channel_filter const *extra_filters[] = { &grpc_http_server_filter}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_server_setup_transport(&exec_ctx, f->server, transport, extra_filters, - GPR_ARRAY_SIZE(extra_filters), mdctx, + GPR_ARRAY_SIZE(extra_filters), grpc_server_get_channel_args(f->server)); grpc_exec_ctx_finish(&exec_ctx); } @@ -75,17 +74,15 @@ typedef struct { } sp_client_setup; static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport, - grpc_mdctx *mdctx) { + grpc_transport *transport) { sp_client_setup *cs = ts; const grpc_channel_filter *filters[] = {&grpc_http_client_filter, &grpc_compress_filter, &grpc_connected_channel_filter}; size_t nfilters = sizeof(filters) / sizeof(*filters); - grpc_channel *channel = - grpc_channel_create_from_filters(exec_ctx, "socketpair-target", filters, - nfilters, cs->client_args, mdctx, 1); + grpc_channel *channel = grpc_channel_create_from_filters( + exec_ctx, "socketpair-target", filters, nfilters, cs->client_args, 1); cs->f->client = channel; @@ -112,13 +109,12 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; grpc_transport *transport; - grpc_mdctx *mdctx = grpc_mdctx_create(); sp_client_setup cs; cs.client_args = client_args; cs.f = f; - transport = grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, - mdctx, 1); - client_setup_transport(&exec_ctx, &cs, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, 1); + client_setup_transport(&exec_ctx, &cs, transport); GPR_ASSERT(f->client); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); @@ -128,15 +124,14 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; - grpc_mdctx *mdctx = grpc_mdctx_create(); grpc_transport *transport; GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(NULL, 0, server_args); grpc_server_register_completion_queue(f->server, f->cq, NULL); grpc_server_start(f->server); - transport = grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, - mdctx, 0); - server_setup_transport(f, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, 0); + server_setup_transport(f, transport); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c index b61fe98610..a6a84c9b1a 100644 --- a/test/core/end2end/fixtures/h2_sockpair.c +++ b/test/core/end2end/fixtures/h2_sockpair.c @@ -56,14 +56,13 @@ /* chttp2 transport that is immediately available (used for testing connected_channel without a client_channel */ -static void server_setup_transport(void *ts, grpc_transport *transport, - grpc_mdctx *mdctx) { +static void server_setup_transport(void *ts, grpc_transport *transport) { grpc_end2end_test_fixture *f = ts; static grpc_channel_filter const *extra_filters[] = { &grpc_http_server_filter}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_server_setup_transport(&exec_ctx, f->server, transport, extra_filters, - GPR_ARRAY_SIZE(extra_filters), mdctx, + GPR_ARRAY_SIZE(extra_filters), grpc_server_get_channel_args(f->server)); grpc_exec_ctx_finish(&exec_ctx); } @@ -74,17 +73,15 @@ typedef struct { } sp_client_setup; static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport, - grpc_mdctx *mdctx) { + grpc_transport *transport) { sp_client_setup *cs = ts; const grpc_channel_filter *filters[] = {&grpc_http_client_filter, &grpc_compress_filter, &grpc_connected_channel_filter}; size_t nfilters = sizeof(filters) / sizeof(*filters); - grpc_channel *channel = - grpc_channel_create_from_filters(exec_ctx, "socketpair-target", filters, - nfilters, cs->client_args, mdctx, 1); + grpc_channel *channel = grpc_channel_create_from_filters( + exec_ctx, "socketpair-target", filters, nfilters, cs->client_args, 1); cs->f->client = channel; @@ -111,13 +108,12 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; grpc_transport *transport; - grpc_mdctx *mdctx = grpc_mdctx_create(); sp_client_setup cs; cs.client_args = client_args; cs.f = f; - transport = grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, - mdctx, 1); - client_setup_transport(&exec_ctx, &cs, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, 1); + client_setup_transport(&exec_ctx, &cs, transport); GPR_ASSERT(f->client); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); @@ -127,15 +123,14 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; - grpc_mdctx *mdctx = grpc_mdctx_create(); grpc_transport *transport; GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(NULL, 0, server_args); grpc_server_register_completion_queue(f->server, f->cq, NULL); grpc_server_start(f->server); - transport = grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, - mdctx, 0); - server_setup_transport(f, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, 0); + server_setup_transport(f, transport); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c index 9f0fd2ea9a..4b8f9054ef 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.c +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c @@ -56,14 +56,13 @@ /* chttp2 transport that is immediately available (used for testing connected_channel without a client_channel */ -static void server_setup_transport(void *ts, grpc_transport *transport, - grpc_mdctx *mdctx) { +static void server_setup_transport(void *ts, grpc_transport *transport) { grpc_end2end_test_fixture *f = ts; static grpc_channel_filter const *extra_filters[] = { &grpc_http_server_filter}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_server_setup_transport(&exec_ctx, f->server, transport, extra_filters, - GPR_ARRAY_SIZE(extra_filters), mdctx, + GPR_ARRAY_SIZE(extra_filters), grpc_server_get_channel_args(f->server)); grpc_exec_ctx_finish(&exec_ctx); } @@ -74,17 +73,15 @@ typedef struct { } sp_client_setup; static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport, - grpc_mdctx *mdctx) { + grpc_transport *transport) { sp_client_setup *cs = ts; const grpc_channel_filter *filters[] = {&grpc_http_client_filter, &grpc_compress_filter, &grpc_connected_channel_filter}; size_t nfilters = sizeof(filters) / sizeof(*filters); - grpc_channel *channel = - grpc_channel_create_from_filters(exec_ctx, "socketpair-target", filters, - nfilters, cs->client_args, mdctx, 1); + grpc_channel *channel = grpc_channel_create_from_filters( + exec_ctx, "socketpair-target", filters, nfilters, cs->client_args, 1); cs->f->client = channel; @@ -111,13 +108,12 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; grpc_transport *transport; - grpc_mdctx *mdctx = grpc_mdctx_create(); sp_client_setup cs; cs.client_args = client_args; cs.f = f; - transport = grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, - mdctx, 1); - client_setup_transport(&exec_ctx, &cs, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, client_args, sfd->client, 1); + client_setup_transport(&exec_ctx, &cs, transport); GPR_ASSERT(f->client); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); @@ -127,15 +123,14 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; - grpc_mdctx *mdctx = grpc_mdctx_create(); grpc_transport *transport; GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(NULL, 0, server_args); grpc_server_register_completion_queue(f->server, f->cq, NULL); grpc_server_start(f->server); - transport = grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, - mdctx, 0); - server_setup_transport(f, transport, mdctx); + transport = + grpc_create_chttp2_transport(&exec_ctx, server_args, sfd->server, 0); + server_setup_transport(f, transport); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL, 0); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/test/core/end2end/fixtures/h2_uchannel.c b/test/core/end2end/fixtures/h2_uchannel.c index d1f9d38b82..ea630c3275 100644 --- a/test/core/end2end/fixtures/h2_uchannel.c +++ b/test/core/end2end/fixtures/h2_uchannel.c @@ -66,8 +66,6 @@ typedef struct { grpc_endpoint *tcp; - grpc_mdctx *mdctx; - grpc_closure connected; } connector; @@ -79,7 +77,6 @@ static void connector_ref(grpc_connector *con) { static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { connector *c = (connector *)con; if (gpr_unref(&c->refs)) { - grpc_mdctx_unref(c->mdctx); gpr_free(c); } } @@ -89,8 +86,8 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) { grpc_closure *notify; grpc_endpoint *tcp = c->tcp; if (tcp != NULL) { - c->result->transport = grpc_create_chttp2_transport( - exec_ctx, c->args.channel_args, tcp, c->mdctx, 1); + c->result->transport = + grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1); grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0); GPR_ASSERT(c->result->transport); @@ -130,7 +127,6 @@ static const grpc_connector_vtable connector_vtable = { typedef struct { grpc_subchannel_factory base; gpr_refcount refs; - grpc_mdctx *mdctx; grpc_channel_args *merge_args; grpc_channel *master; grpc_subchannel **sniffed_subchannel; @@ -147,7 +143,6 @@ static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, if (gpr_unref(&f->refs)) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); grpc_channel_args_destroy(f->merge_args); - grpc_mdctx_unref(f->mdctx); gpr_free(f); } } @@ -162,16 +157,16 @@ static grpc_subchannel *subchannel_factory_create_subchannel( grpc_subchannel *s; memset(c, 0, sizeof(*c)); c->base.vtable = &connector_vtable; - c->mdctx = f->mdctx; - grpc_mdctx_ref(c->mdctx); gpr_ref_init(&c->refs, 1); - args->mdctx = f->mdctx; 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; } @@ -188,22 +183,19 @@ grpc_channel *channel_create(const char *target, const grpc_channel_args *args, const grpc_channel_filter *filters[MAX_FILTERS]; grpc_resolver *resolver; subchannel_factory *f; - grpc_mdctx *mdctx = grpc_mdctx_create(); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; size_t n = 0; filters[n++] = &grpc_client_channel_filter; GPR_ASSERT(n <= MAX_FILTERS); - channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n, - args, mdctx, 1); + channel = + grpc_channel_create_from_filters(&exec_ctx, target, filters, n, args, 1); f = gpr_malloc(sizeof(*f)); f->sniffed_subchannel = sniffed_subchannel; f->base.vtable = &test_subchannel_factory_vtable; gpr_ref_init(&f->refs, 1); - grpc_mdctx_ref(mdctx); - f->mdctx = mdctx; f->merge_args = grpc_channel_args_copy(args); f->master = channel; GRPC_CHANNEL_INTERNAL_REF(f->master, "test_subchannel_factory"); @@ -235,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); @@ -244,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); @@ -263,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); @@ -284,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 af8f48576c..9f94cfe6be 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -37,8 +37,11 @@ import collections import hashlib -FixtureOptions = collections.namedtuple('FixtureOptions', 'fullstack includes_proxy dns_resolver secure platforms ci_mac') -default_unsecure_fixture_options = FixtureOptions(True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True) +FixtureOptions = collections.namedtuple( + 'FixtureOptions', + 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing') +default_unsecure_fixture_options = FixtureOptions( + True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False) socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False) default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True) uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix']) @@ -46,62 +49,78 @@ 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_uchannel': default_unsecure_fixture_options, - 'h2_compress': default_unsecure_fixture_options, - 'h2_uds': uds_fixture_options, - 'h2_uds+poll': uds_fixture_options._replace(platforms=['linux']), - 'h2_full+poll': default_unsecure_fixture_options._replace(platforms=['linux']), - 'h2_proxy': default_unsecure_fixture_options._replace(includes_proxy=True, ci_mac=False), - 'h2_ssl': default_secure_fixture_options, - '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_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), + 'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace( + ci_mac=False), 'h2_sockpair': socketpair_unsecure_fixture_options._replace(ci_mac=False), - 'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace(ci_mac=False), - 'h2_sockpair+trace': socketpair_unsecure_fixture_options, + 'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace( + tracing=True), + 'h2_ssl': default_secure_fixture_options, + '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._replace(fullstack=False), + 'h2_uds+poll': uds_fixture_options._replace(platforms=['linux']), + 'h2_uds': uds_fixture_options, } -TestOptions = collections.namedtuple('TestOptions', 'needs_fullstack needs_dns proxyable flaky secure') -default_test_options = TestOptions(False, False, True, False, False) +TestOptions = collections.namedtuple( + 'TestOptions', 'needs_fullstack needs_dns proxyable flaky secure traceable') +default_test_options = TestOptions(False, False, True, False, False, True) connectivity_test_options = default_test_options._replace(needs_fullstack=True) # maps test names to options END2END_TESTS = { 'bad_hostname': default_test_options, - 'cancel_after_client_done': default_test_options, + 'binary_metadata': default_test_options, + 'call_creds': default_test_options._replace(secure=True), 'cancel_after_accept': default_test_options, + 'cancel_after_client_done': default_test_options, 'cancel_after_invoke': default_test_options, 'cancel_before_invoke': default_test_options, 'cancel_in_a_vacuum': default_test_options, - 'census_simple_request': default_test_options, + 'cancel_with_status': default_test_options, 'channel_connectivity': connectivity_test_options._replace(proxyable=False), - 'default_host': default_test_options._replace(needs_fullstack=True, needs_dns=True), + '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), 'disappearing_server': connectivity_test_options, - 'shutdown_finishes_calls': default_test_options, - 'shutdown_finishes_tags': default_test_options, 'empty_batch': default_test_options, 'graceful_server_shutdown': default_test_options, + 'hpack_size': default_test_options._replace(proxyable=False, + traceable=False), + 'high_initial_seqno': default_test_options, 'invoke_large_request': default_test_options, + 'large_metadata': default_test_options, 'max_concurrent_streams': default_test_options._replace(proxyable=False), 'max_message_length': default_test_options, + 'metadata': default_test_options, + 'negative_deadline': default_test_options, 'no_op': default_test_options, + 'payload': default_test_options, 'ping_pong_streaming': default_test_options, 'registered_call': default_test_options, - 'binary_metadata': default_test_options, - 'metadata': default_test_options, - 'call_creds': default_test_options._replace(secure=True), - 'payload': default_test_options, - 'trailing_metadata': default_test_options, - 'compressed_payload': default_test_options._replace(proxyable=False), 'request_with_flags': default_test_options._replace(proxyable=False), - 'large_metadata': default_test_options, 'request_with_payload': default_test_options, 'server_finishes_request': default_test_options, + 'shutdown_finishes_calls': default_test_options, + 'shutdown_finishes_tags': default_test_options, 'simple_delayed_request': connectivity_test_options, 'simple_request': default_test_options, - 'high_initial_seqno': default_test_options, + 'trailing_metadata': default_test_options, } @@ -115,6 +134,9 @@ def compatible(f, t): if not END2END_TESTS[t].proxyable: if END2END_FIXTURES[f].includes_proxy: return False + if not END2END_TESTS[t].traceable: + if END2END_FIXTURES[f].tracing: + return False return True @@ -147,12 +169,27 @@ def main(): 'language': 'c', 'secure': 'check' if END2END_FIXTURES[f].secure else False, 'src': ['test/core/end2end/fixtures/%s.c' % f], - 'platforms': [ 'linux', 'mac', 'posix' ] if f.endswith('_posix') else END2END_FIXTURES[f].platforms, - 'deps': sec_deps if END2END_FIXTURES[f].secure else unsec_deps, + 'platforms': ['linux', 'mac', 'posix'] if f.endswith('_posix') + else END2END_FIXTURES[f].platforms, + 'deps': sec_deps, 'headers': ['test/core/end2end/end2end_tests.h'], 'vs_proj_dir': 'test', - } - for f in sorted(END2END_FIXTURES.keys())] + [ + } for f in sorted(END2END_FIXTURES.keys()) + ] + [ + { + 'name': 'end2end_nosec_fixture_%s' % f, + 'build': 'private', + 'language': 'c', + 'secure': False, + 'src': ['test/core/end2end/fixtures/%s.c' % f], + 'platforms': ['linux', 'mac', 'posix'] if f.endswith('_posix') + else END2END_FIXTURES[f].platforms, + 'deps': unsec_deps, + 'headers': ['test/core/end2end/end2end_tests.h'], + 'vs_proj_dir': 'test', + } for f in sorted(END2END_FIXTURES.keys()) + if not END2END_FIXTURES[f].secure + ] + [ { 'name': 'end2end_test_%s' % t, 'build': 'private', @@ -161,10 +198,23 @@ def main(): 'src': ['test/core/end2end/tests/%s.c' % t], 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', 'test/core/end2end/end2end_tests.h'], - 'deps': sec_deps if END2END_TESTS[t].secure else unsec_deps, + 'deps': sec_deps, 'vs_proj_dir': 'test', - } - for t in sorted(END2END_TESTS.keys())] + [ + } for t in sorted(END2END_TESTS.keys()) + ] + [ + { + 'name': 'end2end_nosec_test_%s' % t, + 'build': 'private', + 'language': 'c', + 'secure': False, + 'src': ['test/core/end2end/tests/%s.c' % t], + 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', + 'test/core/end2end/end2end_tests.h'], + 'deps': unsec_deps, + 'vs_proj_dir': 'test', + } for t in sorted(END2END_TESTS.keys()) + if not END2END_TESTS[t].secure + ] + [ { 'name': 'end2end_certs', 'build': 'private', @@ -176,7 +226,7 @@ def main(): ], 'vs_proj_dir': 'test', } - ], + ], 'targets': [ { 'name': '%s_%s_test' % (f, t), @@ -185,17 +235,17 @@ def main(): 'src': [], 'flaky': END2END_TESTS[t].flaky, 'platforms': END2END_FIXTURES[f].platforms, - 'ci_platforms': (END2END_FIXTURES[f].platforms - if END2END_FIXTURES[f].ci_mac - else without(END2END_FIXTURES[f].platforms, 'mac')), + 'ci_platforms': (END2END_FIXTURES[f].platforms + if END2END_FIXTURES[f].ci_mac else without( + END2END_FIXTURES[f].platforms, 'mac')), 'deps': [ - 'end2end_fixture_%s' % f, - 'end2end_test_%s' % t] + sec_deps, + 'end2end_fixture_%s' % f, 'end2end_test_%s' % t + ] + sec_deps, 'vs_proj_dir': 'test', } - for f in sorted(END2END_FIXTURES.keys()) - for t in sorted(END2END_TESTS.keys()) - if compatible(f, t)] + [ + for f in sorted(END2END_FIXTURES.keys()) + for t in sorted(END2END_TESTS.keys()) if compatible(f, t) + ] + [ { 'name': '%s_%s_nosec_test' % (f, t), 'build': 'test', @@ -204,16 +254,20 @@ def main(): 'src': [], 'flaky': END2END_TESTS[t].flaky, 'platforms': END2END_FIXTURES[f].platforms, - 'ci_platforms': (END2END_FIXTURES[f].platforms - if END2END_FIXTURES[f].ci_mac - else without(END2END_FIXTURES[f].platforms, 'mac')), + 'ci_platforms': (END2END_FIXTURES[f].platforms + if END2END_FIXTURES[f].ci_mac else without( + END2END_FIXTURES[f].platforms, 'mac')), 'deps': [ - 'end2end_fixture_%s' % f, - 'end2end_test_%s' % t] + unsec_deps, + 'end2end_nosec_fixture_%s' % f, 'end2end_nosec_test_%s' % t + ] + unsec_deps, 'vs_proj_dir': 'test', } - for f in sorted(END2END_FIXTURES.keys()) if not END2END_FIXTURES[f].secure - for t in sorted(END2END_TESTS.keys()) if compatible(f, t) and not END2END_TESTS[t].secure]} + for f in sorted(END2END_FIXTURES.keys()) + if not END2END_FIXTURES[f].secure + for t in sorted(END2END_TESTS.keys()) + if compatible(f, t) and not END2END_TESTS[t].secure + ] + } print yaml.dump(json) diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c new file mode 100644 index 0000000000..1fd4c0145a --- /dev/null +++ b/test/core/end2end/invalid_call_argument_test.c @@ -0,0 +1,557 @@ +/* + * + * 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/host_port.h> +#include <grpc/support/log.h> +#include <limits.h> +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void *tag(gpr_intptr i) { return (void *)i; } + +struct test_state { + int is_client; + grpc_channel *chan; + grpc_call *call; + gpr_timespec deadline; + grpc_completion_queue *cq; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_status_code status; + char *details; + size_t details_capacity; + grpc_call *server_call; + grpc_server *server; + grpc_metadata_array server_initial_metadata_recv; + grpc_call_details call_details; +}; + +static struct test_state g_state; + +static void prepare_test(int is_client) { + int port; + char *server_hostport; + grpc_op *op; + g_state.is_client = is_client; + grpc_metadata_array_init(&g_state.initial_metadata_recv); + grpc_metadata_array_init(&g_state.trailing_metadata_recv); + g_state.deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2); + g_state.cq = grpc_completion_queue_create(NULL); + g_state.cqv = cq_verifier_create(g_state.cq); + g_state.details = NULL; + g_state.details_capacity = 0; + + if (is_client) { + /* create a call, channel to a non existant server */ + g_state.chan = + grpc_insecure_channel_create("nonexistant:54321", NULL, NULL); + g_state.call = grpc_channel_create_call( + g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo", + "nonexistant", g_state.deadline, NULL); + } else { + g_state.server = grpc_server_create(NULL, NULL); + grpc_server_register_completion_queue(g_state.server, g_state.cq, NULL); + port = grpc_pick_unused_port_or_die(); + gpr_join_host_port(&server_hostport, "0.0.0.0", port); + grpc_server_add_insecure_http2_port(g_state.server, server_hostport); + grpc_server_start(g_state.server); + gpr_free(server_hostport); + gpr_join_host_port(&server_hostport, "localhost", port); + g_state.chan = grpc_insecure_channel_create(server_hostport, NULL, NULL); + gpr_free(server_hostport); + g_state.call = grpc_channel_create_call( + g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo", "bar", + g_state.deadline, NULL); + grpc_metadata_array_init(&g_state.server_initial_metadata_recv); + grpc_call_details_init(&g_state.call_details); + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), + tag(1), NULL)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(g_state.server, &g_state.server_call, + &g_state.call_details, + &g_state.server_initial_metadata_recv, + g_state.cq, g_state.cq, tag(101))); + cq_expect_completion(g_state.cqv, tag(101), 1); + cq_expect_completion(g_state.cqv, tag(1), 1); + cq_verify(g_state.cqv); + } +} + +static void cleanup_test() { + grpc_call_destroy(g_state.call); + cq_verifier_destroy(g_state.cqv); + grpc_channel_destroy(g_state.chan); + gpr_free(g_state.details); + grpc_metadata_array_destroy(&g_state.initial_metadata_recv); + grpc_metadata_array_destroy(&g_state.trailing_metadata_recv); + + if (!g_state.is_client) { + grpc_call_destroy(g_state.server_call); + 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); + 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) + ; + grpc_completion_queue_destroy(g_state.cq); +} + +static void test_non_null_reserved_on_start_batch() { + prepare_test(1); + GPR_ASSERT(GRPC_CALL_ERROR == + grpc_call_start_batch(g_state.call, NULL, 0, NULL, tag(1))); + cleanup_test(); +} + +static void test_non_null_reserved_on_op() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = tag(2); + op++; + GPR_ASSERT(GRPC_CALL_ERROR == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); + cleanup_test(); +} + +static void test_send_initial_metadata_more_than_once() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), + tag(1), NULL)); + cq_expect_completion(g_state.cqv, tag(1), 0); + cq_verify(g_state.cqv); + + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + 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)); + cleanup_test(); +} + +static void test_too_many_metadata() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = (size_t)INT_MAX + 1; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_METADATA == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); + cleanup_test(); +} + +static void test_send_null_message() { + grpc_op *op; + prepare_test(1); + + op = g_state.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_MESSAGE; + op->data.send_message = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_MESSAGE == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); + cleanup_test(); +} + +static void test_send_messages_at_the_same_time() { + grpc_op *op; + gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + prepare_test(1); + op = g_state.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_MESSAGE; + op->data.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = tag(2); + 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)); + grpc_byte_buffer_destroy(request_payload); + cleanup_test(); +} + +static void test_send_server_status_from_client() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + 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++; + GPR_ASSERT(GRPC_CALL_ERROR_NOT_ON_CLIENT == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); + cleanup_test(); +} + +static void test_receive_initial_metadata_twice_at_client() { + grpc_op *op; + prepare_test(1); + op = g_state.ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &g_state.initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), + tag(1), NULL)); + cq_expect_completion(g_state.cqv, tag(1), 0); + cq_verify(g_state.cqv); + op = g_state.ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &g_state.initial_metadata_recv; + 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)); + cleanup_test(); +} + +static void test_receive_message_with_invalid_flags() { + grpc_op *op; + grpc_byte_buffer *payload = NULL; + prepare_test(1); + op = g_state.ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &payload; + 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)); + cleanup_test(); +} + +static void test_receive_two_messages_at_the_same_time() { + grpc_op *op; + grpc_byte_buffer *payload = NULL; + prepare_test(1); + op = g_state.ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &payload; + 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)); + cleanup_test(); +} + +static void test_recv_close_on_server_from_client() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_NOT_ON_CLIENT == + grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), tag(1), NULL)); + cleanup_test(); +} + +static void test_recv_status_on_client_twice() { + grpc_op *op; + prepare_test(1); + + op = g_state.ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &g_state.trailing_metadata_recv; + op->data.recv_status_on_client.status = &g_state.status; + op->data.recv_status_on_client.status_details = &g_state.details; + op->data.recv_status_on_client.status_details_capacity = + &g_state.details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(g_state.call, g_state.ops, + (size_t)(op - g_state.ops), + tag(1), NULL)); + cq_expect_completion(g_state.cqv, tag(1), 1); + cq_verify(g_state.cqv); + + op = g_state.ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = NULL; + op->data.recv_status_on_client.status = NULL; + op->data.recv_status_on_client.status_details = NULL; + op->data.recv_status_on_client.status_details_capacity = NULL; + 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)); + cleanup_test(); +} + +static void test_send_close_from_client_on_server() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_NOT_ON_SERVER == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_recv_status_on_client_from_server() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &g_state.trailing_metadata_recv; + op->data.recv_status_on_client.status = &g_state.status; + op->data.recv_status_on_client.status_details = &g_state.details; + op->data.recv_status_on_client.status_details_capacity = + &g_state.details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_NOT_ON_SERVER == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_send_status_from_server_with_invalid_flags() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + 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 = 1; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_FLAGS == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_too_many_trailing_metadata() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = + (size_t)INT_MAX + 1; + 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++; + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_METADATA == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_send_server_status_twice() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + 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_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++; + GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_recv_close_on_server_with_invalid_flags() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = NULL; + op->flags = 1; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_INVALID_FLAGS == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +static void test_recv_close_on_server_twice() { + grpc_op *op; + prepare_test(0); + + op = g_state.ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == + grpc_call_start_batch(g_state.server_call, g_state.ops, + (size_t)(op - g_state.ops), tag(2), NULL)); + cleanup_test(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_non_null_reserved_on_start_batch(); + test_non_null_reserved_on_op(); + test_send_initial_metadata_more_than_once(); + test_too_many_metadata(); + test_send_null_message(); + test_send_messages_at_the_same_time(); + test_send_server_status_from_client(); + test_receive_initial_metadata_twice_at_client(); + test_receive_message_with_invalid_flags(); + test_receive_two_messages_at_the_same_time(); + test_recv_close_on_server_from_client(); + test_recv_status_on_client_twice(); + test_send_close_from_client_on_server(); + test_recv_status_on_client_from_server(); + test_send_status_from_server_with_invalid_flags(); + test_too_many_trailing_metadata(); + test_send_server_status_twice(); + test_recv_close_on_server_with_invalid_flags(); + test_recv_close_on_server_twice(); + grpc_shutdown(); + + return 0; +} 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/census_simple_request.c b/test/core/end2end/tests/cancel_with_status.c index 29f52ed35a..2e36902a51 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/cancel_with_status.c @@ -38,16 +38,16 @@ #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 "test/core/end2end/cq_verifier.h" -static gpr_timespec n_seconds_time(int n) { - return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); -} +enum { TIMEOUT = 200000 }; + +static void *tag(gpr_intptr t) { return (void *)t; } static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, const char *test_name, @@ -56,12 +56,23 @@ 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; } -static void *tag(gpr_intptr t) { return (void *)t; } +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} static void shutdown_server(grpc_end2end_test_fixture *f) { if (!f->server) return; @@ -79,13 +90,6 @@ static void shutdown_client(grpc_end2end_test_fixture *f) { 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); @@ -95,22 +99,20 @@ static void end_test(grpc_end2end_test_fixture *f) { grpc_completion_queue_destroy(f->cq); } -static void test_body(grpc_end2end_test_fixture f) { +static void simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) { grpc_call *c; - grpc_call *s; - gpr_timespec deadline = n_seconds_time(5); + gpr_timespec deadline = five_seconds_time(); 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; + + gpr_log(GPR_DEBUG, "test with %d ops", num_ops); c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr:1234", deadline, @@ -119,24 +121,8 @@ static void test_body(grpc_end2end_test_fixture f) { 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; @@ -145,88 +131,54 @@ static void test_body(grpc_end2end_test_fixture f) { 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->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_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->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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(num_ops <= (size_t)(op - ops)); + error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); - cq_expect_completion(cqv, tag(102), 1); + grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); + 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; +static void test_invoke_simple_request(grpc_end2end_test_config config, + size_t num_ops) { 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); + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(f, num_ops); 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); + size_t i; + for (i = 1; i <= 4; i++) { + test_invoke_simple_request(config, i); + } } 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 new file mode 100644 index 0000000000..f16883ecfd --- /dev/null +++ b/test/core/end2end/tests/hpack_size.c @@ -0,0 +1,446 @@ +/* + * + * 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 <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" + +static void *tag(gpr_intptr t) { return (void *)t; } + +const char *hobbits[][2] = {{"Adaldrida", "Brandybuck"}, + {"Adamanta", "Took"}, + {"Adalgrim", "Took"}, + {"Adelard", "Took"}, + {"Amaranth", "Brandybuck"}, + {"Andwise", "Roper"}, + {"Angelica", "Baggins"}, + {"Asphodel", "Burrows"}, + {"Balbo", "Baggins"}, + {"Bandobras", "Took"}, + {"Belba", "Bolger"}, + {"Bell", "Gamgee"}, + {"Belladonna", "Baggins"}, + {"Berylla", "Baggins"}, + {"Bilbo", "Baggins"}, + {"Bilbo", "Gardner"}, + {"Bill", "Butcher"}, + {"Bingo", "Baggins"}, + {"Bodo", "Proudfoot"}, + {"Bowman", "Cotton"}, + {"Bungo", "Baggins"}, + {"Camellia", "Sackville"}, + {"Carl", "Cotton"}, + {"Celandine", "Brandybuck"}, + {"Chica", "Baggins"}, + {"Daddy", "Twofoot"}, + {"Daisy", "Boffin"}, + {"Diamond", "Took"}, + {"Dinodas", "Brandybuck"}, + {"Doderic", "Brandybuck"}, + {"Dodinas", "Brandybuck"}, + {"Donnamira", "Boffin"}, + {"Dora", "Baggins"}, + {"Drogo", "Baggins"}, + {"Dudo", "Baggins"}, + {"Eglantine", "Took"}, + {"Elanor", "Fairbairn"}, + {"Elfstan", "Fairbairn"}, + {"Esmeralda", "Brandybuck"}, + {"Estella", "Brandybuck"}, + {"Everard", "Took"}, + {"Falco", "Chubb-Baggins"}, + {"Faramir", "Took"}, + {"Farmer", "Maggot"}, + {"Fastolph", "Bolger"}, + {"Ferdibrand", "Took"}, + {"Ferdinand", "Took"}, + {"Ferumbras", "Took"}, + {"Ferumbras", "Took"}, + {"Filibert", "Bolger"}, + {"Firiel", "Fairbairn"}, + {"Flambard", "Took"}, + {"Folco", "Boffin"}, + {"Fortinbras", "Took"}, + {"Fortinbras", "Took"}, + {"Fosco", "Baggins"}, + {"Fredegar", "Bolger"}, + {"Frodo", "Baggins"}, + {"Frodo", "Gardner"}, + {"Gerontius", "Took"}, + {"Gilly", "Baggins"}, + {"Goldilocks", "Took"}, + {"Gorbadoc", "Brandybuck"}, + {"Gorbulas", "Brandybuck"}, + {"Gorhendad", "Brandybuck"}, + {"Gormadoc", "Brandybuck"}, + {"Griffo", "Boffin"}, + {"Halfast", "Gamgee"}, + {"Halfred", "Gamgee"}, + {"Halfred", "Greenhand"}, + {"Hanna", "Brandybuck"}, + {"Hamfast", "Gamgee"}, + {"Hamfast", "Gardner"}, + {"Hamson", "Gamgee"}, + {"Harding", "Gardner"}, + {"Hilda", "Brandybuck"}, + {"Hildibrand", "Took"}, + {"Hildifons", "Took"}, + {"Hildigard", "Took"}, + {"Hildigrim", "Took"}, + {"Hob", "Gammidge"}, + {"Hob", "Hayward"}, + {"Hobson", "Gamgee"}, + {"Holfast", "Gardner"}, + {"Holman", "Cotton"}, + {"Holman", "Greenhand"}, + {"Hugo", "Boffin"}, + {"Hugo", "Bracegirdle"}, + {"Ilberic", "Brandybuck"}, + {"Isembard", "Took"}, + {"Isembold", "Took"}, + {"Isengar", "Took"}, + {"Isengrim", "Took"}, + {"Isengrim", "Took"}, + {"Isumbras", "Took"}, + {"Isumbras", "Took"}, + {"Jolly", "Cotton"}, + {"Lalia", "Took"}, + {"Largo", "Baggins"}, + {"Laura", "Baggins"}, + {"Lily", "Goodbody"}, + {"Lily", "Cotton"}, + {"Linda", "Proudfoot"}, + {"Lobelia", "Sackville-Baggins"}, + {"Longo", "Baggins"}, + {"Lotho", "Sackville-Baggins"}, + {"Madoc", "Brandybuck"}, + {"Malva", "Brandybuck"}, + {"Marigold", "Cotton"}, + {"Marmadas", "Brandybuck"}, + {"Marmadoc", "Brandybuck"}, + {"Marroc", "Brandybuck"}, + {"May", "Gamgee"}, + {"Melilot", "Brandybuck"}, + {"Menegilda", "Brandybuck"}, + {"Mentha", "Brandybuck"}, + {"Meriadoc", "Brandybuck"}, + {"Merimac", "Brandybuck"}, + {"Merimas", "Brandybuck"}, + {"Merry", "Gardner"}, + {"Milo", "Burrows"}, + {"Mimosa", "Baggins"}, + {"Minto", "Burrows"}, + {"Mirabella", "Brandybuck"}, + {"Moro", "Burrows"}, + {"Mosco", "Burrows"}, + {"Mungo", "Baggins"}, + {"Myrtle", "Burrows"}, + {"Odo", "Proudfoot"}, + {"Odovacar", "Bolger"}, + {"Olo", "Proudfoot"}, + {"Orgulas", "Brandybuck"}, + {"Otho", "Sackville-Baggins"}, + {"Paladin", "Took"}, + {"Pansy", "Bolger"}, + {"Pearl", "Took"}, + {"Peony", "Burrows"}, + {"Peregrin", "Took"}, + {"Pervinca", "Took"}, + {"Pimpernel", "Took"}, + {"Pippin", "Gardner"}, + {"Polo", "Baggins"}, + {"Ponto", "Baggins"}, + {"Porto", "Baggins"}, + {"Posco", "Baggins"}, + {"Poppy", "Bolger"}, + {"Primrose", "Gardner"}, + {"Primula", "Baggins"}, + {"Prisca", "Bolger"}, + {"Reginard", "Took"}, + {"Robin", "Smallburrow"}, + {"Robin", "Gardner"}, + {"Rorimac", "Brandybuck"}, + {"Rosa", "Took"}, + {"Rosamunda", "Bolger"}, + {"Rose", "Gardner"}, + {"Ruby", "Baggins"}, + {"Ruby", "Gardner"}, + {"Rudigar", "Bolger"}, + {"Rufus", "Burrows"}, + {"Sadoc", "Brandybuck"}, + {"Salvia", "Bolger"}, + {"Samwise", "Gamgee"}, + {"Sancho", "Proudfoot"}, + {"Saradas", "Brandybuck"}, + {"Saradoc", "Brandybuck"}, + {"Seredic", "Brandybuck"}, + {"Sigismond", "Took"}, + {"Smeagol", "Gollum"}, + {"Tanta", "Baggins"}, + {"Ted", "Sandyman"}, + {"Tobold", "Hornblower"}, + {"Togo", "Goodbody"}, + {"Tolman", "Cotton"}, + {"Tolman", "Gardner"}, + {"Widow", "Rumble"}, + {"Wilcome", "Cotton"}, + {"Wilcome", "Cotton"}, + {"Wilibald", "Bolger"}, + {"Will", "Whitfoot"}, + {"Wiseman", "Gamwich"}}; + +const char *dragons[] = {"Ancalagon", "Glaurung", "Scatha", + "Smaug the Magnificent"}; + +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_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +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 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 simple_request_body(grpc_end2end_test_fixture f, size_t index) { + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = five_seconds_time(); + 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; + grpc_metadata extra_metadata[3]; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + memset(extra_metadata, 0, sizeof(extra_metadata)); + extra_metadata[0].key = "hobbit-first-name"; + extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]; + extra_metadata[0].value_length = strlen(extra_metadata[0].value); + extra_metadata[1].key = "hobbit-second-name"; + extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]; + extra_metadata[1].value_length = strlen(extra_metadata[1].value); + extra_metadata[2].key = "dragon"; + extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)]; + extra_metadata[2].value_length = strlen(extra_metadata[2].value); + + 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 = GPR_ARRAY_SIZE(extra_metadata); + op->data.send_initial_metadata.metadata = extra_metadata; + 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_size(grpc_end2end_test_config config, int encode_size, + int decode_size) { + size_t i; + grpc_end2end_test_fixture f; + grpc_arg server_arg; + grpc_channel_args server_args; + grpc_arg client_arg; + grpc_channel_args client_args; + char *name; + + server_arg.type = GRPC_ARG_INTEGER; + server_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER; + server_arg.value.integer = decode_size; + server_args.num_args = 1; + server_args.args = &server_arg; + + client_arg.type = GRPC_ARG_INTEGER; + client_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER; + client_arg.value.integer = encode_size; + client_args.num_args = 1; + client_args.args = &client_arg; + + gpr_asprintf(&name, "test_size:e=%d:d=%d", encode_size, decode_size); + f = begin_test(config, name, encode_size != 4096 ? &client_args : NULL, + decode_size != 4096 ? &server_args : NULL); + for (i = 0; i < 4 * GPR_ARRAY_SIZE(hobbits); i++) { + simple_request_body(f, i); + } + end_test(&f); + config.tear_down_data(&f); + gpr_free(name); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + static const int interesting_sizes[] = {4096, 0, 100, + 1000, 32768, 4 * 1024 * 1024}; + size_t i, j; + + for (i = 0; i < GPR_ARRAY_SIZE(interesting_sizes); i++) { + for (j = 0; j < GPR_ARRAY_SIZE(interesting_sizes); j++) { + test_size(config, interesting_sizes[i], interesting_sizes[j]); + } + } +} 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 3dad47f37b..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; } @@ -109,6 +109,7 @@ static void test_max_message_length(grpc_end2end_test_config config) { gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *recv_payload; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; @@ -183,6 +184,11 @@ static void test_max_message_length(grpc_end2end_test_config config) { op->flags = 0; op->reserved = NULL; op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &recv_payload; + 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); @@ -194,6 +200,7 @@ static void test_max_message_length(grpc_end2end_test_config config) { 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_ASSERT(recv_payload == NULL); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); 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 new file mode 100644 index 0000000000..23b8591e25 --- /dev/null +++ b/test/core/end2end/tests/negative_deadline.c @@ -0,0 +1,181 @@ +/* + * + * 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/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(gpr_intptr t) { return (void *)t; } + +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_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +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 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 simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) { + grpc_call *c; + gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME); + 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_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + + gpr_log(GPR_DEBUG, "test with %d ops", num_ops); + + 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); + + 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; + 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_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++; + GPR_ASSERT(num_ops <= (size_t)(op - ops)); + error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + cq_expect_completion(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_call_destroy(c); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config, + size_t num_ops) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(f, num_ops); + end_test(&f); + config.tear_down_data(&f); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + size_t i; + for (i = 1; i <= 4; i++) { + test_invoke_simple_request(config, i); + } +} 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 d7c4cff608..0ad5a4612e 100644 --- a/test/core/end2end/tests/request_with_flags.c +++ b/test/core/end2end/tests/request_with_flags.c @@ -41,7 +41,7 @@ #include <grpc/support/log.h> #include <grpc/support/time.h> #include <grpc/support/useful.h> -#include "src/core/transport/stream_op.h" +#include "src/core/transport/byte_stream.h" #include "test/core/end2end/cq_verifier.h" enum { TIMEOUT = 200000 }; @@ -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/fling/client.c b/test/core/fling/client.c index a53411c2f5..99b30d6c4a 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -41,6 +41,7 @@ #include <grpc/support/log.h> #include <grpc/support/time.h> #include <grpc/support/useful.h> +#include "src/core/profiling/timers.h" #include "test/core/util/grpc_profiler.h" #include "test/core/util/test_config.h" @@ -89,6 +90,7 @@ static void init_ping_pong_request(void) { } static void step_ping_pong_request(void) { + GPR_TIMER_BEGIN("ping_pong", 1); call = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Reflector/reflectUnary", "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL); @@ -99,6 +101,7 @@ static void step_ping_pong_request(void) { grpc_call_destroy(call); grpc_byte_buffer_destroy(response_payload_recv); call = NULL; + GPR_TIMER_END("ping_pong", 1); } static void init_ping_pong_stream(void) { @@ -122,10 +125,12 @@ static void init_ping_pong_stream(void) { static void step_ping_pong_stream(void) { grpc_call_error error; + GPR_TIMER_BEGIN("ping_pong", 1); error = grpc_call_start_batch(call, stream_step_ops, 2, (void *)1, NULL); GPR_ASSERT(GRPC_CALL_OK == error); grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); grpc_byte_buffer_destroy(response_payload_recv); + GPR_TIMER_END("ping_pong", 1); } static double now(void) { @@ -159,12 +164,14 @@ int main(int argc, char **argv) { char *scenario_name = "ping-pong-request"; scenario sc = {NULL, NULL, NULL}; + gpr_timers_set_log_filename("latency_trace.fling_client.txt"); + + grpc_init(); + GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; grpc_test_init(1, fake_argv); - grpc_init(); - cl = gpr_cmdline_create("fling client"); gpr_cmdline_add_int(cl, "payload_size", "Size of the payload to send", &payload_size); diff --git a/test/core/fling/server.c b/test/core/fling/server.c index 67631e5a07..ae218b4cc1 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -44,15 +44,16 @@ #include <unistd.h> #endif -#include "test/core/util/grpc_profiler.h" -#include "test/core/util/test_config.h" #include <grpc/support/alloc.h> #include <grpc/support/cmdline.h> #include <grpc/support/host_port.h> #include <grpc/support/log.h> #include <grpc/support/time.h> -#include "test/core/util/port.h" +#include "src/core/profiling/timers.h" #include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/grpc_profiler.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" static grpc_completion_queue *cq; static grpc_server *server; @@ -192,6 +193,8 @@ int main(int argc, char **argv) { char *fake_argv[1]; + gpr_timers_set_log_filename("latency_trace.fling_server.txt"); + GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; grpc_test_init(1, fake_argv); 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/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index f592f63ba9..4be6957a83 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -121,7 +121,7 @@ static void session_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */ int success) { session *se = arg; server *sv = se->sv; - grpc_fd_orphan(exec_ctx, se->em_fd, NULL, "a"); + grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, "a"); gpr_free(se); /* Start to shutdown listen fd. */ grpc_fd_shutdown(exec_ctx, sv->em_fd); @@ -177,7 +177,7 @@ static void listen_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg /*server */, int success) { server *sv = arg; - grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, "b"); + grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, "b"); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); sv->done = 1; @@ -294,7 +294,7 @@ static void client_init(client *cl) { static void client_session_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg /*client */, int success) { client *cl = arg; - grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, "c"); + grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, "c"); cl->done = 1; grpc_pollset_kick(&g_pollset, NULL); } @@ -503,7 +503,7 @@ static void test_grpc_fd_change(void) { GPR_ASSERT(b.cb_that_ran == second_read_callback); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - grpc_fd_orphan(&exec_ctx, em_fd, NULL, "d"); + grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, "d"); grpc_exec_ctx_finish(&exec_ctx); destroy_change_data(&a); destroy_change_data(&b); 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/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index f676454b7f..9feac931a3 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -383,6 +383,76 @@ static void write_test(size_t num_bytes, size_t slice_size) { grpc_exec_ctx_finish(&exec_ctx); } +void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, int success) { + int *done = arg; + *done = 1; + grpc_pollset_kick(&g_pollset, NULL); +} + +/* Do a read_test, then release fd and try to read/write again. */ +static void release_fd_test(size_t num_bytes, size_t slice_size) { + int sv[2]; + grpc_endpoint *ep; + struct read_socket_state state; + size_t written_bytes; + int fd; + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_closure fd_released_cb; + int fd_released_done = 0; + grpc_closure_init(&fd_released_cb, &on_fd_released, &fd_released_done); + + gpr_log(GPR_INFO, "Release fd read_test of size %d, slice size %d", num_bytes, + slice_size); + + create_sockets(sv); + + ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size, "test"); + grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset); + + written_bytes = fill_socket_partial(sv[0], num_bytes); + gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes); + + state.ep = ep; + state.read_bytes = 0; + state.target_read_bytes = written_bytes; + gpr_slice_buffer_init(&state.incoming); + grpc_closure_init(&state.read_cb, read_cb, &state); + + grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); + + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (state.read_bytes < state.target_read_bytes) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), deadline); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + } + GPR_ASSERT(state.read_bytes == state.target_read_bytes); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + + gpr_slice_buffer_destroy(&state.incoming); + grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (!fd_released_done) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), deadline); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + GPR_ASSERT(fd_released_done == 1); + GPR_ASSERT(fd == sv[1]); + grpc_exec_ctx_finish(&exec_ctx); + + written_bytes = fill_socket_partial(sv[0], num_bytes); + drain_socket_blocking(fd, written_bytes, written_bytes); + written_bytes = fill_socket_partial(fd, num_bytes); + drain_socket_blocking(sv[0], written_bytes, written_bytes); + close(fd); +} + void run_tests(void) { size_t i = 0; @@ -402,6 +472,8 @@ void run_tests(void) { for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { write_test(40320, i); } + + release_fd_test(100, 8192); } static void clean_up(void) {} 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 b2b7cfdb6e..a32ddd2ec7 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -31,8 +31,10 @@ * */ +#include <grpc/support/port_platform.h> #include "src/core/security/credentials.h" +#include <stdlib.h> #include <string.h> #include "src/core/httpcli/httpcli.h" @@ -876,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(); @@ -892,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, @@ -1013,8 +1111,34 @@ static void test_metadata_plugin_failure(void) { grpc_exec_ctx_finish(&exec_ctx); } +static void test_get_well_known_google_credentials_file_path(void) { +#ifdef GPR_POSIX_FILE + char *path; + char *old_home = gpr_getenv("HOME"); + gpr_setenv("HOME", "/tmp"); + path = grpc_get_well_known_google_credentials_file_path(); + GPR_ASSERT(path != NULL); + GPR_ASSERT(0 == strcmp("/tmp/.config/" GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY + "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE, + path)); + gpr_free(path); +#if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV) + unsetenv("HOME"); + path = grpc_get_well_known_google_credentials_file_path(); + GPR_ASSERT(path == NULL); +#endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */ + gpr_setenv("HOME", old_home); + gpr_free(old_home); +#else /* GPR_POSIX_FILE */ + char *path = grpc_get_well_known_google_credentials_file_path(); + GPR_ASSERT(path != NULL); + gpr_free(path); +#endif +} + 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(); @@ -1040,8 +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 new file mode 100644 index 0000000000..b950f0ab49 --- /dev/null +++ b/test/core/support/alloc_test.c @@ -0,0 +1,68 @@ +/* + * + * 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/log.h> +#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_realloc(void *addr, size_t size) { return (void *)size; } + +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(); + gpr_intptr addr_to_free = 0; + int *i; + 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_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_free(i); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_custom_allocs(); + return 0; +} diff --git a/test/core/support/avl_test.c b/test/core/support/avl_test.c new file mode 100644 index 0000000000..6530fe4269 --- /dev/null +++ b/test/core/support/avl_test.c @@ -0,0 +1,3671 @@ +/* + * + * 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/avl.h> + +#include <stdio.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/useful.h> + +#include "test/core/util/test_config.h" + +static int *box(int x) { + int *b = gpr_malloc(sizeof(*b)); + *b = x; + return b; +} + +static long int_compare(void *int1, void *int2) { + return (*(int *)int1) - (*(int *)int2); +} +static void *int_copy(void *p) { return box(*(int *)p); } + +static const gpr_avl_vtable int_int_vtable = {gpr_free, int_copy, int_compare, + gpr_free, int_copy}; + +static void check_get(gpr_avl avl, int key, int value) { + int *k = box(key); + GPR_ASSERT(*(int *)gpr_avl_get(avl, k) == value); + gpr_free(k); +} + +static void check_negget(gpr_avl avl, int key) { + int *k = box(key); + GPR_ASSERT(gpr_avl_get(avl, k) == NULL); + gpr_free(k); +} + +static gpr_avl remove_int(gpr_avl avl, int key) { + int *k = box(key); + avl = gpr_avl_remove(avl, k); + gpr_free(k); + return avl; +} + +static void test_get(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_get"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(1), box(11)); + avl = gpr_avl_add(avl, box(2), box(22)); + avl = gpr_avl_add(avl, box(3), box(33)); + check_get(avl, 1, 11); + check_get(avl, 2, 22); + check_get(avl, 3, 33); + check_negget(avl, 4); + gpr_avl_unref(avl); +} + +static void test_ll(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_ll"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(5), box(1)); + avl = gpr_avl_add(avl, box(4), box(2)); + avl = gpr_avl_add(avl, box(3), box(3)); + GPR_ASSERT(*(int *)avl.root->key == 4); + GPR_ASSERT(*(int *)avl.root->left->key == 3); + GPR_ASSERT(*(int *)avl.root->right->key == 5); + gpr_avl_unref(avl); +} + +static void test_lr(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_lr"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(5), box(1)); + avl = gpr_avl_add(avl, box(3), box(2)); + avl = gpr_avl_add(avl, box(4), box(3)); + GPR_ASSERT(*(int *)avl.root->key == 4); + GPR_ASSERT(*(int *)avl.root->left->key == 3); + GPR_ASSERT(*(int *)avl.root->right->key == 5); + gpr_avl_unref(avl); +} + +static void test_rr(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_rr"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(3), box(1)); + avl = gpr_avl_add(avl, box(4), box(2)); + avl = gpr_avl_add(avl, box(5), box(3)); + GPR_ASSERT(*(int *)avl.root->key == 4); + GPR_ASSERT(*(int *)avl.root->left->key == 3); + GPR_ASSERT(*(int *)avl.root->right->key == 5); + gpr_avl_unref(avl); +} + +static void test_rl(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_rl"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(3), box(1)); + avl = gpr_avl_add(avl, box(5), box(2)); + avl = gpr_avl_add(avl, box(4), box(3)); + GPR_ASSERT(*(int *)avl.root->key == 4); + GPR_ASSERT(*(int *)avl.root->left->key == 3); + GPR_ASSERT(*(int *)avl.root->right->key == 5); + gpr_avl_unref(avl); +} + +static void test_unbalanced(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_unbalanced"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(5), box(1)); + avl = gpr_avl_add(avl, box(4), box(2)); + avl = gpr_avl_add(avl, box(3), box(3)); + avl = gpr_avl_add(avl, box(2), box(4)); + avl = gpr_avl_add(avl, box(1), box(5)); + GPR_ASSERT(*(int *)avl.root->key == 4); + GPR_ASSERT(*(int *)avl.root->left->key == 2); + GPR_ASSERT(*(int *)avl.root->left->left->key == 1); + GPR_ASSERT(*(int *)avl.root->left->right->key == 3); + GPR_ASSERT(*(int *)avl.root->right->key == 5); + gpr_avl_unref(avl); +} + +static void test_replace(void) { + gpr_avl avl; + gpr_log(GPR_DEBUG, "test_replace"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(1), box(1)); + avl = gpr_avl_add(avl, box(1), box(2)); + check_get(avl, 1, 2); + check_negget(avl, 2); + gpr_avl_unref(avl); +} + +static void test_remove(void) { + gpr_avl avl; + gpr_avl avl3, avl4, avl5, avln; + gpr_log(GPR_DEBUG, "test_remove"); + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(3), box(1)); + avl = gpr_avl_add(avl, box(4), box(2)); + avl = gpr_avl_add(avl, box(5), box(3)); + + avl3 = remove_int(gpr_avl_ref(avl), 3); + avl4 = remove_int(gpr_avl_ref(avl), 4); + avl5 = remove_int(gpr_avl_ref(avl), 5); + avln = remove_int(gpr_avl_ref(avl), 1); + + gpr_avl_unref(avl); + + check_negget(avl3, 3); + check_get(avl3, 4, 2); + check_get(avl3, 5, 3); + gpr_avl_unref(avl3); + + check_get(avl4, 3, 1); + check_negget(avl4, 4); + check_get(avl4, 5, 3); + gpr_avl_unref(avl4); + + check_get(avl5, 3, 1); + check_get(avl5, 4, 2); + check_negget(avl5, 5); + gpr_avl_unref(avl5); + + check_get(avln, 3, 1); + check_get(avln, 4, 2); + check_get(avln, 5, 3); + gpr_avl_unref(avln); +} + +static void test_badcase1(void) { + gpr_avl avl; + + gpr_log(GPR_DEBUG, "test_badcase1"); + + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(88), box(1)); + avl = remove_int(avl, 643); + avl = remove_int(avl, 983); + avl = gpr_avl_add(avl, box(985), box(4)); + avl = gpr_avl_add(avl, box(640), box(5)); + avl = gpr_avl_add(avl, box(41), box(6)); + avl = gpr_avl_add(avl, box(112), box(7)); + avl = gpr_avl_add(avl, box(342), box(8)); + avl = remove_int(avl, 1013); + avl = gpr_avl_add(avl, box(434), box(10)); + avl = gpr_avl_add(avl, box(520), box(11)); + avl = gpr_avl_add(avl, box(231), box(12)); + avl = gpr_avl_add(avl, box(852), box(13)); + avl = remove_int(avl, 461); + avl = gpr_avl_add(avl, box(108), box(15)); + avl = gpr_avl_add(avl, box(806), box(16)); + avl = gpr_avl_add(avl, box(827), box(17)); + avl = remove_int(avl, 796); + avl = gpr_avl_add(avl, box(340), box(19)); + avl = gpr_avl_add(avl, box(498), box(20)); + avl = gpr_avl_add(avl, box(203), box(21)); + avl = gpr_avl_add(avl, box(751), box(22)); + avl = gpr_avl_add(avl, box(150), box(23)); + avl = remove_int(avl, 237); + avl = gpr_avl_add(avl, box(830), box(25)); + avl = remove_int(avl, 1007); + avl = remove_int(avl, 394); + avl = gpr_avl_add(avl, box(65), box(28)); + avl = remove_int(avl, 904); + avl = remove_int(avl, 123); + avl = gpr_avl_add(avl, box(238), box(31)); + avl = gpr_avl_add(avl, box(184), box(32)); + avl = remove_int(avl, 331); + avl = gpr_avl_add(avl, box(827), box(34)); + + check_get(avl, 830, 25); + + gpr_avl_unref(avl); +} + +static void test_badcase2(void) { + gpr_avl avl; + + gpr_log(GPR_DEBUG, "test_badcase2"); + + avl = gpr_avl_create(&int_int_vtable); + avl = gpr_avl_add(avl, box(288), box(1)); + avl = remove_int(avl, 415); + avl = gpr_avl_add(avl, box(953), box(3)); + avl = gpr_avl_add(avl, box(101), box(4)); + avl = gpr_avl_add(avl, box(516), box(5)); + avl = gpr_avl_add(avl, box(547), box(6)); + avl = gpr_avl_add(avl, box(467), box(7)); + avl = gpr_avl_add(avl, box(793), box(8)); + avl = remove_int(avl, 190); + avl = gpr_avl_add(avl, box(687), box(10)); + avl = gpr_avl_add(avl, box(242), box(11)); + avl = gpr_avl_add(avl, box(142), box(12)); + avl = remove_int(avl, 705); + avl = remove_int(avl, 578); + avl = remove_int(avl, 767); + avl = remove_int(avl, 183); + avl = gpr_avl_add(avl, box(950), box(17)); + avl = gpr_avl_add(avl, box(622), box(18)); + avl = remove_int(avl, 513); + avl = remove_int(avl, 429); + avl = gpr_avl_add(avl, box(205), box(21)); + avl = remove_int(avl, 663); + avl = remove_int(avl, 953); + avl = remove_int(avl, 892); + avl = gpr_avl_add(avl, box(236), box(25)); + avl = remove_int(avl, 982); + avl = remove_int(avl, 201); + avl = remove_int(avl, 684); + avl = gpr_avl_add(avl, box(572), box(29)); + avl = remove_int(avl, 817); + avl = gpr_avl_add(avl, box(970), box(31)); + avl = remove_int(avl, 347); + avl = remove_int(avl, 574); + avl = gpr_avl_add(avl, box(752), box(34)); + avl = gpr_avl_add(avl, box(670), box(35)); + avl = gpr_avl_add(avl, box(69), box(36)); + avl = remove_int(avl, 111); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(141), box(39)); + avl = remove_int(avl, 159); + avl = gpr_avl_add(avl, box(947), box(41)); + avl = gpr_avl_add(avl, box(855), box(42)); + avl = remove_int(avl, 218); + avl = remove_int(avl, 6); + avl = gpr_avl_add(avl, box(753), box(45)); + avl = remove_int(avl, 82); + avl = remove_int(avl, 799); + avl = gpr_avl_add(avl, box(572), box(48)); + avl = remove_int(avl, 376); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(458), box(51)); + avl = remove_int(avl, 897); + avl = gpr_avl_add(avl, box(191), box(53)); + avl = gpr_avl_add(avl, box(609), box(54)); + avl = remove_int(avl, 787); + avl = remove_int(avl, 710); + avl = remove_int(avl, 886); + avl = remove_int(avl, 835); + avl = remove_int(avl, 33); + avl = gpr_avl_add(avl, box(871), box(60)); + avl = remove_int(avl, 641); + avl = gpr_avl_add(avl, box(462), box(62)); + avl = remove_int(avl, 359); + avl = remove_int(avl, 767); + avl = gpr_avl_add(avl, box(310), box(65)); + avl = remove_int(avl, 757); + avl = remove_int(avl, 639); + avl = remove_int(avl, 314); + avl = gpr_avl_add(avl, box(2), box(69)); + avl = remove_int(avl, 138); + avl = gpr_avl_add(avl, box(669), box(71)); + avl = remove_int(avl, 477); + avl = gpr_avl_add(avl, box(366), box(73)); + avl = gpr_avl_add(avl, box(612), box(74)); + avl = gpr_avl_add(avl, box(106), box(75)); + avl = remove_int(avl, 161); + avl = gpr_avl_add(avl, box(388), box(77)); + avl = gpr_avl_add(avl, box(141), box(78)); + avl = remove_int(avl, 633); + avl = remove_int(avl, 459); + avl = gpr_avl_add(avl, box(40), box(81)); + avl = remove_int(avl, 689); + avl = gpr_avl_add(avl, box(823), box(83)); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(903), box(85)); + avl = gpr_avl_add(avl, box(592), box(86)); + avl = remove_int(avl, 448); + avl = gpr_avl_add(avl, box(56), box(88)); + avl = remove_int(avl, 333); + avl = gpr_avl_add(avl, box(189), box(90)); + avl = gpr_avl_add(avl, box(103), box(91)); + avl = remove_int(avl, 164); + avl = remove_int(avl, 974); + avl = gpr_avl_add(avl, box(215), box(94)); + avl = remove_int(avl, 189); + avl = remove_int(avl, 504); + avl = gpr_avl_add(avl, box(868), box(97)); + avl = remove_int(avl, 909); + avl = remove_int(avl, 148); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(994), box(101)); + avl = gpr_avl_add(avl, box(576), box(102)); + avl = remove_int(avl, 82); + avl = remove_int(avl, 209); + avl = gpr_avl_add(avl, box(276), box(105)); + avl = remove_int(avl, 856); + avl = gpr_avl_add(avl, box(750), box(107)); + avl = remove_int(avl, 871); + avl = gpr_avl_add(avl, box(301), box(109)); + avl = remove_int(avl, 260); + avl = remove_int(avl, 737); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(933), box(113)); + avl = gpr_avl_add(avl, box(225), box(114)); + avl = gpr_avl_add(avl, box(975), box(115)); + avl = gpr_avl_add(avl, box(86), box(116)); + avl = remove_int(avl, 732); + avl = gpr_avl_add(avl, box(340), box(118)); + avl = gpr_avl_add(avl, box(271), box(119)); + avl = remove_int(avl, 206); + avl = gpr_avl_add(avl, box(949), box(121)); + avl = gpr_avl_add(avl, box(927), box(122)); + avl = gpr_avl_add(avl, box(34), box(123)); + avl = gpr_avl_add(avl, box(351), box(124)); + avl = remove_int(avl, 836); + avl = gpr_avl_add(avl, box(825), box(126)); + avl = gpr_avl_add(avl, box(352), box(127)); + avl = remove_int(avl, 107); + avl = remove_int(avl, 101); + avl = gpr_avl_add(avl, box(320), box(130)); + avl = gpr_avl_add(avl, box(3), box(131)); + avl = remove_int(avl, 998); + avl = remove_int(avl, 44); + avl = gpr_avl_add(avl, box(525), box(134)); + avl = gpr_avl_add(avl, box(864), box(135)); + avl = gpr_avl_add(avl, box(863), box(136)); + avl = remove_int(avl, 770); + avl = gpr_avl_add(avl, box(440), box(138)); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(116), box(140)); + avl = remove_int(avl, 380); + avl = gpr_avl_add(avl, box(878), box(142)); + avl = remove_int(avl, 439); + avl = gpr_avl_add(avl, box(994), box(144)); + avl = remove_int(avl, 294); + avl = remove_int(avl, 593); + avl = gpr_avl_add(avl, box(696), box(147)); + avl = remove_int(avl, 8); + avl = gpr_avl_add(avl, box(881), box(149)); + avl = remove_int(avl, 32); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(487), box(152)); + avl = gpr_avl_add(avl, box(637), box(153)); + avl = gpr_avl_add(avl, box(793), box(154)); + avl = gpr_avl_add(avl, box(696), box(155)); + avl = remove_int(avl, 458); + avl = gpr_avl_add(avl, box(828), box(157)); + avl = remove_int(avl, 784); + avl = remove_int(avl, 274); + avl = gpr_avl_add(avl, box(783), box(160)); + avl = remove_int(avl, 21); + avl = gpr_avl_add(avl, box(866), box(162)); + avl = remove_int(avl, 919); + avl = gpr_avl_add(avl, box(435), box(164)); + avl = remove_int(avl, 385); + avl = gpr_avl_add(avl, box(475), box(166)); + avl = remove_int(avl, 339); + avl = gpr_avl_add(avl, box(615), box(168)); + avl = remove_int(avl, 866); + avl = remove_int(avl, 82); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(590), box(172)); + avl = gpr_avl_add(avl, box(852), box(173)); + avl = remove_int(avl, 318); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(672), box(176)); + avl = remove_int(avl, 430); + avl = gpr_avl_add(avl, box(821), box(178)); + avl = gpr_avl_add(avl, box(365), box(179)); + avl = remove_int(avl, 78); + avl = gpr_avl_add(avl, box(700), box(181)); + avl = gpr_avl_add(avl, box(353), box(182)); + avl = remove_int(avl, 492); + avl = gpr_avl_add(avl, box(991), box(184)); + avl = remove_int(avl, 330); + avl = gpr_avl_add(avl, box(873), box(186)); + avl = remove_int(avl, 589); + avl = gpr_avl_add(avl, box(676), box(188)); + avl = gpr_avl_add(avl, box(790), box(189)); + avl = remove_int(avl, 521); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(976), box(192)); + avl = gpr_avl_add(avl, box(683), box(193)); + avl = remove_int(avl, 803); + avl = remove_int(avl, 1006); + avl = gpr_avl_add(avl, box(775), box(196)); + avl = gpr_avl_add(avl, box(411), box(197)); + avl = gpr_avl_add(avl, box(697), box(198)); + avl = remove_int(avl, 50); + avl = gpr_avl_add(avl, box(213), box(200)); + avl = remove_int(avl, 714); + avl = gpr_avl_add(avl, box(981), box(202)); + avl = gpr_avl_add(avl, box(502), box(203)); + avl = gpr_avl_add(avl, box(697), box(204)); + avl = gpr_avl_add(avl, box(603), box(205)); + avl = gpr_avl_add(avl, box(117), box(206)); + avl = remove_int(avl, 363); + avl = gpr_avl_add(avl, box(104), box(208)); + avl = remove_int(avl, 842); + avl = gpr_avl_add(avl, box(48), box(210)); + avl = remove_int(avl, 764); + avl = gpr_avl_add(avl, box(482), box(212)); + avl = gpr_avl_add(avl, box(928), box(213)); + avl = gpr_avl_add(avl, box(30), box(214)); + avl = gpr_avl_add(avl, box(820), box(215)); + avl = gpr_avl_add(avl, box(334), box(216)); + avl = remove_int(avl, 306); + avl = gpr_avl_add(avl, box(789), box(218)); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(53), box(220)); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(130), box(222)); + avl = gpr_avl_add(avl, box(239), box(223)); + avl = remove_int(avl, 20); + avl = gpr_avl_add(avl, box(117), box(225)); + avl = remove_int(avl, 882); + avl = remove_int(avl, 891); + avl = gpr_avl_add(avl, box(9), box(228)); + avl = gpr_avl_add(avl, box(496), box(229)); + avl = gpr_avl_add(avl, box(750), box(230)); + avl = gpr_avl_add(avl, box(283), box(231)); + avl = gpr_avl_add(avl, box(802), box(232)); + avl = remove_int(avl, 352); + avl = gpr_avl_add(avl, box(374), box(234)); + avl = gpr_avl_add(avl, box(6), box(235)); + avl = gpr_avl_add(avl, box(756), box(236)); + avl = gpr_avl_add(avl, box(597), box(237)); + avl = gpr_avl_add(avl, box(661), box(238)); + avl = remove_int(avl, 96); + avl = gpr_avl_add(avl, box(894), box(240)); + avl = remove_int(avl, 749); + avl = gpr_avl_add(avl, box(71), box(242)); + avl = remove_int(avl, 68); + avl = gpr_avl_add(avl, box(388), box(244)); + avl = remove_int(avl, 119); + avl = remove_int(avl, 856); + avl = gpr_avl_add(avl, box(176), box(247)); + avl = gpr_avl_add(avl, box(993), box(248)); + avl = remove_int(avl, 178); + avl = remove_int(avl, 781); + avl = remove_int(avl, 771); + avl = remove_int(avl, 848); + avl = remove_int(avl, 376); + avl = remove_int(avl, 157); + avl = remove_int(avl, 142); + avl = remove_int(avl, 686); + avl = gpr_avl_add(avl, box(779), box(257)); + avl = gpr_avl_add(avl, box(484), box(258)); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(388), box(260)); + avl = remove_int(avl, 987); + avl = gpr_avl_add(avl, box(336), box(262)); + avl = remove_int(avl, 855); + avl = gpr_avl_add(avl, box(668), box(264)); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(193), box(266)); + avl = remove_int(avl, 939); + avl = gpr_avl_add(avl, box(740), box(268)); + avl = gpr_avl_add(avl, box(503), box(269)); + avl = gpr_avl_add(avl, box(765), box(270)); + avl = remove_int(avl, 924); + avl = remove_int(avl, 513); + avl = gpr_avl_add(avl, box(161), box(273)); + avl = gpr_avl_add(avl, box(502), box(274)); + avl = gpr_avl_add(avl, box(846), box(275)); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(87), box(277)); + avl = gpr_avl_add(avl, box(949), box(278)); + avl = gpr_avl_add(avl, box(548), box(279)); + avl = gpr_avl_add(avl, box(951), box(280)); + avl = remove_int(avl, 1018); + avl = remove_int(avl, 568); + avl = gpr_avl_add(avl, box(138), box(283)); + avl = gpr_avl_add(avl, box(202), box(284)); + avl = gpr_avl_add(avl, box(157), box(285)); + avl = gpr_avl_add(avl, box(264), box(286)); + avl = gpr_avl_add(avl, box(370), box(287)); + avl = remove_int(avl, 736); + avl = remove_int(avl, 751); + avl = remove_int(avl, 506); + avl = remove_int(avl, 81); + avl = remove_int(avl, 358); + avl = remove_int(avl, 657); + avl = remove_int(avl, 86); + avl = gpr_avl_add(avl, box(876), box(295)); + avl = remove_int(avl, 354); + avl = gpr_avl_add(avl, box(134), box(297)); + avl = remove_int(avl, 781); + avl = remove_int(avl, 183); + avl = gpr_avl_add(avl, box(914), box(300)); + avl = remove_int(avl, 926); + avl = remove_int(avl, 398); + avl = remove_int(avl, 932); + avl = remove_int(avl, 804); + avl = remove_int(avl, 326); + avl = gpr_avl_add(avl, box(208), box(306)); + avl = gpr_avl_add(avl, box(699), box(307)); + avl = remove_int(avl, 576); + avl = remove_int(avl, 850); + avl = remove_int(avl, 514); + avl = remove_int(avl, 676); + avl = remove_int(avl, 549); + avl = remove_int(avl, 767); + avl = gpr_avl_add(avl, box(58), box(314)); + avl = gpr_avl_add(avl, box(265), box(315)); + avl = gpr_avl_add(avl, box(268), box(316)); + avl = gpr_avl_add(avl, box(103), box(317)); + avl = gpr_avl_add(avl, box(440), box(318)); + avl = remove_int(avl, 777); + avl = gpr_avl_add(avl, box(670), box(320)); + avl = remove_int(avl, 506); + avl = remove_int(avl, 487); + avl = gpr_avl_add(avl, box(421), box(323)); + avl = remove_int(avl, 514); + avl = gpr_avl_add(avl, box(701), box(325)); + avl = remove_int(avl, 949); + avl = remove_int(avl, 872); + avl = remove_int(avl, 139); + avl = gpr_avl_add(avl, box(781), box(329)); + avl = gpr_avl_add(avl, box(543), box(330)); + avl = gpr_avl_add(avl, box(147), box(331)); + avl = remove_int(avl, 190); + avl = gpr_avl_add(avl, box(453), box(333)); + avl = remove_int(avl, 262); + avl = remove_int(avl, 850); + avl = remove_int(avl, 286); + avl = remove_int(avl, 787); + avl = gpr_avl_add(avl, box(514), box(338)); + avl = remove_int(avl, 812); + avl = gpr_avl_add(avl, box(431), box(340)); + avl = gpr_avl_add(avl, box(8), box(341)); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(831), box(343)); + avl = remove_int(avl, 472); + avl = remove_int(avl, 157); + avl = gpr_avl_add(avl, box(612), box(346)); + avl = gpr_avl_add(avl, box(802), box(347)); + avl = remove_int(avl, 554); + avl = gpr_avl_add(avl, box(409), box(349)); + avl = gpr_avl_add(avl, box(439), box(350)); + avl = gpr_avl_add(avl, box(725), box(351)); + avl = gpr_avl_add(avl, box(568), box(352)); + avl = remove_int(avl, 475); + avl = remove_int(avl, 672); + avl = remove_int(avl, 62); + avl = remove_int(avl, 753); + avl = gpr_avl_add(avl, box(435), box(357)); + avl = gpr_avl_add(avl, box(950), box(358)); + avl = gpr_avl_add(avl, box(532), box(359)); + avl = gpr_avl_add(avl, box(832), box(360)); + avl = remove_int(avl, 390); + avl = gpr_avl_add(avl, box(993), box(362)); + avl = remove_int(avl, 198); + avl = remove_int(avl, 401); + avl = gpr_avl_add(avl, box(316), box(365)); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(541), box(367)); + avl = gpr_avl_add(avl, box(505), box(368)); + avl = remove_int(avl, 445); + avl = remove_int(avl, 256); + avl = gpr_avl_add(avl, box(232), box(371)); + avl = remove_int(avl, 577); + avl = remove_int(avl, 558); + avl = gpr_avl_add(avl, box(910), box(374)); + avl = remove_int(avl, 902); + avl = remove_int(avl, 755); + avl = remove_int(avl, 114); + avl = remove_int(avl, 438); + avl = remove_int(avl, 224); + avl = gpr_avl_add(avl, box(920), box(380)); + avl = gpr_avl_add(avl, box(655), box(381)); + avl = remove_int(avl, 557); + avl = remove_int(avl, 102); + avl = remove_int(avl, 165); + avl = gpr_avl_add(avl, box(191), box(385)); + avl = remove_int(avl, 30); + avl = gpr_avl_add(avl, box(406), box(387)); + avl = gpr_avl_add(avl, box(66), box(388)); + avl = gpr_avl_add(avl, box(87), box(389)); + avl = remove_int(avl, 7); + avl = remove_int(avl, 671); + avl = gpr_avl_add(avl, box(234), box(392)); + avl = remove_int(avl, 463); + avl = gpr_avl_add(avl, box(75), box(394)); + avl = gpr_avl_add(avl, box(487), box(395)); + avl = remove_int(avl, 203); + avl = gpr_avl_add(avl, box(711), box(397)); + avl = remove_int(avl, 291); + avl = remove_int(avl, 798); + avl = remove_int(avl, 337); + avl = gpr_avl_add(avl, box(877), box(401)); + avl = gpr_avl_add(avl, box(388), box(402)); + avl = remove_int(avl, 975); + avl = gpr_avl_add(avl, box(200), box(404)); + avl = gpr_avl_add(avl, box(408), box(405)); + avl = gpr_avl_add(avl, box(3), box(406)); + avl = gpr_avl_add(avl, box(971), box(407)); + avl = remove_int(avl, 841); + avl = remove_int(avl, 910); + avl = remove_int(avl, 74); + avl = remove_int(avl, 888); + avl = gpr_avl_add(avl, box(492), box(412)); + avl = remove_int(avl, 14); + avl = remove_int(avl, 364); + avl = gpr_avl_add(avl, box(215), box(415)); + avl = remove_int(avl, 778); + avl = remove_int(avl, 45); + avl = gpr_avl_add(avl, box(328), box(418)); + avl = gpr_avl_add(avl, box(597), box(419)); + avl = remove_int(avl, 34); + avl = gpr_avl_add(avl, box(736), box(421)); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(275), box(423)); + avl = gpr_avl_add(avl, box(70), box(424)); + avl = gpr_avl_add(avl, box(771), box(425)); + avl = remove_int(avl, 536); + avl = remove_int(avl, 421); + avl = gpr_avl_add(avl, box(186), box(428)); + avl = gpr_avl_add(avl, box(788), box(429)); + avl = gpr_avl_add(avl, box(224), box(430)); + avl = remove_int(avl, 228); + avl = gpr_avl_add(avl, box(48), box(432)); + avl = gpr_avl_add(avl, box(120), box(433)); + avl = gpr_avl_add(avl, box(269), box(434)); + avl = gpr_avl_add(avl, box(904), box(435)); + avl = remove_int(avl, 699); + avl = gpr_avl_add(avl, box(340), box(437)); + avl = remove_int(avl, 276); + avl = gpr_avl_add(avl, box(591), box(439)); + avl = gpr_avl_add(avl, box(778), box(440)); + avl = remove_int(avl, 490); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(294), box(443)); + avl = gpr_avl_add(avl, box(323), box(444)); + avl = remove_int(avl, 685); + avl = gpr_avl_add(avl, box(38), box(446)); + avl = gpr_avl_add(avl, box(525), box(447)); + avl = remove_int(avl, 162); + avl = gpr_avl_add(avl, box(462), box(449)); + avl = gpr_avl_add(avl, box(340), box(450)); + avl = remove_int(avl, 734); + avl = remove_int(avl, 959); + avl = gpr_avl_add(avl, box(752), box(453)); + avl = gpr_avl_add(avl, box(667), box(454)); + avl = remove_int(avl, 558); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(711), box(457)); + avl = remove_int(avl, 937); + avl = gpr_avl_add(avl, box(741), box(459)); + avl = gpr_avl_add(avl, box(40), box(460)); + avl = remove_int(avl, 784); + avl = gpr_avl_add(avl, box(292), box(462)); + avl = remove_int(avl, 164); + avl = remove_int(avl, 931); + avl = remove_int(avl, 886); + avl = gpr_avl_add(avl, box(968), box(466)); + avl = remove_int(avl, 263); + avl = gpr_avl_add(avl, box(647), box(468)); + avl = gpr_avl_add(avl, box(92), box(469)); + avl = remove_int(avl, 310); + avl = gpr_avl_add(avl, box(711), box(471)); + avl = gpr_avl_add(avl, box(675), box(472)); + avl = remove_int(avl, 549); + avl = gpr_avl_add(avl, box(380), box(474)); + avl = remove_int(avl, 825); + avl = gpr_avl_add(avl, box(668), box(476)); + avl = remove_int(avl, 498); + avl = gpr_avl_add(avl, box(870), box(478)); + avl = gpr_avl_add(avl, box(391), box(479)); + avl = gpr_avl_add(avl, box(264), box(480)); + avl = remove_int(avl, 1); + avl = remove_int(avl, 849); + avl = remove_int(avl, 88); + avl = remove_int(avl, 255); + avl = remove_int(avl, 763); + avl = remove_int(avl, 831); + avl = gpr_avl_add(avl, box(508), box(487)); + avl = remove_int(avl, 849); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(299), box(490)); + avl = remove_int(avl, 625); + avl = remove_int(avl, 433); + avl = remove_int(avl, 904); + avl = remove_int(avl, 761); + avl = gpr_avl_add(avl, box(33), box(495)); + avl = gpr_avl_add(avl, box(524), box(496)); + avl = remove_int(avl, 210); + avl = remove_int(avl, 299); + avl = gpr_avl_add(avl, box(823), box(499)); + avl = remove_int(avl, 479); + avl = remove_int(avl, 96); + avl = remove_int(avl, 1013); + avl = gpr_avl_add(avl, box(768), box(503)); + avl = remove_int(avl, 638); + avl = remove_int(avl, 20); + avl = gpr_avl_add(avl, box(663), box(506)); + avl = remove_int(avl, 882); + avl = gpr_avl_add(avl, box(745), box(508)); + avl = remove_int(avl, 352); + avl = gpr_avl_add(avl, box(10), box(510)); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(420), box(512)); + avl = gpr_avl_add(avl, box(884), box(513)); + avl = gpr_avl_add(avl, box(993), box(514)); + avl = gpr_avl_add(avl, box(251), box(515)); + avl = remove_int(avl, 222); + avl = gpr_avl_add(avl, box(734), box(517)); + avl = gpr_avl_add(avl, box(952), box(518)); + avl = remove_int(avl, 26); + avl = remove_int(avl, 270); + avl = remove_int(avl, 481); + avl = remove_int(avl, 693); + avl = remove_int(avl, 1006); + avl = gpr_avl_add(avl, box(77), box(524)); + avl = remove_int(avl, 897); + avl = gpr_avl_add(avl, box(719), box(526)); + avl = gpr_avl_add(avl, box(622), box(527)); + avl = remove_int(avl, 28); + avl = remove_int(avl, 836); + avl = remove_int(avl, 142); + avl = gpr_avl_add(avl, box(445), box(531)); + avl = gpr_avl_add(avl, box(410), box(532)); + avl = remove_int(avl, 575); + avl = gpr_avl_add(avl, box(634), box(534)); + avl = gpr_avl_add(avl, box(906), box(535)); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(813), box(537)); + avl = remove_int(avl, 702); + avl = remove_int(avl, 732); + avl = gpr_avl_add(avl, box(105), box(540)); + avl = gpr_avl_add(avl, box(867), box(541)); + avl = remove_int(avl, 964); + avl = remove_int(avl, 941); + avl = gpr_avl_add(avl, box(947), box(544)); + avl = remove_int(avl, 990); + avl = gpr_avl_add(avl, box(816), box(546)); + avl = remove_int(avl, 429); + avl = remove_int(avl, 567); + avl = remove_int(avl, 541); + avl = remove_int(avl, 583); + avl = gpr_avl_add(avl, box(57), box(551)); + avl = gpr_avl_add(avl, box(786), box(552)); + avl = gpr_avl_add(avl, box(526), box(553)); + avl = remove_int(avl, 642); + avl = remove_int(avl, 220); + avl = remove_int(avl, 840); + avl = remove_int(avl, 548); + avl = gpr_avl_add(avl, box(528), box(558)); + avl = gpr_avl_add(avl, box(749), box(559)); + avl = gpr_avl_add(avl, box(194), box(560)); + avl = remove_int(avl, 517); + avl = gpr_avl_add(avl, box(102), box(562)); + avl = remove_int(avl, 189); + avl = gpr_avl_add(avl, box(927), box(564)); + avl = remove_int(avl, 846); + avl = remove_int(avl, 130); + avl = gpr_avl_add(avl, box(694), box(567)); + avl = remove_int(avl, 750); + avl = gpr_avl_add(avl, box(357), box(569)); + avl = remove_int(avl, 431); + avl = remove_int(avl, 91); + avl = gpr_avl_add(avl, box(640), box(572)); + avl = remove_int(avl, 4); + avl = gpr_avl_add(avl, box(81), box(574)); + avl = gpr_avl_add(avl, box(595), box(575)); + avl = remove_int(avl, 444); + avl = remove_int(avl, 262); + avl = remove_int(avl, 11); + avl = gpr_avl_add(avl, box(192), box(579)); + avl = gpr_avl_add(avl, box(158), box(580)); + avl = remove_int(avl, 401); + avl = remove_int(avl, 918); + avl = gpr_avl_add(avl, box(180), box(583)); + avl = remove_int(avl, 268); + avl = gpr_avl_add(avl, box(1012), box(585)); + avl = gpr_avl_add(avl, box(90), box(586)); + avl = gpr_avl_add(avl, box(946), box(587)); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(874), box(589)); + avl = gpr_avl_add(avl, box(679), box(590)); + avl = remove_int(avl, 53); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(646), box(593)); + avl = gpr_avl_add(avl, box(767), box(594)); + avl = gpr_avl_add(avl, box(460), box(595)); + avl = gpr_avl_add(avl, box(852), box(596)); + avl = gpr_avl_add(avl, box(189), box(597)); + avl = remove_int(avl, 932); + avl = remove_int(avl, 366); + avl = remove_int(avl, 907); + avl = gpr_avl_add(avl, box(875), box(601)); + avl = gpr_avl_add(avl, box(434), box(602)); + avl = gpr_avl_add(avl, box(704), box(603)); + avl = gpr_avl_add(avl, box(724), box(604)); + avl = gpr_avl_add(avl, box(930), box(605)); + avl = gpr_avl_add(avl, box(1000), box(606)); + avl = remove_int(avl, 479); + avl = gpr_avl_add(avl, box(275), box(608)); + avl = remove_int(avl, 32); + avl = gpr_avl_add(avl, box(939), box(610)); + avl = remove_int(avl, 943); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(490), box(613)); + avl = remove_int(avl, 477); + avl = remove_int(avl, 414); + avl = remove_int(avl, 187); + avl = remove_int(avl, 334); + avl = gpr_avl_add(avl, box(40), box(618)); + avl = remove_int(avl, 751); + avl = gpr_avl_add(avl, box(568), box(620)); + avl = gpr_avl_add(avl, box(120), box(621)); + avl = gpr_avl_add(avl, box(617), box(622)); + avl = gpr_avl_add(avl, box(32), box(623)); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(910), box(625)); + avl = remove_int(avl, 557); + avl = remove_int(avl, 361); + avl = remove_int(avl, 937); + avl = remove_int(avl, 100); + avl = remove_int(avl, 684); + avl = gpr_avl_add(avl, box(751), box(631)); + avl = remove_int(avl, 781); + avl = remove_int(avl, 469); + avl = remove_int(avl, 75); + avl = remove_int(avl, 561); + avl = gpr_avl_add(avl, box(854), box(636)); + avl = remove_int(avl, 164); + avl = remove_int(avl, 258); + avl = remove_int(avl, 315); + avl = remove_int(avl, 261); + avl = gpr_avl_add(avl, box(552), box(641)); + avl = gpr_avl_add(avl, box(6), box(642)); + avl = gpr_avl_add(avl, box(680), box(643)); + avl = remove_int(avl, 741); + avl = remove_int(avl, 309); + avl = remove_int(avl, 272); + avl = gpr_avl_add(avl, box(249), box(647)); + avl = remove_int(avl, 97); + avl = remove_int(avl, 850); + avl = gpr_avl_add(avl, box(915), box(650)); + avl = gpr_avl_add(avl, box(816), box(651)); + avl = gpr_avl_add(avl, box(45), box(652)); + avl = gpr_avl_add(avl, box(168), box(653)); + avl = remove_int(avl, 153); + avl = remove_int(avl, 239); + avl = gpr_avl_add(avl, box(684), box(656)); + avl = gpr_avl_add(avl, box(208), box(657)); + avl = gpr_avl_add(avl, box(681), box(658)); + avl = gpr_avl_add(avl, box(609), box(659)); + avl = gpr_avl_add(avl, box(645), box(660)); + avl = remove_int(avl, 799); + avl = gpr_avl_add(avl, box(955), box(662)); + avl = gpr_avl_add(avl, box(946), box(663)); + avl = gpr_avl_add(avl, box(744), box(664)); + avl = gpr_avl_add(avl, box(201), box(665)); + avl = gpr_avl_add(avl, box(136), box(666)); + avl = remove_int(avl, 357); + avl = gpr_avl_add(avl, box(974), box(668)); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(1009), box(670)); + avl = gpr_avl_add(avl, box(517), box(671)); + avl = remove_int(avl, 491); + avl = gpr_avl_add(avl, box(336), box(673)); + avl = gpr_avl_add(avl, box(589), box(674)); + avl = remove_int(avl, 546); + avl = remove_int(avl, 840); + avl = remove_int(avl, 104); + avl = remove_int(avl, 347); + avl = gpr_avl_add(avl, box(801), box(679)); + avl = remove_int(avl, 799); + avl = remove_int(avl, 702); + avl = remove_int(avl, 996); + avl = remove_int(avl, 93); + avl = gpr_avl_add(avl, box(561), box(684)); + avl = gpr_avl_add(avl, box(25), box(685)); + avl = remove_int(avl, 278); + avl = gpr_avl_add(avl, box(191), box(687)); + avl = remove_int(avl, 243); + avl = remove_int(avl, 918); + avl = remove_int(avl, 449); + avl = gpr_avl_add(avl, box(19), box(691)); + avl = gpr_avl_add(avl, box(762), box(692)); + avl = gpr_avl_add(avl, box(13), box(693)); + avl = gpr_avl_add(avl, box(151), box(694)); + avl = gpr_avl_add(avl, box(152), box(695)); + avl = gpr_avl_add(avl, box(793), box(696)); + avl = remove_int(avl, 862); + avl = remove_int(avl, 890); + avl = gpr_avl_add(avl, box(687), box(699)); + avl = gpr_avl_add(avl, box(509), box(700)); + avl = gpr_avl_add(avl, box(973), box(701)); + avl = remove_int(avl, 230); + avl = gpr_avl_add(avl, box(532), box(703)); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(281), box(705)); + avl = gpr_avl_add(avl, box(867), box(706)); + avl = gpr_avl_add(avl, box(359), box(707)); + avl = remove_int(avl, 425); + avl = gpr_avl_add(avl, box(691), box(709)); + avl = gpr_avl_add(avl, box(163), box(710)); + avl = gpr_avl_add(avl, box(502), box(711)); + avl = remove_int(avl, 674); + avl = gpr_avl_add(avl, box(697), box(713)); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(968), box(715)); + avl = gpr_avl_add(avl, box(48), box(716)); + avl = remove_int(avl, 543); + avl = gpr_avl_add(avl, box(35), box(718)); + avl = gpr_avl_add(avl, box(751), box(719)); + avl = gpr_avl_add(avl, box(478), box(720)); + avl = remove_int(avl, 797); + avl = remove_int(avl, 309); + avl = gpr_avl_add(avl, box(927), box(723)); + avl = remove_int(avl, 504); + avl = gpr_avl_add(avl, box(286), box(725)); + avl = gpr_avl_add(avl, box(413), box(726)); + avl = gpr_avl_add(avl, box(599), box(727)); + avl = remove_int(avl, 105); + avl = remove_int(avl, 605); + avl = gpr_avl_add(avl, box(632), box(730)); + avl = gpr_avl_add(avl, box(133), box(731)); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(958), box(733)); + avl = gpr_avl_add(avl, box(729), box(734)); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(694), box(736)); + avl = gpr_avl_add(avl, box(505), box(737)); + avl = remove_int(avl, 63); + avl = remove_int(avl, 714); + avl = gpr_avl_add(avl, box(1002), box(740)); + avl = remove_int(avl, 211); + avl = gpr_avl_add(avl, box(765), box(742)); + avl = gpr_avl_add(avl, box(455), box(743)); + avl = remove_int(avl, 59); + avl = remove_int(avl, 224); + avl = gpr_avl_add(avl, box(586), box(746)); + avl = gpr_avl_add(avl, box(348), box(747)); + avl = remove_int(avl, 10); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(968), box(750)); + avl = gpr_avl_add(avl, box(923), box(751)); + avl = remove_int(avl, 573); + avl = remove_int(avl, 617); + avl = gpr_avl_add(avl, box(812), box(754)); + avl = gpr_avl_add(avl, box(179), box(755)); + avl = remove_int(avl, 284); + avl = remove_int(avl, 157); + avl = remove_int(avl, 177); + avl = remove_int(avl, 896); + avl = gpr_avl_add(avl, box(649), box(760)); + avl = gpr_avl_add(avl, box(927), box(761)); + avl = gpr_avl_add(avl, box(454), box(762)); + avl = gpr_avl_add(avl, box(217), box(763)); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(180), box(765)); + avl = gpr_avl_add(avl, box(319), box(766)); + avl = remove_int(avl, 92); + avl = gpr_avl_add(avl, box(483), box(768)); + avl = remove_int(avl, 504); + avl = remove_int(avl, 1017); + avl = remove_int(avl, 37); + avl = remove_int(avl, 50); + avl = gpr_avl_add(avl, box(302), box(773)); + avl = remove_int(avl, 807); + avl = gpr_avl_add(avl, box(463), box(775)); + avl = gpr_avl_add(avl, box(271), box(776)); + avl = gpr_avl_add(avl, box(644), box(777)); + avl = remove_int(avl, 618); + avl = gpr_avl_add(avl, box(166), box(779)); + avl = gpr_avl_add(avl, box(538), box(780)); + avl = remove_int(avl, 606); + avl = gpr_avl_add(avl, box(425), box(782)); + avl = remove_int(avl, 725); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(155), box(785)); + avl = remove_int(avl, 889); + avl = gpr_avl_add(avl, box(653), box(787)); + avl = remove_int(avl, 386); + avl = gpr_avl_add(avl, box(142), box(789)); + avl = remove_int(avl, 107); + avl = remove_int(avl, 603); + avl = remove_int(avl, 971); + avl = gpr_avl_add(avl, box(80), box(793)); + avl = gpr_avl_add(avl, box(61), box(794)); + avl = gpr_avl_add(avl, box(693), box(795)); + avl = gpr_avl_add(avl, box(592), box(796)); + avl = gpr_avl_add(avl, box(433), box(797)); + avl = gpr_avl_add(avl, box(973), box(798)); + avl = remove_int(avl, 901); + avl = remove_int(avl, 340); + avl = remove_int(avl, 709); + avl = gpr_avl_add(avl, box(224), box(802)); + avl = remove_int(avl, 120); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(780), box(805)); + avl = gpr_avl_add(avl, box(867), box(806)); + avl = gpr_avl_add(avl, box(756), box(807)); + avl = gpr_avl_add(avl, box(583), box(808)); + avl = gpr_avl_add(avl, box(356), box(809)); + avl = gpr_avl_add(avl, box(58), box(810)); + avl = remove_int(avl, 219); + avl = gpr_avl_add(avl, box(301), box(812)); + avl = remove_int(avl, 643); + avl = remove_int(avl, 787); + avl = remove_int(avl, 583); + avl = remove_int(avl, 552); + avl = remove_int(avl, 308); + avl = remove_int(avl, 608); + avl = remove_int(avl, 363); + avl = remove_int(avl, 690); + avl = gpr_avl_add(avl, box(233), box(821)); + avl = gpr_avl_add(avl, box(479), box(822)); + avl = gpr_avl_add(avl, box(323), box(823)); + avl = gpr_avl_add(avl, box(802), box(824)); + avl = remove_int(avl, 682); + avl = remove_int(avl, 705); + avl = remove_int(avl, 487); + avl = gpr_avl_add(avl, box(530), box(828)); + avl = gpr_avl_add(avl, box(232), box(829)); + avl = remove_int(avl, 627); + avl = gpr_avl_add(avl, box(396), box(831)); + avl = gpr_avl_add(avl, box(61), box(832)); + avl = gpr_avl_add(avl, box(932), box(833)); + avl = gpr_avl_add(avl, box(108), box(834)); + avl = gpr_avl_add(avl, box(524), box(835)); + avl = remove_int(avl, 390); + avl = remove_int(avl, 307); + avl = gpr_avl_add(avl, box(722), box(838)); + avl = gpr_avl_add(avl, box(907), box(839)); + avl = remove_int(avl, 286); + avl = remove_int(avl, 337); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(973), box(843)); + avl = remove_int(avl, 930); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(997), box(846)); + avl = gpr_avl_add(avl, box(689), box(847)); + avl = remove_int(avl, 318); + avl = gpr_avl_add(avl, box(703), box(849)); + avl = gpr_avl_add(avl, box(868), box(850)); + avl = gpr_avl_add(avl, box(200), box(851)); + avl = gpr_avl_add(avl, box(960), box(852)); + avl = gpr_avl_add(avl, box(80), box(853)); + avl = remove_int(avl, 113); + avl = gpr_avl_add(avl, box(135), box(855)); + avl = remove_int(avl, 529); + avl = gpr_avl_add(avl, box(366), box(857)); + avl = remove_int(avl, 272); + avl = gpr_avl_add(avl, box(921), box(859)); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(712), box(861)); + avl = remove_int(avl, 777); + avl = remove_int(avl, 505); + avl = remove_int(avl, 974); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(388), box(866)); + avl = gpr_avl_add(avl, box(29), box(867)); + avl = gpr_avl_add(avl, box(180), box(868)); + avl = gpr_avl_add(avl, box(983), box(869)); + avl = gpr_avl_add(avl, box(72), box(870)); + avl = gpr_avl_add(avl, box(693), box(871)); + avl = gpr_avl_add(avl, box(567), box(872)); + avl = remove_int(avl, 549); + avl = remove_int(avl, 351); + avl = gpr_avl_add(avl, box(1019), box(875)); + avl = remove_int(avl, 585); + avl = remove_int(avl, 294); + avl = remove_int(avl, 61); + avl = gpr_avl_add(avl, box(409), box(879)); + avl = gpr_avl_add(avl, box(984), box(880)); + avl = gpr_avl_add(avl, box(830), box(881)); + avl = remove_int(avl, 579); + avl = gpr_avl_add(avl, box(672), box(883)); + avl = remove_int(avl, 968); + + gpr_avl_unref(avl); +} + +static void test_badcase3(void) { + gpr_avl avl; + + gpr_log(GPR_DEBUG, "test_badcase3"); + + avl = gpr_avl_create(&int_int_vtable); + avl = remove_int(avl, 624); + avl = gpr_avl_add(avl, box(59), box(2)); + avl = gpr_avl_add(avl, box(494), box(3)); + avl = gpr_avl_add(avl, box(226), box(4)); + avl = remove_int(avl, 524); + avl = gpr_avl_add(avl, box(540), box(6)); + avl = remove_int(avl, 1008); + avl = gpr_avl_add(avl, box(502), box(8)); + avl = remove_int(avl, 267); + avl = remove_int(avl, 764); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(8), box(12)); + avl = remove_int(avl, 291); + avl = remove_int(avl, 796); + avl = remove_int(avl, 1002); + avl = gpr_avl_add(avl, box(778), box(16)); + avl = remove_int(avl, 621); + avl = remove_int(avl, 891); + avl = remove_int(avl, 880); + avl = gpr_avl_add(avl, box(197), box(20)); + avl = gpr_avl_add(avl, box(441), box(21)); + avl = gpr_avl_add(avl, box(719), box(22)); + avl = remove_int(avl, 109); + avl = gpr_avl_add(avl, box(458), box(24)); + avl = remove_int(avl, 86); + avl = gpr_avl_add(avl, box(897), box(26)); + avl = gpr_avl_add(avl, box(997), box(27)); + avl = remove_int(avl, 235); + avl = remove_int(avl, 425); + avl = remove_int(avl, 186); + avl = gpr_avl_add(avl, box(887), box(31)); + avl = gpr_avl_add(avl, box(1005), box(32)); + avl = gpr_avl_add(avl, box(778), box(33)); + avl = gpr_avl_add(avl, box(575), box(34)); + avl = remove_int(avl, 966); + avl = remove_int(avl, 1015); + avl = gpr_avl_add(avl, box(486), box(37)); + avl = gpr_avl_add(avl, box(809), box(38)); + avl = gpr_avl_add(avl, box(907), box(39)); + avl = gpr_avl_add(avl, box(971), box(40)); + avl = remove_int(avl, 441); + avl = remove_int(avl, 498); + avl = gpr_avl_add(avl, box(727), box(43)); + avl = remove_int(avl, 679); + avl = remove_int(avl, 740); + avl = remove_int(avl, 532); + avl = gpr_avl_add(avl, box(805), box(47)); + avl = remove_int(avl, 64); + avl = gpr_avl_add(avl, box(362), box(49)); + avl = gpr_avl_add(avl, box(170), box(50)); + avl = gpr_avl_add(avl, box(389), box(51)); + avl = gpr_avl_add(avl, box(689), box(52)); + avl = remove_int(avl, 871); + avl = gpr_avl_add(avl, box(447), box(54)); + avl = remove_int(avl, 718); + avl = gpr_avl_add(avl, box(724), box(56)); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(550), box(58)); + avl = remove_int(avl, 932); + avl = gpr_avl_add(avl, box(47), box(60)); + avl = remove_int(avl, 46); + avl = remove_int(avl, 229); + avl = gpr_avl_add(avl, box(68), box(63)); + avl = gpr_avl_add(avl, box(387), box(64)); + avl = remove_int(avl, 933); + avl = remove_int(avl, 736); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(150), box(68)); + avl = remove_int(avl, 875); + avl = remove_int(avl, 298); + avl = gpr_avl_add(avl, box(991), box(71)); + avl = remove_int(avl, 705); + avl = gpr_avl_add(avl, box(197), box(73)); + avl = gpr_avl_add(avl, box(101), box(74)); + avl = remove_int(avl, 436); + avl = gpr_avl_add(avl, box(755), box(76)); + avl = gpr_avl_add(avl, box(727), box(77)); + avl = remove_int(avl, 309); + avl = remove_int(avl, 253); + avl = gpr_avl_add(avl, box(203), box(80)); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(461), box(82)); + avl = remove_int(avl, 316); + avl = remove_int(avl, 493); + avl = gpr_avl_add(avl, box(184), box(85)); + avl = remove_int(avl, 737); + avl = gpr_avl_add(avl, box(790), box(87)); + avl = gpr_avl_add(avl, box(335), box(88)); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(69), box(90)); + avl = remove_int(avl, 585); + avl = remove_int(avl, 543); + avl = gpr_avl_add(avl, box(784), box(93)); + avl = gpr_avl_add(avl, box(60), box(94)); + avl = gpr_avl_add(avl, box(525), box(95)); + avl = gpr_avl_add(avl, box(177), box(96)); + avl = gpr_avl_add(avl, box(178), box(97)); + avl = gpr_avl_add(avl, box(683), box(98)); + avl = gpr_avl_add(avl, box(226), box(99)); + avl = gpr_avl_add(avl, box(662), box(100)); + avl = remove_int(avl, 944); + avl = gpr_avl_add(avl, box(562), box(102)); + avl = gpr_avl_add(avl, box(793), box(103)); + avl = remove_int(avl, 673); + avl = gpr_avl_add(avl, box(310), box(105)); + avl = remove_int(avl, 479); + avl = remove_int(avl, 543); + avl = remove_int(avl, 159); + avl = remove_int(avl, 850); + avl = gpr_avl_add(avl, box(318), box(110)); + avl = gpr_avl_add(avl, box(483), box(111)); + avl = gpr_avl_add(avl, box(84), box(112)); + avl = remove_int(avl, 109); + avl = gpr_avl_add(avl, box(132), box(114)); + avl = gpr_avl_add(avl, box(920), box(115)); + avl = remove_int(avl, 746); + avl = gpr_avl_add(avl, box(145), box(117)); + avl = gpr_avl_add(avl, box(526), box(118)); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(332), box(120)); + avl = gpr_avl_add(avl, box(918), box(121)); + avl = remove_int(avl, 339); + avl = gpr_avl_add(avl, box(809), box(123)); + avl = gpr_avl_add(avl, box(742), box(124)); + avl = gpr_avl_add(avl, box(718), box(125)); + avl = remove_int(avl, 988); + avl = remove_int(avl, 531); + avl = remove_int(avl, 840); + avl = gpr_avl_add(avl, box(816), box(129)); + avl = gpr_avl_add(avl, box(976), box(130)); + avl = remove_int(avl, 743); + avl = remove_int(avl, 528); + avl = remove_int(avl, 982); + avl = gpr_avl_add(avl, box(803), box(134)); + avl = gpr_avl_add(avl, box(205), box(135)); + avl = gpr_avl_add(avl, box(584), box(136)); + avl = remove_int(avl, 923); + avl = remove_int(avl, 538); + avl = remove_int(avl, 398); + avl = remove_int(avl, 320); + avl = remove_int(avl, 292); + avl = gpr_avl_add(avl, box(270), box(142)); + avl = gpr_avl_add(avl, box(333), box(143)); + avl = remove_int(avl, 439); + avl = gpr_avl_add(avl, box(35), box(145)); + avl = gpr_avl_add(avl, box(837), box(146)); + avl = remove_int(avl, 65); + avl = remove_int(avl, 642); + avl = remove_int(avl, 371); + avl = remove_int(avl, 140); + avl = remove_int(avl, 533); + avl = remove_int(avl, 676); + avl = gpr_avl_add(avl, box(624), box(153)); + avl = gpr_avl_add(avl, box(116), box(154)); + avl = gpr_avl_add(avl, box(446), box(155)); + avl = remove_int(avl, 91); + avl = remove_int(avl, 721); + avl = remove_int(avl, 537); + avl = gpr_avl_add(avl, box(448), box(159)); + avl = remove_int(avl, 155); + avl = remove_int(avl, 344); + avl = remove_int(avl, 237); + avl = gpr_avl_add(avl, box(309), box(163)); + avl = gpr_avl_add(avl, box(434), box(164)); + avl = gpr_avl_add(avl, box(277), box(165)); + avl = remove_int(avl, 233); + avl = gpr_avl_add(avl, box(275), box(167)); + avl = gpr_avl_add(avl, box(218), box(168)); + avl = gpr_avl_add(avl, box(76), box(169)); + avl = gpr_avl_add(avl, box(898), box(170)); + avl = remove_int(avl, 771); + avl = gpr_avl_add(avl, box(237), box(172)); + avl = remove_int(avl, 327); + avl = gpr_avl_add(avl, box(499), box(174)); + avl = remove_int(avl, 727); + avl = remove_int(avl, 234); + avl = remove_int(avl, 623); + avl = remove_int(avl, 458); + avl = remove_int(avl, 326); + avl = remove_int(avl, 589); + avl = gpr_avl_add(avl, box(442), box(181)); + avl = remove_int(avl, 389); + avl = gpr_avl_add(avl, box(708), box(183)); + avl = gpr_avl_add(avl, box(594), box(184)); + avl = gpr_avl_add(avl, box(942), box(185)); + avl = gpr_avl_add(avl, box(282), box(186)); + avl = remove_int(avl, 434); + avl = remove_int(avl, 134); + avl = remove_int(avl, 270); + avl = remove_int(avl, 512); + avl = remove_int(avl, 265); + avl = remove_int(avl, 21); + avl = remove_int(avl, 193); + avl = remove_int(avl, 797); + avl = remove_int(avl, 347); + avl = gpr_avl_add(avl, box(99), box(196)); + avl = gpr_avl_add(avl, box(161), box(197)); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(72), box(199)); + avl = remove_int(avl, 629); + avl = gpr_avl_add(avl, box(522), box(201)); + avl = remove_int(avl, 679); + avl = gpr_avl_add(avl, box(407), box(203)); + avl = remove_int(avl, 693); + avl = gpr_avl_add(avl, box(424), box(205)); + avl = gpr_avl_add(avl, box(651), box(206)); + avl = gpr_avl_add(avl, box(927), box(207)); + avl = remove_int(avl, 553); + avl = gpr_avl_add(avl, box(128), box(209)); + avl = gpr_avl_add(avl, box(616), box(210)); + avl = gpr_avl_add(avl, box(690), box(211)); + avl = remove_int(avl, 241); + avl = remove_int(avl, 179); + avl = gpr_avl_add(avl, box(697), box(214)); + avl = remove_int(avl, 779); + avl = gpr_avl_add(avl, box(241), box(216)); + avl = remove_int(avl, 190); + avl = remove_int(avl, 210); + avl = gpr_avl_add(avl, box(711), box(219)); + avl = remove_int(avl, 251); + avl = remove_int(avl, 61); + avl = gpr_avl_add(avl, box(800), box(222)); + avl = remove_int(avl, 551); + avl = gpr_avl_add(avl, box(61), box(224)); + avl = gpr_avl_add(avl, box(656), box(225)); + avl = remove_int(avl, 130); + avl = remove_int(avl, 368); + avl = remove_int(avl, 150); + avl = remove_int(avl, 73); + avl = gpr_avl_add(avl, box(799), box(230)); + avl = gpr_avl_add(avl, box(125), box(231)); + avl = remove_int(avl, 107); + avl = gpr_avl_add(avl, box(938), box(233)); + avl = gpr_avl_add(avl, box(914), box(234)); + avl = gpr_avl_add(avl, box(197), box(235)); + avl = remove_int(avl, 736); + avl = gpr_avl_add(avl, box(20), box(237)); + avl = remove_int(avl, 224); + avl = remove_int(avl, 841); + avl = gpr_avl_add(avl, box(226), box(240)); + avl = remove_int(avl, 963); + avl = remove_int(avl, 796); + avl = remove_int(avl, 728); + avl = gpr_avl_add(avl, box(855), box(244)); + avl = gpr_avl_add(avl, box(769), box(245)); + avl = gpr_avl_add(avl, box(631), box(246)); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(187), box(248)); + avl = gpr_avl_add(avl, box(31), box(249)); + avl = remove_int(avl, 163); + avl = gpr_avl_add(avl, box(218), box(251)); + avl = gpr_avl_add(avl, box(488), box(252)); + avl = gpr_avl_add(avl, box(387), box(253)); + avl = gpr_avl_add(avl, box(809), box(254)); + avl = gpr_avl_add(avl, box(997), box(255)); + avl = remove_int(avl, 678); + avl = gpr_avl_add(avl, box(368), box(257)); + avl = gpr_avl_add(avl, box(220), box(258)); + avl = gpr_avl_add(avl, box(373), box(259)); + avl = remove_int(avl, 874); + avl = remove_int(avl, 682); + avl = remove_int(avl, 1014); + avl = remove_int(avl, 195); + avl = gpr_avl_add(avl, box(868), box(264)); + avl = remove_int(avl, 254); + avl = remove_int(avl, 456); + avl = gpr_avl_add(avl, box(906), box(267)); + avl = remove_int(avl, 711); + avl = gpr_avl_add(avl, box(632), box(269)); + avl = remove_int(avl, 474); + avl = gpr_avl_add(avl, box(508), box(271)); + avl = gpr_avl_add(avl, box(518), box(272)); + avl = remove_int(avl, 579); + avl = remove_int(avl, 948); + avl = gpr_avl_add(avl, box(789), box(275)); + avl = gpr_avl_add(avl, box(48), box(276)); + avl = gpr_avl_add(avl, box(256), box(277)); + avl = gpr_avl_add(avl, box(754), box(278)); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(679), box(280)); + avl = gpr_avl_add(avl, box(606), box(281)); + avl = remove_int(avl, 941); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(758), box(284)); + avl = remove_int(avl, 101); + avl = gpr_avl_add(avl, box(244), box(286)); + avl = gpr_avl_add(avl, box(337), box(287)); + avl = gpr_avl_add(avl, box(461), box(288)); + avl = remove_int(avl, 476); + avl = gpr_avl_add(avl, box(845), box(290)); + avl = remove_int(avl, 160); + avl = gpr_avl_add(avl, box(690), box(292)); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(869), box(294)); + avl = gpr_avl_add(avl, box(1019), box(295)); + avl = remove_int(avl, 591); + avl = remove_int(avl, 635); + avl = remove_int(avl, 67); + avl = gpr_avl_add(avl, box(113), box(299)); + avl = remove_int(avl, 305); + avl = gpr_avl_add(avl, box(10), box(301)); + avl = remove_int(avl, 823); + avl = remove_int(avl, 288); + avl = remove_int(avl, 239); + avl = gpr_avl_add(avl, box(646), box(305)); + avl = gpr_avl_add(avl, box(1006), box(306)); + avl = gpr_avl_add(avl, box(954), box(307)); + avl = gpr_avl_add(avl, box(199), box(308)); + avl = gpr_avl_add(avl, box(69), box(309)); + avl = gpr_avl_add(avl, box(984), box(310)); + avl = remove_int(avl, 568); + avl = remove_int(avl, 666); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(845), box(314)); + avl = remove_int(avl, 535); + avl = remove_int(avl, 365); + avl = remove_int(avl, 676); + avl = remove_int(avl, 892); + avl = remove_int(avl, 425); + avl = remove_int(avl, 704); + avl = remove_int(avl, 168); + avl = gpr_avl_add(avl, box(853), box(322)); + avl = gpr_avl_add(avl, box(335), box(323)); + avl = gpr_avl_add(avl, box(961), box(324)); + avl = gpr_avl_add(avl, box(73), box(325)); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(449), box(327)); + avl = remove_int(avl, 821); + avl = gpr_avl_add(avl, box(845), box(329)); + avl = remove_int(avl, 637); + avl = gpr_avl_add(avl, box(769), box(331)); + avl = gpr_avl_add(avl, box(901), box(332)); + avl = remove_int(avl, 142); + avl = remove_int(avl, 361); + avl = remove_int(avl, 876); + avl = gpr_avl_add(avl, box(614), box(336)); + avl = gpr_avl_add(avl, box(729), box(337)); + avl = remove_int(avl, 120); + avl = remove_int(avl, 473); + avl = remove_int(avl, 445); + avl = gpr_avl_add(avl, box(978), box(341)); + avl = gpr_avl_add(avl, box(164), box(342)); + avl = gpr_avl_add(avl, box(1), box(343)); + avl = remove_int(avl, 890); + avl = gpr_avl_add(avl, box(605), box(345)); + avl = gpr_avl_add(avl, box(178), box(346)); + avl = gpr_avl_add(avl, box(481), box(347)); + avl = gpr_avl_add(avl, box(772), box(348)); + avl = remove_int(avl, 824); + avl = remove_int(avl, 167); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(698), box(352)); + avl = gpr_avl_add(avl, box(202), box(353)); + avl = gpr_avl_add(avl, box(921), box(354)); + avl = gpr_avl_add(avl, box(875), box(355)); + avl = remove_int(avl, 197); + avl = remove_int(avl, 232); + avl = gpr_avl_add(avl, box(209), box(358)); + avl = remove_int(avl, 324); + avl = remove_int(avl, 56); + avl = remove_int(avl, 579); + avl = remove_int(avl, 255); + avl = remove_int(avl, 290); + avl = gpr_avl_add(avl, box(661), box(364)); + avl = gpr_avl_add(avl, box(113), box(365)); + avl = remove_int(avl, 767); + avl = gpr_avl_add(avl, box(586), box(367)); + avl = gpr_avl_add(avl, box(121), box(368)); + avl = remove_int(avl, 235); + avl = remove_int(avl, 439); + avl = remove_int(avl, 360); + avl = gpr_avl_add(avl, box(916), box(372)); + avl = remove_int(avl, 999); + avl = gpr_avl_add(avl, box(825), box(374)); + avl = gpr_avl_add(avl, box(177), box(375)); + avl = remove_int(avl, 204); + avl = remove_int(avl, 92); + avl = gpr_avl_add(avl, box(794), box(378)); + avl = gpr_avl_add(avl, box(463), box(379)); + avl = gpr_avl_add(avl, box(472), box(380)); + avl = remove_int(avl, 235); + avl = gpr_avl_add(avl, box(840), box(382)); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(586), box(384)); + avl = gpr_avl_add(avl, box(979), box(385)); + avl = remove_int(avl, 979); + avl = gpr_avl_add(avl, box(639), box(387)); + avl = remove_int(avl, 907); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(913), box(390)); + avl = gpr_avl_add(avl, box(566), box(391)); + avl = gpr_avl_add(avl, box(883), box(392)); + avl = gpr_avl_add(avl, box(552), box(393)); + avl = gpr_avl_add(avl, box(16), box(394)); + avl = remove_int(avl, 60); + avl = gpr_avl_add(avl, box(567), box(396)); + avl = gpr_avl_add(avl, box(705), box(397)); + avl = gpr_avl_add(avl, box(94), box(398)); + avl = remove_int(avl, 321); + avl = gpr_avl_add(avl, box(207), box(400)); + avl = gpr_avl_add(avl, box(682), box(401)); + avl = gpr_avl_add(avl, box(592), box(402)); + avl = gpr_avl_add(avl, box(10), box(403)); + avl = remove_int(avl, 911); + avl = remove_int(avl, 161); + avl = gpr_avl_add(avl, box(86), box(406)); + avl = remove_int(avl, 893); + avl = remove_int(avl, 362); + avl = gpr_avl_add(avl, box(599), box(409)); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(867), box(411)); + avl = remove_int(avl, 955); + avl = gpr_avl_add(avl, box(341), box(413)); + avl = gpr_avl_add(avl, box(887), box(414)); + avl = remove_int(avl, 706); + avl = gpr_avl_add(avl, box(939), box(416)); + avl = remove_int(avl, 233); + avl = remove_int(avl, 662); + avl = remove_int(avl, 984); + avl = remove_int(avl, 203); + avl = gpr_avl_add(avl, box(326), box(421)); + avl = remove_int(avl, 848); + avl = gpr_avl_add(avl, box(235), box(423)); + avl = remove_int(avl, 617); + avl = gpr_avl_add(avl, box(565), box(425)); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(988), box(427)); + avl = remove_int(avl, 957); + avl = gpr_avl_add(avl, box(426), box(429)); + avl = remove_int(avl, 967); + avl = gpr_avl_add(avl, box(890), box(431)); + avl = gpr_avl_add(avl, box(473), box(432)); + avl = remove_int(avl, 367); + avl = remove_int(avl, 344); + avl = remove_int(avl, 660); + avl = remove_int(avl, 448); + avl = remove_int(avl, 837); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(459), box(439)); + avl = remove_int(avl, 882); + avl = remove_int(avl, 782); + avl = gpr_avl_add(avl, box(408), box(442)); + avl = gpr_avl_add(avl, box(728), box(443)); + avl = remove_int(avl, 27); + avl = gpr_avl_add(avl, box(137), box(445)); + avl = gpr_avl_add(avl, box(239), box(446)); + avl = remove_int(avl, 854); + avl = gpr_avl_add(avl, box(104), box(448)); + avl = gpr_avl_add(avl, box(823), box(449)); + avl = gpr_avl_add(avl, box(524), box(450)); + avl = gpr_avl_add(avl, box(995), box(451)); + avl = remove_int(avl, 422); + avl = remove_int(avl, 220); + avl = gpr_avl_add(avl, box(856), box(454)); + avl = remove_int(avl, 332); + avl = gpr_avl_add(avl, box(679), box(456)); + avl = remove_int(avl, 18); + avl = gpr_avl_add(avl, box(837), box(458)); + avl = remove_int(avl, 405); + avl = remove_int(avl, 877); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(547), box(462)); + avl = remove_int(avl, 805); + avl = remove_int(avl, 862); + avl = gpr_avl_add(avl, box(75), box(465)); + avl = remove_int(avl, 41); + avl = gpr_avl_add(avl, box(310), box(467)); + avl = remove_int(avl, 855); + avl = gpr_avl_add(avl, box(20), box(469)); + avl = remove_int(avl, 186); + avl = remove_int(avl, 378); + avl = remove_int(avl, 442); + avl = remove_int(avl, 930); + avl = gpr_avl_add(avl, box(118), box(474)); + avl = gpr_avl_add(avl, box(96), box(475)); + avl = remove_int(avl, 854); + avl = gpr_avl_add(avl, box(65), box(477)); + avl = gpr_avl_add(avl, box(573), box(478)); + avl = gpr_avl_add(avl, box(4), box(479)); + avl = gpr_avl_add(avl, box(451), box(480)); + avl = gpr_avl_add(avl, box(774), box(481)); + avl = gpr_avl_add(avl, box(126), box(482)); + avl = remove_int(avl, 956); + avl = remove_int(avl, 591); + avl = remove_int(avl, 644); + avl = gpr_avl_add(avl, box(304), box(486)); + avl = remove_int(avl, 620); + avl = remove_int(avl, 394); + avl = gpr_avl_add(avl, box(1002), box(489)); + avl = gpr_avl_add(avl, box(837), box(490)); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(1005), box(492)); + avl = remove_int(avl, 21); + avl = gpr_avl_add(avl, box(396), box(494)); + avl = remove_int(avl, 966); + avl = gpr_avl_add(avl, box(105), box(496)); + avl = gpr_avl_add(avl, box(316), box(497)); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(188), box(499)); + avl = remove_int(avl, 200); + avl = gpr_avl_add(avl, box(98), box(501)); + avl = gpr_avl_add(avl, box(831), box(502)); + avl = gpr_avl_add(avl, box(227), box(503)); + avl = gpr_avl_add(avl, box(220), box(504)); + avl = remove_int(avl, 715); + avl = remove_int(avl, 279); + avl = gpr_avl_add(avl, box(701), box(507)); + avl = gpr_avl_add(avl, box(726), box(508)); + avl = gpr_avl_add(avl, box(815), box(509)); + avl = gpr_avl_add(avl, box(749), box(510)); + avl = remove_int(avl, 946); + avl = remove_int(avl, 449); + avl = remove_int(avl, 62); + avl = remove_int(avl, 487); + avl = gpr_avl_add(avl, box(545), box(515)); + avl = remove_int(avl, 59); + avl = gpr_avl_add(avl, box(168), box(517)); + avl = remove_int(avl, 337); + avl = gpr_avl_add(avl, box(69), box(519)); + avl = remove_int(avl, 600); + avl = gpr_avl_add(avl, box(591), box(521)); + avl = gpr_avl_add(avl, box(960), box(522)); + avl = gpr_avl_add(avl, box(116), box(523)); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(760), box(525)); + avl = gpr_avl_add(avl, box(664), box(526)); + avl = gpr_avl_add(avl, box(547), box(527)); + avl = remove_int(avl, 922); + avl = gpr_avl_add(avl, box(290), box(529)); + avl = gpr_avl_add(avl, box(859), box(530)); + avl = gpr_avl_add(avl, box(49), box(531)); + avl = remove_int(avl, 455); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(613), box(534)); + avl = gpr_avl_add(avl, box(326), box(535)); + avl = remove_int(avl, 615); + avl = gpr_avl_add(avl, box(45), box(537)); + avl = gpr_avl_add(avl, box(162), box(538)); + avl = gpr_avl_add(avl, box(189), box(539)); + avl = remove_int(avl, 68); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(608), box(542)); + avl = remove_int(avl, 821); + avl = gpr_avl_add(avl, box(978), box(544)); + avl = gpr_avl_add(avl, box(892), box(545)); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(708), box(547)); + avl = remove_int(avl, 135); + avl = remove_int(avl, 124); + avl = gpr_avl_add(avl, box(301), box(550)); + avl = gpr_avl_add(avl, box(939), box(551)); + avl = gpr_avl_add(avl, box(344), box(552)); + avl = remove_int(avl, 443); + avl = remove_int(avl, 122); + avl = gpr_avl_add(avl, box(636), box(555)); + avl = remove_int(avl, 558); + avl = gpr_avl_add(avl, box(923), box(557)); + avl = remove_int(avl, 827); + avl = gpr_avl_add(avl, box(649), box(559)); + avl = gpr_avl_add(avl, box(808), box(560)); + avl = remove_int(avl, 570); + avl = remove_int(avl, 434); + avl = gpr_avl_add(avl, box(40), box(563)); + avl = gpr_avl_add(avl, box(725), box(564)); + avl = remove_int(avl, 295); + avl = remove_int(avl, 615); + avl = remove_int(avl, 919); + avl = remove_int(avl, 170); + avl = remove_int(avl, 442); + avl = remove_int(avl, 971); + avl = gpr_avl_add(avl, box(483), box(571)); + avl = gpr_avl_add(avl, box(512), box(572)); + avl = remove_int(avl, 648); + avl = remove_int(avl, 78); + avl = remove_int(avl, 72); + avl = remove_int(avl, 790); + avl = remove_int(avl, 571); + avl = gpr_avl_add(avl, box(898), box(578)); + avl = remove_int(avl, 770); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(602), box(581)); + avl = remove_int(avl, 251); + avl = gpr_avl_add(avl, box(303), box(583)); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(714), box(585)); + avl = remove_int(avl, 800); + avl = gpr_avl_add(avl, box(266), box(587)); + avl = gpr_avl_add(avl, box(555), box(588)); + avl = remove_int(avl, 604); + avl = remove_int(avl, 163); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(296), box(592)); + avl = remove_int(avl, 129); + avl = gpr_avl_add(avl, box(656), box(594)); + avl = remove_int(avl, 769); + avl = remove_int(avl, 941); + avl = gpr_avl_add(avl, box(775), box(597)); + avl = gpr_avl_add(avl, box(846), box(598)); + avl = remove_int(avl, 591); + avl = remove_int(avl, 801); + avl = remove_int(avl, 419); + avl = remove_int(avl, 455); + avl = gpr_avl_add(avl, box(866), box(603)); + avl = gpr_avl_add(avl, box(575), box(604)); + avl = gpr_avl_add(avl, box(620), box(605)); + avl = remove_int(avl, 100); + avl = remove_int(avl, 667); + avl = gpr_avl_add(avl, box(138), box(608)); + avl = gpr_avl_add(avl, box(566), box(609)); + avl = gpr_avl_add(avl, box(673), box(610)); + avl = gpr_avl_add(avl, box(178), box(611)); + avl = remove_int(avl, 659); + avl = gpr_avl_add(avl, box(759), box(613)); + avl = gpr_avl_add(avl, box(1008), box(614)); + avl = remove_int(avl, 116); + avl = gpr_avl_add(avl, box(608), box(616)); + avl = gpr_avl_add(avl, box(339), box(617)); + avl = gpr_avl_add(avl, box(197), box(618)); + avl = remove_int(avl, 25); + avl = remove_int(avl, 628); + avl = gpr_avl_add(avl, box(487), box(621)); + avl = remove_int(avl, 739); + avl = remove_int(avl, 100); + avl = remove_int(avl, 928); + avl = gpr_avl_add(avl, box(647), box(625)); + avl = remove_int(avl, 978); + avl = remove_int(avl, 143); + avl = remove_int(avl, 755); + avl = gpr_avl_add(avl, box(71), box(629)); + avl = remove_int(avl, 205); + avl = gpr_avl_add(avl, box(501), box(631)); + avl = remove_int(avl, 723); + avl = remove_int(avl, 852); + avl = remove_int(avl, 1021); + avl = remove_int(avl, 670); + avl = remove_int(avl, 500); + avl = gpr_avl_add(avl, box(330), box(637)); + avl = remove_int(avl, 264); + avl = gpr_avl_add(avl, box(69), box(639)); + avl = remove_int(avl, 73); + avl = gpr_avl_add(avl, box(745), box(641)); + avl = remove_int(avl, 518); + avl = remove_int(avl, 641); + avl = remove_int(avl, 768); + avl = gpr_avl_add(avl, box(988), box(645)); + avl = gpr_avl_add(avl, box(899), box(646)); + avl = remove_int(avl, 763); + avl = remove_int(avl, 281); + avl = remove_int(avl, 496); + avl = gpr_avl_add(avl, box(445), box(650)); + avl = remove_int(avl, 905); + avl = gpr_avl_add(avl, box(275), box(652)); + avl = gpr_avl_add(avl, box(137), box(653)); + avl = remove_int(avl, 642); + avl = gpr_avl_add(avl, box(708), box(655)); + avl = remove_int(avl, 922); + avl = gpr_avl_add(avl, box(743), box(657)); + avl = remove_int(avl, 295); + avl = remove_int(avl, 665); + avl = remove_int(avl, 48); + avl = gpr_avl_add(avl, box(1012), box(661)); + avl = remove_int(avl, 71); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(319), box(664)); + avl = remove_int(avl, 632); + avl = gpr_avl_add(avl, box(137), box(666)); + avl = gpr_avl_add(avl, box(686), box(667)); + avl = gpr_avl_add(avl, box(724), box(668)); + avl = gpr_avl_add(avl, box(952), box(669)); + avl = gpr_avl_add(avl, box(5), box(670)); + avl = remove_int(avl, 35); + avl = gpr_avl_add(avl, box(43), box(672)); + avl = gpr_avl_add(avl, box(320), box(673)); + avl = gpr_avl_add(avl, box(115), box(674)); + avl = remove_int(avl, 377); + avl = remove_int(avl, 591); + avl = remove_int(avl, 87); + avl = remove_int(avl, 93); + avl = gpr_avl_add(avl, box(1016), box(679)); + avl = gpr_avl_add(avl, box(605), box(680)); + avl = gpr_avl_add(avl, box(152), box(681)); + avl = gpr_avl_add(avl, box(113), box(682)); + avl = remove_int(avl, 131); + avl = remove_int(avl, 637); + avl = gpr_avl_add(avl, box(156), box(685)); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(546), box(687)); + avl = remove_int(avl, 970); + avl = remove_int(avl, 53); + avl = remove_int(avl, 827); + avl = remove_int(avl, 224); + avl = remove_int(avl, 796); + avl = remove_int(avl, 34); + avl = remove_int(avl, 922); + avl = remove_int(avl, 277); + avl = remove_int(avl, 650); + avl = remove_int(avl, 222); + avl = remove_int(avl, 244); + avl = remove_int(avl, 576); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(500), box(701)); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(825), box(703)); + avl = remove_int(avl, 888); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(285), box(706)); + avl = remove_int(avl, 62); + avl = remove_int(avl, 444); + avl = remove_int(avl, 946); + avl = gpr_avl_add(avl, box(122), box(710)); + avl = gpr_avl_add(avl, box(846), box(711)); + avl = remove_int(avl, 628); + avl = gpr_avl_add(avl, box(511), box(713)); + avl = gpr_avl_add(avl, box(398), box(714)); + avl = remove_int(avl, 730); + avl = gpr_avl_add(avl, box(797), box(716)); + avl = remove_int(avl, 897); + avl = remove_int(avl, 228); + avl = remove_int(avl, 544); + avl = remove_int(avl, 552); + avl = remove_int(avl, 783); + avl = remove_int(avl, 583); + avl = remove_int(avl, 894); + avl = remove_int(avl, 942); + avl = gpr_avl_add(avl, box(346), box(725)); + avl = gpr_avl_add(avl, box(1015), box(726)); + avl = remove_int(avl, 813); + avl = gpr_avl_add(avl, box(213), box(728)); + avl = remove_int(avl, 468); + avl = remove_int(avl, 365); + avl = remove_int(avl, 399); + avl = gpr_avl_add(avl, box(380), box(732)); + avl = remove_int(avl, 835); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(700), box(735)); + avl = gpr_avl_add(avl, box(807), box(736)); + avl = remove_int(avl, 312); + avl = remove_int(avl, 282); + avl = remove_int(avl, 370); + avl = remove_int(avl, 999); + avl = remove_int(avl, 241); + avl = remove_int(avl, 884); + avl = gpr_avl_add(avl, box(587), box(743)); + avl = gpr_avl_add(avl, box(332), box(744)); + avl = remove_int(avl, 686); + avl = remove_int(avl, 206); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(334), box(748)); + avl = remove_int(avl, 171); + avl = gpr_avl_add(avl, box(1002), box(750)); + avl = gpr_avl_add(avl, box(779), box(751)); + avl = gpr_avl_add(avl, box(307), box(752)); + avl = gpr_avl_add(avl, box(127), box(753)); + avl = gpr_avl_add(avl, box(251), box(754)); + avl = remove_int(avl, 790); + avl = remove_int(avl, 189); + avl = remove_int(avl, 193); + avl = remove_int(avl, 38); + avl = remove_int(avl, 124); + avl = gpr_avl_add(avl, box(812), box(760)); + avl = remove_int(avl, 43); + avl = gpr_avl_add(avl, box(871), box(762)); + avl = gpr_avl_add(avl, box(580), box(763)); + avl = remove_int(avl, 501); + avl = remove_int(avl, 462); + avl = remove_int(avl, 599); + avl = gpr_avl_add(avl, box(240), box(767)); + avl = gpr_avl_add(avl, box(285), box(768)); + avl = gpr_avl_add(avl, box(472), box(769)); + avl = remove_int(avl, 865); + avl = remove_int(avl, 763); + avl = remove_int(avl, 245); + avl = remove_int(avl, 80); + avl = remove_int(avl, 713); + avl = remove_int(avl, 654); + avl = remove_int(avl, 1014); + avl = gpr_avl_add(avl, box(495), box(777)); + avl = gpr_avl_add(avl, box(552), box(778)); + avl = remove_int(avl, 19); + avl = remove_int(avl, 803); + avl = gpr_avl_add(avl, box(508), box(781)); + avl = remove_int(avl, 699); + avl = remove_int(avl, 260); + avl = remove_int(avl, 92); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(970), box(786)); + avl = remove_int(avl, 987); + avl = remove_int(avl, 168); + avl = remove_int(avl, 476); + avl = remove_int(avl, 248); + avl = gpr_avl_add(avl, box(358), box(791)); + avl = remove_int(avl, 804); + avl = remove_int(avl, 77); + avl = remove_int(avl, 905); + avl = remove_int(avl, 362); + avl = gpr_avl_add(avl, box(578), box(796)); + avl = remove_int(avl, 38); + avl = remove_int(avl, 595); + avl = gpr_avl_add(avl, box(213), box(799)); + avl = remove_int(avl, 7); + avl = remove_int(avl, 620); + avl = gpr_avl_add(avl, box(946), box(802)); + avl = remove_int(avl, 145); + avl = gpr_avl_add(avl, box(628), box(804)); + avl = remove_int(avl, 972); + avl = gpr_avl_add(avl, box(728), box(806)); + avl = remove_int(avl, 91); + avl = gpr_avl_add(avl, box(136), box(808)); + avl = gpr_avl_add(avl, box(841), box(809)); + avl = gpr_avl_add(avl, box(265), box(810)); + avl = gpr_avl_add(avl, box(701), box(811)); + avl = gpr_avl_add(avl, box(27), box(812)); + avl = remove_int(avl, 72); + avl = remove_int(avl, 14); + avl = gpr_avl_add(avl, box(286), box(815)); + avl = remove_int(avl, 996); + avl = remove_int(avl, 998); + avl = gpr_avl_add(avl, box(466), box(818)); + avl = remove_int(avl, 1009); + avl = remove_int(avl, 741); + avl = remove_int(avl, 947); + avl = remove_int(avl, 241); + avl = remove_int(avl, 954); + avl = remove_int(avl, 183); + avl = remove_int(avl, 395); + avl = remove_int(avl, 951); + avl = gpr_avl_add(avl, box(267), box(827)); + avl = remove_int(avl, 812); + avl = gpr_avl_add(avl, box(577), box(829)); + avl = remove_int(avl, 624); + avl = remove_int(avl, 847); + avl = remove_int(avl, 745); + avl = gpr_avl_add(avl, box(491), box(833)); + avl = gpr_avl_add(avl, box(941), box(834)); + avl = remove_int(avl, 258); + avl = gpr_avl_add(avl, box(410), box(836)); + avl = gpr_avl_add(avl, box(80), box(837)); + avl = gpr_avl_add(avl, box(196), box(838)); + avl = gpr_avl_add(avl, box(5), box(839)); + avl = remove_int(avl, 782); + avl = gpr_avl_add(avl, box(827), box(841)); + avl = remove_int(avl, 472); + avl = remove_int(avl, 664); + avl = gpr_avl_add(avl, box(409), box(844)); + avl = gpr_avl_add(avl, box(62), box(845)); + avl = remove_int(avl, 56); + avl = remove_int(avl, 606); + avl = remove_int(avl, 707); + avl = remove_int(avl, 989); + avl = remove_int(avl, 549); + avl = remove_int(avl, 259); + avl = gpr_avl_add(avl, box(405), box(852)); + avl = remove_int(avl, 587); + avl = remove_int(avl, 350); + avl = gpr_avl_add(avl, box(980), box(855)); + avl = gpr_avl_add(avl, box(992), box(856)); + avl = gpr_avl_add(avl, box(818), box(857)); + avl = remove_int(avl, 853); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(675), box(860)); + avl = remove_int(avl, 248); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(508), box(863)); + avl = remove_int(avl, 927); + avl = gpr_avl_add(avl, box(957), box(865)); + avl = gpr_avl_add(avl, box(698), box(866)); + avl = gpr_avl_add(avl, box(388), box(867)); + avl = gpr_avl_add(avl, box(532), box(868)); + avl = gpr_avl_add(avl, box(681), box(869)); + avl = remove_int(avl, 544); + avl = remove_int(avl, 991); + avl = remove_int(avl, 397); + avl = gpr_avl_add(avl, box(954), box(873)); + avl = gpr_avl_add(avl, box(219), box(874)); + avl = gpr_avl_add(avl, box(465), box(875)); + avl = remove_int(avl, 371); + avl = gpr_avl_add(avl, box(601), box(877)); + avl = gpr_avl_add(avl, box(543), box(878)); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(560), box(880)); + avl = remove_int(avl, 898); + avl = gpr_avl_add(avl, box(455), box(882)); + avl = remove_int(avl, 313); + avl = gpr_avl_add(avl, box(215), box(884)); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(608), box(886)); + avl = remove_int(avl, 248); + avl = gpr_avl_add(avl, box(575), box(888)); + avl = remove_int(avl, 207); + avl = remove_int(avl, 810); + avl = remove_int(avl, 665); + avl = remove_int(avl, 361); + avl = gpr_avl_add(avl, box(154), box(893)); + avl = gpr_avl_add(avl, box(329), box(894)); + avl = gpr_avl_add(avl, box(326), box(895)); + avl = remove_int(avl, 746); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(464), box(898)); + avl = gpr_avl_add(avl, box(141), box(899)); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(414), box(901)); + avl = gpr_avl_add(avl, box(777), box(902)); + avl = remove_int(avl, 972); + avl = remove_int(avl, 841); + avl = remove_int(avl, 100); + avl = gpr_avl_add(avl, box(828), box(906)); + avl = remove_int(avl, 785); + avl = gpr_avl_add(avl, box(1008), box(908)); + avl = gpr_avl_add(avl, box(46), box(909)); + avl = remove_int(avl, 399); + avl = gpr_avl_add(avl, box(178), box(911)); + avl = gpr_avl_add(avl, box(573), box(912)); + avl = remove_int(avl, 299); + avl = gpr_avl_add(avl, box(690), box(914)); + avl = gpr_avl_add(avl, box(692), box(915)); + avl = remove_int(avl, 404); + avl = remove_int(avl, 16); + avl = remove_int(avl, 746); + avl = remove_int(avl, 486); + avl = remove_int(avl, 119); + avl = gpr_avl_add(avl, box(167), box(921)); + avl = remove_int(avl, 328); + avl = gpr_avl_add(avl, box(89), box(923)); + avl = remove_int(avl, 867); + avl = remove_int(avl, 626); + avl = remove_int(avl, 507); + avl = gpr_avl_add(avl, box(365), box(927)); + avl = gpr_avl_add(avl, box(58), box(928)); + avl = gpr_avl_add(avl, box(70), box(929)); + avl = remove_int(avl, 81); + avl = remove_int(avl, 797); + avl = gpr_avl_add(avl, box(846), box(932)); + avl = remove_int(avl, 642); + avl = gpr_avl_add(avl, box(777), box(934)); + avl = remove_int(avl, 107); + avl = gpr_avl_add(avl, box(691), box(936)); + avl = gpr_avl_add(avl, box(820), box(937)); + avl = gpr_avl_add(avl, box(202), box(938)); + avl = gpr_avl_add(avl, box(308), box(939)); + avl = gpr_avl_add(avl, box(20), box(940)); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(714), box(942)); + avl = gpr_avl_add(avl, box(584), box(943)); + avl = remove_int(avl, 294); + avl = gpr_avl_add(avl, box(496), box(945)); + avl = gpr_avl_add(avl, box(394), box(946)); + avl = gpr_avl_add(avl, box(860), box(947)); + avl = gpr_avl_add(avl, box(58), box(948)); + avl = remove_int(avl, 784); + avl = remove_int(avl, 584); + avl = remove_int(avl, 708); + avl = gpr_avl_add(avl, box(142), box(952)); + avl = gpr_avl_add(avl, box(247), box(953)); + avl = gpr_avl_add(avl, box(389), box(954)); + avl = remove_int(avl, 390); + avl = gpr_avl_add(avl, box(465), box(956)); + avl = gpr_avl_add(avl, box(936), box(957)); + avl = gpr_avl_add(avl, box(309), box(958)); + avl = remove_int(avl, 928); + avl = remove_int(avl, 128); + avl = remove_int(avl, 979); + avl = remove_int(avl, 670); + avl = remove_int(avl, 738); + avl = remove_int(avl, 271); + avl = remove_int(avl, 540); + avl = gpr_avl_add(avl, box(365), box(966)); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(728), box(968)); + avl = remove_int(avl, 852); + avl = gpr_avl_add(avl, box(884), box(970)); + avl = gpr_avl_add(avl, box(502), box(971)); + avl = remove_int(avl, 898); + avl = remove_int(avl, 481); + avl = gpr_avl_add(avl, box(911), box(974)); + avl = remove_int(avl, 787); + avl = remove_int(avl, 785); + avl = remove_int(avl, 537); + avl = remove_int(avl, 535); + avl = remove_int(avl, 136); + avl = remove_int(avl, 749); + avl = remove_int(avl, 637); + avl = remove_int(avl, 900); + avl = gpr_avl_add(avl, box(598), box(983)); + avl = remove_int(avl, 25); + avl = remove_int(avl, 697); + avl = gpr_avl_add(avl, box(645), box(986)); + avl = gpr_avl_add(avl, box(211), box(987)); + avl = gpr_avl_add(avl, box(589), box(988)); + avl = remove_int(avl, 702); + avl = gpr_avl_add(avl, box(53), box(990)); + avl = remove_int(avl, 492); + avl = remove_int(avl, 185); + avl = remove_int(avl, 246); + avl = remove_int(avl, 257); + avl = remove_int(avl, 502); + avl = remove_int(avl, 34); + avl = gpr_avl_add(avl, box(74), box(997)); + avl = gpr_avl_add(avl, box(834), box(998)); + avl = gpr_avl_add(avl, box(514), box(999)); + avl = gpr_avl_add(avl, box(75), box(1000)); + avl = remove_int(avl, 745); + avl = gpr_avl_add(avl, box(362), box(1002)); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(624), box(1004)); + avl = remove_int(avl, 404); + avl = remove_int(avl, 359); + avl = remove_int(avl, 491); + avl = gpr_avl_add(avl, box(903), box(1008)); + avl = gpr_avl_add(avl, box(240), box(1009)); + avl = remove_int(avl, 95); + avl = gpr_avl_add(avl, box(119), box(1011)); + avl = gpr_avl_add(avl, box(857), box(1012)); + avl = remove_int(avl, 39); + avl = remove_int(avl, 866); + avl = gpr_avl_add(avl, box(503), box(1015)); + avl = gpr_avl_add(avl, box(740), box(1016)); + avl = remove_int(avl, 637); + avl = remove_int(avl, 156); + avl = remove_int(avl, 6); + avl = remove_int(avl, 745); + avl = remove_int(avl, 433); + avl = remove_int(avl, 283); + avl = gpr_avl_add(avl, box(625), box(1023)); + avl = remove_int(avl, 638); + avl = gpr_avl_add(avl, box(299), box(1025)); + avl = gpr_avl_add(avl, box(584), box(1026)); + avl = remove_int(avl, 863); + avl = gpr_avl_add(avl, box(612), box(1028)); + avl = gpr_avl_add(avl, box(62), box(1029)); + avl = gpr_avl_add(avl, box(432), box(1030)); + avl = remove_int(avl, 371); + avl = remove_int(avl, 790); + avl = remove_int(avl, 227); + avl = remove_int(avl, 836); + avl = gpr_avl_add(avl, box(703), box(1035)); + avl = gpr_avl_add(avl, box(644), box(1036)); + avl = remove_int(avl, 638); + avl = gpr_avl_add(avl, box(13), box(1038)); + avl = remove_int(avl, 66); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(362), box(1041)); + avl = gpr_avl_add(avl, box(783), box(1042)); + avl = remove_int(avl, 60); + avl = gpr_avl_add(avl, box(80), box(1044)); + avl = gpr_avl_add(avl, box(825), box(1045)); + avl = gpr_avl_add(avl, box(688), box(1046)); + avl = gpr_avl_add(avl, box(662), box(1047)); + avl = remove_int(avl, 156); + avl = remove_int(avl, 376); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(526), box(1051)); + avl = gpr_avl_add(avl, box(168), box(1052)); + avl = remove_int(avl, 646); + avl = remove_int(avl, 380); + avl = remove_int(avl, 833); + avl = gpr_avl_add(avl, box(53), box(1056)); + avl = remove_int(avl, 105); + avl = gpr_avl_add(avl, box(373), box(1058)); + avl = gpr_avl_add(avl, box(184), box(1059)); + avl = remove_int(avl, 288); + avl = gpr_avl_add(avl, box(966), box(1061)); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(406), box(1063)); + avl = remove_int(avl, 470); + avl = gpr_avl_add(avl, box(283), box(1065)); + avl = gpr_avl_add(avl, box(838), box(1066)); + avl = gpr_avl_add(avl, box(288), box(1067)); + avl = gpr_avl_add(avl, box(950), box(1068)); + avl = gpr_avl_add(avl, box(163), box(1069)); + avl = remove_int(avl, 623); + avl = remove_int(avl, 769); + avl = gpr_avl_add(avl, box(144), box(1072)); + avl = gpr_avl_add(avl, box(489), box(1073)); + avl = remove_int(avl, 15); + avl = gpr_avl_add(avl, box(971), box(1075)); + avl = remove_int(avl, 660); + avl = gpr_avl_add(avl, box(255), box(1077)); + avl = remove_int(avl, 494); + avl = gpr_avl_add(avl, box(109), box(1079)); + avl = gpr_avl_add(avl, box(420), box(1080)); + avl = gpr_avl_add(avl, box(509), box(1081)); + avl = remove_int(avl, 178); + avl = gpr_avl_add(avl, box(216), box(1083)); + avl = gpr_avl_add(avl, box(707), box(1084)); + avl = gpr_avl_add(avl, box(411), box(1085)); + avl = gpr_avl_add(avl, box(352), box(1086)); + avl = remove_int(avl, 983); + avl = gpr_avl_add(avl, box(6), box(1088)); + avl = gpr_avl_add(avl, box(1014), box(1089)); + avl = remove_int(avl, 98); + avl = remove_int(avl, 325); + avl = gpr_avl_add(avl, box(851), box(1092)); + avl = remove_int(avl, 553); + avl = gpr_avl_add(avl, box(218), box(1094)); + avl = gpr_avl_add(avl, box(261), box(1095)); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(872), box(1097)); + avl = remove_int(avl, 543); + avl = remove_int(avl, 314); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(533), box(1101)); + avl = remove_int(avl, 881); + avl = remove_int(avl, 269); + avl = remove_int(avl, 940); + avl = remove_int(avl, 909); + avl = remove_int(avl, 197); + avl = remove_int(avl, 773); + avl = remove_int(avl, 790); + avl = remove_int(avl, 345); + avl = gpr_avl_add(avl, box(965), box(1110)); + avl = remove_int(avl, 622); + avl = gpr_avl_add(avl, box(352), box(1112)); + avl = remove_int(avl, 182); + avl = gpr_avl_add(avl, box(534), box(1114)); + avl = gpr_avl_add(avl, box(97), box(1115)); + avl = gpr_avl_add(avl, box(198), box(1116)); + avl = remove_int(avl, 750); + avl = gpr_avl_add(avl, box(98), box(1118)); + avl = remove_int(avl, 943); + avl = gpr_avl_add(avl, box(254), box(1120)); + avl = gpr_avl_add(avl, box(30), box(1121)); + avl = remove_int(avl, 14); + avl = remove_int(avl, 475); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(789), box(1125)); + avl = gpr_avl_add(avl, box(402), box(1126)); + avl = remove_int(avl, 1019); + avl = gpr_avl_add(avl, box(858), box(1128)); + avl = gpr_avl_add(avl, box(625), box(1129)); + avl = remove_int(avl, 675); + avl = remove_int(avl, 323); + avl = gpr_avl_add(avl, box(329), box(1132)); + avl = remove_int(avl, 929); + avl = remove_int(avl, 44); + avl = gpr_avl_add(avl, box(443), box(1135)); + avl = gpr_avl_add(avl, box(653), box(1136)); + avl = gpr_avl_add(avl, box(750), box(1137)); + avl = gpr_avl_add(avl, box(252), box(1138)); + avl = gpr_avl_add(avl, box(449), box(1139)); + avl = remove_int(avl, 1022); + avl = remove_int(avl, 357); + avl = remove_int(avl, 602); + avl = remove_int(avl, 131); + avl = gpr_avl_add(avl, box(531), box(1144)); + avl = remove_int(avl, 806); + avl = gpr_avl_add(avl, box(455), box(1146)); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(154), box(1148)); + avl = gpr_avl_add(avl, box(189), box(1149)); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(496), box(1151)); + avl = gpr_avl_add(avl, box(81), box(1152)); + avl = gpr_avl_add(avl, box(59), box(1153)); + avl = remove_int(avl, 424); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(723), box(1156)); + avl = gpr_avl_add(avl, box(822), box(1157)); + avl = gpr_avl_add(avl, box(354), box(1158)); + avl = remove_int(avl, 738); + avl = gpr_avl_add(avl, box(686), box(1160)); + avl = gpr_avl_add(avl, box(43), box(1161)); + avl = gpr_avl_add(avl, box(625), box(1162)); + avl = gpr_avl_add(avl, box(902), box(1163)); + avl = gpr_avl_add(avl, box(12), box(1164)); + avl = gpr_avl_add(avl, box(977), box(1165)); + avl = gpr_avl_add(avl, box(699), box(1166)); + avl = gpr_avl_add(avl, box(189), box(1167)); + avl = remove_int(avl, 672); + avl = remove_int(avl, 90); + avl = remove_int(avl, 757); + avl = remove_int(avl, 494); + avl = gpr_avl_add(avl, box(759), box(1172)); + avl = remove_int(avl, 758); + avl = remove_int(avl, 222); + avl = gpr_avl_add(avl, box(975), box(1175)); + avl = remove_int(avl, 993); + avl = gpr_avl_add(avl, box(2), box(1177)); + avl = gpr_avl_add(avl, box(70), box(1178)); + avl = remove_int(avl, 350); + avl = remove_int(avl, 972); + avl = remove_int(avl, 880); + avl = gpr_avl_add(avl, box(753), box(1182)); + avl = remove_int(avl, 404); + avl = gpr_avl_add(avl, box(294), box(1184)); + avl = remove_int(avl, 474); + avl = gpr_avl_add(avl, box(228), box(1186)); + avl = gpr_avl_add(avl, box(484), box(1187)); + avl = remove_int(avl, 238); + avl = remove_int(avl, 53); + avl = remove_int(avl, 691); + avl = gpr_avl_add(avl, box(345), box(1191)); + avl = remove_int(avl, 0); + avl = gpr_avl_add(avl, box(230), box(1193)); + avl = remove_int(avl, 227); + avl = remove_int(avl, 152); + avl = gpr_avl_add(avl, box(884), box(1196)); + avl = remove_int(avl, 823); + avl = remove_int(avl, 53); + avl = gpr_avl_add(avl, box(1015), box(1199)); + avl = gpr_avl_add(avl, box(697), box(1200)); + avl = gpr_avl_add(avl, box(376), box(1201)); + avl = remove_int(avl, 411); + avl = gpr_avl_add(avl, box(888), box(1203)); + avl = remove_int(avl, 55); + avl = gpr_avl_add(avl, box(85), box(1205)); + avl = remove_int(avl, 947); + avl = remove_int(avl, 382); + avl = remove_int(avl, 777); + avl = gpr_avl_add(avl, box(1017), box(1209)); + avl = gpr_avl_add(avl, box(169), box(1210)); + avl = gpr_avl_add(avl, box(156), box(1211)); + avl = remove_int(avl, 153); + avl = remove_int(avl, 642); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(554), box(1215)); + avl = gpr_avl_add(avl, box(76), box(1216)); + avl = gpr_avl_add(avl, box(756), box(1217)); + avl = remove_int(avl, 767); + avl = remove_int(avl, 112); + avl = remove_int(avl, 539); + avl = remove_int(avl, 544); + avl = remove_int(avl, 628); + avl = remove_int(avl, 385); + avl = remove_int(avl, 514); + avl = remove_int(avl, 362); + avl = gpr_avl_add(avl, box(523), box(1226)); + avl = gpr_avl_add(avl, box(712), box(1227)); + avl = gpr_avl_add(avl, box(474), box(1228)); + avl = gpr_avl_add(avl, box(882), box(1229)); + avl = gpr_avl_add(avl, box(965), box(1230)); + avl = remove_int(avl, 464); + avl = gpr_avl_add(avl, box(319), box(1232)); + avl = gpr_avl_add(avl, box(504), box(1233)); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(884), box(1235)); + avl = gpr_avl_add(avl, box(813), box(1236)); + avl = gpr_avl_add(avl, box(795), box(1237)); + avl = remove_int(avl, 306); + avl = gpr_avl_add(avl, box(799), box(1239)); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(480), box(1241)); + avl = gpr_avl_add(avl, box(656), box(1242)); + avl = gpr_avl_add(avl, box(709), box(1243)); + avl = gpr_avl_add(avl, box(500), box(1244)); + avl = remove_int(avl, 740); + avl = gpr_avl_add(avl, box(980), box(1246)); + avl = gpr_avl_add(avl, box(458), box(1247)); + avl = remove_int(avl, 377); + avl = remove_int(avl, 338); + avl = gpr_avl_add(avl, box(554), box(1250)); + avl = gpr_avl_add(avl, box(504), box(1251)); + avl = gpr_avl_add(avl, box(603), box(1252)); + avl = gpr_avl_add(avl, box(761), box(1253)); + avl = remove_int(avl, 431); + avl = gpr_avl_add(avl, box(707), box(1255)); + avl = gpr_avl_add(avl, box(673), box(1256)); + avl = remove_int(avl, 998); + avl = remove_int(avl, 332); + avl = remove_int(avl, 413); + avl = remove_int(avl, 227); + avl = remove_int(avl, 249); + avl = remove_int(avl, 309); + avl = remove_int(avl, 459); + avl = gpr_avl_add(avl, box(645), box(1264)); + avl = remove_int(avl, 858); + avl = remove_int(avl, 997); + avl = gpr_avl_add(avl, box(519), box(1267)); + avl = remove_int(avl, 614); + avl = remove_int(avl, 462); + avl = remove_int(avl, 792); + avl = gpr_avl_add(avl, box(987), box(1271)); + avl = gpr_avl_add(avl, box(309), box(1272)); + avl = remove_int(avl, 747); + avl = gpr_avl_add(avl, box(621), box(1274)); + avl = gpr_avl_add(avl, box(450), box(1275)); + avl = remove_int(avl, 265); + avl = remove_int(avl, 8); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(238), box(1279)); + avl = remove_int(avl, 241); + avl = gpr_avl_add(avl, box(180), box(1281)); + avl = gpr_avl_add(avl, box(411), box(1282)); + avl = gpr_avl_add(avl, box(791), box(1283)); + avl = gpr_avl_add(avl, box(955), box(1284)); + avl = remove_int(avl, 24); + avl = remove_int(avl, 375); + avl = gpr_avl_add(avl, box(140), box(1287)); + avl = remove_int(avl, 949); + avl = gpr_avl_add(avl, box(301), box(1289)); + avl = gpr_avl_add(avl, box(0), box(1290)); + avl = remove_int(avl, 371); + avl = remove_int(avl, 427); + avl = remove_int(avl, 841); + avl = remove_int(avl, 847); + avl = gpr_avl_add(avl, box(814), box(1295)); + avl = gpr_avl_add(avl, box(127), box(1296)); + avl = gpr_avl_add(avl, box(279), box(1297)); + avl = remove_int(avl, 669); + avl = remove_int(avl, 541); + avl = remove_int(avl, 275); + avl = remove_int(avl, 299); + avl = remove_int(avl, 552); + avl = gpr_avl_add(avl, box(310), box(1303)); + avl = gpr_avl_add(avl, box(304), box(1304)); + avl = gpr_avl_add(avl, box(1), box(1305)); + avl = gpr_avl_add(avl, box(339), box(1306)); + avl = remove_int(avl, 570); + avl = remove_int(avl, 752); + avl = remove_int(avl, 552); + avl = remove_int(avl, 442); + avl = remove_int(avl, 639); + avl = gpr_avl_add(avl, box(313), box(1312)); + avl = remove_int(avl, 85); + avl = gpr_avl_add(avl, box(964), box(1314)); + avl = gpr_avl_add(avl, box(559), box(1315)); + avl = remove_int(avl, 167); + avl = gpr_avl_add(avl, box(866), box(1317)); + avl = remove_int(avl, 275); + avl = gpr_avl_add(avl, box(173), box(1319)); + avl = gpr_avl_add(avl, box(765), box(1320)); + avl = remove_int(avl, 883); + avl = gpr_avl_add(avl, box(547), box(1322)); + avl = gpr_avl_add(avl, box(847), box(1323)); + avl = remove_int(avl, 817); + avl = remove_int(avl, 850); + avl = remove_int(avl, 718); + avl = gpr_avl_add(avl, box(806), box(1327)); + avl = gpr_avl_add(avl, box(360), box(1328)); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(493), box(1330)); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(361), box(1332)); + avl = remove_int(avl, 355); + avl = gpr_avl_add(avl, box(512), box(1334)); + avl = gpr_avl_add(avl, box(191), box(1335)); + avl = remove_int(avl, 703); + avl = gpr_avl_add(avl, box(333), box(1337)); + avl = remove_int(avl, 481); + avl = gpr_avl_add(avl, box(501), box(1339)); + avl = remove_int(avl, 532); + avl = remove_int(avl, 510); + avl = gpr_avl_add(avl, box(793), box(1342)); + avl = gpr_avl_add(avl, box(234), box(1343)); + avl = remove_int(avl, 159); + avl = remove_int(avl, 429); + avl = remove_int(avl, 728); + avl = remove_int(avl, 288); + avl = gpr_avl_add(avl, box(281), box(1348)); + avl = gpr_avl_add(avl, box(702), box(1349)); + avl = gpr_avl_add(avl, box(149), box(1350)); + avl = remove_int(avl, 22); + avl = remove_int(avl, 944); + avl = remove_int(avl, 55); + avl = remove_int(avl, 512); + avl = remove_int(avl, 676); + avl = remove_int(avl, 884); + avl = gpr_avl_add(avl, box(246), box(1357)); + avl = gpr_avl_add(avl, box(455), box(1358)); + avl = remove_int(avl, 782); + avl = remove_int(avl, 682); + avl = gpr_avl_add(avl, box(243), box(1361)); + avl = gpr_avl_add(avl, box(109), box(1362)); + avl = gpr_avl_add(avl, box(452), box(1363)); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(159), box(1365)); + avl = remove_int(avl, 1023); + avl = gpr_avl_add(avl, box(129), box(1367)); + avl = gpr_avl_add(avl, box(537), box(1368)); + avl = remove_int(avl, 321); + avl = gpr_avl_add(avl, box(740), box(1370)); + avl = remove_int(avl, 45); + avl = remove_int(avl, 136); + avl = gpr_avl_add(avl, box(229), box(1373)); + avl = remove_int(avl, 772); + avl = gpr_avl_add(avl, box(181), box(1375)); + avl = remove_int(avl, 175); + avl = gpr_avl_add(avl, box(817), box(1377)); + avl = remove_int(avl, 956); + avl = gpr_avl_add(avl, box(675), box(1379)); + avl = gpr_avl_add(avl, box(375), box(1380)); + avl = remove_int(avl, 384); + avl = gpr_avl_add(avl, box(1016), box(1382)); + avl = remove_int(avl, 295); + avl = remove_int(avl, 697); + avl = remove_int(avl, 554); + avl = remove_int(avl, 590); + avl = remove_int(avl, 1014); + avl = gpr_avl_add(avl, box(890), box(1388)); + avl = gpr_avl_add(avl, box(293), box(1389)); + avl = remove_int(avl, 207); + avl = remove_int(avl, 46); + avl = gpr_avl_add(avl, box(899), box(1392)); + avl = gpr_avl_add(avl, box(666), box(1393)); + avl = gpr_avl_add(avl, box(85), box(1394)); + avl = gpr_avl_add(avl, box(914), box(1395)); + avl = gpr_avl_add(avl, box(128), box(1396)); + avl = gpr_avl_add(avl, box(835), box(1397)); + avl = gpr_avl_add(avl, box(787), box(1398)); + avl = gpr_avl_add(avl, box(649), box(1399)); + avl = gpr_avl_add(avl, box(723), box(1400)); + avl = remove_int(avl, 874); + avl = gpr_avl_add(avl, box(778), box(1402)); + avl = gpr_avl_add(avl, box(1015), box(1403)); + avl = gpr_avl_add(avl, box(59), box(1404)); + avl = gpr_avl_add(avl, box(259), box(1405)); + avl = gpr_avl_add(avl, box(758), box(1406)); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(145), box(1408)); + avl = gpr_avl_add(avl, box(440), box(1409)); + avl = remove_int(avl, 608); + avl = remove_int(avl, 690); + avl = gpr_avl_add(avl, box(605), box(1412)); + avl = remove_int(avl, 856); + avl = remove_int(avl, 608); + avl = gpr_avl_add(avl, box(829), box(1415)); + avl = gpr_avl_add(avl, box(660), box(1416)); + avl = remove_int(avl, 596); + avl = gpr_avl_add(avl, box(519), box(1418)); + avl = gpr_avl_add(avl, box(35), box(1419)); + avl = gpr_avl_add(avl, box(871), box(1420)); + avl = remove_int(avl, 845); + avl = gpr_avl_add(avl, box(600), box(1422)); + avl = gpr_avl_add(avl, box(215), box(1423)); + avl = remove_int(avl, 761); + avl = gpr_avl_add(avl, box(975), box(1425)); + avl = remove_int(avl, 987); + avl = gpr_avl_add(avl, box(58), box(1427)); + avl = remove_int(avl, 119); + avl = gpr_avl_add(avl, box(937), box(1429)); + avl = gpr_avl_add(avl, box(372), box(1430)); + avl = gpr_avl_add(avl, box(11), box(1431)); + avl = gpr_avl_add(avl, box(398), box(1432)); + avl = gpr_avl_add(avl, box(423), box(1433)); + avl = remove_int(avl, 171); + avl = gpr_avl_add(avl, box(473), box(1435)); + avl = remove_int(avl, 752); + avl = remove_int(avl, 625); + avl = remove_int(avl, 764); + avl = remove_int(avl, 49); + avl = gpr_avl_add(avl, box(472), box(1440)); + avl = remove_int(avl, 847); + avl = remove_int(avl, 642); + avl = remove_int(avl, 1004); + avl = remove_int(avl, 795); + avl = remove_int(avl, 465); + avl = gpr_avl_add(avl, box(636), box(1446)); + avl = remove_int(avl, 152); + avl = gpr_avl_add(avl, box(61), box(1448)); + avl = remove_int(avl, 929); + avl = remove_int(avl, 9); + avl = gpr_avl_add(avl, box(251), box(1451)); + avl = gpr_avl_add(avl, box(672), box(1452)); + avl = gpr_avl_add(avl, box(66), box(1453)); + avl = remove_int(avl, 693); + avl = remove_int(avl, 914); + avl = remove_int(avl, 116); + avl = remove_int(avl, 577); + avl = gpr_avl_add(avl, box(618), box(1458)); + avl = gpr_avl_add(avl, box(495), box(1459)); + avl = remove_int(avl, 450); + avl = gpr_avl_add(avl, box(533), box(1461)); + avl = gpr_avl_add(avl, box(414), box(1462)); + avl = remove_int(avl, 74); + avl = remove_int(avl, 236); + avl = gpr_avl_add(avl, box(707), box(1465)); + avl = gpr_avl_add(avl, box(357), box(1466)); + avl = gpr_avl_add(avl, box(1007), box(1467)); + avl = gpr_avl_add(avl, box(811), box(1468)); + avl = gpr_avl_add(avl, box(418), box(1469)); + avl = gpr_avl_add(avl, box(164), box(1470)); + avl = gpr_avl_add(avl, box(622), box(1471)); + avl = remove_int(avl, 22); + avl = remove_int(avl, 14); + avl = remove_int(avl, 732); + avl = remove_int(avl, 7); + avl = remove_int(avl, 447); + avl = gpr_avl_add(avl, box(221), box(1477)); + avl = gpr_avl_add(avl, box(202), box(1478)); + avl = gpr_avl_add(avl, box(312), box(1479)); + avl = remove_int(avl, 274); + avl = gpr_avl_add(avl, box(684), box(1481)); + avl = gpr_avl_add(avl, box(954), box(1482)); + avl = gpr_avl_add(avl, box(637), box(1483)); + avl = remove_int(avl, 716); + avl = gpr_avl_add(avl, box(198), box(1485)); + avl = remove_int(avl, 340); + avl = remove_int(avl, 137); + avl = remove_int(avl, 995); + avl = remove_int(avl, 1004); + avl = gpr_avl_add(avl, box(661), box(1490)); + avl = gpr_avl_add(avl, box(862), box(1491)); + avl = remove_int(avl, 527); + avl = gpr_avl_add(avl, box(945), box(1493)); + avl = remove_int(avl, 355); + avl = remove_int(avl, 144); + avl = gpr_avl_add(avl, box(229), box(1496)); + avl = gpr_avl_add(avl, box(237), box(1497)); + avl = remove_int(avl, 471); + avl = remove_int(avl, 901); + avl = gpr_avl_add(avl, box(905), box(1500)); + avl = remove_int(avl, 19); + avl = remove_int(avl, 896); + avl = remove_int(avl, 585); + avl = remove_int(avl, 308); + avl = gpr_avl_add(avl, box(547), box(1505)); + avl = gpr_avl_add(avl, box(552), box(1506)); + avl = gpr_avl_add(avl, box(30), box(1507)); + avl = gpr_avl_add(avl, box(445), box(1508)); + avl = remove_int(avl, 785); + avl = remove_int(avl, 185); + avl = gpr_avl_add(avl, box(405), box(1511)); + avl = gpr_avl_add(avl, box(733), box(1512)); + avl = gpr_avl_add(avl, box(573), box(1513)); + avl = gpr_avl_add(avl, box(492), box(1514)); + avl = gpr_avl_add(avl, box(343), box(1515)); + avl = gpr_avl_add(avl, box(527), box(1516)); + avl = gpr_avl_add(avl, box(596), box(1517)); + avl = gpr_avl_add(avl, box(519), box(1518)); + avl = remove_int(avl, 243); + avl = remove_int(avl, 722); + avl = gpr_avl_add(avl, box(772), box(1521)); + avl = remove_int(avl, 152); + avl = remove_int(avl, 305); + avl = gpr_avl_add(avl, box(754), box(1524)); + avl = gpr_avl_add(avl, box(373), box(1525)); + avl = remove_int(avl, 995); + avl = gpr_avl_add(avl, box(329), box(1527)); + avl = remove_int(avl, 397); + avl = gpr_avl_add(avl, box(884), box(1529)); + avl = remove_int(avl, 329); + avl = remove_int(avl, 240); + avl = gpr_avl_add(avl, box(566), box(1532)); + avl = gpr_avl_add(avl, box(232), box(1533)); + avl = remove_int(avl, 993); + avl = gpr_avl_add(avl, box(888), box(1535)); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(941), box(1537)); + avl = remove_int(avl, 415); + avl = gpr_avl_add(avl, box(992), box(1539)); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(60), box(1541)); + avl = gpr_avl_add(avl, box(97), box(1542)); + avl = remove_int(avl, 965); + avl = remove_int(avl, 267); + avl = remove_int(avl, 360); + avl = gpr_avl_add(avl, box(5), box(1546)); + avl = remove_int(avl, 429); + avl = gpr_avl_add(avl, box(412), box(1548)); + avl = remove_int(avl, 632); + avl = remove_int(avl, 113); + avl = gpr_avl_add(avl, box(48), box(1551)); + avl = gpr_avl_add(avl, box(108), box(1552)); + avl = gpr_avl_add(avl, box(750), box(1553)); + avl = remove_int(avl, 188); + avl = gpr_avl_add(avl, box(668), box(1555)); + avl = remove_int(avl, 37); + avl = remove_int(avl, 737); + avl = gpr_avl_add(avl, box(93), box(1558)); + avl = gpr_avl_add(avl, box(628), box(1559)); + avl = gpr_avl_add(avl, box(480), box(1560)); + avl = remove_int(avl, 958); + avl = remove_int(avl, 565); + avl = remove_int(avl, 32); + avl = remove_int(avl, 1); + avl = remove_int(avl, 335); + avl = gpr_avl_add(avl, box(136), box(1566)); + avl = gpr_avl_add(avl, box(469), box(1567)); + avl = remove_int(avl, 349); + avl = gpr_avl_add(avl, box(768), box(1569)); + avl = gpr_avl_add(avl, box(915), box(1570)); + avl = remove_int(avl, 1014); + avl = gpr_avl_add(avl, box(117), box(1572)); + avl = remove_int(avl, 62); + avl = gpr_avl_add(avl, box(382), box(1574)); + avl = remove_int(avl, 571); + avl = gpr_avl_add(avl, box(655), box(1576)); + avl = gpr_avl_add(avl, box(323), box(1577)); + avl = remove_int(avl, 869); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(1019), box(1580)); + avl = gpr_avl_add(avl, box(984), box(1581)); + avl = gpr_avl_add(avl, box(870), box(1582)); + avl = gpr_avl_add(avl, box(376), box(1583)); + avl = remove_int(avl, 625); + avl = gpr_avl_add(avl, box(733), box(1585)); + avl = remove_int(avl, 532); + avl = remove_int(avl, 444); + avl = gpr_avl_add(avl, box(428), box(1588)); + avl = gpr_avl_add(avl, box(860), box(1589)); + avl = gpr_avl_add(avl, box(173), box(1590)); + avl = remove_int(avl, 649); + avl = remove_int(avl, 913); + avl = remove_int(avl, 1); + avl = remove_int(avl, 304); + avl = gpr_avl_add(avl, box(604), box(1595)); + avl = gpr_avl_add(avl, box(639), box(1596)); + avl = remove_int(avl, 431); + avl = gpr_avl_add(avl, box(993), box(1598)); + avl = remove_int(avl, 681); + avl = remove_int(avl, 927); + avl = gpr_avl_add(avl, box(87), box(1601)); + avl = gpr_avl_add(avl, box(91), box(1602)); + avl = remove_int(avl, 61); + avl = remove_int(avl, 14); + avl = remove_int(avl, 305); + avl = remove_int(avl, 304); + avl = remove_int(avl, 1016); + avl = gpr_avl_add(avl, box(903), box(1608)); + avl = gpr_avl_add(avl, box(951), box(1609)); + avl = gpr_avl_add(avl, box(146), box(1610)); + avl = gpr_avl_add(avl, box(482), box(1611)); + avl = gpr_avl_add(avl, box(71), box(1612)); + avl = remove_int(avl, 246); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(636), box(1615)); + avl = gpr_avl_add(avl, box(295), box(1616)); + avl = remove_int(avl, 11); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(905), box(1619)); + avl = gpr_avl_add(avl, box(993), box(1620)); + avl = gpr_avl_add(avl, box(433), box(1621)); + avl = gpr_avl_add(avl, box(117), box(1622)); + avl = gpr_avl_add(avl, box(467), box(1623)); + avl = remove_int(avl, 419); + avl = gpr_avl_add(avl, box(179), box(1625)); + avl = remove_int(avl, 926); + avl = remove_int(avl, 326); + avl = gpr_avl_add(avl, box(551), box(1628)); + avl = remove_int(avl, 14); + avl = remove_int(avl, 476); + avl = remove_int(avl, 823); + avl = gpr_avl_add(avl, box(350), box(1632)); + avl = gpr_avl_add(avl, box(133), box(1633)); + avl = remove_int(avl, 906); + avl = gpr_avl_add(avl, box(827), box(1635)); + avl = gpr_avl_add(avl, box(201), box(1636)); + avl = remove_int(avl, 124); + avl = remove_int(avl, 662); + avl = gpr_avl_add(avl, box(314), box(1639)); + avl = gpr_avl_add(avl, box(986), box(1640)); + avl = gpr_avl_add(avl, box(622), box(1641)); + avl = remove_int(avl, 130); + avl = gpr_avl_add(avl, box(861), box(1643)); + avl = remove_int(avl, 497); + avl = remove_int(avl, 905); + avl = gpr_avl_add(avl, box(502), box(1646)); + avl = remove_int(avl, 721); + avl = gpr_avl_add(avl, box(514), box(1648)); + avl = gpr_avl_add(avl, box(410), box(1649)); + avl = remove_int(avl, 869); + avl = remove_int(avl, 247); + avl = gpr_avl_add(avl, box(450), box(1652)); + avl = remove_int(avl, 364); + avl = gpr_avl_add(avl, box(963), box(1654)); + avl = gpr_avl_add(avl, box(146), box(1655)); + avl = remove_int(avl, 147); + avl = remove_int(avl, 789); + avl = gpr_avl_add(avl, box(693), box(1658)); + avl = gpr_avl_add(avl, box(959), box(1659)); + avl = remove_int(avl, 478); + avl = gpr_avl_add(avl, box(116), box(1661)); + avl = gpr_avl_add(avl, box(520), box(1662)); + avl = gpr_avl_add(avl, box(809), box(1663)); + avl = gpr_avl_add(avl, box(667), box(1664)); + avl = gpr_avl_add(avl, box(406), box(1665)); + avl = remove_int(avl, 409); + avl = gpr_avl_add(avl, box(558), box(1667)); + avl = gpr_avl_add(avl, box(0), box(1668)); + avl = gpr_avl_add(avl, box(948), box(1669)); + avl = gpr_avl_add(avl, box(576), box(1670)); + avl = remove_int(avl, 864); + avl = remove_int(avl, 840); + avl = remove_int(avl, 1001); + avl = gpr_avl_add(avl, box(232), box(1674)); + avl = remove_int(avl, 676); + avl = remove_int(avl, 752); + avl = remove_int(avl, 667); + avl = remove_int(avl, 605); + avl = gpr_avl_add(avl, box(258), box(1679)); + avl = gpr_avl_add(avl, box(648), box(1680)); + avl = gpr_avl_add(avl, box(761), box(1681)); + avl = remove_int(avl, 293); + avl = remove_int(avl, 893); + avl = gpr_avl_add(avl, box(194), box(1684)); + avl = remove_int(avl, 233); + avl = gpr_avl_add(avl, box(888), box(1686)); + avl = remove_int(avl, 470); + avl = remove_int(avl, 703); + avl = remove_int(avl, 190); + avl = remove_int(avl, 359); + avl = gpr_avl_add(avl, box(621), box(1691)); + avl = remove_int(avl, 634); + avl = remove_int(avl, 335); + avl = gpr_avl_add(avl, box(718), box(1694)); + avl = gpr_avl_add(avl, box(463), box(1695)); + avl = gpr_avl_add(avl, box(233), box(1696)); + avl = remove_int(avl, 376); + avl = remove_int(avl, 496); + avl = remove_int(avl, 819); + avl = remove_int(avl, 38); + avl = remove_int(avl, 436); + avl = remove_int(avl, 102); + avl = gpr_avl_add(avl, box(607), box(1703)); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(716), box(1705)); + avl = remove_int(avl, 639); + avl = remove_int(avl, 775); + avl = remove_int(avl, 578); + avl = remove_int(avl, 464); + avl = remove_int(avl, 679); + avl = remove_int(avl, 615); + avl = remove_int(avl, 104); + avl = gpr_avl_add(avl, box(414), box(1713)); + avl = gpr_avl_add(avl, box(212), box(1714)); + avl = gpr_avl_add(avl, box(266), box(1715)); + avl = gpr_avl_add(avl, box(238), box(1716)); + avl = remove_int(avl, 153); + avl = gpr_avl_add(avl, box(585), box(1718)); + avl = remove_int(avl, 121); + avl = gpr_avl_add(avl, box(534), box(1720)); + avl = remove_int(avl, 579); + avl = gpr_avl_add(avl, box(127), box(1722)); + avl = gpr_avl_add(avl, box(399), box(1723)); + avl = remove_int(avl, 417); + avl = gpr_avl_add(avl, box(978), box(1725)); + avl = gpr_avl_add(avl, box(768), box(1726)); + avl = remove_int(avl, 985); + avl = gpr_avl_add(avl, box(536), box(1728)); + avl = gpr_avl_add(avl, box(449), box(1729)); + avl = gpr_avl_add(avl, box(586), box(1730)); + avl = remove_int(avl, 998); + avl = remove_int(avl, 394); + avl = remove_int(avl, 141); + avl = gpr_avl_add(avl, box(889), box(1734)); + avl = gpr_avl_add(avl, box(871), box(1735)); + avl = gpr_avl_add(avl, box(76), box(1736)); + avl = gpr_avl_add(avl, box(549), box(1737)); + avl = gpr_avl_add(avl, box(757), box(1738)); + avl = remove_int(avl, 908); + avl = gpr_avl_add(avl, box(789), box(1740)); + avl = remove_int(avl, 224); + avl = gpr_avl_add(avl, box(407), box(1742)); + avl = gpr_avl_add(avl, box(381), box(1743)); + avl = gpr_avl_add(avl, box(561), box(1744)); + avl = gpr_avl_add(avl, box(667), box(1745)); + avl = gpr_avl_add(avl, box(522), box(1746)); + avl = gpr_avl_add(avl, box(948), box(1747)); + avl = remove_int(avl, 770); + avl = gpr_avl_add(avl, box(872), box(1749)); + avl = gpr_avl_add(avl, box(327), box(1750)); + avl = remove_int(avl, 10); + avl = gpr_avl_add(avl, box(122), box(1752)); + avl = remove_int(avl, 606); + avl = gpr_avl_add(avl, box(485), box(1754)); + avl = remove_int(avl, 6); + avl = gpr_avl_add(avl, box(329), box(1756)); + avl = gpr_avl_add(avl, box(783), box(1757)); + avl = remove_int(avl, 416); + avl = gpr_avl_add(avl, box(656), box(1759)); + avl = gpr_avl_add(avl, box(971), box(1760)); + avl = gpr_avl_add(avl, box(77), box(1761)); + avl = gpr_avl_add(avl, box(942), box(1762)); + avl = remove_int(avl, 361); + avl = gpr_avl_add(avl, box(66), box(1764)); + avl = gpr_avl_add(avl, box(299), box(1765)); + avl = gpr_avl_add(avl, box(929), box(1766)); + avl = gpr_avl_add(avl, box(797), box(1767)); + avl = remove_int(avl, 869); + avl = remove_int(avl, 907); + avl = gpr_avl_add(avl, box(870), box(1770)); + avl = remove_int(avl, 580); + avl = remove_int(avl, 120); + avl = gpr_avl_add(avl, box(913), box(1773)); + avl = remove_int(avl, 480); + avl = gpr_avl_add(avl, box(489), box(1775)); + avl = remove_int(avl, 845); + avl = gpr_avl_add(avl, box(896), box(1777)); + avl = remove_int(avl, 567); + avl = remove_int(avl, 427); + avl = gpr_avl_add(avl, box(443), box(1780)); + avl = gpr_avl_add(avl, box(3), box(1781)); + avl = remove_int(avl, 12); + avl = gpr_avl_add(avl, box(376), box(1783)); + avl = gpr_avl_add(avl, box(155), box(1784)); + avl = gpr_avl_add(avl, box(188), box(1785)); + avl = gpr_avl_add(avl, box(149), box(1786)); + avl = gpr_avl_add(avl, box(178), box(1787)); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(805), box(1789)); + avl = gpr_avl_add(avl, box(612), box(1790)); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(837), box(1792)); + avl = remove_int(avl, 173); + avl = remove_int(avl, 72); + avl = gpr_avl_add(avl, box(1014), box(1795)); + avl = remove_int(avl, 303); + avl = gpr_avl_add(avl, box(865), box(1797)); + avl = gpr_avl_add(avl, box(793), box(1798)); + avl = remove_int(avl, 173); + avl = remove_int(avl, 477); + avl = gpr_avl_add(avl, box(950), box(1801)); + avl = gpr_avl_add(avl, box(105), box(1802)); + avl = gpr_avl_add(avl, box(895), box(1803)); + avl = gpr_avl_add(avl, box(171), box(1804)); + avl = gpr_avl_add(avl, box(753), box(1805)); + avl = gpr_avl_add(avl, box(946), box(1806)); + avl = remove_int(avl, 194); + avl = remove_int(avl, 559); + avl = remove_int(avl, 116); + avl = gpr_avl_add(avl, box(968), box(1810)); + avl = remove_int(avl, 124); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(563), box(1813)); + avl = remove_int(avl, 182); + avl = gpr_avl_add(avl, box(816), box(1815)); + avl = remove_int(avl, 73); + avl = remove_int(avl, 261); + avl = gpr_avl_add(avl, box(847), box(1818)); + avl = gpr_avl_add(avl, box(368), box(1819)); + avl = gpr_avl_add(avl, box(808), box(1820)); + avl = gpr_avl_add(avl, box(779), box(1821)); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(466), box(1823)); + avl = remove_int(avl, 316); + avl = gpr_avl_add(avl, box(986), box(1825)); + avl = gpr_avl_add(avl, box(688), box(1826)); + avl = gpr_avl_add(avl, box(509), box(1827)); + avl = gpr_avl_add(avl, box(51), box(1828)); + avl = remove_int(avl, 655); + avl = remove_int(avl, 785); + avl = remove_int(avl, 893); + avl = gpr_avl_add(avl, box(167), box(1832)); + avl = remove_int(avl, 13); + avl = remove_int(avl, 263); + avl = gpr_avl_add(avl, box(1009), box(1835)); + avl = remove_int(avl, 480); + avl = remove_int(avl, 778); + avl = remove_int(avl, 713); + avl = remove_int(avl, 628); + avl = gpr_avl_add(avl, box(803), box(1840)); + avl = remove_int(avl, 267); + avl = gpr_avl_add(avl, box(676), box(1842)); + avl = gpr_avl_add(avl, box(231), box(1843)); + avl = gpr_avl_add(avl, box(824), box(1844)); + avl = remove_int(avl, 961); + avl = gpr_avl_add(avl, box(311), box(1846)); + avl = gpr_avl_add(avl, box(420), box(1847)); + avl = gpr_avl_add(avl, box(960), box(1848)); + avl = gpr_avl_add(avl, box(468), box(1849)); + avl = gpr_avl_add(avl, box(815), box(1850)); + avl = remove_int(avl, 247); + avl = remove_int(avl, 194); + avl = gpr_avl_add(avl, box(546), box(1853)); + avl = remove_int(avl, 222); + avl = remove_int(avl, 914); + avl = remove_int(avl, 741); + avl = gpr_avl_add(avl, box(470), box(1857)); + avl = gpr_avl_add(avl, box(933), box(1858)); + avl = gpr_avl_add(avl, box(97), box(1859)); + avl = remove_int(avl, 564); + avl = remove_int(avl, 295); + avl = gpr_avl_add(avl, box(864), box(1862)); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(124), box(1864)); + avl = gpr_avl_add(avl, box(1000), box(1865)); + avl = gpr_avl_add(avl, box(228), box(1866)); + avl = gpr_avl_add(avl, box(187), box(1867)); + avl = remove_int(avl, 224); + avl = remove_int(avl, 306); + avl = remove_int(avl, 884); + avl = gpr_avl_add(avl, box(449), box(1871)); + avl = gpr_avl_add(avl, box(353), box(1872)); + avl = gpr_avl_add(avl, box(994), box(1873)); + avl = gpr_avl_add(avl, box(596), box(1874)); + avl = gpr_avl_add(avl, box(996), box(1875)); + avl = gpr_avl_add(avl, box(101), box(1876)); + avl = gpr_avl_add(avl, box(1012), box(1877)); + avl = gpr_avl_add(avl, box(982), box(1878)); + avl = gpr_avl_add(avl, box(742), box(1879)); + avl = remove_int(avl, 92); + avl = remove_int(avl, 1022); + avl = gpr_avl_add(avl, box(941), box(1882)); + avl = remove_int(avl, 742); + avl = remove_int(avl, 919); + avl = gpr_avl_add(avl, box(588), box(1885)); + avl = remove_int(avl, 221); + avl = gpr_avl_add(avl, box(356), box(1887)); + avl = gpr_avl_add(avl, box(932), box(1888)); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(394), box(1890)); + avl = gpr_avl_add(avl, box(642), box(1891)); + avl = gpr_avl_add(avl, box(52), box(1892)); + avl = gpr_avl_add(avl, box(437), box(1893)); + avl = gpr_avl_add(avl, box(948), box(1894)); + avl = gpr_avl_add(avl, box(93), box(1895)); + avl = remove_int(avl, 873); + avl = remove_int(avl, 336); + avl = remove_int(avl, 277); + avl = remove_int(avl, 932); + avl = gpr_avl_add(avl, box(80), box(1900)); + avl = gpr_avl_add(avl, box(952), box(1901)); + avl = gpr_avl_add(avl, box(510), box(1902)); + avl = remove_int(avl, 876); + avl = remove_int(avl, 612); + avl = gpr_avl_add(avl, box(923), box(1905)); + avl = gpr_avl_add(avl, box(475), box(1906)); + avl = remove_int(avl, 478); + avl = remove_int(avl, 148); + avl = gpr_avl_add(avl, box(538), box(1909)); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(89), box(1911)); + avl = remove_int(avl, 723); + avl = gpr_avl_add(avl, box(687), box(1913)); + avl = gpr_avl_add(avl, box(480), box(1914)); + avl = gpr_avl_add(avl, box(149), box(1915)); + avl = remove_int(avl, 68); + avl = remove_int(avl, 862); + avl = remove_int(avl, 363); + avl = gpr_avl_add(avl, box(996), box(1919)); + avl = remove_int(avl, 380); + avl = gpr_avl_add(avl, box(957), box(1921)); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(360), box(1923)); + avl = gpr_avl_add(avl, box(304), box(1924)); + avl = gpr_avl_add(avl, box(634), box(1925)); + avl = gpr_avl_add(avl, box(506), box(1926)); + avl = remove_int(avl, 248); + avl = gpr_avl_add(avl, box(124), box(1928)); + avl = gpr_avl_add(avl, box(181), box(1929)); + avl = remove_int(avl, 507); + avl = gpr_avl_add(avl, box(141), box(1931)); + avl = remove_int(avl, 409); + avl = remove_int(avl, 129); + avl = remove_int(avl, 694); + avl = remove_int(avl, 723); + avl = gpr_avl_add(avl, box(998), box(1936)); + avl = gpr_avl_add(avl, box(906), box(1937)); + avl = gpr_avl_add(avl, box(44), box(1938)); + avl = remove_int(avl, 949); + avl = remove_int(avl, 117); + avl = gpr_avl_add(avl, box(700), box(1941)); + avl = gpr_avl_add(avl, box(258), box(1942)); + avl = remove_int(avl, 828); + avl = gpr_avl_add(avl, box(860), box(1944)); + avl = gpr_avl_add(avl, box(987), box(1945)); + avl = gpr_avl_add(avl, box(316), box(1946)); + avl = gpr_avl_add(avl, box(919), box(1947)); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(473), box(1949)); + avl = remove_int(avl, 127); + avl = remove_int(avl, 829); + avl = remove_int(avl, 829); + avl = gpr_avl_add(avl, box(488), box(1953)); + avl = gpr_avl_add(avl, box(954), box(1954)); + avl = remove_int(avl, 198); + avl = remove_int(avl, 972); + avl = remove_int(avl, 670); + avl = gpr_avl_add(avl, box(822), box(1958)); + avl = remove_int(avl, 589); + avl = remove_int(avl, 459); + avl = gpr_avl_add(avl, box(1003), box(1961)); + avl = gpr_avl_add(avl, box(657), box(1962)); + avl = gpr_avl_add(avl, box(477), box(1963)); + avl = gpr_avl_add(avl, box(923), box(1964)); + avl = remove_int(avl, 496); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(127), box(1967)); + avl = gpr_avl_add(avl, box(1013), box(1968)); + avl = gpr_avl_add(avl, box(778), box(1969)); + avl = remove_int(avl, 5); + avl = remove_int(avl, 990); + avl = remove_int(avl, 850); + avl = remove_int(avl, 160); + avl = remove_int(avl, 86); + avl = gpr_avl_add(avl, box(283), box(1975)); + avl = remove_int(avl, 278); + avl = remove_int(avl, 297); + avl = remove_int(avl, 137); + avl = remove_int(avl, 653); + avl = gpr_avl_add(avl, box(702), box(1980)); + avl = remove_int(avl, 63); + avl = remove_int(avl, 427); + avl = remove_int(avl, 706); + avl = remove_int(avl, 806); + avl = gpr_avl_add(avl, box(335), box(1985)); + avl = gpr_avl_add(avl, box(412), box(1986)); + avl = remove_int(avl, 766); + avl = remove_int(avl, 937); + avl = remove_int(avl, 886); + avl = remove_int(avl, 652); + avl = gpr_avl_add(avl, box(545), box(1991)); + avl = gpr_avl_add(avl, box(408), box(1992)); + avl = gpr_avl_add(avl, box(841), box(1993)); + avl = remove_int(avl, 593); + avl = gpr_avl_add(avl, box(582), box(1995)); + avl = gpr_avl_add(avl, box(597), box(1996)); + avl = remove_int(avl, 49); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(417), box(1999)); + avl = gpr_avl_add(avl, box(191), box(2000)); + avl = remove_int(avl, 406); + avl = gpr_avl_add(avl, box(30), box(2002)); + avl = remove_int(avl, 841); + avl = remove_int(avl, 50); + avl = gpr_avl_add(avl, box(967), box(2005)); + avl = gpr_avl_add(avl, box(849), box(2006)); + avl = remove_int(avl, 608); + avl = gpr_avl_add(avl, box(306), box(2008)); + avl = remove_int(avl, 779); + avl = gpr_avl_add(avl, box(897), box(2010)); + avl = gpr_avl_add(avl, box(147), box(2011)); + avl = remove_int(avl, 982); + avl = gpr_avl_add(avl, box(470), box(2013)); + avl = remove_int(avl, 951); + avl = gpr_avl_add(avl, box(388), box(2015)); + avl = remove_int(avl, 616); + avl = remove_int(avl, 721); + avl = remove_int(avl, 942); + avl = remove_int(avl, 589); + avl = gpr_avl_add(avl, box(218), box(2020)); + avl = remove_int(avl, 671); + avl = gpr_avl_add(avl, box(1020), box(2022)); + avl = remove_int(avl, 277); + avl = gpr_avl_add(avl, box(681), box(2024)); + avl = gpr_avl_add(avl, box(179), box(2025)); + avl = gpr_avl_add(avl, box(370), box(2026)); + avl = gpr_avl_add(avl, box(0), box(2027)); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(99), box(2029)); + avl = gpr_avl_add(avl, box(334), box(2030)); + avl = gpr_avl_add(avl, box(569), box(2031)); + avl = gpr_avl_add(avl, box(257), box(2032)); + avl = remove_int(avl, 572); + avl = gpr_avl_add(avl, box(805), box(2034)); + avl = gpr_avl_add(avl, box(143), box(2035)); + avl = gpr_avl_add(avl, box(670), box(2036)); + avl = remove_int(avl, 42); + avl = gpr_avl_add(avl, box(46), box(2038)); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(353), box(2040)); + avl = remove_int(avl, 258); + avl = gpr_avl_add(avl, box(451), box(2042)); + avl = gpr_avl_add(avl, box(28), box(2043)); + avl = gpr_avl_add(avl, box(729), box(2044)); + avl = gpr_avl_add(avl, box(401), box(2045)); + avl = gpr_avl_add(avl, box(614), box(2046)); + avl = remove_int(avl, 990); + avl = remove_int(avl, 212); + avl = remove_int(avl, 22); + avl = remove_int(avl, 677); + avl = gpr_avl_add(avl, box(1016), box(2051)); + avl = gpr_avl_add(avl, box(980), box(2052)); + avl = gpr_avl_add(avl, box(990), box(2053)); + avl = gpr_avl_add(avl, box(355), box(2054)); + avl = remove_int(avl, 730); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(407), box(2057)); + avl = gpr_avl_add(avl, box(222), box(2058)); + avl = gpr_avl_add(avl, box(439), box(2059)); + avl = gpr_avl_add(avl, box(563), box(2060)); + avl = remove_int(avl, 992); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(1), box(2063)); + avl = gpr_avl_add(avl, box(473), box(2064)); + avl = gpr_avl_add(avl, box(992), box(2065)); + avl = remove_int(avl, 190); + avl = remove_int(avl, 450); + avl = remove_int(avl, 1020); + avl = remove_int(avl, 149); + avl = gpr_avl_add(avl, box(329), box(2070)); + avl = gpr_avl_add(avl, box(35), box(2071)); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(855), box(2073)); + avl = remove_int(avl, 878); + avl = gpr_avl_add(avl, box(993), box(2075)); + avl = gpr_avl_add(avl, box(87), box(2076)); + avl = gpr_avl_add(avl, box(572), box(2077)); + avl = remove_int(avl, 896); + avl = gpr_avl_add(avl, box(849), box(2079)); + avl = remove_int(avl, 597); + avl = gpr_avl_add(avl, box(472), box(2081)); + avl = remove_int(avl, 778); + avl = remove_int(avl, 934); + avl = remove_int(avl, 314); + avl = gpr_avl_add(avl, box(101), box(2085)); + avl = remove_int(avl, 938); + avl = remove_int(avl, 1010); + avl = gpr_avl_add(avl, box(579), box(2088)); + avl = remove_int(avl, 798); + avl = remove_int(avl, 88); + avl = gpr_avl_add(avl, box(851), box(2091)); + avl = remove_int(avl, 705); + avl = gpr_avl_add(avl, box(26), box(2093)); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(923), box(2095)); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(310), box(2097)); + avl = gpr_avl_add(avl, box(269), box(2098)); + avl = remove_int(avl, 173); + avl = gpr_avl_add(avl, box(279), box(2100)); + avl = remove_int(avl, 203); + avl = gpr_avl_add(avl, box(411), box(2102)); + avl = remove_int(avl, 950); + avl = gpr_avl_add(avl, box(6), box(2104)); + avl = remove_int(avl, 400); + avl = remove_int(avl, 468); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(627), box(2108)); + avl = remove_int(avl, 727); + avl = remove_int(avl, 148); + avl = remove_int(avl, 98); + avl = remove_int(avl, 997); + avl = remove_int(avl, 215); + avl = remove_int(avl, 628); + avl = remove_int(avl, 826); + avl = remove_int(avl, 664); + avl = gpr_avl_add(avl, box(76), box(2117)); + avl = remove_int(avl, 194); + avl = remove_int(avl, 18); + avl = gpr_avl_add(avl, box(727), box(2120)); + avl = remove_int(avl, 295); + avl = gpr_avl_add(avl, box(645), box(2122)); + avl = remove_int(avl, 321); + avl = remove_int(avl, 863); + avl = gpr_avl_add(avl, box(824), box(2125)); + avl = gpr_avl_add(avl, box(651), box(2126)); + avl = gpr_avl_add(avl, box(804), box(2127)); + avl = remove_int(avl, 307); + avl = gpr_avl_add(avl, box(867), box(2129)); + avl = remove_int(avl, 384); + avl = gpr_avl_add(avl, box(819), box(2131)); + avl = remove_int(avl, 674); + avl = gpr_avl_add(avl, box(76), box(2133)); + avl = remove_int(avl, 898); + avl = gpr_avl_add(avl, box(45), box(2135)); + avl = gpr_avl_add(avl, box(512), box(2136)); + avl = remove_int(avl, 773); + avl = remove_int(avl, 907); + avl = remove_int(avl, 382); + avl = remove_int(avl, 95); + avl = remove_int(avl, 734); + avl = remove_int(avl, 81); + avl = gpr_avl_add(avl, box(348), box(2143)); + avl = remove_int(avl, 509); + avl = remove_int(avl, 301); + avl = gpr_avl_add(avl, box(861), box(2146)); + avl = gpr_avl_add(avl, box(918), box(2147)); + avl = remove_int(avl, 992); + avl = gpr_avl_add(avl, box(356), box(2149)); + avl = remove_int(avl, 64); + avl = remove_int(avl, 444); + avl = remove_int(avl, 741); + avl = gpr_avl_add(avl, box(710), box(2153)); + avl = gpr_avl_add(avl, box(264), box(2154)); + avl = remove_int(avl, 347); + avl = remove_int(avl, 250); + avl = gpr_avl_add(avl, box(82), box(2157)); + avl = gpr_avl_add(avl, box(571), box(2158)); + avl = remove_int(avl, 721); + avl = remove_int(avl, 622); + avl = gpr_avl_add(avl, box(950), box(2161)); + avl = gpr_avl_add(avl, box(94), box(2162)); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(815), box(2164)); + avl = remove_int(avl, 930); + avl = remove_int(avl, 703); + avl = gpr_avl_add(avl, box(432), box(2167)); + avl = remove_int(avl, 544); + avl = gpr_avl_add(avl, box(21), box(2169)); + avl = gpr_avl_add(avl, box(186), box(2170)); + avl = remove_int(avl, 143); + avl = gpr_avl_add(avl, box(425), box(2172)); + avl = remove_int(avl, 769); + avl = gpr_avl_add(avl, box(656), box(2174)); + avl = remove_int(avl, 29); + avl = gpr_avl_add(avl, box(464), box(2176)); + avl = remove_int(avl, 713); + avl = gpr_avl_add(avl, box(800), box(2178)); + avl = remove_int(avl, 621); + avl = gpr_avl_add(avl, box(962), box(2180)); + avl = remove_int(avl, 448); + avl = gpr_avl_add(avl, box(878), box(2182)); + avl = remove_int(avl, 39); + avl = remove_int(avl, 999); + avl = gpr_avl_add(avl, box(182), box(2185)); + avl = gpr_avl_add(avl, box(429), box(2186)); + avl = gpr_avl_add(avl, box(598), box(2187)); + avl = remove_int(avl, 551); + avl = gpr_avl_add(avl, box(827), box(2189)); + avl = gpr_avl_add(avl, box(809), box(2190)); + avl = remove_int(avl, 438); + avl = remove_int(avl, 811); + avl = gpr_avl_add(avl, box(808), box(2193)); + avl = gpr_avl_add(avl, box(788), box(2194)); + avl = remove_int(avl, 156); + avl = gpr_avl_add(avl, box(933), box(2196)); + avl = gpr_avl_add(avl, box(344), box(2197)); + avl = remove_int(avl, 460); + avl = gpr_avl_add(avl, box(161), box(2199)); + avl = gpr_avl_add(avl, box(444), box(2200)); + avl = remove_int(avl, 597); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(703), box(2203)); + avl = remove_int(avl, 515); + avl = gpr_avl_add(avl, box(380), box(2205)); + avl = gpr_avl_add(avl, box(338), box(2206)); + avl = remove_int(avl, 550); + avl = remove_int(avl, 946); + avl = remove_int(avl, 714); + avl = remove_int(avl, 739); + avl = gpr_avl_add(avl, box(413), box(2211)); + avl = remove_int(avl, 450); + avl = gpr_avl_add(avl, box(411), box(2213)); + avl = gpr_avl_add(avl, box(117), box(2214)); + avl = gpr_avl_add(avl, box(322), box(2215)); + avl = gpr_avl_add(avl, box(915), box(2216)); + avl = gpr_avl_add(avl, box(410), box(2217)); + avl = gpr_avl_add(avl, box(66), box(2218)); + avl = remove_int(avl, 756); + avl = remove_int(avl, 596); + avl = gpr_avl_add(avl, box(882), box(2221)); + avl = gpr_avl_add(avl, box(930), box(2222)); + avl = gpr_avl_add(avl, box(36), box(2223)); + avl = remove_int(avl, 742); + avl = gpr_avl_add(avl, box(539), box(2225)); + avl = gpr_avl_add(avl, box(596), box(2226)); + avl = remove_int(avl, 82); + avl = remove_int(avl, 686); + avl = remove_int(avl, 933); + avl = remove_int(avl, 42); + avl = remove_int(avl, 340); + avl = gpr_avl_add(avl, box(126), box(2232)); + avl = gpr_avl_add(avl, box(493), box(2233)); + avl = gpr_avl_add(avl, box(839), box(2234)); + avl = remove_int(avl, 774); + avl = gpr_avl_add(avl, box(337), box(2236)); + avl = remove_int(avl, 322); + avl = gpr_avl_add(avl, box(16), box(2238)); + avl = remove_int(avl, 73); + avl = remove_int(avl, 85); + avl = remove_int(avl, 191); + avl = remove_int(avl, 541); + avl = gpr_avl_add(avl, box(704), box(2243)); + avl = remove_int(avl, 767); + avl = remove_int(avl, 1006); + avl = remove_int(avl, 844); + avl = remove_int(avl, 742); + avl = gpr_avl_add(avl, box(48), box(2248)); + avl = gpr_avl_add(avl, box(138), box(2249)); + avl = gpr_avl_add(avl, box(437), box(2250)); + avl = gpr_avl_add(avl, box(275), box(2251)); + avl = remove_int(avl, 520); + avl = gpr_avl_add(avl, box(1019), box(2253)); + avl = remove_int(avl, 955); + avl = gpr_avl_add(avl, box(270), box(2255)); + avl = remove_int(avl, 680); + avl = remove_int(avl, 698); + avl = gpr_avl_add(avl, box(735), box(2258)); + avl = gpr_avl_add(avl, box(400), box(2259)); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(263), box(2261)); + avl = remove_int(avl, 704); + avl = gpr_avl_add(avl, box(757), box(2263)); + avl = remove_int(avl, 194); + avl = remove_int(avl, 616); + avl = remove_int(avl, 784); + avl = gpr_avl_add(avl, box(382), box(2267)); + avl = gpr_avl_add(avl, box(464), box(2268)); + avl = gpr_avl_add(avl, box(817), box(2269)); + avl = remove_int(avl, 445); + avl = gpr_avl_add(avl, box(412), box(2271)); + avl = remove_int(avl, 525); + avl = gpr_avl_add(avl, box(299), box(2273)); + avl = gpr_avl_add(avl, box(464), box(2274)); + avl = gpr_avl_add(avl, box(715), box(2275)); + avl = remove_int(avl, 58); + avl = remove_int(avl, 218); + avl = gpr_avl_add(avl, box(961), box(2278)); + avl = gpr_avl_add(avl, box(491), box(2279)); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(762), box(2281)); + avl = remove_int(avl, 974); + avl = remove_int(avl, 887); + avl = gpr_avl_add(avl, box(498), box(2284)); + avl = remove_int(avl, 810); + avl = remove_int(avl, 743); + avl = remove_int(avl, 22); + avl = remove_int(avl, 284); + avl = gpr_avl_add(avl, box(482), box(2289)); + avl = gpr_avl_add(avl, box(1021), box(2290)); + avl = remove_int(avl, 155); + avl = remove_int(avl, 128); + avl = gpr_avl_add(avl, box(819), box(2293)); + avl = gpr_avl_add(avl, box(324), box(2294)); + avl = remove_int(avl, 196); + avl = remove_int(avl, 370); + avl = remove_int(avl, 753); + avl = remove_int(avl, 56); + avl = remove_int(avl, 735); + avl = gpr_avl_add(avl, box(272), box(2300)); + avl = gpr_avl_add(avl, box(474), box(2301)); + avl = gpr_avl_add(avl, box(719), box(2302)); + avl = gpr_avl_add(avl, box(236), box(2303)); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(727), box(2305)); + avl = remove_int(avl, 892); + avl = remove_int(avl, 871); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(62), box(2309)); + avl = gpr_avl_add(avl, box(953), box(2310)); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(193), box(2312)); + avl = remove_int(avl, 619); + avl = remove_int(avl, 22); + avl = remove_int(avl, 804); + avl = remove_int(avl, 851); + avl = gpr_avl_add(avl, box(286), box(2317)); + avl = gpr_avl_add(avl, box(751), box(2318)); + avl = remove_int(avl, 525); + avl = gpr_avl_add(avl, box(217), box(2320)); + avl = remove_int(avl, 336); + avl = gpr_avl_add(avl, box(86), box(2322)); + avl = gpr_avl_add(avl, box(81), box(2323)); + avl = gpr_avl_add(avl, box(850), box(2324)); + avl = remove_int(avl, 872); + avl = gpr_avl_add(avl, box(402), box(2326)); + avl = gpr_avl_add(avl, box(54), box(2327)); + avl = gpr_avl_add(avl, box(980), box(2328)); + avl = gpr_avl_add(avl, box(845), box(2329)); + avl = remove_int(avl, 1004); + avl = remove_int(avl, 273); + avl = remove_int(avl, 879); + avl = gpr_avl_add(avl, box(354), box(2333)); + avl = gpr_avl_add(avl, box(58), box(2334)); + avl = gpr_avl_add(avl, box(127), box(2335)); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(360), box(2337)); + avl = remove_int(avl, 648); + avl = remove_int(avl, 488); + avl = remove_int(avl, 585); + avl = remove_int(avl, 230); + avl = gpr_avl_add(avl, box(887), box(2342)); + avl = remove_int(avl, 558); + avl = remove_int(avl, 958); + avl = gpr_avl_add(avl, box(822), box(2345)); + avl = remove_int(avl, 1004); + avl = remove_int(avl, 747); + avl = gpr_avl_add(avl, box(631), box(2348)); + avl = gpr_avl_add(avl, box(442), box(2349)); + avl = remove_int(avl, 957); + avl = remove_int(avl, 964); + avl = gpr_avl_add(avl, box(10), box(2352)); + avl = remove_int(avl, 189); + avl = gpr_avl_add(avl, box(742), box(2354)); + avl = remove_int(avl, 108); + avl = gpr_avl_add(avl, box(1014), box(2356)); + avl = remove_int(avl, 266); + avl = remove_int(avl, 623); + avl = remove_int(avl, 697); + avl = gpr_avl_add(avl, box(180), box(2360)); + avl = remove_int(avl, 472); + avl = gpr_avl_add(avl, box(567), box(2362)); + avl = remove_int(avl, 1020); + avl = remove_int(avl, 273); + avl = gpr_avl_add(avl, box(864), box(2365)); + avl = gpr_avl_add(avl, box(1009), box(2366)); + avl = remove_int(avl, 224); + avl = remove_int(avl, 81); + avl = gpr_avl_add(avl, box(653), box(2369)); + avl = remove_int(avl, 67); + avl = remove_int(avl, 102); + avl = remove_int(avl, 76); + avl = remove_int(avl, 935); + avl = remove_int(avl, 169); + avl = remove_int(avl, 232); + avl = remove_int(avl, 79); + avl = gpr_avl_add(avl, box(509), box(2377)); + avl = remove_int(avl, 900); + avl = remove_int(avl, 822); + avl = remove_int(avl, 945); + avl = remove_int(avl, 356); + avl = gpr_avl_add(avl, box(443), box(2382)); + avl = gpr_avl_add(avl, box(925), box(2383)); + avl = remove_int(avl, 994); + avl = remove_int(avl, 324); + avl = gpr_avl_add(avl, box(291), box(2386)); + avl = remove_int(avl, 94); + avl = remove_int(avl, 795); + avl = remove_int(avl, 42); + avl = gpr_avl_add(avl, box(613), box(2390)); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(980), box(2392)); + avl = remove_int(avl, 316); + avl = gpr_avl_add(avl, box(281), box(2394)); + avl = gpr_avl_add(avl, box(1006), box(2395)); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(108), box(2397)); + avl = gpr_avl_add(avl, box(918), box(2398)); + avl = remove_int(avl, 721); + avl = remove_int(avl, 563); + avl = gpr_avl_add(avl, box(925), box(2401)); + avl = remove_int(avl, 448); + avl = remove_int(avl, 198); + avl = remove_int(avl, 1); + avl = gpr_avl_add(avl, box(160), box(2405)); + avl = remove_int(avl, 515); + avl = gpr_avl_add(avl, box(284), box(2407)); + avl = gpr_avl_add(avl, box(225), box(2408)); + avl = remove_int(avl, 304); + avl = gpr_avl_add(avl, box(714), box(2410)); + avl = gpr_avl_add(avl, box(708), box(2411)); + avl = gpr_avl_add(avl, box(624), box(2412)); + avl = remove_int(avl, 662); + avl = remove_int(avl, 825); + avl = remove_int(avl, 383); + avl = remove_int(avl, 381); + avl = gpr_avl_add(avl, box(194), box(2417)); + avl = remove_int(avl, 280); + avl = remove_int(avl, 25); + avl = remove_int(avl, 633); + avl = gpr_avl_add(avl, box(897), box(2421)); + avl = remove_int(avl, 636); + avl = remove_int(avl, 596); + avl = remove_int(avl, 757); + avl = remove_int(avl, 343); + avl = remove_int(avl, 162); + avl = remove_int(avl, 913); + avl = remove_int(avl, 843); + avl = remove_int(avl, 280); + avl = remove_int(avl, 911); + avl = gpr_avl_add(avl, box(1008), box(2431)); + avl = remove_int(avl, 948); + avl = remove_int(avl, 74); + avl = remove_int(avl, 571); + avl = gpr_avl_add(avl, box(486), box(2435)); + avl = gpr_avl_add(avl, box(285), box(2436)); + avl = remove_int(avl, 304); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(758), box(2439)); + avl = gpr_avl_add(avl, box(776), box(2440)); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(104), box(2442)); + avl = gpr_avl_add(avl, box(700), box(2443)); + avl = gpr_avl_add(avl, box(114), box(2444)); + avl = gpr_avl_add(avl, box(567), box(2445)); + avl = remove_int(avl, 620); + avl = gpr_avl_add(avl, box(270), box(2447)); + avl = remove_int(avl, 730); + avl = gpr_avl_add(avl, box(749), box(2449)); + avl = gpr_avl_add(avl, box(443), box(2450)); + avl = remove_int(avl, 457); + avl = gpr_avl_add(avl, box(571), box(2452)); + avl = gpr_avl_add(avl, box(626), box(2453)); + avl = remove_int(avl, 638); + avl = remove_int(avl, 313); + + gpr_avl_unref(avl); +} + +static void test_stress(void) { + int added[1024]; + int i, j; + int deletions = 0; + gpr_avl avl; + + gpr_log(GPR_DEBUG, "test_stress"); + + srand((unsigned)time(NULL)); + avl = gpr_avl_create(&int_int_vtable); + + memset(added, 0, sizeof(added)); + + for (i = 1; deletions < 1000; i++) { + int idx = rand() % (int)GPR_ARRAY_SIZE(added); + GPR_ASSERT(i); + if (rand() < RAND_MAX / 2) { + added[idx] = i; + fprintf(stderr, "avl = gpr_avl_add(avl, box(%d), box(%d)); /* d=%d */\n", + idx, i, deletions); + avl = gpr_avl_add(avl, box(idx), box(i)); + } else { + deletions += (added[idx] != 0); + added[idx] = 0; + fprintf(stderr, "avl = remove_int(avl, %d); /* d=%d */\n", idx, + deletions); + avl = remove_int(avl, idx); + } + for (j = 0; j < (int)GPR_ARRAY_SIZE(added); j++) { + if (added[j] != 0) { + check_get(avl, j, added[j]); + } else { + check_negget(avl, j); + } + } + } + + gpr_avl_unref(avl); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + + test_get(); + test_ll(); + test_lr(); + test_rr(); + test_rl(); + test_unbalanced(); + test_replace(); + test_remove(); + test_badcase1(); + test_badcase2(); + test_badcase3(); + test_stress(); + + return 0; +} 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/slice_buffer_test.c b/test/core/support/slice_buffer_test.c index a48278434f..cf2da84c2b 100644 --- a/test/core/support/slice_buffer_test.c +++ b/test/core/support/slice_buffer_test.c @@ -35,13 +35,12 @@ #include <grpc/support/slice_buffer.h> #include "test/core/util/test_config.h" -int main(int argc, char **argv) { +void test_slice_buffer_add() { gpr_slice_buffer buf; gpr_slice aaa = gpr_slice_from_copied_string("aaa"); gpr_slice bb = gpr_slice_from_copied_string("bb"); size_t i; - grpc_test_init(argc, argv); gpr_slice_buffer_init(&buf); for (i = 0; i < 10; i++) { gpr_slice_ref(aaa); @@ -70,6 +69,61 @@ int main(int argc, char **argv) { GPR_ASSERT(buf.count == 0); GPR_ASSERT(buf.length == 0); gpr_slice_buffer_destroy(&buf); +} + +void test_slice_buffer_move_first() { + gpr_slice slices[3]; + gpr_slice_buffer src; + gpr_slice_buffer dst; + int idx = 0; + size_t src_len = 0; + size_t dst_len = 0; + + slices[0] = gpr_slice_from_copied_string("aaa"); + slices[1] = gpr_slice_from_copied_string("bbbb"); + slices[2] = gpr_slice_from_copied_string("ccc"); + + gpr_slice_buffer_init(&src); + gpr_slice_buffer_init(&dst); + for (idx = 0; idx < 3; idx++) { + gpr_slice_ref(slices[idx]); + /* For this test, it is important that we add each slice at a new + slice index */ + gpr_slice_buffer_add_indexed(&src, slices[idx]); + gpr_slice_buffer_add_indexed(&dst, slices[idx]); + } + + /* Case 1: Move more than the first slice's length from src to dst */ + src_len = src.length; + dst_len = dst.length; + gpr_slice_buffer_move_first(&src, 4, &dst); + src_len -= 4; + dst_len += 4; + GPR_ASSERT(src.length == src_len); + GPR_ASSERT(dst.length == dst_len); + + /* src now has two slices ["bbb"] and ["ccc"] */ + /* Case 2: Move the first slice from src to dst */ + gpr_slice_buffer_move_first(&src, 3, &dst); + src_len -= 3; + dst_len += 3; + GPR_ASSERT(src.length == src_len); + GPR_ASSERT(dst.length == dst_len); + + /* src now has one slice ["ccc"] */ + /* Case 3: Move less than the first slice's length from src to dst*/ + gpr_slice_buffer_move_first(&src, 2, &dst); + src_len -= 2; + dst_len += 2; + GPR_ASSERT(src.length == src.length); + GPR_ASSERT(dst.length == dst.length); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + test_slice_buffer_add(); + test_slice_buffer_move_first(); return 0; } diff --git a/test/core/support/slice_test.c b/test/core/support/slice_test.c index 1d202f0618..9e0e22c24b 100644 --- a/test/core/support/slice_test.c +++ b/test/core/support/slice_test.c @@ -94,12 +94,27 @@ static void do_nothing_with_len_1(void *ignored, size_t len) { static void test_slice_new_with_len_returns_something_sensible(void) { gpr_uint8 x; + int num_refs = 5; /* To test adding/removing an arbitrary number of refs */ + int i; gpr_slice slice = gpr_slice_new_with_len(&x, 1, do_nothing_with_len_1); - GPR_ASSERT(slice.refcount); + GPR_ASSERT(slice.refcount); /* ref count is initialized to 1 at this point */ GPR_ASSERT(slice.data.refcounted.bytes == &x); GPR_ASSERT(slice.data.refcounted.length == 1); GPR_ASSERT(do_nothing_with_len_1_calls == 0); + + /* Add an arbitrary number of refs to the slice and remoe the refs. This is to + make sure that that the destroy callback (i.e do_nothing_with_len_1()) is + not called until the last unref operation */ + for (i = 0; i < num_refs; i++) { + gpr_slice_ref(slice); + } + for (i = 0; i < num_refs; i++) { + gpr_slice_unref(slice); + } + GPR_ASSERT(do_nothing_with_len_1_calls == 0); /* Shouldn't be called yet */ + + /* last unref */ gpr_slice_unref(slice); GPR_ASSERT(do_nothing_with_len_1_calls == 1); } 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 220b16b60f..73f68e4dbd 100644 --- a/test/core/support/sync_test.c +++ b/test/core/support/sync_test.c @@ -153,6 +153,7 @@ struct test { gpr_int64 counter; int thread_count; /* used to allocate thread ids */ int done; /* threads not yet completed */ + int incr_step; /* how much to increment/decrement refcount each time */ gpr_mu mu; /* protects iterations, counter, thread_count, done */ @@ -170,13 +171,14 @@ struct test { }; /* Return pointer to a new struct test. */ -static struct test *test_new(int threads, gpr_int64 iterations) { +static struct test *test_new(int threads, gpr_int64 iterations, int incr_step) { struct test *m = gpr_malloc(sizeof(*m)); m->threads = threads; m->iterations = iterations; m->counter = 0; m->thread_count = 0; m->done = threads; + m->incr_step = incr_step; gpr_mu_init(&m->mu); gpr_cv_init(&m->cv); gpr_cv_init(&m->done_cv); @@ -238,9 +240,12 @@ static void mark_thread_done(struct test *m) { /* Test several threads running (*body)(struct test *m) for increasing settings of m->iterations, until about timeout_s to 2*timeout_s seconds have elapsed. - If extra!=NULL, run (*extra)(m) in an additional thread. */ + If extra!=NULL, run (*extra)(m) in an additional thread. + incr_step controls by how much m->refcount should be incremented/decremented + (if at all) each time in the tests. + */ static void test(const char *name, void (*body)(void *m), - void (*extra)(void *m), int timeout_s) { + void (*extra)(void *m), int timeout_s, int incr_step) { gpr_int64 iterations = 1024; struct test *m; gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); @@ -251,7 +256,7 @@ static void test(const char *name, void (*body)(void *m), while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { iterations <<= 1; fprintf(stderr, " %ld", (long)iterations); - m = test_new(10, iterations); + m = test_new(10, iterations, incr_step); if (extra != NULL) { gpr_thd_id id; GPR_ASSERT(gpr_thd_new(&id, extra, m, NULL)); @@ -259,7 +264,7 @@ static void test(const char *name, void (*body)(void *m), } test_create_threads(m, body); test_wait(m); - if (m->counter != m->threads * m->iterations) { + if (m->counter != m->threads * m->iterations * m->incr_step) { fprintf(stderr, "counter %ld threads %d iterations %ld\n", (long)m->counter, m->threads, (long)m->iterations); GPR_ASSERT(0); @@ -267,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); } @@ -406,14 +411,18 @@ static void statsinc(void *v /*=m*/) { mark_thread_done(m); } -/* Increment m->refcount m->iterations times, decrement m->thread_refcount - once, and if it reaches zero, set m->event to (void*)1; then mark thread as - done. */ +/* Increment m->refcount by m->incr_step for m->iterations times. Decrement + m->thread_refcount once, and if it reaches zero, set m->event to (void*)1; + then mark thread as done. */ static void refinc(void *v /*=m*/) { struct test *m = v; gpr_int64 i; for (i = 0; i != m->iterations; i++) { - gpr_ref(&m->refcount); + if (m->incr_step == 1) { + gpr_ref(&m->refcount); + } else { + gpr_refn(&m->refcount, m->incr_step); + } } if (gpr_unref(&m->thread_refcount)) { gpr_event_set(&m->event, (void *)1); @@ -421,12 +430,12 @@ static void refinc(void *v /*=m*/) { mark_thread_done(m); } -/* Wait until m->event is set to (void *)1, then decrement m->refcount - m->stats_counter m->iterations times, and ensure that the last decrement - caused the counter to reach zero, then mark thread as done. */ +/* 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. */ static void refcheck(void *v /*=m*/) { struct test *m = v; - gpr_int64 n = m->iterations * m->threads; + gpr_int64 n = m->iterations * m->threads * m->incr_step; gpr_int64 i; GPR_ASSERT(gpr_event_wait(&m->event, gpr_inf_future(GPR_CLOCK_REALTIME)) == (void *)1); @@ -444,13 +453,16 @@ static void refcheck(void *v /*=m*/) { int main(int argc, char *argv[]) { grpc_test_init(argc, argv); - test("mutex", &inc, NULL, 1); - test("mutex try", &inctry, NULL, 1); - test("cv", &inc_by_turns, NULL, 1); - test("timedcv", &inc_with_1ms_delay, NULL, 1); - test("queue", &many_producers, &consumer, 10); - test("stats_counter", &statsinc, NULL, 1); - test("refcount", &refinc, &refcheck, 1); - test("timedevent", &inc_with_1ms_delay_event, NULL, 1); + test("mutex", &inc, NULL, 1, 1); + test("mutex try", &inctry, NULL, 1, 1); + test("cv", &inc_by_turns, NULL, 1, 1); + test("timedcv", &inc_with_1ms_delay, NULL, 1, 1); + test("queue", &many_producers, &consumer, 10, 1); + test("stats_counter", &statsinc, NULL, 1, 1); + test("refcount by 1", &refinc, &refcheck, 1, 1); + test("refcount by 3", &refinc, &refcheck, 1, 3); /* incr_step of 3 is an + arbitrary choice. Any + number > 1 is okay here */ + test("timedevent", &inc_with_1ms_delay_event, NULL, 1, 1); return 0; } 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/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c index 6b41698717..c87fbdc897 100644 --- a/test/core/surface/byte_buffer_reader_test.c +++ b/test/core/surface/byte_buffer_reader_test.c @@ -217,6 +217,42 @@ static void test_readall(void) { grpc_byte_buffer_destroy(buffer); } +static void test_byte_buffer_copy(void) { + char *lotsa_as[512]; + char *lotsa_bs[1024]; + gpr_slice slices[2]; + grpc_byte_buffer *buffer; + grpc_byte_buffer *copied_buffer; + grpc_byte_buffer_reader reader; + gpr_slice slice_out; + + LOG_TEST("test_byte_buffer_copy"); + + memset(lotsa_as, 'a', 512); + memset(lotsa_bs, 'b', 1024); + /* use slices large enough to overflow inlining */ + slices[0] = gpr_slice_malloc(512); + memcpy(GPR_SLICE_START_PTR(slices[0]), lotsa_as, 512); + slices[1] = gpr_slice_malloc(1024); + memcpy(GPR_SLICE_START_PTR(slices[1]), lotsa_bs, 1024); + + buffer = grpc_raw_byte_buffer_create(slices, 2); + gpr_slice_unref(slices[0]); + gpr_slice_unref(slices[1]); + copied_buffer = grpc_byte_buffer_copy(buffer); + + grpc_byte_buffer_reader_init(&reader, copied_buffer); + slice_out = grpc_byte_buffer_reader_readall(&reader); + + GPR_ASSERT(GPR_SLICE_LENGTH(slice_out) == 512 + 1024); + GPR_ASSERT(memcmp(GPR_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0); + GPR_ASSERT(memcmp(&(GPR_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) == + 0); + gpr_slice_unref(slice_out); + grpc_byte_buffer_destroy(buffer); + grpc_byte_buffer_destroy(copied_buffer); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_read_one_slice(); @@ -225,6 +261,7 @@ int main(int argc, char **argv) { test_read_gzip_compressed_slice(); test_read_deflate_compressed_slice(); test_byte_buffer_from_reader(); + test_byte_buffer_copy(); test_readall(); return 0; } diff --git a/test/core/surface/channel_create_test.c b/test/core/surface/channel_create_test.c new file mode 100644 index 0000000000..044e766473 --- /dev/null +++ b/test/core/surface/channel_create_test.c @@ -0,0 +1,55 @@ +/* + * + * 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 "src/core/client_config/resolver_registry.h" +#include "test/core/util/test_config.h" + +void test_unknown_scheme_target(void) { + grpc_channel *chan; + /* avoid default prefix */ + grpc_resolver_registry_shutdown(); + grpc_resolver_registry_init(""); + + chan = grpc_insecure_channel_create("blah://blah", NULL, NULL); + GPR_ASSERT(chan == NULL); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_unknown_scheme_target(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index e3fc789788..252fe80621 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]); } @@ -175,6 +175,77 @@ static void test_pluck(void) { grpc_exec_ctx_finish(&exec_ctx); } +static void test_pluck_after_shutdown(void) { + grpc_event ev; + grpc_completion_queue *cc; + + LOG_TEST("test_pluck_after_shutdown"); + cc = grpc_completion_queue_create(NULL); + grpc_completion_queue_shutdown(cc); + ev = grpc_completion_queue_pluck(cc, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + +struct thread_state { + grpc_completion_queue *cc; + void *tag; +}; + +static void pluck_one(void *arg) { + struct thread_state *state = arg; + grpc_completion_queue_pluck(state->cc, state->tag, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +} + +static void test_too_many_plucks(void) { + grpc_event ev; + grpc_completion_queue *cc; + void *tags[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; + grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; + gpr_thd_id thread_ids[GPR_ARRAY_SIZE(tags)]; + struct thread_state thread_states[GPR_ARRAY_SIZE(tags)]; + gpr_thd_options thread_options = gpr_thd_options_default(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + unsigned i, j; + + LOG_TEST("test_too_many_plucks"); + + cc = grpc_completion_queue_create(NULL); + gpr_thd_options_set_joinable(&thread_options); + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + tags[i] = create_test_tag(); + for (j = 0; j < i; j++) { + GPR_ASSERT(tags[i] != tags[j]); + } + thread_states[i].cc = cc; + thread_states[i].tag = tags[i]; + gpr_thd_new(thread_ids + i, pluck_one, thread_states + i, &thread_options); + } + + /* wait until all other threads are plucking */ + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); + + 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, tags[i]); + grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL, + &completions[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + gpr_thd_join(thread_ids[i]); + } + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); +} + #define TEST_THREAD_EVENTS 10000 typedef struct test_thread_options { @@ -208,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); @@ -343,6 +414,8 @@ int main(int argc, char **argv) { test_shutdown_then_next_with_timeout(); test_cq_end_op(); test_pluck(); + test_pluck_after_shutdown(); + test_too_many_plucks(); test_threading(1, 1); test_threading(1, 10); test_threading(10, 1); diff --git a/test/core/surface/init_test.c b/test/core/surface/init_test.c new file mode 100644 index 0000000000..d4451e4567 --- /dev/null +++ b/test/core/surface/init_test.c @@ -0,0 +1,78 @@ +/* + * + * 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" + +static int g_flag; + +static void test(int rounds) { + int i; + for (i = 0; i < rounds; i++) { + grpc_init(); + } + for (i = 0; i < rounds; i++) { + grpc_shutdown(); + } +} + +static void test_mixed(void) { + grpc_init(); + grpc_init(); + grpc_shutdown(); + grpc_init(); + grpc_shutdown(); + grpc_shutdown(); +} + +static void plugin_init(void) { g_flag = 1; } +static void plugin_destroy(void) { g_flag = 2; } + +static void test_plugin() { + grpc_register_plugin(plugin_init, plugin_destroy); + grpc_init(); + GPR_ASSERT(g_flag == 1); + grpc_shutdown(); + GPR_ASSERT(g_flag == 2); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test(1); + test(2); + test(3); + test_mixed(); + test_plugin(); + return 0; +} diff --git a/test/core/surface/invalid_channel_args_test.c b/test/core/surface/invalid_channel_args_test.c new file mode 100644 index 0000000000..1b1b8b8f92 --- /dev/null +++ b/test/core/surface/invalid_channel_args_test.c @@ -0,0 +1,186 @@ +/* + * + * 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 <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include "test/core/util/test_config.h" + +static char *g_last_log_error_message = NULL; +static const char *g_file_name = "channel.c"; + +static int ends_with(const char *src, const char *suffix) { + size_t src_len = strlen(src); + size_t suffix_len = strlen(suffix); + if (src_len < suffix_len) { + return 0; + } + return strcmp(src + src_len - suffix_len, suffix) == 0; +} + +static void log_error_sink(gpr_log_func_args *args) { + if (args->severity == GPR_LOG_SEVERITY_ERROR && + ends_with(args->file, g_file_name)) { + g_last_log_error_message = gpr_strdup(args->message); + } +} + +static void verify_last_error(const char *message) { + if (message == NULL) { + GPR_ASSERT(g_last_log_error_message == NULL); + return; + } + GPR_ASSERT(strcmp(message, g_last_log_error_message) == 0); + gpr_free(g_last_log_error_message); + g_last_log_error_message = NULL; +} + +static char *compose_error_string(const char *key, const char *message) { + char *ret; + gpr_asprintf(&ret, "%s%s", key, message); + return ret; +} + +static void one_test(grpc_channel_args *args, char *expected_error_message) { + grpc_channel *chan = + grpc_insecure_channel_create("nonexistant:54321", args, NULL); + verify_last_error(expected_error_message); + gpr_free(expected_error_message); + grpc_channel_destroy(chan); +} + +static void test_no_error_message(void) { one_test(NULL, NULL); } + +static void test_max_message_length_type(void) { + grpc_arg client_arg; + grpc_channel_args client_args; + char *expected_error_message; + + client_arg.type = GRPC_ARG_STRING; + client_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH; + client_arg.value.string = NULL; + + client_args.num_args = 1; + client_args.args = &client_arg; + expected_error_message = compose_error_string( + GRPC_ARG_MAX_MESSAGE_LENGTH, " ignored: it must be an integer"); + one_test(&client_args, expected_error_message); +} + +static void test_max_message_length_negative(void) { + grpc_arg client_arg; + grpc_channel_args client_args; + char *expected_error_message; + + client_arg.type = GRPC_ARG_INTEGER; + client_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH; + client_arg.value.integer = -1; + + client_args.num_args = 1; + client_args.args = &client_arg; + expected_error_message = compose_error_string(GRPC_ARG_MAX_MESSAGE_LENGTH, + " ignored: it must be >= 0"); + one_test(&client_args, expected_error_message); +} + +static void test_default_authority_type(void) { + grpc_arg client_arg; + grpc_channel_args client_args; + char *expected_error_message; + + client_arg.type = GRPC_ARG_INTEGER; + client_arg.key = GRPC_ARG_DEFAULT_AUTHORITY; + client_arg.value.integer = 0; + + client_args.num_args = 1; + client_args.args = &client_arg; + expected_error_message = compose_error_string( + GRPC_ARG_DEFAULT_AUTHORITY, " ignored: it must be a string"); + one_test(&client_args, expected_error_message); +} + +static void test_ssl_name_override_type(void) { + grpc_arg client_arg; + grpc_channel_args client_args; + char *expected_error_message; + + client_arg.type = GRPC_ARG_INTEGER; + client_arg.key = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG; + client_arg.value.integer = 0; + + client_args.num_args = 1; + client_args.args = &client_arg; + expected_error_message = compose_error_string( + GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, " ignored: it must be a string"); + one_test(&client_args, expected_error_message); +} + +static void test_ssl_name_override_failed(void) { + grpc_arg client_arg[2]; + grpc_channel_args client_args; + char *expected_error_message; + + client_arg[0].type = GRPC_ARG_STRING; + client_arg[0].key = GRPC_ARG_DEFAULT_AUTHORITY; + client_arg[0].value.string = "default"; + client_arg[1].type = GRPC_ARG_STRING; + client_arg[1].key = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG; + client_arg[1].value.string = "ssl"; + + client_args.num_args = 2; + client_args.args = client_arg; + expected_error_message = + compose_error_string(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, + " ignored: default host already set some other way"); + one_test(&client_args, expected_error_message); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + gpr_set_log_function(log_error_sink); + + test_no_error_message(); + test_max_message_length_type(); + test_max_message_length_negative(); + test_default_authority_type(); + test_ssl_name_override_type(); + test_ssl_name_override_failed(); + + grpc_shutdown(); + + return 0; +} 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/multi_init_test.c b/test/core/surface/server_chttp2_test.c index 99b7a52ff9..ec7df6f0e3 100644 --- a/test/core/surface/multi_init_test.c +++ b/test/core/surface/server_chttp2_test.c @@ -32,32 +32,18 @@ */ #include <grpc/grpc.h> +#include <grpc/support/log.h> #include "test/core/util/test_config.h" -static void test(int rounds) { - int i; - for (i = 0; i < rounds; i++) { - grpc_init(); - } - for (i = 0; i < rounds; i++) { - grpc_shutdown(); - } -} - -static void test_mixed() { - grpc_init(); - grpc_init(); - grpc_shutdown(); - grpc_init(); - grpc_shutdown(); - grpc_shutdown(); +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); - test(1); - test(2); - test(3); - test_mixed(); + 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/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c new file mode 100644 index 0000000000..4a9d143640 --- /dev/null +++ b/test/core/transport/chttp2/hpack_encoder_test.c @@ -0,0 +1,201 @@ +/* + * + * 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/chttp2/hpack_encoder.h" + +#include <stdio.h> + +#include "src/core/support/string.h" +#include "src/core/transport/chttp2/hpack_parser.h" +#include "src/core/transport/metadata.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include "test/core/util/parse_hexstring.h" +#include "test/core/util/slice_splitter.h" +#include "test/core/util/test_config.h" + +#define TEST(x) run_test(x, #x) + +grpc_chttp2_hpack_compressor g_compressor; +int g_failure = 0; + +void **to_delete = NULL; +size_t num_to_delete = 0; +size_t cap_to_delete = 0; + +/* verify that the output generated by encoding the stream matches the + hexstring passed in */ +static void verify(size_t window_available, int eof, size_t expect_window_used, + const char *expected, size_t nheaders, ...) { + gpr_slice_buffer output; + gpr_slice merged; + gpr_slice expect = parse_hexstring(expected); + size_t i; + va_list l; + grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * nheaders); + grpc_metadata_batch b; + + grpc_metadata_batch_init(&b); + + va_start(l, nheaders); + for (i = 0; i < nheaders; i++) { + char *key = va_arg(l, char *); + char *value = va_arg(l, char *); + if (i) { + e[i - 1].next = &e[i]; + e[i].prev = &e[i - 1]; + } + e[i].md = grpc_mdelem_from_strings(key, value); + } + e[0].prev = NULL; + e[nheaders - 1].next = NULL; + va_end(l); + + b.list.head = &e[0]; + b.list.tail = &e[nheaders - 1]; + + if (cap_to_delete == num_to_delete) { + cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000); + to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete); + } + to_delete[num_to_delete++] = e; + + gpr_slice_buffer_init(&output); + + grpc_chttp2_encode_header(&g_compressor, 0xdeadbeef, &b, eof, &output); + merged = grpc_slice_merge(output.slices, output.count); + gpr_slice_buffer_destroy(&output); + grpc_metadata_batch_destroy(&b); + + if (0 != gpr_slice_cmp(merged, expect)) { + char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_ERROR, "mismatched output for %s", expected); + gpr_log(GPR_ERROR, "EXPECT: %s", expect_str); + gpr_log(GPR_ERROR, "GOT: %s", got_str); + gpr_free(expect_str); + gpr_free(got_str); + g_failure = 1; + } + + gpr_slice_unref(merged); + gpr_slice_unref(expect); +} + +static void test_basic_headers(void) { + int i; + + verify(0, 0, 0, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a"); + verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a"); + verify(0, 0, 0, "000001 0104 deadbeef be", 1, "a", "a"); + verify(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", "b", + "c"); + verify(0, 0, 0, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c"); + verify(0, 0, 0, "000004 0104 deadbeef 7f 00 0164", 1, "a", "d"); + + /* flush out what's there to make a few values look very popular */ + for (i = 0; i < 350; i++) { + verify(0, 0, 0, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", "c", "a", + "d"); + } + + verify(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", "k", + "v"); + /* this could be 000004 0104 deadbeef 0f 30 0176 also */ + verify(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v"); +} + +static void encode_int_to_str(int i, char *p) { + p[0] = (char)('a' + i % 26); + i /= 26; + GPR_ASSERT(i < 26); + p[1] = (char)('a' + i); + p[2] = 0; +} + +static void test_decode_table_overflow(void) { + int i; + char key[3], value[3]; + char *expect; + + for (i = 0; i < 114; i++) { + encode_int_to_str(i, key); + encode_int_to_str(i + 1, value); + + if (i + 61 >= 127) { + gpr_asprintf(&expect, + "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x", + i + 61 - 127, key[0], key[1], value[0], value[1]); + } else if (i > 0) { + gpr_asprintf(&expect, + "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x", + 0x80 + 61 + i, key[0], key[1], value[0], value[1]); + } else { + gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x", + key[0], key[1], value[0], value[1]); + } + + if (i > 0) { + verify(0, 0, 0, expect, 2, "aa", "ba", key, value); + } else { + verify(0, 0, 0, expect, 1, key, value); + } + gpr_free(expect); + } + + /* if the above passes, then we must have just knocked this pair out of the + decoder stack, and so we'll be forced to re-encode it */ + verify(0, 0, 0, "000007 0104 deadbeef 40 026161 026261", 1, "aa", "ba"); +} + +static void run_test(void (*test)(), const char *name) { + gpr_log(GPR_INFO, "RUN TEST: %s", name); + grpc_chttp2_hpack_compressor_init(&g_compressor); + test(); + grpc_chttp2_hpack_compressor_destroy(&g_compressor); +} + +int main(int argc, char **argv) { + size_t i; + grpc_test_only_set_metadata_hash_seed(0); + grpc_test_init(argc, argv); + grpc_init(); + TEST(test_basic_headers); + TEST(test_decode_table_overflow); + grpc_shutdown(); + for (i = 0; i < num_to_delete; i++) { + gpr_free(to_delete[i]); + } + return g_failure; +} diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c index 3a313375a4..4456e197af 100644 --- a/test/core/transport/chttp2/hpack_parser_test.c +++ b/test/core/transport/chttp2/hpack_parser_test.c @@ -35,6 +35,7 @@ #include <stdarg.h> +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/slice.h> @@ -90,9 +91,8 @@ static void test_vector(grpc_chttp2_hpack_parser *parser, static void test_vectors(grpc_slice_split_mode mode) { grpc_chttp2_hpack_parser parser; - grpc_mdctx *mdctx = grpc_mdctx_create(); - grpc_chttp2_hpack_parser_init(&parser, mdctx); + grpc_chttp2_hpack_parser_init(&parser); /* D.2.1 */ test_vector(&parser, mode, "400a 6375 7374 6f6d 2d6b 6579 0d63 7573" @@ -110,7 +110,7 @@ static void test_vectors(grpc_slice_split_mode mode) { test_vector(&parser, mode, "82", ":method", "GET", NULL); grpc_chttp2_hpack_parser_destroy(&parser); - grpc_chttp2_hpack_parser_init(&parser, mdctx); + grpc_chttp2_hpack_parser_init(&parser); /* D.3.1 */ test_vector(&parser, mode, "8286 8441 0f77 7777 2e65 7861 6d70 6c65" @@ -130,7 +130,7 @@ static void test_vectors(grpc_slice_split_mode mode) { NULL); grpc_chttp2_hpack_parser_destroy(&parser); - grpc_chttp2_hpack_parser_init(&parser, mdctx); + grpc_chttp2_hpack_parser_init(&parser); /* D.4.1 */ test_vector(&parser, mode, "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4" @@ -150,8 +150,9 @@ static void test_vectors(grpc_slice_split_mode mode) { NULL); grpc_chttp2_hpack_parser_destroy(&parser); - grpc_chttp2_hpack_parser_init(&parser, mdctx); - parser.table.max_bytes = 256; + grpc_chttp2_hpack_parser_init(&parser); + grpc_chttp2_hptbl_set_max_bytes(&parser.table, 256); + grpc_chttp2_hptbl_set_current_table_size(&parser.table, 256); /* D.5.1 */ test_vector(&parser, mode, "4803 3330 3258 0770 7269 7661 7465 611d" @@ -183,8 +184,9 @@ static void test_vectors(grpc_slice_split_mode mode) { "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); grpc_chttp2_hpack_parser_destroy(&parser); - grpc_chttp2_hpack_parser_init(&parser, mdctx); - parser.table.max_bytes = 256; + grpc_chttp2_hpack_parser_init(&parser); + grpc_chttp2_hptbl_set_max_bytes(&parser.table, 256); + grpc_chttp2_hptbl_set_current_table_size(&parser.table, 256); /* D.6.1 */ test_vector(&parser, mode, "4882 6402 5885 aec3 771a 4b61 96d0 7abe" @@ -212,12 +214,13 @@ static void test_vectors(grpc_slice_split_mode mode) { "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); grpc_chttp2_hpack_parser_destroy(&parser); - grpc_mdctx_unref(mdctx); } int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_vectors(GRPC_SLICE_SPLIT_MERGE_ALL); test_vectors(GRPC_SLICE_SPLIT_ONE_BYTE); + grpc_shutdown(); return 0; } diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c index aa3e273a6c..fde352433b 100644 --- a/test/core/transport/chttp2/hpack_table_test.c +++ b/test/core/transport/chttp2/hpack_table_test.c @@ -36,10 +36,12 @@ #include <string.h> #include <stdio.h> -#include "src/core/support/string.h" +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> + +#include "src/core/support/string.h" #include "test/core/util/test_config.h" #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) @@ -58,10 +60,8 @@ static void assert_index(const grpc_chttp2_hptbl *tbl, gpr_uint32 idx, static void test_static_lookup(void) { grpc_chttp2_hptbl tbl; - grpc_mdctx *mdctx; - mdctx = grpc_mdctx_create(); - grpc_chttp2_hptbl_init(&tbl, mdctx); + grpc_chttp2_hptbl_init(&tbl); LOG_TEST("test_static_lookup"); assert_index(&tbl, 1, ":authority", ""); @@ -127,7 +127,6 @@ static void test_static_lookup(void) { assert_index(&tbl, 61, "www-authenticate", ""); grpc_chttp2_hptbl_destroy(&tbl); - grpc_mdctx_unref(mdctx); } static void test_many_additions(void) { @@ -135,17 +134,18 @@ static void test_many_additions(void) { int i; char *key; char *value; - grpc_mdctx *mdctx; LOG_TEST("test_many_additions"); - mdctx = grpc_mdctx_create(); - grpc_chttp2_hptbl_init(&tbl, mdctx); + grpc_chttp2_hptbl_init(&tbl); for (i = 0; i < 1000000; i++) { + grpc_mdelem *elem; gpr_asprintf(&key, "K:%d", i); gpr_asprintf(&value, "VALUE:%d", i); - grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, key, value)); + elem = grpc_mdelem_from_strings(key, value); + GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem)); + GRPC_MDELEM_UNREF(elem); assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value); gpr_free(key); gpr_free(value); @@ -159,13 +159,12 @@ static void test_many_additions(void) { } grpc_chttp2_hptbl_destroy(&tbl); - grpc_mdctx_unref(mdctx); } static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl, const char *key, const char *value) { - grpc_mdelem *md = grpc_mdelem_from_strings(tbl->mdctx, key, value); + grpc_mdelem *md = grpc_mdelem_from_strings(key, value); grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md); GRPC_MDELEM_UNREF(md); return r; @@ -173,18 +172,23 @@ static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl, static void test_find(void) { grpc_chttp2_hptbl tbl; - int i; + gpr_uint32 i; char buffer[32]; - grpc_mdctx *mdctx; + grpc_mdelem *elem; grpc_chttp2_hptbl_find_result r; LOG_TEST("test_find"); - mdctx = grpc_mdctx_create(); - grpc_chttp2_hptbl_init(&tbl, mdctx); - grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "abc", "xyz")); - grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "abc", "123")); - grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "x", "1")); + grpc_chttp2_hptbl_init(&tbl); + elem = grpc_mdelem_from_strings("abc", "xyz"); + GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem)); + GRPC_MDELEM_UNREF(elem); + elem = grpc_mdelem_from_strings("abc", "123"); + GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem)); + GRPC_MDELEM_UNREF(elem); + elem = grpc_mdelem_from_strings("x", "1"); + GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem)); + GRPC_MDELEM_UNREF(elem); r = find_simple(&tbl, "abc", "123"); GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY); @@ -233,8 +237,9 @@ static void test_find(void) { /* overflow the string buffer, check find still works */ for (i = 0; i < 10000; i++) { gpr_ltoa(i, buffer); - grpc_chttp2_hptbl_add(&tbl, - grpc_mdelem_from_strings(mdctx, "test", buffer)); + elem = grpc_mdelem_from_strings("test", buffer); + GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem)); + GRPC_MDELEM_UNREF(elem); } r = find_simple(&tbl, "abc", "123"); @@ -250,7 +255,7 @@ static void test_find(void) { GPR_ASSERT(r.has_value == 1); for (i = 0; i < tbl.num_ents; i++) { - int expect = 9999 - i; + gpr_uint32 expect = 9999 - i; gpr_ltoa(expect, buffer); r = find_simple(&tbl, "test", buffer); @@ -263,13 +268,14 @@ static void test_find(void) { GPR_ASSERT(r.has_value == 0); grpc_chttp2_hptbl_destroy(&tbl); - grpc_mdctx_unref(mdctx); } int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_static_lookup(); test_many_additions(); test_find(); + grpc_shutdown(); return 0; } diff --git a/test/core/transport/chttp2/stream_encoder_test.c b/test/core/transport/chttp2/stream_encoder_test.c deleted file mode 100644 index 71db98c69e..0000000000 --- a/test/core/transport/chttp2/stream_encoder_test.c +++ /dev/null @@ -1,359 +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 "src/core/transport/chttp2/stream_encoder.h" - -#include <stdio.h> - -#include "src/core/support/string.h" -#include "src/core/transport/chttp2/hpack_parser.h" -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include "test/core/util/parse_hexstring.h" -#include "test/core/util/slice_splitter.h" -#include "test/core/util/test_config.h" - -#define TEST(x) run_test(x, #x) - -grpc_mdctx *g_mdctx; -grpc_chttp2_hpack_compressor g_compressor; -int g_failure = 0; -grpc_stream_op_buffer g_sopb; - -void **to_delete = NULL; -size_t num_to_delete = 0; -size_t cap_to_delete = 0; - -static gpr_slice create_test_slice(size_t length) { - gpr_slice slice = gpr_slice_malloc(length); - size_t i; - for (i = 0; i < length; i++) { - GPR_SLICE_START_PTR(slice)[i] = (gpr_uint8)i; - } - return slice; -} - -/* verify that the output generated by encoding the stream matches the - hexstring passed in */ -static void verify_sopb(size_t window_available, int eof, - size_t expect_window_used, const char *expected) { - gpr_slice_buffer output; - grpc_stream_op_buffer encops; - gpr_slice merged; - gpr_slice expect = parse_hexstring(expected); - gpr_slice_buffer_init(&output); - grpc_sopb_init(&encops); - GPR_ASSERT(expect_window_used == - grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, - (gpr_uint32)window_available, &encops)); - grpc_chttp2_encode(encops.ops, encops.nops, eof, 0xdeadbeef, &g_compressor, - &output); - encops.nops = 0; - merged = grpc_slice_merge(output.slices, output.count); - gpr_slice_buffer_destroy(&output); - grpc_sopb_destroy(&encops); - - if (0 != gpr_slice_cmp(merged, expect)) { - char *expect_str = gpr_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *got_str = gpr_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_ERROR, "mismatched output for %s", expected); - gpr_log(GPR_ERROR, "EXPECT: %s", expect_str); - gpr_log(GPR_ERROR, "GOT: %s", got_str); - gpr_free(expect_str); - gpr_free(got_str); - g_failure = 1; - } - - gpr_slice_unref(merged); - gpr_slice_unref(expect); -} - -static void test_small_data_framing(void) { - grpc_sopb_add_no_op(&g_sopb); - verify_sopb(10, 0, 0, ""); - - grpc_sopb_add_slice(&g_sopb, create_test_slice(3)); - verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102"); - - grpc_sopb_add_slice(&g_sopb, create_test_slice(4)); - verify_sopb(10, 0, 4, "000004 0000 deadbeef 00010203"); - - grpc_sopb_add_slice(&g_sopb, create_test_slice(3)); - grpc_sopb_add_slice(&g_sopb, create_test_slice(4)); - verify_sopb(10, 0, 7, "000007 0000 deadbeef 000102 00010203"); - - grpc_sopb_add_slice(&g_sopb, create_test_slice(0)); - grpc_sopb_add_slice(&g_sopb, create_test_slice(0)); - grpc_sopb_add_slice(&g_sopb, create_test_slice(0)); - grpc_sopb_add_slice(&g_sopb, create_test_slice(0)); - grpc_sopb_add_slice(&g_sopb, create_test_slice(3)); - verify_sopb(10, 0, 3, "000003 0000 deadbeef 000102"); - - verify_sopb(10, 1, 0, "000000 0001 deadbeef"); - - grpc_sopb_add_begin_message(&g_sopb, 255, 0); - verify_sopb(10, 0, 5, "000005 0000 deadbeef 00000000ff"); -} - -static void add_sopb_headers(size_t n, ...) { - size_t i; - grpc_metadata_batch b; - va_list l; - grpc_linked_mdelem *e = gpr_malloc(sizeof(*e) * n); - - grpc_metadata_batch_init(&b); - - va_start(l, n); - for (i = 0; i < n; i++) { - char *key = va_arg(l, char *); - char *value = va_arg(l, char *); - if (i) { - e[i - 1].next = &e[i]; - e[i].prev = &e[i - 1]; - } - e[i].md = grpc_mdelem_from_strings(g_mdctx, key, value); - } - e[0].prev = NULL; - e[n - 1].next = NULL; - va_end(l); - - b.list.head = &e[0]; - b.list.tail = &e[n - 1]; - - if (cap_to_delete == num_to_delete) { - cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000); - to_delete = gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete); - } - to_delete[num_to_delete++] = e; - - grpc_sopb_add_metadata(&g_sopb, b); -} - -static void test_basic_headers(void) { - int i; - - add_sopb_headers(1, "a", "a"); - verify_sopb(0, 0, 0, "000005 0104 deadbeef 40 0161 0161"); - - add_sopb_headers(1, "a", "a"); - verify_sopb(0, 0, 0, "000001 0104 deadbeef be"); - - add_sopb_headers(1, "a", "a"); - verify_sopb(0, 0, 0, "000001 0104 deadbeef be"); - - add_sopb_headers(2, "a", "a", "b", "c"); - verify_sopb(0, 0, 0, "000006 0104 deadbeef be 40 0162 0163"); - - add_sopb_headers(2, "a", "a", "b", "c"); - verify_sopb(0, 0, 0, "000002 0104 deadbeef bf be"); - - add_sopb_headers(1, "a", "d"); - verify_sopb(0, 0, 0, "000004 0104 deadbeef 7f 00 0164"); - - /* flush out what's there to make a few values look very popular */ - for (i = 0; i < 350; i++) { - add_sopb_headers(3, "a", "a", "b", "c", "a", "d"); - verify_sopb(0, 0, 0, "000003 0104 deadbeef c0 bf be"); - } - - add_sopb_headers(2, "a", "a", "k", "v"); - verify_sopb(0, 0, 0, "000006 0104 deadbeef c0 00 016b 0176"); - - add_sopb_headers(1, "a", "v"); - /* this could be 000004 0104 deadbeef 0f 30 0176 also */ - verify_sopb(0, 0, 0, "000004 0104 deadbeef 0f 2f 0176"); -} - -static void encode_int_to_str(int i, char *p) { - p[0] = (char)('a' + i % 26); - i /= 26; - GPR_ASSERT(i < 26); - p[1] = (char)('a' + i); - p[2] = 0; -} - -static void test_decode_table_overflow(void) { - int i; - char key[3], value[3]; - char *expect; - - for (i = 0; i < 114; i++) { - if (i > 0) { - add_sopb_headers(1, "aa", "ba"); - } - - encode_int_to_str(i, key); - encode_int_to_str(i + 1, value); - - if (i + 61 >= 127) { - gpr_asprintf(&expect, - "000002 0104 deadbeef ff%02x 000007 0104 deadbeef 40 " - "02%02x%02x 02%02x%02x", - i + 61 - 127, key[0], key[1], value[0], value[1]); - } else if (i > 0) { - gpr_asprintf(&expect, - "000001 0104 deadbeef %02x 000007 0104 deadbeef 40 " - "02%02x%02x 02%02x%02x", - 0x80 + 61 + i, key[0], key[1], value[0], value[1]); - } else { - gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x", - key[0], key[1], value[0], value[1]); - } - - add_sopb_headers(1, key, value); - verify_sopb(0, 0, 0, expect); - gpr_free(expect); - } - - /* if the above passes, then we must have just knocked this pair out of the - decoder stack, and so we'll be forced to re-encode it */ - add_sopb_headers(1, "aa", "ba"); - verify_sopb(0, 0, 0, "000007 0104 deadbeef 40 026161 026261"); -} - -static void randstr(char *p, int bufsz) { - int i; - int len = 1 + rand() % bufsz; - for (i = 0; i < len; i++) { - p[i] = (char)('a' + rand() % 26); - } - p[len] = 0; -} - -typedef struct { - char key[300]; - char value[300]; - int got_hdr; -} test_decode_random_header_state; - -static void chk_hdr(void *p, grpc_mdelem *el) { - test_decode_random_header_state *st = p; - GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key)); - GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value)); - st->got_hdr = 1; - GRPC_MDELEM_UNREF(el); -} - -static void test_decode_random_headers_inner(int max_len) { - int i; - test_decode_random_header_state st; - gpr_slice_buffer output; - gpr_slice merged; - grpc_stream_op_buffer encops; - grpc_chttp2_hpack_parser parser; - - grpc_chttp2_hpack_parser_init(&parser, g_mdctx); - grpc_sopb_init(&encops); - - gpr_log(GPR_INFO, "max_len = %d", max_len); - - for (i = 0; i < 10000; i++) { - randstr(st.key, max_len); - randstr(st.value, max_len); - - add_sopb_headers(1, st.key, st.value); - gpr_slice_buffer_init(&output); - GPR_ASSERT(0 == - grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, 0, &encops)); - grpc_chttp2_encode(encops.ops, encops.nops, 0, 0xdeadbeef, &g_compressor, - &output); - encops.nops = 0; - merged = grpc_slice_merge(output.slices, output.count); - gpr_slice_buffer_destroy(&output); - - st.got_hdr = 0; - parser.on_header = chk_hdr; - parser.on_header_user_data = &st; - grpc_chttp2_hpack_parser_parse(&parser, GPR_SLICE_START_PTR(merged) + 9, - GPR_SLICE_END_PTR(merged)); - GPR_ASSERT(st.got_hdr); - - gpr_slice_unref(merged); - } - - grpc_chttp2_hpack_parser_destroy(&parser); - grpc_sopb_destroy(&encops); -} - -#define DECL_TEST_DECODE_RANDOM_HEADERS(n) \ - static void test_decode_random_headers_##n(void) { \ - test_decode_random_headers_inner(n); \ - } \ - int keeps_formatting_correct_##n - -DECL_TEST_DECODE_RANDOM_HEADERS(1); -DECL_TEST_DECODE_RANDOM_HEADERS(2); -DECL_TEST_DECODE_RANDOM_HEADERS(3); -DECL_TEST_DECODE_RANDOM_HEADERS(5); -DECL_TEST_DECODE_RANDOM_HEADERS(8); -DECL_TEST_DECODE_RANDOM_HEADERS(13); -DECL_TEST_DECODE_RANDOM_HEADERS(21); -DECL_TEST_DECODE_RANDOM_HEADERS(34); -DECL_TEST_DECODE_RANDOM_HEADERS(55); -DECL_TEST_DECODE_RANDOM_HEADERS(89); -DECL_TEST_DECODE_RANDOM_HEADERS(144); - -static void run_test(void (*test)(), const char *name) { - gpr_log(GPR_INFO, "RUN TEST: %s", name); - g_mdctx = grpc_mdctx_create_with_seed(0); - grpc_chttp2_hpack_compressor_init(&g_compressor, g_mdctx); - grpc_sopb_init(&g_sopb); - test(); - grpc_chttp2_hpack_compressor_destroy(&g_compressor); - grpc_mdctx_unref(g_mdctx); - grpc_sopb_destroy(&g_sopb); -} - -int main(int argc, char **argv) { - size_t i; - grpc_test_init(argc, argv); - TEST(test_small_data_framing); - TEST(test_basic_headers); - TEST(test_decode_table_overflow); - TEST(test_decode_random_headers_1); - TEST(test_decode_random_headers_2); - TEST(test_decode_random_headers_3); - TEST(test_decode_random_headers_5); - TEST(test_decode_random_headers_8); - TEST(test_decode_random_headers_13); - TEST(test_decode_random_headers_21); - TEST(test_decode_random_headers_34); - TEST(test_decode_random_headers_55); - TEST(test_decode_random_headers_89); - TEST(test_decode_random_headers_144); - for (i = 0; i < num_to_delete; i++) { - gpr_free(to_delete[i]); - } - return g_failure; -} diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c new file mode 100644 index 0000000000..31fcb7e182 --- /dev/null +++ b/test/core/transport/chttp2/varint_test.c @@ -0,0 +1,69 @@ +/* + * + * 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/chttp2/varint.h" + +#include <grpc/support/log.h> +#include <grpc/support/slice.h> + +#include "test/core/util/test_config.h" + +static void test_varint(gpr_uint32 value, gpr_uint32 prefix_bits, + gpr_uint8 prefix_or, const char *expect_bytes, + size_t expect_length) { + gpr_uint32 nbytes = GRPC_CHTTP2_VARINT_LENGTH(value, prefix_bits); + gpr_slice expect = gpr_slice_from_copied_buffer(expect_bytes, expect_length); + gpr_slice slice; + 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); + 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) + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + TEST_VARINT(0, 1, 0, "\x00"); + TEST_VARINT(128, 1, 0, "\x7f\x01"); + TEST_VARINT(16384, 1, 0, "\x7f\x81\x7f"); + TEST_VARINT(2097152, 1, 0, "\x7f\x81\xff\x7f"); + TEST_VARINT(268435456, 1, 0, "\x7f\x81\xff\xff\x7f"); + TEST_VARINT(0xffffffff, 1, 0, "\x7f\x80\xff\xff\xff\x0f"); + return 0; +} 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/transport/metadata_test.c b/test/core/transport/metadata_test.c index 080e86cb63..928fba7f45 100644 --- a/test/core/transport/metadata_test.c +++ b/test/core/transport/metadata_test.c @@ -35,11 +35,13 @@ #include <stdio.h> -#include "src/core/support/string.h" -#include "src/core/transport/chttp2/bin_encoder.h" +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> + +#include "src/core/support/string.h" +#include "src/core/transport/chttp2/bin_encoder.h" #include "test/core/util/test_config.h" #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) @@ -48,44 +50,39 @@ #define MANY 10000 static void test_no_op(void) { - grpc_mdctx *ctx; - LOG_TEST("test_no_op"); - - ctx = grpc_mdctx_create(); - grpc_mdctx_unref(ctx); + grpc_init(); + grpc_shutdown(); } static void test_create_string(void) { - grpc_mdctx *ctx; grpc_mdstr *s1, *s2, *s3; LOG_TEST("test_create_string"); - ctx = grpc_mdctx_create(); - s1 = grpc_mdstr_from_string(ctx, "hello"); - s2 = grpc_mdstr_from_string(ctx, "hello"); - s3 = grpc_mdstr_from_string(ctx, "very much not hello"); + grpc_init(); + s1 = grpc_mdstr_from_string("hello"); + s2 = grpc_mdstr_from_string("hello"); + s3 = grpc_mdstr_from_string("very much not hello"); GPR_ASSERT(s1 == s2); GPR_ASSERT(s3 != s1); GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0); GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0); GRPC_MDSTR_UNREF(s1); GRPC_MDSTR_UNREF(s2); - grpc_mdctx_unref(ctx); GRPC_MDSTR_UNREF(s3); + grpc_shutdown(); } static void test_create_metadata(void) { - grpc_mdctx *ctx; grpc_mdelem *m1, *m2, *m3; LOG_TEST("test_create_metadata"); - ctx = grpc_mdctx_create(); - m1 = grpc_mdelem_from_strings(ctx, "a", "b"); - m2 = grpc_mdelem_from_strings(ctx, "a", "b"); - m3 = grpc_mdelem_from_strings(ctx, "a", "c"); + grpc_init(); + m1 = grpc_mdelem_from_strings("a", "b"); + m2 = grpc_mdelem_from_strings("a", "b"); + m3 = grpc_mdelem_from_strings("a", "c"); GPR_ASSERT(m1 == m2); GPR_ASSERT(m3 != m1); GPR_ASSERT(m3->key == m1->key); @@ -96,32 +93,25 @@ static void test_create_metadata(void) { GRPC_MDELEM_UNREF(m1); GRPC_MDELEM_UNREF(m2); GRPC_MDELEM_UNREF(m3); - grpc_mdctx_unref(ctx); + grpc_shutdown(); } static void test_create_many_ephemeral_metadata(void) { - grpc_mdctx *ctx; char buffer[GPR_LTOA_MIN_BUFSIZE]; long i; - size_t mdtab_capacity_before; LOG_TEST("test_create_many_ephemeral_metadata"); - ctx = grpc_mdctx_create(); - mdtab_capacity_before = grpc_mdctx_get_mdtab_capacity_test_only(ctx); + grpc_init(); /* add, and immediately delete a bunch of different elements */ for (i = 0; i < MANY; i++) { gpr_ltoa(i, buffer); - GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", buffer)); + GRPC_MDELEM_UNREF(grpc_mdelem_from_strings("a", buffer)); } - /* capacity should not grow */ - GPR_ASSERT(mdtab_capacity_before == - grpc_mdctx_get_mdtab_capacity_test_only(ctx)); - grpc_mdctx_unref(ctx); + grpc_shutdown(); } static void test_create_many_persistant_metadata(void) { - grpc_mdctx *ctx; char buffer[GPR_LTOA_MIN_BUFSIZE]; long i; grpc_mdelem **created = gpr_malloc(sizeof(grpc_mdelem *) * MANY); @@ -129,16 +119,16 @@ static void test_create_many_persistant_metadata(void) { LOG_TEST("test_create_many_persistant_metadata"); - ctx = grpc_mdctx_create(); + grpc_init(); /* add phase */ for (i = 0; i < MANY; i++) { gpr_ltoa(i, buffer); - created[i] = grpc_mdelem_from_strings(ctx, "a", buffer); + created[i] = grpc_mdelem_from_strings("a", buffer); } /* verify phase */ for (i = 0; i < MANY; i++) { gpr_ltoa(i, buffer); - md = grpc_mdelem_from_strings(ctx, "a", buffer); + md = grpc_mdelem_from_strings("a", buffer); GPR_ASSERT(md == created[i]); GRPC_MDELEM_UNREF(md); } @@ -146,37 +136,22 @@ static void test_create_many_persistant_metadata(void) { for (i = 0; i < MANY; i++) { GRPC_MDELEM_UNREF(created[i]); } - grpc_mdctx_unref(ctx); + grpc_shutdown(); gpr_free(created); } static void test_spin_creating_the_same_thing(void) { - grpc_mdctx *ctx; - LOG_TEST("test_spin_creating_the_same_thing"); - ctx = grpc_mdctx_create(); - GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 0); - GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 0); - - GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b")); - GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); - GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); - - GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b")); - GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); - GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); - - GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b")); - GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); - GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); - - grpc_mdctx_unref(ctx); + grpc_init(); + GRPC_MDELEM_UNREF(grpc_mdelem_from_strings("a", "b")); + GRPC_MDELEM_UNREF(grpc_mdelem_from_strings("a", "b")); + GRPC_MDELEM_UNREF(grpc_mdelem_from_strings("a", "b")); + grpc_shutdown(); } static void test_things_stick_around(void) { - grpc_mdctx *ctx; size_t i, j; char *buffer; size_t nstrs = 1000; @@ -186,11 +161,11 @@ static void test_things_stick_around(void) { LOG_TEST("test_things_stick_around"); - ctx = grpc_mdctx_create(); + grpc_init(); for (i = 0; i < nstrs; i++) { gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", i); - strs[i] = grpc_mdstr_from_string(ctx, buffer); + strs[i] = grpc_mdstr_from_string(buffer); shuf[i] = i; gpr_free(buffer); } @@ -212,60 +187,77 @@ static void test_things_stick_around(void) { GRPC_MDSTR_UNREF(strs[shuf[i]]); for (j = i + 1; j < nstrs; j++) { gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]); - test = grpc_mdstr_from_string(ctx, buffer); + test = grpc_mdstr_from_string(buffer); GPR_ASSERT(test == strs[shuf[j]]); GRPC_MDSTR_UNREF(test); gpr_free(buffer); } } - grpc_mdctx_unref(ctx); + grpc_shutdown(); gpr_free(strs); gpr_free(shuf); } static void test_slices_work(void) { /* ensure no memory leaks when switching representation from mdstr to slice */ - grpc_mdctx *ctx; grpc_mdstr *str; gpr_slice slice; LOG_TEST("test_slices_work"); - ctx = grpc_mdctx_create(); + grpc_init(); str = grpc_mdstr_from_string( - ctx, "123456789012345678901234567890123456789012345678901234567890"); + "123456789012345678901234567890123456789012345678901234567890"); slice = gpr_slice_ref(str->slice); GRPC_MDSTR_UNREF(str); gpr_slice_unref(slice); str = grpc_mdstr_from_string( - ctx, "123456789012345678901234567890123456789012345678901234567890"); + "123456789012345678901234567890123456789012345678901234567890"); slice = gpr_slice_ref(str->slice); gpr_slice_unref(slice); GRPC_MDSTR_UNREF(str); - grpc_mdctx_unref(ctx); + grpc_shutdown(); } static void test_base64_and_huffman_works(void) { - grpc_mdctx *ctx; grpc_mdstr *str; gpr_slice slice1; gpr_slice slice2; LOG_TEST("test_base64_and_huffman_works"); - ctx = grpc_mdctx_create(); - str = grpc_mdstr_from_string(ctx, "abcdefg"); + grpc_init(); + str = grpc_mdstr_from_string("abcdefg"); slice1 = grpc_mdstr_as_base64_encoded_and_huffman_compressed(str); slice2 = grpc_chttp2_base64_encode_and_huffman_compress(str->slice); GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2)); gpr_slice_unref(slice2); GRPC_MDSTR_UNREF(str); - grpc_mdctx_unref(ctx); + grpc_shutdown(); +} + +static void test_user_data_works(void) { + int *ud1; + int *ud2; + grpc_mdelem *md; + LOG_TEST("test_user_data_works"); + + grpc_init(); + ud1 = gpr_malloc(sizeof(int)); + *ud1 = 1; + ud2 = gpr_malloc(sizeof(int)); + *ud2 = 2; + md = grpc_mdelem_from_strings("abc", "123"); + grpc_mdelem_set_user_data(md, gpr_free, ud1); + grpc_mdelem_set_user_data(md, gpr_free, ud2); + GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1); + GRPC_MDELEM_UNREF(md); + grpc_shutdown(); } int main(int argc, char **argv) { @@ -279,5 +271,6 @@ int main(int argc, char **argv) { test_things_stick_around(); test_slices_work(); test_base64_and_huffman_works(); + test_user_data_works(); return 0; } diff --git a/test/core/transport/stream_op_test.c b/test/core/transport/stream_op_test.c deleted file mode 100644 index 546080deb9..0000000000 --- a/test/core/transport/stream_op_test.c +++ /dev/null @@ -1,116 +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 "src/core/transport/stream_op.h" - -#include <string.h> - -#include <grpc/support/log.h> -#include "test/core/util/test_config.h" - -static void assert_slices_equal(gpr_slice a, gpr_slice b) { - GPR_ASSERT(a.refcount == b.refcount); - if (a.refcount) { - GPR_ASSERT(a.data.refcounted.bytes == b.data.refcounted.bytes); - GPR_ASSERT(a.data.refcounted.length == b.data.refcounted.length); - } else { - GPR_ASSERT(a.data.inlined.length == b.data.inlined.length); - GPR_ASSERT(0 == memcmp(a.data.inlined.bytes, b.data.inlined.bytes, - a.data.inlined.length)); - } -} - -int main(int argc, char **argv) { - /* some basic test data */ - gpr_slice test_slice_1 = gpr_slice_malloc(1); - gpr_slice test_slice_2 = gpr_slice_malloc(2); - gpr_slice test_slice_3 = gpr_slice_malloc(3); - gpr_slice test_slice_4 = gpr_slice_malloc(4); - unsigned i; - - grpc_stream_op_buffer buf; - grpc_stream_op_buffer buf2; - - grpc_test_init(argc, argv); - /* initialize one of our buffers */ - grpc_sopb_init(&buf); - /* it should start out empty */ - GPR_ASSERT(buf.nops == 0); - - /* add some data to the buffer */ - grpc_sopb_add_begin_message(&buf, 1, 2); - grpc_sopb_add_slice(&buf, test_slice_1); - grpc_sopb_add_slice(&buf, test_slice_2); - grpc_sopb_add_slice(&buf, test_slice_3); - grpc_sopb_add_slice(&buf, test_slice_4); - grpc_sopb_add_no_op(&buf); - - /* verify that the data went in ok */ - GPR_ASSERT(buf.nops == 6); - GPR_ASSERT(buf.ops[0].type == GRPC_OP_BEGIN_MESSAGE); - GPR_ASSERT(buf.ops[0].data.begin_message.length == 1); - GPR_ASSERT(buf.ops[0].data.begin_message.flags == 2); - GPR_ASSERT(buf.ops[1].type == GRPC_OP_SLICE); - assert_slices_equal(buf.ops[1].data.slice, test_slice_1); - GPR_ASSERT(buf.ops[2].type == GRPC_OP_SLICE); - assert_slices_equal(buf.ops[2].data.slice, test_slice_2); - GPR_ASSERT(buf.ops[3].type == GRPC_OP_SLICE); - assert_slices_equal(buf.ops[3].data.slice, test_slice_3); - GPR_ASSERT(buf.ops[4].type == GRPC_OP_SLICE); - assert_slices_equal(buf.ops[4].data.slice, test_slice_4); - GPR_ASSERT(buf.ops[5].type == GRPC_NO_OP); - - /* initialize the second buffer */ - grpc_sopb_init(&buf2); - /* add a no-op, and then the original buffer */ - grpc_sopb_add_no_op(&buf2); - grpc_sopb_append(&buf2, buf.ops, buf.nops); - /* should be one element bigger than the original */ - GPR_ASSERT(buf2.nops == buf.nops + 1); - GPR_ASSERT(buf2.ops[0].type == GRPC_NO_OP); - /* and the tail should be the same */ - for (i = 0; i < buf.nops; i++) { - GPR_ASSERT(buf2.ops[i + 1].type == buf.ops[i].type); - } - - /* destroy the buffers */ - grpc_sopb_destroy(&buf); - grpc_sopb_destroy(&buf2); - - gpr_slice_unref(test_slice_1); - gpr_slice_unref(test_slice_2); - gpr_slice_unref(test_slice_3); - gpr_slice_unref(test_slice_4); - - return 0; -} diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c index 858b92fc9d..7ce343987b 100644 --- a/test/core/tsi/transport_security_test.c +++ b/test/core/tsi/transport_security_test.c @@ -43,6 +43,7 @@ #include <openssl/crypto.h> #include "src/core/support/string.h" +#include "src/core/tsi/fake_transport_security.h" #include "src/core/tsi/ssl_transport_security.h" #include "test/core/util/test_config.h" @@ -296,8 +297,70 @@ static void test_peer_matches_name(void) { } } +typedef struct { + tsi_result res; + const char *str; +} tsi_result_string_pair; + +static void test_result_strings(void) { + const tsi_result_string_pair results[] = { + {TSI_OK, "TSI_OK"}, + {TSI_UNKNOWN_ERROR, "TSI_UNKNOWN_ERROR"}, + {TSI_INVALID_ARGUMENT, "TSI_INVALID_ARGUMENT"}, + {TSI_PERMISSION_DENIED, "TSI_PERMISSION_DENIED"}, + {TSI_INCOMPLETE_DATA, "TSI_INCOMPLETE_DATA"}, + {TSI_FAILED_PRECONDITION, "TSI_FAILED_PRECONDITION"}, + {TSI_UNIMPLEMENTED, "TSI_UNIMPLEMENTED"}, + {TSI_INTERNAL_ERROR, "TSI_INTERNAL_ERROR"}, + {TSI_DATA_CORRUPTED, "TSI_DATA_CORRUPTED"}, + {TSI_NOT_FOUND, "TSI_NOT_FOUND"}, + {TSI_PROTOCOL_FAILURE, "TSI_PROTOCOL_FAILURE"}, + {TSI_HANDSHAKE_IN_PROGRESS, "TSI_HANDSHAKE_IN_PROGRESS"}, + {TSI_OUT_OF_RESOURCES, "TSI_OUT_OF_RESOURCES"}}; + size_t i; + for (i = 0; i < GPR_ARRAY_SIZE(results); i++) { + GPR_ASSERT(strcmp(results[i].str, tsi_result_to_string(results[i].res)) == + 0); + } + GPR_ASSERT(strcmp("UNKNOWN", tsi_result_to_string((tsi_result)42)) == 0); +} + +static void test_protector_invalid_args(void) { + GPR_ASSERT(tsi_frame_protector_protect(NULL, NULL, NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_frame_protector_protect_flush(NULL, NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_frame_protector_unprotect(NULL, NULL, NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); +} + +static void test_handshaker_invalid_args(void) { + GPR_ASSERT(tsi_handshaker_get_result(NULL) == TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_handshaker_extract_peer(NULL, NULL) == TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_handshaker_create_frame_protector(NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_handshaker_process_bytes_from_peer(NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); + GPR_ASSERT(tsi_handshaker_get_bytes_to_send_to_peer(NULL, NULL, NULL) == + TSI_INVALID_ARGUMENT); +} + +static void test_handshaker_invalid_state(void) { + tsi_handshaker *h = tsi_create_fake_handshaker(0); + tsi_peer peer; + tsi_frame_protector *p; + GPR_ASSERT(tsi_handshaker_extract_peer(h, &peer) == TSI_FAILED_PRECONDITION); + GPR_ASSERT(tsi_handshaker_create_frame_protector(h, NULL, &p) == + TSI_FAILED_PRECONDITION); + tsi_handshaker_destroy(h); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_peer_matches_name(); + test_result_strings(); + test_protector_invalid_args(); + test_handshaker_invalid_args(); + test_handshaker_invalid_state(); return 0; } diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c index ee481ef674..28e521221b 100644 --- a/test/core/util/reconnect_server.c +++ b/test/core/util/reconnect_server.c @@ -44,6 +44,7 @@ #include "src/core/iomgr/sockaddr.h" #include "src/core/iomgr/tcp_server.h" #include "test/core/util/port.h" +#include "test/core/util/test_tcp_server.h" static void pretty_print_backoffs(reconnect_server *server) { gpr_timespec diff; @@ -102,47 +103,18 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp) { } void reconnect_server_init(reconnect_server *server) { - grpc_init(); - server->tcp_server = NULL; - grpc_pollset_init(&server->pollset); - server->pollsets[0] = &server->pollset; + test_tcp_server_init(&server->tcp_server, on_connect, server); server->head = NULL; server->tail = NULL; server->peer = NULL; } void reconnect_server_start(reconnect_server *server, int port) { - struct sockaddr_in addr; - int port_added; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - addr.sin_family = AF_INET; - addr.sin_port = htons((gpr_uint16)port); - memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); - - server->tcp_server = grpc_tcp_server_create(); - port_added = - grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr)); - GPR_ASSERT(port_added == port); - - grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1, - on_connect, server); - gpr_log(GPR_INFO, "reconnect tcp server listening on 0.0.0.0:%d", port); - - grpc_exec_ctx_finish(&exec_ctx); + test_tcp_server_start(&server->tcp_server, port); } void reconnect_server_poll(reconnect_server *server, int seconds) { - grpc_pollset_worker worker; - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_seconds(seconds, GPR_TIMESPAN)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset)); - grpc_pollset_work(&exec_ctx, &server->pollset, &worker, - gpr_now(GPR_CLOCK_MONOTONIC), deadline); - gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset)); - grpc_exec_ctx_finish(&exec_ctx); + test_tcp_server_poll(&server->tcp_server, seconds); } void reconnect_server_clear_timestamps(reconnect_server *server) { @@ -157,18 +129,7 @@ void reconnect_server_clear_timestamps(reconnect_server *server) { server->peer = NULL; } -static void do_nothing(grpc_exec_ctx *exec_ctx, void *ignored, int success) {} - void reconnect_server_destroy(reconnect_server *server) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure do_nothing_closure[2]; - grpc_closure_init(&do_nothing_closure[0], do_nothing, NULL); - grpc_closure_init(&do_nothing_closure[1], do_nothing, NULL); - grpc_tcp_server_destroy(&exec_ctx, server->tcp_server, - &do_nothing_closure[0]); reconnect_server_clear_timestamps(server); - grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_closure[1]); - grpc_exec_ctx_finish(&exec_ctx); - grpc_pollset_destroy(&server->pollset); - grpc_shutdown(); + test_tcp_server_destroy(&server->tcp_server); } diff --git a/test/core/util/reconnect_server.h b/test/core/util/reconnect_server.h index 8a278e0c7a..e2e6a02461 100644 --- a/test/core/util/reconnect_server.h +++ b/test/core/util/reconnect_server.h @@ -36,7 +36,7 @@ #include <grpc/support/sync.h> #include <grpc/support/time.h> -#include "src/core/iomgr/tcp_server.h" +#include "test/core/util/test_tcp_server.h" #ifdef __cplusplus extern "C" { @@ -48,9 +48,7 @@ typedef struct timestamp_list { } timestamp_list; typedef struct reconnect_server { - grpc_tcp_server *tcp_server; - grpc_pollset pollset; - grpc_pollset *pollsets[1]; + test_tcp_server tcp_server; timestamp_list *head; timestamp_list *tail; char *peer; 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() {} diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c new file mode 100644 index 0000000000..c700d3637f --- /dev/null +++ b/test/core/util/test_tcp_server.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/util/test_tcp_server.h" + +#include <grpc/grpc.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/time.h> +#include <string.h> +#include "src/core/iomgr/endpoint.h" +#include "src/core/iomgr/sockaddr.h" +#include "src/core/iomgr/tcp_server.h" +#include "test/core/util/port.h" + +void test_tcp_server_init(test_tcp_server *server, + grpc_tcp_server_cb on_connect, void *user_data) { + grpc_init(); + server->tcp_server = NULL; + server->shutdown = 0; + grpc_pollset_init(&server->pollset); + server->pollsets[0] = &server->pollset; + server->on_connect = on_connect; + server->cb_data = user_data; +} + +void test_tcp_server_start(test_tcp_server *server, int port) { + struct sockaddr_in addr; + grpc_tcp_listener *listener; + int port_added; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + addr.sin_family = AF_INET; + addr.sin_port = htons((gpr_uint16)port); + memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); + + server->tcp_server = grpc_tcp_server_create(); + listener = grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr)); + port_added = grpc_tcp_listener_get_port(listener); + GPR_ASSERT(port_added == port); + + grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1, + server->on_connect, server->cb_data); + gpr_log(GPR_INFO, "test tcp server listening on 0.0.0.0:%d", port); + + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_tcp_server_poll(test_tcp_server *server, int seconds) { + grpc_pollset_worker worker; + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(seconds, GPR_TIMESPAN)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset)); + grpc_pollset_work(&exec_ctx, &server->pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), deadline); + gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset)); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data, + int success) { + test_tcp_server *server = data; + server->shutdown = 1; +} + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {} + +void test_tcp_server_destroy(test_tcp_server *server) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_timespec shutdown_deadline; + grpc_closure server_shutdown_cb; + grpc_closure do_nothing_cb; + grpc_closure_init(&server_shutdown_cb, on_server_destroyed, server); + grpc_closure_init(&do_nothing_cb, do_nothing, NULL); + grpc_tcp_server_destroy(&exec_ctx, server->tcp_server, &server_shutdown_cb); + shutdown_deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(5, GPR_TIMESPAN)); + while (!server->shutdown && + gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), shutdown_deadline) < 0) { + test_tcp_server_poll(server, 1); + } + grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_cb); + grpc_exec_ctx_finish(&exec_ctx); + grpc_pollset_destroy(&server->pollset); + grpc_shutdown(); +} diff --git a/test/core/util/test_tcp_server.h b/test/core/util/test_tcp_server.h new file mode 100644 index 0000000000..deb65eef11 --- /dev/null +++ b/test/core/util/test_tcp_server.h @@ -0,0 +1,55 @@ +/* + * + * 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_UTIL_TEST_TCP_SERVER_H +#define GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H + +#include <grpc/support/sync.h> +#include "src/core/iomgr/tcp_server.h" + +typedef struct test_tcp_server { + grpc_tcp_server *tcp_server; + int shutdown; + grpc_pollset pollset; + grpc_pollset *pollsets[1]; + grpc_tcp_server_cb on_connect; + void *cb_data; +} test_tcp_server; + +void test_tcp_server_init(test_tcp_server *server, + grpc_tcp_server_cb on_connect, void *user_data); +void test_tcp_server_start(test_tcp_server *server, int port); +void test_tcp_server_poll(test_tcp_server *server, int seconds); +void test_tcp_server_destroy(test_tcp_server *server); + +#endif /* GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H */ |