From 04f404922dc2a98472d4299b973e7a81e7f19886 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 21 Oct 2017 16:06:18 -0700 Subject: Class-ify lockfree event --- src/core/lib/iomgr/lockfree_event.cc | 111 ++++++++++++++++------------------- src/core/lib/iomgr/lockfree_event.h | 47 ++++++++------- 2 files changed, 75 insertions(+), 83 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index f967b22ba9..549747b34b 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -26,92 +26,79 @@ extern grpc_tracer_flag grpc_polling_trace; /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: - CLOSURE_READY : The fd has an I/O event of interest but there is no + kClosureReady : The fd has an I/O event of interest but there is no closure yet to execute - CLOSURE_NOT_READY : The fd has no I/O event of interest + kClosureNotReady : The fd has no I/O event of interest closure ptr : The closure to be executed when the fd has an I/O event of interest - shutdown_error | FD_SHUTDOWN_BIT : - 'shutdown_error' field ORed with FD_SHUTDOWN_BIT. + shutdown_error | kShutdownBit : + 'shutdown_error' field ORed with kShutdownBit. This indicates that the fd is shutdown. Since all memory allocations are word-aligned, the lower two bits of the shutdown_error pointer are always 0. So - it is safe to OR these with FD_SHUTDOWN_BIT + it is safe to OR these with kShutdownBit Valid state transitions: - <-----3------ CLOSURE_NOT_READY ----1----> CLOSURE_READY + <-----3------ kClosureNotReady -----1-------> kClosureReady | | ^ | ^ | | | | | | | | | | +--------------4----------+ 6 +---------2---------------+ | | | | | v | - +-----5-------> [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+ + +-----5-------> [shutdown_error | kShutdownBit] <-------7---------+ - For 1, 4 : See grpc_lfev_set_ready() function - For 2, 3 : See grpc_lfev_notify_on() function - For 5,6,7: See grpc_lfev_set_shutdown() function */ + For 1, 4 : See SetReady() function + For 2, 3 : See NotifyOn() function + For 5,6,7: See SetShutdown() function */ -#define CLOSURE_NOT_READY ((gpr_atm)0) -#define CLOSURE_READY ((gpr_atm)2) +namespace grpc_core { -#define FD_SHUTDOWN_BIT ((gpr_atm)1) - -void grpc_lfev_init(gpr_atm *state) { - gpr_atm_no_barrier_store(state, CLOSURE_NOT_READY); -} - -void grpc_lfev_destroy(gpr_atm *state) { - gpr_atm curr = gpr_atm_no_barrier_load(state); - if (curr & FD_SHUTDOWN_BIT) { - GRPC_ERROR_UNREF((grpc_error *)(curr & ~FD_SHUTDOWN_BIT)); +LockfreeEvent::~LockfreeEvent() { + gpr_atm curr = gpr_atm_no_barrier_load(&state_); + if (curr & kShutdownBit) { + GRPC_ERROR_UNREF((grpc_error *)(curr & ~kShutdownBit)); } else { - GPR_ASSERT(curr == CLOSURE_NOT_READY || curr == CLOSURE_READY); + GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); } } -bool grpc_lfev_is_shutdown(gpr_atm *state) { - gpr_atm curr = gpr_atm_no_barrier_load(state); - return (curr & FD_SHUTDOWN_BIT) != 0; -} - -void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, - grpc_closure *closure, const char *variable) { +void LockfreeEvent::NotifyOn(grpc_exec_ctx *exec_ctx, grpc_closure *closure) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_notify_on[%s]: %p curr=%p closure=%p", variable, - state, (void *)curr, closure); + gpr_log(GPR_ERROR, "lfev_notify_on: %p curr=%p closure=%p", this, + (void *)curr, closure); } switch (curr) { - case CLOSURE_NOT_READY: { - /* CLOSURE_NOT_READY -> . + case kClosureNotReady: { + /* kClosureNotReady -> . We're guaranteed by API that there's an acquire barrier before here, so there's no need to double-dip and this can be a release-only. The release itself pairs with the acquire half of a set_ready full barrier. */ - if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) { + if (gpr_atm_rel_cas(&state_, kClosureNotReady, (gpr_atm)closure)) { return; /* Successful. Return */ } break; /* retry */ } - case CLOSURE_READY: { - /* Change the state to CLOSURE_NOT_READY. Schedule the closure if + case kClosureReady: { + /* Change the state to kClosureNotReady. Schedule the closure if successful. If not, the state most likely transitioned to shutdown. We should retry. This can be a no-barrier cas since the state is being transitioned to - CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any + kClosureNotReady; set_ready and set_shutdown do not schedule any closure when transitioning out of CLOSURE_NO_READY state (i.e there is no other code that needs to 'happen-after' this) */ - if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) { + if (gpr_atm_no_barrier_cas(&state_, kClosureReady, kClosureNotReady)) { GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_NONE); return; /* Successful. Return */ } @@ -123,8 +110,8 @@ void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, /* 'curr' is either a closure or the fd is shutdown(in which case 'curr' contains a pointer to the shutdown-error). If the fd is shutdown, schedule the closure with the shutdown error */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { - grpc_error *shutdown_err = (grpc_error *)(curr & ~FD_SHUTDOWN_BIT); + if ((curr & kShutdownBit) > 0) { + grpc_error *shutdown_err = (grpc_error *)(curr & ~kShutdownBit); GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -142,22 +129,22 @@ void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, GPR_UNREACHABLE_CODE(return ); } -bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, - grpc_error *shutdown_err) { - gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT; +bool LockfreeEvent::SetShutdown(grpc_exec_ctx *exec_ctx, + grpc_error *shutdown_err) { + gpr_atm new_state = (gpr_atm)shutdown_err | kShutdownBit; while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", state, + gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", &state_, (void *)curr, grpc_error_string(shutdown_err)); } switch (curr) { - case CLOSURE_READY: - case CLOSURE_NOT_READY: + case kClosureReady: + case kClosureNotReady: /* Need a full barrier here so that the initial load in notify_on doesn't need a barrier */ - if (gpr_atm_full_cas(state, curr, new_state)) { + if (gpr_atm_full_cas(&state_, curr, new_state)) { return true; /* early out */ } break; /* retry */ @@ -166,7 +153,7 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, /* 'curr' is either a closure or the fd is already shutdown */ /* If fd is already shutdown, we are done */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { + if ((curr & kShutdownBit) > 0) { GRPC_ERROR_UNREF(shutdown_err); return false; } @@ -176,7 +163,7 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, Needs an acquire to pair with setting the closure (and get a happens-after on that edge), and a release to pair with anything loading the shutdown state. */ - if (gpr_atm_full_cas(state, curr, new_state)) { + if (gpr_atm_full_cas(&state_, curr, new_state)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -193,26 +180,24 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, GPR_UNREACHABLE_CODE(return false); } -void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state, - const char *variable) { +void LockfreeEvent::SetReady(grpc_exec_ctx *exec_ctx) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_ready[%s]: %p curr=%p", variable, state, - (void *)curr); + gpr_log(GPR_ERROR, "lfev_set_ready: %p curr=%p", &state_, (void *)curr); } switch (curr) { - case CLOSURE_READY: { + case kClosureReady: { /* Already ready. We are done here */ return; } - case CLOSURE_NOT_READY: { + case kClosureNotReady: { /* No barrier required as we're transitioning to a state that does not involve a closure */ - if (gpr_atm_no_barrier_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) { + if (gpr_atm_no_barrier_cas(&state_, kClosureNotReady, kClosureReady)) { return; /* early out */ } break; /* retry */ @@ -220,14 +205,14 @@ void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state, default: { /* 'curr' is either a closure or the fd is shutdown */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { + if ((curr & kShutdownBit) > 0) { /* The fd is shutdown. Do nothing */ return; } /* Full cas: acquire pairs with this cas' release in the event of a spurious set_ready; release pairs with this or the acquire in notify_on (or set_shutdown) */ - else if (gpr_atm_full_cas(state, curr, CLOSURE_NOT_READY)) { + else if (gpr_atm_full_cas(&state_, curr, kClosureNotReady)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE); return; } @@ -239,3 +224,5 @@ void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state, } } } + +} // namespace grpc_core diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index 925f004945..d843c340a1 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -25,24 +25,29 @@ #include "src/core/lib/iomgr/exec_ctx.h" -#ifdef __cplusplus -extern "C" { -#endif - -void grpc_lfev_init(gpr_atm *state); -void grpc_lfev_destroy(gpr_atm *state); -bool grpc_lfev_is_shutdown(gpr_atm *state); - -void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, - grpc_closure *closure, const char *variable); -/* Returns true on first successful shutdown */ -bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, - grpc_error *shutdown_err); -void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state, - const char *variable); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */ \ No newline at end of file +namespace grpc_core { + +class LockfreeEvent { + public: + ~LockfreeEvent(); + + LockfreeEvent(const LockfreeEvent &) = delete; + LockfreeEvent &operator=(const LockfreeEvent &) = delete; + + bool IsShutdown() const { + return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0; + } + + void NotifyOn(grpc_exec_ctx *exec_ctx, grpc_closure *closure); + bool SetShutdown(grpc_exec_ctx *exec_ctx, grpc_error *error); + void SetReady(grpc_exec_ctx *exec_ctx); + + private: + enum State { kClosureNotReady = 0, kClosureReady = 2, kShutdownBit = 1 }; + + gpr_atm state_ = kClosureNotReady; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */ -- cgit v1.2.3 From fb222de58fe47e79bfb184ead2483b41d8b9e62e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sun, 22 Oct 2017 04:27:56 -0700 Subject: Convert epollexclusive --- src/core/lib/iomgr/ev_epollex_linux.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index fa6d79cbfc..d7d5f219aa 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -48,6 +48,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/spinlock.h" // debug aid: create workers on the heap (allows asan to spot @@ -153,8 +154,8 @@ struct grpc_fd { gpr_mu pollable_mu; pollable *pollable_obj; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd *freelist_next; grpc_closure *on_done_closure; @@ -286,8 +287,8 @@ static void fd_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { fd->freelist_next = fd_freelist; fd_freelist = fd; - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_unlock(&fd_freelist_mu); } @@ -346,8 +347,8 @@ static grpc_fd *fd_create(int fd, const char *name) { new_fd->pollable_obj = NULL; gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -410,27 +411,26 @@ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, } static bool fd_is_shutdown(grpc_fd *fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } /******************************************************************************* @@ -701,7 +701,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx *exec_ctx, static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -713,7 +713,7 @@ static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, } static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } static grpc_error *fd_get_or_become_pollable(grpc_fd *fd, pollable **p) { -- cgit v1.2.3 From 34a57d0346afe95e11104462c30dc468b0cb0b89 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 23 Oct 2017 15:33:21 -0700 Subject: rename all test core files to cc and a lot of C++ style conversions --- CMakeLists.txt | 704 ++-- Makefile | 754 ++-- build.yaml | 342 +- gRPC-Core.podspec | 18 +- grpc.gyp | 312 +- include/grpc/support/cmdline.h | 2 +- src/core/lib/iomgr/network_status_tracker.h | 8 - src/core/lib/support/cmdline.cc | 2 +- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 2 +- templates/gRPC-Core.podspec.template | 18 +- .../core/end2end/end2end_nosec_tests.c.template | 4 - .../core/end2end/end2end_nosec_tests.cc.template | 4 + .../test/core/end2end/end2end_tests.c.template | 4 - .../test/core/end2end/end2end_tests.cc.template | 4 + test/core/backoff/backoff_test.c | 150 - test/core/backoff/backoff_test.cc | 150 + test/core/bad_client/bad_client.c | 211 -- test/core/bad_client/bad_client.cc | 211 ++ test/core/bad_client/gen_build_yaml.py | 4 +- test/core/bad_client/generate_tests.bzl | 4 +- test/core/bad_client/tests/badreq.c | 125 - test/core/bad_client/tests/badreq.cc | 125 + test/core/bad_client/tests/connection_prefix.c | 60 - test/core/bad_client/tests/connection_prefix.cc | 60 + test/core/bad_client/tests/head_of_line_blocking.c | 136 - .../core/bad_client/tests/head_of_line_blocking.cc | 136 + test/core/bad_client/tests/headers.c | 293 -- test/core/bad_client/tests/headers.cc | 293 ++ .../core/bad_client/tests/initial_settings_frame.c | 108 - .../bad_client/tests/initial_settings_frame.cc | 108 + test/core/bad_client/tests/large_metadata.c | 240 -- test/core/bad_client/tests/large_metadata.cc | 240 ++ .../bad_client/tests/server_registered_method.c | 124 - .../bad_client/tests/server_registered_method.cc | 124 + test/core/bad_client/tests/simple_request.c | 166 - test/core/bad_client/tests/simple_request.cc | 166 + test/core/bad_client/tests/unknown_frame.c | 44 - test/core/bad_client/tests/unknown_frame.cc | 44 + test/core/bad_client/tests/window_overflow.c | 98 - test/core/bad_client/tests/window_overflow.cc | 98 + test/core/bad_ssl/bad_ssl_test.c | 160 - test/core/bad_ssl/bad_ssl_test.cc | 161 + test/core/bad_ssl/gen_build_yaml.py | 6 +- test/core/bad_ssl/generate_tests.bzl | 4 +- test/core/bad_ssl/server_common.c | 103 - test/core/bad_ssl/server_common.cc | 103 + test/core/bad_ssl/servers/alpn.c | 71 - test/core/bad_ssl/servers/alpn.cc | 71 + test/core/bad_ssl/servers/cert.c | 65 - test/core/bad_ssl/servers/cert.cc | 65 + test/core/census/context_test.c | 363 -- test/core/census/context_test.cc | 363 ++ test/core/census/intrusive_hash_map_test.c | 284 -- test/core/census/intrusive_hash_map_test.cc | 284 ++ test/core/census/mlog_test.c | 574 --- test/core/census/mlog_test.cc | 574 +++ test/core/census/resource_test.c | 154 - test/core/census/resource_test.cc | 154 + test/core/census/trace_context_test.c | 215 -- test/core/census/trace_context_test.cc | 215 ++ test/core/channel/channel_args_test.c | 155 - test/core/channel/channel_args_test.cc | 155 + test/core/channel/channel_stack_builder_test.c | 146 - test/core/channel/channel_stack_builder_test.cc | 147 + test/core/channel/channel_stack_test.c | 157 - test/core/channel/channel_stack_test.cc | 162 + test/core/channel/minimal_stack_is_minimal_test.c | 217 -- test/core/channel/minimal_stack_is_minimal_test.cc | 221 ++ test/core/client_channel/lb_policies_test.c | 1009 ------ test/core/client_channel/lb_policies_test.cc | 1033 ++++++ test/core/client_channel/parse_address_test.c | 101 - test/core/client_channel/parse_address_test.cc | 101 + .../resolvers/dns_resolver_connectivity_test.c | 180 - .../resolvers/dns_resolver_connectivity_test.cc | 182 + .../client_channel/resolvers/dns_resolver_test.c | 92 - .../client_channel/resolvers/dns_resolver_test.cc | 92 + .../client_channel/resolvers/fake_resolver_test.c | 177 - .../client_channel/resolvers/fake_resolver_test.cc | 177 + .../resolvers/sockaddr_resolver_test.c | 122 - .../resolvers/sockaddr_resolver_test.cc | 122 + test/core/client_channel/uri_fuzzer_test.c | 44 - test/core/client_channel/uri_fuzzer_test.cc | 44 + test/core/client_channel/uri_parser_test.c | 152 - test/core/client_channel/uri_parser_test.cc | 152 + test/core/compression/algorithm_test.c | 97 - test/core/compression/algorithm_test.cc | 100 + test/core/compression/compression_test.c | 214 -- test/core/compression/compression_test.cc | 220 ++ test/core/compression/message_compress_test.c | 320 -- test/core/compression/message_compress_test.cc | 330 ++ test/core/compression/stream_compression_test.c | 297 -- test/core/compression/stream_compression_test.cc | 298 ++ test/core/end2end/BUILD | 12 +- test/core/end2end/bad_server_response_test.c | 341 -- test/core/end2end/bad_server_response_test.cc | 341 ++ test/core/end2end/connection_refused_test.c | 148 - test/core/end2end/connection_refused_test.cc | 148 + test/core/end2end/cq_verifier.c | 321 -- test/core/end2end/cq_verifier.cc | 321 ++ test/core/end2end/cq_verifier_native.c | 59 - test/core/end2end/cq_verifier_native.cc | 59 + test/core/end2end/cq_verifier_uv.c | 97 - test/core/end2end/cq_verifier_uv.cc | 97 + test/core/end2end/data/client_certs.c | 328 -- test/core/end2end/data/client_certs.cc | 330 ++ test/core/end2end/data/server1_cert.c | 100 - test/core/end2end/data/server1_cert.cc | 102 + test/core/end2end/data/server1_key.c | 93 - test/core/end2end/data/server1_key.cc | 95 + test/core/end2end/data/ssl_test_data.h | 8 - test/core/end2end/data/test_root_cert.c | 86 - test/core/end2end/data/test_root_cert.cc | 88 + test/core/end2end/dualstack_socket_test.c | 357 -- test/core/end2end/dualstack_socket_test.cc | 358 ++ test/core/end2end/end2end_nosec_tests.c | 518 --- test/core/end2end/end2end_nosec_tests.cc | 518 +++ test/core/end2end/end2end_test_utils.c | 50 - test/core/end2end/end2end_test_utils.cc | 50 + test/core/end2end/end2end_tests.c | 526 --- test/core/end2end/end2end_tests.cc | 526 +++ test/core/end2end/fixtures/h2_census.c | 129 - test/core/end2end/fixtures/h2_census.cc | 133 + test/core/end2end/fixtures/h2_compress.c | 131 - test/core/end2end/fixtures/h2_compress.cc | 135 + test/core/end2end/fixtures/h2_fakesec.c | 151 - test/core/end2end/fixtures/h2_fakesec.cc | 155 + test/core/end2end/fixtures/h2_fd.c | 125 - test/core/end2end/fixtures/h2_fd.cc | 126 + test/core/end2end/fixtures/h2_full+pipe.c | 120 - test/core/end2end/fixtures/h2_full+pipe.cc | 124 + test/core/end2end/fixtures/h2_full+trace.c | 126 - test/core/end2end/fixtures/h2_full+trace.cc | 130 + test/core/end2end/fixtures/h2_full+workarounds.c | 123 - test/core/end2end/fixtures/h2_full+workarounds.cc | 127 + test/core/end2end/fixtures/h2_full.c | 106 - test/core/end2end/fixtures/h2_full.cc | 110 + test/core/end2end/fixtures/h2_http_proxy.c | 128 - test/core/end2end/fixtures/h2_http_proxy.cc | 132 + test/core/end2end/fixtures/h2_load_reporting.c | 117 - test/core/end2end/fixtures/h2_load_reporting.cc | 120 + test/core/end2end/fixtures/h2_oauth2.c | 229 -- test/core/end2end/fixtures/h2_oauth2.cc | 235 ++ test/core/end2end/fixtures/h2_proxy.c | 124 - test/core/end2end/fixtures/h2_proxy.cc | 128 + test/core/end2end/fixtures/h2_sockpair+trace.c | 162 - test/core/end2end/fixtures/h2_sockpair+trace.cc | 163 + test/core/end2end/fixtures/h2_sockpair.c | 141 - test/core/end2end/fixtures/h2_sockpair.cc | 142 + test/core/end2end/fixtures/h2_sockpair_1byte.c | 154 - test/core/end2end/fixtures/h2_sockpair_1byte.cc | 156 + test/core/end2end/fixtures/h2_ssl.c | 183 - test/core/end2end/fixtures/h2_ssl.cc | 188 + test/core/end2end/fixtures/h2_ssl_proxy.c | 221 -- test/core/end2end/fixtures/h2_ssl_proxy.cc | 227 ++ test/core/end2end/fixtures/h2_uds.c | 111 - test/core/end2end/fixtures/h2_uds.cc | 115 + test/core/end2end/fixtures/http_proxy_fixture.c | 550 --- test/core/end2end/fixtures/http_proxy_fixture.cc | 550 +++ test/core/end2end/fixtures/inproc.c | 96 - test/core/end2end/fixtures/inproc.cc | 98 + test/core/end2end/fixtures/proxy.c | 437 --- test/core/end2end/fixtures/proxy.cc | 437 +++ test/core/end2end/fuzzers/api_fuzzer.c | 1220 ------- test/core/end2end/fuzzers/api_fuzzer.cc | 1227 +++++++ test/core/end2end/fuzzers/client_fuzzer.c | 157 - test/core/end2end/fuzzers/client_fuzzer.cc | 157 + test/core/end2end/fuzzers/server_fuzzer.c | 123 - test/core/end2end/fuzzers/server_fuzzer.cc | 123 + test/core/end2end/gen_build_yaml.py | 16 +- test/core/end2end/generate_tests.bzl | 6 +- test/core/end2end/goaway_server_test.c | 355 -- test/core/end2end/goaway_server_test.cc | 359 ++ test/core/end2end/invalid_call_argument_test.c | 615 ---- test/core/end2end/invalid_call_argument_test.cc | 615 ++++ test/core/end2end/multiple_server_queues_test.c | 71 - test/core/end2end/multiple_server_queues_test.cc | 71 + test/core/end2end/no_server_test.c | 95 - test/core/end2end/no_server_test.cc | 95 + test/core/end2end/tests/authority_not_supported.c | 188 - test/core/end2end/tests/authority_not_supported.cc | 188 + test/core/end2end/tests/bad_hostname.c | 171 - test/core/end2end/tests/bad_hostname.cc | 171 + test/core/end2end/tests/bad_ping.c | 227 -- test/core/end2end/tests/bad_ping.cc | 227 ++ test/core/end2end/tests/binary_metadata.c | 320 -- test/core/end2end/tests/binary_metadata.cc | 320 ++ test/core/end2end/tests/call_creds.c | 477 --- test/core/end2end/tests/call_creds.cc | 479 +++ test/core/end2end/tests/cancel_after_accept.c | 271 -- test/core/end2end/tests/cancel_after_accept.cc | 271 ++ test/core/end2end/tests/cancel_after_client_done.c | 235 -- .../core/end2end/tests/cancel_after_client_done.cc | 235 ++ test/core/end2end/tests/cancel_after_invoke.c | 195 -- test/core/end2end/tests/cancel_after_invoke.cc | 195 ++ test/core/end2end/tests/cancel_after_round_trip.c | 304 -- test/core/end2end/tests/cancel_after_round_trip.cc | 304 ++ test/core/end2end/tests/cancel_before_invoke.c | 190 - test/core/end2end/tests/cancel_before_invoke.cc | 190 + test/core/end2end/tests/cancel_in_a_vacuum.c | 123 - test/core/end2end/tests/cancel_in_a_vacuum.cc | 123 + test/core/end2end/tests/cancel_with_status.c | 183 - test/core/end2end/tests/cancel_with_status.cc | 183 + test/core/end2end/tests/compressed_payload.c | 648 ---- test/core/end2end/tests/compressed_payload.cc | 648 ++++ test/core/end2end/tests/connectivity.c | 172 - test/core/end2end/tests/connectivity.cc | 173 + test/core/end2end/tests/default_host.c | 225 -- test/core/end2end/tests/default_host.cc | 225 ++ test/core/end2end/tests/disappearing_server.c | 211 -- test/core/end2end/tests/disappearing_server.cc | 211 ++ test/core/end2end/tests/empty_batch.c | 127 - test/core/end2end/tests/empty_batch.cc | 127 + test/core/end2end/tests/filter_call_init_fails.c | 531 --- test/core/end2end/tests/filter_call_init_fails.cc | 531 +++ test/core/end2end/tests/filter_causes_close.c | 282 -- test/core/end2end/tests/filter_causes_close.cc | 282 ++ test/core/end2end/tests/filter_latency.c | 356 -- test/core/end2end/tests/filter_latency.cc | 356 ++ test/core/end2end/tests/graceful_server_shutdown.c | 206 -- .../core/end2end/tests/graceful_server_shutdown.cc | 206 ++ test/core/end2end/tests/high_initial_seqno.c | 239 -- test/core/end2end/tests/high_initial_seqno.cc | 239 ++ test/core/end2end/tests/hpack_size.c | 397 --- test/core/end2end/tests/hpack_size.cc | 397 +++ test/core/end2end/tests/idempotent_request.c | 242 -- test/core/end2end/tests/idempotent_request.cc | 242 ++ test/core/end2end/tests/invoke_large_request.c | 285 -- test/core/end2end/tests/invoke_large_request.cc | 285 ++ test/core/end2end/tests/keepalive_timeout.c | 227 -- test/core/end2end/tests/keepalive_timeout.cc | 228 ++ test/core/end2end/tests/large_metadata.c | 252 -- test/core/end2end/tests/large_metadata.cc | 253 ++ test/core/end2end/tests/load_reporting_hook.c | 314 -- test/core/end2end/tests/load_reporting_hook.cc | 314 ++ test/core/end2end/tests/max_concurrent_streams.c | 831 ----- test/core/end2end/tests/max_concurrent_streams.cc | 831 +++++ test/core/end2end/tests/max_connection_age.c | 366 -- test/core/end2end/tests/max_connection_age.cc | 366 ++ test/core/end2end/tests/max_connection_idle.c | 240 -- test/core/end2end/tests/max_connection_idle.cc | 241 ++ test/core/end2end/tests/max_message_length.c | 507 --- test/core/end2end/tests/max_message_length.cc | 511 +++ test/core/end2end/tests/negative_deadline.c | 172 - test/core/end2end/tests/negative_deadline.cc | 172 + test/core/end2end/tests/network_status_change.c | 239 -- test/core/end2end/tests/network_status_change.cc | 239 ++ test/core/end2end/tests/no_logging.c | 296 -- test/core/end2end/tests/no_logging.cc | 296 ++ test/core/end2end/tests/no_op.c | 95 - test/core/end2end/tests/no_op.cc | 95 + test/core/end2end/tests/payload.c | 288 -- test/core/end2end/tests/payload.cc | 288 ++ test/core/end2end/tests/ping.c | 118 - test/core/end2end/tests/ping.cc | 118 + test/core/end2end/tests/ping_pong_streaming.c | 276 -- test/core/end2end/tests/ping_pong_streaming.cc | 276 ++ test/core/end2end/tests/proxy_auth.c | 235 -- test/core/end2end/tests/proxy_auth.cc | 236 ++ test/core/end2end/tests/registered_call.c | 227 -- test/core/end2end/tests/registered_call.cc | 227 ++ test/core/end2end/tests/request_with_flags.c | 208 -- test/core/end2end/tests/request_with_flags.cc | 208 ++ test/core/end2end/tests/request_with_payload.c | 230 -- test/core/end2end/tests/request_with_payload.cc | 230 ++ test/core/end2end/tests/resource_quota_server.c | 377 -- test/core/end2end/tests/resource_quota_server.cc | 377 ++ test/core/end2end/tests/server_finishes_request.c | 206 -- test/core/end2end/tests/server_finishes_request.cc | 206 ++ test/core/end2end/tests/shutdown_finishes_calls.c | 189 - test/core/end2end/tests/shutdown_finishes_calls.cc | 189 + test/core/end2end/tests/shutdown_finishes_tags.c | 110 - test/core/end2end/tests/shutdown_finishes_tags.cc | 110 + test/core/end2end/tests/simple_cacheable_request.c | 280 -- .../core/end2end/tests/simple_cacheable_request.cc | 280 ++ test/core/end2end/tests/simple_delayed_request.c | 233 -- test/core/end2end/tests/simple_delayed_request.cc | 235 ++ test/core/end2end/tests/simple_metadata.c | 272 -- test/core/end2end/tests/simple_metadata.cc | 272 ++ test/core/end2end/tests/simple_request.c | 266 -- test/core/end2end/tests/simple_request.cc | 268 ++ .../tests/stream_compression_compressed_payload.c | 653 ---- .../tests/stream_compression_compressed_payload.cc | 653 ++++ .../end2end/tests/stream_compression_payload.c | 305 -- .../end2end/tests/stream_compression_payload.cc | 305 ++ .../tests/stream_compression_ping_pong_streaming.c | 291 -- .../stream_compression_ping_pong_streaming.cc | 291 ++ test/core/end2end/tests/streaming_error_response.c | 270 -- .../core/end2end/tests/streaming_error_response.cc | 270 ++ test/core/end2end/tests/trailing_metadata.c | 282 -- test/core/end2end/tests/trailing_metadata.cc | 282 ++ .../end2end/tests/workaround_cronet_compression.c | 396 --- .../end2end/tests/workaround_cronet_compression.cc | 399 +++ test/core/end2end/tests/write_buffering.c | 280 -- test/core/end2end/tests/write_buffering.cc | 280 ++ test/core/end2end/tests/write_buffering_at_end.c | 269 -- test/core/end2end/tests/write_buffering_at_end.cc | 269 ++ test/core/fling/client.c | 244 -- test/core/fling/client.cc | 244 ++ test/core/fling/fling_stream_test.c | 79 - test/core/fling/fling_stream_test.cc | 79 + test/core/fling/fling_test.c | 79 - test/core/fling/fling_test.cc | 79 + test/core/fling/server.c | 324 -- test/core/fling/server.cc | 324 ++ test/core/handshake/client_ssl.c | 323 -- test/core/handshake/client_ssl.cc | 323 ++ test/core/handshake/server_ssl.c | 255 -- test/core/handshake/server_ssl.cc | 256 ++ test/core/http/format_request_test.c | 149 - test/core/http/format_request_test.cc | 152 + test/core/http/httpcli_test.c | 209 -- test/core/http/httpcli_test.cc | 211 ++ test/core/http/httpscli_test.c | 212 -- test/core/http/httpscli_test.cc | 214 ++ test/core/http/parser_test.c | 299 -- test/core/http/parser_test.cc | 304 ++ test/core/http/request_fuzzer.c | 42 - test/core/http/request_fuzzer.cc | 42 + test/core/http/response_fuzzer.c | 41 - test/core/http/response_fuzzer.cc | 41 + test/core/iomgr/combiner_test.c | 167 - test/core/iomgr/combiner_test.cc | 168 + test/core/iomgr/endpoint_pair_test.c | 77 - test/core/iomgr/endpoint_pair_test.cc | 78 + test/core/iomgr/endpoint_tests.c | 335 -- test/core/iomgr/endpoint_tests.cc | 335 ++ test/core/iomgr/error_test.c | 245 -- test/core/iomgr/error_test.cc | 245 ++ test/core/iomgr/ev_epollsig_linux_test.c | 330 -- test/core/iomgr/ev_epollsig_linux_test.cc | 331 ++ test/core/iomgr/fd_conservation_posix_test.c | 56 - test/core/iomgr/fd_conservation_posix_test.cc | 56 + test/core/iomgr/fd_posix_test.c | 545 --- test/core/iomgr/fd_posix_test.cc | 545 +++ test/core/iomgr/load_file_test.c | 160 - test/core/iomgr/load_file_test.cc | 160 + test/core/iomgr/pollset_set_test.c | 458 --- test/core/iomgr/pollset_set_test.cc | 459 +++ test/core/iomgr/resolve_address_posix_test.c | 170 - test/core/iomgr/resolve_address_posix_test.cc | 171 + test/core/iomgr/resolve_address_test.c | 268 -- test/core/iomgr/resolve_address_test.cc | 268 ++ test/core/iomgr/resource_quota_test.c | 864 ----- test/core/iomgr/resource_quota_test.cc | 864 +++++ test/core/iomgr/sockaddr_utils_test.c | 279 -- test/core/iomgr/sockaddr_utils_test.cc | 279 ++ test/core/iomgr/socket_utils_test.c | 132 - test/core/iomgr/socket_utils_test.cc | 132 + test/core/iomgr/tcp_client_posix_test.c | 223 -- test/core/iomgr/tcp_client_posix_test.cc | 223 ++ test/core/iomgr/tcp_client_uv_test.c | 216 -- test/core/iomgr/tcp_client_uv_test.cc | 216 ++ test/core/iomgr/tcp_posix_test.c | 577 --- test/core/iomgr/tcp_posix_test.cc | 580 ++++ test/core/iomgr/tcp_server_posix_test.c | 509 --- test/core/iomgr/tcp_server_posix_test.cc | 512 +++ test/core/iomgr/tcp_server_uv_test.c | 325 -- test/core/iomgr/tcp_server_uv_test.cc | 325 ++ test/core/iomgr/time_averaged_stats_test.c | 193 -- test/core/iomgr/time_averaged_stats_test.cc | 193 ++ test/core/iomgr/timer_heap_test.c | 304 -- test/core/iomgr/timer_heap_test.cc | 307 ++ test/core/iomgr/timer_list_test.c | 167 - test/core/iomgr/timer_list_test.cc | 167 + test/core/iomgr/udp_server_test.c | 327 -- test/core/iomgr/udp_server_test.cc | 328 ++ test/core/iomgr/wakeup_fd_cv_test.c | 234 -- test/core/iomgr/wakeup_fd_cv_test.cc | 234 ++ test/core/json/fuzzer.c | 47 - test/core/json/fuzzer.cc | 47 + test/core/json/json_rewrite.c | 237 -- test/core/json/json_rewrite.cc | 239 ++ test/core/json/json_rewrite_test.c | 290 -- test/core/json/json_rewrite_test.cc | 292 ++ test/core/json/json_stream_error_test.c | 57 - test/core/json/json_stream_error_test.cc | 57 + test/core/json/json_test.c | 191 - test/core/json/json_test.cc | 191 + test/core/memory_usage/client.c | 329 -- test/core/memory_usage/client.cc | 329 ++ test/core/memory_usage/memory_usage_test.c | 78 - test/core/memory_usage/memory_usage_test.cc | 78 + test/core/memory_usage/server.c | 315 -- test/core/memory_usage/server.cc | 315 ++ test/core/nanopb/fuzzer_response.c | 40 - test/core/nanopb/fuzzer_response.cc | 40 + test/core/nanopb/fuzzer_serverlist.c | 40 - test/core/nanopb/fuzzer_serverlist.cc | 40 + test/core/network_benchmarks/low_level_ping_pong.c | 684 ---- .../core/network_benchmarks/low_level_ping_pong.cc | 684 ++++ test/core/security/auth_context_test.c | 138 - test/core/security/auth_context_test.cc | 138 + test/core/security/create_jwt.c | 93 - test/core/security/create_jwt.cc | 93 + test/core/security/credentials_test.c | 1216 ------- test/core/security/credentials_test.cc | 1219 +++++++ test/core/security/fetch_oauth2.c | 104 - test/core/security/fetch_oauth2.cc | 104 + test/core/security/json_token_test.c | 501 --- test/core/security/json_token_test.cc | 501 +++ test/core/security/jwt_verifier_test.c | 634 ---- test/core/security/jwt_verifier_test.cc | 634 ++++ test/core/security/oauth2_utils.c | 118 - test/core/security/oauth2_utils.cc | 118 + .../security/print_google_default_creds_token.c | 130 - .../security/print_google_default_creds_token.cc | 132 + test/core/security/secure_endpoint_test.c | 229 -- test/core/security/secure_endpoint_test.cc | 230 ++ test/core/security/security_connector_test.c | 405 --- test/core/security/security_connector_test.cc | 405 +++ test/core/security/ssl_server_fuzzer.c | 125 - test/core/security/ssl_server_fuzzer.cc | 126 + test/core/security/verify_jwt.c | 122 - test/core/security/verify_jwt.cc | 122 + test/core/slice/b64_test.c | 219 -- test/core/slice/b64_test.cc | 219 ++ test/core/slice/percent_decode_fuzzer.c | 51 - test/core/slice/percent_decode_fuzzer.cc | 51 + test/core/slice/percent_encode_fuzzer.c | 58 - test/core/slice/percent_encode_fuzzer.cc | 58 + test/core/slice/percent_encoding_test.c | 144 - test/core/slice/percent_encoding_test.cc | 144 + test/core/slice/slice_buffer_test.c | 114 - test/core/slice/slice_buffer_test.cc | 114 + test/core/slice/slice_hash_table_test.c | 241 -- test/core/slice/slice_hash_table_test.cc | 243 ++ test/core/slice/slice_string_helpers_test.c | 135 - test/core/slice/slice_string_helpers_test.cc | 136 + test/core/slice/slice_test.c | 309 -- test/core/slice/slice_test.cc | 309 ++ test/core/statistics/census_log_tests.c | 576 --- test/core/statistics/census_log_tests.cc | 576 +++ test/core/statistics/census_stub_test.c | 62 - test/core/statistics/census_stub_test.cc | 62 + test/core/statistics/hash_table_test.c | 286 -- test/core/statistics/hash_table_test.cc | 286 ++ .../multiple_writers_circular_buffer_test.c | 31 - .../multiple_writers_circular_buffer_test.cc | 31 + test/core/statistics/multiple_writers_test.c | 31 - test/core/statistics/multiple_writers_test.cc | 31 + test/core/statistics/performance_test.c | 31 - test/core/statistics/performance_test.cc | 31 + test/core/statistics/quick_test.c | 39 - test/core/statistics/quick_test.cc | 39 + test/core/statistics/rpc_stats_test.c | 183 - test/core/statistics/rpc_stats_test.cc | 183 + test/core/statistics/small_log_test.c | 31 - test/core/statistics/small_log_test.cc | 31 + test/core/statistics/trace_test.c | 240 -- test/core/statistics/trace_test.cc | 240 ++ test/core/statistics/window_stats_test.c | 303 -- test/core/statistics/window_stats_test.cc | 303 ++ test/core/support/alloc_test.c | 55 - test/core/support/alloc_test.cc | 56 + test/core/support/arena_test.c | 128 - test/core/support/arena_test.cc | 128 + test/core/support/avl_test.c | 3659 -------------------- test/core/support/avl_test.cc | 3659 ++++++++++++++++++++ test/core/support/cmdline_test.c | 481 --- test/core/support/cmdline_test.cc | 492 +++ test/core/support/cpu_test.c | 135 - test/core/support/cpu_test.cc | 135 + test/core/support/env_test.c | 49 - test/core/support/env_test.cc | 49 + test/core/support/histogram_test.c | 163 - test/core/support/histogram_test.cc | 163 + test/core/support/host_port_test.c | 58 - test/core/support/host_port_test.cc | 58 + test/core/support/log_test.c | 108 - test/core/support/log_test.cc | 108 + test/core/support/mpscq_test.c | 191 - test/core/support/mpscq_test.cc | 191 + test/core/support/murmur_hash_test.c | 73 - test/core/support/murmur_hash_test.cc | 73 + test/core/support/spinlock_test.c | 146 - test/core/support/spinlock_test.cc | 147 + test/core/support/stack_lockfree_test.c | 140 - test/core/support/stack_lockfree_test.cc | 140 + test/core/support/string_test.c | 312 -- test/core/support/string_test.cc | 312 ++ test/core/support/sync_test.c | 453 --- test/core/support/sync_test.cc | 453 +++ test/core/support/thd_test.c | 101 - test/core/support/thd_test.cc | 101 + test/core/support/time_test.c | 255 -- test/core/support/time_test.cc | 255 ++ test/core/support/tls_test.c | 68 - test/core/support/tls_test.cc | 68 + test/core/support/useful_test.c | 58 - test/core/support/useful_test.cc | 58 + test/core/surface/alarm_test.c | 105 - test/core/surface/alarm_test.cc | 105 + test/core/surface/byte_buffer_reader_test.c | 280 -- test/core/surface/byte_buffer_reader_test.cc | 280 ++ test/core/surface/channel_create_test.c | 53 - test/core/surface/channel_create_test.cc | 53 + test/core/surface/completion_queue_test.c | 305 -- test/core/surface/completion_queue_test.cc | 305 ++ .../core/surface/completion_queue_threading_test.c | 293 -- .../surface/completion_queue_threading_test.cc | 294 ++ test/core/surface/concurrent_connectivity_test.c | 293 -- test/core/surface/concurrent_connectivity_test.cc | 293 ++ test/core/surface/init_test.c | 71 - test/core/surface/init_test.cc | 71 + test/core/surface/invalid_channel_args_test.c | 137 - test/core/surface/invalid_channel_args_test.cc | 137 + test/core/surface/lame_client_test.c | 156 - test/core/surface/lame_client_test.cc | 156 + .../num_external_connectivity_watchers_test.c | 199 -- .../num_external_connectivity_watchers_test.cc | 200 ++ test/core/surface/secure_channel_create_test.c | 81 - test/core/surface/secure_channel_create_test.cc | 81 + test/core/surface/sequential_connectivity_test.c | 173 - test/core/surface/sequential_connectivity_test.cc | 174 + test/core/surface/server_chttp2_test.c | 72 - test/core/surface/server_chttp2_test.cc | 72 + test/core/surface/server_test.c | 165 - test/core/surface/server_test.cc | 165 + test/core/transport/byte_stream_test.c | 279 -- test/core/transport/byte_stream_test.cc | 279 ++ test/core/transport/chttp2/alpn_test.c | 57 - test/core/transport/chttp2/alpn_test.cc | 57 + test/core/transport/chttp2/bin_decoder_test.c | 143 - test/core/transport/chttp2/bin_decoder_test.cc | 143 + test/core/transport/chttp2/bin_encoder_test.c | 173 - test/core/transport/chttp2/bin_encoder_test.cc | 173 + test/core/transport/chttp2/hpack_encoder_test.c | 284 -- test/core/transport/chttp2/hpack_encoder_test.cc | 287 ++ .../transport/chttp2/hpack_parser_fuzzer_test.c | 51 - .../transport/chttp2/hpack_parser_fuzzer_test.cc | 51 + test/core/transport/chttp2/hpack_parser_test.c | 216 -- test/core/transport/chttp2/hpack_parser_test.cc | 216 ++ test/core/transport/chttp2/hpack_table_test.c | 285 -- test/core/transport/chttp2/hpack_table_test.cc | 285 ++ test/core/transport/chttp2/stream_map_test.c | 215 -- test/core/transport/chttp2/stream_map_test.cc | 215 ++ test/core/transport/chttp2/varint_test.c | 54 - test/core/transport/chttp2/varint_test.cc | 54 + test/core/transport/connectivity_state_test.c | 146 - test/core/transport/connectivity_state_test.cc | 146 + test/core/transport/metadata_test.c | 402 --- test/core/transport/metadata_test.cc | 404 +++ test/core/transport/status_conversion_test.c | 162 - test/core/transport/status_conversion_test.cc | 162 + test/core/transport/stream_owned_slice_test.c | 43 - test/core/transport/stream_owned_slice_test.cc | 43 + test/core/transport/timeout_encoding_test.c | 161 - test/core/transport/timeout_encoding_test.cc | 161 + test/core/tsi/fake_transport_security_test.c | 148 - test/core/tsi/fake_transport_security_test.cc | 149 + test/core/tsi/ssl_transport_security_test.c | 673 ---- test/core/tsi/ssl_transport_security_test.cc | 680 ++++ test/core/tsi/transport_security_test.c | 386 --- test/core/tsi/transport_security_test.cc | 386 +++ test/core/tsi/transport_security_test_lib.c | 579 ---- test/core/tsi/transport_security_test_lib.cc | 588 ++++ test/core/util/grpc_profiler.c | 45 - test/core/util/grpc_profiler.cc | 45 + test/core/util/memory_counters.c | 108 - test/core/util/memory_counters.cc | 108 + test/core/util/mock_endpoint.c | 138 - test/core/util/mock_endpoint.cc | 138 + test/core/util/one_corpus_entry_fuzzer.c | 39 - test/core/util/one_corpus_entry_fuzzer.cc | 39 + test/core/util/parse_hexstring.c | 55 - test/core/util/parse_hexstring.cc | 55 + test/core/util/passthru_endpoint.c | 196 -- test/core/util/passthru_endpoint.cc | 196 ++ test/core/util/port.c | 132 - test/core/util/port.cc | 132 + test/core/util/port_server_client.c | 255 -- test/core/util/port_server_client.cc | 255 ++ test/core/util/reconnect_server.c | 129 - test/core/util/reconnect_server.cc | 129 + test/core/util/slice_splitter.c | 124 - test/core/util/slice_splitter.cc | 124 + test/core/util/test_config.c | 396 --- test/core/util/test_config.cc | 396 +++ test/core/util/test_tcp_server.c | 118 - test/core/util/test_tcp_server.cc | 119 + test/core/util/trickle_endpoint.c | 194 -- test/core/util/trickle_endpoint.cc | 194 ++ .../clang_format_all_the_things.sh | 2 +- tools/run_tests/generated/sources_and_headers.json | 704 ++-- 584 files changed, 68886 insertions(+), 68659 deletions(-) delete mode 100644 templates/test/core/end2end/end2end_nosec_tests.c.template create mode 100644 templates/test/core/end2end/end2end_nosec_tests.cc.template delete mode 100644 templates/test/core/end2end/end2end_tests.c.template create mode 100644 templates/test/core/end2end/end2end_tests.cc.template delete mode 100644 test/core/backoff/backoff_test.c create mode 100644 test/core/backoff/backoff_test.cc delete mode 100644 test/core/bad_client/bad_client.c create mode 100644 test/core/bad_client/bad_client.cc delete mode 100644 test/core/bad_client/tests/badreq.c create mode 100644 test/core/bad_client/tests/badreq.cc delete mode 100644 test/core/bad_client/tests/connection_prefix.c create mode 100644 test/core/bad_client/tests/connection_prefix.cc delete mode 100644 test/core/bad_client/tests/head_of_line_blocking.c create mode 100644 test/core/bad_client/tests/head_of_line_blocking.cc delete mode 100644 test/core/bad_client/tests/headers.c create mode 100644 test/core/bad_client/tests/headers.cc delete mode 100644 test/core/bad_client/tests/initial_settings_frame.c create mode 100644 test/core/bad_client/tests/initial_settings_frame.cc delete mode 100644 test/core/bad_client/tests/large_metadata.c create mode 100644 test/core/bad_client/tests/large_metadata.cc delete mode 100644 test/core/bad_client/tests/server_registered_method.c create mode 100644 test/core/bad_client/tests/server_registered_method.cc delete mode 100644 test/core/bad_client/tests/simple_request.c create mode 100644 test/core/bad_client/tests/simple_request.cc delete mode 100644 test/core/bad_client/tests/unknown_frame.c create mode 100644 test/core/bad_client/tests/unknown_frame.cc delete mode 100644 test/core/bad_client/tests/window_overflow.c create mode 100644 test/core/bad_client/tests/window_overflow.cc delete mode 100644 test/core/bad_ssl/bad_ssl_test.c create mode 100644 test/core/bad_ssl/bad_ssl_test.cc delete mode 100644 test/core/bad_ssl/server_common.c create mode 100644 test/core/bad_ssl/server_common.cc delete mode 100644 test/core/bad_ssl/servers/alpn.c create mode 100644 test/core/bad_ssl/servers/alpn.cc delete mode 100644 test/core/bad_ssl/servers/cert.c create mode 100644 test/core/bad_ssl/servers/cert.cc delete mode 100644 test/core/census/context_test.c create mode 100644 test/core/census/context_test.cc delete mode 100644 test/core/census/intrusive_hash_map_test.c create mode 100644 test/core/census/intrusive_hash_map_test.cc delete mode 100644 test/core/census/mlog_test.c create mode 100644 test/core/census/mlog_test.cc delete mode 100644 test/core/census/resource_test.c create mode 100644 test/core/census/resource_test.cc delete mode 100644 test/core/census/trace_context_test.c create mode 100644 test/core/census/trace_context_test.cc delete mode 100644 test/core/channel/channel_args_test.c create mode 100644 test/core/channel/channel_args_test.cc delete mode 100644 test/core/channel/channel_stack_builder_test.c create mode 100644 test/core/channel/channel_stack_builder_test.cc delete mode 100644 test/core/channel/channel_stack_test.c create mode 100644 test/core/channel/channel_stack_test.cc delete mode 100644 test/core/channel/minimal_stack_is_minimal_test.c create mode 100644 test/core/channel/minimal_stack_is_minimal_test.cc delete mode 100644 test/core/client_channel/lb_policies_test.c create mode 100644 test/core/client_channel/lb_policies_test.cc delete mode 100644 test/core/client_channel/parse_address_test.c create mode 100644 test/core/client_channel/parse_address_test.cc delete mode 100644 test/core/client_channel/resolvers/dns_resolver_connectivity_test.c create mode 100644 test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc delete mode 100644 test/core/client_channel/resolvers/dns_resolver_test.c create mode 100644 test/core/client_channel/resolvers/dns_resolver_test.cc delete mode 100644 test/core/client_channel/resolvers/fake_resolver_test.c create mode 100644 test/core/client_channel/resolvers/fake_resolver_test.cc delete mode 100644 test/core/client_channel/resolvers/sockaddr_resolver_test.c create mode 100644 test/core/client_channel/resolvers/sockaddr_resolver_test.cc delete mode 100644 test/core/client_channel/uri_fuzzer_test.c create mode 100644 test/core/client_channel/uri_fuzzer_test.cc delete mode 100644 test/core/client_channel/uri_parser_test.c create mode 100644 test/core/client_channel/uri_parser_test.cc delete mode 100644 test/core/compression/algorithm_test.c create mode 100644 test/core/compression/algorithm_test.cc delete mode 100644 test/core/compression/compression_test.c create mode 100644 test/core/compression/compression_test.cc delete mode 100644 test/core/compression/message_compress_test.c create mode 100644 test/core/compression/message_compress_test.cc delete mode 100644 test/core/compression/stream_compression_test.c create mode 100644 test/core/compression/stream_compression_test.cc delete mode 100644 test/core/end2end/bad_server_response_test.c create mode 100644 test/core/end2end/bad_server_response_test.cc delete mode 100644 test/core/end2end/connection_refused_test.c create mode 100644 test/core/end2end/connection_refused_test.cc delete mode 100644 test/core/end2end/cq_verifier.c create mode 100644 test/core/end2end/cq_verifier.cc delete mode 100644 test/core/end2end/cq_verifier_native.c create mode 100644 test/core/end2end/cq_verifier_native.cc delete mode 100644 test/core/end2end/cq_verifier_uv.c create mode 100644 test/core/end2end/cq_verifier_uv.cc delete mode 100644 test/core/end2end/data/client_certs.c create mode 100644 test/core/end2end/data/client_certs.cc delete mode 100644 test/core/end2end/data/server1_cert.c create mode 100644 test/core/end2end/data/server1_cert.cc delete mode 100644 test/core/end2end/data/server1_key.c create mode 100644 test/core/end2end/data/server1_key.cc delete mode 100644 test/core/end2end/data/test_root_cert.c create mode 100644 test/core/end2end/data/test_root_cert.cc delete mode 100644 test/core/end2end/dualstack_socket_test.c create mode 100644 test/core/end2end/dualstack_socket_test.cc delete mode 100644 test/core/end2end/end2end_nosec_tests.c create mode 100644 test/core/end2end/end2end_nosec_tests.cc delete mode 100644 test/core/end2end/end2end_test_utils.c create mode 100644 test/core/end2end/end2end_test_utils.cc delete mode 100644 test/core/end2end/end2end_tests.c create mode 100644 test/core/end2end/end2end_tests.cc delete mode 100644 test/core/end2end/fixtures/h2_census.c create mode 100644 test/core/end2end/fixtures/h2_census.cc delete mode 100644 test/core/end2end/fixtures/h2_compress.c create mode 100644 test/core/end2end/fixtures/h2_compress.cc delete mode 100644 test/core/end2end/fixtures/h2_fakesec.c create mode 100644 test/core/end2end/fixtures/h2_fakesec.cc delete mode 100644 test/core/end2end/fixtures/h2_fd.c create mode 100644 test/core/end2end/fixtures/h2_fd.cc delete mode 100644 test/core/end2end/fixtures/h2_full+pipe.c create mode 100644 test/core/end2end/fixtures/h2_full+pipe.cc delete mode 100644 test/core/end2end/fixtures/h2_full+trace.c create mode 100644 test/core/end2end/fixtures/h2_full+trace.cc delete mode 100644 test/core/end2end/fixtures/h2_full+workarounds.c create mode 100644 test/core/end2end/fixtures/h2_full+workarounds.cc delete mode 100644 test/core/end2end/fixtures/h2_full.c create mode 100644 test/core/end2end/fixtures/h2_full.cc delete mode 100644 test/core/end2end/fixtures/h2_http_proxy.c create mode 100644 test/core/end2end/fixtures/h2_http_proxy.cc delete mode 100644 test/core/end2end/fixtures/h2_load_reporting.c create mode 100644 test/core/end2end/fixtures/h2_load_reporting.cc delete mode 100644 test/core/end2end/fixtures/h2_oauth2.c create mode 100644 test/core/end2end/fixtures/h2_oauth2.cc delete mode 100644 test/core/end2end/fixtures/h2_proxy.c create mode 100644 test/core/end2end/fixtures/h2_proxy.cc delete mode 100644 test/core/end2end/fixtures/h2_sockpair+trace.c create mode 100644 test/core/end2end/fixtures/h2_sockpair+trace.cc delete mode 100644 test/core/end2end/fixtures/h2_sockpair.c create mode 100644 test/core/end2end/fixtures/h2_sockpair.cc delete mode 100644 test/core/end2end/fixtures/h2_sockpair_1byte.c create mode 100644 test/core/end2end/fixtures/h2_sockpair_1byte.cc delete mode 100644 test/core/end2end/fixtures/h2_ssl.c create mode 100644 test/core/end2end/fixtures/h2_ssl.cc delete mode 100644 test/core/end2end/fixtures/h2_ssl_proxy.c create mode 100644 test/core/end2end/fixtures/h2_ssl_proxy.cc delete mode 100644 test/core/end2end/fixtures/h2_uds.c create mode 100644 test/core/end2end/fixtures/h2_uds.cc delete mode 100644 test/core/end2end/fixtures/http_proxy_fixture.c create mode 100644 test/core/end2end/fixtures/http_proxy_fixture.cc delete mode 100644 test/core/end2end/fixtures/inproc.c create mode 100644 test/core/end2end/fixtures/inproc.cc delete mode 100644 test/core/end2end/fixtures/proxy.c create mode 100644 test/core/end2end/fixtures/proxy.cc delete mode 100644 test/core/end2end/fuzzers/api_fuzzer.c create mode 100644 test/core/end2end/fuzzers/api_fuzzer.cc delete mode 100644 test/core/end2end/fuzzers/client_fuzzer.c create mode 100644 test/core/end2end/fuzzers/client_fuzzer.cc delete mode 100644 test/core/end2end/fuzzers/server_fuzzer.c create mode 100644 test/core/end2end/fuzzers/server_fuzzer.cc delete mode 100644 test/core/end2end/goaway_server_test.c create mode 100644 test/core/end2end/goaway_server_test.cc delete mode 100644 test/core/end2end/invalid_call_argument_test.c create mode 100644 test/core/end2end/invalid_call_argument_test.cc delete mode 100644 test/core/end2end/multiple_server_queues_test.c create mode 100644 test/core/end2end/multiple_server_queues_test.cc delete mode 100644 test/core/end2end/no_server_test.c create mode 100644 test/core/end2end/no_server_test.cc delete mode 100644 test/core/end2end/tests/authority_not_supported.c create mode 100644 test/core/end2end/tests/authority_not_supported.cc delete mode 100644 test/core/end2end/tests/bad_hostname.c create mode 100644 test/core/end2end/tests/bad_hostname.cc delete mode 100644 test/core/end2end/tests/bad_ping.c create mode 100644 test/core/end2end/tests/bad_ping.cc delete mode 100644 test/core/end2end/tests/binary_metadata.c create mode 100644 test/core/end2end/tests/binary_metadata.cc delete mode 100644 test/core/end2end/tests/call_creds.c create mode 100644 test/core/end2end/tests/call_creds.cc delete mode 100644 test/core/end2end/tests/cancel_after_accept.c create mode 100644 test/core/end2end/tests/cancel_after_accept.cc delete mode 100644 test/core/end2end/tests/cancel_after_client_done.c create mode 100644 test/core/end2end/tests/cancel_after_client_done.cc delete mode 100644 test/core/end2end/tests/cancel_after_invoke.c create mode 100644 test/core/end2end/tests/cancel_after_invoke.cc delete mode 100644 test/core/end2end/tests/cancel_after_round_trip.c create mode 100644 test/core/end2end/tests/cancel_after_round_trip.cc delete mode 100644 test/core/end2end/tests/cancel_before_invoke.c create mode 100644 test/core/end2end/tests/cancel_before_invoke.cc delete mode 100644 test/core/end2end/tests/cancel_in_a_vacuum.c create mode 100644 test/core/end2end/tests/cancel_in_a_vacuum.cc delete mode 100644 test/core/end2end/tests/cancel_with_status.c create mode 100644 test/core/end2end/tests/cancel_with_status.cc delete mode 100644 test/core/end2end/tests/compressed_payload.c create mode 100644 test/core/end2end/tests/compressed_payload.cc delete mode 100644 test/core/end2end/tests/connectivity.c create mode 100644 test/core/end2end/tests/connectivity.cc delete mode 100644 test/core/end2end/tests/default_host.c create mode 100644 test/core/end2end/tests/default_host.cc delete mode 100644 test/core/end2end/tests/disappearing_server.c create mode 100644 test/core/end2end/tests/disappearing_server.cc delete mode 100644 test/core/end2end/tests/empty_batch.c create mode 100644 test/core/end2end/tests/empty_batch.cc delete mode 100644 test/core/end2end/tests/filter_call_init_fails.c create mode 100644 test/core/end2end/tests/filter_call_init_fails.cc delete mode 100644 test/core/end2end/tests/filter_causes_close.c create mode 100644 test/core/end2end/tests/filter_causes_close.cc delete mode 100644 test/core/end2end/tests/filter_latency.c create mode 100644 test/core/end2end/tests/filter_latency.cc delete mode 100644 test/core/end2end/tests/graceful_server_shutdown.c create mode 100644 test/core/end2end/tests/graceful_server_shutdown.cc delete mode 100644 test/core/end2end/tests/high_initial_seqno.c create mode 100644 test/core/end2end/tests/high_initial_seqno.cc delete mode 100644 test/core/end2end/tests/hpack_size.c create mode 100644 test/core/end2end/tests/hpack_size.cc delete mode 100644 test/core/end2end/tests/idempotent_request.c create mode 100644 test/core/end2end/tests/idempotent_request.cc delete mode 100644 test/core/end2end/tests/invoke_large_request.c create mode 100644 test/core/end2end/tests/invoke_large_request.cc delete mode 100644 test/core/end2end/tests/keepalive_timeout.c create mode 100644 test/core/end2end/tests/keepalive_timeout.cc delete mode 100644 test/core/end2end/tests/large_metadata.c create mode 100644 test/core/end2end/tests/large_metadata.cc delete mode 100644 test/core/end2end/tests/load_reporting_hook.c create mode 100644 test/core/end2end/tests/load_reporting_hook.cc delete mode 100644 test/core/end2end/tests/max_concurrent_streams.c create mode 100644 test/core/end2end/tests/max_concurrent_streams.cc delete mode 100644 test/core/end2end/tests/max_connection_age.c create mode 100644 test/core/end2end/tests/max_connection_age.cc delete mode 100644 test/core/end2end/tests/max_connection_idle.c create mode 100644 test/core/end2end/tests/max_connection_idle.cc delete mode 100644 test/core/end2end/tests/max_message_length.c create mode 100644 test/core/end2end/tests/max_message_length.cc delete mode 100644 test/core/end2end/tests/negative_deadline.c create mode 100644 test/core/end2end/tests/negative_deadline.cc delete mode 100644 test/core/end2end/tests/network_status_change.c create mode 100644 test/core/end2end/tests/network_status_change.cc delete mode 100644 test/core/end2end/tests/no_logging.c create mode 100644 test/core/end2end/tests/no_logging.cc delete mode 100644 test/core/end2end/tests/no_op.c create mode 100644 test/core/end2end/tests/no_op.cc delete mode 100644 test/core/end2end/tests/payload.c create mode 100644 test/core/end2end/tests/payload.cc delete mode 100644 test/core/end2end/tests/ping.c create mode 100644 test/core/end2end/tests/ping.cc delete mode 100644 test/core/end2end/tests/ping_pong_streaming.c create mode 100644 test/core/end2end/tests/ping_pong_streaming.cc delete mode 100644 test/core/end2end/tests/proxy_auth.c create mode 100644 test/core/end2end/tests/proxy_auth.cc delete mode 100644 test/core/end2end/tests/registered_call.c create mode 100644 test/core/end2end/tests/registered_call.cc delete mode 100644 test/core/end2end/tests/request_with_flags.c create mode 100644 test/core/end2end/tests/request_with_flags.cc delete mode 100644 test/core/end2end/tests/request_with_payload.c create mode 100644 test/core/end2end/tests/request_with_payload.cc delete mode 100644 test/core/end2end/tests/resource_quota_server.c create mode 100644 test/core/end2end/tests/resource_quota_server.cc delete mode 100644 test/core/end2end/tests/server_finishes_request.c create mode 100644 test/core/end2end/tests/server_finishes_request.cc delete mode 100644 test/core/end2end/tests/shutdown_finishes_calls.c create mode 100644 test/core/end2end/tests/shutdown_finishes_calls.cc delete mode 100644 test/core/end2end/tests/shutdown_finishes_tags.c create mode 100644 test/core/end2end/tests/shutdown_finishes_tags.cc delete mode 100644 test/core/end2end/tests/simple_cacheable_request.c create mode 100644 test/core/end2end/tests/simple_cacheable_request.cc delete mode 100644 test/core/end2end/tests/simple_delayed_request.c create mode 100644 test/core/end2end/tests/simple_delayed_request.cc delete mode 100644 test/core/end2end/tests/simple_metadata.c create mode 100644 test/core/end2end/tests/simple_metadata.cc delete mode 100644 test/core/end2end/tests/simple_request.c create mode 100644 test/core/end2end/tests/simple_request.cc delete mode 100644 test/core/end2end/tests/stream_compression_compressed_payload.c create mode 100644 test/core/end2end/tests/stream_compression_compressed_payload.cc delete mode 100644 test/core/end2end/tests/stream_compression_payload.c create mode 100644 test/core/end2end/tests/stream_compression_payload.cc delete mode 100644 test/core/end2end/tests/stream_compression_ping_pong_streaming.c create mode 100644 test/core/end2end/tests/stream_compression_ping_pong_streaming.cc delete mode 100644 test/core/end2end/tests/streaming_error_response.c create mode 100644 test/core/end2end/tests/streaming_error_response.cc delete mode 100644 test/core/end2end/tests/trailing_metadata.c create mode 100644 test/core/end2end/tests/trailing_metadata.cc delete mode 100644 test/core/end2end/tests/workaround_cronet_compression.c create mode 100644 test/core/end2end/tests/workaround_cronet_compression.cc delete mode 100644 test/core/end2end/tests/write_buffering.c create mode 100644 test/core/end2end/tests/write_buffering.cc delete mode 100644 test/core/end2end/tests/write_buffering_at_end.c create mode 100644 test/core/end2end/tests/write_buffering_at_end.cc delete mode 100644 test/core/fling/client.c create mode 100644 test/core/fling/client.cc delete mode 100644 test/core/fling/fling_stream_test.c create mode 100644 test/core/fling/fling_stream_test.cc delete mode 100644 test/core/fling/fling_test.c create mode 100644 test/core/fling/fling_test.cc delete mode 100644 test/core/fling/server.c create mode 100644 test/core/fling/server.cc delete mode 100644 test/core/handshake/client_ssl.c create mode 100644 test/core/handshake/client_ssl.cc delete mode 100644 test/core/handshake/server_ssl.c create mode 100644 test/core/handshake/server_ssl.cc delete mode 100644 test/core/http/format_request_test.c create mode 100644 test/core/http/format_request_test.cc delete mode 100644 test/core/http/httpcli_test.c create mode 100644 test/core/http/httpcli_test.cc delete mode 100644 test/core/http/httpscli_test.c create mode 100644 test/core/http/httpscli_test.cc delete mode 100644 test/core/http/parser_test.c create mode 100644 test/core/http/parser_test.cc delete mode 100644 test/core/http/request_fuzzer.c create mode 100644 test/core/http/request_fuzzer.cc delete mode 100644 test/core/http/response_fuzzer.c create mode 100644 test/core/http/response_fuzzer.cc delete mode 100644 test/core/iomgr/combiner_test.c create mode 100644 test/core/iomgr/combiner_test.cc delete mode 100644 test/core/iomgr/endpoint_pair_test.c create mode 100644 test/core/iomgr/endpoint_pair_test.cc delete mode 100644 test/core/iomgr/endpoint_tests.c create mode 100644 test/core/iomgr/endpoint_tests.cc delete mode 100644 test/core/iomgr/error_test.c create mode 100644 test/core/iomgr/error_test.cc delete mode 100644 test/core/iomgr/ev_epollsig_linux_test.c create mode 100644 test/core/iomgr/ev_epollsig_linux_test.cc delete mode 100644 test/core/iomgr/fd_conservation_posix_test.c create mode 100644 test/core/iomgr/fd_conservation_posix_test.cc delete mode 100644 test/core/iomgr/fd_posix_test.c create mode 100644 test/core/iomgr/fd_posix_test.cc delete mode 100644 test/core/iomgr/load_file_test.c create mode 100644 test/core/iomgr/load_file_test.cc delete mode 100644 test/core/iomgr/pollset_set_test.c create mode 100644 test/core/iomgr/pollset_set_test.cc delete mode 100644 test/core/iomgr/resolve_address_posix_test.c create mode 100644 test/core/iomgr/resolve_address_posix_test.cc delete mode 100644 test/core/iomgr/resolve_address_test.c create mode 100644 test/core/iomgr/resolve_address_test.cc delete mode 100644 test/core/iomgr/resource_quota_test.c create mode 100644 test/core/iomgr/resource_quota_test.cc delete mode 100644 test/core/iomgr/sockaddr_utils_test.c create mode 100644 test/core/iomgr/sockaddr_utils_test.cc delete mode 100644 test/core/iomgr/socket_utils_test.c create mode 100644 test/core/iomgr/socket_utils_test.cc delete mode 100644 test/core/iomgr/tcp_client_posix_test.c create mode 100644 test/core/iomgr/tcp_client_posix_test.cc delete mode 100644 test/core/iomgr/tcp_client_uv_test.c create mode 100644 test/core/iomgr/tcp_client_uv_test.cc delete mode 100644 test/core/iomgr/tcp_posix_test.c create mode 100644 test/core/iomgr/tcp_posix_test.cc delete mode 100644 test/core/iomgr/tcp_server_posix_test.c create mode 100644 test/core/iomgr/tcp_server_posix_test.cc delete mode 100644 test/core/iomgr/tcp_server_uv_test.c create mode 100644 test/core/iomgr/tcp_server_uv_test.cc delete mode 100644 test/core/iomgr/time_averaged_stats_test.c create mode 100644 test/core/iomgr/time_averaged_stats_test.cc delete mode 100644 test/core/iomgr/timer_heap_test.c create mode 100644 test/core/iomgr/timer_heap_test.cc delete mode 100644 test/core/iomgr/timer_list_test.c create mode 100644 test/core/iomgr/timer_list_test.cc delete mode 100644 test/core/iomgr/udp_server_test.c create mode 100644 test/core/iomgr/udp_server_test.cc delete mode 100644 test/core/iomgr/wakeup_fd_cv_test.c create mode 100644 test/core/iomgr/wakeup_fd_cv_test.cc delete mode 100644 test/core/json/fuzzer.c create mode 100644 test/core/json/fuzzer.cc delete mode 100644 test/core/json/json_rewrite.c create mode 100644 test/core/json/json_rewrite.cc delete mode 100644 test/core/json/json_rewrite_test.c create mode 100644 test/core/json/json_rewrite_test.cc delete mode 100644 test/core/json/json_stream_error_test.c create mode 100644 test/core/json/json_stream_error_test.cc delete mode 100644 test/core/json/json_test.c create mode 100644 test/core/json/json_test.cc delete mode 100644 test/core/memory_usage/client.c create mode 100644 test/core/memory_usage/client.cc delete mode 100644 test/core/memory_usage/memory_usage_test.c create mode 100644 test/core/memory_usage/memory_usage_test.cc delete mode 100644 test/core/memory_usage/server.c create mode 100644 test/core/memory_usage/server.cc delete mode 100644 test/core/nanopb/fuzzer_response.c create mode 100644 test/core/nanopb/fuzzer_response.cc delete mode 100644 test/core/nanopb/fuzzer_serverlist.c create mode 100644 test/core/nanopb/fuzzer_serverlist.cc delete mode 100644 test/core/network_benchmarks/low_level_ping_pong.c create mode 100644 test/core/network_benchmarks/low_level_ping_pong.cc delete mode 100644 test/core/security/auth_context_test.c create mode 100644 test/core/security/auth_context_test.cc delete mode 100644 test/core/security/create_jwt.c create mode 100644 test/core/security/create_jwt.cc delete mode 100644 test/core/security/credentials_test.c create mode 100644 test/core/security/credentials_test.cc delete mode 100644 test/core/security/fetch_oauth2.c create mode 100644 test/core/security/fetch_oauth2.cc delete mode 100644 test/core/security/json_token_test.c create mode 100644 test/core/security/json_token_test.cc delete mode 100644 test/core/security/jwt_verifier_test.c create mode 100644 test/core/security/jwt_verifier_test.cc delete mode 100644 test/core/security/oauth2_utils.c create mode 100644 test/core/security/oauth2_utils.cc delete mode 100644 test/core/security/print_google_default_creds_token.c create mode 100644 test/core/security/print_google_default_creds_token.cc delete mode 100644 test/core/security/secure_endpoint_test.c create mode 100644 test/core/security/secure_endpoint_test.cc delete mode 100644 test/core/security/security_connector_test.c create mode 100644 test/core/security/security_connector_test.cc delete mode 100644 test/core/security/ssl_server_fuzzer.c create mode 100644 test/core/security/ssl_server_fuzzer.cc delete mode 100644 test/core/security/verify_jwt.c create mode 100644 test/core/security/verify_jwt.cc delete mode 100644 test/core/slice/b64_test.c create mode 100644 test/core/slice/b64_test.cc delete mode 100644 test/core/slice/percent_decode_fuzzer.c create mode 100644 test/core/slice/percent_decode_fuzzer.cc delete mode 100644 test/core/slice/percent_encode_fuzzer.c create mode 100644 test/core/slice/percent_encode_fuzzer.cc delete mode 100644 test/core/slice/percent_encoding_test.c create mode 100644 test/core/slice/percent_encoding_test.cc delete mode 100644 test/core/slice/slice_buffer_test.c create mode 100644 test/core/slice/slice_buffer_test.cc delete mode 100644 test/core/slice/slice_hash_table_test.c create mode 100644 test/core/slice/slice_hash_table_test.cc delete mode 100644 test/core/slice/slice_string_helpers_test.c create mode 100644 test/core/slice/slice_string_helpers_test.cc delete mode 100644 test/core/slice/slice_test.c create mode 100644 test/core/slice/slice_test.cc delete mode 100644 test/core/statistics/census_log_tests.c create mode 100644 test/core/statistics/census_log_tests.cc delete mode 100644 test/core/statistics/census_stub_test.c create mode 100644 test/core/statistics/census_stub_test.cc delete mode 100644 test/core/statistics/hash_table_test.c create mode 100644 test/core/statistics/hash_table_test.cc delete mode 100644 test/core/statistics/multiple_writers_circular_buffer_test.c create mode 100644 test/core/statistics/multiple_writers_circular_buffer_test.cc delete mode 100644 test/core/statistics/multiple_writers_test.c create mode 100644 test/core/statistics/multiple_writers_test.cc delete mode 100644 test/core/statistics/performance_test.c create mode 100644 test/core/statistics/performance_test.cc delete mode 100644 test/core/statistics/quick_test.c create mode 100644 test/core/statistics/quick_test.cc delete mode 100644 test/core/statistics/rpc_stats_test.c create mode 100644 test/core/statistics/rpc_stats_test.cc delete mode 100644 test/core/statistics/small_log_test.c create mode 100644 test/core/statistics/small_log_test.cc delete mode 100644 test/core/statistics/trace_test.c create mode 100644 test/core/statistics/trace_test.cc delete mode 100644 test/core/statistics/window_stats_test.c create mode 100644 test/core/statistics/window_stats_test.cc delete mode 100644 test/core/support/alloc_test.c create mode 100644 test/core/support/alloc_test.cc delete mode 100644 test/core/support/arena_test.c create mode 100644 test/core/support/arena_test.cc delete mode 100644 test/core/support/avl_test.c create mode 100644 test/core/support/avl_test.cc delete mode 100644 test/core/support/cmdline_test.c create mode 100644 test/core/support/cmdline_test.cc delete mode 100644 test/core/support/cpu_test.c create mode 100644 test/core/support/cpu_test.cc delete mode 100644 test/core/support/env_test.c create mode 100644 test/core/support/env_test.cc delete mode 100644 test/core/support/histogram_test.c create mode 100644 test/core/support/histogram_test.cc delete mode 100644 test/core/support/host_port_test.c create mode 100644 test/core/support/host_port_test.cc delete mode 100644 test/core/support/log_test.c create mode 100644 test/core/support/log_test.cc delete mode 100644 test/core/support/mpscq_test.c create mode 100644 test/core/support/mpscq_test.cc delete mode 100644 test/core/support/murmur_hash_test.c create mode 100644 test/core/support/murmur_hash_test.cc delete mode 100644 test/core/support/spinlock_test.c create mode 100644 test/core/support/spinlock_test.cc delete mode 100644 test/core/support/stack_lockfree_test.c create mode 100644 test/core/support/stack_lockfree_test.cc delete mode 100644 test/core/support/string_test.c create mode 100644 test/core/support/string_test.cc delete mode 100644 test/core/support/sync_test.c create mode 100644 test/core/support/sync_test.cc delete mode 100644 test/core/support/thd_test.c create mode 100644 test/core/support/thd_test.cc delete mode 100644 test/core/support/time_test.c create mode 100644 test/core/support/time_test.cc delete mode 100644 test/core/support/tls_test.c create mode 100644 test/core/support/tls_test.cc delete mode 100644 test/core/support/useful_test.c create mode 100644 test/core/support/useful_test.cc delete mode 100644 test/core/surface/alarm_test.c create mode 100644 test/core/surface/alarm_test.cc delete mode 100644 test/core/surface/byte_buffer_reader_test.c create mode 100644 test/core/surface/byte_buffer_reader_test.cc delete mode 100644 test/core/surface/channel_create_test.c create mode 100644 test/core/surface/channel_create_test.cc delete mode 100644 test/core/surface/completion_queue_test.c create mode 100644 test/core/surface/completion_queue_test.cc delete mode 100644 test/core/surface/completion_queue_threading_test.c create mode 100644 test/core/surface/completion_queue_threading_test.cc delete mode 100644 test/core/surface/concurrent_connectivity_test.c create mode 100644 test/core/surface/concurrent_connectivity_test.cc delete mode 100644 test/core/surface/init_test.c create mode 100644 test/core/surface/init_test.cc delete mode 100644 test/core/surface/invalid_channel_args_test.c create mode 100644 test/core/surface/invalid_channel_args_test.cc delete mode 100644 test/core/surface/lame_client_test.c create mode 100644 test/core/surface/lame_client_test.cc delete mode 100644 test/core/surface/num_external_connectivity_watchers_test.c create mode 100644 test/core/surface/num_external_connectivity_watchers_test.cc delete mode 100644 test/core/surface/secure_channel_create_test.c create mode 100644 test/core/surface/secure_channel_create_test.cc delete mode 100644 test/core/surface/sequential_connectivity_test.c create mode 100644 test/core/surface/sequential_connectivity_test.cc delete mode 100644 test/core/surface/server_chttp2_test.c create mode 100644 test/core/surface/server_chttp2_test.cc delete mode 100644 test/core/surface/server_test.c create mode 100644 test/core/surface/server_test.cc delete mode 100644 test/core/transport/byte_stream_test.c create mode 100644 test/core/transport/byte_stream_test.cc delete mode 100644 test/core/transport/chttp2/alpn_test.c create mode 100644 test/core/transport/chttp2/alpn_test.cc delete mode 100644 test/core/transport/chttp2/bin_decoder_test.c create mode 100644 test/core/transport/chttp2/bin_decoder_test.cc delete mode 100644 test/core/transport/chttp2/bin_encoder_test.c create mode 100644 test/core/transport/chttp2/bin_encoder_test.cc delete mode 100644 test/core/transport/chttp2/hpack_encoder_test.c create mode 100644 test/core/transport/chttp2/hpack_encoder_test.cc delete mode 100644 test/core/transport/chttp2/hpack_parser_fuzzer_test.c create mode 100644 test/core/transport/chttp2/hpack_parser_fuzzer_test.cc delete mode 100644 test/core/transport/chttp2/hpack_parser_test.c create mode 100644 test/core/transport/chttp2/hpack_parser_test.cc delete mode 100644 test/core/transport/chttp2/hpack_table_test.c create mode 100644 test/core/transport/chttp2/hpack_table_test.cc delete mode 100644 test/core/transport/chttp2/stream_map_test.c create mode 100644 test/core/transport/chttp2/stream_map_test.cc delete mode 100644 test/core/transport/chttp2/varint_test.c create mode 100644 test/core/transport/chttp2/varint_test.cc delete mode 100644 test/core/transport/connectivity_state_test.c create mode 100644 test/core/transport/connectivity_state_test.cc delete mode 100644 test/core/transport/metadata_test.c create mode 100644 test/core/transport/metadata_test.cc delete mode 100644 test/core/transport/status_conversion_test.c create mode 100644 test/core/transport/status_conversion_test.cc delete mode 100644 test/core/transport/stream_owned_slice_test.c create mode 100644 test/core/transport/stream_owned_slice_test.cc delete mode 100644 test/core/transport/timeout_encoding_test.c create mode 100644 test/core/transport/timeout_encoding_test.cc delete mode 100644 test/core/tsi/fake_transport_security_test.c create mode 100644 test/core/tsi/fake_transport_security_test.cc delete mode 100644 test/core/tsi/ssl_transport_security_test.c create mode 100644 test/core/tsi/ssl_transport_security_test.cc delete mode 100644 test/core/tsi/transport_security_test.c create mode 100644 test/core/tsi/transport_security_test.cc delete mode 100644 test/core/tsi/transport_security_test_lib.c create mode 100644 test/core/tsi/transport_security_test_lib.cc delete mode 100644 test/core/util/grpc_profiler.c create mode 100644 test/core/util/grpc_profiler.cc delete mode 100644 test/core/util/memory_counters.c create mode 100644 test/core/util/memory_counters.cc delete mode 100644 test/core/util/mock_endpoint.c create mode 100644 test/core/util/mock_endpoint.cc delete mode 100644 test/core/util/one_corpus_entry_fuzzer.c create mode 100644 test/core/util/one_corpus_entry_fuzzer.cc delete mode 100644 test/core/util/parse_hexstring.c create mode 100644 test/core/util/parse_hexstring.cc delete mode 100644 test/core/util/passthru_endpoint.c create mode 100644 test/core/util/passthru_endpoint.cc delete mode 100644 test/core/util/port.c create mode 100644 test/core/util/port.cc delete mode 100644 test/core/util/port_server_client.c create mode 100644 test/core/util/port_server_client.cc delete mode 100644 test/core/util/reconnect_server.c create mode 100644 test/core/util/reconnect_server.cc delete mode 100644 test/core/util/slice_splitter.c create mode 100644 test/core/util/slice_splitter.cc delete mode 100644 test/core/util/test_config.c create mode 100644 test/core/util/test_config.cc delete mode 100644 test/core/util/test_tcp_server.c create mode 100644 test/core/util/test_tcp_server.cc delete mode 100644 test/core/util/trickle_endpoint.c create mode 100644 test/core/util/trickle_endpoint.cc (limited to 'src/core/lib') diff --git a/CMakeLists.txt b/CMakeLists.txt index 579621b090..4865c35753 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -920,7 +920,7 @@ endif() if (gRPC_BUILD_TESTS) add_library(gpr_test_util - test/core/util/test_config.c + test/core/util/test_config.cc ) if(WIN32 AND MSVC) @@ -1613,26 +1613,26 @@ endif() if (gRPC_BUILD_TESTS) add_library(grpc_test_util - test/core/end2end/data/client_certs.c - test/core/end2end/data/server1_cert.c - test/core/end2end/data/server1_key.c - test/core/end2end/data/test_root_cert.c - test/core/security/oauth2_utils.c + test/core/end2end/data/client_certs.cc + test/core/end2end/data/server1_cert.cc + test/core/end2end/data/server1_key.cc + test/core/end2end/data/test_root_cert.cc + test/core/security/oauth2_utils.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc - test/core/end2end/cq_verifier.c - test/core/end2end/fixtures/http_proxy_fixture.c - test/core/end2end/fixtures/proxy.c - test/core/iomgr/endpoint_tests.c + test/core/end2end/cq_verifier.cc + test/core/end2end/fixtures/http_proxy_fixture.cc + test/core/end2end/fixtures/proxy.cc + test/core/iomgr/endpoint_tests.cc test/core/util/debugger_macros.cc - test/core/util/grpc_profiler.c - test/core/util/memory_counters.c - test/core/util/mock_endpoint.c - test/core/util/parse_hexstring.c - test/core/util/passthru_endpoint.c - test/core/util/port.c - test/core/util/port_server_client.c - test/core/util/slice_splitter.c - test/core/util/trickle_endpoint.c + test/core/util/grpc_profiler.cc + test/core/util/memory_counters.cc + test/core/util/mock_endpoint.cc + test/core/util/parse_hexstring.cc + test/core/util/passthru_endpoint.cc + test/core/util/port.cc + test/core/util/port_server_client.cc + test/core/util/slice_splitter.cc + test/core/util/trickle_endpoint.cc src/core/lib/backoff/backoff.cc src/core/lib/channel/channel_args.cc src/core/lib/channel/channel_stack.cc @@ -1884,20 +1884,20 @@ if (gRPC_BUILD_TESTS) add_library(grpc_test_util_unsecure src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc - test/core/end2end/cq_verifier.c - test/core/end2end/fixtures/http_proxy_fixture.c - test/core/end2end/fixtures/proxy.c - test/core/iomgr/endpoint_tests.c + test/core/end2end/cq_verifier.cc + test/core/end2end/fixtures/http_proxy_fixture.cc + test/core/end2end/fixtures/proxy.cc + test/core/iomgr/endpoint_tests.cc test/core/util/debugger_macros.cc - test/core/util/grpc_profiler.c - test/core/util/memory_counters.c - test/core/util/mock_endpoint.c - test/core/util/parse_hexstring.c - test/core/util/passthru_endpoint.c - test/core/util/port.c - test/core/util/port_server_client.c - test/core/util/slice_splitter.c - test/core/util/trickle_endpoint.c + test/core/util/grpc_profiler.cc + test/core/util/memory_counters.cc + test/core/util/mock_endpoint.cc + test/core/util/parse_hexstring.cc + test/core/util/passthru_endpoint.cc + test/core/util/port.cc + test/core/util/port_server_client.cc + test/core/util/slice_splitter.cc + test/core/util/trickle_endpoint.cc src/core/lib/backoff/backoff.cc src/core/lib/channel/channel_args.cc src/core/lib/channel/channel_stack.cc @@ -2468,7 +2468,7 @@ endif() if (gRPC_BUILD_TESTS) add_library(reconnect_server - test/core/util/reconnect_server.c + test/core/util/reconnect_server.cc ) if(WIN32 AND MSVC) @@ -2511,7 +2511,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(test_tcp_server - test/core/util/test_tcp_server.c + test/core/util/test_tcp_server.cc ) if(WIN32 AND MSVC) @@ -4809,7 +4809,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(bad_client_test - test/core/bad_client/bad_client.c + test/core/bad_client/bad_client.cc ) if(WIN32 AND MSVC) @@ -4851,7 +4851,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(bad_ssl_test_server - test/core/bad_ssl/server_common.c + test/core/bad_ssl/server_common.cc ) if(WIN32 AND MSVC) @@ -4893,67 +4893,67 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(end2end_tests - test/core/end2end/end2end_tests.c - test/core/end2end/end2end_test_utils.c - test/core/end2end/tests/authority_not_supported.c - test/core/end2end/tests/bad_hostname.c - test/core/end2end/tests/bad_ping.c - test/core/end2end/tests/binary_metadata.c - test/core/end2end/tests/call_creds.c - test/core/end2end/tests/cancel_after_accept.c - test/core/end2end/tests/cancel_after_client_done.c - test/core/end2end/tests/cancel_after_invoke.c - test/core/end2end/tests/cancel_after_round_trip.c - test/core/end2end/tests/cancel_before_invoke.c - test/core/end2end/tests/cancel_in_a_vacuum.c - test/core/end2end/tests/cancel_with_status.c - test/core/end2end/tests/compressed_payload.c - test/core/end2end/tests/connectivity.c - test/core/end2end/tests/default_host.c - test/core/end2end/tests/disappearing_server.c - test/core/end2end/tests/empty_batch.c - test/core/end2end/tests/filter_call_init_fails.c - test/core/end2end/tests/filter_causes_close.c - test/core/end2end/tests/filter_latency.c - test/core/end2end/tests/graceful_server_shutdown.c - test/core/end2end/tests/high_initial_seqno.c - test/core/end2end/tests/hpack_size.c - test/core/end2end/tests/idempotent_request.c - test/core/end2end/tests/invoke_large_request.c - test/core/end2end/tests/keepalive_timeout.c - test/core/end2end/tests/large_metadata.c - test/core/end2end/tests/load_reporting_hook.c - test/core/end2end/tests/max_concurrent_streams.c - test/core/end2end/tests/max_connection_age.c - test/core/end2end/tests/max_connection_idle.c - test/core/end2end/tests/max_message_length.c - test/core/end2end/tests/negative_deadline.c - test/core/end2end/tests/network_status_change.c - test/core/end2end/tests/no_logging.c - test/core/end2end/tests/no_op.c - test/core/end2end/tests/payload.c - test/core/end2end/tests/ping.c - test/core/end2end/tests/ping_pong_streaming.c - test/core/end2end/tests/proxy_auth.c - test/core/end2end/tests/registered_call.c - test/core/end2end/tests/request_with_flags.c - test/core/end2end/tests/request_with_payload.c - test/core/end2end/tests/resource_quota_server.c - test/core/end2end/tests/server_finishes_request.c - test/core/end2end/tests/shutdown_finishes_calls.c - test/core/end2end/tests/shutdown_finishes_tags.c - test/core/end2end/tests/simple_cacheable_request.c - test/core/end2end/tests/simple_delayed_request.c - test/core/end2end/tests/simple_metadata.c - test/core/end2end/tests/simple_request.c - test/core/end2end/tests/stream_compression_compressed_payload.c - test/core/end2end/tests/stream_compression_payload.c - test/core/end2end/tests/stream_compression_ping_pong_streaming.c - test/core/end2end/tests/streaming_error_response.c - test/core/end2end/tests/trailing_metadata.c - test/core/end2end/tests/workaround_cronet_compression.c - test/core/end2end/tests/write_buffering.c - test/core/end2end/tests/write_buffering_at_end.c + test/core/end2end/end2end_tests.cc + test/core/end2end/end2end_test_utils.cc + test/core/end2end/tests/authority_not_supported.cc + test/core/end2end/tests/bad_hostname.cc + test/core/end2end/tests/bad_ping.cc + test/core/end2end/tests/binary_metadata.cc + test/core/end2end/tests/call_creds.cc + test/core/end2end/tests/cancel_after_accept.cc + test/core/end2end/tests/cancel_after_client_done.cc + test/core/end2end/tests/cancel_after_invoke.cc + test/core/end2end/tests/cancel_after_round_trip.cc + test/core/end2end/tests/cancel_before_invoke.cc + test/core/end2end/tests/cancel_in_a_vacuum.cc + test/core/end2end/tests/cancel_with_status.cc + test/core/end2end/tests/compressed_payload.cc + test/core/end2end/tests/connectivity.cc + test/core/end2end/tests/default_host.cc + test/core/end2end/tests/disappearing_server.cc + test/core/end2end/tests/empty_batch.cc + test/core/end2end/tests/filter_call_init_fails.cc + test/core/end2end/tests/filter_causes_close.cc + test/core/end2end/tests/filter_latency.cc + test/core/end2end/tests/graceful_server_shutdown.cc + test/core/end2end/tests/high_initial_seqno.cc + test/core/end2end/tests/hpack_size.cc + test/core/end2end/tests/idempotent_request.cc + test/core/end2end/tests/invoke_large_request.cc + test/core/end2end/tests/keepalive_timeout.cc + test/core/end2end/tests/large_metadata.cc + test/core/end2end/tests/load_reporting_hook.cc + test/core/end2end/tests/max_concurrent_streams.cc + test/core/end2end/tests/max_connection_age.cc + test/core/end2end/tests/max_connection_idle.cc + test/core/end2end/tests/max_message_length.cc + test/core/end2end/tests/negative_deadline.cc + test/core/end2end/tests/network_status_change.cc + test/core/end2end/tests/no_logging.cc + test/core/end2end/tests/no_op.cc + test/core/end2end/tests/payload.cc + test/core/end2end/tests/ping.cc + test/core/end2end/tests/ping_pong_streaming.cc + test/core/end2end/tests/proxy_auth.cc + test/core/end2end/tests/registered_call.cc + test/core/end2end/tests/request_with_flags.cc + test/core/end2end/tests/request_with_payload.cc + test/core/end2end/tests/resource_quota_server.cc + test/core/end2end/tests/server_finishes_request.cc + test/core/end2end/tests/shutdown_finishes_calls.cc + test/core/end2end/tests/shutdown_finishes_tags.cc + test/core/end2end/tests/simple_cacheable_request.cc + test/core/end2end/tests/simple_delayed_request.cc + test/core/end2end/tests/simple_metadata.cc + test/core/end2end/tests/simple_request.cc + test/core/end2end/tests/stream_compression_compressed_payload.cc + test/core/end2end/tests/stream_compression_payload.cc + test/core/end2end/tests/stream_compression_ping_pong_streaming.cc + test/core/end2end/tests/streaming_error_response.cc + test/core/end2end/tests/trailing_metadata.cc + test/core/end2end/tests/workaround_cronet_compression.cc + test/core/end2end/tests/write_buffering.cc + test/core/end2end/tests/write_buffering_at_end.cc ) if(WIN32 AND MSVC) @@ -4996,66 +4996,66 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(end2end_nosec_tests - test/core/end2end/end2end_nosec_tests.c - test/core/end2end/end2end_test_utils.c - test/core/end2end/tests/authority_not_supported.c - test/core/end2end/tests/bad_hostname.c - test/core/end2end/tests/bad_ping.c - test/core/end2end/tests/binary_metadata.c - test/core/end2end/tests/cancel_after_accept.c - test/core/end2end/tests/cancel_after_client_done.c - test/core/end2end/tests/cancel_after_invoke.c - test/core/end2end/tests/cancel_after_round_trip.c - test/core/end2end/tests/cancel_before_invoke.c - test/core/end2end/tests/cancel_in_a_vacuum.c - test/core/end2end/tests/cancel_with_status.c - test/core/end2end/tests/compressed_payload.c - test/core/end2end/tests/connectivity.c - test/core/end2end/tests/default_host.c - test/core/end2end/tests/disappearing_server.c - test/core/end2end/tests/empty_batch.c - test/core/end2end/tests/filter_call_init_fails.c - test/core/end2end/tests/filter_causes_close.c - test/core/end2end/tests/filter_latency.c - test/core/end2end/tests/graceful_server_shutdown.c - test/core/end2end/tests/high_initial_seqno.c - test/core/end2end/tests/hpack_size.c - test/core/end2end/tests/idempotent_request.c - test/core/end2end/tests/invoke_large_request.c - test/core/end2end/tests/keepalive_timeout.c - test/core/end2end/tests/large_metadata.c - test/core/end2end/tests/load_reporting_hook.c - test/core/end2end/tests/max_concurrent_streams.c - test/core/end2end/tests/max_connection_age.c - test/core/end2end/tests/max_connection_idle.c - test/core/end2end/tests/max_message_length.c - test/core/end2end/tests/negative_deadline.c - test/core/end2end/tests/network_status_change.c - test/core/end2end/tests/no_logging.c - test/core/end2end/tests/no_op.c - test/core/end2end/tests/payload.c - test/core/end2end/tests/ping.c - test/core/end2end/tests/ping_pong_streaming.c - test/core/end2end/tests/proxy_auth.c - test/core/end2end/tests/registered_call.c - test/core/end2end/tests/request_with_flags.c - test/core/end2end/tests/request_with_payload.c - test/core/end2end/tests/resource_quota_server.c - test/core/end2end/tests/server_finishes_request.c - test/core/end2end/tests/shutdown_finishes_calls.c - test/core/end2end/tests/shutdown_finishes_tags.c - test/core/end2end/tests/simple_cacheable_request.c - test/core/end2end/tests/simple_delayed_request.c - test/core/end2end/tests/simple_metadata.c - test/core/end2end/tests/simple_request.c - test/core/end2end/tests/stream_compression_compressed_payload.c - test/core/end2end/tests/stream_compression_payload.c - test/core/end2end/tests/stream_compression_ping_pong_streaming.c - test/core/end2end/tests/streaming_error_response.c - test/core/end2end/tests/trailing_metadata.c - test/core/end2end/tests/workaround_cronet_compression.c - test/core/end2end/tests/write_buffering.c - test/core/end2end/tests/write_buffering_at_end.c + test/core/end2end/end2end_nosec_tests.cc + test/core/end2end/end2end_test_utils.cc + test/core/end2end/tests/authority_not_supported.cc + test/core/end2end/tests/bad_hostname.cc + test/core/end2end/tests/bad_ping.cc + test/core/end2end/tests/binary_metadata.cc + test/core/end2end/tests/cancel_after_accept.cc + test/core/end2end/tests/cancel_after_client_done.cc + test/core/end2end/tests/cancel_after_invoke.cc + test/core/end2end/tests/cancel_after_round_trip.cc + test/core/end2end/tests/cancel_before_invoke.cc + test/core/end2end/tests/cancel_in_a_vacuum.cc + test/core/end2end/tests/cancel_with_status.cc + test/core/end2end/tests/compressed_payload.cc + test/core/end2end/tests/connectivity.cc + test/core/end2end/tests/default_host.cc + test/core/end2end/tests/disappearing_server.cc + test/core/end2end/tests/empty_batch.cc + test/core/end2end/tests/filter_call_init_fails.cc + test/core/end2end/tests/filter_causes_close.cc + test/core/end2end/tests/filter_latency.cc + test/core/end2end/tests/graceful_server_shutdown.cc + test/core/end2end/tests/high_initial_seqno.cc + test/core/end2end/tests/hpack_size.cc + test/core/end2end/tests/idempotent_request.cc + test/core/end2end/tests/invoke_large_request.cc + test/core/end2end/tests/keepalive_timeout.cc + test/core/end2end/tests/large_metadata.cc + test/core/end2end/tests/load_reporting_hook.cc + test/core/end2end/tests/max_concurrent_streams.cc + test/core/end2end/tests/max_connection_age.cc + test/core/end2end/tests/max_connection_idle.cc + test/core/end2end/tests/max_message_length.cc + test/core/end2end/tests/negative_deadline.cc + test/core/end2end/tests/network_status_change.cc + test/core/end2end/tests/no_logging.cc + test/core/end2end/tests/no_op.cc + test/core/end2end/tests/payload.cc + test/core/end2end/tests/ping.cc + test/core/end2end/tests/ping_pong_streaming.cc + test/core/end2end/tests/proxy_auth.cc + test/core/end2end/tests/registered_call.cc + test/core/end2end/tests/request_with_flags.cc + test/core/end2end/tests/request_with_payload.cc + test/core/end2end/tests/resource_quota_server.cc + test/core/end2end/tests/server_finishes_request.cc + test/core/end2end/tests/shutdown_finishes_calls.cc + test/core/end2end/tests/shutdown_finishes_tags.cc + test/core/end2end/tests/simple_cacheable_request.cc + test/core/end2end/tests/simple_delayed_request.cc + test/core/end2end/tests/simple_metadata.cc + test/core/end2end/tests/simple_request.cc + test/core/end2end/tests/stream_compression_compressed_payload.cc + test/core/end2end/tests/stream_compression_payload.cc + test/core/end2end/tests/stream_compression_ping_pong_streaming.cc + test/core/end2end/tests/streaming_error_response.cc + test/core/end2end/tests/trailing_metadata.cc + test/core/end2end/tests/workaround_cronet_compression.cc + test/core/end2end/tests/write_buffering.cc + test/core/end2end/tests/write_buffering_at_end.cc ) if(WIN32 AND MSVC) @@ -5098,7 +5098,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alarm_test - test/core/surface/alarm_test.c + test/core/surface/alarm_test.cc ) @@ -5128,7 +5128,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(algorithm_test - test/core/compression/algorithm_test.c + test/core/compression/algorithm_test.cc ) @@ -5158,7 +5158,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alloc_test - test/core/support/alloc_test.c + test/core/support/alloc_test.cc ) @@ -5186,7 +5186,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alpn_test - test/core/transport/chttp2/alpn_test.c + test/core/transport/chttp2/alpn_test.cc ) @@ -5216,7 +5216,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(arena_test - test/core/support/arena_test.c + test/core/support/arena_test.cc ) @@ -5244,7 +5244,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(backoff_test - test/core/backoff/backoff_test.c + test/core/backoff/backoff_test.cc ) @@ -5274,7 +5274,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bad_server_response_test - test/core/end2end/bad_server_response_test.c + test/core/end2end/bad_server_response_test.cc ) @@ -5305,7 +5305,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bin_decoder_test - test/core/transport/chttp2/bin_decoder_test.c + test/core/transport/chttp2/bin_decoder_test.cc ) @@ -5333,7 +5333,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bin_encoder_test - test/core/transport/chttp2/bin_encoder_test.c + test/core/transport/chttp2/bin_encoder_test.cc ) @@ -5361,7 +5361,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(byte_stream_test - test/core/transport/byte_stream_test.c + test/core/transport/byte_stream_test.cc ) @@ -5391,7 +5391,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_context_test - test/core/census/context_test.c + test/core/census/context_test.cc ) @@ -5421,7 +5421,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_intrusive_hash_map_test - test/core/census/intrusive_hash_map_test.c + test/core/census/intrusive_hash_map_test.cc ) @@ -5451,7 +5451,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_resource_test - test/core/census/resource_test.c + test/core/census/resource_test.cc ) @@ -5481,7 +5481,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_trace_context_test - test/core/census/trace_context_test.c + test/core/census/trace_context_test.cc ) @@ -5511,7 +5511,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(channel_create_test - test/core/surface/channel_create_test.c + test/core/surface/channel_create_test.cc ) @@ -5540,7 +5540,7 @@ target_link_libraries(channel_create_test endif (gRPC_BUILD_TESTS) add_executable(check_epollexclusive - test/build/check_epollexclusive.c + test/build/check_epollexclusive.cc ) @@ -5576,7 +5576,7 @@ endif() if (gRPC_BUILD_TESTS) add_executable(chttp2_hpack_encoder_test - test/core/transport/chttp2/hpack_encoder_test.c + test/core/transport/chttp2/hpack_encoder_test.cc ) @@ -5606,7 +5606,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(chttp2_stream_map_test - test/core/transport/chttp2/stream_map_test.c + test/core/transport/chttp2/stream_map_test.cc ) @@ -5636,7 +5636,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(chttp2_varint_test - test/core/transport/chttp2/varint_test.c + test/core/transport/chttp2/varint_test.cc ) @@ -5666,7 +5666,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(combiner_test - test/core/iomgr/combiner_test.c + test/core/iomgr/combiner_test.cc ) @@ -5696,7 +5696,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(compression_test - test/core/compression/compression_test.c + test/core/compression/compression_test.cc ) @@ -5726,7 +5726,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(concurrent_connectivity_test - test/core/surface/concurrent_connectivity_test.c + test/core/surface/concurrent_connectivity_test.cc ) @@ -5756,7 +5756,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(connection_refused_test - test/core/end2end/connection_refused_test.c + test/core/end2end/connection_refused_test.cc ) @@ -5786,7 +5786,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(dns_resolver_connectivity_test - test/core/client_channel/resolvers/dns_resolver_connectivity_test.c + test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc ) @@ -5816,7 +5816,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(dns_resolver_test - test/core/client_channel/resolvers/dns_resolver_test.c + test/core/client_channel/resolvers/dns_resolver_test.cc ) @@ -5847,7 +5847,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(dualstack_socket_test - test/core/end2end/dualstack_socket_test.c + test/core/end2end/dualstack_socket_test.cc ) @@ -5878,7 +5878,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(endpoint_pair_test - test/core/iomgr/endpoint_pair_test.c + test/core/iomgr/endpoint_pair_test.cc ) @@ -5908,7 +5908,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(error_test - test/core/iomgr/error_test.c + test/core/iomgr/error_test.cc ) @@ -5939,7 +5939,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(ev_epollsig_linux_test - test/core/iomgr/ev_epollsig_linux_test.c + test/core/iomgr/ev_epollsig_linux_test.cc ) @@ -5970,7 +5970,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(fake_resolver_test - test/core/client_channel/resolvers/fake_resolver_test.c + test/core/client_channel/resolvers/fake_resolver_test.cc ) @@ -6001,8 +6001,8 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fake_transport_security_test - test/core/tsi/fake_transport_security_test.c - test/core/tsi/transport_security_test_lib.c + test/core/tsi/fake_transport_security_test.cc + test/core/tsi/transport_security_test_lib.cc ) @@ -6033,7 +6033,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fd_conservation_posix_test - test/core/iomgr/fd_conservation_posix_test.c + test/core/iomgr/fd_conservation_posix_test.cc ) @@ -6065,7 +6065,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fd_posix_test - test/core/iomgr/fd_posix_test.c + test/core/iomgr/fd_posix_test.cc ) @@ -6096,7 +6096,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(fling_client - test/core/fling/client.c + test/core/fling/client.cc ) @@ -6126,7 +6126,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(fling_server - test/core/fling/server.c + test/core/fling/server.cc ) @@ -6157,7 +6157,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fling_stream_test - test/core/fling/fling_stream_test.c + test/core/fling/fling_stream_test.cc ) @@ -6189,7 +6189,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fling_test - test/core/fling/fling_test.c + test/core/fling/fling_test.cc ) @@ -6322,7 +6322,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(goaway_server_test - test/core/end2end/goaway_server_test.c + test/core/end2end/goaway_server_test.cc ) @@ -6353,7 +6353,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_avl_test - test/core/support/avl_test.c + test/core/support/avl_test.cc ) @@ -6381,7 +6381,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_cmdline_test - test/core/support/cmdline_test.c + test/core/support/cmdline_test.cc ) @@ -6409,7 +6409,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_cpu_test - test/core/support/cpu_test.c + test/core/support/cpu_test.cc ) @@ -6437,7 +6437,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_env_test - test/core/support/env_test.c + test/core/support/env_test.cc ) @@ -6465,7 +6465,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_histogram_test - test/core/support/histogram_test.c + test/core/support/histogram_test.cc ) @@ -6493,7 +6493,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_host_port_test - test/core/support/host_port_test.c + test/core/support/host_port_test.cc ) @@ -6521,7 +6521,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_log_test - test/core/support/log_test.c + test/core/support/log_test.cc ) @@ -6549,7 +6549,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_mpscq_test - test/core/support/mpscq_test.c + test/core/support/mpscq_test.cc ) @@ -6577,7 +6577,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_spinlock_test - test/core/support/spinlock_test.c + test/core/support/spinlock_test.cc ) @@ -6605,7 +6605,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_stack_lockfree_test - test/core/support/stack_lockfree_test.c + test/core/support/stack_lockfree_test.cc ) @@ -6633,7 +6633,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_string_test - test/core/support/string_test.c + test/core/support/string_test.cc ) @@ -6661,7 +6661,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_sync_test - test/core/support/sync_test.c + test/core/support/sync_test.cc ) @@ -6689,7 +6689,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_thd_test - test/core/support/thd_test.c + test/core/support/thd_test.cc ) @@ -6717,7 +6717,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_time_test - test/core/support/time_test.c + test/core/support/time_test.cc ) @@ -6745,7 +6745,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_tls_test - test/core/support/tls_test.c + test/core/support/tls_test.cc ) @@ -6773,7 +6773,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_useful_test - test/core/support/useful_test.c + test/core/support/useful_test.cc ) @@ -6801,7 +6801,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_auth_context_test - test/core/security/auth_context_test.c + test/core/security/auth_context_test.cc ) @@ -6831,7 +6831,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_b64_test - test/core/slice/b64_test.c + test/core/slice/b64_test.cc ) @@ -6861,7 +6861,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_byte_buffer_reader_test - test/core/surface/byte_buffer_reader_test.c + test/core/surface/byte_buffer_reader_test.cc ) @@ -6891,7 +6891,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_channel_args_test - test/core/channel/channel_args_test.c + test/core/channel/channel_args_test.cc ) @@ -6921,7 +6921,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_channel_stack_builder_test - test/core/channel/channel_stack_builder_test.c + test/core/channel/channel_stack_builder_test.cc ) @@ -6951,7 +6951,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_channel_stack_test - test/core/channel/channel_stack_test.c + test/core/channel/channel_stack_test.cc ) @@ -6981,7 +6981,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_completion_queue_test - test/core/surface/completion_queue_test.c + test/core/surface/completion_queue_test.cc ) @@ -7011,7 +7011,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_completion_queue_threading_test - test/core/surface/completion_queue_threading_test.c + test/core/surface/completion_queue_threading_test.cc ) @@ -7040,7 +7040,7 @@ target_link_libraries(grpc_completion_queue_threading_test endif (gRPC_BUILD_TESTS) add_executable(grpc_create_jwt - test/core/security/create_jwt.c + test/core/security/create_jwt.cc ) @@ -7077,7 +7077,7 @@ endif() if (gRPC_BUILD_TESTS) add_executable(grpc_credentials_test - test/core/security/credentials_test.c + test/core/security/credentials_test.cc ) @@ -7107,7 +7107,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_fetch_oauth2 - test/core/security/fetch_oauth2.c + test/core/security/fetch_oauth2.cc ) @@ -7137,7 +7137,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_invalid_channel_args_test - test/core/surface/invalid_channel_args_test.c + test/core/surface/invalid_channel_args_test.cc ) @@ -7168,7 +7168,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(grpc_json_token_test - test/core/security/json_token_test.c + test/core/security/json_token_test.cc ) @@ -7199,7 +7199,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_jwt_verifier_test - test/core/security/jwt_verifier_test.c + test/core/security/jwt_verifier_test.cc ) @@ -7228,7 +7228,7 @@ target_link_libraries(grpc_jwt_verifier_test endif (gRPC_BUILD_TESTS) add_executable(grpc_print_google_default_creds_token - test/core/security/print_google_default_creds_token.c + test/core/security/print_google_default_creds_token.cc ) @@ -7264,7 +7264,7 @@ endif() if (gRPC_BUILD_TESTS) add_executable(grpc_security_connector_test - test/core/security/security_connector_test.c + test/core/security/security_connector_test.cc ) @@ -7293,7 +7293,7 @@ target_link_libraries(grpc_security_connector_test endif (gRPC_BUILD_TESTS) add_executable(grpc_verify_jwt - test/core/security/verify_jwt.c + test/core/security/verify_jwt.cc ) @@ -7330,7 +7330,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(handshake_client - test/core/handshake/client_ssl.c + test/core/handshake/client_ssl.cc ) @@ -7363,7 +7363,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(handshake_server - test/core/handshake/server_ssl.c + test/core/handshake/server_ssl.cc ) @@ -7395,7 +7395,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_parser_test - test/core/transport/chttp2/hpack_parser_test.c + test/core/transport/chttp2/hpack_parser_test.cc ) @@ -7425,7 +7425,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_table_test - test/core/transport/chttp2/hpack_table_test.c + test/core/transport/chttp2/hpack_table_test.cc ) @@ -7455,7 +7455,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_parser_test - test/core/http/parser_test.c + test/core/http/parser_test.cc ) @@ -7485,7 +7485,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(httpcli_format_request_test - test/core/http/format_request_test.c + test/core/http/format_request_test.cc ) @@ -7516,7 +7516,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(httpcli_test - test/core/http/httpcli_test.c + test/core/http/httpcli_test.cc ) @@ -7548,7 +7548,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(httpscli_test - test/core/http/httpscli_test.c + test/core/http/httpscli_test.cc ) @@ -7579,7 +7579,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(init_test - test/core/surface/init_test.c + test/core/surface/init_test.cc ) @@ -7609,7 +7609,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(invalid_call_argument_test - test/core/end2end/invalid_call_argument_test.c + test/core/end2end/invalid_call_argument_test.cc ) @@ -7639,7 +7639,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_rewrite - test/core/json/json_rewrite.c + test/core/json/json_rewrite.cc ) @@ -7667,7 +7667,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_rewrite_test - test/core/json/json_rewrite_test.c + test/core/json/json_rewrite_test.cc ) @@ -7697,7 +7697,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_stream_error_test - test/core/json/json_stream_error_test.c + test/core/json/json_stream_error_test.cc ) @@ -7727,7 +7727,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_test - test/core/json/json_test.c + test/core/json/json_test.cc ) @@ -7757,7 +7757,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(lame_client_test - test/core/surface/lame_client_test.c + test/core/surface/lame_client_test.cc ) @@ -7787,7 +7787,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(lb_policies_test - test/core/client_channel/lb_policies_test.c + test/core/client_channel/lb_policies_test.cc ) @@ -7817,7 +7817,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(load_file_test - test/core/iomgr/load_file_test.c + test/core/iomgr/load_file_test.cc ) @@ -7847,7 +7847,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(memory_profile_client - test/core/memory_usage/client.c + test/core/memory_usage/client.cc ) @@ -7877,7 +7877,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(memory_profile_server - test/core/memory_usage/server.c + test/core/memory_usage/server.cc ) @@ -7908,7 +7908,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(memory_profile_test - test/core/memory_usage/memory_usage_test.c + test/core/memory_usage/memory_usage_test.cc ) @@ -7939,7 +7939,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(message_compress_test - test/core/compression/message_compress_test.c + test/core/compression/message_compress_test.cc ) @@ -7969,7 +7969,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(minimal_stack_is_minimal_test - test/core/channel/minimal_stack_is_minimal_test.c + test/core/channel/minimal_stack_is_minimal_test.cc ) @@ -7999,7 +7999,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(mlog_test - test/core/census/mlog_test.c + test/core/census/mlog_test.cc ) @@ -8029,7 +8029,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(multiple_server_queues_test - test/core/end2end/multiple_server_queues_test.c + test/core/end2end/multiple_server_queues_test.cc ) @@ -8059,7 +8059,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(murmur_hash_test - test/core/support/murmur_hash_test.c + test/core/support/murmur_hash_test.cc ) @@ -8087,7 +8087,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(no_server_test - test/core/end2end/no_server_test.c + test/core/end2end/no_server_test.cc ) @@ -8117,7 +8117,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(num_external_connectivity_watchers_test - test/core/surface/num_external_connectivity_watchers_test.c + test/core/surface/num_external_connectivity_watchers_test.cc ) @@ -8147,7 +8147,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(parse_address_test - test/core/client_channel/parse_address_test.c + test/core/client_channel/parse_address_test.cc ) @@ -8177,7 +8177,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_encoding_test - test/core/slice/percent_encoding_test.c + test/core/slice/percent_encoding_test.cc ) @@ -8208,7 +8208,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(pollset_set_test - test/core/iomgr/pollset_set_test.c + test/core/iomgr/pollset_set_test.cc ) @@ -8240,7 +8240,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(resolve_address_posix_test - test/core/iomgr/resolve_address_posix_test.c + test/core/iomgr/resolve_address_posix_test.cc ) @@ -8271,7 +8271,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(resolve_address_test - test/core/iomgr/resolve_address_test.c + test/core/iomgr/resolve_address_test.cc ) @@ -8301,7 +8301,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(resource_quota_test - test/core/iomgr/resource_quota_test.c + test/core/iomgr/resource_quota_test.cc ) @@ -8331,7 +8331,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(secure_channel_create_test - test/core/surface/secure_channel_create_test.c + test/core/surface/secure_channel_create_test.cc ) @@ -8361,7 +8361,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(secure_endpoint_test - test/core/security/secure_endpoint_test.c + test/core/security/secure_endpoint_test.cc ) @@ -8391,7 +8391,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sequential_connectivity_test - test/core/surface/sequential_connectivity_test.c + test/core/surface/sequential_connectivity_test.cc ) @@ -8421,7 +8421,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_chttp2_test - test/core/surface/server_chttp2_test.c + test/core/surface/server_chttp2_test.cc ) @@ -8451,7 +8451,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_test - test/core/surface/server_test.c + test/core/surface/server_test.cc ) @@ -8481,7 +8481,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_buffer_test - test/core/slice/slice_buffer_test.c + test/core/slice/slice_buffer_test.cc ) @@ -8511,7 +8511,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_hash_table_test - test/core/slice/slice_hash_table_test.c + test/core/slice/slice_hash_table_test.cc ) @@ -8541,7 +8541,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_string_helpers_test - test/core/slice/slice_string_helpers_test.c + test/core/slice/slice_string_helpers_test.cc ) @@ -8571,7 +8571,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_test - test/core/slice/slice_test.c + test/core/slice/slice_test.cc ) @@ -8601,7 +8601,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sockaddr_resolver_test - test/core/client_channel/resolvers/sockaddr_resolver_test.c + test/core/client_channel/resolvers/sockaddr_resolver_test.cc ) @@ -8631,7 +8631,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sockaddr_utils_test - test/core/iomgr/sockaddr_utils_test.c + test/core/iomgr/sockaddr_utils_test.cc ) @@ -8662,7 +8662,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(socket_utils_test - test/core/iomgr/socket_utils_test.c + test/core/iomgr/socket_utils_test.cc ) @@ -8694,8 +8694,8 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(ssl_transport_security_test - test/core/tsi/ssl_transport_security_test.c - test/core/tsi/transport_security_test_lib.c + test/core/tsi/ssl_transport_security_test.cc + test/core/tsi/transport_security_test_lib.cc ) @@ -8725,7 +8725,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(status_conversion_test - test/core/transport/status_conversion_test.c + test/core/transport/status_conversion_test.cc ) @@ -8755,7 +8755,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(stream_compression_test - test/core/compression/stream_compression_test.c + test/core/compression/stream_compression_test.cc ) @@ -8785,7 +8785,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(stream_owned_slice_test - test/core/transport/stream_owned_slice_test.c + test/core/transport/stream_owned_slice_test.cc ) @@ -8816,7 +8816,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_client_posix_test - test/core/iomgr/tcp_client_posix_test.c + test/core/iomgr/tcp_client_posix_test.cc ) @@ -8847,7 +8847,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(tcp_client_uv_test - test/core/iomgr/tcp_client_uv_test.c + test/core/iomgr/tcp_client_uv_test.cc ) @@ -8878,7 +8878,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_posix_test - test/core/iomgr/tcp_posix_test.c + test/core/iomgr/tcp_posix_test.cc ) @@ -8910,7 +8910,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_server_posix_test - test/core/iomgr/tcp_server_posix_test.c + test/core/iomgr/tcp_server_posix_test.cc ) @@ -8941,7 +8941,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(tcp_server_uv_test - test/core/iomgr/tcp_server_uv_test.c + test/core/iomgr/tcp_server_uv_test.cc ) @@ -8971,7 +8971,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(time_averaged_stats_test - test/core/iomgr/time_averaged_stats_test.c + test/core/iomgr/time_averaged_stats_test.cc ) @@ -9001,7 +9001,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timeout_encoding_test - test/core/transport/timeout_encoding_test.c + test/core/transport/timeout_encoding_test.cc ) @@ -9031,7 +9031,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timer_heap_test - test/core/iomgr/timer_heap_test.c + test/core/iomgr/timer_heap_test.cc ) @@ -9061,7 +9061,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timer_list_test - test/core/iomgr/timer_list_test.c + test/core/iomgr/timer_list_test.cc ) @@ -9091,7 +9091,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(transport_connectivity_state_test - test/core/transport/connectivity_state_test.c + test/core/transport/connectivity_state_test.cc ) @@ -9121,7 +9121,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(transport_metadata_test - test/core/transport/metadata_test.c + test/core/transport/metadata_test.cc ) @@ -9152,7 +9152,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(transport_security_test - test/core/tsi/transport_security_test.c + test/core/tsi/transport_security_test.cc ) @@ -9184,7 +9184,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(udp_server_test - test/core/iomgr/udp_server_test.c + test/core/iomgr/udp_server_test.cc ) @@ -9215,7 +9215,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(uri_parser_test - test/core/client_channel/uri_parser_test.c + test/core/client_channel/uri_parser_test.cc ) @@ -9246,7 +9246,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(wakeup_fd_cv_test - test/core/iomgr/wakeup_fd_cv_test.c + test/core/iomgr/wakeup_fd_cv_test.cc ) @@ -13138,7 +13138,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(badreq_bad_client_test - test/core/bad_client/tests/badreq.c + test/core/bad_client/tests/badreq.cc ) @@ -13170,7 +13170,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(connection_prefix_bad_client_test - test/core/bad_client/tests/connection_prefix.c + test/core/bad_client/tests/connection_prefix.cc ) @@ -13202,7 +13202,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(head_of_line_blocking_bad_client_test - test/core/bad_client/tests/head_of_line_blocking.c + test/core/bad_client/tests/head_of_line_blocking.cc ) @@ -13234,7 +13234,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(headers_bad_client_test - test/core/bad_client/tests/headers.c + test/core/bad_client/tests/headers.cc ) @@ -13266,7 +13266,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(initial_settings_frame_bad_client_test - test/core/bad_client/tests/initial_settings_frame.c + test/core/bad_client/tests/initial_settings_frame.cc ) @@ -13298,7 +13298,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_registered_method_bad_client_test - test/core/bad_client/tests/server_registered_method.c + test/core/bad_client/tests/server_registered_method.cc ) @@ -13330,7 +13330,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(simple_request_bad_client_test - test/core/bad_client/tests/simple_request.c + test/core/bad_client/tests/simple_request.cc ) @@ -13362,7 +13362,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(unknown_frame_bad_client_test - test/core/bad_client/tests/unknown_frame.c + test/core/bad_client/tests/unknown_frame.cc ) @@ -13394,7 +13394,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(window_overflow_bad_client_test - test/core/bad_client/tests/window_overflow.c + test/core/bad_client/tests/window_overflow.cc ) @@ -13427,7 +13427,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bad_ssl_cert_server - test/core/bad_ssl/servers/cert.c + test/core/bad_ssl/servers/cert.cc ) @@ -13460,7 +13460,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bad_ssl_cert_test - test/core/bad_ssl/bad_ssl_test.c + test/core/bad_ssl/bad_ssl_test.cc ) @@ -13491,7 +13491,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_census_test - test/core/end2end/fixtures/h2_census.c + test/core/end2end/fixtures/h2_census.cc ) @@ -13522,7 +13522,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_compress_test - test/core/end2end/fixtures/h2_compress.c + test/core/end2end/fixtures/h2_compress.cc ) @@ -13553,7 +13553,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_fakesec_test - test/core/end2end/fixtures/h2_fakesec.c + test/core/end2end/fixtures/h2_fakesec.cc ) @@ -13585,7 +13585,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_fd_test - test/core/end2end/fixtures/h2_fd.c + test/core/end2end/fixtures/h2_fd.cc ) @@ -13617,7 +13617,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full_test - test/core/end2end/fixtures/h2_full.c + test/core/end2end/fixtures/h2_full.cc ) @@ -13649,7 +13649,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(h2_full+pipe_test - test/core/end2end/fixtures/h2_full+pipe.c + test/core/end2end/fixtures/h2_full+pipe.cc ) @@ -13681,7 +13681,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+trace_test - test/core/end2end/fixtures/h2_full+trace.c + test/core/end2end/fixtures/h2_full+trace.cc ) @@ -13712,7 +13712,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+workarounds_test - test/core/end2end/fixtures/h2_full+workarounds.c + test/core/end2end/fixtures/h2_full+workarounds.cc ) @@ -13743,7 +13743,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_http_proxy_test - test/core/end2end/fixtures/h2_http_proxy.c + test/core/end2end/fixtures/h2_http_proxy.cc ) @@ -13774,7 +13774,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_load_reporting_test - test/core/end2end/fixtures/h2_load_reporting.c + test/core/end2end/fixtures/h2_load_reporting.cc ) @@ -13805,7 +13805,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_oauth2_test - test/core/end2end/fixtures/h2_oauth2.c + test/core/end2end/fixtures/h2_oauth2.cc ) @@ -13836,7 +13836,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_proxy_test - test/core/end2end/fixtures/h2_proxy.c + test/core/end2end/fixtures/h2_proxy.cc ) @@ -13867,7 +13867,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_test - test/core/end2end/fixtures/h2_sockpair.c + test/core/end2end/fixtures/h2_sockpair.cc ) @@ -13898,7 +13898,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair+trace_test - test/core/end2end/fixtures/h2_sockpair+trace.c + test/core/end2end/fixtures/h2_sockpair+trace.cc ) @@ -13929,7 +13929,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_1byte_test - test/core/end2end/fixtures/h2_sockpair_1byte.c + test/core/end2end/fixtures/h2_sockpair_1byte.cc ) @@ -13960,7 +13960,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_ssl_test - test/core/end2end/fixtures/h2_ssl.c + test/core/end2end/fixtures/h2_ssl.cc ) @@ -13991,7 +13991,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_ssl_proxy_test - test/core/end2end/fixtures/h2_ssl_proxy.c + test/core/end2end/fixtures/h2_ssl_proxy.cc ) @@ -14023,7 +14023,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_uds_test - test/core/end2end/fixtures/h2_uds.c + test/core/end2end/fixtures/h2_uds.cc ) @@ -14055,7 +14055,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(inproc_test - test/core/end2end/fixtures/inproc.c + test/core/end2end/fixtures/inproc.cc ) @@ -14086,7 +14086,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_census_nosec_test - test/core/end2end/fixtures/h2_census.c + test/core/end2end/fixtures/h2_census.cc ) @@ -14117,7 +14117,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_compress_nosec_test - test/core/end2end/fixtures/h2_compress.c + test/core/end2end/fixtures/h2_compress.cc ) @@ -14149,7 +14149,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_fd_nosec_test - test/core/end2end/fixtures/h2_fd.c + test/core/end2end/fixtures/h2_fd.cc ) @@ -14181,7 +14181,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full_nosec_test - test/core/end2end/fixtures/h2_full.c + test/core/end2end/fixtures/h2_full.cc ) @@ -14213,7 +14213,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(h2_full+pipe_nosec_test - test/core/end2end/fixtures/h2_full+pipe.c + test/core/end2end/fixtures/h2_full+pipe.cc ) @@ -14245,7 +14245,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+trace_nosec_test - test/core/end2end/fixtures/h2_full+trace.c + test/core/end2end/fixtures/h2_full+trace.cc ) @@ -14276,7 +14276,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+workarounds_nosec_test - test/core/end2end/fixtures/h2_full+workarounds.c + test/core/end2end/fixtures/h2_full+workarounds.cc ) @@ -14307,7 +14307,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_http_proxy_nosec_test - test/core/end2end/fixtures/h2_http_proxy.c + test/core/end2end/fixtures/h2_http_proxy.cc ) @@ -14338,7 +14338,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_load_reporting_nosec_test - test/core/end2end/fixtures/h2_load_reporting.c + test/core/end2end/fixtures/h2_load_reporting.cc ) @@ -14369,7 +14369,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_proxy_nosec_test - test/core/end2end/fixtures/h2_proxy.c + test/core/end2end/fixtures/h2_proxy.cc ) @@ -14400,7 +14400,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_nosec_test - test/core/end2end/fixtures/h2_sockpair.c + test/core/end2end/fixtures/h2_sockpair.cc ) @@ -14431,7 +14431,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair+trace_nosec_test - test/core/end2end/fixtures/h2_sockpair+trace.c + test/core/end2end/fixtures/h2_sockpair+trace.cc ) @@ -14462,7 +14462,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_1byte_nosec_test - test/core/end2end/fixtures/h2_sockpair_1byte.c + test/core/end2end/fixtures/h2_sockpair_1byte.cc ) @@ -14494,7 +14494,7 @@ if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_uds_nosec_test - test/core/end2end/fixtures/h2_uds.c + test/core/end2end/fixtures/h2_uds.cc ) @@ -14526,7 +14526,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(inproc_nosec_test - test/core/end2end/fixtures/inproc.c + test/core/end2end/fixtures/inproc.cc ) @@ -14733,7 +14733,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(api_fuzzer_one_entry - test/core/end2end/fuzzers/api_fuzzer.c + test/core/end2end/fuzzers/api_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14764,7 +14764,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(client_fuzzer_one_entry - test/core/end2end/fuzzers/client_fuzzer.c + test/core/end2end/fuzzers/client_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14795,7 +14795,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_parser_fuzzer_test_one_entry - test/core/transport/chttp2/hpack_parser_fuzzer_test.c + test/core/transport/chttp2/hpack_parser_fuzzer_test.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14826,7 +14826,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_request_fuzzer_test_one_entry - test/core/http/request_fuzzer.c + test/core/http/request_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14857,7 +14857,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_response_fuzzer_test_one_entry - test/core/http/response_fuzzer.c + test/core/http/response_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14888,7 +14888,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_fuzzer_test_one_entry - test/core/json/fuzzer.c + test/core/json/fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14919,7 +14919,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(nanopb_fuzzer_response_test_one_entry - test/core/nanopb/fuzzer_response.c + test/core/nanopb/fuzzer_response.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14950,7 +14950,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(nanopb_fuzzer_serverlist_test_one_entry - test/core/nanopb/fuzzer_serverlist.c + test/core/nanopb/fuzzer_serverlist.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -14981,7 +14981,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_decode_fuzzer_one_entry - test/core/slice/percent_decode_fuzzer.c + test/core/slice/percent_decode_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -15012,7 +15012,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_encode_fuzzer_one_entry - test/core/slice/percent_encode_fuzzer.c + test/core/slice/percent_encode_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -15043,7 +15043,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_fuzzer_one_entry - test/core/end2end/fuzzers/server_fuzzer.c + test/core/end2end/fuzzers/server_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -15074,7 +15074,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(ssl_server_fuzzer_one_entry - test/core/security/ssl_server_fuzzer.c + test/core/security/ssl_server_fuzzer.cc test/core/util/one_corpus_entry_fuzzer.c ) @@ -15105,7 +15105,7 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(uri_fuzzer_test_one_entry - test/core/client_channel/uri_fuzzer_test.c + test/core/client_channel/uri_fuzzer_test.cc test/core/util/one_corpus_entry_fuzzer.c ) diff --git a/Makefile b/Makefile index bb02c9bdf0..da6a0f08d9 100644 --- a/Makefile +++ b/Makefile @@ -2930,7 +2930,7 @@ endif LIBGPR_TEST_UTIL_SRC = \ - test/core/util/test_config.c \ + test/core/util/test_config.cc \ PUBLIC_HEADERS_C += \ @@ -3607,26 +3607,26 @@ endif LIBGRPC_TEST_UTIL_SRC = \ - test/core/end2end/data/client_certs.c \ - test/core/end2end/data/server1_cert.c \ - test/core/end2end/data/server1_key.c \ - test/core/end2end/data/test_root_cert.c \ - test/core/security/oauth2_utils.c \ + test/core/end2end/data/client_certs.cc \ + test/core/end2end/data/server1_cert.cc \ + test/core/end2end/data/server1_key.cc \ + test/core/end2end/data/test_root_cert.cc \ + test/core/security/oauth2_utils.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ - test/core/end2end/cq_verifier.c \ - test/core/end2end/fixtures/http_proxy_fixture.c \ - test/core/end2end/fixtures/proxy.c \ - test/core/iomgr/endpoint_tests.c \ + test/core/end2end/cq_verifier.cc \ + test/core/end2end/fixtures/http_proxy_fixture.cc \ + test/core/end2end/fixtures/proxy.cc \ + test/core/iomgr/endpoint_tests.cc \ test/core/util/debugger_macros.cc \ - test/core/util/grpc_profiler.c \ - test/core/util/memory_counters.c \ - test/core/util/mock_endpoint.c \ - test/core/util/parse_hexstring.c \ - test/core/util/passthru_endpoint.c \ - test/core/util/port.c \ - test/core/util/port_server_client.c \ - test/core/util/slice_splitter.c \ - test/core/util/trickle_endpoint.c \ + test/core/util/grpc_profiler.cc \ + test/core/util/memory_counters.cc \ + test/core/util/mock_endpoint.cc \ + test/core/util/parse_hexstring.cc \ + test/core/util/passthru_endpoint.cc \ + test/core/util/port.cc \ + test/core/util/port_server_client.cc \ + test/core/util/slice_splitter.cc \ + test/core/util/trickle_endpoint.cc \ src/core/lib/backoff/backoff.cc \ src/core/lib/channel/channel_args.cc \ src/core/lib/channel/channel_stack.cc \ @@ -3868,20 +3868,20 @@ endif LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ - test/core/end2end/cq_verifier.c \ - test/core/end2end/fixtures/http_proxy_fixture.c \ - test/core/end2end/fixtures/proxy.c \ - test/core/iomgr/endpoint_tests.c \ + test/core/end2end/cq_verifier.cc \ + test/core/end2end/fixtures/http_proxy_fixture.cc \ + test/core/end2end/fixtures/proxy.cc \ + test/core/iomgr/endpoint_tests.cc \ test/core/util/debugger_macros.cc \ - test/core/util/grpc_profiler.c \ - test/core/util/memory_counters.c \ - test/core/util/mock_endpoint.c \ - test/core/util/parse_hexstring.c \ - test/core/util/passthru_endpoint.c \ - test/core/util/port.c \ - test/core/util/port_server_client.c \ - test/core/util/slice_splitter.c \ - test/core/util/trickle_endpoint.c \ + test/core/util/grpc_profiler.cc \ + test/core/util/memory_counters.cc \ + test/core/util/mock_endpoint.cc \ + test/core/util/parse_hexstring.cc \ + test/core/util/passthru_endpoint.cc \ + test/core/util/port.cc \ + test/core/util/port_server_client.cc \ + test/core/util/slice_splitter.cc \ + test/core/util/trickle_endpoint.cc \ src/core/lib/backoff/backoff.cc \ src/core/lib/channel/channel_args.cc \ src/core/lib/channel/channel_stack.cc \ @@ -4413,7 +4413,7 @@ endif LIBRECONNECT_SERVER_SRC = \ - test/core/util/reconnect_server.c \ + test/core/util/reconnect_server.cc \ PUBLIC_HEADERS_C += \ @@ -4452,7 +4452,7 @@ endif LIBTEST_TCP_SERVER_SRC = \ - test/core/util/test_tcp_server.c \ + test/core/util/test_tcp_server.cc \ PUBLIC_HEADERS_C += \ @@ -8452,7 +8452,7 @@ endif LIBBAD_CLIENT_TEST_SRC = \ - test/core/bad_client/bad_client.c \ + test/core/bad_client/bad_client.cc \ PUBLIC_HEADERS_C += \ @@ -8491,7 +8491,7 @@ endif LIBBAD_SSL_TEST_SERVER_SRC = \ - test/core/bad_ssl/server_common.c \ + test/core/bad_ssl/server_common.cc \ PUBLIC_HEADERS_C += \ @@ -8530,67 +8530,67 @@ endif LIBEND2END_TESTS_SRC = \ - test/core/end2end/end2end_tests.c \ - test/core/end2end/end2end_test_utils.c \ - test/core/end2end/tests/authority_not_supported.c \ - test/core/end2end/tests/bad_hostname.c \ - test/core/end2end/tests/bad_ping.c \ - test/core/end2end/tests/binary_metadata.c \ - test/core/end2end/tests/call_creds.c \ - test/core/end2end/tests/cancel_after_accept.c \ - test/core/end2end/tests/cancel_after_client_done.c \ - test/core/end2end/tests/cancel_after_invoke.c \ - test/core/end2end/tests/cancel_after_round_trip.c \ - test/core/end2end/tests/cancel_before_invoke.c \ - test/core/end2end/tests/cancel_in_a_vacuum.c \ - test/core/end2end/tests/cancel_with_status.c \ - test/core/end2end/tests/compressed_payload.c \ - test/core/end2end/tests/connectivity.c \ - test/core/end2end/tests/default_host.c \ - test/core/end2end/tests/disappearing_server.c \ - test/core/end2end/tests/empty_batch.c \ - test/core/end2end/tests/filter_call_init_fails.c \ - test/core/end2end/tests/filter_causes_close.c \ - test/core/end2end/tests/filter_latency.c \ - test/core/end2end/tests/graceful_server_shutdown.c \ - test/core/end2end/tests/high_initial_seqno.c \ - test/core/end2end/tests/hpack_size.c \ - test/core/end2end/tests/idempotent_request.c \ - test/core/end2end/tests/invoke_large_request.c \ - test/core/end2end/tests/keepalive_timeout.c \ - test/core/end2end/tests/large_metadata.c \ - test/core/end2end/tests/load_reporting_hook.c \ - test/core/end2end/tests/max_concurrent_streams.c \ - test/core/end2end/tests/max_connection_age.c \ - test/core/end2end/tests/max_connection_idle.c \ - test/core/end2end/tests/max_message_length.c \ - test/core/end2end/tests/negative_deadline.c \ - test/core/end2end/tests/network_status_change.c \ - test/core/end2end/tests/no_logging.c \ - test/core/end2end/tests/no_op.c \ - test/core/end2end/tests/payload.c \ - test/core/end2end/tests/ping.c \ - test/core/end2end/tests/ping_pong_streaming.c \ - test/core/end2end/tests/proxy_auth.c \ - test/core/end2end/tests/registered_call.c \ - test/core/end2end/tests/request_with_flags.c \ - test/core/end2end/tests/request_with_payload.c \ - test/core/end2end/tests/resource_quota_server.c \ - test/core/end2end/tests/server_finishes_request.c \ - test/core/end2end/tests/shutdown_finishes_calls.c \ - test/core/end2end/tests/shutdown_finishes_tags.c \ - test/core/end2end/tests/simple_cacheable_request.c \ - test/core/end2end/tests/simple_delayed_request.c \ - test/core/end2end/tests/simple_metadata.c \ - test/core/end2end/tests/simple_request.c \ - test/core/end2end/tests/stream_compression_compressed_payload.c \ - test/core/end2end/tests/stream_compression_payload.c \ - test/core/end2end/tests/stream_compression_ping_pong_streaming.c \ - test/core/end2end/tests/streaming_error_response.c \ - test/core/end2end/tests/trailing_metadata.c \ - test/core/end2end/tests/workaround_cronet_compression.c \ - test/core/end2end/tests/write_buffering.c \ - test/core/end2end/tests/write_buffering_at_end.c \ + test/core/end2end/end2end_tests.cc \ + test/core/end2end/end2end_test_utils.cc \ + test/core/end2end/tests/authority_not_supported.cc \ + test/core/end2end/tests/bad_hostname.cc \ + test/core/end2end/tests/bad_ping.cc \ + test/core/end2end/tests/binary_metadata.cc \ + test/core/end2end/tests/call_creds.cc \ + test/core/end2end/tests/cancel_after_accept.cc \ + test/core/end2end/tests/cancel_after_client_done.cc \ + test/core/end2end/tests/cancel_after_invoke.cc \ + test/core/end2end/tests/cancel_after_round_trip.cc \ + test/core/end2end/tests/cancel_before_invoke.cc \ + test/core/end2end/tests/cancel_in_a_vacuum.cc \ + test/core/end2end/tests/cancel_with_status.cc \ + test/core/end2end/tests/compressed_payload.cc \ + test/core/end2end/tests/connectivity.cc \ + test/core/end2end/tests/default_host.cc \ + test/core/end2end/tests/disappearing_server.cc \ + test/core/end2end/tests/empty_batch.cc \ + test/core/end2end/tests/filter_call_init_fails.cc \ + test/core/end2end/tests/filter_causes_close.cc \ + test/core/end2end/tests/filter_latency.cc \ + test/core/end2end/tests/graceful_server_shutdown.cc \ + test/core/end2end/tests/high_initial_seqno.cc \ + test/core/end2end/tests/hpack_size.cc \ + test/core/end2end/tests/idempotent_request.cc \ + test/core/end2end/tests/invoke_large_request.cc \ + test/core/end2end/tests/keepalive_timeout.cc \ + test/core/end2end/tests/large_metadata.cc \ + test/core/end2end/tests/load_reporting_hook.cc \ + test/core/end2end/tests/max_concurrent_streams.cc \ + test/core/end2end/tests/max_connection_age.cc \ + test/core/end2end/tests/max_connection_idle.cc \ + test/core/end2end/tests/max_message_length.cc \ + test/core/end2end/tests/negative_deadline.cc \ + test/core/end2end/tests/network_status_change.cc \ + test/core/end2end/tests/no_logging.cc \ + test/core/end2end/tests/no_op.cc \ + test/core/end2end/tests/payload.cc \ + test/core/end2end/tests/ping.cc \ + test/core/end2end/tests/ping_pong_streaming.cc \ + test/core/end2end/tests/proxy_auth.cc \ + test/core/end2end/tests/registered_call.cc \ + test/core/end2end/tests/request_with_flags.cc \ + test/core/end2end/tests/request_with_payload.cc \ + test/core/end2end/tests/resource_quota_server.cc \ + test/core/end2end/tests/server_finishes_request.cc \ + test/core/end2end/tests/shutdown_finishes_calls.cc \ + test/core/end2end/tests/shutdown_finishes_tags.cc \ + test/core/end2end/tests/simple_cacheable_request.cc \ + test/core/end2end/tests/simple_delayed_request.cc \ + test/core/end2end/tests/simple_metadata.cc \ + test/core/end2end/tests/simple_request.cc \ + test/core/end2end/tests/stream_compression_compressed_payload.cc \ + test/core/end2end/tests/stream_compression_payload.cc \ + test/core/end2end/tests/stream_compression_ping_pong_streaming.cc \ + test/core/end2end/tests/streaming_error_response.cc \ + test/core/end2end/tests/trailing_metadata.cc \ + test/core/end2end/tests/workaround_cronet_compression.cc \ + test/core/end2end/tests/write_buffering.cc \ + test/core/end2end/tests/write_buffering_at_end.cc \ PUBLIC_HEADERS_C += \ @@ -8629,66 +8629,66 @@ endif LIBEND2END_NOSEC_TESTS_SRC = \ - test/core/end2end/end2end_nosec_tests.c \ - test/core/end2end/end2end_test_utils.c \ - test/core/end2end/tests/authority_not_supported.c \ - test/core/end2end/tests/bad_hostname.c \ - test/core/end2end/tests/bad_ping.c \ - test/core/end2end/tests/binary_metadata.c \ - test/core/end2end/tests/cancel_after_accept.c \ - test/core/end2end/tests/cancel_after_client_done.c \ - test/core/end2end/tests/cancel_after_invoke.c \ - test/core/end2end/tests/cancel_after_round_trip.c \ - test/core/end2end/tests/cancel_before_invoke.c \ - test/core/end2end/tests/cancel_in_a_vacuum.c \ - test/core/end2end/tests/cancel_with_status.c \ - test/core/end2end/tests/compressed_payload.c \ - test/core/end2end/tests/connectivity.c \ - test/core/end2end/tests/default_host.c \ - test/core/end2end/tests/disappearing_server.c \ - test/core/end2end/tests/empty_batch.c \ - test/core/end2end/tests/filter_call_init_fails.c \ - test/core/end2end/tests/filter_causes_close.c \ - test/core/end2end/tests/filter_latency.c \ - test/core/end2end/tests/graceful_server_shutdown.c \ - test/core/end2end/tests/high_initial_seqno.c \ - test/core/end2end/tests/hpack_size.c \ - test/core/end2end/tests/idempotent_request.c \ - test/core/end2end/tests/invoke_large_request.c \ - test/core/end2end/tests/keepalive_timeout.c \ - test/core/end2end/tests/large_metadata.c \ - test/core/end2end/tests/load_reporting_hook.c \ - test/core/end2end/tests/max_concurrent_streams.c \ - test/core/end2end/tests/max_connection_age.c \ - test/core/end2end/tests/max_connection_idle.c \ - test/core/end2end/tests/max_message_length.c \ - test/core/end2end/tests/negative_deadline.c \ - test/core/end2end/tests/network_status_change.c \ - test/core/end2end/tests/no_logging.c \ - test/core/end2end/tests/no_op.c \ - test/core/end2end/tests/payload.c \ - test/core/end2end/tests/ping.c \ - test/core/end2end/tests/ping_pong_streaming.c \ - test/core/end2end/tests/proxy_auth.c \ - test/core/end2end/tests/registered_call.c \ - test/core/end2end/tests/request_with_flags.c \ - test/core/end2end/tests/request_with_payload.c \ - test/core/end2end/tests/resource_quota_server.c \ - test/core/end2end/tests/server_finishes_request.c \ - test/core/end2end/tests/shutdown_finishes_calls.c \ - test/core/end2end/tests/shutdown_finishes_tags.c \ - test/core/end2end/tests/simple_cacheable_request.c \ - test/core/end2end/tests/simple_delayed_request.c \ - test/core/end2end/tests/simple_metadata.c \ - test/core/end2end/tests/simple_request.c \ - test/core/end2end/tests/stream_compression_compressed_payload.c \ - test/core/end2end/tests/stream_compression_payload.c \ - test/core/end2end/tests/stream_compression_ping_pong_streaming.c \ - test/core/end2end/tests/streaming_error_response.c \ - test/core/end2end/tests/trailing_metadata.c \ - test/core/end2end/tests/workaround_cronet_compression.c \ - test/core/end2end/tests/write_buffering.c \ - test/core/end2end/tests/write_buffering_at_end.c \ + test/core/end2end/end2end_nosec_tests.cc \ + test/core/end2end/end2end_test_utils.cc \ + test/core/end2end/tests/authority_not_supported.cc \ + test/core/end2end/tests/bad_hostname.cc \ + test/core/end2end/tests/bad_ping.cc \ + test/core/end2end/tests/binary_metadata.cc \ + test/core/end2end/tests/cancel_after_accept.cc \ + test/core/end2end/tests/cancel_after_client_done.cc \ + test/core/end2end/tests/cancel_after_invoke.cc \ + test/core/end2end/tests/cancel_after_round_trip.cc \ + test/core/end2end/tests/cancel_before_invoke.cc \ + test/core/end2end/tests/cancel_in_a_vacuum.cc \ + test/core/end2end/tests/cancel_with_status.cc \ + test/core/end2end/tests/compressed_payload.cc \ + test/core/end2end/tests/connectivity.cc \ + test/core/end2end/tests/default_host.cc \ + test/core/end2end/tests/disappearing_server.cc \ + test/core/end2end/tests/empty_batch.cc \ + test/core/end2end/tests/filter_call_init_fails.cc \ + test/core/end2end/tests/filter_causes_close.cc \ + test/core/end2end/tests/filter_latency.cc \ + test/core/end2end/tests/graceful_server_shutdown.cc \ + test/core/end2end/tests/high_initial_seqno.cc \ + test/core/end2end/tests/hpack_size.cc \ + test/core/end2end/tests/idempotent_request.cc \ + test/core/end2end/tests/invoke_large_request.cc \ + test/core/end2end/tests/keepalive_timeout.cc \ + test/core/end2end/tests/large_metadata.cc \ + test/core/end2end/tests/load_reporting_hook.cc \ + test/core/end2end/tests/max_concurrent_streams.cc \ + test/core/end2end/tests/max_connection_age.cc \ + test/core/end2end/tests/max_connection_idle.cc \ + test/core/end2end/tests/max_message_length.cc \ + test/core/end2end/tests/negative_deadline.cc \ + test/core/end2end/tests/network_status_change.cc \ + test/core/end2end/tests/no_logging.cc \ + test/core/end2end/tests/no_op.cc \ + test/core/end2end/tests/payload.cc \ + test/core/end2end/tests/ping.cc \ + test/core/end2end/tests/ping_pong_streaming.cc \ + test/core/end2end/tests/proxy_auth.cc \ + test/core/end2end/tests/registered_call.cc \ + test/core/end2end/tests/request_with_flags.cc \ + test/core/end2end/tests/request_with_payload.cc \ + test/core/end2end/tests/resource_quota_server.cc \ + test/core/end2end/tests/server_finishes_request.cc \ + test/core/end2end/tests/shutdown_finishes_calls.cc \ + test/core/end2end/tests/shutdown_finishes_tags.cc \ + test/core/end2end/tests/simple_cacheable_request.cc \ + test/core/end2end/tests/simple_delayed_request.cc \ + test/core/end2end/tests/simple_metadata.cc \ + test/core/end2end/tests/simple_request.cc \ + test/core/end2end/tests/stream_compression_compressed_payload.cc \ + test/core/end2end/tests/stream_compression_payload.cc \ + test/core/end2end/tests/stream_compression_ping_pong_streaming.cc \ + test/core/end2end/tests/streaming_error_response.cc \ + test/core/end2end/tests/trailing_metadata.cc \ + test/core/end2end/tests/workaround_cronet_compression.cc \ + test/core/end2end/tests/write_buffering.cc \ + test/core/end2end/tests/write_buffering_at_end.cc \ PUBLIC_HEADERS_C += \ @@ -8717,7 +8717,7 @@ endif ALARM_TEST_SRC = \ - test/core/surface/alarm_test.c \ + test/core/surface/alarm_test.cc \ ALARM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8749,7 +8749,7 @@ endif ALGORITHM_TEST_SRC = \ - test/core/compression/algorithm_test.c \ + test/core/compression/algorithm_test.cc \ ALGORITHM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALGORITHM_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8781,7 +8781,7 @@ endif ALLOC_TEST_SRC = \ - test/core/support/alloc_test.c \ + test/core/support/alloc_test.cc \ ALLOC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALLOC_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8813,7 +8813,7 @@ endif ALPN_TEST_SRC = \ - test/core/transport/chttp2/alpn_test.c \ + test/core/transport/chttp2/alpn_test.cc \ ALPN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALPN_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8845,7 +8845,7 @@ endif API_FUZZER_SRC = \ - test/core/end2end/fuzzers/api_fuzzer.c \ + test/core/end2end/fuzzers/api_fuzzer.cc \ API_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -8877,7 +8877,7 @@ endif ARENA_TEST_SRC = \ - test/core/support/arena_test.c \ + test/core/support/arena_test.cc \ ARENA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ARENA_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8909,7 +8909,7 @@ endif BACKOFF_TEST_SRC = \ - test/core/backoff/backoff_test.c \ + test/core/backoff/backoff_test.cc \ BACKOFF_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BACKOFF_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8941,7 +8941,7 @@ endif BAD_SERVER_RESPONSE_TEST_SRC = \ - test/core/end2end/bad_server_response_test.c \ + test/core/end2end/bad_server_response_test.cc \ BAD_SERVER_RESPONSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SERVER_RESPONSE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -8973,7 +8973,7 @@ endif BIN_DECODER_TEST_SRC = \ - test/core/transport/chttp2/bin_decoder_test.c \ + test/core/transport/chttp2/bin_decoder_test.cc \ BIN_DECODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BIN_DECODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9005,7 +9005,7 @@ endif BIN_ENCODER_TEST_SRC = \ - test/core/transport/chttp2/bin_encoder_test.c \ + test/core/transport/chttp2/bin_encoder_test.cc \ BIN_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BIN_ENCODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9037,7 +9037,7 @@ endif BYTE_STREAM_TEST_SRC = \ - test/core/transport/byte_stream_test.c \ + test/core/transport/byte_stream_test.cc \ BYTE_STREAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BYTE_STREAM_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9069,7 +9069,7 @@ endif CENSUS_CONTEXT_TEST_SRC = \ - test/core/census/context_test.c \ + test/core/census/context_test.cc \ CENSUS_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9101,7 +9101,7 @@ endif CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC = \ - test/core/census/intrusive_hash_map_test.c \ + test/core/census/intrusive_hash_map_test.cc \ CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9133,7 +9133,7 @@ endif CENSUS_RESOURCE_TEST_SRC = \ - test/core/census/resource_test.c \ + test/core/census/resource_test.cc \ CENSUS_RESOURCE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_RESOURCE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9165,7 +9165,7 @@ endif CENSUS_TRACE_CONTEXT_TEST_SRC = \ - test/core/census/trace_context_test.c \ + test/core/census/trace_context_test.cc \ CENSUS_TRACE_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9197,7 +9197,7 @@ endif CHANNEL_CREATE_TEST_SRC = \ - test/core/surface/channel_create_test.c \ + test/core/surface/channel_create_test.cc \ CHANNEL_CREATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNEL_CREATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9229,7 +9229,7 @@ endif CHECK_EPOLLEXCLUSIVE_SRC = \ - test/build/check_epollexclusive.c \ + test/build/check_epollexclusive.cc \ CHECK_EPOLLEXCLUSIVE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHECK_EPOLLEXCLUSIVE_SRC)))) ifeq ($(NO_SECURE),true) @@ -9261,7 +9261,7 @@ endif CHTTP2_HPACK_ENCODER_TEST_SRC = \ - test/core/transport/chttp2/hpack_encoder_test.c \ + test/core/transport/chttp2/hpack_encoder_test.cc \ CHTTP2_HPACK_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_HPACK_ENCODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9293,7 +9293,7 @@ endif CHTTP2_STREAM_MAP_TEST_SRC = \ - test/core/transport/chttp2/stream_map_test.c \ + test/core/transport/chttp2/stream_map_test.cc \ CHTTP2_STREAM_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STREAM_MAP_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9325,7 +9325,7 @@ endif CHTTP2_VARINT_TEST_SRC = \ - test/core/transport/chttp2/varint_test.c \ + test/core/transport/chttp2/varint_test.cc \ CHTTP2_VARINT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_VARINT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9357,7 +9357,7 @@ endif CLIENT_FUZZER_SRC = \ - test/core/end2end/fuzzers/client_fuzzer.c \ + test/core/end2end/fuzzers/client_fuzzer.cc \ CLIENT_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -9389,7 +9389,7 @@ endif COMBINER_TEST_SRC = \ - test/core/iomgr/combiner_test.c \ + test/core/iomgr/combiner_test.cc \ COMBINER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMBINER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9421,7 +9421,7 @@ endif COMPRESSION_TEST_SRC = \ - test/core/compression/compression_test.c \ + test/core/compression/compression_test.cc \ COMPRESSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMPRESSION_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9453,7 +9453,7 @@ endif CONCURRENT_CONNECTIVITY_TEST_SRC = \ - test/core/surface/concurrent_connectivity_test.c \ + test/core/surface/concurrent_connectivity_test.cc \ CONCURRENT_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONCURRENT_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9485,7 +9485,7 @@ endif CONNECTION_REFUSED_TEST_SRC = \ - test/core/end2end/connection_refused_test.c \ + test/core/end2end/connection_refused_test.cc \ CONNECTION_REFUSED_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONNECTION_REFUSED_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9517,7 +9517,7 @@ endif DNS_RESOLVER_CONNECTIVITY_TEST_SRC = \ - test/core/client_channel/resolvers/dns_resolver_connectivity_test.c \ + test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc \ DNS_RESOLVER_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9549,7 +9549,7 @@ endif DNS_RESOLVER_TEST_SRC = \ - test/core/client_channel/resolvers/dns_resolver_test.c \ + test/core/client_channel/resolvers/dns_resolver_test.cc \ DNS_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9581,7 +9581,7 @@ endif DUALSTACK_SOCKET_TEST_SRC = \ - test/core/end2end/dualstack_socket_test.c \ + test/core/end2end/dualstack_socket_test.cc \ DUALSTACK_SOCKET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DUALSTACK_SOCKET_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9613,7 +9613,7 @@ endif ENDPOINT_PAIR_TEST_SRC = \ - test/core/iomgr/endpoint_pair_test.c \ + test/core/iomgr/endpoint_pair_test.cc \ ENDPOINT_PAIR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ENDPOINT_PAIR_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9645,7 +9645,7 @@ endif ERROR_TEST_SRC = \ - test/core/iomgr/error_test.c \ + test/core/iomgr/error_test.cc \ ERROR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ERROR_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9677,7 +9677,7 @@ endif EV_EPOLLSIG_LINUX_TEST_SRC = \ - test/core/iomgr/ev_epollsig_linux_test.c \ + test/core/iomgr/ev_epollsig_linux_test.cc \ EV_EPOLLSIG_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLLSIG_LINUX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9709,7 +9709,7 @@ endif FAKE_RESOLVER_TEST_SRC = \ - test/core/client_channel/resolvers/fake_resolver_test.c \ + test/core/client_channel/resolvers/fake_resolver_test.cc \ FAKE_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FAKE_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9741,8 +9741,8 @@ endif FAKE_TRANSPORT_SECURITY_TEST_SRC = \ - test/core/tsi/fake_transport_security_test.c \ - test/core/tsi/transport_security_test_lib.c \ + test/core/tsi/fake_transport_security_test.cc \ + test/core/tsi/transport_security_test_lib.cc \ FAKE_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FAKE_TRANSPORT_SECURITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9776,7 +9776,7 @@ endif FD_CONSERVATION_POSIX_TEST_SRC = \ - test/core/iomgr/fd_conservation_posix_test.c \ + test/core/iomgr/fd_conservation_posix_test.cc \ FD_CONSERVATION_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_CONSERVATION_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9808,7 +9808,7 @@ endif FD_POSIX_TEST_SRC = \ - test/core/iomgr/fd_posix_test.c \ + test/core/iomgr/fd_posix_test.cc \ FD_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9840,7 +9840,7 @@ endif FLING_CLIENT_SRC = \ - test/core/fling/client.c \ + test/core/fling/client.cc \ FLING_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) @@ -9872,7 +9872,7 @@ endif FLING_SERVER_SRC = \ - test/core/fling/server.c \ + test/core/fling/server.cc \ FLING_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -9904,7 +9904,7 @@ endif FLING_STREAM_TEST_SRC = \ - test/core/fling/fling_stream_test.c \ + test/core/fling/fling_stream_test.cc \ FLING_STREAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_STREAM_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -9936,7 +9936,7 @@ endif FLING_TEST_SRC = \ - test/core/fling/fling_test.c \ + test/core/fling/fling_test.cc \ FLING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10064,7 +10064,7 @@ endif GOAWAY_SERVER_TEST_SRC = \ - test/core/end2end/goaway_server_test.c \ + test/core/end2end/goaway_server_test.cc \ GOAWAY_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GOAWAY_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10096,7 +10096,7 @@ endif GPR_AVL_TEST_SRC = \ - test/core/support/avl_test.c \ + test/core/support/avl_test.cc \ GPR_AVL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_AVL_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10128,7 +10128,7 @@ endif GPR_CMDLINE_TEST_SRC = \ - test/core/support/cmdline_test.c \ + test/core/support/cmdline_test.cc \ GPR_CMDLINE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CMDLINE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10160,7 +10160,7 @@ endif GPR_CPU_TEST_SRC = \ - test/core/support/cpu_test.c \ + test/core/support/cpu_test.cc \ GPR_CPU_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CPU_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10192,7 +10192,7 @@ endif GPR_ENV_TEST_SRC = \ - test/core/support/env_test.c \ + test/core/support/env_test.cc \ GPR_ENV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_ENV_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10224,7 +10224,7 @@ endif GPR_HISTOGRAM_TEST_SRC = \ - test/core/support/histogram_test.c \ + test/core/support/histogram_test.cc \ GPR_HISTOGRAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HISTOGRAM_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10256,7 +10256,7 @@ endif GPR_HOST_PORT_TEST_SRC = \ - test/core/support/host_port_test.c \ + test/core/support/host_port_test.cc \ GPR_HOST_PORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HOST_PORT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10288,7 +10288,7 @@ endif GPR_LOG_TEST_SRC = \ - test/core/support/log_test.c \ + test/core/support/log_test.cc \ GPR_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOG_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10320,7 +10320,7 @@ endif GPR_MPSCQ_TEST_SRC = \ - test/core/support/mpscq_test.c \ + test/core/support/mpscq_test.cc \ GPR_MPSCQ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MPSCQ_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10352,7 +10352,7 @@ endif GPR_SPINLOCK_TEST_SRC = \ - test/core/support/spinlock_test.c \ + test/core/support/spinlock_test.cc \ GPR_SPINLOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SPINLOCK_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10384,7 +10384,7 @@ endif GPR_STACK_LOCKFREE_TEST_SRC = \ - test/core/support/stack_lockfree_test.c \ + test/core/support/stack_lockfree_test.cc \ GPR_STACK_LOCKFREE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STACK_LOCKFREE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10416,7 +10416,7 @@ endif GPR_STRING_TEST_SRC = \ - test/core/support/string_test.c \ + test/core/support/string_test.cc \ GPR_STRING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STRING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10448,7 +10448,7 @@ endif GPR_SYNC_TEST_SRC = \ - test/core/support/sync_test.c \ + test/core/support/sync_test.cc \ GPR_SYNC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SYNC_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10480,7 +10480,7 @@ endif GPR_THD_TEST_SRC = \ - test/core/support/thd_test.c \ + test/core/support/thd_test.cc \ GPR_THD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_THD_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10512,7 +10512,7 @@ endif GPR_TIME_TEST_SRC = \ - test/core/support/time_test.c \ + test/core/support/time_test.cc \ GPR_TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TIME_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10544,7 +10544,7 @@ endif GPR_TLS_TEST_SRC = \ - test/core/support/tls_test.c \ + test/core/support/tls_test.cc \ GPR_TLS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TLS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10576,7 +10576,7 @@ endif GPR_USEFUL_TEST_SRC = \ - test/core/support/useful_test.c \ + test/core/support/useful_test.cc \ GPR_USEFUL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_USEFUL_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10608,7 +10608,7 @@ endif GRPC_AUTH_CONTEXT_TEST_SRC = \ - test/core/security/auth_context_test.c \ + test/core/security/auth_context_test.cc \ GRPC_AUTH_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_AUTH_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10640,7 +10640,7 @@ endif GRPC_B64_TEST_SRC = \ - test/core/slice/b64_test.c \ + test/core/slice/b64_test.cc \ GRPC_B64_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_B64_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10672,7 +10672,7 @@ endif GRPC_BYTE_BUFFER_READER_TEST_SRC = \ - test/core/surface/byte_buffer_reader_test.c \ + test/core/surface/byte_buffer_reader_test.cc \ GRPC_BYTE_BUFFER_READER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_BYTE_BUFFER_READER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10704,7 +10704,7 @@ endif GRPC_CHANNEL_ARGS_TEST_SRC = \ - test/core/channel/channel_args_test.c \ + test/core/channel/channel_args_test.cc \ GRPC_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_ARGS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10736,7 +10736,7 @@ endif GRPC_CHANNEL_STACK_BUILDER_TEST_SRC = \ - test/core/channel/channel_stack_builder_test.c \ + test/core/channel/channel_stack_builder_test.cc \ GRPC_CHANNEL_STACK_BUILDER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_STACK_BUILDER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10768,7 +10768,7 @@ endif GRPC_CHANNEL_STACK_TEST_SRC = \ - test/core/channel/channel_stack_test.c \ + test/core/channel/channel_stack_test.cc \ GRPC_CHANNEL_STACK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_STACK_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10800,7 +10800,7 @@ endif GRPC_COMPLETION_QUEUE_TEST_SRC = \ - test/core/surface/completion_queue_test.c \ + test/core/surface/completion_queue_test.cc \ GRPC_COMPLETION_QUEUE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10832,7 +10832,7 @@ endif GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC = \ - test/core/surface/completion_queue_threading_test.c \ + test/core/surface/completion_queue_threading_test.cc \ GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10864,7 +10864,7 @@ endif GRPC_CREATE_JWT_SRC = \ - test/core/security/create_jwt.c \ + test/core/security/create_jwt.cc \ GRPC_CREATE_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREATE_JWT_SRC)))) ifeq ($(NO_SECURE),true) @@ -10896,7 +10896,7 @@ endif GRPC_CREDENTIALS_TEST_SRC = \ - test/core/security/credentials_test.c \ + test/core/security/credentials_test.cc \ GRPC_CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREDENTIALS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10928,7 +10928,7 @@ endif GRPC_FETCH_OAUTH2_SRC = \ - test/core/security/fetch_oauth2.c \ + test/core/security/fetch_oauth2.cc \ GRPC_FETCH_OAUTH2_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_FETCH_OAUTH2_SRC)))) ifeq ($(NO_SECURE),true) @@ -10960,7 +10960,7 @@ endif GRPC_INVALID_CHANNEL_ARGS_TEST_SRC = \ - test/core/surface/invalid_channel_args_test.c \ + test/core/surface/invalid_channel_args_test.cc \ GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_INVALID_CHANNEL_ARGS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -10992,7 +10992,7 @@ endif GRPC_JSON_TOKEN_TEST_SRC = \ - test/core/security/json_token_test.c \ + test/core/security/json_token_test.cc \ GRPC_JSON_TOKEN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JSON_TOKEN_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11024,7 +11024,7 @@ endif GRPC_JWT_VERIFIER_TEST_SRC = \ - test/core/security/jwt_verifier_test.c \ + test/core/security/jwt_verifier_test.cc \ GRPC_JWT_VERIFIER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JWT_VERIFIER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11056,7 +11056,7 @@ endif GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC = \ - test/core/security/print_google_default_creds_token.c \ + test/core/security/print_google_default_creds_token.cc \ GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC)))) ifeq ($(NO_SECURE),true) @@ -11088,7 +11088,7 @@ endif GRPC_SECURITY_CONNECTOR_TEST_SRC = \ - test/core/security/security_connector_test.c \ + test/core/security/security_connector_test.cc \ GRPC_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SECURITY_CONNECTOR_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11120,7 +11120,7 @@ endif GRPC_VERIFY_JWT_SRC = \ - test/core/security/verify_jwt.c \ + test/core/security/verify_jwt.cc \ GRPC_VERIFY_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_VERIFY_JWT_SRC)))) ifeq ($(NO_SECURE),true) @@ -11152,7 +11152,7 @@ endif HANDSHAKE_CLIENT_SRC = \ - test/core/handshake/client_ssl.c \ + test/core/handshake/client_ssl.cc \ HANDSHAKE_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) @@ -11184,7 +11184,7 @@ endif HANDSHAKE_SERVER_SRC = \ - test/core/handshake/server_ssl.c \ + test/core/handshake/server_ssl.cc \ HANDSHAKE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -11216,7 +11216,7 @@ endif HPACK_PARSER_FUZZER_TEST_SRC = \ - test/core/transport/chttp2/hpack_parser_fuzzer_test.c \ + test/core/transport/chttp2/hpack_parser_fuzzer_test.cc \ HPACK_PARSER_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11248,7 +11248,7 @@ endif HPACK_PARSER_TEST_SRC = \ - test/core/transport/chttp2/hpack_parser_test.c \ + test/core/transport/chttp2/hpack_parser_test.cc \ HPACK_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11280,7 +11280,7 @@ endif HPACK_TABLE_TEST_SRC = \ - test/core/transport/chttp2/hpack_table_test.c \ + test/core/transport/chttp2/hpack_table_test.cc \ HPACK_TABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_TABLE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11312,7 +11312,7 @@ endif HTTP_PARSER_TEST_SRC = \ - test/core/http/parser_test.c \ + test/core/http/parser_test.cc \ HTTP_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11344,7 +11344,7 @@ endif HTTP_REQUEST_FUZZER_TEST_SRC = \ - test/core/http/request_fuzzer.c \ + test/core/http/request_fuzzer.cc \ HTTP_REQUEST_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11376,7 +11376,7 @@ endif HTTP_RESPONSE_FUZZER_TEST_SRC = \ - test/core/http/response_fuzzer.c \ + test/core/http/response_fuzzer.cc \ HTTP_RESPONSE_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11408,7 +11408,7 @@ endif HTTPCLI_FORMAT_REQUEST_TEST_SRC = \ - test/core/http/format_request_test.c \ + test/core/http/format_request_test.cc \ HTTPCLI_FORMAT_REQUEST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_FORMAT_REQUEST_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11440,7 +11440,7 @@ endif HTTPCLI_TEST_SRC = \ - test/core/http/httpcli_test.c \ + test/core/http/httpcli_test.cc \ HTTPCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11472,7 +11472,7 @@ endif HTTPSCLI_TEST_SRC = \ - test/core/http/httpscli_test.c \ + test/core/http/httpscli_test.cc \ HTTPSCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPSCLI_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11504,7 +11504,7 @@ endif INIT_TEST_SRC = \ - test/core/surface/init_test.c \ + test/core/surface/init_test.cc \ INIT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INIT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11536,7 +11536,7 @@ endif INVALID_CALL_ARGUMENT_TEST_SRC = \ - test/core/end2end/invalid_call_argument_test.c \ + test/core/end2end/invalid_call_argument_test.cc \ INVALID_CALL_ARGUMENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INVALID_CALL_ARGUMENT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11568,7 +11568,7 @@ endif JSON_FUZZER_TEST_SRC = \ - test/core/json/fuzzer.c \ + test/core/json/fuzzer.cc \ JSON_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11600,7 +11600,7 @@ endif JSON_REWRITE_SRC = \ - test/core/json/json_rewrite.c \ + test/core/json/json_rewrite.cc \ JSON_REWRITE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_SRC)))) ifeq ($(NO_SECURE),true) @@ -11632,7 +11632,7 @@ endif JSON_REWRITE_TEST_SRC = \ - test/core/json/json_rewrite_test.c \ + test/core/json/json_rewrite_test.cc \ JSON_REWRITE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11664,7 +11664,7 @@ endif JSON_STREAM_ERROR_TEST_SRC = \ - test/core/json/json_stream_error_test.c \ + test/core/json/json_stream_error_test.cc \ JSON_STREAM_ERROR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_STREAM_ERROR_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11696,7 +11696,7 @@ endif JSON_TEST_SRC = \ - test/core/json/json_test.c \ + test/core/json/json_test.cc \ JSON_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11728,7 +11728,7 @@ endif LAME_CLIENT_TEST_SRC = \ - test/core/surface/lame_client_test.c \ + test/core/surface/lame_client_test.cc \ LAME_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LAME_CLIENT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11760,7 +11760,7 @@ endif LB_POLICIES_TEST_SRC = \ - test/core/client_channel/lb_policies_test.c \ + test/core/client_channel/lb_policies_test.cc \ LB_POLICIES_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LB_POLICIES_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11792,7 +11792,7 @@ endif LOAD_FILE_TEST_SRC = \ - test/core/iomgr/load_file_test.c \ + test/core/iomgr/load_file_test.cc \ LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOAD_FILE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11824,7 +11824,7 @@ endif LOW_LEVEL_PING_PONG_BENCHMARK_SRC = \ - test/core/network_benchmarks/low_level_ping_pong.c \ + test/core/network_benchmarks/low_level_ping_pong.cc \ LOW_LEVEL_PING_PONG_BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOW_LEVEL_PING_PONG_BENCHMARK_SRC)))) ifeq ($(NO_SECURE),true) @@ -11856,7 +11856,7 @@ endif MEMORY_PROFILE_CLIENT_SRC = \ - test/core/memory_usage/client.c \ + test/core/memory_usage/client.cc \ MEMORY_PROFILE_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) @@ -11888,7 +11888,7 @@ endif MEMORY_PROFILE_SERVER_SRC = \ - test/core/memory_usage/server.c \ + test/core/memory_usage/server.cc \ MEMORY_PROFILE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -11920,7 +11920,7 @@ endif MEMORY_PROFILE_TEST_SRC = \ - test/core/memory_usage/memory_usage_test.c \ + test/core/memory_usage/memory_usage_test.cc \ MEMORY_PROFILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11952,7 +11952,7 @@ endif MESSAGE_COMPRESS_TEST_SRC = \ - test/core/compression/message_compress_test.c \ + test/core/compression/message_compress_test.cc \ MESSAGE_COMPRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MESSAGE_COMPRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -11984,7 +11984,7 @@ endif MINIMAL_STACK_IS_MINIMAL_TEST_SRC = \ - test/core/channel/minimal_stack_is_minimal_test.c \ + test/core/channel/minimal_stack_is_minimal_test.cc \ MINIMAL_STACK_IS_MINIMAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MINIMAL_STACK_IS_MINIMAL_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12016,7 +12016,7 @@ endif MLOG_TEST_SRC = \ - test/core/census/mlog_test.c \ + test/core/census/mlog_test.cc \ MLOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MLOG_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12048,7 +12048,7 @@ endif MULTIPLE_SERVER_QUEUES_TEST_SRC = \ - test/core/end2end/multiple_server_queues_test.c \ + test/core/end2end/multiple_server_queues_test.cc \ MULTIPLE_SERVER_QUEUES_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MULTIPLE_SERVER_QUEUES_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12080,7 +12080,7 @@ endif MURMUR_HASH_TEST_SRC = \ - test/core/support/murmur_hash_test.c \ + test/core/support/murmur_hash_test.cc \ MURMUR_HASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MURMUR_HASH_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12112,7 +12112,7 @@ endif NANOPB_FUZZER_RESPONSE_TEST_SRC = \ - test/core/nanopb/fuzzer_response.c \ + test/core/nanopb/fuzzer_response.cc \ NANOPB_FUZZER_RESPONSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12144,7 +12144,7 @@ endif NANOPB_FUZZER_SERVERLIST_TEST_SRC = \ - test/core/nanopb/fuzzer_serverlist.c \ + test/core/nanopb/fuzzer_serverlist.cc \ NANOPB_FUZZER_SERVERLIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12176,7 +12176,7 @@ endif NO_SERVER_TEST_SRC = \ - test/core/end2end/no_server_test.c \ + test/core/end2end/no_server_test.cc \ NO_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NO_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12208,7 +12208,7 @@ endif NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC = \ - test/core/surface/num_external_connectivity_watchers_test.c \ + test/core/surface/num_external_connectivity_watchers_test.cc \ NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12240,7 +12240,7 @@ endif PARSE_ADDRESS_TEST_SRC = \ - test/core/client_channel/parse_address_test.c \ + test/core/client_channel/parse_address_test.cc \ PARSE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PARSE_ADDRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12272,7 +12272,7 @@ endif PERCENT_DECODE_FUZZER_SRC = \ - test/core/slice/percent_decode_fuzzer.c \ + test/core/slice/percent_decode_fuzzer.cc \ PERCENT_DECODE_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_DECODE_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -12304,7 +12304,7 @@ endif PERCENT_ENCODE_FUZZER_SRC = \ - test/core/slice/percent_encode_fuzzer.c \ + test/core/slice/percent_encode_fuzzer.cc \ PERCENT_ENCODE_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODE_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -12336,7 +12336,7 @@ endif PERCENT_ENCODING_TEST_SRC = \ - test/core/slice/percent_encoding_test.c \ + test/core/slice/percent_encoding_test.cc \ PERCENT_ENCODING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12368,7 +12368,7 @@ endif POLLSET_SET_TEST_SRC = \ - test/core/iomgr/pollset_set_test.c \ + test/core/iomgr/pollset_set_test.cc \ POLLSET_SET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLLSET_SET_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12400,7 +12400,7 @@ endif RESOLVE_ADDRESS_POSIX_TEST_SRC = \ - test/core/iomgr/resolve_address_posix_test.c \ + test/core/iomgr/resolve_address_posix_test.cc \ RESOLVE_ADDRESS_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12432,7 +12432,7 @@ endif RESOLVE_ADDRESS_TEST_SRC = \ - test/core/iomgr/resolve_address_test.c \ + test/core/iomgr/resolve_address_test.cc \ RESOLVE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12464,7 +12464,7 @@ endif RESOURCE_QUOTA_TEST_SRC = \ - test/core/iomgr/resource_quota_test.c \ + test/core/iomgr/resource_quota_test.cc \ RESOURCE_QUOTA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOURCE_QUOTA_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12496,7 +12496,7 @@ endif SECURE_CHANNEL_CREATE_TEST_SRC = \ - test/core/surface/secure_channel_create_test.c \ + test/core/surface/secure_channel_create_test.cc \ SECURE_CHANNEL_CREATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_CHANNEL_CREATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12528,7 +12528,7 @@ endif SECURE_ENDPOINT_TEST_SRC = \ - test/core/security/secure_endpoint_test.c \ + test/core/security/secure_endpoint_test.cc \ SECURE_ENDPOINT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_ENDPOINT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12560,7 +12560,7 @@ endif SEQUENTIAL_CONNECTIVITY_TEST_SRC = \ - test/core/surface/sequential_connectivity_test.c \ + test/core/surface/sequential_connectivity_test.cc \ SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12592,7 +12592,7 @@ endif SERVER_CHTTP2_TEST_SRC = \ - test/core/surface/server_chttp2_test.c \ + test/core/surface/server_chttp2_test.cc \ SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12624,7 +12624,7 @@ endif SERVER_FUZZER_SRC = \ - test/core/end2end/fuzzers/server_fuzzer.c \ + test/core/end2end/fuzzers/server_fuzzer.cc \ SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -12656,7 +12656,7 @@ endif SERVER_TEST_SRC = \ - test/core/surface/server_test.c \ + test/core/surface/server_test.cc \ SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12688,7 +12688,7 @@ endif SLICE_BUFFER_TEST_SRC = \ - test/core/slice/slice_buffer_test.c \ + test/core/slice/slice_buffer_test.cc \ SLICE_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_BUFFER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12720,7 +12720,7 @@ endif SLICE_HASH_TABLE_TEST_SRC = \ - test/core/slice/slice_hash_table_test.c \ + test/core/slice/slice_hash_table_test.cc \ SLICE_HASH_TABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_HASH_TABLE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12752,7 +12752,7 @@ endif SLICE_STRING_HELPERS_TEST_SRC = \ - test/core/slice/slice_string_helpers_test.c \ + test/core/slice/slice_string_helpers_test.cc \ SLICE_STRING_HELPERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_STRING_HELPERS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12784,7 +12784,7 @@ endif SLICE_TEST_SRC = \ - test/core/slice/slice_test.c \ + test/core/slice/slice_test.cc \ SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12816,7 +12816,7 @@ endif SOCKADDR_RESOLVER_TEST_SRC = \ - test/core/client_channel/resolvers/sockaddr_resolver_test.c \ + test/core/client_channel/resolvers/sockaddr_resolver_test.cc \ SOCKADDR_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKADDR_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12848,7 +12848,7 @@ endif SOCKADDR_UTILS_TEST_SRC = \ - test/core/iomgr/sockaddr_utils_test.c \ + test/core/iomgr/sockaddr_utils_test.cc \ SOCKADDR_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKADDR_UTILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12880,7 +12880,7 @@ endif SOCKET_UTILS_TEST_SRC = \ - test/core/iomgr/socket_utils_test.c \ + test/core/iomgr/socket_utils_test.cc \ SOCKET_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKET_UTILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12912,7 +12912,7 @@ endif SSL_SERVER_FUZZER_SRC = \ - test/core/security/ssl_server_fuzzer.c \ + test/core/security/ssl_server_fuzzer.cc \ SSL_SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) @@ -12944,8 +12944,8 @@ endif SSL_TRANSPORT_SECURITY_TEST_SRC = \ - test/core/tsi/ssl_transport_security_test.c \ - test/core/tsi/transport_security_test_lib.c \ + test/core/tsi/ssl_transport_security_test.cc \ + test/core/tsi/transport_security_test_lib.cc \ SSL_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_TRANSPORT_SECURITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -12979,7 +12979,7 @@ endif STATUS_CONVERSION_TEST_SRC = \ - test/core/transport/status_conversion_test.c \ + test/core/transport/status_conversion_test.cc \ STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_CONVERSION_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13011,7 +13011,7 @@ endif STREAM_COMPRESSION_TEST_SRC = \ - test/core/compression/stream_compression_test.c \ + test/core/compression/stream_compression_test.cc \ STREAM_COMPRESSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_COMPRESSION_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13043,7 +13043,7 @@ endif STREAM_OWNED_SLICE_TEST_SRC = \ - test/core/transport/stream_owned_slice_test.c \ + test/core/transport/stream_owned_slice_test.cc \ STREAM_OWNED_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_OWNED_SLICE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13075,7 +13075,7 @@ endif TCP_CLIENT_POSIX_TEST_SRC = \ - test/core/iomgr/tcp_client_posix_test.c \ + test/core/iomgr/tcp_client_posix_test.cc \ TCP_CLIENT_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13107,7 +13107,7 @@ endif TCP_CLIENT_UV_TEST_SRC = \ - test/core/iomgr/tcp_client_uv_test.c \ + test/core/iomgr/tcp_client_uv_test.cc \ TCP_CLIENT_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_UV_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13139,7 +13139,7 @@ endif TCP_POSIX_TEST_SRC = \ - test/core/iomgr/tcp_posix_test.c \ + test/core/iomgr/tcp_posix_test.cc \ TCP_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13171,7 +13171,7 @@ endif TCP_SERVER_POSIX_TEST_SRC = \ - test/core/iomgr/tcp_server_posix_test.c \ + test/core/iomgr/tcp_server_posix_test.cc \ TCP_SERVER_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13203,7 +13203,7 @@ endif TCP_SERVER_UV_TEST_SRC = \ - test/core/iomgr/tcp_server_uv_test.c \ + test/core/iomgr/tcp_server_uv_test.cc \ TCP_SERVER_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_UV_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13235,7 +13235,7 @@ endif TIME_AVERAGED_STATS_TEST_SRC = \ - test/core/iomgr/time_averaged_stats_test.c \ + test/core/iomgr/time_averaged_stats_test.cc \ TIME_AVERAGED_STATS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_AVERAGED_STATS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13267,7 +13267,7 @@ endif TIMEOUT_ENCODING_TEST_SRC = \ - test/core/transport/timeout_encoding_test.c \ + test/core/transport/timeout_encoding_test.cc \ TIMEOUT_ENCODING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMEOUT_ENCODING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13299,7 +13299,7 @@ endif TIMER_HEAP_TEST_SRC = \ - test/core/iomgr/timer_heap_test.c \ + test/core/iomgr/timer_heap_test.cc \ TIMER_HEAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMER_HEAP_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13331,7 +13331,7 @@ endif TIMER_LIST_TEST_SRC = \ - test/core/iomgr/timer_list_test.c \ + test/core/iomgr/timer_list_test.cc \ TIMER_LIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMER_LIST_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13363,7 +13363,7 @@ endif TRANSPORT_CONNECTIVITY_STATE_TEST_SRC = \ - test/core/transport/connectivity_state_test.c \ + test/core/transport/connectivity_state_test.cc \ TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_CONNECTIVITY_STATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13395,7 +13395,7 @@ endif TRANSPORT_METADATA_TEST_SRC = \ - test/core/transport/metadata_test.c \ + test/core/transport/metadata_test.cc \ TRANSPORT_METADATA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_METADATA_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13427,7 +13427,7 @@ endif TRANSPORT_SECURITY_TEST_SRC = \ - test/core/tsi/transport_security_test.c \ + test/core/tsi/transport_security_test.cc \ TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_SECURITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13459,7 +13459,7 @@ endif UDP_SERVER_TEST_SRC = \ - test/core/iomgr/udp_server_test.c \ + test/core/iomgr/udp_server_test.cc \ UDP_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(UDP_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13491,7 +13491,7 @@ endif URI_FUZZER_TEST_SRC = \ - test/core/client_channel/uri_fuzzer_test.c \ + test/core/client_channel/uri_fuzzer_test.cc \ URI_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13523,7 +13523,7 @@ endif URI_PARSER_TEST_SRC = \ - test/core/client_channel/uri_parser_test.c \ + test/core/client_channel/uri_parser_test.cc \ URI_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -13555,7 +13555,7 @@ endif WAKEUP_FD_CV_TEST_SRC = \ - test/core/iomgr/wakeup_fd_cv_test.c \ + test/core/iomgr/wakeup_fd_cv_test.cc \ WAKEUP_FD_CV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WAKEUP_FD_CV_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18487,7 +18487,7 @@ $(BORINGSSL_V3NAME_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -W BADREQ_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/badreq.c \ + test/core/bad_client/tests/badreq.cc \ BADREQ_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BADREQ_BAD_CLIENT_TEST_SRC)))) @@ -18507,7 +18507,7 @@ endif CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/connection_prefix.c \ + test/core/bad_client/tests/connection_prefix.cc \ CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC)))) @@ -18527,7 +18527,7 @@ endif HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/head_of_line_blocking.c \ + test/core/bad_client/tests/head_of_line_blocking.cc \ HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC)))) @@ -18547,7 +18547,7 @@ endif HEADERS_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/headers.c \ + test/core/bad_client/tests/headers.cc \ HEADERS_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEADERS_BAD_CLIENT_TEST_SRC)))) @@ -18567,7 +18567,7 @@ endif INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/initial_settings_frame.c \ + test/core/bad_client/tests/initial_settings_frame.cc \ INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC)))) @@ -18587,7 +18587,7 @@ endif SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/server_registered_method.c \ + test/core/bad_client/tests/server_registered_method.cc \ SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC)))) @@ -18607,7 +18607,7 @@ endif SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/simple_request.c \ + test/core/bad_client/tests/simple_request.cc \ SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC)))) @@ -18627,7 +18627,7 @@ endif UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/unknown_frame.c \ + test/core/bad_client/tests/unknown_frame.cc \ UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC)))) @@ -18647,7 +18647,7 @@ endif WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC = \ - test/core/bad_client/tests/window_overflow.c \ + test/core/bad_client/tests/window_overflow.cc \ WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC)))) @@ -18667,7 +18667,7 @@ endif BAD_SSL_CERT_SERVER_SRC = \ - test/core/bad_ssl/servers/cert.c \ + test/core/bad_ssl/servers/cert.cc \ BAD_SSL_CERT_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SSL_CERT_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -18699,7 +18699,7 @@ endif BAD_SSL_CERT_TEST_SRC = \ - test/core/bad_ssl/bad_ssl_test.c \ + test/core/bad_ssl/bad_ssl_test.cc \ BAD_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SSL_CERT_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18731,7 +18731,7 @@ endif H2_CENSUS_TEST_SRC = \ - test/core/end2end/fixtures/h2_census.c \ + test/core/end2end/fixtures/h2_census.cc \ H2_CENSUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_CENSUS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18763,7 +18763,7 @@ endif H2_COMPRESS_TEST_SRC = \ - test/core/end2end/fixtures/h2_compress.c \ + test/core/end2end/fixtures/h2_compress.cc \ H2_COMPRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_COMPRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18795,7 +18795,7 @@ endif H2_FAKESEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_fakesec.c \ + test/core/end2end/fixtures/h2_fakesec.cc \ H2_FAKESEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FAKESEC_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18827,7 +18827,7 @@ endif H2_FD_TEST_SRC = \ - test/core/end2end/fixtures/h2_fd.c \ + test/core/end2end/fixtures/h2_fd.cc \ H2_FD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FD_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18859,7 +18859,7 @@ endif H2_FULL_TEST_SRC = \ - test/core/end2end/fixtures/h2_full.c \ + test/core/end2end/fixtures/h2_full.cc \ H2_FULL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18891,7 +18891,7 @@ endif H2_FULL+PIPE_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+pipe.c \ + test/core/end2end/fixtures/h2_full+pipe.cc \ H2_FULL+PIPE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+PIPE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18923,7 +18923,7 @@ endif H2_FULL+TRACE_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+trace.c \ + test/core/end2end/fixtures/h2_full+trace.cc \ H2_FULL+TRACE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+TRACE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18955,7 +18955,7 @@ endif H2_FULL+WORKAROUNDS_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+workarounds.c \ + test/core/end2end/fixtures/h2_full+workarounds.cc \ H2_FULL+WORKAROUNDS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+WORKAROUNDS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -18987,7 +18987,7 @@ endif H2_HTTP_PROXY_TEST_SRC = \ - test/core/end2end/fixtures/h2_http_proxy.c \ + test/core/end2end/fixtures/h2_http_proxy.cc \ H2_HTTP_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_HTTP_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19019,7 +19019,7 @@ endif H2_LOAD_REPORTING_TEST_SRC = \ - test/core/end2end/fixtures/h2_load_reporting.c \ + test/core/end2end/fixtures/h2_load_reporting.cc \ H2_LOAD_REPORTING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19051,7 +19051,7 @@ endif H2_OAUTH2_TEST_SRC = \ - test/core/end2end/fixtures/h2_oauth2.c \ + test/core/end2end/fixtures/h2_oauth2.cc \ H2_OAUTH2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_OAUTH2_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19083,7 +19083,7 @@ endif H2_PROXY_TEST_SRC = \ - test/core/end2end/fixtures/h2_proxy.c \ + test/core/end2end/fixtures/h2_proxy.cc \ H2_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19115,7 +19115,7 @@ endif H2_SOCKPAIR_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair.c \ + test/core/end2end/fixtures/h2_sockpair.cc \ H2_SOCKPAIR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19147,7 +19147,7 @@ endif H2_SOCKPAIR+TRACE_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair+trace.c \ + test/core/end2end/fixtures/h2_sockpair+trace.cc \ H2_SOCKPAIR+TRACE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR+TRACE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19179,7 +19179,7 @@ endif H2_SOCKPAIR_1BYTE_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair_1byte.c \ + test/core/end2end/fixtures/h2_sockpair_1byte.cc \ H2_SOCKPAIR_1BYTE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_1BYTE_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19211,7 +19211,7 @@ endif H2_SSL_TEST_SRC = \ - test/core/end2end/fixtures/h2_ssl.c \ + test/core/end2end/fixtures/h2_ssl.cc \ H2_SSL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19243,7 +19243,7 @@ endif H2_SSL_PROXY_TEST_SRC = \ - test/core/end2end/fixtures/h2_ssl_proxy.c \ + test/core/end2end/fixtures/h2_ssl_proxy.cc \ H2_SSL_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19275,7 +19275,7 @@ endif H2_UDS_TEST_SRC = \ - test/core/end2end/fixtures/h2_uds.c \ + test/core/end2end/fixtures/h2_uds.cc \ H2_UDS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19307,7 +19307,7 @@ endif INPROC_TEST_SRC = \ - test/core/end2end/fixtures/inproc.c \ + test/core/end2end/fixtures/inproc.cc \ INPROC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_TEST_SRC)))) ifeq ($(NO_SECURE),true) @@ -19339,7 +19339,7 @@ endif H2_CENSUS_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_census.c \ + test/core/end2end/fixtures/h2_census.cc \ H2_CENSUS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_CENSUS_NOSEC_TEST_SRC)))) @@ -19359,7 +19359,7 @@ endif H2_COMPRESS_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_compress.c \ + test/core/end2end/fixtures/h2_compress.cc \ H2_COMPRESS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_COMPRESS_NOSEC_TEST_SRC)))) @@ -19379,7 +19379,7 @@ endif H2_FD_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_fd.c \ + test/core/end2end/fixtures/h2_fd.cc \ H2_FD_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FD_NOSEC_TEST_SRC)))) @@ -19399,7 +19399,7 @@ endif H2_FULL_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_full.c \ + test/core/end2end/fixtures/h2_full.cc \ H2_FULL_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL_NOSEC_TEST_SRC)))) @@ -19419,7 +19419,7 @@ endif H2_FULL+PIPE_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+pipe.c \ + test/core/end2end/fixtures/h2_full+pipe.cc \ H2_FULL+PIPE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+PIPE_NOSEC_TEST_SRC)))) @@ -19439,7 +19439,7 @@ endif H2_FULL+TRACE_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+trace.c \ + test/core/end2end/fixtures/h2_full+trace.cc \ H2_FULL+TRACE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+TRACE_NOSEC_TEST_SRC)))) @@ -19459,7 +19459,7 @@ endif H2_FULL+WORKAROUNDS_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_full+workarounds.c \ + test/core/end2end/fixtures/h2_full+workarounds.cc \ H2_FULL+WORKAROUNDS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+WORKAROUNDS_NOSEC_TEST_SRC)))) @@ -19479,7 +19479,7 @@ endif H2_HTTP_PROXY_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_http_proxy.c \ + test/core/end2end/fixtures/h2_http_proxy.cc \ H2_HTTP_PROXY_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_HTTP_PROXY_NOSEC_TEST_SRC)))) @@ -19499,7 +19499,7 @@ endif H2_LOAD_REPORTING_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_load_reporting.c \ + test/core/end2end/fixtures/h2_load_reporting.cc \ H2_LOAD_REPORTING_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_NOSEC_TEST_SRC)))) @@ -19519,7 +19519,7 @@ endif H2_PROXY_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_proxy.c \ + test/core/end2end/fixtures/h2_proxy.cc \ H2_PROXY_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_PROXY_NOSEC_TEST_SRC)))) @@ -19539,7 +19539,7 @@ endif H2_SOCKPAIR_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair.c \ + test/core/end2end/fixtures/h2_sockpair.cc \ H2_SOCKPAIR_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_NOSEC_TEST_SRC)))) @@ -19559,7 +19559,7 @@ endif H2_SOCKPAIR+TRACE_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair+trace.c \ + test/core/end2end/fixtures/h2_sockpair+trace.cc \ H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR+TRACE_NOSEC_TEST_SRC)))) @@ -19579,7 +19579,7 @@ endif H2_SOCKPAIR_1BYTE_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_sockpair_1byte.c \ + test/core/end2end/fixtures/h2_sockpair_1byte.cc \ H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_SRC)))) @@ -19599,7 +19599,7 @@ endif H2_UDS_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/h2_uds.c \ + test/core/end2end/fixtures/h2_uds.cc \ H2_UDS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS_NOSEC_TEST_SRC)))) @@ -19619,7 +19619,7 @@ endif INPROC_NOSEC_TEST_SRC = \ - test/core/end2end/fixtures/inproc.c \ + test/core/end2end/fixtures/inproc.cc \ INPROC_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_NOSEC_TEST_SRC)))) @@ -19811,7 +19811,7 @@ endif API_FUZZER_ONE_ENTRY_SRC = \ - test/core/end2end/fuzzers/api_fuzzer.c \ + test/core/end2end/fuzzers/api_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ API_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_ONE_ENTRY_SRC)))) @@ -19846,7 +19846,7 @@ endif CLIENT_FUZZER_ONE_ENTRY_SRC = \ - test/core/end2end/fuzzers/client_fuzzer.c \ + test/core/end2end/fuzzers/client_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ CLIENT_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_ONE_ENTRY_SRC)))) @@ -19881,7 +19881,7 @@ endif HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC = \ - test/core/transport/chttp2/hpack_parser_fuzzer_test.c \ + test/core/transport/chttp2/hpack_parser_fuzzer_test.cc \ test/core/util/one_corpus_entry_fuzzer.c \ HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC)))) @@ -19916,7 +19916,7 @@ endif HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC = \ - test/core/http/request_fuzzer.c \ + test/core/http/request_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC)))) @@ -19951,7 +19951,7 @@ endif HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC = \ - test/core/http/response_fuzzer.c \ + test/core/http/response_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC)))) @@ -19986,7 +19986,7 @@ endif JSON_FUZZER_TEST_ONE_ENTRY_SRC = \ - test/core/json/fuzzer.c \ + test/core/json/fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ JSON_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_ONE_ENTRY_SRC)))) @@ -20021,7 +20021,7 @@ endif NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC = \ - test/core/nanopb/fuzzer_response.c \ + test/core/nanopb/fuzzer_response.cc \ test/core/util/one_corpus_entry_fuzzer.c \ NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC)))) @@ -20056,7 +20056,7 @@ endif NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC = \ - test/core/nanopb/fuzzer_serverlist.c \ + test/core/nanopb/fuzzer_serverlist.cc \ test/core/util/one_corpus_entry_fuzzer.c \ NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC)))) @@ -20091,7 +20091,7 @@ endif PERCENT_DECODE_FUZZER_ONE_ENTRY_SRC = \ - test/core/slice/percent_decode_fuzzer.c \ + test/core/slice/percent_decode_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ PERCENT_DECODE_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_DECODE_FUZZER_ONE_ENTRY_SRC)))) @@ -20126,7 +20126,7 @@ endif PERCENT_ENCODE_FUZZER_ONE_ENTRY_SRC = \ - test/core/slice/percent_encode_fuzzer.c \ + test/core/slice/percent_encode_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ PERCENT_ENCODE_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_SRC)))) @@ -20161,7 +20161,7 @@ endif SERVER_FUZZER_ONE_ENTRY_SRC = \ - test/core/end2end/fuzzers/server_fuzzer.c \ + test/core/end2end/fuzzers/server_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_ONE_ENTRY_SRC)))) @@ -20196,7 +20196,7 @@ endif SSL_SERVER_FUZZER_ONE_ENTRY_SRC = \ - test/core/security/ssl_server_fuzzer.c \ + test/core/security/ssl_server_fuzzer.cc \ test/core/util/one_corpus_entry_fuzzer.c \ SSL_SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_ONE_ENTRY_SRC)))) @@ -20231,7 +20231,7 @@ endif URI_FUZZER_TEST_ONE_ENTRY_SRC = \ - test/core/client_channel/uri_fuzzer_test.c \ + test/core/client_channel/uri_fuzzer_test.cc \ test/core/util/one_corpus_entry_fuzzer.c \ URI_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_ONE_ENTRY_SRC)))) @@ -20323,17 +20323,17 @@ src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP) src/cpp/util/core_stats.cc: $(OPENSSL_DEP) src/cpp/util/error_details.cc: $(OPENSSL_DEP) src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP) -test/core/bad_client/bad_client.c: $(OPENSSL_DEP) -test/core/bad_ssl/server_common.c: $(OPENSSL_DEP) -test/core/end2end/data/client_certs.c: $(OPENSSL_DEP) -test/core/end2end/data/server1_cert.c: $(OPENSSL_DEP) -test/core/end2end/data/server1_key.c: $(OPENSSL_DEP) -test/core/end2end/data/test_root_cert.c: $(OPENSSL_DEP) -test/core/end2end/end2end_tests.c: $(OPENSSL_DEP) -test/core/end2end/tests/call_creds.c: $(OPENSSL_DEP) -test/core/security/oauth2_utils.c: $(OPENSSL_DEP) -test/core/util/reconnect_server.c: $(OPENSSL_DEP) -test/core/util/test_tcp_server.c: $(OPENSSL_DEP) +test/core/bad_client/bad_client.cc: $(OPENSSL_DEP) +test/core/bad_ssl/server_common.cc: $(OPENSSL_DEP) +test/core/end2end/data/client_certs.cc: $(OPENSSL_DEP) +test/core/end2end/data/server1_cert.cc: $(OPENSSL_DEP) +test/core/end2end/data/server1_key.cc: $(OPENSSL_DEP) +test/core/end2end/data/test_root_cert.cc: $(OPENSSL_DEP) +test/core/end2end/end2end_tests.cc: $(OPENSSL_DEP) +test/core/end2end/tests/call_creds.cc: $(OPENSSL_DEP) +test/core/security/oauth2_utils.cc: $(OPENSSL_DEP) +test/core/util/reconnect_server.cc: $(OPENSSL_DEP) +test/core/util/test_tcp_server.cc: $(OPENSSL_DEP) test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP) test/cpp/interop/client.cc: $(OPENSSL_DEP) test/cpp/interop/client_helper.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index e2faa438ab..fe139470e1 100644 --- a/build.yaml +++ b/build.yaml @@ -739,20 +739,20 @@ filegroups: - test/core/util/trickle_endpoint.h src: - src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc - - test/core/end2end/cq_verifier.c - - test/core/end2end/fixtures/http_proxy_fixture.c - - test/core/end2end/fixtures/proxy.c - - test/core/iomgr/endpoint_tests.c + - test/core/end2end/cq_verifier.cc + - test/core/end2end/fixtures/http_proxy_fixture.cc + - test/core/end2end/fixtures/proxy.cc + - test/core/iomgr/endpoint_tests.cc - test/core/util/debugger_macros.cc - - test/core/util/grpc_profiler.c - - test/core/util/memory_counters.c - - test/core/util/mock_endpoint.c - - test/core/util/parse_hexstring.c - - test/core/util/passthru_endpoint.c - - test/core/util/port.c - - test/core/util/port_server_client.c - - test/core/util/slice_splitter.c - - test/core/util/trickle_endpoint.c + - test/core/util/grpc_profiler.cc + - test/core/util/memory_counters.cc + - test/core/util/mock_endpoint.cc + - test/core/util/parse_hexstring.cc + - test/core/util/passthru_endpoint.cc + - test/core/util/port.cc + - test/core/util/port_server_client.cc + - test/core/util/slice_splitter.cc + - test/core/util/trickle_endpoint.cc deps: - gpr_test_util - gpr @@ -937,7 +937,7 @@ filegroups: headers: - test/core/tsi/transport_security_test_lib.h src: - - test/core/tsi/transport_security_test_lib.c + - test/core/tsi/transport_security_test_lib.cc deps: - grpc - name: tsi @@ -1147,7 +1147,7 @@ libs: headers: - test/core/util/test_config.h src: - - test/core/util/test_config.c + - test/core/util/test_config.cc deps: - gpr secure: false @@ -1233,11 +1233,11 @@ libs: - test/core/end2end/data/ssl_test_data.h - test/core/security/oauth2_utils.h src: - - test/core/end2end/data/client_certs.c - - test/core/end2end/data/server1_cert.c - - test/core/end2end/data/server1_key.c - - test/core/end2end/data/test_root_cert.c - - test/core/security/oauth2_utils.c + - test/core/end2end/data/client_certs.cc + - test/core/end2end/data/server1_cert.cc + - test/core/end2end/data/server1_key.cc + - test/core/end2end/data/test_root_cert.cc + - test/core/security/oauth2_utils.cc deps: - gpr_test_util - gpr @@ -1293,7 +1293,7 @@ libs: headers: - test/core/util/reconnect_server.h src: - - test/core/util/reconnect_server.c + - test/core/util/reconnect_server.cc deps: - test_tcp_server - grpc_test_util @@ -1306,7 +1306,7 @@ libs: headers: - test/core/util/test_tcp_server.h src: - - test/core/util/test_tcp_server.c + - test/core/util/test_tcp_server.cc deps: - grpc_test_util - grpc @@ -1722,7 +1722,7 @@ targets: build: test language: c src: - - test/core/surface/alarm_test.c + - test/core/surface/alarm_test.cc deps: - grpc_test_util - grpc @@ -1732,7 +1732,7 @@ targets: build: test language: c src: - - test/core/compression/algorithm_test.c + - test/core/compression/algorithm_test.cc deps: - grpc_test_util - grpc @@ -1743,7 +1743,7 @@ targets: build: test language: c src: - - test/core/support/alloc_test.c + - test/core/support/alloc_test.cc deps: - gpr_test_util - gpr @@ -1752,7 +1752,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/alpn_test.c + - test/core/transport/chttp2/alpn_test.cc deps: - grpc_test_util - grpc @@ -1762,7 +1762,7 @@ targets: build: fuzzer language: c src: - - test/core/end2end/fuzzers/api_fuzzer.c + - test/core/end2end/fuzzers/api_fuzzer.cc deps: - grpc_test_util - grpc @@ -1776,7 +1776,7 @@ targets: build: test language: c src: - - test/core/support/arena_test.c + - test/core/support/arena_test.cc deps: - gpr_test_util - gpr @@ -1785,7 +1785,7 @@ targets: build: test language: c src: - - test/core/backoff/backoff_test.c + - test/core/backoff/backoff_test.cc deps: - grpc_test_util - grpc @@ -1796,7 +1796,7 @@ targets: build: test language: c src: - - test/core/end2end/bad_server_response_test.c + - test/core/end2end/bad_server_response_test.cc deps: - test_tcp_server - grpc_test_util @@ -1809,7 +1809,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/bin_decoder_test.c + - test/core/transport/chttp2/bin_decoder_test.cc deps: - grpc_test_util - grpc @@ -1818,7 +1818,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/bin_encoder_test.c + - test/core/transport/chttp2/bin_encoder_test.cc deps: - grpc_test_util - grpc @@ -1827,7 +1827,7 @@ targets: build: test language: c src: - - test/core/transport/byte_stream_test.c + - test/core/transport/byte_stream_test.cc deps: - grpc_test_util - grpc @@ -1838,7 +1838,7 @@ targets: build: test language: c src: - - test/core/census/context_test.c + - test/core/census/context_test.cc deps: - grpc_test_util - grpc @@ -1849,7 +1849,7 @@ targets: build: test language: c src: - - test/core/census/intrusive_hash_map_test.c + - test/core/census/intrusive_hash_map_test.cc deps: - grpc_test_util - grpc @@ -1860,7 +1860,7 @@ targets: build: test language: c src: - - test/core/census/resource_test.c + - test/core/census/resource_test.cc deps: - grpc_test_util - grpc @@ -1871,7 +1871,7 @@ targets: build: test language: c src: - - test/core/census/trace_context_test.c + - test/core/census/trace_context_test.cc deps: - grpc_test_util - grpc @@ -1882,7 +1882,7 @@ targets: build: test language: c src: - - test/core/surface/channel_create_test.c + - test/core/surface/channel_create_test.cc deps: - grpc_test_util - grpc @@ -1892,7 +1892,7 @@ targets: build: tool language: c src: - - test/build/check_epollexclusive.c + - test/build/check_epollexclusive.cc deps: - grpc - gpr @@ -1900,7 +1900,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/hpack_encoder_test.c + - test/core/transport/chttp2/hpack_encoder_test.cc deps: - grpc_test_util - grpc @@ -1911,7 +1911,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/stream_map_test.c + - test/core/transport/chttp2/stream_map_test.cc deps: - grpc_test_util - grpc @@ -1922,7 +1922,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/varint_test.c + - test/core/transport/chttp2/varint_test.cc deps: - grpc_test_util - grpc @@ -1933,7 +1933,7 @@ targets: build: fuzzer language: c src: - - test/core/end2end/fuzzers/client_fuzzer.c + - test/core/end2end/fuzzers/client_fuzzer.cc deps: - grpc_test_util - grpc @@ -1948,7 +1948,7 @@ targets: build: test language: c src: - - test/core/iomgr/combiner_test.c + - test/core/iomgr/combiner_test.cc deps: - grpc_test_util - grpc @@ -1958,7 +1958,7 @@ targets: build: test language: c src: - - test/core/compression/compression_test.c + - test/core/compression/compression_test.cc deps: - grpc_test_util - grpc @@ -1970,7 +1970,7 @@ targets: build: test language: c src: - - test/core/surface/concurrent_connectivity_test.c + - test/core/surface/concurrent_connectivity_test.cc deps: - grpc_test_util - grpc @@ -1983,7 +1983,7 @@ targets: build: test language: c src: - - test/core/end2end/connection_refused_test.c + - test/core/end2end/connection_refused_test.cc deps: - grpc_test_util - grpc @@ -1994,7 +1994,7 @@ targets: build: test language: c src: - - test/core/client_channel/resolvers/dns_resolver_connectivity_test.c + - test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc deps: - grpc_test_util - grpc @@ -2006,7 +2006,7 @@ targets: build: test language: c src: - - test/core/client_channel/resolvers/dns_resolver_test.c + - test/core/client_channel/resolvers/dns_resolver_test.cc deps: - grpc_test_util - grpc @@ -2017,7 +2017,7 @@ targets: build: test language: c src: - - test/core/end2end/dualstack_socket_test.c + - test/core/end2end/dualstack_socket_test.cc deps: - grpc_test_util - grpc @@ -2033,7 +2033,7 @@ targets: build: test language: c src: - - test/core/iomgr/endpoint_pair_test.c + - test/core/iomgr/endpoint_pair_test.cc deps: - grpc_test_util - grpc @@ -2046,7 +2046,7 @@ targets: build: test language: c src: - - test/core/iomgr/error_test.c + - test/core/iomgr/error_test.cc deps: - grpc_test_util - grpc @@ -2058,7 +2058,7 @@ targets: build: test language: c src: - - test/core/iomgr/ev_epollsig_linux_test.c + - test/core/iomgr/ev_epollsig_linux_test.cc deps: - grpc_test_util - grpc @@ -2072,7 +2072,7 @@ targets: build: test language: c src: - - test/core/client_channel/resolvers/fake_resolver_test.c + - test/core/client_channel/resolvers/fake_resolver_test.cc deps: - grpc_test_util - grpc @@ -2082,7 +2082,7 @@ targets: build: test language: c src: - - test/core/tsi/fake_transport_security_test.c + - test/core/tsi/fake_transport_security_test.cc deps: - gpr_test_util - gpr @@ -2097,7 +2097,7 @@ targets: build: test language: c src: - - test/core/iomgr/fd_conservation_posix_test.c + - test/core/iomgr/fd_conservation_posix_test.cc deps: - grpc_test_util - grpc @@ -2113,7 +2113,7 @@ targets: build: test language: c src: - - test/core/iomgr/fd_posix_test.c + - test/core/iomgr/fd_posix_test.cc deps: - grpc_test_util - grpc @@ -2130,7 +2130,7 @@ targets: run: false language: c src: - - test/core/fling/client.c + - test/core/fling/client.cc deps: - grpc_test_util - grpc @@ -2141,7 +2141,7 @@ targets: run: false language: c src: - - test/core/fling/server.c + - test/core/fling/server.cc deps: - grpc_test_util - grpc @@ -2152,7 +2152,7 @@ targets: build: test language: c src: - - test/core/fling/fling_stream_test.c + - test/core/fling/fling_stream_test.cc deps: - grpc_test_util - grpc @@ -2167,7 +2167,7 @@ targets: build: test language: c src: - - test/core/fling/fling_test.c + - test/core/fling/fling_test.cc deps: - grpc_test_util - grpc @@ -2204,7 +2204,7 @@ targets: build: test language: c src: - - test/core/end2end/goaway_server_test.c + - test/core/end2end/goaway_server_test.cc deps: - grpc_test_util - grpc @@ -2220,7 +2220,7 @@ targets: build: test language: c src: - - test/core/support/avl_test.c + - test/core/support/avl_test.cc deps: - gpr_test_util - gpr @@ -2229,7 +2229,7 @@ targets: build: test language: c src: - - test/core/support/cmdline_test.c + - test/core/support/cmdline_test.cc deps: - gpr_test_util - gpr @@ -2239,7 +2239,7 @@ targets: build: test language: c src: - - test/core/support/cpu_test.c + - test/core/support/cpu_test.cc deps: - gpr_test_util - gpr @@ -2248,7 +2248,7 @@ targets: build: test language: c src: - - test/core/support/env_test.c + - test/core/support/env_test.cc deps: - gpr_test_util - gpr @@ -2257,7 +2257,7 @@ targets: build: test language: c src: - - test/core/support/histogram_test.c + - test/core/support/histogram_test.cc deps: - gpr_test_util - gpr @@ -2266,7 +2266,7 @@ targets: build: test language: c src: - - test/core/support/host_port_test.c + - test/core/support/host_port_test.cc deps: - gpr_test_util - gpr @@ -2275,7 +2275,7 @@ targets: build: test language: c src: - - test/core/support/log_test.c + - test/core/support/log_test.cc deps: - gpr_test_util - gpr @@ -2285,7 +2285,7 @@ targets: build: test language: c src: - - test/core/support/mpscq_test.c + - test/core/support/mpscq_test.cc deps: - gpr_test_util - gpr @@ -2295,7 +2295,7 @@ targets: build: test language: c src: - - test/core/support/spinlock_test.c + - test/core/support/spinlock_test.cc deps: - gpr_test_util - gpr @@ -2305,7 +2305,7 @@ targets: build: test language: c src: - - test/core/support/stack_lockfree_test.c + - test/core/support/stack_lockfree_test.cc deps: - gpr_test_util - gpr @@ -2314,7 +2314,7 @@ targets: build: test language: c src: - - test/core/support/string_test.c + - test/core/support/string_test.cc deps: - gpr_test_util - gpr @@ -2324,7 +2324,7 @@ targets: build: test language: c src: - - test/core/support/sync_test.c + - test/core/support/sync_test.cc deps: - gpr_test_util - gpr @@ -2334,7 +2334,7 @@ targets: build: test language: c src: - - test/core/support/thd_test.c + - test/core/support/thd_test.cc deps: - gpr_test_util - gpr @@ -2343,7 +2343,7 @@ targets: build: test language: c src: - - test/core/support/time_test.c + - test/core/support/time_test.cc deps: - gpr_test_util - gpr @@ -2352,7 +2352,7 @@ targets: build: test language: c src: - - test/core/support/tls_test.c + - test/core/support/tls_test.cc deps: - gpr_test_util - gpr @@ -2361,7 +2361,7 @@ targets: build: test language: c src: - - test/core/support/useful_test.c + - test/core/support/useful_test.cc deps: - gpr_test_util - gpr @@ -2370,7 +2370,7 @@ targets: build: test language: c src: - - test/core/security/auth_context_test.c + - test/core/security/auth_context_test.cc deps: - grpc_test_util - grpc @@ -2381,7 +2381,7 @@ targets: build: test language: c src: - - test/core/slice/b64_test.c + - test/core/slice/b64_test.cc deps: - grpc_test_util - grpc @@ -2392,7 +2392,7 @@ targets: build: test language: c src: - - test/core/surface/byte_buffer_reader_test.c + - test/core/surface/byte_buffer_reader_test.cc deps: - grpc_test_util - grpc @@ -2403,7 +2403,7 @@ targets: build: test language: c src: - - test/core/channel/channel_args_test.c + - test/core/channel/channel_args_test.cc deps: - grpc_test_util - grpc @@ -2414,7 +2414,7 @@ targets: build: test language: c src: - - test/core/channel/channel_stack_builder_test.c + - test/core/channel/channel_stack_builder_test.cc deps: - grpc_test_util - grpc @@ -2424,7 +2424,7 @@ targets: build: test language: c src: - - test/core/channel/channel_stack_test.c + - test/core/channel/channel_stack_test.cc deps: - grpc_test_util - grpc @@ -2435,7 +2435,7 @@ targets: build: test language: c src: - - test/core/surface/completion_queue_test.c + - test/core/surface/completion_queue_test.cc deps: - grpc_test_util - grpc @@ -2445,7 +2445,7 @@ targets: build: test language: c src: - - test/core/surface/completion_queue_threading_test.c + - test/core/surface/completion_queue_threading_test.cc deps: - grpc_test_util - grpc @@ -2457,7 +2457,7 @@ targets: build: tool language: c src: - - test/core/security/create_jwt.c + - test/core/security/create_jwt.cc deps: - grpc - gpr @@ -2467,7 +2467,7 @@ targets: build: test language: c src: - - test/core/security/credentials_test.c + - test/core/security/credentials_test.cc deps: - grpc_test_util - grpc @@ -2478,7 +2478,7 @@ targets: run: false language: c src: - - test/core/security/fetch_oauth2.c + - test/core/security/fetch_oauth2.cc deps: - grpc_test_util - grpc @@ -2488,7 +2488,7 @@ targets: build: test language: c src: - - test/core/surface/invalid_channel_args_test.c + - test/core/surface/invalid_channel_args_test.cc deps: - grpc_test_util - grpc @@ -2499,7 +2499,7 @@ targets: build: test language: c src: - - test/core/security/json_token_test.c + - test/core/security/json_token_test.cc deps: - grpc_test_util - grpc @@ -2514,7 +2514,7 @@ targets: build: test language: c src: - - test/core/security/jwt_verifier_test.c + - test/core/security/jwt_verifier_test.cc deps: - grpc_test_util - grpc @@ -2525,7 +2525,7 @@ targets: build: tool language: c src: - - test/core/security/print_google_default_creds_token.c + - test/core/security/print_google_default_creds_token.cc deps: - grpc - gpr @@ -2534,7 +2534,7 @@ targets: build: test language: c src: - - test/core/security/security_connector_test.c + - test/core/security/security_connector_test.cc deps: - grpc_test_util - grpc @@ -2544,7 +2544,7 @@ targets: build: tool language: c src: - - test/core/security/verify_jwt.c + - test/core/security/verify_jwt.cc deps: - grpc - gpr @@ -2553,7 +2553,7 @@ targets: build: test language: c src: - - test/core/handshake/client_ssl.c + - test/core/handshake/client_ssl.cc deps: - grpc_test_util - grpc @@ -2568,7 +2568,7 @@ targets: build: test language: c src: - - test/core/handshake/server_ssl.c + - test/core/handshake/server_ssl.cc deps: - grpc_test_util - grpc @@ -2583,7 +2583,7 @@ targets: build: fuzzer language: c src: - - test/core/transport/chttp2/hpack_parser_fuzzer_test.c + - test/core/transport/chttp2/hpack_parser_fuzzer_test.cc deps: - grpc_test_util - grpc @@ -2597,7 +2597,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/hpack_parser_test.c + - test/core/transport/chttp2/hpack_parser_test.cc deps: - grpc_test_util - grpc @@ -2608,7 +2608,7 @@ targets: build: test language: c src: - - test/core/transport/chttp2/hpack_table_test.c + - test/core/transport/chttp2/hpack_table_test.cc deps: - grpc_test_util - grpc @@ -2619,7 +2619,7 @@ targets: build: test language: c src: - - test/core/http/parser_test.c + - test/core/http/parser_test.cc deps: - grpc_test_util - grpc @@ -2630,7 +2630,7 @@ targets: build: fuzzer language: c src: - - test/core/http/request_fuzzer.c + - test/core/http/request_fuzzer.cc deps: - grpc_test_util - grpc @@ -2643,7 +2643,7 @@ targets: build: fuzzer language: c src: - - test/core/http/response_fuzzer.c + - test/core/http/response_fuzzer.cc deps: - grpc_test_util - grpc @@ -2656,7 +2656,7 @@ targets: build: test language: c src: - - test/core/http/format_request_test.c + - test/core/http/format_request_test.cc deps: - grpc_test_util - grpc @@ -2667,7 +2667,7 @@ targets: build: test language: c src: - - test/core/http/httpcli_test.c + - test/core/http/httpcli_test.cc deps: - grpc_test_util - grpc @@ -2682,7 +2682,7 @@ targets: build: test language: c src: - - test/core/http/httpscli_test.c + - test/core/http/httpscli_test.cc deps: - grpc_test_util - grpc @@ -2694,7 +2694,7 @@ targets: build: test language: c src: - - test/core/surface/init_test.c + - test/core/surface/init_test.cc deps: - grpc_test_util - grpc @@ -2706,7 +2706,7 @@ targets: build: test language: c src: - - test/core/end2end/invalid_call_argument_test.c + - test/core/end2end/invalid_call_argument_test.cc deps: - grpc_test_util - grpc @@ -2716,7 +2716,7 @@ targets: build: fuzzer language: c src: - - test/core/json/fuzzer.c + - test/core/json/fuzzer.cc deps: - grpc_test_util - grpc @@ -2730,7 +2730,7 @@ targets: run: false language: c src: - - test/core/json/json_rewrite.c + - test/core/json/json_rewrite.cc deps: - grpc - gpr @@ -2739,7 +2739,7 @@ targets: build: test language: c src: - - test/core/json/json_rewrite_test.c + - test/core/json/json_rewrite_test.cc deps: - grpc_test_util - grpc @@ -2750,7 +2750,7 @@ targets: build: test language: c src: - - test/core/json/json_stream_error_test.c + - test/core/json/json_stream_error_test.cc deps: - grpc_test_util - grpc @@ -2761,7 +2761,7 @@ targets: build: test language: c src: - - test/core/json/json_test.c + - test/core/json/json_test.cc deps: - grpc_test_util - grpc @@ -2772,7 +2772,7 @@ targets: build: test language: c src: - - test/core/surface/lame_client_test.c + - test/core/surface/lame_client_test.cc deps: - grpc_test_util - grpc @@ -2784,7 +2784,7 @@ targets: run: false language: c src: - - test/core/client_channel/lb_policies_test.c + - test/core/client_channel/lb_policies_test.cc deps: - grpc_test_util - grpc @@ -2795,7 +2795,7 @@ targets: build: test language: c src: - - test/core/iomgr/load_file_test.c + - test/core/iomgr/load_file_test.cc deps: - grpc_test_util - grpc @@ -2806,7 +2806,7 @@ targets: build: benchmark language: c src: - - test/core/network_benchmarks/low_level_ping_pong.c + - test/core/network_benchmarks/low_level_ping_pong.cc deps: - grpc_test_util - grpc @@ -2821,7 +2821,7 @@ targets: run: false language: c src: - - test/core/memory_usage/client.c + - test/core/memory_usage/client.cc deps: - grpc_test_util - grpc @@ -2833,7 +2833,7 @@ targets: run: false language: c src: - - test/core/memory_usage/server.c + - test/core/memory_usage/server.cc deps: - grpc_test_util - grpc @@ -2844,7 +2844,7 @@ targets: build: test language: c src: - - test/core/memory_usage/memory_usage_test.c + - test/core/memory_usage/memory_usage_test.cc deps: - grpc_test_util - grpc @@ -2858,7 +2858,7 @@ targets: build: test language: c src: - - test/core/compression/message_compress_test.c + - test/core/compression/message_compress_test.cc deps: - grpc_test_util - grpc @@ -2869,7 +2869,7 @@ targets: build: test language: c src: - - test/core/channel/minimal_stack_is_minimal_test.c + - test/core/channel/minimal_stack_is_minimal_test.cc deps: - grpc_test_util - grpc @@ -2881,7 +2881,7 @@ targets: build: test language: c src: - - test/core/census/mlog_test.c + - test/core/census/mlog_test.cc deps: - grpc_test_util - grpc @@ -2892,7 +2892,7 @@ targets: build: test language: c src: - - test/core/end2end/multiple_server_queues_test.c + - test/core/end2end/multiple_server_queues_test.cc deps: - grpc_test_util - grpc @@ -2902,7 +2902,7 @@ targets: build: test language: c src: - - test/core/support/murmur_hash_test.c + - test/core/support/murmur_hash_test.cc deps: - gpr_test_util - gpr @@ -2911,7 +2911,7 @@ targets: build: fuzzer language: c src: - - test/core/nanopb/fuzzer_response.c + - test/core/nanopb/fuzzer_response.cc deps: - grpc_test_util - grpc @@ -2924,7 +2924,7 @@ targets: build: fuzzer language: c src: - - test/core/nanopb/fuzzer_serverlist.c + - test/core/nanopb/fuzzer_serverlist.cc deps: - grpc_test_util - grpc @@ -2938,7 +2938,7 @@ targets: build: test language: c src: - - test/core/end2end/no_server_test.c + - test/core/end2end/no_server_test.cc deps: - grpc_test_util - grpc @@ -2948,7 +2948,7 @@ targets: build: test language: c src: - - test/core/surface/num_external_connectivity_watchers_test.c + - test/core/surface/num_external_connectivity_watchers_test.cc deps: - grpc_test_util - grpc @@ -2960,7 +2960,7 @@ targets: build: test language: c src: - - test/core/client_channel/parse_address_test.c + - test/core/client_channel/parse_address_test.cc deps: - grpc_test_util - grpc @@ -2971,7 +2971,7 @@ targets: build: fuzzer language: c src: - - test/core/slice/percent_decode_fuzzer.c + - test/core/slice/percent_decode_fuzzer.cc deps: - grpc_test_util - grpc @@ -2984,7 +2984,7 @@ targets: build: fuzzer language: c src: - - test/core/slice/percent_encode_fuzzer.c + - test/core/slice/percent_encode_fuzzer.cc deps: - grpc_test_util - grpc @@ -2997,7 +2997,7 @@ targets: build: test language: c src: - - test/core/slice/percent_encoding_test.c + - test/core/slice/percent_encoding_test.cc deps: - grpc_test_util - grpc @@ -3008,7 +3008,7 @@ targets: build: test language: c src: - - test/core/iomgr/pollset_set_test.c + - test/core/iomgr/pollset_set_test.cc deps: - grpc_test_util - grpc @@ -3022,7 +3022,7 @@ targets: build: test language: c src: - - test/core/iomgr/resolve_address_posix_test.c + - test/core/iomgr/resolve_address_posix_test.cc deps: - grpc_test_util - grpc @@ -3038,7 +3038,7 @@ targets: build: test language: c src: - - test/core/iomgr/resolve_address_test.c + - test/core/iomgr/resolve_address_test.cc deps: - grpc_test_util - grpc @@ -3049,7 +3049,7 @@ targets: build: test language: c src: - - test/core/iomgr/resource_quota_test.c + - test/core/iomgr/resource_quota_test.cc deps: - grpc_test_util - grpc @@ -3059,7 +3059,7 @@ targets: build: test language: c src: - - test/core/surface/secure_channel_create_test.c + - test/core/surface/secure_channel_create_test.cc deps: - grpc_test_util - grpc @@ -3069,7 +3069,7 @@ targets: build: test language: c src: - - test/core/security/secure_endpoint_test.c + - test/core/security/secure_endpoint_test.cc deps: - grpc_test_util - grpc @@ -3081,7 +3081,7 @@ targets: build: test language: c src: - - test/core/surface/sequential_connectivity_test.c + - test/core/surface/sequential_connectivity_test.cc deps: - grpc_test_util - grpc @@ -3093,7 +3093,7 @@ targets: build: test language: c src: - - test/core/surface/server_chttp2_test.c + - test/core/surface/server_chttp2_test.cc deps: - grpc_test_util - grpc @@ -3103,7 +3103,7 @@ targets: build: fuzzer language: c src: - - test/core/end2end/fuzzers/server_fuzzer.c + - test/core/end2end/fuzzers/server_fuzzer.cc deps: - grpc_test_util - grpc @@ -3117,7 +3117,7 @@ targets: build: test language: c src: - - test/core/surface/server_test.c + - test/core/surface/server_test.cc deps: - grpc_test_util - grpc @@ -3127,7 +3127,7 @@ targets: build: test language: c src: - - test/core/slice/slice_buffer_test.c + - test/core/slice/slice_buffer_test.cc deps: - grpc_test_util - grpc @@ -3138,7 +3138,7 @@ targets: build: test language: c src: - - test/core/slice/slice_hash_table_test.c + - test/core/slice/slice_hash_table_test.cc deps: - grpc_test_util - grpc @@ -3149,7 +3149,7 @@ targets: build: test language: c src: - - test/core/slice/slice_string_helpers_test.c + - test/core/slice/slice_string_helpers_test.cc deps: - grpc_test_util - grpc @@ -3160,7 +3160,7 @@ targets: build: test language: c src: - - test/core/slice/slice_test.c + - test/core/slice/slice_test.cc deps: - grpc_test_util - grpc @@ -3171,7 +3171,7 @@ targets: build: test language: c src: - - test/core/client_channel/resolvers/sockaddr_resolver_test.c + - test/core/client_channel/resolvers/sockaddr_resolver_test.cc deps: - grpc_test_util - grpc @@ -3181,7 +3181,7 @@ targets: build: test language: c src: - - test/core/iomgr/sockaddr_utils_test.c + - test/core/iomgr/sockaddr_utils_test.cc deps: - grpc_test_util - grpc @@ -3191,7 +3191,7 @@ targets: build: test language: c src: - - test/core/iomgr/socket_utils_test.c + - test/core/iomgr/socket_utils_test.cc deps: - grpc_test_util - grpc @@ -3207,7 +3207,7 @@ targets: build: fuzzer language: c src: - - test/core/security/ssl_server_fuzzer.c + - test/core/security/ssl_server_fuzzer.cc deps: - grpc_test_util - grpc @@ -3220,7 +3220,7 @@ targets: build: test language: c src: - - test/core/tsi/ssl_transport_security_test.c + - test/core/tsi/ssl_transport_security_test.cc deps: - gpr_test_util - gpr @@ -3235,7 +3235,7 @@ targets: build: test language: c src: - - test/core/transport/status_conversion_test.c + - test/core/transport/status_conversion_test.cc deps: - grpc_test_util - grpc @@ -3246,7 +3246,7 @@ targets: build: test language: c src: - - test/core/compression/stream_compression_test.c + - test/core/compression/stream_compression_test.cc deps: - grpc_test_util - grpc @@ -3257,7 +3257,7 @@ targets: build: test language: c src: - - test/core/transport/stream_owned_slice_test.c + - test/core/transport/stream_owned_slice_test.cc deps: - grpc_test_util - grpc @@ -3269,7 +3269,7 @@ targets: build: test language: c src: - - test/core/iomgr/tcp_client_posix_test.c + - test/core/iomgr/tcp_client_posix_test.cc deps: - grpc_test_util - grpc @@ -3286,7 +3286,7 @@ targets: build: test language: c src: - - test/core/iomgr/tcp_client_uv_test.c + - test/core/iomgr/tcp_client_uv_test.cc deps: - grpc_test_util - grpc @@ -3299,7 +3299,7 @@ targets: build: test language: c src: - - test/core/iomgr/tcp_posix_test.c + - test/core/iomgr/tcp_posix_test.cc deps: - grpc_test_util - grpc @@ -3315,7 +3315,7 @@ targets: build: test language: c src: - - test/core/iomgr/tcp_server_posix_test.c + - test/core/iomgr/tcp_server_posix_test.cc deps: - grpc_test_util - grpc @@ -3331,7 +3331,7 @@ targets: build: test language: c src: - - test/core/iomgr/tcp_server_uv_test.c + - test/core/iomgr/tcp_server_uv_test.cc deps: - grpc_test_util - grpc @@ -3343,7 +3343,7 @@ targets: build: test language: c src: - - test/core/iomgr/time_averaged_stats_test.c + - test/core/iomgr/time_averaged_stats_test.cc deps: - grpc_test_util - grpc @@ -3354,7 +3354,7 @@ targets: build: test language: c src: - - test/core/transport/timeout_encoding_test.c + - test/core/transport/timeout_encoding_test.cc deps: - grpc_test_util - grpc @@ -3365,7 +3365,7 @@ targets: build: test language: c src: - - test/core/iomgr/timer_heap_test.c + - test/core/iomgr/timer_heap_test.cc deps: - grpc_test_util - grpc @@ -3378,7 +3378,7 @@ targets: build: test language: c src: - - test/core/iomgr/timer_list_test.c + - test/core/iomgr/timer_list_test.cc deps: - grpc_test_util - grpc @@ -3391,7 +3391,7 @@ targets: build: test language: c src: - - test/core/transport/connectivity_state_test.c + - test/core/transport/connectivity_state_test.cc deps: - grpc_test_util - grpc @@ -3401,7 +3401,7 @@ targets: build: test language: c src: - - test/core/transport/metadata_test.c + - test/core/transport/metadata_test.cc deps: - grpc_test_util - grpc @@ -3411,7 +3411,7 @@ targets: build: test language: c src: - - test/core/tsi/transport_security_test.c + - test/core/tsi/transport_security_test.cc deps: - grpc_test_util - grpc @@ -3425,7 +3425,7 @@ targets: build: test language: c src: - - test/core/iomgr/udp_server_test.c + - test/core/iomgr/udp_server_test.cc deps: - grpc_test_util - grpc @@ -3441,7 +3441,7 @@ targets: build: fuzzer language: c src: - - test/core/client_channel/uri_fuzzer_test.c + - test/core/client_channel/uri_fuzzer_test.cc deps: - grpc_test_util - grpc @@ -3454,7 +3454,7 @@ targets: build: test language: c src: - - test/core/client_channel/uri_parser_test.c + - test/core/client_channel/uri_parser_test.cc deps: - grpc_test_util - grpc @@ -3464,7 +3464,7 @@ targets: build: test language: c src: - - test/core/iomgr/wakeup_fd_cv_test.c + - test/core/iomgr/wakeup_fd_cv_test.cc deps: - grpc_test_util - grpc diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index a9b451e3de..2074323858 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1001,17 +1001,17 @@ Pod::Spec.new do |s| ss.dependency "#{s.name}/Interface", version ss.dependency "#{s.name}/Implementation", version - ss.source_files = 'test/core/end2end/cq_verifier.{c,h}', - 'test/core/end2end/end2end_tests.{c,h}', - 'test/core/end2end/end2end_test_utils.c', - 'test/core/end2end/tests/*.{c,h}', + ss.source_files = 'test/core/end2end/cq_verifier.{cc,h}', + 'test/core/end2end/end2end_tests.{cc,h}', + 'test/core/end2end/end2end_test_utils.cc', + 'test/core/end2end/tests/*.{cc,h}', 'test/core/end2end/fixtures/*.h', - 'test/core/end2end/data/*.{c,h}', - 'test/core/util/debugger_macros.{c,h}', - 'test/core/util/test_config.{c,h}', + 'test/core/end2end/data/*.{cc,h}', + 'test/core/util/debugger_macros.{cc,h}', + 'test/core/util/test_config.{cc,h}', 'test/core/util/port.h', - 'test/core/util/port.c', - 'test/core/util/port_server_client.{c,h}' + 'test/core/util/port.cc', + 'test/core/util/port_server_client.{cc,h}' end # TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path? diff --git a/grpc.gyp b/grpc.gyp index 487d529316..6e2fc9df19 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -215,7 +215,7 @@ 'gpr', ], 'sources': [ - 'test/core/util/test_config.c', + 'test/core/util/test_config.cc', ], }, { @@ -508,26 +508,26 @@ 'grpc', ], 'sources': [ - 'test/core/end2end/data/client_certs.c', - 'test/core/end2end/data/server1_cert.c', - 'test/core/end2end/data/server1_key.c', - 'test/core/end2end/data/test_root_cert.c', - 'test/core/security/oauth2_utils.c', + 'test/core/end2end/data/client_certs.cc', + 'test/core/end2end/data/server1_cert.cc', + 'test/core/end2end/data/server1_key.cc', + 'test/core/end2end/data/test_root_cert.cc', + 'test/core/security/oauth2_utils.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', - 'test/core/end2end/cq_verifier.c', - 'test/core/end2end/fixtures/http_proxy_fixture.c', - 'test/core/end2end/fixtures/proxy.c', - 'test/core/iomgr/endpoint_tests.c', + 'test/core/end2end/cq_verifier.cc', + 'test/core/end2end/fixtures/http_proxy_fixture.cc', + 'test/core/end2end/fixtures/proxy.cc', + 'test/core/iomgr/endpoint_tests.cc', 'test/core/util/debugger_macros.cc', - 'test/core/util/grpc_profiler.c', - 'test/core/util/memory_counters.c', - 'test/core/util/mock_endpoint.c', - 'test/core/util/parse_hexstring.c', - 'test/core/util/passthru_endpoint.c', - 'test/core/util/port.c', - 'test/core/util/port_server_client.c', - 'test/core/util/slice_splitter.c', - 'test/core/util/trickle_endpoint.c', + 'test/core/util/grpc_profiler.cc', + 'test/core/util/memory_counters.cc', + 'test/core/util/mock_endpoint.cc', + 'test/core/util/parse_hexstring.cc', + 'test/core/util/passthru_endpoint.cc', + 'test/core/util/port.cc', + 'test/core/util/port_server_client.cc', + 'test/core/util/slice_splitter.cc', + 'test/core/util/trickle_endpoint.cc', 'src/core/lib/backoff/backoff.cc', 'src/core/lib/channel/channel_args.cc', 'src/core/lib/channel/channel_stack.cc', @@ -721,20 +721,20 @@ ], 'sources': [ 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', - 'test/core/end2end/cq_verifier.c', - 'test/core/end2end/fixtures/http_proxy_fixture.c', - 'test/core/end2end/fixtures/proxy.c', - 'test/core/iomgr/endpoint_tests.c', + 'test/core/end2end/cq_verifier.cc', + 'test/core/end2end/fixtures/http_proxy_fixture.cc', + 'test/core/end2end/fixtures/proxy.cc', + 'test/core/iomgr/endpoint_tests.cc', 'test/core/util/debugger_macros.cc', - 'test/core/util/grpc_profiler.c', - 'test/core/util/memory_counters.c', - 'test/core/util/mock_endpoint.c', - 'test/core/util/parse_hexstring.c', - 'test/core/util/passthru_endpoint.c', - 'test/core/util/port.c', - 'test/core/util/port_server_client.c', - 'test/core/util/slice_splitter.c', - 'test/core/util/trickle_endpoint.c', + 'test/core/util/grpc_profiler.cc', + 'test/core/util/memory_counters.cc', + 'test/core/util/mock_endpoint.cc', + 'test/core/util/parse_hexstring.cc', + 'test/core/util/passthru_endpoint.cc', + 'test/core/util/port.cc', + 'test/core/util/port_server_client.cc', + 'test/core/util/slice_splitter.cc', + 'test/core/util/trickle_endpoint.cc', 'src/core/lib/backoff/backoff.cc', 'src/core/lib/channel/channel_args.cc', 'src/core/lib/channel/channel_stack.cc', @@ -1169,7 +1169,7 @@ 'gpr', ], 'sources': [ - 'test/core/util/reconnect_server.c', + 'test/core/util/reconnect_server.cc', ], }, { @@ -1182,7 +1182,7 @@ 'gpr', ], 'sources': [ - 'test/core/util/test_tcp_server.c', + 'test/core/util/test_tcp_server.cc', ], }, { @@ -2358,7 +2358,7 @@ 'gpr', ], 'sources': [ - 'test/core/bad_client/bad_client.c', + 'test/core/bad_client/bad_client.cc', ], }, { @@ -2371,67 +2371,67 @@ 'gpr', ], 'sources': [ - 'test/core/end2end/end2end_tests.c', - 'test/core/end2end/end2end_test_utils.c', - 'test/core/end2end/tests/authority_not_supported.c', - 'test/core/end2end/tests/bad_hostname.c', - 'test/core/end2end/tests/bad_ping.c', - 'test/core/end2end/tests/binary_metadata.c', - 'test/core/end2end/tests/call_creds.c', - 'test/core/end2end/tests/cancel_after_accept.c', - 'test/core/end2end/tests/cancel_after_client_done.c', - 'test/core/end2end/tests/cancel_after_invoke.c', - 'test/core/end2end/tests/cancel_after_round_trip.c', - 'test/core/end2end/tests/cancel_before_invoke.c', - 'test/core/end2end/tests/cancel_in_a_vacuum.c', - 'test/core/end2end/tests/cancel_with_status.c', - 'test/core/end2end/tests/compressed_payload.c', - 'test/core/end2end/tests/connectivity.c', - 'test/core/end2end/tests/default_host.c', - 'test/core/end2end/tests/disappearing_server.c', - 'test/core/end2end/tests/empty_batch.c', - 'test/core/end2end/tests/filter_call_init_fails.c', - 'test/core/end2end/tests/filter_causes_close.c', - 'test/core/end2end/tests/filter_latency.c', - 'test/core/end2end/tests/graceful_server_shutdown.c', - 'test/core/end2end/tests/high_initial_seqno.c', - 'test/core/end2end/tests/hpack_size.c', - 'test/core/end2end/tests/idempotent_request.c', - 'test/core/end2end/tests/invoke_large_request.c', - 'test/core/end2end/tests/keepalive_timeout.c', - 'test/core/end2end/tests/large_metadata.c', - 'test/core/end2end/tests/load_reporting_hook.c', - 'test/core/end2end/tests/max_concurrent_streams.c', - 'test/core/end2end/tests/max_connection_age.c', - 'test/core/end2end/tests/max_connection_idle.c', - 'test/core/end2end/tests/max_message_length.c', - 'test/core/end2end/tests/negative_deadline.c', - 'test/core/end2end/tests/network_status_change.c', - 'test/core/end2end/tests/no_logging.c', - 'test/core/end2end/tests/no_op.c', - 'test/core/end2end/tests/payload.c', - 'test/core/end2end/tests/ping.c', - 'test/core/end2end/tests/ping_pong_streaming.c', - 'test/core/end2end/tests/proxy_auth.c', - 'test/core/end2end/tests/registered_call.c', - 'test/core/end2end/tests/request_with_flags.c', - 'test/core/end2end/tests/request_with_payload.c', - 'test/core/end2end/tests/resource_quota_server.c', - 'test/core/end2end/tests/server_finishes_request.c', - 'test/core/end2end/tests/shutdown_finishes_calls.c', - 'test/core/end2end/tests/shutdown_finishes_tags.c', - 'test/core/end2end/tests/simple_cacheable_request.c', - 'test/core/end2end/tests/simple_delayed_request.c', - 'test/core/end2end/tests/simple_metadata.c', - 'test/core/end2end/tests/simple_request.c', - 'test/core/end2end/tests/stream_compression_compressed_payload.c', - 'test/core/end2end/tests/stream_compression_payload.c', - 'test/core/end2end/tests/stream_compression_ping_pong_streaming.c', - 'test/core/end2end/tests/streaming_error_response.c', - 'test/core/end2end/tests/trailing_metadata.c', - 'test/core/end2end/tests/workaround_cronet_compression.c', - 'test/core/end2end/tests/write_buffering.c', - 'test/core/end2end/tests/write_buffering_at_end.c', + 'test/core/end2end/end2end_tests.cc', + 'test/core/end2end/end2end_test_utils.cc', + 'test/core/end2end/tests/authority_not_supported.cc', + 'test/core/end2end/tests/bad_hostname.cc', + 'test/core/end2end/tests/bad_ping.cc', + 'test/core/end2end/tests/binary_metadata.cc', + 'test/core/end2end/tests/call_creds.cc', + 'test/core/end2end/tests/cancel_after_accept.cc', + 'test/core/end2end/tests/cancel_after_client_done.cc', + 'test/core/end2end/tests/cancel_after_invoke.cc', + 'test/core/end2end/tests/cancel_after_round_trip.cc', + 'test/core/end2end/tests/cancel_before_invoke.cc', + 'test/core/end2end/tests/cancel_in_a_vacuum.cc', + 'test/core/end2end/tests/cancel_with_status.cc', + 'test/core/end2end/tests/compressed_payload.cc', + 'test/core/end2end/tests/connectivity.cc', + 'test/core/end2end/tests/default_host.cc', + 'test/core/end2end/tests/disappearing_server.cc', + 'test/core/end2end/tests/empty_batch.cc', + 'test/core/end2end/tests/filter_call_init_fails.cc', + 'test/core/end2end/tests/filter_causes_close.cc', + 'test/core/end2end/tests/filter_latency.cc', + 'test/core/end2end/tests/graceful_server_shutdown.cc', + 'test/core/end2end/tests/high_initial_seqno.cc', + 'test/core/end2end/tests/hpack_size.cc', + 'test/core/end2end/tests/idempotent_request.cc', + 'test/core/end2end/tests/invoke_large_request.cc', + 'test/core/end2end/tests/keepalive_timeout.cc', + 'test/core/end2end/tests/large_metadata.cc', + 'test/core/end2end/tests/load_reporting_hook.cc', + 'test/core/end2end/tests/max_concurrent_streams.cc', + 'test/core/end2end/tests/max_connection_age.cc', + 'test/core/end2end/tests/max_connection_idle.cc', + 'test/core/end2end/tests/max_message_length.cc', + 'test/core/end2end/tests/negative_deadline.cc', + 'test/core/end2end/tests/network_status_change.cc', + 'test/core/end2end/tests/no_logging.cc', + 'test/core/end2end/tests/no_op.cc', + 'test/core/end2end/tests/payload.cc', + 'test/core/end2end/tests/ping.cc', + 'test/core/end2end/tests/ping_pong_streaming.cc', + 'test/core/end2end/tests/proxy_auth.cc', + 'test/core/end2end/tests/registered_call.cc', + 'test/core/end2end/tests/request_with_flags.cc', + 'test/core/end2end/tests/request_with_payload.cc', + 'test/core/end2end/tests/resource_quota_server.cc', + 'test/core/end2end/tests/server_finishes_request.cc', + 'test/core/end2end/tests/shutdown_finishes_calls.cc', + 'test/core/end2end/tests/shutdown_finishes_tags.cc', + 'test/core/end2end/tests/simple_cacheable_request.cc', + 'test/core/end2end/tests/simple_delayed_request.cc', + 'test/core/end2end/tests/simple_metadata.cc', + 'test/core/end2end/tests/simple_request.cc', + 'test/core/end2end/tests/stream_compression_compressed_payload.cc', + 'test/core/end2end/tests/stream_compression_payload.cc', + 'test/core/end2end/tests/stream_compression_ping_pong_streaming.cc', + 'test/core/end2end/tests/streaming_error_response.cc', + 'test/core/end2end/tests/trailing_metadata.cc', + 'test/core/end2end/tests/workaround_cronet_compression.cc', + 'test/core/end2end/tests/write_buffering.cc', + 'test/core/end2end/tests/write_buffering_at_end.cc', ], }, { @@ -2444,66 +2444,66 @@ 'gpr', ], 'sources': [ - 'test/core/end2end/end2end_nosec_tests.c', - 'test/core/end2end/end2end_test_utils.c', - 'test/core/end2end/tests/authority_not_supported.c', - 'test/core/end2end/tests/bad_hostname.c', - 'test/core/end2end/tests/bad_ping.c', - 'test/core/end2end/tests/binary_metadata.c', - 'test/core/end2end/tests/cancel_after_accept.c', - 'test/core/end2end/tests/cancel_after_client_done.c', - 'test/core/end2end/tests/cancel_after_invoke.c', - 'test/core/end2end/tests/cancel_after_round_trip.c', - 'test/core/end2end/tests/cancel_before_invoke.c', - 'test/core/end2end/tests/cancel_in_a_vacuum.c', - 'test/core/end2end/tests/cancel_with_status.c', - 'test/core/end2end/tests/compressed_payload.c', - 'test/core/end2end/tests/connectivity.c', - 'test/core/end2end/tests/default_host.c', - 'test/core/end2end/tests/disappearing_server.c', - 'test/core/end2end/tests/empty_batch.c', - 'test/core/end2end/tests/filter_call_init_fails.c', - 'test/core/end2end/tests/filter_causes_close.c', - 'test/core/end2end/tests/filter_latency.c', - 'test/core/end2end/tests/graceful_server_shutdown.c', - 'test/core/end2end/tests/high_initial_seqno.c', - 'test/core/end2end/tests/hpack_size.c', - 'test/core/end2end/tests/idempotent_request.c', - 'test/core/end2end/tests/invoke_large_request.c', - 'test/core/end2end/tests/keepalive_timeout.c', - 'test/core/end2end/tests/large_metadata.c', - 'test/core/end2end/tests/load_reporting_hook.c', - 'test/core/end2end/tests/max_concurrent_streams.c', - 'test/core/end2end/tests/max_connection_age.c', - 'test/core/end2end/tests/max_connection_idle.c', - 'test/core/end2end/tests/max_message_length.c', - 'test/core/end2end/tests/negative_deadline.c', - 'test/core/end2end/tests/network_status_change.c', - 'test/core/end2end/tests/no_logging.c', - 'test/core/end2end/tests/no_op.c', - 'test/core/end2end/tests/payload.c', - 'test/core/end2end/tests/ping.c', - 'test/core/end2end/tests/ping_pong_streaming.c', - 'test/core/end2end/tests/proxy_auth.c', - 'test/core/end2end/tests/registered_call.c', - 'test/core/end2end/tests/request_with_flags.c', - 'test/core/end2end/tests/request_with_payload.c', - 'test/core/end2end/tests/resource_quota_server.c', - 'test/core/end2end/tests/server_finishes_request.c', - 'test/core/end2end/tests/shutdown_finishes_calls.c', - 'test/core/end2end/tests/shutdown_finishes_tags.c', - 'test/core/end2end/tests/simple_cacheable_request.c', - 'test/core/end2end/tests/simple_delayed_request.c', - 'test/core/end2end/tests/simple_metadata.c', - 'test/core/end2end/tests/simple_request.c', - 'test/core/end2end/tests/stream_compression_compressed_payload.c', - 'test/core/end2end/tests/stream_compression_payload.c', - 'test/core/end2end/tests/stream_compression_ping_pong_streaming.c', - 'test/core/end2end/tests/streaming_error_response.c', - 'test/core/end2end/tests/trailing_metadata.c', - 'test/core/end2end/tests/workaround_cronet_compression.c', - 'test/core/end2end/tests/write_buffering.c', - 'test/core/end2end/tests/write_buffering_at_end.c', + 'test/core/end2end/end2end_nosec_tests.cc', + 'test/core/end2end/end2end_test_utils.cc', + 'test/core/end2end/tests/authority_not_supported.cc', + 'test/core/end2end/tests/bad_hostname.cc', + 'test/core/end2end/tests/bad_ping.cc', + 'test/core/end2end/tests/binary_metadata.cc', + 'test/core/end2end/tests/cancel_after_accept.cc', + 'test/core/end2end/tests/cancel_after_client_done.cc', + 'test/core/end2end/tests/cancel_after_invoke.cc', + 'test/core/end2end/tests/cancel_after_round_trip.cc', + 'test/core/end2end/tests/cancel_before_invoke.cc', + 'test/core/end2end/tests/cancel_in_a_vacuum.cc', + 'test/core/end2end/tests/cancel_with_status.cc', + 'test/core/end2end/tests/compressed_payload.cc', + 'test/core/end2end/tests/connectivity.cc', + 'test/core/end2end/tests/default_host.cc', + 'test/core/end2end/tests/disappearing_server.cc', + 'test/core/end2end/tests/empty_batch.cc', + 'test/core/end2end/tests/filter_call_init_fails.cc', + 'test/core/end2end/tests/filter_causes_close.cc', + 'test/core/end2end/tests/filter_latency.cc', + 'test/core/end2end/tests/graceful_server_shutdown.cc', + 'test/core/end2end/tests/high_initial_seqno.cc', + 'test/core/end2end/tests/hpack_size.cc', + 'test/core/end2end/tests/idempotent_request.cc', + 'test/core/end2end/tests/invoke_large_request.cc', + 'test/core/end2end/tests/keepalive_timeout.cc', + 'test/core/end2end/tests/large_metadata.cc', + 'test/core/end2end/tests/load_reporting_hook.cc', + 'test/core/end2end/tests/max_concurrent_streams.cc', + 'test/core/end2end/tests/max_connection_age.cc', + 'test/core/end2end/tests/max_connection_idle.cc', + 'test/core/end2end/tests/max_message_length.cc', + 'test/core/end2end/tests/negative_deadline.cc', + 'test/core/end2end/tests/network_status_change.cc', + 'test/core/end2end/tests/no_logging.cc', + 'test/core/end2end/tests/no_op.cc', + 'test/core/end2end/tests/payload.cc', + 'test/core/end2end/tests/ping.cc', + 'test/core/end2end/tests/ping_pong_streaming.cc', + 'test/core/end2end/tests/proxy_auth.cc', + 'test/core/end2end/tests/registered_call.cc', + 'test/core/end2end/tests/request_with_flags.cc', + 'test/core/end2end/tests/request_with_payload.cc', + 'test/core/end2end/tests/resource_quota_server.cc', + 'test/core/end2end/tests/server_finishes_request.cc', + 'test/core/end2end/tests/shutdown_finishes_calls.cc', + 'test/core/end2end/tests/shutdown_finishes_tags.cc', + 'test/core/end2end/tests/simple_cacheable_request.cc', + 'test/core/end2end/tests/simple_delayed_request.cc', + 'test/core/end2end/tests/simple_metadata.cc', + 'test/core/end2end/tests/simple_request.cc', + 'test/core/end2end/tests/stream_compression_compressed_payload.cc', + 'test/core/end2end/tests/stream_compression_payload.cc', + 'test/core/end2end/tests/stream_compression_ping_pong_streaming.cc', + 'test/core/end2end/tests/streaming_error_response.cc', + 'test/core/end2end/tests/trailing_metadata.cc', + 'test/core/end2end/tests/workaround_cronet_compression.cc', + 'test/core/end2end/tests/write_buffering.cc', + 'test/core/end2end/tests/write_buffering_at_end.cc', ], }, ] diff --git a/include/grpc/support/cmdline.h b/include/grpc/support/cmdline.h index 9f46491b38..5baa06b638 100644 --- a/include/grpc/support/cmdline.h +++ b/include/grpc/support/cmdline.h @@ -65,7 +65,7 @@ GPRAPI void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help, int *value); /** And for a string */ GPRAPI void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, - const char *help, char **value); + const char *help, const char **value); /** Set a callback for non-named arguments */ GPRAPI void gpr_cmdline_on_extra_arg( gpr_cmdline *cl, const char *name, const char *help, diff --git a/src/core/lib/iomgr/network_status_tracker.h b/src/core/lib/iomgr/network_status_tracker.h index cba38d4530..c0295c1f74 100644 --- a/src/core/lib/iomgr/network_status_tracker.h +++ b/src/core/lib/iomgr/network_status_tracker.h @@ -20,10 +20,6 @@ #define GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H #include "src/core/lib/iomgr/endpoint.h" -#ifdef __cplusplus -extern "C" { -#endif - void grpc_network_status_init(void); void grpc_network_status_shutdown(void); @@ -31,8 +27,4 @@ void grpc_network_status_register_endpoint(grpc_endpoint *ep); void grpc_network_status_unregister_endpoint(grpc_endpoint *ep); void grpc_network_status_shutdown_all_endpoints(); -#ifdef __cplusplus -} -#endif - #endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */ diff --git a/src/core/lib/support/cmdline.cc b/src/core/lib/support/cmdline.cc index 9fb80d4460..9a059bab77 100644 --- a/src/core/lib/support/cmdline.cc +++ b/src/core/lib/support/cmdline.cc @@ -105,7 +105,7 @@ void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help, } void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help, - char **value) { + const char **value) { add_arg(cl, name, help, ARGTYPE_STRING, value); } diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 868772cfc8..172cba1271 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -689,7 +689,7 @@ extern gpr_cmdline_add_int_type gpr_cmdline_add_int_import; typedef void(*gpr_cmdline_add_flag_type)(gpr_cmdline *cl, const char *name, const char *help, int *value); extern gpr_cmdline_add_flag_type gpr_cmdline_add_flag_import; #define gpr_cmdline_add_flag gpr_cmdline_add_flag_import -typedef void(*gpr_cmdline_add_string_type)(gpr_cmdline *cl, const char *name, const char *help, char **value); +typedef void(*gpr_cmdline_add_string_type)(gpr_cmdline *cl, const char *name, const char *help, const char **value); extern gpr_cmdline_add_string_type gpr_cmdline_add_string_import; #define gpr_cmdline_add_string gpr_cmdline_add_string_import typedef void(*gpr_cmdline_on_extra_arg_type)(gpr_cmdline *cl, const char *name, const char *help, void (*on_extra_arg)(void *user_data, const char *arg), void *user_data); diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 5657df8521..d7e8faeb36 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -168,17 +168,17 @@ ss.dependency "#{s.name}/Interface", version ss.dependency "#{s.name}/Implementation", version - ss.source_files = 'test/core/end2end/cq_verifier.{c,h}', - 'test/core/end2end/end2end_tests.{c,h}', - 'test/core/end2end/end2end_test_utils.c', - 'test/core/end2end/tests/*.{c,h}', + ss.source_files = 'test/core/end2end/cq_verifier.{cc,h}', + 'test/core/end2end/end2end_tests.{cc,h}', + 'test/core/end2end/end2end_test_utils.cc', + 'test/core/end2end/tests/*.{cc,h}', 'test/core/end2end/fixtures/*.h', - 'test/core/end2end/data/*.{c,h}', - 'test/core/util/debugger_macros.{c,h}', - 'test/core/util/test_config.{c,h}', + 'test/core/end2end/data/*.{cc,h}', + 'test/core/util/debugger_macros.{cc,h}', + 'test/core/util/test_config.{cc,h}', 'test/core/util/port.h', - 'test/core/util/port.c', - 'test/core/util/port_server_client.{c,h}' + 'test/core/util/port.cc', + 'test/core/util/port_server_client.{cc,h}' end # TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path? diff --git a/templates/test/core/end2end/end2end_nosec_tests.c.template b/templates/test/core/end2end/end2end_nosec_tests.c.template deleted file mode 100644 index 3719ded75d..0000000000 --- a/templates/test/core/end2end/end2end_nosec_tests.c.template +++ /dev/null @@ -1,4 +0,0 @@ -%YAML 1.2 ---- | - <%namespace file="end2end_defs.include" import="*"/>\ - ${end2end_selector(k for k, v in core_end2end_tests.iteritems() if not v)} diff --git a/templates/test/core/end2end/end2end_nosec_tests.cc.template b/templates/test/core/end2end/end2end_nosec_tests.cc.template new file mode 100644 index 0000000000..3719ded75d --- /dev/null +++ b/templates/test/core/end2end/end2end_nosec_tests.cc.template @@ -0,0 +1,4 @@ +%YAML 1.2 +--- | + <%namespace file="end2end_defs.include" import="*"/>\ + ${end2end_selector(k for k, v in core_end2end_tests.iteritems() if not v)} diff --git a/templates/test/core/end2end/end2end_tests.c.template b/templates/test/core/end2end/end2end_tests.c.template deleted file mode 100644 index e6a49f2795..0000000000 --- a/templates/test/core/end2end/end2end_tests.c.template +++ /dev/null @@ -1,4 +0,0 @@ -%YAML 1.2 ---- | - <%namespace file="end2end_defs.include" import="*"/>\ - ${end2end_selector(core_end2end_tests.keys())} diff --git a/templates/test/core/end2end/end2end_tests.cc.template b/templates/test/core/end2end/end2end_tests.cc.template new file mode 100644 index 0000000000..e6a49f2795 --- /dev/null +++ b/templates/test/core/end2end/end2end_tests.cc.template @@ -0,0 +1,4 @@ +%YAML 1.2 +--- | + <%namespace file="end2end_defs.include" import="*"/>\ + ${end2end_selector(core_end2end_tests.keys())} diff --git a/test/core/backoff/backoff_test.c b/test/core/backoff/backoff_test.c deleted file mode 100644 index a29cce6cc7..0000000000 --- a/test/core/backoff/backoff_test.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/backoff/backoff.h" - -#include - -#include "test/core/util/test_config.h" - -static void test_constant_backoff(void) { - grpc_backoff backoff; - grpc_backoff_init(&backoff, 200 /* initial timeout */, 1.0 /* multiplier */, - 0.0 /* jitter */, 100 /* min timeout */, - 1000 /* max timeout */); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); - for (int i = 0; i < 10000; i++) { - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); - exec_ctx.now = next; - } - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_min_connect(void) { - grpc_backoff backoff; - grpc_backoff_init(&backoff, 100 /* initial timeout */, 1.0 /* multiplier */, - 0.0 /* jitter */, 200 /* min timeout */, - 1000 /* max timeout */); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_jitter_backoff(void) { - grpc_backoff backoff; - grpc_backoff_init(&backoff, 2 /* initial timeout */, 2.0 /* multiplier */, - 0.0 /* jitter */, 1 /* min timeout */, - 513 /* max timeout */); - // x_1 = 2 - // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 ) - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - exec_ctx.now = 0; - exec_ctx.now_is_valid = true; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next == 2); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 6); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 14); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 30); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 62); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 126); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 254); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 510); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 1022); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - // Hit the maximum timeout. From this point onwards, retries will increase - // only by max timeout. - GPR_ASSERT(next == 1535); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 2048); - exec_ctx.now = next; - next = grpc_backoff_step(&exec_ctx, &backoff); - GPR_ASSERT(next == 2561); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_jitter_backoff(void) { - const int64_t initial_timeout = 500; - const double jitter = 0.1; - grpc_backoff backoff; - grpc_backoff_init(&backoff, (grpc_millis)initial_timeout, - 1.0 /* multiplier */, jitter, 100 /* min timeout */, - 1000 /* max timeout */); - - backoff.rng_state = 0; // force consistent PRNG - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); - GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 500); - - int64_t expected_next_lower_bound = - (int64_t)((double)initial_timeout * (1 - jitter)); - int64_t expected_next_upper_bound = - (int64_t)((double)initial_timeout * (1 + jitter)); - - for (int i = 0; i < 10000; i++) { - next = grpc_backoff_step(&exec_ctx, &backoff); - - // next-now must be within (jitter*100)% of the previous timeout. - const int64_t timeout_millis = next - grpc_exec_ctx_now(&exec_ctx); - GPR_ASSERT(timeout_millis >= expected_next_lower_bound); - GPR_ASSERT(timeout_millis <= expected_next_upper_bound); - - expected_next_lower_bound = - (int64_t)((double)timeout_millis * (1 - jitter)); - expected_next_upper_bound = - (int64_t)((double)timeout_millis * (1 + jitter)); - exec_ctx.now = next; - } - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - gpr_time_init(); - - test_constant_backoff(); - test_min_connect(); - test_no_jitter_backoff(); - test_jitter_backoff(); - - return 0; -} diff --git a/test/core/backoff/backoff_test.cc b/test/core/backoff/backoff_test.cc new file mode 100644 index 0000000000..a29cce6cc7 --- /dev/null +++ b/test/core/backoff/backoff_test.cc @@ -0,0 +1,150 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/backoff/backoff.h" + +#include + +#include "test/core/util/test_config.h" + +static void test_constant_backoff(void) { + grpc_backoff backoff; + grpc_backoff_init(&backoff, 200 /* initial timeout */, 1.0 /* multiplier */, + 0.0 /* jitter */, 100 /* min timeout */, + 1000 /* max timeout */); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); + for (int i = 0; i < 10000; i++) { + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); + exec_ctx.now = next; + } + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_min_connect(void) { + grpc_backoff backoff; + grpc_backoff_init(&backoff, 100 /* initial timeout */, 1.0 /* multiplier */, + 0.0 /* jitter */, 200 /* min timeout */, + 1000 /* max timeout */); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 200); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_jitter_backoff(void) { + grpc_backoff backoff; + grpc_backoff_init(&backoff, 2 /* initial timeout */, 2.0 /* multiplier */, + 0.0 /* jitter */, 1 /* min timeout */, + 513 /* max timeout */); + // x_1 = 2 + // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 ) + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + exec_ctx.now = 0; + exec_ctx.now_is_valid = true; + grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next == 2); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 6); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 14); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 30); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 62); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 126); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 254); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 510); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 1022); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + // Hit the maximum timeout. From this point onwards, retries will increase + // only by max timeout. + GPR_ASSERT(next == 1535); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 2048); + exec_ctx.now = next; + next = grpc_backoff_step(&exec_ctx, &backoff); + GPR_ASSERT(next == 2561); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_jitter_backoff(void) { + const int64_t initial_timeout = 500; + const double jitter = 0.1; + grpc_backoff backoff; + grpc_backoff_init(&backoff, (grpc_millis)initial_timeout, + 1.0 /* multiplier */, jitter, 100 /* min timeout */, + 1000 /* max timeout */); + + backoff.rng_state = 0; // force consistent PRNG + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis next = grpc_backoff_begin(&exec_ctx, &backoff); + GPR_ASSERT(next - grpc_exec_ctx_now(&exec_ctx) == 500); + + int64_t expected_next_lower_bound = + (int64_t)((double)initial_timeout * (1 - jitter)); + int64_t expected_next_upper_bound = + (int64_t)((double)initial_timeout * (1 + jitter)); + + for (int i = 0; i < 10000; i++) { + next = grpc_backoff_step(&exec_ctx, &backoff); + + // next-now must be within (jitter*100)% of the previous timeout. + const int64_t timeout_millis = next - grpc_exec_ctx_now(&exec_ctx); + GPR_ASSERT(timeout_millis >= expected_next_lower_bound); + GPR_ASSERT(timeout_millis <= expected_next_upper_bound); + + expected_next_lower_bound = + (int64_t)((double)timeout_millis * (1 - jitter)); + expected_next_upper_bound = + (int64_t)((double)timeout_millis * (1 + jitter)); + exec_ctx.now = next; + } + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + gpr_time_init(); + + test_constant_backoff(); + test_min_connect(); + test_no_jitter_backoff(); + test_jitter_backoff(); + + return 0; +} diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c deleted file mode 100644 index b7b28a9ac4..0000000000 --- a/test/core/bad_client/bad_client.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include -#include -#include -#include - -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/support/murmur_hash.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/completion_queue.h" -#include "src/core/lib/surface/server.h" - -typedef struct { - grpc_server *server; - grpc_completion_queue *cq; - grpc_bad_client_server_side_validator validator; - void *registered_method; - gpr_event done_thd; - gpr_event done_write; -} thd_args; - -static void thd_func(void *arg) { - thd_args *a = (thd_args *)arg; - a->validator(a->server, a->cq, a->registered_method); - gpr_event_set(&a->done_thd, (void *)1); -} - -static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - thd_args *a = (thd_args *)arg; - gpr_event_set(&a->done_write, (void *)1); -} - -static void server_setup_transport(void *ts, grpc_transport *transport) { - thd_args *a = (thd_args *)ts; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_server_setup_transport(&exec_ctx, a->server, transport, NULL, - grpc_server_get_channel_args(a->server)); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void read_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - gpr_event *read_done = (gpr_event *)arg; - gpr_event_set(read_done, (void *)1); -} - -void grpc_run_bad_client_test( - grpc_bad_client_server_side_validator server_validator, - grpc_bad_client_client_stream_validator client_validator, - const char *client_payload, size_t client_payload_length, uint32_t flags) { - grpc_endpoint_pair sfd; - thd_args a; - gpr_thd_id id; - char *hex; - grpc_transport *transport; - grpc_slice slice = - grpc_slice_from_copied_buffer(client_payload, client_payload_length); - grpc_slice_buffer outgoing; - grpc_closure done_write_closure; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_completion_queue *shutdown_cq; - - if (client_payload_length < 4 * 1024) { - hex = gpr_dump(client_payload, client_payload_length, - GPR_DUMP_HEX | GPR_DUMP_ASCII); - - /* Add a debug log */ - gpr_log(GPR_INFO, "TEST: %s", hex); - - gpr_free(hex); - } else { - gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)", - client_payload_length); - } - - /* Init grpc */ - grpc_init(); - - /* Create endpoints */ - sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); - - /* Create server, completion events */ - a.server = grpc_server_create(NULL, NULL); - a.cq = grpc_completion_queue_create_for_next(NULL); - gpr_event_init(&a.done_thd); - gpr_event_init(&a.done_write); - a.validator = server_validator; - grpc_server_register_completion_queue(a.server, a.cq, NULL); - a.registered_method = - grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD, - GRPC_BAD_CLIENT_REGISTERED_HOST, - GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0); - grpc_server_start(a.server); - 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); - grpc_exec_ctx_finish(&exec_ctx); - - /* Bind everything into the same pollset */ - grpc_endpoint_add_to_pollset(&exec_ctx, sfd.client, grpc_cq_pollset(a.cq)); - grpc_endpoint_add_to_pollset(&exec_ctx, sfd.server, grpc_cq_pollset(a.cq)); - - /* Check a ground truth */ - GPR_ASSERT(grpc_server_has_open_connections(a.server)); - - /* Start validator */ - gpr_thd_new(&id, thd_func, &a, NULL); - - grpc_slice_buffer_init(&outgoing); - grpc_slice_buffer_add(&outgoing, slice); - GRPC_CLOSURE_INIT(&done_write_closure, done_write, &a, - grpc_schedule_on_exec_ctx); - - /* Write data */ - grpc_endpoint_write(&exec_ctx, sfd.client, &outgoing, &done_write_closure); - grpc_exec_ctx_finish(&exec_ctx); - - /* Await completion, unless the request is large and write may not finish - * before the peer shuts down. */ - if (!(flags & GRPC_BAD_CLIENT_LARGE_REQUEST)) { - GPR_ASSERT( - gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(5))); - } - - if (flags & GRPC_BAD_CLIENT_DISCONNECT) { - grpc_endpoint_shutdown( - &exec_ctx, sfd.client, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Disconnect")); - grpc_endpoint_destroy(&exec_ctx, sfd.client); - grpc_exec_ctx_finish(&exec_ctx); - sfd.client = NULL; - } - - GPR_ASSERT(gpr_event_wait(&a.done_thd, grpc_timeout_seconds_to_deadline(5))); - - if (sfd.client != NULL) { - // Validate client stream, if requested. - if (client_validator != NULL) { - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - grpc_slice_buffer incoming; - grpc_slice_buffer_init(&incoming); - // We may need to do multiple reads to read the complete server response. - while (true) { - gpr_event read_done_event; - gpr_event_init(&read_done_event); - grpc_closure read_done_closure; - GRPC_CLOSURE_INIT(&read_done_closure, read_done, &read_done_event, - grpc_schedule_on_exec_ctx); - grpc_endpoint_read(&exec_ctx, sfd.client, &incoming, - &read_done_closure); - grpc_exec_ctx_finish(&exec_ctx); - do { - GPR_ASSERT(gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0); - GPR_ASSERT(grpc_completion_queue_next( - a.cq, grpc_timeout_milliseconds_to_deadline(100), NULL) - .type == GRPC_QUEUE_TIMEOUT); - } while (!gpr_event_get(&read_done_event)); - if (client_validator(&incoming)) break; - gpr_log(GPR_INFO, - "client validator failed; trying additional read " - "in case we didn't get all the data"); - } - grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); - } - // Shutdown. - grpc_endpoint_shutdown( - &exec_ctx, sfd.client, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - grpc_endpoint_destroy(&exec_ctx, sfd.client); - grpc_exec_ctx_finish(&exec_ctx); - } - - GPR_ASSERT( - gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(1))); - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server_shutdown_and_notify(a.server, shutdown_cq, NULL); - GPR_ASSERT(grpc_completion_queue_pluck( - shutdown_cq, NULL, grpc_timeout_seconds_to_deadline(1), NULL) - .type == GRPC_OP_COMPLETE); - grpc_completion_queue_destroy(shutdown_cq); - grpc_server_destroy(a.server); - grpc_completion_queue_destroy(a.cq); - grpc_slice_buffer_destroy_internal(&exec_ctx, &outgoing); - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} diff --git a/test/core/bad_client/bad_client.cc b/test/core/bad_client/bad_client.cc new file mode 100644 index 0000000000..b7b28a9ac4 --- /dev/null +++ b/test/core/bad_client/bad_client.cc @@ -0,0 +1,211 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include +#include +#include +#include + +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/murmur_hash.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" + +typedef struct { + grpc_server *server; + grpc_completion_queue *cq; + grpc_bad_client_server_side_validator validator; + void *registered_method; + gpr_event done_thd; + gpr_event done_write; +} thd_args; + +static void thd_func(void *arg) { + thd_args *a = (thd_args *)arg; + a->validator(a->server, a->cq, a->registered_method); + gpr_event_set(&a->done_thd, (void *)1); +} + +static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + thd_args *a = (thd_args *)arg; + gpr_event_set(&a->done_write, (void *)1); +} + +static void server_setup_transport(void *ts, grpc_transport *transport) { + thd_args *a = (thd_args *)ts; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_server_setup_transport(&exec_ctx, a->server, transport, NULL, + grpc_server_get_channel_args(a->server)); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void read_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + gpr_event *read_done = (gpr_event *)arg; + gpr_event_set(read_done, (void *)1); +} + +void grpc_run_bad_client_test( + grpc_bad_client_server_side_validator server_validator, + grpc_bad_client_client_stream_validator client_validator, + const char *client_payload, size_t client_payload_length, uint32_t flags) { + grpc_endpoint_pair sfd; + thd_args a; + gpr_thd_id id; + char *hex; + grpc_transport *transport; + grpc_slice slice = + grpc_slice_from_copied_buffer(client_payload, client_payload_length); + grpc_slice_buffer outgoing; + grpc_closure done_write_closure; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_completion_queue *shutdown_cq; + + if (client_payload_length < 4 * 1024) { + hex = gpr_dump(client_payload, client_payload_length, + GPR_DUMP_HEX | GPR_DUMP_ASCII); + + /* Add a debug log */ + gpr_log(GPR_INFO, "TEST: %s", hex); + + gpr_free(hex); + } else { + gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)", + client_payload_length); + } + + /* Init grpc */ + grpc_init(); + + /* Create endpoints */ + sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); + + /* Create server, completion events */ + a.server = grpc_server_create(NULL, NULL); + a.cq = grpc_completion_queue_create_for_next(NULL); + gpr_event_init(&a.done_thd); + gpr_event_init(&a.done_write); + a.validator = server_validator; + grpc_server_register_completion_queue(a.server, a.cq, NULL); + a.registered_method = + grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD, + GRPC_BAD_CLIENT_REGISTERED_HOST, + GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0); + grpc_server_start(a.server); + 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); + grpc_exec_ctx_finish(&exec_ctx); + + /* Bind everything into the same pollset */ + grpc_endpoint_add_to_pollset(&exec_ctx, sfd.client, grpc_cq_pollset(a.cq)); + grpc_endpoint_add_to_pollset(&exec_ctx, sfd.server, grpc_cq_pollset(a.cq)); + + /* Check a ground truth */ + GPR_ASSERT(grpc_server_has_open_connections(a.server)); + + /* Start validator */ + gpr_thd_new(&id, thd_func, &a, NULL); + + grpc_slice_buffer_init(&outgoing); + grpc_slice_buffer_add(&outgoing, slice); + GRPC_CLOSURE_INIT(&done_write_closure, done_write, &a, + grpc_schedule_on_exec_ctx); + + /* Write data */ + grpc_endpoint_write(&exec_ctx, sfd.client, &outgoing, &done_write_closure); + grpc_exec_ctx_finish(&exec_ctx); + + /* Await completion, unless the request is large and write may not finish + * before the peer shuts down. */ + if (!(flags & GRPC_BAD_CLIENT_LARGE_REQUEST)) { + GPR_ASSERT( + gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(5))); + } + + if (flags & GRPC_BAD_CLIENT_DISCONNECT) { + grpc_endpoint_shutdown( + &exec_ctx, sfd.client, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Disconnect")); + grpc_endpoint_destroy(&exec_ctx, sfd.client); + grpc_exec_ctx_finish(&exec_ctx); + sfd.client = NULL; + } + + GPR_ASSERT(gpr_event_wait(&a.done_thd, grpc_timeout_seconds_to_deadline(5))); + + if (sfd.client != NULL) { + // Validate client stream, if requested. + if (client_validator != NULL) { + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); + grpc_slice_buffer incoming; + grpc_slice_buffer_init(&incoming); + // We may need to do multiple reads to read the complete server response. + while (true) { + gpr_event read_done_event; + gpr_event_init(&read_done_event); + grpc_closure read_done_closure; + GRPC_CLOSURE_INIT(&read_done_closure, read_done, &read_done_event, + grpc_schedule_on_exec_ctx); + grpc_endpoint_read(&exec_ctx, sfd.client, &incoming, + &read_done_closure); + grpc_exec_ctx_finish(&exec_ctx); + do { + GPR_ASSERT(gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0); + GPR_ASSERT(grpc_completion_queue_next( + a.cq, grpc_timeout_milliseconds_to_deadline(100), NULL) + .type == GRPC_QUEUE_TIMEOUT); + } while (!gpr_event_get(&read_done_event)); + if (client_validator(&incoming)) break; + gpr_log(GPR_INFO, + "client validator failed; trying additional read " + "in case we didn't get all the data"); + } + grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); + } + // Shutdown. + grpc_endpoint_shutdown( + &exec_ctx, sfd.client, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + grpc_endpoint_destroy(&exec_ctx, sfd.client); + grpc_exec_ctx_finish(&exec_ctx); + } + + GPR_ASSERT( + gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(1))); + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server_shutdown_and_notify(a.server, shutdown_cq, NULL); + GPR_ASSERT(grpc_completion_queue_pluck( + shutdown_cq, NULL, grpc_timeout_seconds_to_deadline(1), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_destroy(shutdown_cq); + grpc_server_destroy(a.server); + grpc_completion_queue_destroy(a.cq); + grpc_slice_buffer_destroy_internal(&exec_ctx, &outgoing); + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py index 61cf1f7cd7..14c8a27334 100755 --- a/test/core/bad_client/gen_build_yaml.py +++ b/test/core/bad_client/gen_build_yaml.py @@ -46,7 +46,7 @@ def main(): 'build': 'private', 'language': 'c', 'src': [ - 'test/core/bad_client/bad_client.c' + 'test/core/bad_client/bad_client.cc' ], 'headers': [ 'test/core/bad_client/bad_client.h' @@ -66,7 +66,7 @@ def main(): 'build': 'test', 'language': 'c', 'secure': 'no', - 'src': ['test/core/bad_client/tests/%s.c' % t], + 'src': ['test/core/bad_client/tests/%s.cc' % t], 'vs_proj_dir': 'test', 'exclude_iomgrs': ['uv'], 'deps': [ diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl index 58b48d688f..cdea9cc2d1 100755 --- a/test/core/bad_client/generate_tests.bzl +++ b/test/core/bad_client/generate_tests.bzl @@ -38,7 +38,7 @@ BAD_CLIENT_TESTS = { def grpc_bad_client_tests(): native.cc_library( name = 'bad_client_test', - srcs = ['bad_client.c'], + srcs = ['bad_client.cc'], hdrs = ['bad_client.h'], copts = ['-std=c99'], deps = ['//test/core/util:grpc_test_util', '//:grpc', '//:gpr', '//test/core/end2end:cq_verifier'] @@ -46,7 +46,7 @@ def grpc_bad_client_tests(): for t, topt in BAD_CLIENT_TESTS.items(): native.cc_test( name = '%s_bad_client_test' % t, - srcs = ['tests/%s.c' % t], + srcs = ['tests/%s.cc' % t], deps = [':bad_client_test'], copts = ['-std=c99'], ) diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c deleted file mode 100644 index 7d9a103e43..0000000000 --- a/test/core/bad_client/tests/badreq.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" - -#define PFX_STR \ - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ - -static void verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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.cc b/test/core/bad_client/tests/badreq.cc new file mode 100644 index 0000000000..7d9a103e43 --- /dev/null +++ b/test/core/bad_client/tests/badreq.cc @@ -0,0 +1,125 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" + +#define PFX_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c deleted file mode 100644 index 6cc4b72314..0000000000 --- a/test/core/bad_client/tests/connection_prefix.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/server.h" -#include "test/core/bad_client/bad_client.h" - -static void verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_to_deadline(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRIX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI *X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTPX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0X", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSMX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\rX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\nX", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\n\rX", - 0); - return 0; -} diff --git a/test/core/bad_client/tests/connection_prefix.cc b/test/core/bad_client/tests/connection_prefix.cc new file mode 100644 index 0000000000..6cc4b72314 --- /dev/null +++ b/test/core/bad_client/tests/connection_prefix.cc @@ -0,0 +1,60 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/server.h" +#include "test/core/bad_client/bad_client.h" + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_to_deadline(20), NULL) + .type == GRPC_QUEUE_TIMEOUT); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRIX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI *X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTPX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0X", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSMX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\rX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\nX", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, "PRI * HTTP/2.0\r\n\r\nSM\r\n\rX", + 0); + return 0; +} diff --git a/test/core/bad_client/tests/head_of_line_blocking.c b/test/core/bad_client/tests/head_of_line_blocking.c deleted file mode 100644 index 04485d501f..0000000000 --- a/test/core/bad_client/tests/head_of_line_blocking.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include - -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" - -static const char prefix[] = - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" - // settings frame - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" - // stream 1 headers: generated from server_registered_method.headers in this - // directory - "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" - "\x10\x05:path\x0f/registered/bar" - "\x10\x07:scheme\x04http" - "\x10\x07:method\x04POST" - "\x10\x0a:authority\x09localhost" - "\x10\x0c" - "content-type\x10" - "application/grpc" - "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" - "\x10\x02te\x08trailers" - "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" - // data frame for stream 1: advertise a 10000 byte payload (that we won't - // fulfill) - "\x00\x00\x05\x00\x00\x00\x00\x00\x01" - "\x01\x00\x00\x27\x10" - // stream 3 headers: generated from server_registered_method.headers in this - // directory - "\x00\x00\xd0\x01\x04\x00\x00\x00\x03" - "\x10\x05:path\x0f/registered/bar" - "\x10\x07:scheme\x04http" - "\x10\x07:method\x04POST" - "\x10\x0a:authority\x09localhost" - "\x10\x0c" - "content-type\x10" - "application/grpc" - "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" - "\x10\x02te\x08trailers" - "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" - // data frame for stream 3: advertise a 10000 byte payload (that we will - // fulfill) - "\x00\x00\x05\x00\x00\x00\x00\x00\x03" - "\x01\x00\x00\x27\x10" - ""; - -static void *tag(intptr_t t) { return (void *)t; } - -static void verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - grpc_call_error error; - grpc_call *s; - cq_verifier *cqv = cq_verifier_create(cq); - grpc_metadata_array request_metadata_recv; - gpr_timespec deadline; - grpc_byte_buffer *payload = NULL; - - grpc_metadata_array_init(&request_metadata_recv); - - error = grpc_server_request_registered_call(server, registered_method, &s, - &deadline, &request_metadata_recv, - &payload, cq, cq, tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - GPR_ASSERT(payload != NULL); - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_unref(s); - grpc_byte_buffer_destroy(payload); - cq_verifier_destroy(cqv); -} - -char *g_buffer; -size_t g_cap = 0; -size_t g_count = 0; - -static void addbuf(const void *data, size_t len) { - if (g_count + len > g_cap) { - g_cap = GPR_MAX(g_count + len, g_cap * 2); - g_buffer = gpr_realloc(g_buffer, g_cap); - } - memcpy(g_buffer + g_count, data, len); - g_count += len; -} - -int main(int argc, char **argv) { - int i; - grpc_test_init(argc, argv); - -#define NUM_FRAMES 10 -#define FRAME_SIZE 1000 - - addbuf(prefix, sizeof(prefix) - 1); - for (i = 0; i < NUM_FRAMES; i++) { - uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16), - (uint8_t)(FRAME_SIZE >> 8), - (uint8_t)FRAME_SIZE, - 0, - 0, - 0, - 0, - 0, - 3}; - uint8_t msg[FRAME_SIZE]; - memset(msg, 'a', sizeof(msg)); - addbuf(hdr, sizeof(hdr)); - addbuf(msg, FRAME_SIZE); - } - grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, 0); - gpr_free(g_buffer); - - return 0; -} diff --git a/test/core/bad_client/tests/head_of_line_blocking.cc b/test/core/bad_client/tests/head_of_line_blocking.cc new file mode 100644 index 0000000000..cb89423907 --- /dev/null +++ b/test/core/bad_client/tests/head_of_line_blocking.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include + +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" + +static const char prefix[] = + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" + // settings frame + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" + // stream 1 headers: generated from server_registered_method.headers in this + // directory + "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" + "\x10\x05:path\x0f/registered/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + // data frame for stream 1: advertise a 10000 byte payload (that we won't + // fulfill) + "\x00\x00\x05\x00\x00\x00\x00\x00\x01" + "\x01\x00\x00\x27\x10" + // stream 3 headers: generated from server_registered_method.headers in this + // directory + "\x00\x00\xd0\x01\x04\x00\x00\x00\x03" + "\x10\x05:path\x0f/registered/bar" + "\x10\x07:scheme\x04http" + "\x10\x07:method\x04POST" + "\x10\x0a:authority\x09localhost" + "\x10\x0c" + "content-type\x10" + "application/grpc" + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" + "\x10\x02te\x08trailers" + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + // data frame for stream 3: advertise a 10000 byte payload (that we will + // fulfill) + "\x00\x00\x05\x00\x00\x00\x00\x00\x03" + "\x01\x00\x00\x27\x10" + ""; + +static void *tag(intptr_t t) { return (void *)t; } + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + gpr_timespec deadline; + grpc_byte_buffer *payload = NULL; + + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_registered_call(server, registered_method, &s, + &deadline, &request_metadata_recv, + &payload, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(payload != NULL); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_unref(s); + grpc_byte_buffer_destroy(payload); + cq_verifier_destroy(cqv); +} + +char *g_buffer; +size_t g_cap = 0; +size_t g_count = 0; + +static void addbuf(const void *data, size_t len) { + if (g_count + len > g_cap) { + g_cap = GPR_MAX(g_count + len, g_cap * 2); + g_buffer = static_cast(gpr_realloc(g_buffer, g_cap)); + } + memcpy(g_buffer + g_count, data, len); + g_count += len; +} + +int main(int argc, char **argv) { + int i; + grpc_test_init(argc, argv); + +#define NUM_FRAMES 10 +#define FRAME_SIZE 1000 + + addbuf(prefix, sizeof(prefix) - 1); + for (i = 0; i < NUM_FRAMES; i++) { + uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16), + (uint8_t)(FRAME_SIZE >> 8), + (uint8_t)FRAME_SIZE, + 0, + 0, + 0, + 0, + 0, + 3}; + uint8_t msg[FRAME_SIZE]; + memset(msg, 'a', sizeof(msg)); + addbuf(hdr, sizeof(hdr)); + addbuf(msg, FRAME_SIZE); + } + grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, 0); + gpr_free(g_buffer); + + return 0; +} diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c deleted file mode 100644 index c704dbbcb6..0000000000 --- a/test/core/bad_client/tests/headers.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/server.h" -#include "test/core/bad_client/bad_client.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, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_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, NULL, PFX_STR "\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x05", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x01\x04\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - 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, NULL, PFX_STR - "\x00\x00\x01\x01\x24\x00\x00\x00\x01" - "\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x02\x01\x24\x00\x00\x00\x01" - "\x00\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x03\x01\x24\x00\x00\x00\x01" - "\x00\x00\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x04\x01\x24\x00\x00\x00\x01" - "\x00\x00\x00\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x05\x01\x24\x00\x00\x00\x01" - "", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x05\x01\x24\x00\x00\x00\x01" - "\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x05\x01\x24\x00\x00\x00\x01" - "\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x05\x01\x24\x00\x00\x00\x01" - "\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, 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, NULL, PFX_STR - "\x00\x00\x01\x01\x04\x00\x00\x00\x01" - "\xfe", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\x7f\x7f\x01" - "a", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\x0f\x7f\x01" - "a", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR - "\x00\x00\x03\x01\x04\x00\x00\x00\x01" - "\x01\x01" - "a", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR - "\x00\x00\x01\x01\x04\x00\x00\x00\x01" - "\x80", - 0); - /* parse some long indices */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x02\x01\x04\x00\x00\x00\x01" - "\xff\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x03\x01\x04\x00\x00\x00\x01" - "\xff\x80\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x04\x01\x04\x00\x00\x00\x01" - "\xff\x80\x80\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x05\x01\x04\x00\x00\x00\x01" - "\xff\x80\x80\x80\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x06\x01\x04\x00\x00\x00\x01" - "\xff\x80\x80\x80\x80\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR - "\x00\x00\x08\x01\x04\x00\x00\x00\x01" - "\xff", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x08\x01\x04\x00\x00\x00\x01" - "\xff\x80", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR - "\x00\x00\x08\x01\x04\x00\x00\x00\x01" - "\xff\x80\x80", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, - PFX_STR "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); - /* three header frames */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, - 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, NULL, 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, NULL, 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/headers.cc b/test/core/bad_client/tests/headers.cc new file mode 100644 index 0000000000..c704dbbcb6 --- /dev/null +++ b/test/core/bad_client/tests/headers.cc @@ -0,0 +1,293 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/server.h" +#include "test/core/bad_client/bad_client.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, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_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, NULL, PFX_STR "\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x05", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x01\x04\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x01\x04\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + 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, NULL, PFX_STR + "\x00\x00\x01\x01\x24\x00\x00\x00\x01" + "\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x02\x01\x24\x00\x00\x00\x01" + "\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x03\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x04\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x05\x01\x24\x00\x00\x00\x01" + "\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, 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, NULL, PFX_STR + "\x00\x00\x01\x01\x04\x00\x00\x00\x01" + "\xfe", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\x7f\x7f\x01" + "a", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\x0f\x7f\x01" + "a", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\x01\x01" + "a", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR + "\x00\x00\x01\x01\x04\x00\x00\x00\x01" + "\x80", + 0); + /* parse some long indices */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x02\x01\x04\x00\x00\x00\x01" + "\xff\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x03\x01\x04\x00\x00\x00\x01" + "\xff\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x04\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x05\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x06\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80\x80\x80\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR + "\x00\x00\x08\x01\x04\x00\x00\x00\x01" + "\xff\x80\x80", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, + PFX_STR "\x00\x00\x00\x09\x04\x00\x00\x00\x01", 0); + /* three header frames */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, + 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, NULL, 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, NULL, 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 deleted file mode 100644 index 0696ef9383..0000000000 --- a/test/core/bad_client/tests/initial_settings_frame.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/server.h" -#include "test/core/bad_client/bad_client.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, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_to_deadline(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - /* various partial prefixes */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x06", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x06", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x01", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\xff", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x04\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - /* must not send frames with stream id != 0 */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00\x01", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x00\x04\x00\x40\x00\x00\x00", 0); - /* settings frame must be a multiple of six bytes long */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x01\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x02\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x03\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - PFX_STR "\x00\x00\x04\x04\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - 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, NULL, - PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - 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, NULL, - PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - /* ack with data */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, - PFX_STR "\x00\x00\x00\x04\x10\x00\x00\x00\x00", 0); - /* unknown settings should be ignored */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, - 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/initial_settings_frame.cc b/test/core/bad_client/tests/initial_settings_frame.cc new file mode 100644 index 0000000000..0696ef9383 --- /dev/null +++ b/test/core/bad_client/tests/initial_settings_frame.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/server.h" +#include "test/core/bad_client/bad_client.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, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_to_deadline(20), NULL) + .type == GRPC_QUEUE_TIMEOUT); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + /* various partial prefixes */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x06", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x06", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x06", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\xff", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR "\x00\x00\x00\x04\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + /* must not send frames with stream id != 0 */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x00\x00\x00\x01", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x00\x04\x00\x40\x00\x00\x00", 0); + /* settings frame must be a multiple of six bytes long */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x01\x04\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x02\x04\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x03\x04\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + PFX_STR "\x00\x00\x04\x04\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + 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, NULL, + PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + 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, NULL, + PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + /* ack with data */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, + PFX_STR "\x00\x00\x00\x04\x10\x00\x00\x00\x00", 0); + /* unknown settings should be ignored */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, + 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/large_metadata.c b/test/core/bad_client/tests/large_metadata.c deleted file mode 100644 index ca3d234be9..0000000000 --- a/test/core/bad_client/tests/large_metadata.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include -#include -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" - -// The large-metadata headers that we're adding for this test are not -// actually appended to this in a single string, since the string would -// be longer than the C99 string literal limit. Instead, we dynamically -// construct it by adding the large headers one at a time. - -#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR \ - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame */ \ - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* headers: generated from \ - large_metadata.headers in this \ - directory */ \ - "\x00\x00\x00\x04\x01\x00\x00\x00\x00" \ - "\x00" \ - "5{\x01\x05\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\x08trailers" \ - "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" - -// Each large-metadata header is constructed from these start and end -// strings, with a two-digit number in between. -#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR "\x10\x0duser-header" -#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR \ - "~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - -// The size of each large-metadata header string. -#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_SIZE \ - ((sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR) - 1) + 2 + \ - (sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR) - 1)) - -// The number of headers we're adding and the total size of the client -// payload. -#define NUM_HEADERS 46 -#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_PAYLOAD_SIZE \ - ((sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR) - 1) + \ - (NUM_HEADERS * PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_SIZE) + 1) - -#define PFX_TOO_MUCH_METADATA_FROM_SERVER_STR \ - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame: sets \ - MAX_HEADER_LIST_SIZE to 8K */ \ - "\x00\x00\x06\x04\x00\x00\x00\x00\x00\x00\x06\x00\x00\x20\x00" /* headers: \ - generated \ - from \ - simple_request.headers \ - in this \ - directory \ - */ \ - "\x00\x00\x00\x04\x01\x00\x00\x00\x00" \ - "\x00\x00\xc9\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\x15" \ - "deflate,identity,gzip" \ - "\x10\x02te\x08trailers" \ - "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" - -static void *tag(intptr_t t) { return (void *)t; } - -static void server_verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - 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 == grpc_slice_str_cmp(call_details.host, "localhost")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(s); - cq_verifier_destroy(cqv); -} - -static void server_verifier_sends_too_much_metadata(grpc_server *server, - grpc_completion_queue *cq, - void *registered_method) { - 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 == grpc_slice_str_cmp(call_details.host, "localhost")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); - - const size_t metadata_value_size = 8 * 1024; - grpc_metadata meta; - meta.key = grpc_slice_from_static_string("key"); - meta.value = grpc_slice_malloc(metadata_value_size); - memset(GRPC_SLICE_START_PTR(meta.value), 'a', metadata_value_size); - - grpc_op op; - memset(&op, 0, sizeof(op)); - op.op = GRPC_OP_SEND_INITIAL_METADATA; - op.data.send_initial_metadata.count = 1; - op.data.send_initial_metadata.metadata = &meta; - op.flags = 0; - op.reserved = NULL; - error = grpc_call_start_batch(s, &op, 1, tag(102), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(102), 0); // Operation fails. - cq_verify(cqv); - - grpc_slice_unref(meta.value); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(s); - cq_verifier_destroy(cqv); -} - -static bool client_validator(grpc_slice_buffer *incoming) { - for (size_t i = 0; i < incoming->count; ++i) { - const char *s = (const char *)GRPC_SLICE_START_PTR(incoming->slices[i]); - char *hex = gpr_dump(s, GRPC_SLICE_LENGTH(incoming->slices[i]), - GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_INFO, "RESPONSE SLICE %" PRIdPTR ": %s", i, hex); - gpr_free(hex); - } - - // Get last frame from incoming slice buffer. - grpc_slice_buffer last_frame_buffer; - grpc_slice_buffer_init(&last_frame_buffer); - grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer); - GPR_ASSERT(last_frame_buffer.count == 1); - grpc_slice last_frame = last_frame_buffer.slices[0]; - - const uint8_t *p = GRPC_SLICE_START_PTR(last_frame); - bool success = - // Length == 4 - *p++ != 0 || *p++ != 0 || *p++ != 4 || - // Frame type (RST_STREAM) - *p++ != 3 || - // Flags - *p++ != 0 || - // Stream ID. - *p++ != 0 || *p++ != 0 || *p++ != 0 || *p++ != 1 || - // Payload (error code) - *p++ == 0 || *p++ == 0 || *p++ == 0 || *p == 0 || *p == 11; - - if (!success) { - gpr_log(GPR_INFO, "client expected RST_STREAM frame, not found"); - } - - grpc_slice_buffer_destroy(&last_frame_buffer); - return success; -} - -int main(int argc, char **argv) { - int i; - - grpc_test_init(argc, argv); - - // Test sending more metadata than the server will accept. - gpr_strvec headers; - gpr_strvec_init(&headers); - for (i = 0; i < NUM_HEADERS; ++i) { - char *str; - gpr_asprintf(&str, "%s%02d%s", - PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i, - PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR); - gpr_strvec_add(&headers, str); - } - size_t headers_len; - const char *client_headers = gpr_strvec_flatten(&headers, &headers_len); - gpr_strvec_destroy(&headers); - char client_payload[PFX_TOO_MUCH_METADATA_FROM_CLIENT_PAYLOAD_SIZE] = - PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR; - memcpy( - client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR) - 1, - client_headers, headers_len); - GRPC_RUN_BAD_CLIENT_TEST(server_verifier, client_validator, client_payload, - 0); - gpr_free((void *)client_headers); - - // Test sending more metadata than the client will accept. - GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata, - client_validator, - PFX_TOO_MUCH_METADATA_FROM_SERVER_STR, 0); - - return 0; -} diff --git a/test/core/bad_client/tests/large_metadata.cc b/test/core/bad_client/tests/large_metadata.cc new file mode 100644 index 0000000000..ca3d234be9 --- /dev/null +++ b/test/core/bad_client/tests/large_metadata.cc @@ -0,0 +1,240 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include +#include +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" + +// The large-metadata headers that we're adding for this test are not +// actually appended to this in a single string, since the string would +// be longer than the C99 string literal limit. Instead, we dynamically +// construct it by adding the large headers one at a time. + +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame */ \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* headers: generated from \ + large_metadata.headers in this \ + directory */ \ + "\x00\x00\x00\x04\x01\x00\x00\x00\x00" \ + "\x00" \ + "5{\x01\x05\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\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +// Each large-metadata header is constructed from these start and end +// strings, with a two-digit number in between. +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR "\x10\x0duser-header" +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR \ + "~aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +// The size of each large-metadata header string. +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_SIZE \ + ((sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR) - 1) + 2 + \ + (sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR) - 1)) + +// The number of headers we're adding and the total size of the client +// payload. +#define NUM_HEADERS 46 +#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_PAYLOAD_SIZE \ + ((sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR) - 1) + \ + (NUM_HEADERS * PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_SIZE) + 1) + +#define PFX_TOO_MUCH_METADATA_FROM_SERVER_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* settings frame: sets \ + MAX_HEADER_LIST_SIZE to 8K */ \ + "\x00\x00\x06\x04\x00\x00\x00\x00\x00\x00\x06\x00\x00\x20\x00" /* headers: \ + generated \ + from \ + simple_request.headers \ + in this \ + directory \ + */ \ + "\x00\x00\x00\x04\x01\x00\x00\x00\x00" \ + "\x00\x00\xc9\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\x15" \ + "deflate,identity,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +static void *tag(intptr_t t) { return (void *)t; } + +static void server_verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + 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 == grpc_slice_str_cmp(call_details.host, "localhost")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_unref(s); + cq_verifier_destroy(cqv); +} + +static void server_verifier_sends_too_much_metadata(grpc_server *server, + grpc_completion_queue *cq, + void *registered_method) { + 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 == grpc_slice_str_cmp(call_details.host, "localhost")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); + + const size_t metadata_value_size = 8 * 1024; + grpc_metadata meta; + meta.key = grpc_slice_from_static_string("key"); + meta.value = grpc_slice_malloc(metadata_value_size); + memset(GRPC_SLICE_START_PTR(meta.value), 'a', metadata_value_size); + + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_INITIAL_METADATA; + op.data.send_initial_metadata.count = 1; + op.data.send_initial_metadata.metadata = &meta; + op.flags = 0; + op.reserved = NULL; + error = grpc_call_start_batch(s, &op, 1, tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(102), 0); // Operation fails. + cq_verify(cqv); + + grpc_slice_unref(meta.value); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_unref(s); + cq_verifier_destroy(cqv); +} + +static bool client_validator(grpc_slice_buffer *incoming) { + for (size_t i = 0; i < incoming->count; ++i) { + const char *s = (const char *)GRPC_SLICE_START_PTR(incoming->slices[i]); + char *hex = gpr_dump(s, GRPC_SLICE_LENGTH(incoming->slices[i]), + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_INFO, "RESPONSE SLICE %" PRIdPTR ": %s", i, hex); + gpr_free(hex); + } + + // Get last frame from incoming slice buffer. + grpc_slice_buffer last_frame_buffer; + grpc_slice_buffer_init(&last_frame_buffer); + grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer); + GPR_ASSERT(last_frame_buffer.count == 1); + grpc_slice last_frame = last_frame_buffer.slices[0]; + + const uint8_t *p = GRPC_SLICE_START_PTR(last_frame); + bool success = + // Length == 4 + *p++ != 0 || *p++ != 0 || *p++ != 4 || + // Frame type (RST_STREAM) + *p++ != 3 || + // Flags + *p++ != 0 || + // Stream ID. + *p++ != 0 || *p++ != 0 || *p++ != 0 || *p++ != 1 || + // Payload (error code) + *p++ == 0 || *p++ == 0 || *p++ == 0 || *p == 0 || *p == 11; + + if (!success) { + gpr_log(GPR_INFO, "client expected RST_STREAM frame, not found"); + } + + grpc_slice_buffer_destroy(&last_frame_buffer); + return success; +} + +int main(int argc, char **argv) { + int i; + + grpc_test_init(argc, argv); + + // Test sending more metadata than the server will accept. + gpr_strvec headers; + gpr_strvec_init(&headers); + for (i = 0; i < NUM_HEADERS; ++i) { + char *str; + gpr_asprintf(&str, "%s%02d%s", + PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i, + PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR); + gpr_strvec_add(&headers, str); + } + size_t headers_len; + const char *client_headers = gpr_strvec_flatten(&headers, &headers_len); + gpr_strvec_destroy(&headers); + char client_payload[PFX_TOO_MUCH_METADATA_FROM_CLIENT_PAYLOAD_SIZE] = + PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR; + memcpy( + client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_PREFIX_STR) - 1, + client_headers, headers_len); + GRPC_RUN_BAD_CLIENT_TEST(server_verifier, client_validator, client_payload, + 0); + gpr_free((void *)client_headers); + + // Test sending more metadata than the client will accept. + GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata, + client_validator, + PFX_TOO_MUCH_METADATA_FROM_SERVER_STR, 0); + + return 0; +} diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c deleted file mode 100644 index f52350302b..0000000000 --- a/test/core/bad_client/tests/server_registered_method.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" - -#define PFX_STR \ - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \ - "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" \ - "\x10\x05:path\x0f/registered/bar" \ - "\x10\x07:scheme\x04http" \ - "\x10\x07:method\x04POST" \ - "\x10\x0a:authority\x09localhost" \ - "\x10\x0c" \ - "content-type\x10" \ - "application/grpc" \ - "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \ - "\x10\x02te\x08trailers" \ - "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" - -static void *tag(intptr_t t) { return (void *)t; } - -static void verifier_succeeds(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - grpc_call_error error; - grpc_call *s; - cq_verifier *cqv = cq_verifier_create(cq); - grpc_metadata_array request_metadata_recv; - gpr_timespec deadline; - grpc_byte_buffer *payload = NULL; - - grpc_metadata_array_init(&request_metadata_recv); - - error = grpc_server_request_registered_call(server, registered_method, &s, - &deadline, &request_metadata_recv, - &payload, cq, cq, tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - GPR_ASSERT(payload != NULL); - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_unref(s); - grpc_byte_buffer_destroy(payload); - cq_verifier_destroy(cqv); -} - -static void verifier_fails(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_to_deadline(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - /* body generated with - * tools/codegen/core/gen_server_registered_method_bad_client_test_body.py */ - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, - PFX_STR "\x00\x00\x00\x00\x00\x00\x00\x00\x01", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, - PFX_STR "\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR - "\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR - "\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, NULL, - PFX_STR "\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, NULL, - PFX_STR "\x00\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00", 0); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, NULL, - PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, NULL, - PFX_STR "\x00\x00\x06\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00", - 0); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, NULL, - PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_fails, NULL, - PFX_STR "\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00", - GRPC_BAD_CLIENT_DISCONNECT); - GRPC_RUN_BAD_CLIENT_TEST( - verifier_succeeds, NULL, PFX_STR - "\x00\x00\x07\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\x00", - 0); - - return 0; -} diff --git a/test/core/bad_client/tests/server_registered_method.cc b/test/core/bad_client/tests/server_registered_method.cc new file mode 100644 index 0000000000..f52350302b --- /dev/null +++ b/test/core/bad_client/tests/server_registered_method.cc @@ -0,0 +1,124 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" + +#define PFX_STR \ + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \ + "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" \ + "\x10\x05:path\x0f/registered/bar" \ + "\x10\x07:scheme\x04http" \ + "\x10\x07:method\x04POST" \ + "\x10\x0a:authority\x09localhost" \ + "\x10\x0c" \ + "content-type\x10" \ + "application/grpc" \ + "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \ + "\x10\x02te\x08trailers" \ + "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" + +static void *tag(intptr_t t) { return (void *)t; } + +static void verifier_succeeds(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + cq_verifier *cqv = cq_verifier_create(cq); + grpc_metadata_array request_metadata_recv; + gpr_timespec deadline; + grpc_byte_buffer *payload = NULL; + + grpc_metadata_array_init(&request_metadata_recv); + + error = grpc_server_request_registered_call(server, registered_method, &s, + &deadline, &request_metadata_recv, + &payload, cq, cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + GPR_ASSERT(payload != NULL); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_unref(s); + grpc_byte_buffer_destroy(payload); + cq_verifier_destroy(cqv); +} + +static void verifier_fails(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_to_deadline(20), NULL) + .type == GRPC_QUEUE_TIMEOUT); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + /* body generated with + * tools/codegen/core/gen_server_registered_method_bad_client_test_body.py */ + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, + PFX_STR "\x00\x00\x00\x00\x00\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, + PFX_STR "\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR + "\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, NULL, PFX_STR + "\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, NULL, + PFX_STR "\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, NULL, + PFX_STR "\x00\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00", 0); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, NULL, + PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, NULL, + PFX_STR "\x00\x00\x06\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00", + 0); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, NULL, + PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_fails, NULL, + PFX_STR "\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00", + GRPC_BAD_CLIENT_DISCONNECT); + GRPC_RUN_BAD_CLIENT_TEST( + verifier_succeeds, NULL, PFX_STR + "\x00\x00\x07\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\x00", + 0); + + return 0; +} diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c deleted file mode 100644 index a516632819..0000000000 --- a/test/core/bad_client/tests/simple_request.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.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" - -#define PFX_STR_UNUSUAL2 \ - "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_unusual2.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(intptr_t t) { return (void *)t; } - -static void verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - grpc_call_error error; - grpc_call *s; - grpc_call_details call_details; - 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 == grpc_slice_str_cmp(call_details.host, "localhost")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(s); - cq_verifier_destroy(cqv); -} - -static void failure_verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_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, NULL, PFX_STR, 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL, 0); - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL2, 0); - - /* push an illegal data frame */ - GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, - 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, NULL, - 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, NULL, - 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, NULL, 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, NULL, - PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0); - /* disconnect before sending goaway */ - GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, - 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, NULL, - 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, NULL, - PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0); - - return 0; -} diff --git a/test/core/bad_client/tests/simple_request.cc b/test/core/bad_client/tests/simple_request.cc new file mode 100644 index 0000000000..a516632819 --- /dev/null +++ b/test/core/bad_client/tests/simple_request.cc @@ -0,0 +1,166 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.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" + +#define PFX_STR_UNUSUAL2 \ + "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_unusual2.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(intptr_t t) { return (void *)t; } + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + grpc_call_error error; + grpc_call *s; + grpc_call_details call_details; + 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 == grpc_slice_str_cmp(call_details.host, "localhost")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar")); + + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_unref(s); + cq_verifier_destroy(cqv); +} + +static void failure_verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_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, NULL, PFX_STR, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL, 0); + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, PFX_STR_UNUSUAL2, 0); + + /* push an illegal data frame */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, NULL, 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, NULL, + 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, NULL, + 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, NULL, + 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, NULL, 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, NULL, + PFX_STR "\x00\x00\x04\x07\x00\x00\x00\x00\x00", 0); + /* disconnect before sending goaway */ + GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, NULL, + 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, NULL, + 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, NULL, + PFX_STR "\x00\x00\x00\x03\x10\x00\x00\x00\x01", 0); + + return 0; +} diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c deleted file mode 100644 index 448803d12b..0000000000 --- a/test/core/bad_client/tests/unknown_frame.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/server.h" -#include "test/core/bad_client/bad_client.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, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_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, NULL, - PFX_STR "\x00\x00\x00\x88\x00\x00\x00\x00\x01", - GRPC_BAD_CLIENT_DISCONNECT); - - return 0; -} diff --git a/test/core/bad_client/tests/unknown_frame.cc b/test/core/bad_client/tests/unknown_frame.cc new file mode 100644 index 0000000000..448803d12b --- /dev/null +++ b/test/core/bad_client/tests/unknown_frame.cc @@ -0,0 +1,44 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/server.h" +#include "test/core/bad_client/bad_client.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, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_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, NULL, + PFX_STR "\x00\x00\x00\x88\x00\x00\x00\x00\x01", + GRPC_BAD_CLIENT_DISCONNECT); + + return 0; +} diff --git a/test/core/bad_client/tests/window_overflow.c b/test/core/bad_client/tests/window_overflow.c deleted file mode 100644 index e4b5f9711b..0000000000 --- a/test/core/bad_client/tests/window_overflow.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/bad_client/bad_client.h" - -#include - -#include - -#include "src/core/lib/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)" - -static void verifier(grpc_server *server, grpc_completion_queue *cq, - void *registered_method) { - while (grpc_server_has_open_connections(server)) { - GPR_ASSERT(grpc_completion_queue_next( - cq, grpc_timeout_milliseconds_to_deadline(20), NULL) - .type == GRPC_QUEUE_TIMEOUT); - } -} - -char *g_buffer; -size_t g_cap = 0; -size_t g_count = 0; - -static void addbuf(const void *data, size_t len) { - if (g_count + len > g_cap) { - g_cap = GPR_MAX(g_count + len, g_cap * 2); - g_buffer = gpr_realloc(g_buffer, g_cap); - } - memcpy(g_buffer + g_count, data, len); - g_count += len; -} - -int main(int argc, char **argv) { - int i, j; -#define MAX_FRAME_SIZE 16384 -#define MESSAGES_PER_FRAME (MAX_FRAME_SIZE / 5) -#define FRAME_SIZE (MESSAGES_PER_FRAME * 5) -#define SEND_SIZE (6 * 1024 * 1024) -#define NUM_FRAMES (SEND_SIZE / FRAME_SIZE + 1) - grpc_test_init(argc, argv); - - addbuf(PFX_STR, sizeof(PFX_STR) - 1); - for (i = 0; i < NUM_FRAMES; i++) { - uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16), - (uint8_t)(FRAME_SIZE >> 8), - (uint8_t)FRAME_SIZE, - 0, - 0, - 0, - 0, - 0, - 1}; - addbuf(hdr, sizeof(hdr)); - for (j = 0; j < MESSAGES_PER_FRAME; j++) { - uint8_t message[5] = {0, 0, 0, 0, 0}; - addbuf(message, sizeof(message)); - } - } - grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, - GRPC_BAD_CLIENT_LARGE_REQUEST); - gpr_free(g_buffer); - - return 0; -} diff --git a/test/core/bad_client/tests/window_overflow.cc b/test/core/bad_client/tests/window_overflow.cc new file mode 100644 index 0000000000..40552e5345 --- /dev/null +++ b/test/core/bad_client/tests/window_overflow.cc @@ -0,0 +1,98 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/bad_client/bad_client.h" + +#include + +#include + +#include "src/core/lib/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)" + +static void verifier(grpc_server *server, grpc_completion_queue *cq, + void *registered_method) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, grpc_timeout_milliseconds_to_deadline(20), NULL) + .type == GRPC_QUEUE_TIMEOUT); + } +} + +char *g_buffer; +size_t g_cap = 0; +size_t g_count = 0; + +static void addbuf(const void *data, size_t len) { + if (g_count + len > g_cap) { + g_cap = GPR_MAX(g_count + len, g_cap * 2); + g_buffer = static_cast(gpr_realloc(g_buffer, g_cap)); + } + memcpy(g_buffer + g_count, data, len); + g_count += len; +} + +int main(int argc, char **argv) { + int i, j; +#define MAX_FRAME_SIZE 16384 +#define MESSAGES_PER_FRAME (MAX_FRAME_SIZE / 5) +#define FRAME_SIZE (MESSAGES_PER_FRAME * 5) +#define SEND_SIZE (6 * 1024 * 1024) +#define NUM_FRAMES (SEND_SIZE / FRAME_SIZE + 1) + grpc_test_init(argc, argv); + + addbuf(PFX_STR, sizeof(PFX_STR) - 1); + for (i = 0; i < NUM_FRAMES; i++) { + uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16), + (uint8_t)(FRAME_SIZE >> 8), + (uint8_t)FRAME_SIZE, + 0, + 0, + 0, + 0, + 0, + 1}; + addbuf(hdr, sizeof(hdr)); + for (j = 0; j < MESSAGES_PER_FRAME; j++) { + uint8_t message[5] = {0, 0, 0, 0, 0}; + addbuf(message, sizeof(message)); + } + } + grpc_run_bad_client_test(verifier, NULL, g_buffer, g_count, + GRPC_BAD_CLIENT_LARGE_REQUEST); + gpr_free(g_buffer); + + return 0; +} diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c deleted file mode 100644 index 793627bcdc..0000000000 --- a/test/core/bad_ssl/bad_ssl_test.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static void *tag(intptr_t 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; - grpc_slice details; - 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_for_next(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); - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234"); - c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/foo"), &host, - deadline, NULL); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - 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->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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_unref(c); - grpc_slice_unref(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, "."); - } - if (argc == 2) { - gpr_setenv("GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", argv[1]); - } - /* 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/bad_ssl_test.cc b/test/core/bad_ssl/bad_ssl_test.cc new file mode 100644 index 0000000000..2183fbb633 --- /dev/null +++ b/test/core/bad_ssl/bad_ssl_test.cc @@ -0,0 +1,161 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void *tag(intptr_t 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; + grpc_slice details; + 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_for_next(NULL); + cq_verifier *cqv = cq_verifier_create(cq); + + grpc_op ops[6]; + grpc_op *op; + + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("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); + grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234"); + c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/foo"), &host, + deadline, NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + 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->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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_unref(c); + grpc_slice_unref(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, "."); + } + if (argc == 2) { + gpr_setenv("GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", argv[1]); + } + /* 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] = const_cast("--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 index 30fdb5ea02..6b78e9c7aa 100755 --- a/test/core/bad_ssl/gen_build_yaml.py +++ b/test/core/bad_ssl/gen_build_yaml.py @@ -38,7 +38,7 @@ def main(): 'name': 'bad_ssl_test_server', 'build': 'private', 'language': 'c', - 'src': ['test/core/bad_ssl/server_common.c'], + 'src': ['test/core/bad_ssl/server_common.cc'], 'headers': ['test/core/bad_ssl/server_common.h'], 'vs_proj_dir': 'test', 'platforms': ['linux', 'posix', 'mac'], @@ -56,7 +56,7 @@ def main(): 'build': 'test', 'language': 'c', 'run': False, - 'src': ['test/core/bad_ssl/servers/%s.c' % t], + 'src': ['test/core/bad_ssl/servers/%s.cc' % t], 'vs_proj_dir': 'test/bad_ssl', 'platforms': ['linux', 'posix', 'mac'], 'deps': [ @@ -73,7 +73,7 @@ def main(): 'cpu_cost': BAD_CLIENT_TESTS[t].cpu_cost, 'build': 'test', 'language': 'c', - 'src': ['test/core/bad_ssl/bad_ssl_test.c'], + 'src': ['test/core/bad_ssl/bad_ssl_test.cc'], 'vs_proj_dir': 'test', 'platforms': ['linux', 'posix', 'mac'], 'deps': [ diff --git a/test/core/bad_ssl/generate_tests.bzl b/test/core/bad_ssl/generate_tests.bzl index b61fabc051..b7cb8f86e6 100755 --- a/test/core/bad_ssl/generate_tests.bzl +++ b/test/core/bad_ssl/generate_tests.bzl @@ -24,14 +24,14 @@ BAD_SSL_TESTS = ['cert', 'alpn'] def grpc_bad_ssl_tests(): native.cc_library( name = 'bad_ssl_test_server', - srcs = ['server_common.c'], + srcs = ['server_common.cc'], hdrs = ['server_common.h'], deps = ['//test/core/util:grpc_test_util', '//:grpc', '//test/core/end2end:ssl_test_data'] ) for t in BAD_SSL_TESTS: native.cc_test( name = 'bad_ssl_%s_server' % t, - srcs = ['servers/%s.c' % t], + srcs = ['servers/%s.cc' % t], deps = [':bad_ssl_test_server'], ) diff --git a/test/core/bad_ssl/server_common.c b/test/core/bad_ssl/server_common.c deleted file mode 100644 index 0588d43c38..0000000000 --- a/test/core/bad_ssl/server_common.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include "test/core/bad_ssl/server_common.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_for_next(NULL); - grpc_completion_queue *shutdown_cq; - - 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"); - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server_shutdown_and_notify(server, shutdown_cq, NULL); - GPR_ASSERT( - grpc_completion_queue_pluck(shutdown_cq, NULL, - grpc_timeout_seconds_to_deadline(5), NULL) - .type == GRPC_OP_COMPLETE); - grpc_completion_queue_destroy(shutdown_cq); - 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_common.cc b/test/core/bad_ssl/server_common.cc new file mode 100644 index 0000000000..5def618257 --- /dev/null +++ b/test/core/bad_ssl/server_common.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "test/core/bad_ssl/server_common.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; + const 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_for_next(NULL); + grpc_completion_queue *shutdown_cq; + + 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"); + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server_shutdown_and_notify(server, shutdown_cq, NULL); + GPR_ASSERT( + grpc_completion_queue_pluck(shutdown_cq, NULL, + grpc_timeout_seconds_to_deadline(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_destroy(shutdown_cq); + 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/servers/alpn.c b/test/core/bad_ssl/servers/alpn.c deleted file mode 100644 index 3179054aff..0000000000 --- a/test/core/bad_ssl/servers/alpn.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include - -#include "src/core/ext/transport/chttp2/alpn/alpn.h" -#include "test/core/bad_ssl/server_common.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/alpn.cc b/test/core/bad_ssl/servers/alpn.cc new file mode 100644 index 0000000000..3179054aff --- /dev/null +++ b/test/core/bad_ssl/servers/alpn.cc @@ -0,0 +1,71 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "test/core/bad_ssl/server_common.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 deleted file mode 100644 index a1f3048164..0000000000 --- a/test/core/bad_ssl/servers/cert.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/load_file.h" - -#include "test/core/bad_ssl/server_common.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; - grpc_slice cert_slice, key_slice; - - grpc_init(); - - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", - grpc_load_file("src/core/tsi/test_creds/badserver.pem", 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", - grpc_load_file("src/core/tsi/test_creds/badserver.key", 1, &key_slice))); - pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char *)GRPC_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); - - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - - bad_ssl_run(server); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/bad_ssl/servers/cert.cc b/test/core/bad_ssl/servers/cert.cc new file mode 100644 index 0000000000..a1f3048164 --- /dev/null +++ b/test/core/bad_ssl/servers/cert.cc @@ -0,0 +1,65 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/load_file.h" + +#include "test/core/bad_ssl/server_common.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; + grpc_slice cert_slice, key_slice; + + grpc_init(); + + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", + grpc_load_file("src/core/tsi/test_creds/badserver.pem", 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", + grpc_load_file("src/core/tsi/test_creds/badserver.key", 1, &key_slice))); + pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GRPC_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); + + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + + bad_ssl_run(server); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/census/context_test.c b/test/core/census/context_test.c deleted file mode 100644 index ca5a6ec5cd..0000000000 --- a/test/core/census/context_test.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Test census_context functions, including encoding/decoding - -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -// A set of tags Used to create a basic context for testing. Note that -// replace_add_delete_test() relies on specific offsets into this array - if -// you add or delete entries, you will also need to change the test. -#define BASIC_TAG_COUNT 8 -static census_tag basic_tags[BASIC_TAG_COUNT] = { - /* 0 */ {"key0", "tag value", 0}, - /* 1 */ {"k1", "a", CENSUS_TAG_PROPAGATE}, - /* 2 */ {"k2", "a longer tag value supercalifragilisticexpialiadocious", - CENSUS_TAG_STATS}, - /* 3 */ {"key_three", "", 0}, - /* 4 */ {"a_really_really_really_really_long_key_4", "random", - CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}, - /* 5 */ {"k5", "v5", CENSUS_TAG_PROPAGATE}, - /* 6 */ {"k6", "v6", CENSUS_TAG_STATS}, - /* 7 */ {"k7", "v7", CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}}; - -// Set of tags used to modify the basic context. Note that -// replace_add_delete_test() relies on specific offsets into this array - if -// you add or delete entries, you will also need to change the test. Other -// tests that rely on specific instances have XXX_XXX_OFFSET definitions (also -// change the defines below if you add/delete entires). -#define MODIFY_TAG_COUNT 10 -static census_tag modify_tags[MODIFY_TAG_COUNT] = { -#define REPLACE_VALUE_OFFSET 0 - /* 0 */ {"key0", "replace key0", 0}, // replaces tag value only -#define ADD_TAG_OFFSET 1 - /* 1 */ {"new_key", "xyzzy", CENSUS_TAG_STATS}, // new tag -#define DELETE_TAG_OFFSET 2 - /* 2 */ {"k5", NULL, 0}, // should delete tag - /* 3 */ {"k5", NULL, 0}, // try deleting already-deleted tag - /* 4 */ {"non-existent", NULL, 0}, // delete non-existent tag -#define REPLACE_FLAG_OFFSET 5 - /* 5 */ {"k1", "a", 0}, // change flags only - /* 6 */ {"k7", "bar", CENSUS_TAG_STATS}, // change flags and value - /* 7 */ {"k2", "", CENSUS_TAG_PROPAGATE}, // more value and flags change - /* 8 */ {"k5", "bar", 0}, // add back tag, with different value - /* 9 */ {"foo", "bar", CENSUS_TAG_PROPAGATE}, // another new tag -}; - -// Utility function to compare tags. Returns true if all fields match. -static bool compare_tag(const census_tag *t1, const census_tag *t2) { - return (strcmp(t1->key, t2->key) == 0 && strcmp(t1->value, t2->value) == 0 && - t1->flags == t2->flags); -} - -// Utility function to validate a tag exists in context. -static bool validate_tag(const census_context *context, const census_tag *tag) { - census_tag tag2; - if (census_context_get_tag(context, tag->key, &tag2) != 1) return false; - return compare_tag(tag, &tag2); -} - -// Create an empty context. -static void empty_test(void) { - struct census_context *context = census_context_create(NULL, NULL, 0, NULL); - GPR_ASSERT(context != NULL); - const census_context_status *status = census_context_get_status(context); - census_context_status expected = {0, 0, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); -} - -// Test create and iteration over basic context. -static void basic_test(void) { - const census_context_status *status; - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, &status); - census_context_status expected = {4, 4, 0, 8, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_iterator it; - census_context_initialize_iterator(context, &it); - census_tag tag; - while (census_context_next_tag(&it, &tag)) { - // can't rely on tag return order: make sure it matches exactly one. - int matches = 0; - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - if (compare_tag(&tag, &basic_tags[i])) matches++; - } - GPR_ASSERT(matches == 1); - } - census_context_destroy(context); -} - -// Test census_context_get_tag(). -static void lookup_by_key_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - census_tag tag; - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - GPR_ASSERT(census_context_get_tag(context, basic_tags[i].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } - // non-existent keys - GPR_ASSERT(census_context_get_tag(context, "key", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "key01", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "k9", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "random", &tag) == 0); - GPR_ASSERT(census_context_get_tag(context, "", &tag) == 0); - census_context_destroy(context); -} - -// Try creating context with invalid entries. -static void invalid_test(void) { - char key[300]; - memset(key, 'k', 299); - key[299] = 0; - char value[300]; - memset(value, 'v', 299); - value[299] = 0; - census_tag tag = {key, value, 0}; - // long keys, short value. Key lengths (including terminator) should be - // <= 255 (CENSUS_MAX_TAG_KV_LEN) - value[3] = 0; - GPR_ASSERT(strlen(value) == 3); - GPR_ASSERT(strlen(key) == 299); - const census_context_status *status; - struct census_context *context = - census_context_create(NULL, &tag, 1, &status); - census_context_status expected = {0, 0, 0, 0, 0, 1, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - key[CENSUS_MAX_TAG_KV_LEN] = 0; - GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - key[CENSUS_MAX_TAG_KV_LEN - 1] = 0; - GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN - 1); - context = census_context_create(NULL, &tag, 1, &status); - census_context_status expected2 = {0, 1, 0, 1, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); - census_context_destroy(context); - // now try with long values - value[3] = 'v'; - GPR_ASSERT(strlen(value) == 299); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - value[CENSUS_MAX_TAG_KV_LEN] = 0; - GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - value[CENSUS_MAX_TAG_KV_LEN - 1] = 0; - GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN - 1); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); - census_context_destroy(context); - // 0 length key. - key[0] = 0; - GPR_ASSERT(strlen(key) == 0); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - // invalid key character - key[0] = 31; // 32 (' ') is the first valid character value - key[1] = 0; - GPR_ASSERT(strlen(key) == 1); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); - // invalid value character - key[0] = ' '; - value[5] = 127; // 127 (DEL) is ('~' + 1) - value[8] = 0; - GPR_ASSERT(strlen(key) == 1); - GPR_ASSERT(strlen(value) == 8); - context = census_context_create(NULL, &tag, 1, &status); - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_context_destroy(context); -} - -// Make a copy of a context -static void copy_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, NULL, 0, &status); - census_context_status expected = {4, 4, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - census_tag tag; - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } - census_context_destroy(context); - census_context_destroy(context2); -} - -// replace a single tag value -static void replace_value_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + REPLACE_VALUE_OFFSET, 1, &status); - census_context_status expected = {4, 4, 0, 0, 1, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[REPLACE_VALUE_OFFSET].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_VALUE_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// replace a single tags flags -static void replace_flags_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + REPLACE_FLAG_OFFSET, 1, &status); - census_context_status expected = {3, 5, 0, 0, 1, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[REPLACE_FLAG_OFFSET].key, &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_FLAG_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// delete a single tag. -static void delete_tag_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = census_context_create( - context, modify_tags + DELETE_TAG_OFFSET, 1, &status); - census_context_status expected = {3, 4, 1, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag( - context2, modify_tags[DELETE_TAG_OFFSET].key, &tag) == 0); - census_context_destroy(context); - census_context_destroy(context2); -} - -// add a single new tag. -static void add_tag_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, modify_tags + ADD_TAG_OFFSET, 1, &status); - census_context_status expected = {4, 5, 0, 1, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - census_tag tag; - GPR_ASSERT(census_context_get_tag(context2, modify_tags[ADD_TAG_OFFSET].key, - &tag) == 1); - GPR_ASSERT(compare_tag(&tag, &modify_tags[ADD_TAG_OFFSET])); - census_context_destroy(context); - census_context_destroy(context2); -} - -// test many changes at once. -static void replace_add_delete_test(void) { - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - const census_context_status *status; - struct census_context *context2 = - census_context_create(context, modify_tags, MODIFY_TAG_COUNT, &status); - census_context_status expected = {3, 7, 1, 3, 4, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - // validate context contents. Use specific indices into the two arrays - // holding tag values. - GPR_ASSERT(validate_tag(context2, &basic_tags[3])); - GPR_ASSERT(validate_tag(context2, &basic_tags[4])); - GPR_ASSERT(validate_tag(context2, &basic_tags[6])); - GPR_ASSERT(validate_tag(context2, &modify_tags[0])); - GPR_ASSERT(validate_tag(context2, &modify_tags[1])); - GPR_ASSERT(validate_tag(context2, &modify_tags[5])); - GPR_ASSERT(validate_tag(context2, &modify_tags[6])); - GPR_ASSERT(validate_tag(context2, &modify_tags[7])); - GPR_ASSERT(validate_tag(context2, &modify_tags[8])); - GPR_ASSERT(validate_tag(context2, &modify_tags[9])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[0])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[1])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[2])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[5])); - GPR_ASSERT(!validate_tag(context2, &basic_tags[7])); - census_context_destroy(context); - census_context_destroy(context2); -} - -#define BUF_SIZE 200 - -// test encode/decode. -static void encode_decode_test(void) { - char buffer[BUF_SIZE]; - struct census_context *context = - census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); - // Test with too small a buffer - GPR_ASSERT(census_context_encode(context, buffer, 2) == 0); - // Test with sufficient buffer - size_t buf_used = census_context_encode(context, buffer, BUF_SIZE); - GPR_ASSERT(buf_used != 0); - census_context *context2 = census_context_decode(buffer, buf_used); - GPR_ASSERT(context2 != NULL); - const census_context_status *status = census_context_get_status(context2); - census_context_status expected = {4, 0, 0, 0, 0, 0, 0}; - GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); - for (int i = 0; i < BASIC_TAG_COUNT; i++) { - census_tag tag; - if (CENSUS_TAG_IS_PROPAGATED(basic_tags[i].flags)) { - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == - 1); - GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); - } else { - GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == - 0); - } - } - census_context_destroy(context2); - census_context_destroy(context); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - empty_test(); - basic_test(); - lookup_by_key_test(); - invalid_test(); - copy_test(); - replace_value_test(); - replace_flags_test(); - delete_tag_test(); - add_tag_test(); - replace_add_delete_test(); - encode_decode_test(); - return 0; -} diff --git a/test/core/census/context_test.cc b/test/core/census/context_test.cc new file mode 100644 index 0000000000..ca5a6ec5cd --- /dev/null +++ b/test/core/census/context_test.cc @@ -0,0 +1,363 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// Test census_context functions, including encoding/decoding + +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +// A set of tags Used to create a basic context for testing. Note that +// replace_add_delete_test() relies on specific offsets into this array - if +// you add or delete entries, you will also need to change the test. +#define BASIC_TAG_COUNT 8 +static census_tag basic_tags[BASIC_TAG_COUNT] = { + /* 0 */ {"key0", "tag value", 0}, + /* 1 */ {"k1", "a", CENSUS_TAG_PROPAGATE}, + /* 2 */ {"k2", "a longer tag value supercalifragilisticexpialiadocious", + CENSUS_TAG_STATS}, + /* 3 */ {"key_three", "", 0}, + /* 4 */ {"a_really_really_really_really_long_key_4", "random", + CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}, + /* 5 */ {"k5", "v5", CENSUS_TAG_PROPAGATE}, + /* 6 */ {"k6", "v6", CENSUS_TAG_STATS}, + /* 7 */ {"k7", "v7", CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}}; + +// Set of tags used to modify the basic context. Note that +// replace_add_delete_test() relies on specific offsets into this array - if +// you add or delete entries, you will also need to change the test. Other +// tests that rely on specific instances have XXX_XXX_OFFSET definitions (also +// change the defines below if you add/delete entires). +#define MODIFY_TAG_COUNT 10 +static census_tag modify_tags[MODIFY_TAG_COUNT] = { +#define REPLACE_VALUE_OFFSET 0 + /* 0 */ {"key0", "replace key0", 0}, // replaces tag value only +#define ADD_TAG_OFFSET 1 + /* 1 */ {"new_key", "xyzzy", CENSUS_TAG_STATS}, // new tag +#define DELETE_TAG_OFFSET 2 + /* 2 */ {"k5", NULL, 0}, // should delete tag + /* 3 */ {"k5", NULL, 0}, // try deleting already-deleted tag + /* 4 */ {"non-existent", NULL, 0}, // delete non-existent tag +#define REPLACE_FLAG_OFFSET 5 + /* 5 */ {"k1", "a", 0}, // change flags only + /* 6 */ {"k7", "bar", CENSUS_TAG_STATS}, // change flags and value + /* 7 */ {"k2", "", CENSUS_TAG_PROPAGATE}, // more value and flags change + /* 8 */ {"k5", "bar", 0}, // add back tag, with different value + /* 9 */ {"foo", "bar", CENSUS_TAG_PROPAGATE}, // another new tag +}; + +// Utility function to compare tags. Returns true if all fields match. +static bool compare_tag(const census_tag *t1, const census_tag *t2) { + return (strcmp(t1->key, t2->key) == 0 && strcmp(t1->value, t2->value) == 0 && + t1->flags == t2->flags); +} + +// Utility function to validate a tag exists in context. +static bool validate_tag(const census_context *context, const census_tag *tag) { + census_tag tag2; + if (census_context_get_tag(context, tag->key, &tag2) != 1) return false; + return compare_tag(tag, &tag2); +} + +// Create an empty context. +static void empty_test(void) { + struct census_context *context = census_context_create(NULL, NULL, 0, NULL); + GPR_ASSERT(context != NULL); + const census_context_status *status = census_context_get_status(context); + census_context_status expected = {0, 0, 0, 0, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); +} + +// Test create and iteration over basic context. +static void basic_test(void) { + const census_context_status *status; + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, &status); + census_context_status expected = {4, 4, 0, 8, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_iterator it; + census_context_initialize_iterator(context, &it); + census_tag tag; + while (census_context_next_tag(&it, &tag)) { + // can't rely on tag return order: make sure it matches exactly one. + int matches = 0; + for (int i = 0; i < BASIC_TAG_COUNT; i++) { + if (compare_tag(&tag, &basic_tags[i])) matches++; + } + GPR_ASSERT(matches == 1); + } + census_context_destroy(context); +} + +// Test census_context_get_tag(). +static void lookup_by_key_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + census_tag tag; + for (int i = 0; i < BASIC_TAG_COUNT; i++) { + GPR_ASSERT(census_context_get_tag(context, basic_tags[i].key, &tag) == 1); + GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); + } + // non-existent keys + GPR_ASSERT(census_context_get_tag(context, "key", &tag) == 0); + GPR_ASSERT(census_context_get_tag(context, "key01", &tag) == 0); + GPR_ASSERT(census_context_get_tag(context, "k9", &tag) == 0); + GPR_ASSERT(census_context_get_tag(context, "random", &tag) == 0); + GPR_ASSERT(census_context_get_tag(context, "", &tag) == 0); + census_context_destroy(context); +} + +// Try creating context with invalid entries. +static void invalid_test(void) { + char key[300]; + memset(key, 'k', 299); + key[299] = 0; + char value[300]; + memset(value, 'v', 299); + value[299] = 0; + census_tag tag = {key, value, 0}; + // long keys, short value. Key lengths (including terminator) should be + // <= 255 (CENSUS_MAX_TAG_KV_LEN) + value[3] = 0; + GPR_ASSERT(strlen(value) == 3); + GPR_ASSERT(strlen(key) == 299); + const census_context_status *status; + struct census_context *context = + census_context_create(NULL, &tag, 1, &status); + census_context_status expected = {0, 0, 0, 0, 0, 1, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + key[CENSUS_MAX_TAG_KV_LEN] = 0; + GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + key[CENSUS_MAX_TAG_KV_LEN - 1] = 0; + GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN - 1); + context = census_context_create(NULL, &tag, 1, &status); + census_context_status expected2 = {0, 1, 0, 1, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); + census_context_destroy(context); + // now try with long values + value[3] = 'v'; + GPR_ASSERT(strlen(value) == 299); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + value[CENSUS_MAX_TAG_KV_LEN] = 0; + GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + value[CENSUS_MAX_TAG_KV_LEN - 1] = 0; + GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN - 1); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0); + census_context_destroy(context); + // 0 length key. + key[0] = 0; + GPR_ASSERT(strlen(key) == 0); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + // invalid key character + key[0] = 31; // 32 (' ') is the first valid character value + key[1] = 0; + GPR_ASSERT(strlen(key) == 1); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); + // invalid value character + key[0] = ' '; + value[5] = 127; // 127 (DEL) is ('~' + 1) + value[8] = 0; + GPR_ASSERT(strlen(key) == 1); + GPR_ASSERT(strlen(value) == 8); + context = census_context_create(NULL, &tag, 1, &status); + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_context_destroy(context); +} + +// Make a copy of a context +static void copy_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = + census_context_create(context, NULL, 0, &status); + census_context_status expected = {4, 4, 0, 0, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + for (int i = 0; i < BASIC_TAG_COUNT; i++) { + census_tag tag; + GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == 1); + GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); + } + census_context_destroy(context); + census_context_destroy(context2); +} + +// replace a single tag value +static void replace_value_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = census_context_create( + context, modify_tags + REPLACE_VALUE_OFFSET, 1, &status); + census_context_status expected = {4, 4, 0, 0, 1, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_tag tag; + GPR_ASSERT(census_context_get_tag( + context2, modify_tags[REPLACE_VALUE_OFFSET].key, &tag) == 1); + GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_VALUE_OFFSET])); + census_context_destroy(context); + census_context_destroy(context2); +} + +// replace a single tags flags +static void replace_flags_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = census_context_create( + context, modify_tags + REPLACE_FLAG_OFFSET, 1, &status); + census_context_status expected = {3, 5, 0, 0, 1, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_tag tag; + GPR_ASSERT(census_context_get_tag( + context2, modify_tags[REPLACE_FLAG_OFFSET].key, &tag) == 1); + GPR_ASSERT(compare_tag(&tag, &modify_tags[REPLACE_FLAG_OFFSET])); + census_context_destroy(context); + census_context_destroy(context2); +} + +// delete a single tag. +static void delete_tag_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = census_context_create( + context, modify_tags + DELETE_TAG_OFFSET, 1, &status); + census_context_status expected = {3, 4, 1, 0, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_tag tag; + GPR_ASSERT(census_context_get_tag( + context2, modify_tags[DELETE_TAG_OFFSET].key, &tag) == 0); + census_context_destroy(context); + census_context_destroy(context2); +} + +// add a single new tag. +static void add_tag_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = + census_context_create(context, modify_tags + ADD_TAG_OFFSET, 1, &status); + census_context_status expected = {4, 5, 0, 1, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + census_tag tag; + GPR_ASSERT(census_context_get_tag(context2, modify_tags[ADD_TAG_OFFSET].key, + &tag) == 1); + GPR_ASSERT(compare_tag(&tag, &modify_tags[ADD_TAG_OFFSET])); + census_context_destroy(context); + census_context_destroy(context2); +} + +// test many changes at once. +static void replace_add_delete_test(void) { + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + const census_context_status *status; + struct census_context *context2 = + census_context_create(context, modify_tags, MODIFY_TAG_COUNT, &status); + census_context_status expected = {3, 7, 1, 3, 4, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + // validate context contents. Use specific indices into the two arrays + // holding tag values. + GPR_ASSERT(validate_tag(context2, &basic_tags[3])); + GPR_ASSERT(validate_tag(context2, &basic_tags[4])); + GPR_ASSERT(validate_tag(context2, &basic_tags[6])); + GPR_ASSERT(validate_tag(context2, &modify_tags[0])); + GPR_ASSERT(validate_tag(context2, &modify_tags[1])); + GPR_ASSERT(validate_tag(context2, &modify_tags[5])); + GPR_ASSERT(validate_tag(context2, &modify_tags[6])); + GPR_ASSERT(validate_tag(context2, &modify_tags[7])); + GPR_ASSERT(validate_tag(context2, &modify_tags[8])); + GPR_ASSERT(validate_tag(context2, &modify_tags[9])); + GPR_ASSERT(!validate_tag(context2, &basic_tags[0])); + GPR_ASSERT(!validate_tag(context2, &basic_tags[1])); + GPR_ASSERT(!validate_tag(context2, &basic_tags[2])); + GPR_ASSERT(!validate_tag(context2, &basic_tags[5])); + GPR_ASSERT(!validate_tag(context2, &basic_tags[7])); + census_context_destroy(context); + census_context_destroy(context2); +} + +#define BUF_SIZE 200 + +// test encode/decode. +static void encode_decode_test(void) { + char buffer[BUF_SIZE]; + struct census_context *context = + census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); + // Test with too small a buffer + GPR_ASSERT(census_context_encode(context, buffer, 2) == 0); + // Test with sufficient buffer + size_t buf_used = census_context_encode(context, buffer, BUF_SIZE); + GPR_ASSERT(buf_used != 0); + census_context *context2 = census_context_decode(buffer, buf_used); + GPR_ASSERT(context2 != NULL); + const census_context_status *status = census_context_get_status(context2); + census_context_status expected = {4, 0, 0, 0, 0, 0, 0}; + GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); + for (int i = 0; i < BASIC_TAG_COUNT; i++) { + census_tag tag; + if (CENSUS_TAG_IS_PROPAGATED(basic_tags[i].flags)) { + GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == + 1); + GPR_ASSERT(compare_tag(&tag, &basic_tags[i])); + } else { + GPR_ASSERT(census_context_get_tag(context2, basic_tags[i].key, &tag) == + 0); + } + } + census_context_destroy(context2); + census_context_destroy(context); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + empty_test(); + basic_test(); + lookup_by_key_test(); + invalid_test(); + copy_test(); + replace_value_test(); + replace_flags_test(); + delete_tag_test(); + add_tag_test(); + replace_add_delete_test(); + encode_decode_test(); + return 0; +} diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c deleted file mode 100644 index 0826b55c63..0000000000 --- a/test/core/census/intrusive_hash_map_test.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/intrusive_hash_map.h" - -#include -#include -#include "test/core/util/test_config.h" - -#include -#include -#include -#include - -/* The initial size of an intrusive hash map will be 2 to this power. */ -static const uint32_t kInitialLog2Size = 4; - -/* Simple object used for testing intrusive_hash_map. */ -typedef struct object { uint64_t val; } object; - -/* Helper function to allocate and initialize object. */ -static __inline object *make_new_object(uint64_t val) { - object *obj = (object *)gpr_malloc(sizeof(object)); - obj->val = val; - return obj; -} - -/* Wrapper struct for object. */ -typedef struct ptr_item { - INTRUSIVE_HASH_MAP_HEADER; - object *obj; -} ptr_item; - -/* Helper function that creates a new hash map item. It is up to the user to - * free the item that was allocated. */ -static __inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) { - ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item)); - new_item->IHM_key = key; - new_item->IHM_hash_link = NULL; - new_item->obj = make_new_object(value); - return new_item; -} - -/* Helper function to deallocate ptr_item. */ -static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); } - -/* Simple string object used for testing intrusive_hash_map. */ -typedef struct string_item { - INTRUSIVE_HASH_MAP_HEADER; - // User data. - char buf[32]; - uint16_t len; -} string_item; - -/* Helper function to allocate and initialize string object. */ -static string_item *make_string_item(uint64_t key, const char *buf, - uint16_t len) { - string_item *item = (string_item *)gpr_malloc(sizeof(string_item)); - item->IHM_key = key; - item->IHM_hash_link = NULL; - item->len = len; - memcpy(item->buf, buf, sizeof(char) * len); - return item; -} - -/* Helper function for comparing two string objects. */ -static bool compare_string_item(const string_item *A, const string_item *B) { - if (A->IHM_key != B->IHM_key || A->len != B->len) - return false; - else { - for (int i = 0; i < A->len; ++i) { - if (A->buf[i] != B->buf[i]) return false; - } - } - - return true; -} - -void test_empty() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, NULL); -} - -void test_single_item() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - ptr_item *new_item = make_ptr_item(10, 20); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item); - GPR_ASSERT(ok); - - ptr_item *item1 = - (ptr_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); - GPR_ASSERT(item1->obj->val == 20); - GPR_ASSERT(item1 == new_item); - - ptr_item *item2 = - (ptr_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); - GPR_ASSERT(item2 == new_item); - - gpr_free(new_item->obj); - gpr_free(new_item); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -void test_two_items() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - string_item *new_item1 = make_string_item(10, "test1", 5); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1); - GPR_ASSERT(ok); - string_item *new_item2 = make_string_item(20, "test2", 5); - ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item2); - GPR_ASSERT(ok); - - string_item *item1 = - (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); - GPR_ASSERT(compare_string_item(new_item1, item1)); - GPR_ASSERT(item1 == new_item1); - string_item *item2 = - (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)20); - GPR_ASSERT(compare_string_item(new_item2, item2)); - GPR_ASSERT(item2 == new_item2); - - item1 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); - GPR_ASSERT(item1 == new_item1); - item2 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)20); - GPR_ASSERT(item2 == new_item2); - - gpr_free(new_item1); - gpr_free(new_item2); - GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); - intrusive_hash_map_free(&hash_map, NULL); -} - -// Test resetting and clearing the hash map. -void test_reset_clear() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - // Add some data to the hash_map. - for (uint64_t i = 0; i < 3; ++i) { - intrusive_hash_map_insert(&hash_map, (hm_item *)make_ptr_item(i, i)); - } - GPR_ASSERT(3 == intrusive_hash_map_size(&hash_map)); - - // Test find. - for (uint64_t i = 0; i < 3; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->IHM_key == i && item->obj->val == i); - } - - intrusive_hash_map_clear(&hash_map, &free_ptr_item); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -// Check that the hash_map contains every key between [min_value, max_value] -// (inclusive). -void check_hash_map_values(intrusive_hash_map *hash_map, uint64_t min_value, - uint64_t max_value) { - GPR_ASSERT(intrusive_hash_map_size(hash_map) == max_value - min_value + 1); - - for (uint64_t i = min_value; i <= max_value; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->obj->val == i); - } -} - -// Add many items and cause the hash_map to extend. -void test_extend() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - - const uint64_t kNumValues = (1 << 16); - - for (uint64_t i = 0; i < kNumValues; ++i) { - ptr_item *item = make_ptr_item(i, i); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); - GPR_ASSERT(ok); - if (i % 1000 == 0) { - check_hash_map_values(&hash_map, 0, i); - } - } - - for (uint64_t i = 0; i < kNumValues; ++i) { - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); - GPR_ASSERT(item != NULL); - GPR_ASSERT(item->IHM_key == i && item->obj->val == i); - ptr_item *item2 = (ptr_item *)intrusive_hash_map_erase(&hash_map, i); - GPR_ASSERT(item == item2); - gpr_free(item->obj); - gpr_free(item); - } - - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -void test_stress() { - intrusive_hash_map hash_map; - intrusive_hash_map_init(&hash_map, kInitialLog2Size); - size_t n = 0; - - // Randomly add and insert entries 1000000 times. - for (uint64_t i = 0; i < 1000000; ++i) { - int op = rand() & 0x1; - - switch (op) { - // Case 0 is insertion of entry. - case 0: { - uint64_t key = (uint64_t)(rand() % 10000); - ptr_item *item = make_ptr_item(key, key); - bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); - if (ok) { - n++; - } else { - gpr_free(item->obj); - gpr_free(item); - } - break; - } - // Case 1 is removal of entry. - case 1: { - uint64_t key = (uint64_t)(rand() % 10000); - ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key); - if (item != NULL) { - n--; - GPR_ASSERT(key == item->obj->val); - ptr_item *item2 = - (ptr_item *)intrusive_hash_map_erase(&hash_map, key); - GPR_ASSERT(item == item2); - gpr_free(item->obj); - gpr_free(item); - } - break; - } - } - } - // Check size - GPR_ASSERT(n == intrusive_hash_map_size(&hash_map)); - - // Clean the hash_map up. - intrusive_hash_map_clear(&hash_map, &free_ptr_item); - GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); - intrusive_hash_map_free(&hash_map, &free_ptr_item); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - gpr_time_init(); - srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - - test_empty(); - test_single_item(); - test_two_items(); - test_reset_clear(); - test_extend(); - test_stress(); - - return 0; -} diff --git a/test/core/census/intrusive_hash_map_test.cc b/test/core/census/intrusive_hash_map_test.cc new file mode 100644 index 0000000000..0826b55c63 --- /dev/null +++ b/test/core/census/intrusive_hash_map_test.cc @@ -0,0 +1,284 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/census/intrusive_hash_map.h" + +#include +#include +#include "test/core/util/test_config.h" + +#include +#include +#include +#include + +/* The initial size of an intrusive hash map will be 2 to this power. */ +static const uint32_t kInitialLog2Size = 4; + +/* Simple object used for testing intrusive_hash_map. */ +typedef struct object { uint64_t val; } object; + +/* Helper function to allocate and initialize object. */ +static __inline object *make_new_object(uint64_t val) { + object *obj = (object *)gpr_malloc(sizeof(object)); + obj->val = val; + return obj; +} + +/* Wrapper struct for object. */ +typedef struct ptr_item { + INTRUSIVE_HASH_MAP_HEADER; + object *obj; +} ptr_item; + +/* Helper function that creates a new hash map item. It is up to the user to + * free the item that was allocated. */ +static __inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) { + ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item)); + new_item->IHM_key = key; + new_item->IHM_hash_link = NULL; + new_item->obj = make_new_object(value); + return new_item; +} + +/* Helper function to deallocate ptr_item. */ +static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); } + +/* Simple string object used for testing intrusive_hash_map. */ +typedef struct string_item { + INTRUSIVE_HASH_MAP_HEADER; + // User data. + char buf[32]; + uint16_t len; +} string_item; + +/* Helper function to allocate and initialize string object. */ +static string_item *make_string_item(uint64_t key, const char *buf, + uint16_t len) { + string_item *item = (string_item *)gpr_malloc(sizeof(string_item)); + item->IHM_key = key; + item->IHM_hash_link = NULL; + item->len = len; + memcpy(item->buf, buf, sizeof(char) * len); + return item; +} + +/* Helper function for comparing two string objects. */ +static bool compare_string_item(const string_item *A, const string_item *B) { + if (A->IHM_key != B->IHM_key || A->len != B->len) + return false; + else { + for (int i = 0; i < A->len; ++i) { + if (A->buf[i] != B->buf[i]) return false; + } + } + + return true; +} + +void test_empty() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); + GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); + intrusive_hash_map_free(&hash_map, NULL); +} + +void test_single_item() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + + ptr_item *new_item = make_ptr_item(10, 20); + bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item); + GPR_ASSERT(ok); + + ptr_item *item1 = + (ptr_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); + GPR_ASSERT(item1->obj->val == 20); + GPR_ASSERT(item1 == new_item); + + ptr_item *item2 = + (ptr_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); + GPR_ASSERT(item2 == new_item); + + gpr_free(new_item->obj); + gpr_free(new_item); + GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); + intrusive_hash_map_free(&hash_map, &free_ptr_item); +} + +void test_two_items() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + + string_item *new_item1 = make_string_item(10, "test1", 5); + bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1); + GPR_ASSERT(ok); + string_item *new_item2 = make_string_item(20, "test2", 5); + ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item2); + GPR_ASSERT(ok); + + string_item *item1 = + (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10); + GPR_ASSERT(compare_string_item(new_item1, item1)); + GPR_ASSERT(item1 == new_item1); + string_item *item2 = + (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)20); + GPR_ASSERT(compare_string_item(new_item2, item2)); + GPR_ASSERT(item2 == new_item2); + + item1 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10); + GPR_ASSERT(item1 == new_item1); + item2 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)20); + GPR_ASSERT(item2 == new_item2); + + gpr_free(new_item1); + gpr_free(new_item2); + GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map)); + intrusive_hash_map_free(&hash_map, NULL); +} + +// Test resetting and clearing the hash map. +void test_reset_clear() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + + // Add some data to the hash_map. + for (uint64_t i = 0; i < 3; ++i) { + intrusive_hash_map_insert(&hash_map, (hm_item *)make_ptr_item(i, i)); + } + GPR_ASSERT(3 == intrusive_hash_map_size(&hash_map)); + + // Test find. + for (uint64_t i = 0; i < 3; ++i) { + ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); + GPR_ASSERT(item != NULL); + GPR_ASSERT(item->IHM_key == i && item->obj->val == i); + } + + intrusive_hash_map_clear(&hash_map, &free_ptr_item); + GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); + intrusive_hash_map_free(&hash_map, &free_ptr_item); +} + +// Check that the hash_map contains every key between [min_value, max_value] +// (inclusive). +void check_hash_map_values(intrusive_hash_map *hash_map, uint64_t min_value, + uint64_t max_value) { + GPR_ASSERT(intrusive_hash_map_size(hash_map) == max_value - min_value + 1); + + for (uint64_t i = min_value; i <= max_value; ++i) { + ptr_item *item = (ptr_item *)intrusive_hash_map_find(hash_map, i); + GPR_ASSERT(item != NULL); + GPR_ASSERT(item->obj->val == i); + } +} + +// Add many items and cause the hash_map to extend. +void test_extend() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + + const uint64_t kNumValues = (1 << 16); + + for (uint64_t i = 0; i < kNumValues; ++i) { + ptr_item *item = make_ptr_item(i, i); + bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); + GPR_ASSERT(ok); + if (i % 1000 == 0) { + check_hash_map_values(&hash_map, 0, i); + } + } + + for (uint64_t i = 0; i < kNumValues; ++i) { + ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i); + GPR_ASSERT(item != NULL); + GPR_ASSERT(item->IHM_key == i && item->obj->val == i); + ptr_item *item2 = (ptr_item *)intrusive_hash_map_erase(&hash_map, i); + GPR_ASSERT(item == item2); + gpr_free(item->obj); + gpr_free(item); + } + + GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); + intrusive_hash_map_free(&hash_map, &free_ptr_item); +} + +void test_stress() { + intrusive_hash_map hash_map; + intrusive_hash_map_init(&hash_map, kInitialLog2Size); + size_t n = 0; + + // Randomly add and insert entries 1000000 times. + for (uint64_t i = 0; i < 1000000; ++i) { + int op = rand() & 0x1; + + switch (op) { + // Case 0 is insertion of entry. + case 0: { + uint64_t key = (uint64_t)(rand() % 10000); + ptr_item *item = make_ptr_item(key, key); + bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item); + if (ok) { + n++; + } else { + gpr_free(item->obj); + gpr_free(item); + } + break; + } + // Case 1 is removal of entry. + case 1: { + uint64_t key = (uint64_t)(rand() % 10000); + ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key); + if (item != NULL) { + n--; + GPR_ASSERT(key == item->obj->val); + ptr_item *item2 = + (ptr_item *)intrusive_hash_map_erase(&hash_map, key); + GPR_ASSERT(item == item2); + gpr_free(item->obj); + gpr_free(item); + } + break; + } + } + } + // Check size + GPR_ASSERT(n == intrusive_hash_map_size(&hash_map)); + + // Clean the hash_map up. + intrusive_hash_map_clear(&hash_map, &free_ptr_item); + GPR_ASSERT(intrusive_hash_map_empty(&hash_map)); + intrusive_hash_map_free(&hash_map, &free_ptr_item); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + gpr_time_init(); + srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + + test_empty(); + test_single_item(); + test_two_items(); + test_reset_clear(); + test_extend(); + test_stress(); + + return 0; +} diff --git a/test/core/census/mlog_test.c b/test/core/census/mlog_test.c deleted file mode 100644 index 968fd91da4..0000000000 --- a/test/core/census/mlog_test.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/mlog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -// Change this to non-zero if you want more output. -#define VERBOSE 0 - -// Log size to use for all tests. -#define LOG_SIZE_IN_MB 1 -#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) - -// Fills in 'record' of size 'size'. Each byte in record is filled in with the -// same value. The value is extracted from 'record' pointer. -static void write_record(char* record, size_t size) { - char data = (char)((uintptr_t)record % 255); - memset(record, data, size); -} - -// Reads fixed size records. Returns the number of records read in -// 'num_records'. -static void read_records(size_t record_size, const char* buffer, - size_t buffer_size, int* num_records) { - GPR_ASSERT(buffer_size >= record_size); - GPR_ASSERT(buffer_size % record_size == 0); - *num_records = (int)(buffer_size / record_size); - for (int i = 0; i < *num_records; ++i) { - const char* record = buffer + (record_size * (size_t)i); - char data = (char)((uintptr_t)record % 255); - for (size_t j = 0; j < record_size; ++j) { - GPR_ASSERT(data == record[j]); - } - } -} - -// Tries to write the specified number of records. Stops when the log gets -// full. Returns the number of records written. Spins for random -// number of times, up to 'max_spin_count', between writes. -static int write_records_to_log(int writer_id, size_t record_size, - int num_records, int max_spin_count) { - int counter = 0; - for (int i = 0; i < num_records; ++i) { - int spin_count = max_spin_count ? rand() % max_spin_count : 0; - if (VERBOSE && (counter++ == num_records / 10)) { - printf(" Writer %d: %d out of %d written\n", writer_id, i, num_records); - counter = 0; - } - char* record = (char*)(census_log_start_write(record_size)); - if (record == NULL) { - return i; - } - write_record(record, record_size); - census_log_end_write(record, record_size); - for (int j = 0; j < spin_count; ++j) { - GPR_ASSERT(j >= 0); - } - } - return num_records; -} - -// Performs a single read iteration. Returns the number of records read. -static int perform_read_iteration(size_t record_size) { - const void* read_buffer = NULL; - size_t bytes_available; - int records_read = 0; - census_log_init_reader(); - while ((read_buffer = census_log_read_next(&bytes_available))) { - int num_records = 0; - read_records(record_size, (const char*)read_buffer, bytes_available, - &num_records); - records_read += num_records; - } - return records_read; -} - -// Asserts that the log is empty. -static void assert_log_empty(void) { - census_log_init_reader(); - size_t bytes_available; - GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); -} - -// Fills the log and verifies data. If 'no fragmentation' is true, records -// are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record -// size. If not a circular log, verifies that the number of records written -// match the number of records read. -static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { - size_t size; - if (no_fragmentation) { - int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); - size = ((size_t)1 << log2size); - } else { - while (1) { - size = 1 + ((size_t)rand() % CENSUS_LOG_MAX_RECORD_SIZE); - if (CENSUS_LOG_MAX_RECORD_SIZE % size) { - break; - } - } - } - int records_written = - write_records_to_log(0 /* writer id */, size, - (int)((log_size / size) * 2), 0 /* spin count */); - int records_read = perform_read_iteration(size); - if (!circular_log) { - GPR_ASSERT(records_written == records_read); - } - assert_log_empty(); -} - -// Structure to pass args to writer_thread -typedef struct writer_thread_args { - // Index of this thread in the writers vector. - int index; - // Record size. - size_t record_size; - // Number of records to write. - int num_records; - // Used to signal when writer is complete - gpr_cv* done; - gpr_mu* mu; - int* count; -} writer_thread_args; - -// Writes the given number of records of random size (up to kMaxRecordSize) and -// random data to the specified log. -static void writer_thread(void* arg) { - writer_thread_args* args = (writer_thread_args*)arg; - // Maximum number of times to spin between writes. - static const int MAX_SPIN_COUNT = 50; - int records_written = 0; - if (VERBOSE) { - printf(" Writer %d starting\n", args->index); - } - while (records_written < args->num_records) { - records_written += write_records_to_log(args->index, args->record_size, - args->num_records - records_written, - MAX_SPIN_COUNT); - if (records_written < args->num_records) { - // Ran out of log space. Sleep for a bit and let the reader catch up. - // This should never happen for circular logs. - if (VERBOSE) { - printf( - " Writer %d stalled due to out-of-space: %d out of %d " - "written\n", - args->index, records_written, args->num_records); - } - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); - } - } - // Done. Decrement count and signal. - gpr_mu_lock(args->mu); - (*args->count)--; - gpr_cv_signal(args->done); - if (VERBOSE) { - printf(" Writer %d done\n", args->index); - } - gpr_mu_unlock(args->mu); -} - -// struct to pass args to reader_thread -typedef struct reader_thread_args { - // Record size. - size_t record_size; - // Interval between read iterations. - int read_iteration_interval_in_msec; - // Total number of records. - int total_records; - // Signalled when reader should stop. - gpr_cv stop; - int stop_flag; - // Used to signal when reader has finished - gpr_cv* done; - gpr_mu* mu; - int running; -} reader_thread_args; - -// Reads and verifies the specified number of records. Reader can also be -// stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' -// between read iterations. -static void reader_thread(void* arg) { - reader_thread_args* args = (reader_thread_args*)arg; - if (VERBOSE) { - printf(" Reader starting\n"); - } - gpr_timespec interval = gpr_time_from_micros( - args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); - gpr_mu_lock(args->mu); - int records_read = 0; - int num_iterations = 0; - int counter = 0; - while (!args->stop_flag && records_read < args->total_records) { - gpr_cv_wait(&args->stop, args->mu, interval); - if (!args->stop_flag) { - records_read += perform_read_iteration(args->record_size); - GPR_ASSERT(records_read <= args->total_records); - if (VERBOSE && (counter++ == 100000)) { - printf(" Reader: %d out of %d read\n", records_read, - args->total_records); - counter = 0; - } - ++num_iterations; - } - } - // Done - args->running = 0; - gpr_cv_signal(args->done); - if (VERBOSE) { - printf(" Reader: records: %d, iterations: %d\n", records_read, - num_iterations); - } - gpr_mu_unlock(args->mu); -} - -// Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER -// records. Also, starts a reader that iterates over and reads blocks every -// READ_ITERATION_INTERVAL_IN_MSEC. -// Number of writers. -#define NUM_WRITERS 5 -static void multiple_writers_single_reader(int circular_log) { - // Sleep interval between read iterations. - static const int READ_ITERATION_INTERVAL_IN_MSEC = 10; - // Maximum record size. - static const size_t MAX_RECORD_SIZE = 20; - // Number of records written by each writer. This is sized such that we - // will write through the entire log ~10 times. - const int NUM_RECORDS_PER_WRITER = - (int)((10 * census_log_remaining_space()) / (MAX_RECORD_SIZE / 2)) / - NUM_WRITERS; - size_t record_size = ((size_t)rand() % MAX_RECORD_SIZE) + 1; - // Create and start writers. - writer_thread_args writers[NUM_WRITERS]; - int writers_count = NUM_WRITERS; - gpr_cv writers_done; - gpr_mu writers_mu; // protects writers_done and writers_count - gpr_cv_init(&writers_done); - gpr_mu_init(&writers_mu); - gpr_thd_id id; - for (int i = 0; i < NUM_WRITERS; ++i) { - writers[i].index = i; - writers[i].record_size = record_size; - writers[i].num_records = NUM_RECORDS_PER_WRITER; - writers[i].done = &writers_done; - writers[i].count = &writers_count; - writers[i].mu = &writers_mu; - gpr_thd_new(&id, &writer_thread, &writers[i], NULL); - } - // Start reader. - gpr_cv reader_done; - gpr_mu reader_mu; // protects reader_done and reader.running - reader_thread_args reader; - reader.record_size = record_size; - reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; - reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; - reader.stop_flag = 0; - gpr_cv_init(&reader.stop); - gpr_cv_init(&reader_done); - reader.done = &reader_done; - gpr_mu_init(&reader_mu); - reader.mu = &reader_mu; - reader.running = 1; - gpr_thd_new(&id, &reader_thread, &reader, NULL); - // Wait for writers to finish. - gpr_mu_lock(&writers_mu); - while (writers_count != 0) { - gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&writers_mu); - gpr_mu_destroy(&writers_mu); - gpr_cv_destroy(&writers_done); - gpr_mu_lock(&reader_mu); - if (circular_log) { - // Stop reader. - reader.stop_flag = 1; - gpr_cv_signal(&reader.stop); - } - // wait for reader to finish - while (reader.running) { - gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - if (circular_log) { - // Assert that there were no out-of-space errors. - GPR_ASSERT(0 == census_log_out_of_space_count()); - } - gpr_mu_unlock(&reader_mu); - gpr_mu_destroy(&reader_mu); - gpr_cv_destroy(&reader_done); - if (VERBOSE) { - printf(" Reader: finished\n"); - } -} - -static void setup_test(int circular_log) { - census_log_initialize(LOG_SIZE_IN_MB, circular_log); - // GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); -} - -// Attempts to create a record of invalid size (size > -// CENSUS_LOG_MAX_RECORD_SIZE). -void test_invalid_record_size(void) { - static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; - static const size_t VALID_SIZE = 1; - printf("Starting test: invalid record size\n"); - setup_test(0); - void* record = census_log_start_write(INVALID_SIZE); - GPR_ASSERT(record == NULL); - // Now try writing a valid record. - record = census_log_start_write(VALID_SIZE); - GPR_ASSERT(record != NULL); - census_log_end_write(record, VALID_SIZE); - // Verifies that available space went down by one block. In theory, this - // check can fail if the thread is context switched to a new CPU during the - // start_write execution (multiple blocks get allocated), but this has not - // been observed in practice. - // GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == - // census_log_remaining_space()); - census_log_shutdown(); -} - -// Tests end_write() with a different size than what was specified in -// start_write(). -void test_end_write_with_different_size(void) { - static const size_t START_WRITE_SIZE = 10; - static const size_t END_WRITE_SIZE = 7; - printf("Starting test: end write with different size\n"); - setup_test(0); - void* record_written = census_log_start_write(START_WRITE_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, END_WRITE_SIZE); - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(END_WRITE_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Verifies that pending records are not available via read_next(). -void test_read_pending_record(void) { - static const size_t PR_RECORD_SIZE = 1024; - printf("Starting test: read pending record\n"); - setup_test(0); - // Start a write. - void* record_written = census_log_start_write(PR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - // As write is pending, read should fail. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - // A read followed by end_write() should succeed. - census_log_end_write(record_written, PR_RECORD_SIZE); - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(PR_RECORD_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Tries reading beyond pending write. -void test_read_beyond_pending_record(void) { - printf("Starting test: read beyond pending record\n"); - setup_test(0); - // Start a write. - const size_t incomplete_record_size = 10; - void* incomplete_record = census_log_start_write(incomplete_record_size); - GPR_ASSERT(incomplete_record != NULL); - const size_t complete_record_size = 20; - void* complete_record = census_log_start_write(complete_record_size); - GPR_ASSERT(complete_record != NULL); - GPR_ASSERT(complete_record != incomplete_record); - census_log_end_write(complete_record, complete_record_size); - // Now iterate over blocks to read completed records. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(complete_record == record_read); - GPR_ASSERT(complete_record_size == bytes_available); - // Complete first record. - census_log_end_write(incomplete_record, incomplete_record_size); - // Have read past the incomplete record, so read_next() should return NULL. - // NB: this test also assumes our thread did not get switched to a different - // CPU between the two start_write calls - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - // Reset reader to get the newly completed record. - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(incomplete_record == record_read); - GPR_ASSERT(incomplete_record_size == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -// Tests scenario where block being read is detached from a core and put on the -// dirty list. -void test_detached_while_reading(void) { - printf("Starting test: detached while reading\n"); - setup_test(0); - // Start a write. - static const size_t DWR_RECORD_SIZE = 10; - void* record_written = census_log_start_write(DWR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, DWR_RECORD_SIZE); - // Read this record. - census_log_init_reader(); - size_t bytes_available; - const void* record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read != NULL); - GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); - // Now fill the log. This will move the block being read from core-local - // array to the dirty list. - while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { - census_log_end_write(record_written, DWR_RECORD_SIZE); - } - - // In this iteration, read_next() should only traverse blocks in the - // core-local array. Therefore, we expect at most gpr_cpu_num_cores() more - // blocks. As log is full, if read_next() is traversing the dirty list, we - // will get more than gpr_cpu_num_cores() blocks. - int block_read = 0; - while ((record_read = census_log_read_next(&bytes_available))) { - ++block_read; - GPR_ASSERT(block_read <= (int)gpr_cpu_num_cores()); - } - census_log_shutdown(); -} - -// Fills non-circular log with records sized such that size is a multiple of -// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). -void test_fill_log_no_fragmentation(void) { - printf("Starting test: fill log no fragmentation\n"); - const int circular = 0; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -// Fills circular log with records sized such that size is a multiple of -// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). -void test_fill_circular_log_no_fragmentation(void) { - printf("Starting test: fill circular log no fragmentation\n"); - const int circular = 1; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -// Fills non-circular log with records that may straddle end of a block. -void test_fill_log_with_straddling_records(void) { - printf("Starting test: fill log with straddling records\n"); - const int circular = 0; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -// Fills circular log with records that may straddle end of a block. -void test_fill_circular_log_with_straddling_records(void) { - printf("Starting test: fill circular log with straddling records\n"); - const int circular = 1; - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -// Tests scenario where multiple writers and a single reader are using a log -// that is configured to discard old records. -void test_multiple_writers_circular_log(void) { - printf("Starting test: multiple writers circular log\n"); - const int circular = 1; - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -// Tests scenario where multiple writers and a single reader are using a log -// that is configured to discard old records. -void test_multiple_writers(void) { - printf("Starting test: multiple writers\n"); - const int circular = 0; - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -// Repeat the straddling records and multiple writers tests with a small log. -void test_small_log(void) { - printf("Starting test: small log\n"); - const int circular = 0; - census_log_initialize(0, circular); - size_t log_size = census_log_remaining_space(); - GPR_ASSERT(log_size > 0); - fill_log(log_size, 0, circular); - census_log_shutdown(); - census_log_initialize(0, circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -void test_performance(void) { - for (size_t write_size = 1; write_size < CENSUS_LOG_MAX_RECORD_SIZE; - write_size *= 2) { - setup_test(0); - gpr_timespec start_time = gpr_now(GPR_CLOCK_REALTIME); - int nrecords = 0; - while (1) { - void* record = census_log_start_write(write_size); - if (record == NULL) { - break; - } - census_log_end_write(record, write_size); - nrecords++; - } - gpr_timespec write_time = - gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); - double write_time_micro = - (double)write_time.tv_sec * 1000000 + (double)write_time.tv_nsec / 1000; - census_log_shutdown(); - printf( - "Wrote %d %d byte records in %.3g microseconds: %g records/us " - "(%g ns/record), %g gigabytes/s\n", - nrecords, (int)write_size, write_time_micro, - nrecords / write_time_micro, 1000 * write_time_micro / nrecords, - (double)((int)write_size * nrecords) / write_time_micro / 1000); - } -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - gpr_time_init(); - srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_invalid_record_size(); - test_end_write_with_different_size(); - test_read_pending_record(); - test_read_beyond_pending_record(); - test_detached_while_reading(); - test_fill_log_no_fragmentation(); - test_fill_circular_log_no_fragmentation(); - test_fill_log_with_straddling_records(); - test_fill_circular_log_with_straddling_records(); - test_small_log(); - test_multiple_writers(); - test_multiple_writers_circular_log(); - test_performance(); - return 0; -} diff --git a/test/core/census/mlog_test.cc b/test/core/census/mlog_test.cc new file mode 100644 index 0000000000..968fd91da4 --- /dev/null +++ b/test/core/census/mlog_test.cc @@ -0,0 +1,574 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/census/mlog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +// Change this to non-zero if you want more output. +#define VERBOSE 0 + +// Log size to use for all tests. +#define LOG_SIZE_IN_MB 1 +#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) + +// Fills in 'record' of size 'size'. Each byte in record is filled in with the +// same value. The value is extracted from 'record' pointer. +static void write_record(char* record, size_t size) { + char data = (char)((uintptr_t)record % 255); + memset(record, data, size); +} + +// Reads fixed size records. Returns the number of records read in +// 'num_records'. +static void read_records(size_t record_size, const char* buffer, + size_t buffer_size, int* num_records) { + GPR_ASSERT(buffer_size >= record_size); + GPR_ASSERT(buffer_size % record_size == 0); + *num_records = (int)(buffer_size / record_size); + for (int i = 0; i < *num_records; ++i) { + const char* record = buffer + (record_size * (size_t)i); + char data = (char)((uintptr_t)record % 255); + for (size_t j = 0; j < record_size; ++j) { + GPR_ASSERT(data == record[j]); + } + } +} + +// Tries to write the specified number of records. Stops when the log gets +// full. Returns the number of records written. Spins for random +// number of times, up to 'max_spin_count', between writes. +static int write_records_to_log(int writer_id, size_t record_size, + int num_records, int max_spin_count) { + int counter = 0; + for (int i = 0; i < num_records; ++i) { + int spin_count = max_spin_count ? rand() % max_spin_count : 0; + if (VERBOSE && (counter++ == num_records / 10)) { + printf(" Writer %d: %d out of %d written\n", writer_id, i, num_records); + counter = 0; + } + char* record = (char*)(census_log_start_write(record_size)); + if (record == NULL) { + return i; + } + write_record(record, record_size); + census_log_end_write(record, record_size); + for (int j = 0; j < spin_count; ++j) { + GPR_ASSERT(j >= 0); + } + } + return num_records; +} + +// Performs a single read iteration. Returns the number of records read. +static int perform_read_iteration(size_t record_size) { + const void* read_buffer = NULL; + size_t bytes_available; + int records_read = 0; + census_log_init_reader(); + while ((read_buffer = census_log_read_next(&bytes_available))) { + int num_records = 0; + read_records(record_size, (const char*)read_buffer, bytes_available, + &num_records); + records_read += num_records; + } + return records_read; +} + +// Asserts that the log is empty. +static void assert_log_empty(void) { + census_log_init_reader(); + size_t bytes_available; + GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); +} + +// Fills the log and verifies data. If 'no fragmentation' is true, records +// are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record +// size. If not a circular log, verifies that the number of records written +// match the number of records read. +static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { + size_t size; + if (no_fragmentation) { + int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); + size = ((size_t)1 << log2size); + } else { + while (1) { + size = 1 + ((size_t)rand() % CENSUS_LOG_MAX_RECORD_SIZE); + if (CENSUS_LOG_MAX_RECORD_SIZE % size) { + break; + } + } + } + int records_written = + write_records_to_log(0 /* writer id */, size, + (int)((log_size / size) * 2), 0 /* spin count */); + int records_read = perform_read_iteration(size); + if (!circular_log) { + GPR_ASSERT(records_written == records_read); + } + assert_log_empty(); +} + +// Structure to pass args to writer_thread +typedef struct writer_thread_args { + // Index of this thread in the writers vector. + int index; + // Record size. + size_t record_size; + // Number of records to write. + int num_records; + // Used to signal when writer is complete + gpr_cv* done; + gpr_mu* mu; + int* count; +} writer_thread_args; + +// Writes the given number of records of random size (up to kMaxRecordSize) and +// random data to the specified log. +static void writer_thread(void* arg) { + writer_thread_args* args = (writer_thread_args*)arg; + // Maximum number of times to spin between writes. + static const int MAX_SPIN_COUNT = 50; + int records_written = 0; + if (VERBOSE) { + printf(" Writer %d starting\n", args->index); + } + while (records_written < args->num_records) { + records_written += write_records_to_log(args->index, args->record_size, + args->num_records - records_written, + MAX_SPIN_COUNT); + if (records_written < args->num_records) { + // Ran out of log space. Sleep for a bit and let the reader catch up. + // This should never happen for circular logs. + if (VERBOSE) { + printf( + " Writer %d stalled due to out-of-space: %d out of %d " + "written\n", + args->index, records_written, args->num_records); + } + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); + } + } + // Done. Decrement count and signal. + gpr_mu_lock(args->mu); + (*args->count)--; + gpr_cv_signal(args->done); + if (VERBOSE) { + printf(" Writer %d done\n", args->index); + } + gpr_mu_unlock(args->mu); +} + +// struct to pass args to reader_thread +typedef struct reader_thread_args { + // Record size. + size_t record_size; + // Interval between read iterations. + int read_iteration_interval_in_msec; + // Total number of records. + int total_records; + // Signalled when reader should stop. + gpr_cv stop; + int stop_flag; + // Used to signal when reader has finished + gpr_cv* done; + gpr_mu* mu; + int running; +} reader_thread_args; + +// Reads and verifies the specified number of records. Reader can also be +// stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' +// between read iterations. +static void reader_thread(void* arg) { + reader_thread_args* args = (reader_thread_args*)arg; + if (VERBOSE) { + printf(" Reader starting\n"); + } + gpr_timespec interval = gpr_time_from_micros( + args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); + gpr_mu_lock(args->mu); + int records_read = 0; + int num_iterations = 0; + int counter = 0; + while (!args->stop_flag && records_read < args->total_records) { + gpr_cv_wait(&args->stop, args->mu, interval); + if (!args->stop_flag) { + records_read += perform_read_iteration(args->record_size); + GPR_ASSERT(records_read <= args->total_records); + if (VERBOSE && (counter++ == 100000)) { + printf(" Reader: %d out of %d read\n", records_read, + args->total_records); + counter = 0; + } + ++num_iterations; + } + } + // Done + args->running = 0; + gpr_cv_signal(args->done); + if (VERBOSE) { + printf(" Reader: records: %d, iterations: %d\n", records_read, + num_iterations); + } + gpr_mu_unlock(args->mu); +} + +// Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER +// records. Also, starts a reader that iterates over and reads blocks every +// READ_ITERATION_INTERVAL_IN_MSEC. +// Number of writers. +#define NUM_WRITERS 5 +static void multiple_writers_single_reader(int circular_log) { + // Sleep interval between read iterations. + static const int READ_ITERATION_INTERVAL_IN_MSEC = 10; + // Maximum record size. + static const size_t MAX_RECORD_SIZE = 20; + // Number of records written by each writer. This is sized such that we + // will write through the entire log ~10 times. + const int NUM_RECORDS_PER_WRITER = + (int)((10 * census_log_remaining_space()) / (MAX_RECORD_SIZE / 2)) / + NUM_WRITERS; + size_t record_size = ((size_t)rand() % MAX_RECORD_SIZE) + 1; + // Create and start writers. + writer_thread_args writers[NUM_WRITERS]; + int writers_count = NUM_WRITERS; + gpr_cv writers_done; + gpr_mu writers_mu; // protects writers_done and writers_count + gpr_cv_init(&writers_done); + gpr_mu_init(&writers_mu); + gpr_thd_id id; + for (int i = 0; i < NUM_WRITERS; ++i) { + writers[i].index = i; + writers[i].record_size = record_size; + writers[i].num_records = NUM_RECORDS_PER_WRITER; + writers[i].done = &writers_done; + writers[i].count = &writers_count; + writers[i].mu = &writers_mu; + gpr_thd_new(&id, &writer_thread, &writers[i], NULL); + } + // Start reader. + gpr_cv reader_done; + gpr_mu reader_mu; // protects reader_done and reader.running + reader_thread_args reader; + reader.record_size = record_size; + reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; + reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; + reader.stop_flag = 0; + gpr_cv_init(&reader.stop); + gpr_cv_init(&reader_done); + reader.done = &reader_done; + gpr_mu_init(&reader_mu); + reader.mu = &reader_mu; + reader.running = 1; + gpr_thd_new(&id, &reader_thread, &reader, NULL); + // Wait for writers to finish. + gpr_mu_lock(&writers_mu); + while (writers_count != 0) { + gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&writers_mu); + gpr_mu_destroy(&writers_mu); + gpr_cv_destroy(&writers_done); + gpr_mu_lock(&reader_mu); + if (circular_log) { + // Stop reader. + reader.stop_flag = 1; + gpr_cv_signal(&reader.stop); + } + // wait for reader to finish + while (reader.running) { + gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + if (circular_log) { + // Assert that there were no out-of-space errors. + GPR_ASSERT(0 == census_log_out_of_space_count()); + } + gpr_mu_unlock(&reader_mu); + gpr_mu_destroy(&reader_mu); + gpr_cv_destroy(&reader_done); + if (VERBOSE) { + printf(" Reader: finished\n"); + } +} + +static void setup_test(int circular_log) { + census_log_initialize(LOG_SIZE_IN_MB, circular_log); + // GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); +} + +// Attempts to create a record of invalid size (size > +// CENSUS_LOG_MAX_RECORD_SIZE). +void test_invalid_record_size(void) { + static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; + static const size_t VALID_SIZE = 1; + printf("Starting test: invalid record size\n"); + setup_test(0); + void* record = census_log_start_write(INVALID_SIZE); + GPR_ASSERT(record == NULL); + // Now try writing a valid record. + record = census_log_start_write(VALID_SIZE); + GPR_ASSERT(record != NULL); + census_log_end_write(record, VALID_SIZE); + // Verifies that available space went down by one block. In theory, this + // check can fail if the thread is context switched to a new CPU during the + // start_write execution (multiple blocks get allocated), but this has not + // been observed in practice. + // GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == + // census_log_remaining_space()); + census_log_shutdown(); +} + +// Tests end_write() with a different size than what was specified in +// start_write(). +void test_end_write_with_different_size(void) { + static const size_t START_WRITE_SIZE = 10; + static const size_t END_WRITE_SIZE = 7; + printf("Starting test: end write with different size\n"); + setup_test(0); + void* record_written = census_log_start_write(START_WRITE_SIZE); + GPR_ASSERT(record_written != NULL); + census_log_end_write(record_written, END_WRITE_SIZE); + census_log_init_reader(); + size_t bytes_available; + const void* record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_written == record_read); + GPR_ASSERT(END_WRITE_SIZE == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +// Verifies that pending records are not available via read_next(). +void test_read_pending_record(void) { + static const size_t PR_RECORD_SIZE = 1024; + printf("Starting test: read pending record\n"); + setup_test(0); + // Start a write. + void* record_written = census_log_start_write(PR_RECORD_SIZE); + GPR_ASSERT(record_written != NULL); + // As write is pending, read should fail. + census_log_init_reader(); + size_t bytes_available; + const void* record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read == NULL); + // A read followed by end_write() should succeed. + census_log_end_write(record_written, PR_RECORD_SIZE); + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_written == record_read); + GPR_ASSERT(PR_RECORD_SIZE == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +// Tries reading beyond pending write. +void test_read_beyond_pending_record(void) { + printf("Starting test: read beyond pending record\n"); + setup_test(0); + // Start a write. + const size_t incomplete_record_size = 10; + void* incomplete_record = census_log_start_write(incomplete_record_size); + GPR_ASSERT(incomplete_record != NULL); + const size_t complete_record_size = 20; + void* complete_record = census_log_start_write(complete_record_size); + GPR_ASSERT(complete_record != NULL); + GPR_ASSERT(complete_record != incomplete_record); + census_log_end_write(complete_record, complete_record_size); + // Now iterate over blocks to read completed records. + census_log_init_reader(); + size_t bytes_available; + const void* record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(complete_record == record_read); + GPR_ASSERT(complete_record_size == bytes_available); + // Complete first record. + census_log_end_write(incomplete_record, incomplete_record_size); + // Have read past the incomplete record, so read_next() should return NULL. + // NB: this test also assumes our thread did not get switched to a different + // CPU between the two start_write calls + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read == NULL); + // Reset reader to get the newly completed record. + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(incomplete_record == record_read); + GPR_ASSERT(incomplete_record_size == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +// Tests scenario where block being read is detached from a core and put on the +// dirty list. +void test_detached_while_reading(void) { + printf("Starting test: detached while reading\n"); + setup_test(0); + // Start a write. + static const size_t DWR_RECORD_SIZE = 10; + void* record_written = census_log_start_write(DWR_RECORD_SIZE); + GPR_ASSERT(record_written != NULL); + census_log_end_write(record_written, DWR_RECORD_SIZE); + // Read this record. + census_log_init_reader(); + size_t bytes_available; + const void* record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read != NULL); + GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); + // Now fill the log. This will move the block being read from core-local + // array to the dirty list. + while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { + census_log_end_write(record_written, DWR_RECORD_SIZE); + } + + // In this iteration, read_next() should only traverse blocks in the + // core-local array. Therefore, we expect at most gpr_cpu_num_cores() more + // blocks. As log is full, if read_next() is traversing the dirty list, we + // will get more than gpr_cpu_num_cores() blocks. + int block_read = 0; + while ((record_read = census_log_read_next(&bytes_available))) { + ++block_read; + GPR_ASSERT(block_read <= (int)gpr_cpu_num_cores()); + } + census_log_shutdown(); +} + +// Fills non-circular log with records sized such that size is a multiple of +// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). +void test_fill_log_no_fragmentation(void) { + printf("Starting test: fill log no fragmentation\n"); + const int circular = 0; + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); + census_log_shutdown(); +} + +// Fills circular log with records sized such that size is a multiple of +// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). +void test_fill_circular_log_no_fragmentation(void) { + printf("Starting test: fill circular log no fragmentation\n"); + const int circular = 1; + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); + census_log_shutdown(); +} + +// Fills non-circular log with records that may straddle end of a block. +void test_fill_log_with_straddling_records(void) { + printf("Starting test: fill log with straddling records\n"); + const int circular = 0; + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); + census_log_shutdown(); +} + +// Fills circular log with records that may straddle end of a block. +void test_fill_circular_log_with_straddling_records(void) { + printf("Starting test: fill circular log with straddling records\n"); + const int circular = 1; + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); + census_log_shutdown(); +} + +// Tests scenario where multiple writers and a single reader are using a log +// that is configured to discard old records. +void test_multiple_writers_circular_log(void) { + printf("Starting test: multiple writers circular log\n"); + const int circular = 1; + setup_test(circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +// Tests scenario where multiple writers and a single reader are using a log +// that is configured to discard old records. +void test_multiple_writers(void) { + printf("Starting test: multiple writers\n"); + const int circular = 0; + setup_test(circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +// Repeat the straddling records and multiple writers tests with a small log. +void test_small_log(void) { + printf("Starting test: small log\n"); + const int circular = 0; + census_log_initialize(0, circular); + size_t log_size = census_log_remaining_space(); + GPR_ASSERT(log_size > 0); + fill_log(log_size, 0, circular); + census_log_shutdown(); + census_log_initialize(0, circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +void test_performance(void) { + for (size_t write_size = 1; write_size < CENSUS_LOG_MAX_RECORD_SIZE; + write_size *= 2) { + setup_test(0); + gpr_timespec start_time = gpr_now(GPR_CLOCK_REALTIME); + int nrecords = 0; + while (1) { + void* record = census_log_start_write(write_size); + if (record == NULL) { + break; + } + census_log_end_write(record, write_size); + nrecords++; + } + gpr_timespec write_time = + gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); + double write_time_micro = + (double)write_time.tv_sec * 1000000 + (double)write_time.tv_nsec / 1000; + census_log_shutdown(); + printf( + "Wrote %d %d byte records in %.3g microseconds: %g records/us " + "(%g ns/record), %g gigabytes/s\n", + nrecords, (int)write_size, write_time_micro, + nrecords / write_time_micro, 1000 * write_time_micro / nrecords, + (double)((int)write_size * nrecords) / write_time_micro / 1000); + } +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + gpr_time_init(); + srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_invalid_record_size(); + test_end_write_with_different_size(); + test_read_pending_record(); + test_read_beyond_pending_record(); + test_detached_while_reading(); + test_fill_log_no_fragmentation(); + test_fill_circular_log_no_fragmentation(); + test_fill_log_with_straddling_records(); + test_fill_circular_log_with_straddling_records(); + test_small_log(); + test_multiple_writers(); + test_multiple_writers_circular_log(); + test_performance(); + return 0; +} diff --git a/test/core/census/resource_test.c b/test/core/census/resource_test.c deleted file mode 100644 index 48fc43e45b..0000000000 --- a/test/core/census/resource_test.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/resource.h" -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/census/base_resources.h" -#include "test/core/util/test_config.h" - -// Test all the functionality for dealing with Resources. - -// Just startup and shutdown resources subsystem. -static void test_enable_disable() { - initialize_resources(); - shutdown_resources(); -} - -// A blank/empty initialization should not work. -static void test_empty_definition() { - initialize_resources(); - int32_t rid = census_define_resource(NULL, 0); - GPR_ASSERT(rid == -1); - uint8_t buffer[50] = {0}; - rid = census_define_resource(buffer, 50); - GPR_ASSERT(rid == -1); - shutdown_resources(); -} - -// Given a file name, read raw proto and define the resource included within. -// Returns resource id from census_define_resource(). -static int32_t define_resource_from_file(const char *file) { -#define BUF_SIZE 512 - uint8_t buffer[BUF_SIZE]; - FILE *input = fopen(file, "rb"); - GPR_ASSERT(input != NULL); - size_t nbytes = fread(buffer, 1, BUF_SIZE, input); - GPR_ASSERT(nbytes != 0 && nbytes < BUF_SIZE && feof(input) && !ferror(input)); - int32_t rid = census_define_resource(buffer, nbytes); - GPR_ASSERT(fclose(input) == 0); - return rid; -} - -// Test definition of a single resource, using a proto read from a file. The -// `succeed` parameter indicates whether we expect the definition to succeed or -// fail. `name` is used to check that the returned resource can be looked up by -// name. -static void test_define_single_resource(const char *file, const char *name, - bool succeed) { - gpr_log(GPR_INFO, "Test defining resource \"%s\"\n", name); - initialize_resources(); - int32_t rid = define_resource_from_file(file); - if (succeed) { - GPR_ASSERT(rid >= 0); - int32_t rid2 = census_resource_id(name); - GPR_ASSERT(rid == rid2); - } else { - GPR_ASSERT(rid < 0); - } - shutdown_resources(); -} - -// Try deleting various resources (both those that exist and those that don't). -static void test_delete_resource(const char *minimal_good, const char *full) { - initialize_resources(); - // Try deleting resource before any are defined. - census_delete_resource(0); - // Create and check a couple of resources. - int32_t rid1 = define_resource_from_file(minimal_good); - int32_t rid2 = define_resource_from_file(full); - GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); - int32_t rid3 = census_resource_id("minimal_good"); - int32_t rid4 = census_resource_id("full_resource"); - GPR_ASSERT(rid1 == rid3 && rid2 == rid4); - // Try deleting non-existant resources. - census_delete_resource(-1); - census_delete_resource(rid1 + rid2 + 1); - census_delete_resource(10000000); - // Delete one of the previously defined resources and check for deletion. - census_delete_resource(rid1); - rid3 = census_resource_id("minimal_good"); - GPR_ASSERT(rid3 < 0); - // Check that re-adding works. - rid1 = define_resource_from_file(minimal_good); - GPR_ASSERT(rid1 >= 0); - rid3 = census_resource_id("minimal_good"); - GPR_ASSERT(rid1 == rid3); - shutdown_resources(); -} - -// Test define base resources. -static void test_base_resources() { - initialize_resources(); - define_base_resources(); - int32_t rid1 = census_resource_id("client_rpc_latency"); - int32_t rid2 = census_resource_id("server_rpc_latency"); - GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); - shutdown_resources(); -} - -int main(int argc, char **argv) { - const char *resource_empty_name_pb, *resource_full_pb, - *resource_minimal_good_pb, *resource_no_name_pb, - *resource_no_numerator_pb, *resource_no_unit_pb; - if (argc == 7) { - resource_empty_name_pb = argv[1]; - resource_full_pb = argv[2]; - resource_minimal_good_pb = argv[3]; - resource_no_name_pb = argv[4]; - resource_no_numerator_pb = argv[5]; - resource_no_unit_pb = argv[6]; - } else { - GPR_ASSERT(argc == 1); - resource_empty_name_pb = "test/core/census/data/resource_empty_name.pb"; - resource_full_pb = "test/core/census/data/resource_full.pb"; - resource_minimal_good_pb = "test/core/census/data/resource_minimal_good.pb"; - resource_no_name_pb = "test/core/census/data/resource_no_name.pb"; - resource_no_numerator_pb = "test/core/census/data/resource_no_numerator.pb"; - resource_no_unit_pb = "test/core/census/data/resource_no_unit.pb"; - } - grpc_test_init(argc, argv); - test_enable_disable(); - test_empty_definition(); - test_define_single_resource(resource_minimal_good_pb, "minimal_good", true); - test_define_single_resource(resource_full_pb, "full_resource", true); - test_define_single_resource(resource_no_name_pb, "resource_no_name", false); - test_define_single_resource(resource_no_numerator_pb, "resource_no_numerator", - false); - test_define_single_resource(resource_no_unit_pb, "resource_no_unit", false); - test_define_single_resource(resource_empty_name_pb, "resource_empty_name", - false); - test_delete_resource(resource_minimal_good_pb, resource_full_pb); - test_base_resources(); - return 0; -} diff --git a/test/core/census/resource_test.cc b/test/core/census/resource_test.cc new file mode 100644 index 0000000000..48fc43e45b --- /dev/null +++ b/test/core/census/resource_test.cc @@ -0,0 +1,154 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/census/resource.h" +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/census/base_resources.h" +#include "test/core/util/test_config.h" + +// Test all the functionality for dealing with Resources. + +// Just startup and shutdown resources subsystem. +static void test_enable_disable() { + initialize_resources(); + shutdown_resources(); +} + +// A blank/empty initialization should not work. +static void test_empty_definition() { + initialize_resources(); + int32_t rid = census_define_resource(NULL, 0); + GPR_ASSERT(rid == -1); + uint8_t buffer[50] = {0}; + rid = census_define_resource(buffer, 50); + GPR_ASSERT(rid == -1); + shutdown_resources(); +} + +// Given a file name, read raw proto and define the resource included within. +// Returns resource id from census_define_resource(). +static int32_t define_resource_from_file(const char *file) { +#define BUF_SIZE 512 + uint8_t buffer[BUF_SIZE]; + FILE *input = fopen(file, "rb"); + GPR_ASSERT(input != NULL); + size_t nbytes = fread(buffer, 1, BUF_SIZE, input); + GPR_ASSERT(nbytes != 0 && nbytes < BUF_SIZE && feof(input) && !ferror(input)); + int32_t rid = census_define_resource(buffer, nbytes); + GPR_ASSERT(fclose(input) == 0); + return rid; +} + +// Test definition of a single resource, using a proto read from a file. The +// `succeed` parameter indicates whether we expect the definition to succeed or +// fail. `name` is used to check that the returned resource can be looked up by +// name. +static void test_define_single_resource(const char *file, const char *name, + bool succeed) { + gpr_log(GPR_INFO, "Test defining resource \"%s\"\n", name); + initialize_resources(); + int32_t rid = define_resource_from_file(file); + if (succeed) { + GPR_ASSERT(rid >= 0); + int32_t rid2 = census_resource_id(name); + GPR_ASSERT(rid == rid2); + } else { + GPR_ASSERT(rid < 0); + } + shutdown_resources(); +} + +// Try deleting various resources (both those that exist and those that don't). +static void test_delete_resource(const char *minimal_good, const char *full) { + initialize_resources(); + // Try deleting resource before any are defined. + census_delete_resource(0); + // Create and check a couple of resources. + int32_t rid1 = define_resource_from_file(minimal_good); + int32_t rid2 = define_resource_from_file(full); + GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); + int32_t rid3 = census_resource_id("minimal_good"); + int32_t rid4 = census_resource_id("full_resource"); + GPR_ASSERT(rid1 == rid3 && rid2 == rid4); + // Try deleting non-existant resources. + census_delete_resource(-1); + census_delete_resource(rid1 + rid2 + 1); + census_delete_resource(10000000); + // Delete one of the previously defined resources and check for deletion. + census_delete_resource(rid1); + rid3 = census_resource_id("minimal_good"); + GPR_ASSERT(rid3 < 0); + // Check that re-adding works. + rid1 = define_resource_from_file(minimal_good); + GPR_ASSERT(rid1 >= 0); + rid3 = census_resource_id("minimal_good"); + GPR_ASSERT(rid1 == rid3); + shutdown_resources(); +} + +// Test define base resources. +static void test_base_resources() { + initialize_resources(); + define_base_resources(); + int32_t rid1 = census_resource_id("client_rpc_latency"); + int32_t rid2 = census_resource_id("server_rpc_latency"); + GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2); + shutdown_resources(); +} + +int main(int argc, char **argv) { + const char *resource_empty_name_pb, *resource_full_pb, + *resource_minimal_good_pb, *resource_no_name_pb, + *resource_no_numerator_pb, *resource_no_unit_pb; + if (argc == 7) { + resource_empty_name_pb = argv[1]; + resource_full_pb = argv[2]; + resource_minimal_good_pb = argv[3]; + resource_no_name_pb = argv[4]; + resource_no_numerator_pb = argv[5]; + resource_no_unit_pb = argv[6]; + } else { + GPR_ASSERT(argc == 1); + resource_empty_name_pb = "test/core/census/data/resource_empty_name.pb"; + resource_full_pb = "test/core/census/data/resource_full.pb"; + resource_minimal_good_pb = "test/core/census/data/resource_minimal_good.pb"; + resource_no_name_pb = "test/core/census/data/resource_no_name.pb"; + resource_no_numerator_pb = "test/core/census/data/resource_no_numerator.pb"; + resource_no_unit_pb = "test/core/census/data/resource_no_unit.pb"; + } + grpc_test_init(argc, argv); + test_enable_disable(); + test_empty_definition(); + test_define_single_resource(resource_minimal_good_pb, "minimal_good", true); + test_define_single_resource(resource_full_pb, "full_resource", true); + test_define_single_resource(resource_no_name_pb, "resource_no_name", false); + test_define_single_resource(resource_no_numerator_pb, "resource_no_numerator", + false); + test_define_single_resource(resource_no_unit_pb, "resource_no_unit", false); + test_define_single_resource(resource_empty_name_pb, "resource_empty_name", + false); + test_delete_resource(resource_minimal_good_pb, resource_full_pb); + test_base_resources(); + return 0; +} diff --git a/test/core/census/trace_context_test.c b/test/core/census/trace_context_test.c deleted file mode 100644 index 6eb831a85e..0000000000 --- a/test/core/census/trace_context_test.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/census/base_resources.h" -#include "src/core/ext/census/resource.h" -#include "test/core/util/test_config.h" - -#include "src/core/ext/census/gen/trace_context.pb.h" -#include "src/core/ext/census/trace_context.h" -#include "third_party/nanopb/pb_decode.h" -#include "third_party/nanopb/pb_encode.h" - -#define BUF_SIZE 256 - -/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it -to a second TraceContext (ctxt2). Validates that the resulting TraceContext -has a span_id, trace_id, and that the values are equal to those in initial -TraceContext. On success, returns true. If encode_trace_context returns 0, -decode_trace_context fails, or the resulting TraceContext is missing a trace_id -or span_id, it will return false. */ -bool validate_encode_decode_context(google_trace_TraceContext *ctxt1, - uint8_t *buffer, size_t buf_size) { - google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; - size_t msg_length; - - msg_length = encode_trace_context(ctxt1, buffer, buf_size); - if (msg_length == 0) { - return false; - } - - if (!decode_trace_context(&ctxt2, buffer, msg_length)) { - return false; - } - - if (!ctxt2.has_trace_id_hi || !ctxt2.has_trace_id_lo || !ctxt2.has_span_id) { - return false; - } - - GPR_ASSERT(ctxt1->trace_id_hi == ctxt2.trace_id_hi && - ctxt1->trace_id_lo == ctxt2.trace_id_lo && - ctxt1->span_id == ctxt2.span_id && - ctxt1->has_span_options == ctxt2.has_span_options && - (ctxt1->has_span_options - ? ctxt1->span_options == ctxt2.span_options - : true)); - - return true; -} - -/* Decodes a proto-encoded TraceContext from a buffer. If decode_trace_context -fails or the resulting TraceContext is missing a trace_id or span_id it will -return false, otherwise returns true. */ -bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer, - size_t msg_length) { - // Validate the decoding of a context written to buffer. - if (!decode_trace_context(ctxt, buffer, msg_length)) { - return false; - } - - if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo || !ctxt->has_span_id) { - return false; - } - - return true; -} - -/* Read an encoded trace context from a file. Validates that the decoding -gives the expected result (succeed). */ -static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt, - const char *file, - const bool succeed) { - uint8_t buffer[BUF_SIZE]; - FILE *input = fopen(file, "rb"); - GPR_ASSERT(input != NULL); - size_t nbytes = fread(buffer, 1, BUF_SIZE, input); - GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input)); - bool res = validate_decode_context(ctxt, buffer, nbytes); - GPR_ASSERT(res == succeed); - GPR_ASSERT(fclose(input) == 0); -} - -// Test full proto-buffer. -static void test_full() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_full.pb", true); -} - -// Test empty proto-buffer. -static void test_empty() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_empty.pb", false); -} - -// Test proto-buffer with only trace_id. -static void test_trace_only() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_trace_only.pb", false); -} - -// Test proto-buffer with only span_id. -static void test_span_only() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_span_only.pb", false); -} - -// Test proto-buffer without span_options value. -static void test_no_span_options() { - google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; - read_and_validate_context_from_file( - &ctxt, "test/core/census/data/context_no_span_options.pb", true); - GPR_ASSERT(ctxt.has_span_options == false && ctxt.span_options == 0); -} - -static void test_encode_decode() { - uint8_t buffer[BUF_SIZE] = {0}; - - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer)); - - // Missing trace_id. This should fail. - google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; - ctxt2.has_trace_id_hi = false; - ctxt2.has_trace_id_lo = false; - ctxt2.has_span_id = true; - validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer)); -} - -// Test a corrupted proto-buffer. This should fail. -static void test_corrupt() { - uint8_t buffer[BUF_SIZE] = {0}; - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - size_t msg_length; - - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - ctxt1.has_span_options = true; - ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; - msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); - - /* Corrupt some bytes. 255 (0xFF) should be illegal for the first byte of the - proto encoded object. */ - buffer[0] = 255; - - bool res = validate_decode_context(&ctxt1, buffer, msg_length); - GPR_ASSERT(res == false); -} - -static void test_buffer_size() { - // This buffer is too small. This should fail. - uint8_t buffer[16] = {0}; - google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; - size_t msg_length; - - ctxt1.has_trace_id_hi = true; - ctxt1.has_trace_id_lo = true; - ctxt1.trace_id_lo = 1; - ctxt1.trace_id_hi = 2; - ctxt1.has_span_id = true; - ctxt1.span_id = 3; - ctxt1.has_span_options = true; - ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; - msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); - - GPR_ASSERT(msg_length == 0); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_full(); - test_empty(); - test_trace_only(); - test_span_only(); - test_encode_decode(); - test_corrupt(); - test_no_span_options(); - test_buffer_size(); - - return 0; -} diff --git a/test/core/census/trace_context_test.cc b/test/core/census/trace_context_test.cc new file mode 100644 index 0000000000..6eb831a85e --- /dev/null +++ b/test/core/census/trace_context_test.cc @@ -0,0 +1,215 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/census/base_resources.h" +#include "src/core/ext/census/resource.h" +#include "test/core/util/test_config.h" + +#include "src/core/ext/census/gen/trace_context.pb.h" +#include "src/core/ext/census/trace_context.h" +#include "third_party/nanopb/pb_decode.h" +#include "third_party/nanopb/pb_encode.h" + +#define BUF_SIZE 256 + +/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it +to a second TraceContext (ctxt2). Validates that the resulting TraceContext +has a span_id, trace_id, and that the values are equal to those in initial +TraceContext. On success, returns true. If encode_trace_context returns 0, +decode_trace_context fails, or the resulting TraceContext is missing a trace_id +or span_id, it will return false. */ +bool validate_encode_decode_context(google_trace_TraceContext *ctxt1, + uint8_t *buffer, size_t buf_size) { + google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; + size_t msg_length; + + msg_length = encode_trace_context(ctxt1, buffer, buf_size); + if (msg_length == 0) { + return false; + } + + if (!decode_trace_context(&ctxt2, buffer, msg_length)) { + return false; + } + + if (!ctxt2.has_trace_id_hi || !ctxt2.has_trace_id_lo || !ctxt2.has_span_id) { + return false; + } + + GPR_ASSERT(ctxt1->trace_id_hi == ctxt2.trace_id_hi && + ctxt1->trace_id_lo == ctxt2.trace_id_lo && + ctxt1->span_id == ctxt2.span_id && + ctxt1->has_span_options == ctxt2.has_span_options && + (ctxt1->has_span_options + ? ctxt1->span_options == ctxt2.span_options + : true)); + + return true; +} + +/* Decodes a proto-encoded TraceContext from a buffer. If decode_trace_context +fails or the resulting TraceContext is missing a trace_id or span_id it will +return false, otherwise returns true. */ +bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer, + size_t msg_length) { + // Validate the decoding of a context written to buffer. + if (!decode_trace_context(ctxt, buffer, msg_length)) { + return false; + } + + if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo || !ctxt->has_span_id) { + return false; + } + + return true; +} + +/* Read an encoded trace context from a file. Validates that the decoding +gives the expected result (succeed). */ +static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt, + const char *file, + const bool succeed) { + uint8_t buffer[BUF_SIZE]; + FILE *input = fopen(file, "rb"); + GPR_ASSERT(input != NULL); + size_t nbytes = fread(buffer, 1, BUF_SIZE, input); + GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input)); + bool res = validate_decode_context(ctxt, buffer, nbytes); + GPR_ASSERT(res == succeed); + GPR_ASSERT(fclose(input) == 0); +} + +// Test full proto-buffer. +static void test_full() { + google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; + read_and_validate_context_from_file( + &ctxt, "test/core/census/data/context_full.pb", true); +} + +// Test empty proto-buffer. +static void test_empty() { + google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; + read_and_validate_context_from_file( + &ctxt, "test/core/census/data/context_empty.pb", false); +} + +// Test proto-buffer with only trace_id. +static void test_trace_only() { + google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; + read_and_validate_context_from_file( + &ctxt, "test/core/census/data/context_trace_only.pb", false); +} + +// Test proto-buffer with only span_id. +static void test_span_only() { + google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; + read_and_validate_context_from_file( + &ctxt, "test/core/census/data/context_span_only.pb", false); +} + +// Test proto-buffer without span_options value. +static void test_no_span_options() { + google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero; + read_and_validate_context_from_file( + &ctxt, "test/core/census/data/context_no_span_options.pb", true); + GPR_ASSERT(ctxt.has_span_options == false && ctxt.span_options == 0); +} + +static void test_encode_decode() { + uint8_t buffer[BUF_SIZE] = {0}; + + google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; + ctxt1.has_trace_id_hi = true; + ctxt1.has_trace_id_lo = true; + ctxt1.trace_id_lo = 1; + ctxt1.trace_id_hi = 2; + ctxt1.has_span_id = true; + ctxt1.span_id = 3; + validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer)); + + // Missing trace_id. This should fail. + google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero; + ctxt2.has_trace_id_hi = false; + ctxt2.has_trace_id_lo = false; + ctxt2.has_span_id = true; + validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer)); +} + +// Test a corrupted proto-buffer. This should fail. +static void test_corrupt() { + uint8_t buffer[BUF_SIZE] = {0}; + google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; + size_t msg_length; + + ctxt1.has_trace_id_hi = true; + ctxt1.has_trace_id_lo = true; + ctxt1.trace_id_lo = 1; + ctxt1.trace_id_hi = 2; + ctxt1.has_span_id = true; + ctxt1.span_id = 3; + ctxt1.has_span_options = true; + ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; + msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); + + /* Corrupt some bytes. 255 (0xFF) should be illegal for the first byte of the + proto encoded object. */ + buffer[0] = 255; + + bool res = validate_decode_context(&ctxt1, buffer, msg_length); + GPR_ASSERT(res == false); +} + +static void test_buffer_size() { + // This buffer is too small. This should fail. + uint8_t buffer[16] = {0}; + google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero; + size_t msg_length; + + ctxt1.has_trace_id_hi = true; + ctxt1.has_trace_id_lo = true; + ctxt1.trace_id_lo = 1; + ctxt1.trace_id_hi = 2; + ctxt1.has_span_id = true; + ctxt1.span_id = 3; + ctxt1.has_span_options = true; + ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED; + msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer)); + + GPR_ASSERT(msg_length == 0); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_full(); + test_empty(); + test_trace_only(); + test_span_only(); + test_encode_decode(); + test_corrupt(); + test_no_span_options(); + test_buffer_size(); + + return 0; +} diff --git a/test/core/channel/channel_args_test.c b/test/core/channel/channel_args_test.c deleted file mode 100644 index deaf2933ec..0000000000 --- a/test/core/channel/channel_args_test.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/util/test_config.h" - -static void test_create(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_arg arg_int; - grpc_arg arg_string; - grpc_arg to_add[2]; - grpc_channel_args *ch_args; - - arg_int.key = "int_arg"; - arg_int.type = GRPC_ARG_INTEGER; - arg_int.value.integer = 123; - - arg_string.key = "str key"; - arg_string.type = GRPC_ARG_STRING; - arg_string.value.string = "str value"; - - to_add[0] = arg_int; - to_add[1] = arg_string; - ch_args = grpc_channel_args_copy_and_add(NULL, to_add, 2); - - GPR_ASSERT(ch_args->num_args == 2); - GPR_ASSERT(strcmp(ch_args->args[0].key, arg_int.key) == 0); - GPR_ASSERT(ch_args->args[0].type == arg_int.type); - GPR_ASSERT(ch_args->args[0].value.integer == arg_int.value.integer); - - GPR_ASSERT(strcmp(ch_args->args[1].key, arg_string.key) == 0); - GPR_ASSERT(ch_args->args[1].type == arg_string.type); - GPR_ASSERT(strcmp(ch_args->args[1].value.string, arg_string.value.string) == - 0); - - grpc_channel_args_destroy(&exec_ctx, ch_args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_set_compression_algorithm(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *ch_args; - - ch_args = - grpc_channel_args_set_compression_algorithm(NULL, GRPC_COMPRESS_GZIP); - GPR_ASSERT(ch_args->num_args == 1); - GPR_ASSERT(strcmp(ch_args->args[0].key, - GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM) == 0); - GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_INTEGER); - - grpc_channel_args_destroy(&exec_ctx, ch_args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_compression_algorithm_states(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *ch_args, *ch_args_wo_gzip, *ch_args_wo_gzip_deflate; - unsigned states_bitset; - size_t i; - - ch_args = grpc_channel_args_copy_and_add(NULL, NULL, 0); - /* by default, all enabled */ - states_bitset = - (unsigned)grpc_channel_args_compression_algorithm_get_states(ch_args); - - for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { - GPR_ASSERT(GPR_BITGET(states_bitset, i)); - } - - /* disable gzip and deflate */ - ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( - &exec_ctx, &ch_args, GRPC_COMPRESS_GZIP, 0); - GPR_ASSERT(ch_args == ch_args_wo_gzip); - ch_args_wo_gzip_deflate = grpc_channel_args_compression_algorithm_set_state( - &exec_ctx, &ch_args_wo_gzip, GRPC_COMPRESS_DEFLATE, 0); - GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); - - states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( - ch_args_wo_gzip_deflate); - for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { - if (i == GRPC_COMPRESS_GZIP || i == GRPC_COMPRESS_DEFLATE) { - GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); - } else { - GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); - } - } - - /* re-enabled gzip only */ - ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( - &exec_ctx, &ch_args_wo_gzip_deflate, GRPC_COMPRESS_GZIP, 1); - GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); - - states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( - ch_args_wo_gzip); - for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { - if (i == GRPC_COMPRESS_DEFLATE) { - GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); - } else { - GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); - } - } - - grpc_channel_args_destroy(&exec_ctx, ch_args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_set_socket_mutator(void) { - grpc_channel_args *ch_args; - grpc_socket_mutator mutator; - grpc_socket_mutator_init(&mutator, NULL); - - ch_args = grpc_channel_args_set_socket_mutator(NULL, &mutator); - GPR_ASSERT(ch_args->num_args == 1); - GPR_ASSERT(strcmp(ch_args->args[0].key, GRPC_ARG_SOCKET_MUTATOR) == 0); - GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_POINTER); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, ch_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_create(); - test_set_compression_algorithm(); - test_compression_algorithm_states(); - test_set_socket_mutator(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/channel/channel_args_test.cc b/test/core/channel/channel_args_test.cc new file mode 100644 index 0000000000..08dd1f47e3 --- /dev/null +++ b/test/core/channel/channel_args_test.cc @@ -0,0 +1,155 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/util/test_config.h" + +static void test_create(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_arg arg_int; + grpc_arg arg_string; + grpc_arg to_add[2]; + grpc_channel_args *ch_args; + + arg_int.key = const_cast("int_arg"); + arg_int.type = GRPC_ARG_INTEGER; + arg_int.value.integer = 123; + + arg_string.key = const_cast("str key"); + arg_string.type = GRPC_ARG_STRING; + arg_string.value.string = const_cast("str value"); + + to_add[0] = arg_int; + to_add[1] = arg_string; + ch_args = grpc_channel_args_copy_and_add(NULL, to_add, 2); + + GPR_ASSERT(ch_args->num_args == 2); + GPR_ASSERT(strcmp(ch_args->args[0].key, arg_int.key) == 0); + GPR_ASSERT(ch_args->args[0].type == arg_int.type); + GPR_ASSERT(ch_args->args[0].value.integer == arg_int.value.integer); + + GPR_ASSERT(strcmp(ch_args->args[1].key, arg_string.key) == 0); + GPR_ASSERT(ch_args->args[1].type == arg_string.type); + GPR_ASSERT(strcmp(ch_args->args[1].value.string, arg_string.value.string) == + 0); + + grpc_channel_args_destroy(&exec_ctx, ch_args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_set_compression_algorithm(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *ch_args; + + ch_args = + grpc_channel_args_set_compression_algorithm(NULL, GRPC_COMPRESS_GZIP); + GPR_ASSERT(ch_args->num_args == 1); + GPR_ASSERT(strcmp(ch_args->args[0].key, + GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM) == 0); + GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_INTEGER); + + grpc_channel_args_destroy(&exec_ctx, ch_args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_compression_algorithm_states(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *ch_args, *ch_args_wo_gzip, *ch_args_wo_gzip_deflate; + unsigned states_bitset; + size_t i; + + ch_args = grpc_channel_args_copy_and_add(NULL, NULL, 0); + /* by default, all enabled */ + states_bitset = + (unsigned)grpc_channel_args_compression_algorithm_get_states(ch_args); + + for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + GPR_ASSERT(GPR_BITGET(states_bitset, i)); + } + + /* disable gzip and deflate */ + ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( + &exec_ctx, &ch_args, GRPC_COMPRESS_GZIP, 0); + GPR_ASSERT(ch_args == ch_args_wo_gzip); + ch_args_wo_gzip_deflate = grpc_channel_args_compression_algorithm_set_state( + &exec_ctx, &ch_args_wo_gzip, GRPC_COMPRESS_DEFLATE, 0); + GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); + + states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( + ch_args_wo_gzip_deflate); + for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (i == GRPC_COMPRESS_GZIP || i == GRPC_COMPRESS_DEFLATE) { + GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); + } else { + GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); + } + } + + /* re-enabled gzip only */ + ch_args_wo_gzip = grpc_channel_args_compression_algorithm_set_state( + &exec_ctx, &ch_args_wo_gzip_deflate, GRPC_COMPRESS_GZIP, 1); + GPR_ASSERT(ch_args_wo_gzip == ch_args_wo_gzip_deflate); + + states_bitset = (unsigned)grpc_channel_args_compression_algorithm_get_states( + ch_args_wo_gzip); + for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (i == GRPC_COMPRESS_DEFLATE) { + GPR_ASSERT(GPR_BITGET(states_bitset, i) == 0); + } else { + GPR_ASSERT(GPR_BITGET(states_bitset, i) != 0); + } + } + + grpc_channel_args_destroy(&exec_ctx, ch_args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_set_socket_mutator(void) { + grpc_channel_args *ch_args; + grpc_socket_mutator mutator; + grpc_socket_mutator_init(&mutator, NULL); + + ch_args = grpc_channel_args_set_socket_mutator(NULL, &mutator); + GPR_ASSERT(ch_args->num_args == 1); + GPR_ASSERT(strcmp(ch_args->args[0].key, GRPC_ARG_SOCKET_MUTATOR) == 0); + GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_POINTER); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, ch_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_create(); + test_set_compression_algorithm(); + test_compression_algorithm_states(); + test_set_socket_mutator(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/channel/channel_stack_builder_test.c b/test/core/channel/channel_stack_builder_test.c deleted file mode 100644 index 682efd1438..0000000000 --- a/test/core/channel/channel_stack_builder_test.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/channel/channel_stack_builder.h" - -#include -#include - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/channel_init.h" -#include "test/core/util/test_config.h" - -static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - return GRPC_ERROR_NONE; -} - -static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void channel_destroy_func(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) {} - -static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) {} - -static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op_batch *op) {} - -static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, - grpc_transport_op *op) { - if (op->disconnect_with_error != GRPC_ERROR_NONE) { - GRPC_ERROR_UNREF(op->disconnect_with_error); - } - GRPC_CLOSURE_SCHED(exec_ctx, op->on_consumed, GRPC_ERROR_NONE); -} - -bool g_replacement_fn_called = false; -bool g_original_fn_called = false; -void set_arg_once_fn(grpc_channel_stack *channel_stack, - grpc_channel_element *elem, void *arg) { - bool *called = arg; - // Make sure this function is only called once per arg. - GPR_ASSERT(*called == false); - *called = true; -} - -static void test_channel_stack_builder_filter_replace(void) { - grpc_channel *channel = - grpc_insecure_channel_create("target name isn't used", NULL, NULL); - GPR_ASSERT(channel != NULL); - // Make sure the high priority filter has been created. - GPR_ASSERT(g_replacement_fn_called); - // ... and that the low priority one hasn't. - GPR_ASSERT(!g_original_fn_called); - grpc_channel_destroy(channel); -} - -const grpc_channel_filter replacement_filter = { - call_func, - channel_func, - 0, - call_init_func, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - call_destroy_func, - 0, - channel_init_func, - channel_destroy_func, - grpc_channel_next_get_info, - "filter_name"}; - -const grpc_channel_filter original_filter = { - call_func, - channel_func, - 0, - call_init_func, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - call_destroy_func, - 0, - channel_init_func, - channel_destroy_func, - grpc_channel_next_get_info, - "filter_name"}; - -static bool add_replacement_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, - void *arg) { - const grpc_channel_filter *filter = arg; - // Get rid of any other version of the filter, as determined by having the - // same name. - GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder, filter->name)); - return grpc_channel_stack_builder_prepend_filter( - builder, filter, set_arg_once_fn, &g_replacement_fn_called); -} - -static bool add_original_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, - void *arg) { - return grpc_channel_stack_builder_prepend_filter( - builder, (const grpc_channel_filter *)arg, set_arg_once_fn, - &g_original_fn_called); -} - -static void init_plugin(void) { - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - add_original_filter, - (void *)&original_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - add_replacement_filter, - (void *)&replacement_filter); -} - -static void destroy_plugin(void) {} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_register_plugin(init_plugin, destroy_plugin); - grpc_init(); - test_channel_stack_builder_filter_replace(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/channel/channel_stack_builder_test.cc b/test/core/channel/channel_stack_builder_test.cc new file mode 100644 index 0000000000..f9129605e9 --- /dev/null +++ b/test/core/channel/channel_stack_builder_test.cc @@ -0,0 +1,147 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/channel/channel_stack_builder.h" + +#include +#include + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/channel_init.h" +#include "test/core/util/test_config.h" + +static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + return GRPC_ERROR_NONE; +} + +static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void channel_destroy_func(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) {} + +static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *op) {} + +static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, + grpc_transport_op *op) { + if (op->disconnect_with_error != GRPC_ERROR_NONE) { + GRPC_ERROR_UNREF(op->disconnect_with_error); + } + GRPC_CLOSURE_SCHED(exec_ctx, op->on_consumed, GRPC_ERROR_NONE); +} + +bool g_replacement_fn_called = false; +bool g_original_fn_called = false; +void set_arg_once_fn(grpc_channel_stack *channel_stack, + grpc_channel_element *elem, void *arg) { + bool *called = static_cast(arg); + // Make sure this function is only called once per arg. + GPR_ASSERT(*called == false); + *called = true; +} + +static void test_channel_stack_builder_filter_replace(void) { + grpc_channel *channel = + grpc_insecure_channel_create("target name isn't used", NULL, NULL); + GPR_ASSERT(channel != NULL); + // Make sure the high priority filter has been created. + GPR_ASSERT(g_replacement_fn_called); + // ... and that the low priority one hasn't. + GPR_ASSERT(!g_original_fn_called); + grpc_channel_destroy(channel); +} + +const grpc_channel_filter replacement_filter = { + call_func, + channel_func, + 0, + call_init_func, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + call_destroy_func, + 0, + channel_init_func, + channel_destroy_func, + grpc_channel_next_get_info, + "filter_name"}; + +const grpc_channel_filter original_filter = { + call_func, + channel_func, + 0, + call_init_func, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + call_destroy_func, + 0, + channel_init_func, + channel_destroy_func, + grpc_channel_next_get_info, + "filter_name"}; + +static bool add_replacement_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, + void *arg) { + const grpc_channel_filter *filter = + static_cast(arg); + // Get rid of any other version of the filter, as determined by having the + // same name. + GPR_ASSERT(grpc_channel_stack_builder_remove_filter(builder, filter->name)); + return grpc_channel_stack_builder_prepend_filter( + builder, filter, set_arg_once_fn, &g_replacement_fn_called); +} + +static bool add_original_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, + void *arg) { + return grpc_channel_stack_builder_prepend_filter( + builder, (const grpc_channel_filter *)arg, set_arg_once_fn, + &g_original_fn_called); +} + +static void init_plugin(void) { + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + add_original_filter, + (void *)&original_filter); + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + add_replacement_filter, + (void *)&replacement_filter); +} + +static void destroy_plugin(void) {} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_register_plugin(init_plugin, destroy_plugin); + grpc_init(); + test_channel_stack_builder_filter_replace(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c deleted file mode 100644 index a07ef89ba8..0000000000 --- a/test/core/channel/channel_stack_test.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/channel/channel_stack.h" - -#include - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx, - 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; - return GRPC_ERROR_NONE; -} - -static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_element_args *args) { - ++*(int *)(elem->channel_data); - *(int *)(elem->call_data) = 0; - return GRPC_ERROR_NONE; -} - -static void channel_destroy_func(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) {} - -static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) { - ++*(int *)(elem->channel_data); -} - -static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op_batch *op) { - ++*(int *)(elem->call_data); -} - -static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, - grpc_transport_op *op) { - ++*(int *)(elem->channel_data); -} - -static void free_channel(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_channel_stack_destroy(exec_ctx, arg); - gpr_free(arg); -} - -static void free_call(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_call_stack_destroy(exec_ctx, arg, NULL, NULL); - gpr_free(arg); -} - -static void test_create_channel_stack(void) { - const grpc_channel_filter filter = { - call_func, - channel_func, - sizeof(int), - call_init_func, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - call_destroy_func, - sizeof(int), - channel_init_func, - channel_destroy_func, - grpc_channel_next_get_info, - "some_test_filter"}; - const grpc_channel_filter *filters = &filter; - grpc_channel_stack *channel_stack; - grpc_call_stack *call_stack; - grpc_channel_element *channel_elem; - grpc_call_element *call_elem; - grpc_arg arg; - grpc_channel_args chan_args; - int *channel_data; - int *call_data; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice path = grpc_slice_from_static_string("/service/method"); - - arg.type = GRPC_ARG_INTEGER; - arg.key = "test_key"; - arg.value.integer = 42; - - chan_args.num_args = 1; - chan_args.args = &arg; - - channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); - grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, - 1, &chan_args, NULL, "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); - const grpc_call_element_args args = { - .call_stack = call_stack, - .server_transport_data = NULL, - .context = NULL, - .path = path, - .start_time = gpr_now(GPR_CLOCK_MONOTONIC), - .deadline = GRPC_MILLIS_INF_FUTURE, - .arena = NULL}; - grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1, - free_call, call_stack, &args); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(call_stack->count == 1); - call_elem = grpc_call_stack_element(call_stack, 0); - GPR_ASSERT(call_elem->filter == channel_elem->filter); - GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); - call_data = (int *)call_elem->call_data; - GPR_ASSERT(*call_data == 0); - GPR_ASSERT(*channel_data == 1); - - GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(*channel_data == 2); - - GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); - - grpc_slice_unref_internal(&exec_ctx, path); - 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/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc new file mode 100644 index 0000000000..88007375b2 --- /dev/null +++ b/test/core/channel/channel_stack_test.cc @@ -0,0 +1,162 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/channel/channel_stack.h" + +#include + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx, + 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; + return GRPC_ERROR_NONE; +} + +static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + ++*(int *)(elem->channel_data); + *(int *)(elem->call_data) = 0; + return GRPC_ERROR_NONE; +} + +static void channel_destroy_func(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) { + ++*(int *)(elem->channel_data); +} + +static void call_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *op) { + ++*(int *)(elem->call_data); +} + +static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, + grpc_transport_op *op) { + ++*(int *)(elem->channel_data); +} + +static void free_channel(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_channel_stack_destroy(exec_ctx, static_cast(arg)); + gpr_free(arg); +} + +static void free_call(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + grpc_call_stack_destroy(exec_ctx, static_cast(arg), NULL, + NULL); + gpr_free(arg); +} + +static void test_create_channel_stack(void) { + const grpc_channel_filter filter = { + call_func, + channel_func, + sizeof(int), + call_init_func, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + call_destroy_func, + sizeof(int), + channel_init_func, + channel_destroy_func, + grpc_channel_next_get_info, + "some_test_filter"}; + const grpc_channel_filter *filters = &filter; + grpc_channel_stack *channel_stack; + grpc_call_stack *call_stack; + grpc_channel_element *channel_elem; + grpc_call_element *call_elem; + grpc_arg arg; + grpc_channel_args chan_args; + int *channel_data; + int *call_data; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice path = grpc_slice_from_static_string("/service/method"); + + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast("test_key"); + arg.value.integer = 42; + + chan_args.num_args = 1; + chan_args.args = &arg; + + channel_stack = static_cast( + gpr_malloc(grpc_channel_stack_size(&filters, 1))); + grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, + 1, &chan_args, NULL, "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 = static_cast( + gpr_malloc(channel_stack->call_stack_size)); + const grpc_call_element_args args = { + call_stack, /* call_stack */ + nullptr, /* server_transport_data */ + nullptr, /* context */ + path, /* path */ + gpr_now(GPR_CLOCK_MONOTONIC), /* start_time */ + GRPC_MILLIS_INF_FUTURE, /* deadline */ + nullptr, /* arena */ + nullptr /* call_combiner */ + }; + grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1, + free_call, call_stack, &args); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(call_stack->count == 1); + call_elem = grpc_call_stack_element(call_stack, 0); + GPR_ASSERT(call_elem->filter == channel_elem->filter); + GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); + call_data = (int *)call_elem->call_data; + GPR_ASSERT(*call_data == 0); + GPR_ASSERT(*channel_data == 1); + + GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(*channel_data == 2); + + GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); + + grpc_slice_unref_internal(&exec_ctx, path); + 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/channel/minimal_stack_is_minimal_test.c b/test/core/channel/minimal_stack_is_minimal_test.c deleted file mode 100644 index b4528346f7..0000000000 --- a/test/core/channel/minimal_stack_is_minimal_test.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/******************************************************************************* - * This test verifies that various stack configurations result in the set of - * filters that we expect. - * - * This is akin to a golden-file test, and suffers the same disadvantages and - * advantages: it reflects that the code as written has not been modified - and - * valid code modifications WILL break this test and it will need updating. - * - * The intent therefore is to allow code reviewers to more easily catch changes - * that perturb the generated list of channel filters in different - * configurations and assess whether such a change is correct and desirable. - */ - -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/channel_init.h" -#include "src/core/lib/surface/channel_stack_type.h" -#include "src/core/lib/transport/transport_impl.h" -#include "test/core/util/test_config.h" - -// use CHECK_STACK instead -static int check_stack(const char *file, int line, const char *transport_name, - grpc_channel_args *init_args, - unsigned channel_stack_type, ...); - -// arguments: const char *transport_name - the name of the transport type to -// simulate -// grpc_channel_args *init_args - channel args to pass down -// grpc_channel_stack_type channel_stack_type - the archetype of -// channel stack to create -// variadic arguments - the (in-order) expected list of channel -// filters to instantiate, terminated with NULL -#define CHECK_STACK(...) check_stack(__FILE__, __LINE__, __VA_ARGS__) - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - int errors = 0; - - // tests with a minimal stack - grpc_arg minimal_stack_arg = {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MINIMAL_STACK, - .value.integer = 1}; - grpc_channel_args minimal_stack_args = {.num_args = 1, - .args = &minimal_stack_arg}; - errors += CHECK_STACK("unknown", &minimal_stack_args, - GRPC_CLIENT_DIRECT_CHANNEL, "connected", NULL); - errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, - "connected", NULL); - errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_SERVER_CHANNEL, - "server", "connected", NULL); - errors += - CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL, - "http-client", "connected", NULL); - errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, - "http-client", "connected", NULL); - errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_SERVER_CHANNEL, - "server", "http-server", "connected", NULL); - errors += CHECK_STACK(NULL, &minimal_stack_args, GRPC_CLIENT_CHANNEL, - "client-channel", NULL); - - // tests with a default stack - errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_DIRECT_CHANNEL, - "message_size", "deadline", "connected", NULL); - errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", - "connected", NULL); - errors += CHECK_STACK("unknown", NULL, GRPC_SERVER_CHANNEL, "server", - "message_size", "deadline", "connected", NULL); - errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_DIRECT_CHANNEL, - "message_size", "deadline", "http-client", - "message_compress", "connected", NULL); - errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", - "http-client", "message_compress", "connected", NULL); - errors += CHECK_STACK("chttp2", NULL, GRPC_SERVER_CHANNEL, "server", - "message_size", "deadline", "http-server", - "message_compress", "connected", NULL); - errors += - CHECK_STACK(NULL, NULL, GRPC_CLIENT_CHANNEL, "client-channel", NULL); - - GPR_ASSERT(errors == 0); - grpc_shutdown(); - return 0; -} - -/******************************************************************************* - * End of tests definitions, start of test infrastructure - */ - -static int check_stack(const char *file, int line, const char *transport_name, - grpc_channel_args *init_args, - unsigned channel_stack_type, ...) { - // create dummy channel stack - grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create(); - grpc_transport_vtable fake_transport_vtable = {.name = transport_name}; - grpc_transport fake_transport = {.vtable = &fake_transport_vtable}; - grpc_channel_stack_builder_set_target(builder, "foo.test.google.fr"); - grpc_channel_args *channel_args = grpc_channel_args_copy(init_args); - if (transport_name != NULL) { - grpc_channel_stack_builder_set_transport(builder, &fake_transport); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_stack_builder_set_channel_arguments(&exec_ctx, builder, - channel_args); - GPR_ASSERT(grpc_channel_init_create_stack( - &exec_ctx, builder, (grpc_channel_stack_type)channel_stack_type)); - grpc_exec_ctx_finish(&exec_ctx); - } - - // build up our expectation list - gpr_strvec v; - gpr_strvec_init(&v); - va_list args; - va_start(args, channel_stack_type); - for (;;) { - char *a = va_arg(args, char *); - if (a == NULL) break; - if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); - gpr_strvec_add(&v, gpr_strdup(a)); - } - va_end(args); - char *expect = gpr_strvec_flatten(&v, NULL); - gpr_strvec_destroy(&v); - - // build up our "got" list - gpr_strvec_init(&v); - grpc_channel_stack_builder_iterator *it = - grpc_channel_stack_builder_create_iterator_at_first(builder); - while (grpc_channel_stack_builder_move_next(it)) { - const char *name = grpc_channel_stack_builder_iterator_filter_name(it); - if (name == NULL) continue; - if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); - gpr_strvec_add(&v, gpr_strdup(name)); - } - char *got = gpr_strvec_flatten(&v, NULL); - gpr_strvec_destroy(&v); - grpc_channel_stack_builder_iterator_destroy(it); - - // figure out result, log if there's an error - int result = 0; - if (0 != strcmp(got, expect)) { - gpr_strvec_init(&v); - gpr_strvec_add(&v, gpr_strdup("{")); - for (size_t i = 0; i < channel_args->num_args; i++) { - if (i > 0) gpr_strvec_add(&v, gpr_strdup(", ")); - gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key)); - gpr_strvec_add(&v, gpr_strdup("=")); - switch (channel_args->args[i].type) { - case GRPC_ARG_INTEGER: { - char *tmp; - gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer); - gpr_strvec_add(&v, tmp); - break; - } - case GRPC_ARG_STRING: - gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string)); - break; - case GRPC_ARG_POINTER: { - char *tmp; - gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p); - gpr_strvec_add(&v, tmp); - break; - } - } - } - gpr_strvec_add(&v, gpr_strdup("}")); - char *args_str = gpr_strvec_flatten(&v, NULL); - gpr_strvec_destroy(&v); - - gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, - "**************************************************"); - gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, - "FAILED transport=%s; stack_type=%s; channel_args=%s:", - transport_name, grpc_channel_stack_type_string(channel_stack_type), - args_str); - gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect); - gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got); - result = 1; - - gpr_free(args_str); - } - - gpr_free(got); - gpr_free(expect); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_stack_builder_destroy(&exec_ctx, builder); - grpc_channel_args_destroy(&exec_ctx, channel_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - return result; -} diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc new file mode 100644 index 0000000000..be6670c368 --- /dev/null +++ b/test/core/channel/minimal_stack_is_minimal_test.cc @@ -0,0 +1,221 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/******************************************************************************* + * This test verifies that various stack configurations result in the set of + * filters that we expect. + * + * This is akin to a golden-file test, and suffers the same disadvantages and + * advantages: it reflects that the code as written has not been modified - and + * valid code modifications WILL break this test and it will need updating. + * + * The intent therefore is to allow code reviewers to more easily catch changes + * that perturb the generated list of channel filters in different + * configurations and assess whether such a change is correct and desirable. + */ + +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/channel_init.h" +#include "src/core/lib/surface/channel_stack_type.h" +#include "src/core/lib/transport/transport_impl.h" +#include "test/core/util/test_config.h" + +// use CHECK_STACK instead +static int check_stack(const char *file, int line, const char *transport_name, + grpc_channel_args *init_args, + unsigned channel_stack_type, ...); + +// arguments: const char *transport_name - the name of the transport type to +// simulate +// grpc_channel_args *init_args - channel args to pass down +// grpc_channel_stack_type channel_stack_type - the archetype of +// channel stack to create +// variadic arguments - the (in-order) expected list of channel +// filters to instantiate, terminated with NULL +#define CHECK_STACK(...) check_stack(__FILE__, __LINE__, __VA_ARGS__) + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + int errors = 0; + + // tests with a minimal stack + grpc_arg minimal_stack_arg; + minimal_stack_arg.type = GRPC_ARG_INTEGER; + minimal_stack_arg.key = const_cast(GRPC_ARG_MINIMAL_STACK); + minimal_stack_arg.value.integer = 1; + grpc_channel_args minimal_stack_args = {1, &minimal_stack_arg}; + errors += CHECK_STACK("unknown", &minimal_stack_args, + GRPC_CLIENT_DIRECT_CHANNEL, "connected", NULL); + errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, + "connected", NULL); + errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_SERVER_CHANNEL, + "server", "connected", NULL); + errors += + CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL, + "http-client", "connected", NULL); + errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, + "http-client", "connected", NULL); + errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_SERVER_CHANNEL, + "server", "http-server", "connected", NULL); + errors += CHECK_STACK(NULL, &minimal_stack_args, GRPC_CLIENT_CHANNEL, + "client-channel", NULL); + + // tests with a default stack + errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_DIRECT_CHANNEL, + "message_size", "deadline", "connected", NULL); + errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", + "connected", NULL); + errors += CHECK_STACK("unknown", NULL, GRPC_SERVER_CHANNEL, "server", + "message_size", "deadline", "connected", NULL); + errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_DIRECT_CHANNEL, + "message_size", "deadline", "http-client", + "message_compress", "connected", NULL); + errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", + "http-client", "message_compress", "connected", NULL); + errors += CHECK_STACK("chttp2", NULL, GRPC_SERVER_CHANNEL, "server", + "message_size", "deadline", "http-server", + "message_compress", "connected", NULL); + errors += + CHECK_STACK(NULL, NULL, GRPC_CLIENT_CHANNEL, "client-channel", NULL); + + GPR_ASSERT(errors == 0); + grpc_shutdown(); + return 0; +} + +/******************************************************************************* + * End of tests definitions, start of test infrastructure + */ + +static int check_stack(const char *file, int line, const char *transport_name, + grpc_channel_args *init_args, + unsigned channel_stack_type, ...) { + // create dummy channel stack + grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create(); + grpc_transport_vtable fake_transport_vtable; + memset(&fake_transport_vtable, 0, sizeof(grpc_transport_vtable)); + fake_transport_vtable.name = transport_name; + grpc_transport fake_transport = {.vtable = &fake_transport_vtable}; + grpc_channel_stack_builder_set_target(builder, "foo.test.google.fr"); + grpc_channel_args *channel_args = grpc_channel_args_copy(init_args); + if (transport_name != NULL) { + grpc_channel_stack_builder_set_transport(builder, &fake_transport); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_stack_builder_set_channel_arguments(&exec_ctx, builder, + channel_args); + GPR_ASSERT(grpc_channel_init_create_stack( + &exec_ctx, builder, (grpc_channel_stack_type)channel_stack_type)); + grpc_exec_ctx_finish(&exec_ctx); + } + + // build up our expectation list + gpr_strvec v; + gpr_strvec_init(&v); + va_list args; + va_start(args, channel_stack_type); + for (;;) { + char *a = va_arg(args, char *); + if (a == NULL) break; + if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); + gpr_strvec_add(&v, gpr_strdup(a)); + } + va_end(args); + char *expect = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + + // build up our "got" list + gpr_strvec_init(&v); + grpc_channel_stack_builder_iterator *it = + grpc_channel_stack_builder_create_iterator_at_first(builder); + while (grpc_channel_stack_builder_move_next(it)) { + const char *name = grpc_channel_stack_builder_iterator_filter_name(it); + if (name == NULL) continue; + if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); + gpr_strvec_add(&v, gpr_strdup(name)); + } + char *got = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + grpc_channel_stack_builder_iterator_destroy(it); + + // figure out result, log if there's an error + int result = 0; + if (0 != strcmp(got, expect)) { + gpr_strvec_init(&v); + gpr_strvec_add(&v, gpr_strdup("{")); + for (size_t i = 0; i < channel_args->num_args; i++) { + if (i > 0) gpr_strvec_add(&v, gpr_strdup(", ")); + gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key)); + gpr_strvec_add(&v, gpr_strdup("=")); + switch (channel_args->args[i].type) { + case GRPC_ARG_INTEGER: { + char *tmp; + gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer); + gpr_strvec_add(&v, tmp); + break; + } + case GRPC_ARG_STRING: + gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string)); + break; + case GRPC_ARG_POINTER: { + char *tmp; + gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p); + gpr_strvec_add(&v, tmp); + break; + } + } + } + gpr_strvec_add(&v, gpr_strdup("}")); + char *args_str = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + + gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, + "**************************************************"); + gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, + "FAILED transport=%s; stack_type=%s; channel_args=%s:", + transport_name, + grpc_channel_stack_type_string( + static_cast(channel_stack_type)), + args_str); + gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect); + gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got); + result = 1; + + gpr_free(args_str); + } + + gpr_free(got); + gpr_free(expect); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_stack_builder_destroy(&exec_ctx, builder); + grpc_channel_args_destroy(&exec_ctx, channel_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + return result; +} diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c deleted file mode 100644 index ba37cd673f..0000000000 --- a/test/core/client_channel/lb_policies_test.c +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/client_channel/lb_policy_registry.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define RETRY_TIMEOUT 300 - -typedef struct servers_fixture { - size_t num_servers; - grpc_server **servers; - grpc_call **server_calls; - grpc_completion_queue *cq; - grpc_completion_queue *shutdown_cq; - char **servers_hostports; - grpc_metadata_array *request_metadata_recv; -} servers_fixture; - -typedef struct request_sequences { - size_t n; /* number of iterations */ - int *connections; /* indexed by the interation number, value is the index of - the server it connected to or -1 if none */ - int *connectivity_states; /* indexed by the interation number, value is the - client connectivity state */ -} request_sequences; - -typedef void (*verifier_fn)(const servers_fixture *, grpc_channel *, - const request_sequences *, const size_t); - -typedef struct test_spec { - size_t num_iters; - size_t num_servers; - - int **kill_at; - int **revive_at; - - const char *description; - - verifier_fn verifier; - -} test_spec; - -static void test_spec_reset(test_spec *spec) { - size_t i, j; - - for (i = 0; i < spec->num_iters; i++) { - for (j = 0; j < spec->num_servers; j++) { - spec->kill_at[i][j] = 0; - spec->revive_at[i][j] = 0; - } - } -} - -static test_spec *test_spec_create(size_t num_iters, size_t num_servers) { - test_spec *spec; - size_t i; - - spec = gpr_malloc(sizeof(test_spec)); - spec->num_iters = num_iters; - spec->num_servers = num_servers; - spec->kill_at = gpr_malloc(sizeof(int *) * num_iters); - spec->revive_at = gpr_malloc(sizeof(int *) * num_iters); - for (i = 0; i < num_iters; i++) { - spec->kill_at[i] = gpr_malloc(sizeof(int) * num_servers); - spec->revive_at[i] = gpr_malloc(sizeof(int) * num_servers); - } - - test_spec_reset(spec); - return spec; -} - -static void test_spec_destroy(test_spec *spec) { - size_t i; - for (i = 0; i < spec->num_iters; i++) { - gpr_free(spec->kill_at[i]); - gpr_free(spec->revive_at[i]); - } - - gpr_free(spec->kill_at); - gpr_free(spec->revive_at); - - gpr_free(spec); -} - -static void *tag(intptr_t t) { return (void *)t; } - -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_millis_time(5000), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void kill_server(const servers_fixture *f, size_t i) { - gpr_log(GPR_INFO, "KILLING SERVER %" PRIuPTR, i); - GPR_ASSERT(f->servers[i] != NULL); - grpc_server_shutdown_and_notify(f->servers[i], f->shutdown_cq, tag(10000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(10000), - n_millis_time(5000), NULL) - .type == GRPC_OP_COMPLETE); - grpc_server_destroy(f->servers[i]); - f->servers[i] = NULL; -} - -typedef struct request_data { - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_slice details; - 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 %" PRIuPTR, 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)); - size_t i; - - f->num_servers = num_servers; - f->server_calls = gpr_malloc(sizeof(grpc_call *) * num_servers); - f->request_metadata_recv = - gpr_malloc(sizeof(grpc_metadata_array) * num_servers); - /* Create 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_for_next(NULL); - f->shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - for (i = 0; i < num_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); - } - return f; -} - -static void teardown_servers(servers_fixture *f) { - size_t i; - /* Destroy server. */ - for (i = 0; i < f->num_servers; i++) { - if (f->servers[i] == NULL) continue; - grpc_server_shutdown_and_notify(f->servers[i], f->shutdown_cq, tag(10000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(10000), - n_millis_time(5000), NULL) - .type == GRPC_OP_COMPLETE); - grpc_server_destroy(f->servers[i]); - } - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); - grpc_completion_queue_destroy(f->shutdown_cq); - - gpr_free(f->servers); - - 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); - gpr_free(f->request_metadata_recv); - gpr_free(f->server_calls); - gpr_free(f); -} - -static request_sequences request_sequences_create(size_t n) { - request_sequences res; - res.n = n; - res.connections = gpr_malloc(sizeof(*res.connections) * n); - res.connectivity_states = gpr_malloc(sizeof(*res.connectivity_states) * n); - memset(res.connections, 0, sizeof(*res.connections) * n); - memset(res.connectivity_states, 0, sizeof(*res.connectivity_states) * n); - return res; -} - -static void request_sequences_destroy(const request_sequences *rseqs) { - gpr_free(rseqs->connections); - gpr_free(rseqs->connectivity_states); -} - -/** Returns connection sequence (server indices), which must be freed */ -static request_sequences perform_request(servers_fixture *f, - grpc_channel *client, - request_data *rdata, - const test_spec *spec) { - grpc_call *c; - int s_idx; - int *s_valid; - grpc_op ops[6]; - grpc_op *op; - int was_cancelled; - size_t i, iter_num; - grpc_event ev; - int read_tag; - int completed_client; - const request_sequences sequences = request_sequences_create(spec->num_iters); - - s_valid = gpr_malloc(sizeof(int) * f->num_servers); - - for (iter_num = 0; iter_num < spec->num_iters; iter_num++) { - cq_verifier *cqv = cq_verifier_create(f->cq); - was_cancelled = 2; - - for (i = 0; i < f->num_servers; i++) { - if (spec->kill_at[iter_num][i] != 0) { - kill_server(f, i); - } else if (spec->revive_at[iter_num][i] != 0) { - /* killing takes precedence */ - revive_server(f, rdata, i); - } - } - - sequences.connections[iter_num] = -1; - grpc_metadata_array_init(&rdata->initial_metadata_recv); - grpc_metadata_array_init(&rdata->trailing_metadata_recv); - - for (i = 0; i < f->num_servers; i++) { - grpc_call_details_init(&rdata->call_details[i]); - } - memset(s_valid, 0, f->num_servers * sizeof(int)); - - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); - c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - grpc_slice_from_static_string("/foo"), &host, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(c); - completed_client = 0; - - memset(ops, 0, sizeof(ops)); - 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.recv_initial_metadata = - &rdata->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 = - &rdata->trailing_metadata_recv; - op->data.recv_status_on_client.status = &rdata->status; - op->data.recv_status_on_client.status_details = &rdata->details; - op->flags = 0; - op->reserved = NULL; - op++; - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL)); - - s_idx = -1; - while ( - (ev = grpc_completion_queue_next( - f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL)) - .type != GRPC_QUEUE_TIMEOUT) { - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - read_tag = ((int)(intptr_t)ev.tag); - const grpc_connectivity_state conn_state = - grpc_channel_check_connectivity_state(client, 0); - sequences.connectivity_states[iter_num] = conn_state; - gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%" PRIuPTR, - ev.success, ev.type, read_tag, iter_num); - if (ev.success && read_tag >= 1000) { - GPR_ASSERT(s_idx == -1); /* only one server must reply */ - /* only server notifications for non-shutdown events */ - s_idx = read_tag - 1000; - s_valid[s_idx] = 1; - sequences.connections[iter_num] = s_idx; - break; - } else if (read_tag == 1) { - gpr_log(GPR_DEBUG, "client timed out"); - GPR_ASSERT(ev.success); - completed_client = 1; - } - } - - if (s_idx >= 0) { - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(f->server_calls[s_idx], - ops, (size_t)(op - ops), - tag(102), NULL)); - - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - if (!completed_client) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - } - cq_verify(cqv); - - GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->details, "xyz")); - GPR_ASSERT(0 == - grpc_slice_str_cmp(rdata->call_details[s_idx].method, "/foo")); - GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].host, - "foo.test.google.fr")); - GPR_ASSERT(was_cancelled == 1); - - grpc_call_unref(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); - } - } - - GPR_ASSERT( - grpc_completion_queue_next( - f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL) - .type == GRPC_QUEUE_TIMEOUT); - - grpc_metadata_array_destroy(&rdata->initial_metadata_recv); - grpc_metadata_array_destroy(&rdata->trailing_metadata_recv); - - cq_verifier_destroy(cqv); - - grpc_call_unref(c); - - for (i = 0; i < f->num_servers; i++) { - grpc_call_details_destroy(&rdata->call_details[i]); - } - grpc_slice_unref(rdata->details); - } - - gpr_free(s_valid); - - return sequences; -} - -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); - } - - memset(ops, 0, sizeof(ops)); - 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; - - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); - for (i = 0; i < concurrent_calls; i++) { - calls[i] = - grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - grpc_slice_from_static_string("/foo"), &host, - 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; -} - -void run_spec(const test_spec *spec) { - grpc_channel *client; - char *client_hostport; - char *servers_hostports_str; - request_data rdata; - servers_fixture *f; - grpc_channel_args args; - grpc_arg arg_array[2]; - 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", servers_hostports_str); - - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = RETRY_TIMEOUT; - arg_array[1].type = GRPC_ARG_STRING; - arg_array[1].key = GRPC_ARG_LB_POLICY_NAME; - arg_array[1].value.string = "round_robin"; - args.num_args = 2; - args.args = arg_array; - - 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); - - const request_sequences sequences = perform_request(f, client, &rdata, spec); - - spec->verifier(f, client, &sequences, spec->num_iters); - - gpr_free(client_hostport); - gpr_free(servers_hostports_str); - gpr_free(rdata.call_details); - request_sequences_destroy(&sequences); - - 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_array[3]; - 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", servers_hostports_str); - - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = RETRY_TIMEOUT; - arg_array[1].type = GRPC_ARG_STRING; - arg_array[1].key = GRPC_ARG_LB_POLICY_NAME; - arg_array[1].value.string = "ROUND_ROBIN"; - arg_array[2].type = GRPC_ARG_INTEGER; - arg_array[2].key = GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS; - arg_array[2].value.integer = 0; - args.num_args = GPR_ARRAY_SIZE(arg_array); - args.args = arg_array; - - 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_unref(calls[i]); - } - gpr_free(calls); - teardown_servers(f); - test_spec_destroy(spec); -} - -static void test_get_channel_info() { - grpc_channel *channel = - grpc_insecure_channel_create("ipv4:127.0.0.1:1234", NULL, NULL); - // Ensures that resolver returns. - grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); - // First, request no fields. This is a no-op. - grpc_channel_info channel_info; - memset(&channel_info, 0, sizeof(channel_info)); - grpc_channel_get_info(channel, &channel_info); - // Request LB policy name. - char *lb_policy_name = NULL; - channel_info.lb_policy_name = &lb_policy_name; - grpc_channel_get_info(channel, &channel_info); - GPR_ASSERT(lb_policy_name != NULL); - GPR_ASSERT(strcmp(lb_policy_name, "pick_first") == 0); - gpr_free(lb_policy_name); - // Request service config, which does not exist, so we'll get nothing back. - memset(&channel_info, 0, sizeof(channel_info)); - char *service_config_json = "dummy_string"; - channel_info.service_config_json = &service_config_json; - grpc_channel_get_info(channel, &channel_info); - GPR_ASSERT(service_config_json == NULL); - // Recreate the channel such that it has a service config. - grpc_channel_destroy(channel); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = "{\"loadBalancingPolicy\": \"ROUND_ROBIN\"}"; - grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - channel = grpc_insecure_channel_create("ipv4:127.0.0.1:1234", args, NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - // Ensures that resolver returns. - grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); - // Now request the service config again. - grpc_channel_get_info(channel, &channel_info); - GPR_ASSERT(service_config_json != NULL); - GPR_ASSERT(strcmp(service_config_json, arg.value.string) == 0); - gpr_free(service_config_json); - // Clean up. - grpc_channel_destroy(channel); -} - -static void print_failed_expectations(const int *expected_connection_sequence, - const int *actual_connection_sequence, - const size_t expected_seq_length, - const size_t num_iters) { - size_t i; - for (i = 0; i < num_iters; i++) { - gpr_log(GPR_ERROR, - "FAILURE: Iter (expected, actual): %" PRIuPTR " (%d, %d)", i, - expected_connection_sequence[i % expected_seq_length], - actual_connection_sequence[i]); - } -} - -static void verify_vanilla_round_robin(const servers_fixture *f, - grpc_channel *client, - const request_sequences *sequences, - const size_t num_iters) { - const size_t expected_seq_length = f->num_servers; - - /* verify conn. seq. expectation */ - /* get the first sequence of "num_servers" elements */ - int *expected_connection_sequence = - gpr_malloc(sizeof(int) * expected_seq_length); - memcpy(expected_connection_sequence, sequences->connections, - sizeof(int) * expected_seq_length); - - for (size_t i = 0; i < num_iters; i++) { - const int actual = sequences->connections[i]; - const int expected = expected_connection_sequence[i % expected_seq_length]; - if (actual != expected) { - gpr_log( - GPR_ERROR, - "CONNECTION SEQUENCE FAILURE: expected %d, got %d at iteration #%d", - expected, actual, (int)i); - abort(); - } - } - - /* All servers are available, therefore all client subchannels are READY, even - * when we only need one for the client channel state to be READY */ - for (size_t i = 0; i < sequences->n; i++) { - const grpc_connectivity_state actual = sequences->connectivity_states[i]; - const grpc_connectivity_state expected = GRPC_CHANNEL_READY; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), (int)i); - abort(); - } - } - - gpr_free(expected_connection_sequence); -} - -/* At the start of the second iteration, all but the first and last servers (as - * given in "f") are killed */ -static void verify_vanishing_floor_round_robin( - const servers_fixture *f, grpc_channel *client, - const request_sequences *sequences, const size_t num_iters) { - int *expected_connection_sequence; - const size_t expected_seq_length = 2; - size_t i; - - /* verify conn. seq. expectation */ - /* copy the first full sequence (without -1s) */ - expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length); - memcpy(expected_connection_sequence, sequences->connections + 2, - expected_seq_length * sizeof(int)); - - /* first two elements of the sequence should be [0 (1st server), -1 (failure)] - */ - GPR_ASSERT(sequences->connections[0] == 0); - GPR_ASSERT(sequences->connections[1] == -1); - - /* the next two element must be [3, 0], repeating from that point: the 3 is - * brought forth by servers 1 and 2 disappearing after the intial pick of 0 */ - GPR_ASSERT(sequences->connections[2] == 3); - GPR_ASSERT(sequences->connections[3] == 0); - - /* make sure that the expectation obliges */ - for (i = 2; i < num_iters; i++) { - const int actual = sequences->connections[i]; - const int expected = expected_connection_sequence[i % expected_seq_length]; - if (actual != expected) { - print_failed_expectations(expected_connection_sequence, - sequences->connections, expected_seq_length, - num_iters); - abort(); - } - } - - /* There's always at least one subchannel READY (connected), therefore the - * overall state of the client channel is READY at all times. */ - for (i = 0; i < sequences->n; i++) { - const grpc_connectivity_state actual = sequences->connectivity_states[i]; - const grpc_connectivity_state expected = GRPC_CHANNEL_READY; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), (int)i); - abort(); - } - } - - gpr_free(expected_connection_sequence); -} - -static void verify_total_carnage_round_robin(const servers_fixture *f, - grpc_channel *client, - const request_sequences *sequences, - const size_t num_iters) { - for (size_t i = 0; i < num_iters; i++) { - const int actual = sequences->connections[i]; - const int expected = -1; - if (actual != expected) { - gpr_log( - GPR_ERROR, - "CONNECTION SEQUENCE FAILURE: expected %d, got %d at iteration #%d", - expected, actual, (int)i); - abort(); - } - } - - /* No server is ever available. There should be no READY states (or SHUTDOWN). - * Note that all other states (IDLE, CONNECTING, TRANSIENT_FAILURE) are still - * possible, as the policy transitions while attempting to reconnect. */ - for (size_t i = 0; i < sequences->n; i++) { - const grpc_connectivity_state actual = sequences->connectivity_states[i]; - if (actual == GRPC_CHANNEL_READY || actual == GRPC_CHANNEL_SHUTDOWN) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: got unexpected state " - "'%s' at iteration #%d.", - grpc_connectivity_state_name(actual), (int)i); - abort(); - } - } -} - -static void verify_partial_carnage_round_robin( - const servers_fixture *f, grpc_channel *client, - const request_sequences *sequences, const size_t num_iters) { - int *expected_connection_sequence; - size_t i; - const size_t expected_seq_length = f->num_servers; - - /* verify conn. seq. expectation */ - /* get the first sequence of "num_servers" elements */ - expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length); - memcpy(expected_connection_sequence, sequences->connections, - sizeof(int) * expected_seq_length); - - for (i = 0; i < num_iters / 2; i++) { - const int actual = sequences->connections[i]; - const int expected = expected_connection_sequence[i % expected_seq_length]; - if (actual != expected) { - print_failed_expectations(expected_connection_sequence, - sequences->connections, expected_seq_length, - num_iters); - abort(); - } - } - - /* second half of the iterations go without response */ - for (; i < num_iters; i++) { - GPR_ASSERT(sequences->connections[i] == -1); - } - - /* We can assert that the first client channel state should be READY, when all - * servers were available */ - grpc_connectivity_state actual = sequences->connectivity_states[0]; - grpc_connectivity_state expected = GRPC_CHANNEL_READY; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), 0); - abort(); - } - - /* ... and that the last one shouldn't be READY (or SHUTDOWN): all servers are - * gone. It may be all other states (IDLE, CONNECTING, TRANSIENT_FAILURE), as - * the policy transitions while attempting to reconnect. */ - actual = sequences->connectivity_states[num_iters - 1]; - for (i = 0; i < sequences->n; i++) { - if (actual == GRPC_CHANNEL_READY || actual == GRPC_CHANNEL_SHUTDOWN) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: got unexpected state " - "'%s' at iteration #%d.", - grpc_connectivity_state_name(actual), (int)i); - abort(); - } - } - gpr_free(expected_connection_sequence); -} - -static void dump_array(const char *desc, const int *data, const size_t count) { - gpr_strvec s; - char *tmp; - size_t i; - gpr_strvec_init(&s); - gpr_strvec_add(&s, gpr_strdup(desc)); - gpr_strvec_add(&s, gpr_strdup(":")); - for (i = 0; i < count; i++) { - gpr_asprintf(&tmp, " %d", data[i]); - gpr_strvec_add(&s, tmp); - } - tmp = gpr_strvec_flatten(&s, NULL); - gpr_strvec_destroy(&s); - gpr_log(GPR_DEBUG, "%s", tmp); - gpr_free(tmp); -} - -static void verify_rebirth_round_robin(const servers_fixture *f, - grpc_channel *client, - const request_sequences *sequences, - const size_t num_iters) { - dump_array("actual_connection_sequence", sequences->connections, num_iters); - - /* first iteration succeeds */ - GPR_ASSERT(sequences->connections[0] != -1); - /* then we fail for a while... */ - GPR_ASSERT(sequences->connections[1] == -1); - /* ... but should be up eventually */ - size_t first_iter_back_up = ~0ul; - for (size_t i = 2; i < sequences->n; ++i) { - if (sequences->connections[i] != -1) { - first_iter_back_up = i; - break; - } - } - GPR_ASSERT(first_iter_back_up != ~0ul); - - /* We can assert that the first client channel state should be READY, when all - * servers were available; same thing for the last one. In the middle - * somewhere there must exist at least one TRANSIENT_FAILURE */ - grpc_connectivity_state actual = sequences->connectivity_states[0]; - grpc_connectivity_state expected = GRPC_CHANNEL_READY; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), 0); - abort(); - } - - actual = sequences->connectivity_states[num_iters - 1]; - expected = GRPC_CHANNEL_READY; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), (int)num_iters - 1); - abort(); - } - - bool found_failure_status = false; - for (size_t i = 1; i < sequences->n - 1; i++) { - if (sequences->connectivity_states[i] == GRPC_CHANNEL_TRANSIENT_FAILURE) { - found_failure_status = true; - break; - } - } - if (!found_failure_status) { - gpr_log( - GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: " - "GRPC_CHANNEL_TRANSIENT_FAILURE status not found. Got the following " - "instead:"); - for (size_t i = 0; i < num_iters; i++) { - gpr_log(GPR_ERROR, "[%d]: %s", (int)i, - grpc_connectivity_state_name(sequences->connectivity_states[i])); - } - } -} - -int main(int argc, char **argv) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - test_spec *spec; - size_t i; - const size_t NUM_ITERS = 10; - const size_t NUM_SERVERS = 4; - - grpc_init(); - grpc_test_init(argc, argv); - grpc_tracer_set_enabled("round_robin", 1); - - GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, "this-lb-policy-does-not-exist", - NULL) == NULL); - GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, NULL, NULL) == NULL); - - 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); - - /* Kill all servers first thing in the morning */ - test_spec_reset(spec); - spec->verifier = verify_total_carnage_round_robin; - spec->description = "test_kill_all_server"; - for (i = 0; i < NUM_SERVERS; i++) { - spec->kill_at[0][i] = 1; - } - run_spec(spec); - - /* 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; - spec->description = "test_kill_middle_servers_at_2nd_iteration"; - for (i = 1; i < NUM_SERVERS - 1; i++) { - spec->kill_at[1][i] = 1; - } - run_spec(spec); - - /* Midway, kill all servers. */ - test_spec_reset(spec); - spec->verifier = verify_partial_carnage_round_robin; - spec->description = "test_kill_all_server_midway"; - for (i = 0; i < NUM_SERVERS; i++) { - spec->kill_at[spec->num_iters / 2][i] = 1; - } - run_spec(spec); - - /* After first iteration, kill all servers. On the third one, bring them all - * back up. */ - test_spec_reset(spec); - spec->verifier = verify_rebirth_round_robin; - spec->description = "test_kill_all_server_after_1st_resurrect_at_3rd"; - for (i = 0; i < NUM_SERVERS; i++) { - spec->kill_at[1][i] = 1; - spec->revive_at[3][i] = 1; - } - run_spec(spec); - test_spec_destroy(spec); - - test_pending_calls(4); - test_ping(); - test_get_channel_info(); - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} diff --git a/test/core/client_channel/lb_policies_test.cc b/test/core/client_channel/lb_policies_test.cc new file mode 100644 index 0000000000..4379af11da --- /dev/null +++ b/test/core/client_channel/lb_policies_test.cc @@ -0,0 +1,1033 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define RETRY_TIMEOUT 300 + +typedef struct servers_fixture { + size_t num_servers; + grpc_server **servers; + grpc_call **server_calls; + grpc_completion_queue *cq; + grpc_completion_queue *shutdown_cq; + char **servers_hostports; + grpc_metadata_array *request_metadata_recv; +} servers_fixture; + +typedef struct request_sequences { + size_t n; /* number of iterations */ + int *connections; /* indexed by the interation number, value is the index of + the server it connected to or -1 if none */ + int *connectivity_states; /* indexed by the interation number, value is the + client connectivity state */ +} request_sequences; + +typedef void (*verifier_fn)(const servers_fixture *, grpc_channel *, + const request_sequences *, const size_t); + +typedef struct test_spec { + size_t num_iters; + size_t num_servers; + + int **kill_at; + int **revive_at; + + const char *description; + + verifier_fn verifier; + +} test_spec; + +static void test_spec_reset(test_spec *spec) { + size_t i, j; + + for (i = 0; i < spec->num_iters; i++) { + for (j = 0; j < spec->num_servers; j++) { + spec->kill_at[i][j] = 0; + spec->revive_at[i][j] = 0; + } + } +} + +static test_spec *test_spec_create(size_t num_iters, size_t num_servers) { + test_spec *spec; + size_t i; + + spec = static_cast(gpr_malloc(sizeof(test_spec))); + spec->num_iters = num_iters; + spec->num_servers = num_servers; + spec->kill_at = static_cast(gpr_malloc(sizeof(int *) * num_iters)); + spec->revive_at = static_cast(gpr_malloc(sizeof(int *) * num_iters)); + for (i = 0; i < num_iters; i++) { + spec->kill_at[i] = + static_cast(gpr_malloc(sizeof(int) * num_servers)); + spec->revive_at[i] = + static_cast(gpr_malloc(sizeof(int) * num_servers)); + } + + test_spec_reset(spec); + return spec; +} + +static void test_spec_destroy(test_spec *spec) { + size_t i; + for (i = 0; i < spec->num_iters; i++) { + gpr_free(spec->kill_at[i]); + gpr_free(spec->revive_at[i]); + } + + gpr_free(spec->kill_at); + gpr_free(spec->revive_at); + + gpr_free(spec); +} + +static void *tag(intptr_t t) { return (void *)t; } + +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_millis_time(5000), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void kill_server(const servers_fixture *f, size_t i) { + gpr_log(GPR_INFO, "KILLING SERVER %" PRIuPTR, i); + GPR_ASSERT(f->servers[i] != NULL); + grpc_server_shutdown_and_notify(f->servers[i], f->shutdown_cq, tag(10000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(10000), + n_millis_time(5000), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->servers[i]); + f->servers[i] = NULL; +} + +typedef struct request_data { + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_slice details; + 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 %" PRIuPTR, 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 = + static_cast(gpr_malloc(sizeof(servers_fixture))); + size_t i; + + f->num_servers = num_servers; + f->server_calls = + static_cast(gpr_malloc(sizeof(grpc_call *) * num_servers)); + f->request_metadata_recv = static_cast( + gpr_malloc(sizeof(grpc_metadata_array) * num_servers)); + /* Create servers. */ + f->servers = static_cast( + gpr_malloc(sizeof(grpc_server *) * num_servers)); + f->servers_hostports = + static_cast(gpr_malloc(sizeof(char *) * num_servers)); + f->cq = grpc_completion_queue_create_for_next(NULL); + f->shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + for (i = 0; i < num_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); + } + return f; +} + +static void teardown_servers(servers_fixture *f) { + size_t i; + /* Destroy server. */ + for (i = 0; i < f->num_servers; i++) { + if (f->servers[i] == NULL) continue; + grpc_server_shutdown_and_notify(f->servers[i], f->shutdown_cq, tag(10000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(10000), + n_millis_time(5000), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->servers[i]); + } + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); + + gpr_free(f->servers); + + 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); + gpr_free(f->request_metadata_recv); + gpr_free(f->server_calls); + gpr_free(f); +} + +static request_sequences request_sequences_create(size_t n) { + request_sequences res; + res.n = n; + res.connections = + static_cast(gpr_malloc(sizeof(*res.connections) * n)); + res.connectivity_states = + static_cast(gpr_malloc(sizeof(*res.connectivity_states) * n)); + memset(res.connections, 0, sizeof(*res.connections) * n); + memset(res.connectivity_states, 0, sizeof(*res.connectivity_states) * n); + return res; +} + +static void request_sequences_destroy(const request_sequences *rseqs) { + gpr_free(rseqs->connections); + gpr_free(rseqs->connectivity_states); +} + +/** Returns connection sequence (server indices), which must be freed */ +static request_sequences perform_request(servers_fixture *f, + grpc_channel *client, + request_data *rdata, + const test_spec *spec) { + grpc_call *c; + int s_idx; + int *s_valid; + grpc_op ops[6]; + grpc_op *op; + int was_cancelled; + size_t i, iter_num; + grpc_event ev; + int read_tag; + int completed_client; + const request_sequences sequences = request_sequences_create(spec->num_iters); + + s_valid = static_cast(gpr_malloc(sizeof(int) * f->num_servers)); + + for (iter_num = 0; iter_num < spec->num_iters; iter_num++) { + cq_verifier *cqv = cq_verifier_create(f->cq); + was_cancelled = 2; + + for (i = 0; i < f->num_servers; i++) { + if (spec->kill_at[iter_num][i] != 0) { + kill_server(f, i); + } else if (spec->revive_at[iter_num][i] != 0) { + /* killing takes precedence */ + revive_server(f, rdata, i); + } + } + + sequences.connections[iter_num] = -1; + grpc_metadata_array_init(&rdata->initial_metadata_recv); + grpc_metadata_array_init(&rdata->trailing_metadata_recv); + + for (i = 0; i < f->num_servers; i++) { + grpc_call_details_init(&rdata->call_details[i]); + } + memset(s_valid, 0, f->num_servers * sizeof(int)); + + grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); + c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, + grpc_slice_from_static_string("/foo"), &host, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(c); + completed_client = 0; + + memset(ops, 0, sizeof(ops)); + 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.recv_initial_metadata = + &rdata->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 = + &rdata->trailing_metadata_recv; + op->data.recv_status_on_client.status = &rdata->status; + op->data.recv_status_on_client.status_details = &rdata->details; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL)); + + s_idx = -1; + while ( + (ev = grpc_completion_queue_next( + f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL)) + .type != GRPC_QUEUE_TIMEOUT) { + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + read_tag = ((int)(intptr_t)ev.tag); + const grpc_connectivity_state conn_state = + grpc_channel_check_connectivity_state(client, 0); + sequences.connectivity_states[iter_num] = conn_state; + gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%" PRIuPTR, + ev.success, ev.type, read_tag, iter_num); + if (ev.success && read_tag >= 1000) { + GPR_ASSERT(s_idx == -1); /* only one server must reply */ + /* only server notifications for non-shutdown events */ + s_idx = read_tag - 1000; + s_valid[s_idx] = 1; + sequences.connections[iter_num] = s_idx; + break; + } else if (read_tag == 1) { + gpr_log(GPR_DEBUG, "client timed out"); + GPR_ASSERT(ev.success); + completed_client = 1; + } + } + + if (s_idx >= 0) { + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(f->server_calls[s_idx], + ops, (size_t)(op - ops), + tag(102), NULL)); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + if (!completed_client) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + } + cq_verify(cqv); + + GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->details, "xyz")); + GPR_ASSERT(0 == + grpc_slice_str_cmp(rdata->call_details[s_idx].method, "/foo")); + GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].host, + "foo.test.google.fr")); + GPR_ASSERT(was_cancelled == 1); + + grpc_call_unref(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); + } + } + + GPR_ASSERT( + grpc_completion_queue_next( + f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL) + .type == GRPC_QUEUE_TIMEOUT); + + grpc_metadata_array_destroy(&rdata->initial_metadata_recv); + grpc_metadata_array_destroy(&rdata->trailing_metadata_recv); + + cq_verifier_destroy(cqv); + + grpc_call_unref(c); + + for (i = 0; i < f->num_servers; i++) { + grpc_call_details_destroy(&rdata->call_details[i]); + } + grpc_slice_unref(rdata->details); + } + + gpr_free(s_valid); + + return sequences; +} + +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 = static_cast( + gpr_malloc(sizeof(grpc_call *) * concurrent_calls)); + for (i = 0; i < f->num_servers; i++) { + kill_server(f, i); + } + + memset(ops, 0, sizeof(ops)); + 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; + + grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); + for (i = 0; i < concurrent_calls; i++) { + calls[i] = + grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, + grpc_slice_from_static_string("/foo"), &host, + 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; +} + +void run_spec(const test_spec *spec) { + grpc_channel *client; + char *client_hostport; + char *servers_hostports_str; + request_data rdata; + servers_fixture *f; + grpc_channel_args args; + grpc_arg arg_array[2]; + rdata.call_details = static_cast( + 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", servers_hostports_str); + + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = RETRY_TIMEOUT; + arg_array[1].type = GRPC_ARG_STRING; + arg_array[1].key = const_cast(GRPC_ARG_LB_POLICY_NAME); + arg_array[1].value.string = const_cast("round_robin"); + args.num_args = 2; + args.args = arg_array; + + 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); + + const request_sequences sequences = perform_request(f, client, &rdata, spec); + + spec->verifier(f, client, &sequences, spec->num_iters); + + gpr_free(client_hostport); + gpr_free(servers_hostports_str); + gpr_free(rdata.call_details); + request_sequences_destroy(&sequences); + + 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_array[3]; + 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", servers_hostports_str); + + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = RETRY_TIMEOUT; + arg_array[1].type = GRPC_ARG_STRING; + arg_array[1].key = const_cast(GRPC_ARG_LB_POLICY_NAME); + arg_array[1].value.string = const_cast("ROUND_ROBIN"); + arg_array[2].type = GRPC_ARG_INTEGER; + arg_array[2].key = + const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); + arg_array[2].value.integer = 0; + args.num_args = GPR_ARRAY_SIZE(arg_array); + args.args = arg_array; + + 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 = static_cast( + 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 = static_cast( + 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_unref(calls[i]); + } + gpr_free(calls); + teardown_servers(f); + test_spec_destroy(spec); +} + +static void test_get_channel_info() { + grpc_channel *channel = + grpc_insecure_channel_create("ipv4:127.0.0.1:1234", NULL, NULL); + // Ensures that resolver returns. + grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); + // First, request no fields. This is a no-op. + grpc_channel_info channel_info; + memset(&channel_info, 0, sizeof(channel_info)); + grpc_channel_get_info(channel, &channel_info); + // Request LB policy name. + char *lb_policy_name = NULL; + channel_info.lb_policy_name = &lb_policy_name; + grpc_channel_get_info(channel, &channel_info); + GPR_ASSERT(lb_policy_name != NULL); + GPR_ASSERT(strcmp(lb_policy_name, "pick_first") == 0); + gpr_free(lb_policy_name); + // Request service config, which does not exist, so we'll get nothing back. + memset(&channel_info, 0, sizeof(channel_info)); + char *service_config_json = const_cast("dummy_string"); + channel_info.service_config_json = &service_config_json; + grpc_channel_get_info(channel, &channel_info); + GPR_ASSERT(service_config_json == NULL); + // Recreate the channel such that it has a service config. + grpc_channel_destroy(channel); + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = + const_cast("{\"loadBalancingPolicy\": \"ROUND_ROBIN\"}"); + grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); + channel = grpc_insecure_channel_create("ipv4:127.0.0.1:1234", args, NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + // Ensures that resolver returns. + grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); + // Now request the service config again. + grpc_channel_get_info(channel, &channel_info); + GPR_ASSERT(service_config_json != NULL); + GPR_ASSERT(strcmp(service_config_json, arg.value.string) == 0); + gpr_free(service_config_json); + // Clean up. + grpc_channel_destroy(channel); +} + +static void print_failed_expectations(const int *expected_connection_sequence, + const int *actual_connection_sequence, + const size_t expected_seq_length, + const size_t num_iters) { + size_t i; + for (i = 0; i < num_iters; i++) { + gpr_log(GPR_ERROR, + "FAILURE: Iter (expected, actual): %" PRIuPTR " (%d, %d)", i, + expected_connection_sequence[i % expected_seq_length], + actual_connection_sequence[i]); + } +} + +static void verify_vanilla_round_robin(const servers_fixture *f, + grpc_channel *client, + const request_sequences *sequences, + const size_t num_iters) { + const size_t expected_seq_length = f->num_servers; + + /* verify conn. seq. expectation */ + /* get the first sequence of "num_servers" elements */ + int *expected_connection_sequence = + static_cast(gpr_malloc(sizeof(int) * expected_seq_length)); + memcpy(expected_connection_sequence, sequences->connections, + sizeof(int) * expected_seq_length); + + for (size_t i = 0; i < num_iters; i++) { + const int actual = sequences->connections[i]; + const int expected = expected_connection_sequence[i % expected_seq_length]; + if (actual != expected) { + gpr_log( + GPR_ERROR, + "CONNECTION SEQUENCE FAILURE: expected %d, got %d at iteration #%d", + expected, actual, (int)i); + abort(); + } + } + + /* All servers are available, therefore all client subchannels are READY, even + * when we only need one for the client channel state to be READY */ + for (size_t i = 0; i < sequences->n; i++) { + const grpc_connectivity_state actual = + static_cast(sequences->connectivity_states[i]); + const grpc_connectivity_state expected = GRPC_CHANNEL_READY; + if (actual != expected) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " + "at iteration #%d", + grpc_connectivity_state_name(expected), + grpc_connectivity_state_name(actual), (int)i); + abort(); + } + } + + gpr_free(expected_connection_sequence); +} + +/* At the start of the second iteration, all but the first and last servers (as + * given in "f") are killed */ +static void verify_vanishing_floor_round_robin( + const servers_fixture *f, grpc_channel *client, + const request_sequences *sequences, const size_t num_iters) { + int *expected_connection_sequence; + const size_t expected_seq_length = 2; + size_t i; + + /* verify conn. seq. expectation */ + /* copy the first full sequence (without -1s) */ + expected_connection_sequence = + static_cast(gpr_malloc(sizeof(int) * expected_seq_length)); + memcpy(expected_connection_sequence, sequences->connections + 2, + expected_seq_length * sizeof(int)); + + /* first two elements of the sequence should be [0 (1st server), -1 (failure)] + */ + GPR_ASSERT(sequences->connections[0] == 0); + GPR_ASSERT(sequences->connections[1] == -1); + + /* the next two element must be [3, 0], repeating from that point: the 3 is + * brought forth by servers 1 and 2 disappearing after the intial pick of 0 */ + GPR_ASSERT(sequences->connections[2] == 3); + GPR_ASSERT(sequences->connections[3] == 0); + + /* make sure that the expectation obliges */ + for (i = 2; i < num_iters; i++) { + const int actual = sequences->connections[i]; + const int expected = expected_connection_sequence[i % expected_seq_length]; + if (actual != expected) { + print_failed_expectations(expected_connection_sequence, + sequences->connections, expected_seq_length, + num_iters); + abort(); + } + } + + /* There's always at least one subchannel READY (connected), therefore the + * overall state of the client channel is READY at all times. */ + for (i = 0; i < sequences->n; i++) { + const grpc_connectivity_state actual = + static_cast(sequences->connectivity_states[i]); + const grpc_connectivity_state expected = GRPC_CHANNEL_READY; + if (actual != expected) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " + "at iteration #%d", + grpc_connectivity_state_name(expected), + grpc_connectivity_state_name(actual), (int)i); + abort(); + } + } + + gpr_free(expected_connection_sequence); +} + +static void verify_total_carnage_round_robin(const servers_fixture *f, + grpc_channel *client, + const request_sequences *sequences, + const size_t num_iters) { + for (size_t i = 0; i < num_iters; i++) { + const int actual = sequences->connections[i]; + const int expected = -1; + if (actual != expected) { + gpr_log( + GPR_ERROR, + "CONNECTION SEQUENCE FAILURE: expected %d, got %d at iteration #%d", + expected, actual, (int)i); + abort(); + } + } + + /* No server is ever available. There should be no READY states (or SHUTDOWN). + * Note that all other states (IDLE, CONNECTING, TRANSIENT_FAILURE) are still + * possible, as the policy transitions while attempting to reconnect. */ + for (size_t i = 0; i < sequences->n; i++) { + const grpc_connectivity_state actual = + static_cast(sequences->connectivity_states[i]); + if (actual == GRPC_CHANNEL_READY || actual == GRPC_CHANNEL_SHUTDOWN) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: got unexpected state " + "'%s' at iteration #%d.", + grpc_connectivity_state_name(actual), (int)i); + abort(); + } + } +} + +static void verify_partial_carnage_round_robin( + const servers_fixture *f, grpc_channel *client, + const request_sequences *sequences, const size_t num_iters) { + int *expected_connection_sequence; + size_t i; + const size_t expected_seq_length = f->num_servers; + + /* verify conn. seq. expectation */ + /* get the first sequence of "num_servers" elements */ + expected_connection_sequence = + static_cast(gpr_malloc(sizeof(int) * expected_seq_length)); + memcpy(expected_connection_sequence, sequences->connections, + sizeof(int) * expected_seq_length); + + for (i = 0; i < num_iters / 2; i++) { + const int actual = sequences->connections[i]; + const int expected = expected_connection_sequence[i % expected_seq_length]; + if (actual != expected) { + print_failed_expectations(expected_connection_sequence, + sequences->connections, expected_seq_length, + num_iters); + abort(); + } + } + + /* second half of the iterations go without response */ + for (; i < num_iters; i++) { + GPR_ASSERT(sequences->connections[i] == -1); + } + + /* We can assert that the first client channel state should be READY, when all + * servers were available */ + grpc_connectivity_state actual = + static_cast(sequences->connectivity_states[0]); + grpc_connectivity_state expected = GRPC_CHANNEL_READY; + if (actual != expected) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " + "at iteration #%d", + grpc_connectivity_state_name(expected), + grpc_connectivity_state_name(actual), 0); + abort(); + } + + /* ... and that the last one shouldn't be READY (or SHUTDOWN): all servers are + * gone. It may be all other states (IDLE, CONNECTING, TRANSIENT_FAILURE), as + * the policy transitions while attempting to reconnect. */ + actual = static_cast( + sequences->connectivity_states[num_iters - 1]); + for (i = 0; i < sequences->n; i++) { + if (actual == GRPC_CHANNEL_READY || actual == GRPC_CHANNEL_SHUTDOWN) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: got unexpected state " + "'%s' at iteration #%d.", + grpc_connectivity_state_name(actual), (int)i); + abort(); + } + } + gpr_free(expected_connection_sequence); +} + +static void dump_array(const char *desc, const int *data, const size_t count) { + gpr_strvec s; + char *tmp; + size_t i; + gpr_strvec_init(&s); + gpr_strvec_add(&s, gpr_strdup(desc)); + gpr_strvec_add(&s, gpr_strdup(":")); + for (i = 0; i < count; i++) { + gpr_asprintf(&tmp, " %d", data[i]); + gpr_strvec_add(&s, tmp); + } + tmp = gpr_strvec_flatten(&s, NULL); + gpr_strvec_destroy(&s); + gpr_log(GPR_DEBUG, "%s", tmp); + gpr_free(tmp); +} + +static void verify_rebirth_round_robin(const servers_fixture *f, + grpc_channel *client, + const request_sequences *sequences, + const size_t num_iters) { + dump_array("actual_connection_sequence", sequences->connections, num_iters); + + /* first iteration succeeds */ + GPR_ASSERT(sequences->connections[0] != -1); + /* then we fail for a while... */ + GPR_ASSERT(sequences->connections[1] == -1); + /* ... but should be up eventually */ + size_t first_iter_back_up = ~0ul; + for (size_t i = 2; i < sequences->n; ++i) { + if (sequences->connections[i] != -1) { + first_iter_back_up = i; + break; + } + } + GPR_ASSERT(first_iter_back_up != ~0ul); + + /* We can assert that the first client channel state should be READY, when all + * servers were available; same thing for the last one. In the middle + * somewhere there must exist at least one TRANSIENT_FAILURE */ + grpc_connectivity_state actual = + static_cast(sequences->connectivity_states[0]); + grpc_connectivity_state expected = GRPC_CHANNEL_READY; + if (actual != expected) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " + "at iteration #%d", + grpc_connectivity_state_name(expected), + grpc_connectivity_state_name(actual), 0); + abort(); + } + + actual = static_cast( + sequences->connectivity_states[num_iters - 1]); + expected = GRPC_CHANNEL_READY; + if (actual != expected) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " + "at iteration #%d", + grpc_connectivity_state_name(expected), + grpc_connectivity_state_name(actual), (int)num_iters - 1); + abort(); + } + + bool found_failure_status = false; + for (size_t i = 1; i < sequences->n - 1; i++) { + if (sequences->connectivity_states[i] == GRPC_CHANNEL_TRANSIENT_FAILURE) { + found_failure_status = true; + break; + } + } + if (!found_failure_status) { + gpr_log( + GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: " + "GRPC_CHANNEL_TRANSIENT_FAILURE status not found. Got the following " + "instead:"); + for (size_t i = 0; i < num_iters; i++) { + gpr_log(GPR_ERROR, "[%d]: %s", (int)i, + grpc_connectivity_state_name(static_cast( + sequences->connectivity_states[i]))); + } + } +} + +int main(int argc, char **argv) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + test_spec *spec; + size_t i; + const size_t NUM_ITERS = 10; + const size_t NUM_SERVERS = 4; + + grpc_init(); + grpc_test_init(argc, argv); + grpc_tracer_set_enabled("round_robin", 1); + + GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, "this-lb-policy-does-not-exist", + NULL) == NULL); + GPR_ASSERT(grpc_lb_policy_create(&exec_ctx, NULL, NULL) == NULL); + + 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); + + /* Kill all servers first thing in the morning */ + test_spec_reset(spec); + spec->verifier = verify_total_carnage_round_robin; + spec->description = "test_kill_all_server"; + for (i = 0; i < NUM_SERVERS; i++) { + spec->kill_at[0][i] = 1; + } + run_spec(spec); + + /* 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; + spec->description = "test_kill_middle_servers_at_2nd_iteration"; + for (i = 1; i < NUM_SERVERS - 1; i++) { + spec->kill_at[1][i] = 1; + } + run_spec(spec); + + /* Midway, kill all servers. */ + test_spec_reset(spec); + spec->verifier = verify_partial_carnage_round_robin; + spec->description = "test_kill_all_server_midway"; + for (i = 0; i < NUM_SERVERS; i++) { + spec->kill_at[spec->num_iters / 2][i] = 1; + } + run_spec(spec); + + /* After first iteration, kill all servers. On the third one, bring them all + * back up. */ + test_spec_reset(spec); + spec->verifier = verify_rebirth_round_robin; + spec->description = "test_kill_all_server_after_1st_resurrect_at_3rd"; + for (i = 0; i < NUM_SERVERS; i++) { + spec->kill_at[1][i] = 1; + spec->revive_at[3][i] = 1; + } + run_spec(spec); + test_spec_destroy(spec); + + test_pending_calls(4); + test_ping(); + test_get_channel_info(); + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} diff --git a/test/core/client_channel/parse_address_test.c b/test/core/client_channel/parse_address_test.c deleted file mode 100644 index d011176869..0000000000 --- a/test/core/client_channel/parse_address_test.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/filters/client_channel/parse_address.h" -#include "src/core/lib/iomgr/sockaddr.h" - -#include -#ifdef GRPC_HAVE_UNIX_SOCKET -#include -#endif - -#include - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/socket_utils.h" -#include "test/core/util/test_config.h" - -#ifdef GRPC_HAVE_UNIX_SOCKET - -static void test_grpc_parse_unix(const char *uri_text, const char *pathname) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - grpc_resolved_address addr; - - GPR_ASSERT(1 == grpc_parse_unix(uri, &addr)); - struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr; - GPR_ASSERT(AF_UNIX == addr_un->sun_family); - GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname)); - - grpc_uri_destroy(uri); - grpc_exec_ctx_finish(&exec_ctx); -} - -#else /* GRPC_HAVE_UNIX_SOCKET */ - -static void test_grpc_parse_unix(const char *uri_text, const char *pathname) {} - -#endif /* GRPC_HAVE_UNIX_SOCKET */ - -static void test_grpc_parse_ipv4(const char *uri_text, const char *host, - unsigned short port) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - grpc_resolved_address addr; - char ntop_buf[INET_ADDRSTRLEN]; - - GPR_ASSERT(1 == grpc_parse_ipv4(uri, &addr)); - struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr; - GPR_ASSERT(AF_INET == addr_in->sin_family); - GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf, - sizeof(ntop_buf))); - GPR_ASSERT(0 == strcmp(ntop_buf, host)); - GPR_ASSERT(ntohs(addr_in->sin_port) == port); - - grpc_uri_destroy(uri); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_grpc_parse_ipv6(const char *uri_text, const char *host, - unsigned short port, uint32_t scope_id) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - grpc_resolved_address addr; - char ntop_buf[INET6_ADDRSTRLEN]; - - GPR_ASSERT(1 == grpc_parse_ipv6(uri, &addr)); - struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr; - GPR_ASSERT(AF_INET6 == addr_in6->sin6_family); - GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf, - sizeof(ntop_buf))); - GPR_ASSERT(0 == strcmp(ntop_buf, host)); - GPR_ASSERT(ntohs(addr_in6->sin6_port) == port); - GPR_ASSERT(addr_in6->sin6_scope_id == scope_id); - - grpc_uri_destroy(uri); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - test_grpc_parse_unix("unix:/path/name", "/path/name"); - test_grpc_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345); - test_grpc_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0); - test_grpc_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2); -} diff --git a/test/core/client_channel/parse_address_test.cc b/test/core/client_channel/parse_address_test.cc new file mode 100644 index 0000000000..d011176869 --- /dev/null +++ b/test/core/client_channel/parse_address_test.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/lib/iomgr/sockaddr.h" + +#include +#ifdef GRPC_HAVE_UNIX_SOCKET +#include +#endif + +#include + +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/socket_utils.h" +#include "test/core/util/test_config.h" + +#ifdef GRPC_HAVE_UNIX_SOCKET + +static void test_grpc_parse_unix(const char *uri_text, const char *pathname) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + grpc_resolved_address addr; + + GPR_ASSERT(1 == grpc_parse_unix(uri, &addr)); + struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr; + GPR_ASSERT(AF_UNIX == addr_un->sun_family); + GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname)); + + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +#else /* GRPC_HAVE_UNIX_SOCKET */ + +static void test_grpc_parse_unix(const char *uri_text, const char *pathname) {} + +#endif /* GRPC_HAVE_UNIX_SOCKET */ + +static void test_grpc_parse_ipv4(const char *uri_text, const char *host, + unsigned short port) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + grpc_resolved_address addr; + char ntop_buf[INET_ADDRSTRLEN]; + + GPR_ASSERT(1 == grpc_parse_ipv4(uri, &addr)); + struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr; + GPR_ASSERT(AF_INET == addr_in->sin_family); + GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf, + sizeof(ntop_buf))); + GPR_ASSERT(0 == strcmp(ntop_buf, host)); + GPR_ASSERT(ntohs(addr_in->sin_port) == port); + + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_grpc_parse_ipv6(const char *uri_text, const char *host, + unsigned short port, uint32_t scope_id) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + grpc_resolved_address addr; + char ntop_buf[INET6_ADDRSTRLEN]; + + GPR_ASSERT(1 == grpc_parse_ipv6(uri, &addr)); + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr; + GPR_ASSERT(AF_INET6 == addr_in6->sin6_family); + GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf, + sizeof(ntop_buf))); + GPR_ASSERT(0 == strcmp(ntop_buf, host)); + GPR_ASSERT(ntohs(addr_in6->sin6_port) == port); + GPR_ASSERT(addr_in6->sin6_scope_id == scope_id); + + grpc_uri_destroy(uri); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + test_grpc_parse_unix("unix:/path/name", "/path/name"); + test_grpc_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345); + test_grpc_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0); + test_grpc_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2); +} diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c deleted file mode 100644 index 4597285063..0000000000 --- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/resolver.h" -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/combiner.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/timer.h" -#include "test/core/util/test_config.h" - -static gpr_mu g_mu; -static bool g_fail_resolution = true; -static grpc_combiner *g_combiner; - -static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, - const char *default_port, - grpc_pollset_set *interested_parties, - grpc_closure *on_done, - grpc_resolved_addresses **addrs) { - gpr_mu_lock(&g_mu); - GPR_ASSERT(0 == strcmp("test", addr)); - grpc_error *error = GRPC_ERROR_NONE; - if (g_fail_resolution) { - g_fail_resolution = false; - gpr_mu_unlock(&g_mu); - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); - } else { - gpr_mu_unlock(&g_mu); - *addrs = gpr_malloc(sizeof(**addrs)); - (*addrs)->naddrs = 1; - (*addrs)->addrs = gpr_malloc(sizeof(*(*addrs)->addrs)); - (*addrs)->addrs[0].len = 123; - } - GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); -} - -static grpc_ares_request *my_dns_lookup_ares( - grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, - const char *default_port, grpc_pollset_set *interested_parties, - grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, - char **service_config_json) { - gpr_mu_lock(&g_mu); - GPR_ASSERT(0 == strcmp("test", addr)); - grpc_error *error = GRPC_ERROR_NONE; - if (g_fail_resolution) { - g_fail_resolution = false; - gpr_mu_unlock(&g_mu); - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); - } else { - gpr_mu_unlock(&g_mu); - *lb_addrs = grpc_lb_addresses_create(1, NULL); - grpc_lb_addresses_set_address(*lb_addrs, 0, NULL, 0, false, NULL, NULL); - } - GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); - return NULL; -} - -static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx, - const char *name) { - grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns"); - grpc_uri *uri = grpc_uri_parse(exec_ctx, name, 0); - GPR_ASSERT(uri); - grpc_resolver_args args; - memset(&args, 0, sizeof(args)); - args.uri = uri; - args.combiner = g_combiner; - grpc_resolver *resolver = - grpc_resolver_factory_create_resolver(exec_ctx, factory, &args); - grpc_resolver_factory_unref(factory); - grpc_uri_destroy(uri); - return resolver; -} - -static void on_done(grpc_exec_ctx *exec_ctx, void *ev, grpc_error *error) { - gpr_event_set(ev, (void *)1); -} - -// interleave waiting for an event with a timer check -static bool wait_loop(int deadline_seconds, gpr_event *ev) { - while (deadline_seconds) { - gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds); - if (gpr_event_wait(ev, grpc_timeout_seconds_to_deadline(1))) return true; - deadline_seconds--; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_timer_check(&exec_ctx, NULL); - grpc_exec_ctx_finish(&exec_ctx); - } - return false; -} - -typedef struct next_args { - grpc_resolver *resolver; - grpc_channel_args **result; - grpc_closure *on_complete; -} next_args; - -static void call_resolver_next_now_lock_taken(grpc_exec_ctx *exec_ctx, - void *arg, - grpc_error *error_unused) { - next_args *a = arg; - grpc_resolver_next_locked(exec_ctx, a->resolver, a->result, a->on_complete); - gpr_free(a); -} - -static void call_resolver_next_after_locking(grpc_exec_ctx *exec_ctx, - grpc_resolver *resolver, - grpc_channel_args **result, - grpc_closure *on_complete) { - next_args *a = gpr_malloc(sizeof(*a)); - a->resolver = resolver; - a->result = result; - a->on_complete = on_complete; - GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE( - call_resolver_next_now_lock_taken, a, - grpc_combiner_scheduler(resolver->combiner)), - GRPC_ERROR_NONE); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - grpc_init(); - gpr_mu_init(&g_mu); - g_combiner = grpc_combiner_create(); - grpc_resolve_address = my_resolve_address; - grpc_dns_lookup_ares = my_dns_lookup_ares; - grpc_channel_args *result = (grpc_channel_args *)1; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test"); - gpr_event ev1; - gpr_event_init(&ev1); - call_resolver_next_after_locking( - &exec_ctx, resolver, &result, - GRPC_CLOSURE_CREATE(on_done, &ev1, grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(wait_loop(5, &ev1)); - GPR_ASSERT(result == NULL); - - gpr_event ev2; - gpr_event_init(&ev2); - call_resolver_next_after_locking( - &exec_ctx, resolver, &result, - GRPC_CLOSURE_CREATE(on_done, &ev2, grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(wait_loop(30, &ev2)); - GPR_ASSERT(result != NULL); - - grpc_channel_args_destroy(&exec_ctx, result); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); - GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_shutdown(); - gpr_mu_destroy(&g_mu); -} diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc new file mode 100644 index 0000000000..4dfee8cf90 --- /dev/null +++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc @@ -0,0 +1,182 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/resolver.h" +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/timer.h" +#include "test/core/util/test_config.h" + +static gpr_mu g_mu; +static bool g_fail_resolution = true; +static grpc_combiner *g_combiner; + +static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, + const char *default_port, + grpc_pollset_set *interested_parties, + grpc_closure *on_done, + grpc_resolved_addresses **addrs) { + gpr_mu_lock(&g_mu); + GPR_ASSERT(0 == strcmp("test", addr)); + grpc_error *error = GRPC_ERROR_NONE; + if (g_fail_resolution) { + g_fail_resolution = false; + gpr_mu_unlock(&g_mu); + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); + } else { + gpr_mu_unlock(&g_mu); + *addrs = + static_cast(gpr_malloc(sizeof(**addrs))); + (*addrs)->naddrs = 1; + (*addrs)->addrs = static_cast( + gpr_malloc(sizeof(*(*addrs)->addrs))); + (*addrs)->addrs[0].len = 123; + } + GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); +} + +static grpc_ares_request *my_dns_lookup_ares( + grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, + const char *default_port, grpc_pollset_set *interested_parties, + grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, + char **service_config_json) { + gpr_mu_lock(&g_mu); + GPR_ASSERT(0 == strcmp("test", addr)); + grpc_error *error = GRPC_ERROR_NONE; + if (g_fail_resolution) { + g_fail_resolution = false; + gpr_mu_unlock(&g_mu); + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); + } else { + gpr_mu_unlock(&g_mu); + *lb_addrs = grpc_lb_addresses_create(1, NULL); + grpc_lb_addresses_set_address(*lb_addrs, 0, NULL, 0, false, NULL, NULL); + } + GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); + return NULL; +} + +static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx, + const char *name) { + grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns"); + grpc_uri *uri = grpc_uri_parse(exec_ctx, name, 0); + GPR_ASSERT(uri); + grpc_resolver_args args; + memset(&args, 0, sizeof(args)); + args.uri = uri; + args.combiner = g_combiner; + grpc_resolver *resolver = + grpc_resolver_factory_create_resolver(exec_ctx, factory, &args); + grpc_resolver_factory_unref(factory); + grpc_uri_destroy(uri); + return resolver; +} + +static void on_done(grpc_exec_ctx *exec_ctx, void *ev, grpc_error *error) { + gpr_event_set((gpr_event *)ev, (void *)1); +} + +// interleave waiting for an event with a timer check +static bool wait_loop(int deadline_seconds, gpr_event *ev) { + while (deadline_seconds) { + gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds); + if (gpr_event_wait(ev, grpc_timeout_seconds_to_deadline(1))) return true; + deadline_seconds--; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_timer_check(&exec_ctx, NULL); + grpc_exec_ctx_finish(&exec_ctx); + } + return false; +} + +typedef struct next_args { + grpc_resolver *resolver; + grpc_channel_args **result; + grpc_closure *on_complete; +} next_args; + +static void call_resolver_next_now_lock_taken(grpc_exec_ctx *exec_ctx, + void *arg, + grpc_error *error_unused) { + next_args *a = static_cast(arg); + grpc_resolver_next_locked(exec_ctx, a->resolver, a->result, a->on_complete); + gpr_free(a); +} + +static void call_resolver_next_after_locking(grpc_exec_ctx *exec_ctx, + grpc_resolver *resolver, + grpc_channel_args **result, + grpc_closure *on_complete) { + next_args *a = static_cast(gpr_malloc(sizeof(*a))); + a->resolver = resolver; + a->result = result; + a->on_complete = on_complete; + GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE( + call_resolver_next_now_lock_taken, a, + grpc_combiner_scheduler(resolver->combiner)), + GRPC_ERROR_NONE); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + grpc_init(); + gpr_mu_init(&g_mu); + g_combiner = grpc_combiner_create(); + grpc_resolve_address = my_resolve_address; + grpc_dns_lookup_ares = my_dns_lookup_ares; + grpc_channel_args *result = (grpc_channel_args *)1; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test"); + gpr_event ev1; + gpr_event_init(&ev1); + call_resolver_next_after_locking( + &exec_ctx, resolver, &result, + GRPC_CLOSURE_CREATE(on_done, &ev1, grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(wait_loop(5, &ev1)); + GPR_ASSERT(result == NULL); + + gpr_event ev2; + gpr_event_init(&ev2); + call_resolver_next_after_locking( + &exec_ctx, resolver, &result, + GRPC_CLOSURE_CREATE(on_done, &ev2, grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(wait_loop(30, &ev2)); + GPR_ASSERT(result != NULL); + + grpc_channel_args_destroy(&exec_ctx, result); + GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); + GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_shutdown(); + gpr_mu_destroy(&g_mu); +} diff --git a/test/core/client_channel/resolvers/dns_resolver_test.c b/test/core/client_channel/resolvers/dns_resolver_test.c deleted file mode 100644 index a14926f173..0000000000 --- a/test/core/client_channel/resolvers/dns_resolver_test.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/iomgr/combiner.h" -#include "test/core/util/test_config.h" - -static grpc_combiner *g_combiner; - -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(&exec_ctx, 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.combiner = g_combiner; - resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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(&exec_ctx, 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; - args.combiner = g_combiner; - resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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); - grpc_init(); - - g_combiner = grpc_combiner_create(); - - dns = grpc_resolver_factory_lookup("dns"); - - test_succeeds(dns, "dns:10.2.1.1"); - test_succeeds(dns, "dns:10.2.1.1:1234"); - test_succeeds(dns, "ipv4:www.google.com"); - if (grpc_resolve_address == grpc_resolve_address_ares) { - test_succeeds(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); - } else { - test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); - } - - grpc_resolver_factory_unref(dns); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_shutdown(); - - return 0; -} diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc new file mode 100644 index 0000000000..a14926f173 --- /dev/null +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -0,0 +1,92 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/iomgr/combiner.h" +#include "test/core/util/test_config.h" + +static grpc_combiner *g_combiner; + +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(&exec_ctx, 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.combiner = g_combiner; + resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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(&exec_ctx, 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; + args.combiner = g_combiner; + resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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); + grpc_init(); + + g_combiner = grpc_combiner_create(); + + dns = grpc_resolver_factory_lookup("dns"); + + test_succeeds(dns, "dns:10.2.1.1"); + test_succeeds(dns, "dns:10.2.1.1:1234"); + test_succeeds(dns, "ipv4:www.google.com"); + if (grpc_resolve_address == grpc_resolve_address_ares) { + test_succeeds(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); + } else { + test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); + } + + grpc_resolver_factory_unref(dns); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_shutdown(); + + return 0; +} diff --git a/test/core/client_channel/resolvers/fake_resolver_test.c b/test/core/client_channel/resolvers/fake_resolver_test.c deleted file mode 100644 index 9b0854d6d8..0000000000 --- a/test/core/client_channel/resolvers/fake_resolver_test.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include - -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/parse_address.h" -#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/combiner.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" - -#include "test/core/util/test_config.h" - -static grpc_resolver *build_fake_resolver( - grpc_exec_ctx *exec_ctx, grpc_combiner *combiner, - grpc_fake_resolver_response_generator *response_generator) { - grpc_resolver_factory *factory = grpc_resolver_factory_lookup("fake"); - grpc_arg generator_arg = - grpc_fake_resolver_response_generator_arg(response_generator); - grpc_resolver_args args; - memset(&args, 0, sizeof(args)); - grpc_channel_args channel_args = {1, &generator_arg}; - args.args = &channel_args; - args.combiner = combiner; - grpc_resolver *resolver = - grpc_resolver_factory_create_resolver(exec_ctx, factory, &args); - grpc_resolver_factory_unref(factory); - return resolver; -} - -typedef struct on_resolution_arg { - grpc_channel_args *resolver_result; - grpc_channel_args *expected_resolver_result; - gpr_event ev; -} on_resolution_arg; - -void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - on_resolution_arg *res = arg; - // We only check the addresses channel arg because that's the only one - // explicitly set by the test via - // grpc_fake_resolver_response_generator_set_response. - const grpc_lb_addresses *actual_lb_addresses = - grpc_lb_addresses_find_channel_arg(res->resolver_result); - const grpc_lb_addresses *expected_lb_addresses = - grpc_lb_addresses_find_channel_arg(res->expected_resolver_result); - GPR_ASSERT( - grpc_lb_addresses_cmp(actual_lb_addresses, expected_lb_addresses) == 0); - grpc_channel_args_destroy(exec_ctx, res->resolver_result); - grpc_channel_args_destroy(exec_ctx, res->expected_resolver_result); - gpr_event_set(&res->ev, (void *)1); -} - -static void test_fake_resolver() { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_combiner *combiner = grpc_combiner_create(); - // Create resolver. - grpc_fake_resolver_response_generator *response_generator = - grpc_fake_resolver_response_generator_create(); - grpc_resolver *resolver = - build_fake_resolver(&exec_ctx, combiner, response_generator); - GPR_ASSERT(resolver != NULL); - - // Setup expectations. - grpc_uri *uris[] = {grpc_uri_parse(&exec_ctx, "ipv4:10.2.1.1:1234", true), - grpc_uri_parse(&exec_ctx, "ipv4:127.0.0.1:4321", true)}; - char *balancer_names[] = {"name1", "name2"}; - const bool is_balancer[] = {true, false}; - grpc_lb_addresses *addresses = grpc_lb_addresses_create(3, NULL); - for (size_t i = 0; i < GPR_ARRAY_SIZE(uris); ++i) { - grpc_lb_addresses_set_address_from_uri( - addresses, i, uris[i], is_balancer[i], balancer_names[i], NULL); - grpc_uri_destroy(uris[i]); - } - const grpc_arg addresses_arg = - grpc_lb_addresses_create_channel_arg(addresses); - grpc_channel_args *results = - grpc_channel_args_copy_and_add(NULL, &addresses_arg, 1); - grpc_lb_addresses_destroy(&exec_ctx, addresses); - on_resolution_arg on_res_arg; - memset(&on_res_arg, 0, sizeof(on_res_arg)); - on_res_arg.expected_resolver_result = results; - gpr_event_init(&on_res_arg.ev); - grpc_closure *on_resolution = GRPC_CLOSURE_CREATE( - on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner)); - - // Set resolver results and trigger first resolution. on_resolution_cb - // performs the checks. - grpc_fake_resolver_response_generator_set_response( - &exec_ctx, response_generator, results); - grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, - on_resolution); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, - grpc_timeout_seconds_to_deadline(5)) != NULL); - - // Setup update. - grpc_uri *uris_update[] = { - grpc_uri_parse(&exec_ctx, "ipv4:192.168.1.0:31416", true)}; - char *balancer_names_update[] = {"name3"}; - const bool is_balancer_update[] = {false}; - grpc_lb_addresses *addresses_update = grpc_lb_addresses_create(1, NULL); - for (size_t i = 0; i < GPR_ARRAY_SIZE(uris_update); ++i) { - grpc_lb_addresses_set_address_from_uri(addresses_update, i, uris_update[i], - is_balancer_update[i], - balancer_names_update[i], NULL); - grpc_uri_destroy(uris_update[i]); - } - - grpc_arg addresses_update_arg = - grpc_lb_addresses_create_channel_arg(addresses_update); - grpc_channel_args *results_update = - grpc_channel_args_copy_and_add(NULL, &addresses_update_arg, 1); - grpc_lb_addresses_destroy(&exec_ctx, addresses_update); - - // Setup expectations for the update. - on_resolution_arg on_res_arg_update; - memset(&on_res_arg_update, 0, sizeof(on_res_arg_update)); - on_res_arg_update.expected_resolver_result = results_update; - gpr_event_init(&on_res_arg_update.ev); - on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg_update, - grpc_combiner_scheduler(combiner)); - - // Set updated resolver results and trigger a second resolution. - grpc_fake_resolver_response_generator_set_response( - &exec_ctx, response_generator, results_update); - grpc_resolver_next_locked(&exec_ctx, resolver, - &on_res_arg_update.resolver_result, on_resolution); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&on_res_arg_update.ev, - grpc_timeout_seconds_to_deadline(5)) != NULL); - - // Requesting a new resolution without re-senting the response shouldn't - // trigger the resolution callback. - memset(&on_res_arg, 0, sizeof(on_res_arg)); - grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, - on_resolution); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - - GRPC_COMBINER_UNREF(&exec_ctx, combiner, "test_fake_resolver"); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_fake_resolver"); - grpc_exec_ctx_finish(&exec_ctx); - grpc_fake_resolver_response_generator_unref(response_generator); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - - test_fake_resolver(); - - grpc_shutdown(); - return 0; -} diff --git a/test/core/client_channel/resolvers/fake_resolver_test.cc b/test/core/client_channel/resolvers/fake_resolver_test.cc new file mode 100644 index 0000000000..ed14151ae3 --- /dev/null +++ b/test/core/client_channel/resolvers/fake_resolver_test.cc @@ -0,0 +1,177 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" + +#include "test/core/util/test_config.h" + +static grpc_resolver *build_fake_resolver( + grpc_exec_ctx *exec_ctx, grpc_combiner *combiner, + grpc_fake_resolver_response_generator *response_generator) { + grpc_resolver_factory *factory = grpc_resolver_factory_lookup("fake"); + grpc_arg generator_arg = + grpc_fake_resolver_response_generator_arg(response_generator); + grpc_resolver_args args; + memset(&args, 0, sizeof(args)); + grpc_channel_args channel_args = {1, &generator_arg}; + args.args = &channel_args; + args.combiner = combiner; + grpc_resolver *resolver = + grpc_resolver_factory_create_resolver(exec_ctx, factory, &args); + grpc_resolver_factory_unref(factory); + return resolver; +} + +typedef struct on_resolution_arg { + grpc_channel_args *resolver_result; + grpc_channel_args *expected_resolver_result; + gpr_event ev; +} on_resolution_arg; + +void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + on_resolution_arg *res = static_cast(arg); + // We only check the addresses channel arg because that's the only one + // explicitly set by the test via + // grpc_fake_resolver_response_generator_set_response. + const grpc_lb_addresses *actual_lb_addresses = + grpc_lb_addresses_find_channel_arg(res->resolver_result); + const grpc_lb_addresses *expected_lb_addresses = + grpc_lb_addresses_find_channel_arg(res->expected_resolver_result); + GPR_ASSERT( + grpc_lb_addresses_cmp(actual_lb_addresses, expected_lb_addresses) == 0); + grpc_channel_args_destroy(exec_ctx, res->resolver_result); + grpc_channel_args_destroy(exec_ctx, res->expected_resolver_result); + gpr_event_set(&res->ev, (void *)1); +} + +static void test_fake_resolver() { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner *combiner = grpc_combiner_create(); + // Create resolver. + grpc_fake_resolver_response_generator *response_generator = + grpc_fake_resolver_response_generator_create(); + grpc_resolver *resolver = + build_fake_resolver(&exec_ctx, combiner, response_generator); + GPR_ASSERT(resolver != NULL); + + // Setup expectations. + grpc_uri *uris[] = {grpc_uri_parse(&exec_ctx, "ipv4:10.2.1.1:1234", true), + grpc_uri_parse(&exec_ctx, "ipv4:127.0.0.1:4321", true)}; + const char *balancer_names[] = {"name1", "name2"}; + const bool is_balancer[] = {true, false}; + grpc_lb_addresses *addresses = grpc_lb_addresses_create(3, NULL); + for (size_t i = 0; i < GPR_ARRAY_SIZE(uris); ++i) { + grpc_lb_addresses_set_address_from_uri( + addresses, i, uris[i], is_balancer[i], balancer_names[i], NULL); + grpc_uri_destroy(uris[i]); + } + const grpc_arg addresses_arg = + grpc_lb_addresses_create_channel_arg(addresses); + grpc_channel_args *results = + grpc_channel_args_copy_and_add(NULL, &addresses_arg, 1); + grpc_lb_addresses_destroy(&exec_ctx, addresses); + on_resolution_arg on_res_arg; + memset(&on_res_arg, 0, sizeof(on_res_arg)); + on_res_arg.expected_resolver_result = results; + gpr_event_init(&on_res_arg.ev); + grpc_closure *on_resolution = GRPC_CLOSURE_CREATE( + on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner)); + + // Set resolver results and trigger first resolution. on_resolution_cb + // performs the checks. + grpc_fake_resolver_response_generator_set_response( + &exec_ctx, response_generator, results); + grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, + on_resolution); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, + grpc_timeout_seconds_to_deadline(5)) != NULL); + + // Setup update. + grpc_uri *uris_update[] = { + grpc_uri_parse(&exec_ctx, "ipv4:192.168.1.0:31416", true)}; + const char *balancer_names_update[] = {"name3"}; + const bool is_balancer_update[] = {false}; + grpc_lb_addresses *addresses_update = grpc_lb_addresses_create(1, NULL); + for (size_t i = 0; i < GPR_ARRAY_SIZE(uris_update); ++i) { + grpc_lb_addresses_set_address_from_uri(addresses_update, i, uris_update[i], + is_balancer_update[i], + balancer_names_update[i], NULL); + grpc_uri_destroy(uris_update[i]); + } + + grpc_arg addresses_update_arg = + grpc_lb_addresses_create_channel_arg(addresses_update); + grpc_channel_args *results_update = + grpc_channel_args_copy_and_add(NULL, &addresses_update_arg, 1); + grpc_lb_addresses_destroy(&exec_ctx, addresses_update); + + // Setup expectations for the update. + on_resolution_arg on_res_arg_update; + memset(&on_res_arg_update, 0, sizeof(on_res_arg_update)); + on_res_arg_update.expected_resolver_result = results_update; + gpr_event_init(&on_res_arg_update.ev); + on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg_update, + grpc_combiner_scheduler(combiner)); + + // Set updated resolver results and trigger a second resolution. + grpc_fake_resolver_response_generator_set_response( + &exec_ctx, response_generator, results_update); + grpc_resolver_next_locked(&exec_ctx, resolver, + &on_res_arg_update.resolver_result, on_resolution); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&on_res_arg_update.ev, + grpc_timeout_seconds_to_deadline(5)) != NULL); + + // Requesting a new resolution without re-senting the response shouldn't + // trigger the resolution callback. + memset(&on_res_arg, 0, sizeof(on_res_arg)); + grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, + on_resolution); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + + GRPC_COMBINER_UNREF(&exec_ctx, combiner, "test_fake_resolver"); + GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_fake_resolver"); + grpc_exec_ctx_finish(&exec_ctx); + grpc_fake_resolver_response_generator_unref(response_generator); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_fake_resolver(); + + grpc_shutdown(); + return 0; +} diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c deleted file mode 100644 index 8b88619164..0000000000 --- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include - -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/combiner.h" - -#include "test/core/util/test_config.h" - -static grpc_combiner *g_combiner; - -typedef struct on_resolution_arg { - char *expected_server_name; - grpc_channel_args *resolver_result; -} on_resolution_arg; - -void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - on_resolution_arg *res = arg; - grpc_channel_args_destroy(exec_ctx, res->resolver_result); -} - -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(&exec_ctx, 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.combiner = g_combiner; - resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); - GPR_ASSERT(resolver != NULL); - - on_resolution_arg on_res_arg; - memset(&on_res_arg, 0, sizeof(on_res_arg)); - on_res_arg.expected_server_name = uri->path; - grpc_closure *on_resolution = GRPC_CLOSURE_CREATE( - on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx); - - grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, - on_resolution); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); - grpc_exec_ctx_finish(&exec_ctx); - grpc_uri_destroy(uri); -} - -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(&exec_ctx, 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; - args.combiner = g_combiner; - resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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); - grpc_init(); - - g_combiner = grpc_combiner_create(); - - ipv4 = grpc_resolver_factory_lookup("ipv4"); - ipv6 = grpc_resolver_factory_lookup("ipv6"); - - test_fails(ipv4, "ipv4:10.2.1.1"); - test_succeeds(ipv4, "ipv4:10.2.1.1:1234"); - test_succeeds(ipv4, "ipv4:10.2.1.1:1234,127.0.0.1:4321"); - 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); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_shutdown(); - - return 0; -} diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc new file mode 100644 index 0000000000..254ce59bc2 --- /dev/null +++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc @@ -0,0 +1,122 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/combiner.h" + +#include "test/core/util/test_config.h" + +static grpc_combiner *g_combiner; + +typedef struct on_resolution_arg { + char *expected_server_name; + grpc_channel_args *resolver_result; +} on_resolution_arg; + +void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + on_resolution_arg *res = static_cast(arg); + grpc_channel_args_destroy(exec_ctx, res->resolver_result); +} + +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(&exec_ctx, 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.combiner = g_combiner; + resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); + GPR_ASSERT(resolver != NULL); + + on_resolution_arg on_res_arg; + memset(&on_res_arg, 0, sizeof(on_res_arg)); + on_res_arg.expected_server_name = uri->path; + grpc_closure *on_resolution = GRPC_CLOSURE_CREATE( + on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx); + + grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result, + on_resolution); + GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); + grpc_exec_ctx_finish(&exec_ctx); + grpc_uri_destroy(uri); +} + +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(&exec_ctx, 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; + args.combiner = g_combiner; + resolver = grpc_resolver_factory_create_resolver(&exec_ctx, 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); + grpc_init(); + + g_combiner = grpc_combiner_create(); + + ipv4 = grpc_resolver_factory_lookup("ipv4"); + ipv6 = grpc_resolver_factory_lookup("ipv6"); + + test_fails(ipv4, "ipv4:10.2.1.1"); + test_succeeds(ipv4, "ipv4:10.2.1.1:1234"); + test_succeeds(ipv4, "ipv4:10.2.1.1:1234,127.0.0.1:4321"); + 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); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_shutdown(); + + return 0; +} diff --git a/test/core/client_channel/uri_fuzzer_test.c b/test/core/client_channel/uri_fuzzer_test.c deleted file mode 100644 index e51d0031ec..0000000000 --- a/test/core/client_channel/uri_fuzzer_test.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include - -#include "src/core/ext/filters/client_channel/uri_parser.h" -#include "src/core/lib/iomgr/exec_ctx.h" - -bool squelch = true; -bool leak_check = true; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - char *s = gpr_malloc(size + 1); - memcpy(s, data, size); - s[size] = 0; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_uri *x; - if ((x = grpc_uri_parse(&exec_ctx, s, 1))) { - grpc_uri_destroy(x); - } - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(s); - return 0; -} diff --git a/test/core/client_channel/uri_fuzzer_test.cc b/test/core/client_channel/uri_fuzzer_test.cc new file mode 100644 index 0000000000..8c071454bc --- /dev/null +++ b/test/core/client_channel/uri_fuzzer_test.cc @@ -0,0 +1,44 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include + +#include "src/core/ext/filters/client_channel/uri_parser.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +bool squelch = true; +bool leak_check = true; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + char *s = static_cast(gpr_malloc(size + 1)); + memcpy(s, data, size); + s[size] = 0; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *x; + if ((x = grpc_uri_parse(&exec_ctx, s, 1))) { + grpc_uri_destroy(x); + } + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(s); + return 0; +} diff --git a/test/core/client_channel/uri_parser_test.c b/test/core/client_channel/uri_parser_test.c deleted file mode 100644 index f53cae196b..0000000000 --- a/test/core/client_channel/uri_parser_test.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/filters/client_channel/uri_parser.h" - -#include - -#include - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/util/test_config.h" - -static void test_succeeds(const char *uri_text, const char *scheme, - const char *authority, const char *path, - const char *query, const char *fragment) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - GPR_ASSERT(uri); - GPR_ASSERT(0 == strcmp(scheme, uri->scheme)); - GPR_ASSERT(0 == strcmp(authority, uri->authority)); - GPR_ASSERT(0 == strcmp(path, uri->path)); - GPR_ASSERT(0 == strcmp(query, uri->query)); - GPR_ASSERT(0 == strcmp(fragment, uri->fragment)); - grpc_exec_ctx_finish(&exec_ctx); - grpc_uri_destroy(uri); -} - -static void test_fails(const char *uri_text) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(NULL == grpc_uri_parse(&exec_ctx, uri_text, 0)); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_query_parts() { - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - const char *uri_text = "http://foo/path?a&b=B&c=&#frag"; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - GPR_ASSERT(uri); - - GPR_ASSERT(0 == strcmp("http", uri->scheme)); - GPR_ASSERT(0 == strcmp("foo", uri->authority)); - GPR_ASSERT(0 == strcmp("/path", uri->path)); - GPR_ASSERT(0 == strcmp("a&b=B&c=&", uri->query)); - GPR_ASSERT(4 == uri->num_query_parts); - - GPR_ASSERT(0 == strcmp("a", uri->query_parts[0])); - GPR_ASSERT(NULL == uri->query_parts_values[0]); - - GPR_ASSERT(0 == strcmp("b", uri->query_parts[1])); - GPR_ASSERT(0 == strcmp("B", uri->query_parts_values[1])); - - GPR_ASSERT(0 == strcmp("c", uri->query_parts[2])); - GPR_ASSERT(0 == strcmp("", uri->query_parts_values[2])); - - GPR_ASSERT(0 == strcmp("", uri->query_parts[3])); - GPR_ASSERT(NULL == uri->query_parts_values[3]); - - GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "a")); - GPR_ASSERT(0 == strcmp("B", grpc_uri_get_query_arg(uri, "b"))); - GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "c"))); - GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "")); - - GPR_ASSERT(0 == strcmp("frag", uri->fragment)); - grpc_exec_ctx_finish(&exec_ctx); - grpc_uri_destroy(uri); - } - { - /* test the current behavior of multiple query part values */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - const char *uri_text = "http://auth/path?foo=bar=baz&foobar=="; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - GPR_ASSERT(uri); - - GPR_ASSERT(0 == strcmp("http", uri->scheme)); - GPR_ASSERT(0 == strcmp("auth", uri->authority)); - GPR_ASSERT(0 == strcmp("/path", uri->path)); - GPR_ASSERT(0 == strcmp("foo=bar=baz&foobar==", uri->query)); - GPR_ASSERT(2 == uri->num_query_parts); - - GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo"))); - GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar"))); - - grpc_exec_ctx_finish(&exec_ctx); - grpc_uri_destroy(uri); - } - { - /* empty query */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - const char *uri_text = "http://foo/path"; - grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); - GPR_ASSERT(uri); - - GPR_ASSERT(0 == strcmp("http", uri->scheme)); - GPR_ASSERT(0 == strcmp("foo", uri->authority)); - GPR_ASSERT(0 == strcmp("/path", uri->path)); - GPR_ASSERT(0 == strcmp("", uri->query)); - GPR_ASSERT(0 == uri->num_query_parts); - GPR_ASSERT(NULL == uri->query_parts); - GPR_ASSERT(NULL == uri->query_parts_values); - GPR_ASSERT(0 == strcmp("", uri->fragment)); - grpc_exec_ctx_finish(&exec_ctx); - grpc_uri_destroy(uri); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_succeeds("http://www.google.com", "http", "www.google.com", "", "", ""); - test_succeeds("dns:///foo", "dns", "", "/foo", "", ""); - test_succeeds("http://www.google.com:90", "http", "www.google.com:90", "", "", - ""); - test_succeeds("a192.4-df:foo.coom", "a192.4-df", "", "foo.coom", "", ""); - test_succeeds("a+b:foo.coom", "a+b", "", "foo.coom", "", ""); - test_succeeds("zookeeper://127.0.0.1:2181/foo/bar", "zookeeper", - "127.0.0.1:2181", "/foo/bar", "", ""); - test_succeeds("http://www.google.com?yay-i'm-using-queries", "http", - "www.google.com", "", "yay-i'm-using-queries", ""); - test_succeeds("dns:foo.com#fragment-all-the-things", "dns", "", "foo.com", "", - "fragment-all-the-things"); - test_succeeds("http:?legit", "http", "", "", "legit", ""); - test_succeeds("unix:#this-is-ok-too", "unix", "", "", "", "this-is-ok-too"); - test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice"); - test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?"); - test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/"); - test_succeeds("ipv6:[2001:db8::1%252]:12345", "ipv6", "", - "[2001:db8::1%2]:12345", "", ""); - - test_fails("xyz"); - test_fails("http:?dangling-pct-%0"); - test_fails("http://foo?[bar]"); - test_fails("http://foo?x[bar]"); - test_fails("http://foo?bar#lol#"); - - test_query_parts(); - return 0; -} diff --git a/test/core/client_channel/uri_parser_test.cc b/test/core/client_channel/uri_parser_test.cc new file mode 100644 index 0000000000..f53cae196b --- /dev/null +++ b/test/core/client_channel/uri_parser_test.cc @@ -0,0 +1,152 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/filters/client_channel/uri_parser.h" + +#include + +#include + +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/util/test_config.h" + +static void test_succeeds(const char *uri_text, const char *scheme, + const char *authority, const char *path, + const char *query, const char *fragment) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + GPR_ASSERT(uri); + GPR_ASSERT(0 == strcmp(scheme, uri->scheme)); + GPR_ASSERT(0 == strcmp(authority, uri->authority)); + GPR_ASSERT(0 == strcmp(path, uri->path)); + GPR_ASSERT(0 == strcmp(query, uri->query)); + GPR_ASSERT(0 == strcmp(fragment, uri->fragment)); + grpc_exec_ctx_finish(&exec_ctx); + grpc_uri_destroy(uri); +} + +static void test_fails(const char *uri_text) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(NULL == grpc_uri_parse(&exec_ctx, uri_text, 0)); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_query_parts() { + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + const char *uri_text = "http://foo/path?a&b=B&c=&#frag"; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + GPR_ASSERT(uri); + + GPR_ASSERT(0 == strcmp("http", uri->scheme)); + GPR_ASSERT(0 == strcmp("foo", uri->authority)); + GPR_ASSERT(0 == strcmp("/path", uri->path)); + GPR_ASSERT(0 == strcmp("a&b=B&c=&", uri->query)); + GPR_ASSERT(4 == uri->num_query_parts); + + GPR_ASSERT(0 == strcmp("a", uri->query_parts[0])); + GPR_ASSERT(NULL == uri->query_parts_values[0]); + + GPR_ASSERT(0 == strcmp("b", uri->query_parts[1])); + GPR_ASSERT(0 == strcmp("B", uri->query_parts_values[1])); + + GPR_ASSERT(0 == strcmp("c", uri->query_parts[2])); + GPR_ASSERT(0 == strcmp("", uri->query_parts_values[2])); + + GPR_ASSERT(0 == strcmp("", uri->query_parts[3])); + GPR_ASSERT(NULL == uri->query_parts_values[3]); + + GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "a")); + GPR_ASSERT(0 == strcmp("B", grpc_uri_get_query_arg(uri, "b"))); + GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "c"))); + GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "")); + + GPR_ASSERT(0 == strcmp("frag", uri->fragment)); + grpc_exec_ctx_finish(&exec_ctx); + grpc_uri_destroy(uri); + } + { + /* test the current behavior of multiple query part values */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + const char *uri_text = "http://auth/path?foo=bar=baz&foobar=="; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + GPR_ASSERT(uri); + + GPR_ASSERT(0 == strcmp("http", uri->scheme)); + GPR_ASSERT(0 == strcmp("auth", uri->authority)); + GPR_ASSERT(0 == strcmp("/path", uri->path)); + GPR_ASSERT(0 == strcmp("foo=bar=baz&foobar==", uri->query)); + GPR_ASSERT(2 == uri->num_query_parts); + + GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo"))); + GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar"))); + + grpc_exec_ctx_finish(&exec_ctx); + grpc_uri_destroy(uri); + } + { + /* empty query */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + const char *uri_text = "http://foo/path"; + grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); + GPR_ASSERT(uri); + + GPR_ASSERT(0 == strcmp("http", uri->scheme)); + GPR_ASSERT(0 == strcmp("foo", uri->authority)); + GPR_ASSERT(0 == strcmp("/path", uri->path)); + GPR_ASSERT(0 == strcmp("", uri->query)); + GPR_ASSERT(0 == uri->num_query_parts); + GPR_ASSERT(NULL == uri->query_parts); + GPR_ASSERT(NULL == uri->query_parts_values); + GPR_ASSERT(0 == strcmp("", uri->fragment)); + grpc_exec_ctx_finish(&exec_ctx); + grpc_uri_destroy(uri); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_succeeds("http://www.google.com", "http", "www.google.com", "", "", ""); + test_succeeds("dns:///foo", "dns", "", "/foo", "", ""); + test_succeeds("http://www.google.com:90", "http", "www.google.com:90", "", "", + ""); + test_succeeds("a192.4-df:foo.coom", "a192.4-df", "", "foo.coom", "", ""); + test_succeeds("a+b:foo.coom", "a+b", "", "foo.coom", "", ""); + test_succeeds("zookeeper://127.0.0.1:2181/foo/bar", "zookeeper", + "127.0.0.1:2181", "/foo/bar", "", ""); + test_succeeds("http://www.google.com?yay-i'm-using-queries", "http", + "www.google.com", "", "yay-i'm-using-queries", ""); + test_succeeds("dns:foo.com#fragment-all-the-things", "dns", "", "foo.com", "", + "fragment-all-the-things"); + test_succeeds("http:?legit", "http", "", "", "legit", ""); + test_succeeds("unix:#this-is-ok-too", "unix", "", "", "", "this-is-ok-too"); + test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice"); + test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?"); + test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/"); + test_succeeds("ipv6:[2001:db8::1%252]:12345", "ipv6", "", + "[2001:db8::1%2]:12345", "", ""); + + test_fails("xyz"); + test_fails("http:?dangling-pct-%0"); + test_fails("http://foo?[bar]"); + test_fails("http://foo?x[bar]"); + test_fails("http://foo?bar#lol#"); + + test_query_parts(); + return 0; +} diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c deleted file mode 100644 index a11e6e90ac..0000000000 --- a/test/core/compression/algorithm_test.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/compression/algorithm_metadata.h" - -#include -#include - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/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++) { - const char *name; - grpc_compression_algorithm parsed; - grpc_slice mdstr; - grpc_mdelem mdelem; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT( - grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name)); - GPR_ASSERT(grpc_compression_algorithm_parse( - grpc_slice_from_static_string(name), &parsed)); - GPR_ASSERT((int)parsed == i); - mdstr = grpc_slice_from_copied_string(name); - GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed))); - GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr)); - mdelem = grpc_compression_encoding_mdelem(parsed); - GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr)); - GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING)); - grpc_slice_unref_internal(&exec_ctx, mdstr); - GRPC_MDELEM_UNREF(&exec_ctx, mdelem); - grpc_exec_ctx_finish(&exec_ctx); - } - - /* test failure */ - GPR_ASSERT(GRPC_MDISNULL( - grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT))); -} - -static void test_algorithm_failure(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice 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_slice_from_static_string("this-is-an-invalid-algorithm"); - GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) == - GRPC_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT(grpc_slice_eq( - grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT), - grpc_empty_slice())); - GPR_ASSERT(grpc_slice_eq( - grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT + 1), - grpc_empty_slice())); - grpc_slice_unref_internal(&exec_ctx, mdstr); - grpc_exec_ctx_finish(&exec_ctx); -} - -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/algorithm_test.cc b/test/core/compression/algorithm_test.cc new file mode 100644 index 0000000000..4ca979e30f --- /dev/null +++ b/test/core/compression/algorithm_test.cc @@ -0,0 +1,100 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/compression/algorithm_metadata.h" + +#include +#include + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/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++) { + const char *name; + grpc_compression_algorithm parsed; + grpc_slice mdstr; + grpc_mdelem mdelem; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT( + grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name)); + GPR_ASSERT(grpc_compression_algorithm_parse( + grpc_slice_from_static_string(name), &parsed)); + GPR_ASSERT((int)parsed == i); + mdstr = grpc_slice_from_copied_string(name); + GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed))); + GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr)); + mdelem = grpc_compression_encoding_mdelem(parsed); + GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr)); + GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING)); + grpc_slice_unref_internal(&exec_ctx, mdstr); + GRPC_MDELEM_UNREF(&exec_ctx, mdelem); + grpc_exec_ctx_finish(&exec_ctx); + } + + /* test failure */ + GPR_ASSERT(GRPC_MDISNULL( + grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT))); +} + +static void test_algorithm_failure(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice 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(static_cast( + GRPC_COMPRESS_ALGORITHMS_COUNT + 1), + NULL) == 0); + mdstr = grpc_slice_from_static_string("this-is-an-invalid-algorithm"); + GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) == + GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(grpc_slice_eq( + grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT), + grpc_empty_slice())); + GPR_ASSERT(grpc_slice_eq( + grpc_compression_algorithm_slice(static_cast( + static_cast(GRPC_COMPRESS_ALGORITHMS_COUNT) + 1)), + grpc_empty_slice())); + grpc_slice_unref_internal(&exec_ctx, mdstr); + grpc_exec_ctx_finish(&exec_ctx); +} + +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 deleted file mode 100644 index 326a800300..0000000000 --- a/test/core/compression/compression_test.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include - -#include "test/core/util/test_config.h" - -static void test_compression_algorithm_parse(void) { - 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}; - const char *invalid_names[] = {"gzip2", "foo", "", "2gzip"}; - - gpr_log(GPR_DEBUG, "test_compression_algorithm_parse"); - - for (i = 0; i < GPR_ARRAY_SIZE(valid_names); i++) { - const char *valid_name = valid_names[i]; - grpc_compression_algorithm algorithm; - const int success = grpc_compression_algorithm_parse( - grpc_slice_from_static_string(valid_name), &algorithm); - GPR_ASSERT(success != 0); - GPR_ASSERT(algorithm == valid_algorithms[i]); - } - - for (i = 0; i < GPR_ARRAY_SIZE(invalid_names); i++) { - const char *invalid_name = invalid_names[i]; - grpc_compression_algorithm algorithm; - int success; - success = grpc_compression_algorithm_parse( - grpc_slice_from_static_string(invalid_name), &algorithm); - GPR_ASSERT(success == 0); - /* the value of "algorithm" is undefined upon failure */ - } -} - -static void test_compression_algorithm_name(void) { - int success; - const 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) { - gpr_log(GPR_DEBUG, "test_compression_algorithm_for_level"); - - { - /* accept only identity (aka none) */ - uint32_t accepted_encodings = 0; - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, - accepted_encodings)); - } - - { - /* accept only gzip */ - uint32_t accepted_encodings = 0; - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_GZIP == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_GZIP == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_GZIP == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, - accepted_encodings)); - } - - { - /* accept only deflate */ - uint32_t accepted_encodings = 0; - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_DEFLATE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_DEFLATE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_DEFLATE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, - accepted_encodings)); - } - - { - /* accept gzip and deflate */ - uint32_t accepted_encodings = 0; - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP); - GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE); - - GPR_ASSERT(GRPC_COMPRESS_NONE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_GZIP == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_DEFLATE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, - accepted_encodings)); - - GPR_ASSERT(GRPC_COMPRESS_DEFLATE == - grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, - accepted_encodings)); - } -} - -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/compression_test.cc b/test/core/compression/compression_test.cc new file mode 100644 index 0000000000..f4fa3a8d63 --- /dev/null +++ b/test/core/compression/compression_test.cc @@ -0,0 +1,220 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include + +#include "test/core/util/test_config.h" + +static void test_compression_algorithm_parse(void) { + 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}; + const char *invalid_names[] = {"gzip2", "foo", "", "2gzip"}; + + gpr_log(GPR_DEBUG, "test_compression_algorithm_parse"); + + for (i = 0; i < GPR_ARRAY_SIZE(valid_names); i++) { + const char *valid_name = valid_names[i]; + grpc_compression_algorithm algorithm; + const int success = grpc_compression_algorithm_parse( + grpc_slice_from_static_string(valid_name), &algorithm); + GPR_ASSERT(success != 0); + GPR_ASSERT(algorithm == valid_algorithms[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(invalid_names); i++) { + const char *invalid_name = invalid_names[i]; + grpc_compression_algorithm algorithm; + int success; + success = grpc_compression_algorithm_parse( + grpc_slice_from_static_string(invalid_name), &algorithm); + GPR_ASSERT(success == 0); + /* the value of "algorithm" is undefined upon failure */ + } +} + +static void test_compression_algorithm_name(void) { + int success; + const 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) { + gpr_log(GPR_DEBUG, "test_compression_algorithm_for_level"); + + { + /* accept only identity (aka none) */ + uint32_t accepted_encodings = 0; + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, + accepted_encodings)); + } + + { + /* accept only gzip */ + uint32_t accepted_encodings = 0; + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_GZIP == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_GZIP == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_GZIP == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, + accepted_encodings)); + } + + { + /* accept only deflate */ + uint32_t accepted_encodings = 0; + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_DEFLATE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_DEFLATE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_DEFLATE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, + accepted_encodings)); + } + + { + /* accept gzip and deflate */ + uint32_t accepted_encodings = 0; + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */ + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP); + GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE); + + GPR_ASSERT(GRPC_COMPRESS_NONE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_GZIP == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_DEFLATE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED, + accepted_encodings)); + + GPR_ASSERT(GRPC_COMPRESS_DEFLATE == + grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH, + accepted_encodings)); + } +} + +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 = static_cast( + static_cast(algorithm) + 1)) { + /* 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 = static_cast( + static_cast(algorithm) + 1)) { + 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 = static_cast( + static_cast(algorithm) + 1)) { + 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 deleted file mode 100644 index f7f4893dee..0000000000 --- a/test/core/compression/message_compress_test.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/compression/message_compress.h" - -#include -#include - -#include -#include -#include - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/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; - -typedef enum { - SHOULD_NOT_COMPRESS, - SHOULD_COMPRESS, - MAYBE_COMPRESSES -} compressability; - -static void assert_passthrough(grpc_slice value, - grpc_compression_algorithm algorithm, - grpc_slice_split_mode uncompressed_split_mode, - grpc_slice_split_mode compressed_split_mode, - compressability compress_result_check) { - grpc_slice_buffer input; - grpc_slice_buffer compressed_raw; - grpc_slice_buffer compressed; - grpc_slice_buffer output; - grpc_slice final; - int was_compressed; - const char *algorithm_name; - - GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algorithm_name) != 0); - gpr_log( - GPR_INFO, "assert_passthrough: value_length=%" PRIuPTR - " value_hash=0x%08x " - "algorithm='%s' uncompressed_split='%s' compressed_split='%s'", - GRPC_SLICE_LENGTH(value), gpr_murmur_hash3(GRPC_SLICE_START_PTR(value), - GRPC_SLICE_LENGTH(value), 0), - algorithm_name, grpc_slice_split_mode_name(uncompressed_split_mode), - grpc_slice_split_mode_name(compressed_split_mode)); - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&compressed_raw); - grpc_slice_buffer_init(&compressed); - grpc_slice_buffer_init(&output); - - grpc_split_slices_to_buffer(uncompressed_split_mode, &value, 1, &input); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - was_compressed = - grpc_msg_compress(&exec_ctx, algorithm, &input, &compressed_raw); - grpc_exec_ctx_finish(&exec_ctx); - } - GPR_ASSERT(input.count > 0); - - switch (compress_result_check) { - case SHOULD_NOT_COMPRESS: - GPR_ASSERT(was_compressed == 0); - break; - case SHOULD_COMPRESS: - GPR_ASSERT(was_compressed == 1); - break; - case MAYBE_COMPRESSES: - /* no check */ - break; - } - - grpc_split_slice_buffer(compressed_split_mode, &compressed_raw, &compressed); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(grpc_msg_decompress( - &exec_ctx, was_compressed ? algorithm : GRPC_COMPRESS_NONE, &compressed, - &output)); - grpc_exec_ctx_finish(&exec_ctx); - } - - final = grpc_slice_merge(output.slices, output.count); - GPR_ASSERT(grpc_slice_eq(value, final)); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&compressed); - grpc_slice_buffer_destroy(&compressed_raw); - grpc_slice_buffer_destroy(&output); - grpc_slice_unref(final); -} - -static grpc_slice repeated(char c, size_t length) { - grpc_slice out = grpc_slice_malloc(length); - memset(GRPC_SLICE_START_PTR(out), c, length); - return out; -} - -static compressability get_compressability( - test_value id, grpc_compression_algorithm algorithm) { - if (algorithm == GRPC_COMPRESS_NONE) return SHOULD_NOT_COMPRESS; - switch (id) { - case ONE_A: - return SHOULD_NOT_COMPRESS; - case ONE_KB_A: - case ONE_MB_A: - return SHOULD_COMPRESS; - case TEST_VALUE_COUNT: - abort(); - break; - } - return MAYBE_COMPRESSES; -} - -static grpc_slice create_test_value(test_value id) { - switch (id) { - case ONE_A: - return grpc_slice_from_copied_string("a"); - case ONE_KB_A: - return repeated('a', 1024); - case ONE_MB_A: - return repeated('a', 1024 * 1024); - case TEST_VALUE_COUNT: - abort(); - break; - } - return grpc_slice_from_copied_string("bad value"); -} - -static void test_tiny_data_compress(void) { - grpc_slice_buffer input; - grpc_slice_buffer output; - grpc_compression_algorithm i; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&output); - grpc_slice_buffer_add(&input, create_test_value(ONE_A)); - - for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { - if (i == GRPC_COMPRESS_NONE) continue; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(0 == grpc_msg_compress(&exec_ctx, i, &input, &output)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(1 == output.count); - } - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&output); -} - -static void test_bad_decompression_data_crc(void) { - grpc_slice_buffer input; - grpc_slice_buffer corrupted; - grpc_slice_buffer output; - size_t idx; - const uint32_t bad = 0xdeadbeef; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&corrupted); - grpc_slice_buffer_init(&output); - grpc_slice_buffer_add(&input, create_test_value(ONE_MB_A)); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - /* compress it */ - grpc_msg_compress(&exec_ctx, GRPC_COMPRESS_GZIP, &input, &corrupted); - /* corrupt the output by smashing the CRC */ - GPR_ASSERT(corrupted.count > 1); - GPR_ASSERT(GRPC_SLICE_LENGTH(corrupted.slices[1]) > 8); - idx = GRPC_SLICE_LENGTH(corrupted.slices[1]) - 8; - memcpy(GRPC_SLICE_START_PTR(corrupted.slices[1]) + idx, &bad, 4); - - /* try (and fail) to decompress the corrupted compresed buffer */ - GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_GZIP, &corrupted, - &output)); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&corrupted); - grpc_slice_buffer_destroy(&output); -} - -static void test_bad_decompression_data_trailing_garbage(void) { - grpc_slice_buffer input; - grpc_slice_buffer output; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&output); - /* append 0x99 to the end of an otherwise valid stream */ - grpc_slice_buffer_add( - &input, grpc_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 */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_DEFLATE, &input, - &output)); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&output); -} - -static void test_bad_decompression_data_stream(void) { - grpc_slice_buffer input; - grpc_slice_buffer output; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&output); - grpc_slice_buffer_add(&input, - grpc_slice_from_copied_buffer("\x78\xda\xff\xff", 4)); - - /* try (and fail) to decompress the invalid compresed buffer */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_DEFLATE, &input, - &output)); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&output); -} - -static void test_bad_compression_algorithm(void) { - grpc_slice_buffer input; - grpc_slice_buffer output; - int was_compressed; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&output); - grpc_slice_buffer_add( - &input, grpc_slice_from_copied_string("Never gonna give you up")); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - was_compressed = grpc_msg_compress(&exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT, - &input, &output); - GPR_ASSERT(0 == was_compressed); - - was_compressed = grpc_msg_compress( - &exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT + 123, &input, &output); - GPR_ASSERT(0 == was_compressed); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&output); -} - -static void test_bad_decompression_algorithm(void) { - grpc_slice_buffer input; - grpc_slice_buffer output; - int was_decompressed; - - grpc_slice_buffer_init(&input); - grpc_slice_buffer_init(&output); - grpc_slice_buffer_add(&input, - grpc_slice_from_copied_string( - "I'm not really compressed but it doesn't matter")); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - was_decompressed = grpc_msg_decompress( - &exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); - GPR_ASSERT(0 == was_decompressed); - - was_decompressed = grpc_msg_decompress( - &exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT + 123, &input, &output); - GPR_ASSERT(0 == was_decompressed); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_slice_buffer_destroy(&input); - grpc_slice_buffer_destroy(&output); -} - -int main(int argc, char **argv) { - unsigned i, j, k, m; - grpc_slice_split_mode uncompressed_split_modes[] = { - GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; - grpc_slice_split_mode compressed_split_modes[] = {GRPC_SLICE_SPLIT_MERGE_ALL, - GRPC_SLICE_SPLIT_IDENTITY, - 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++) { - for (k = 0; k < GPR_ARRAY_SIZE(compressed_split_modes); k++) { - for (m = 0; m < TEST_VALUE_COUNT; m++) { - grpc_slice slice = create_test_value(m); - assert_passthrough(slice, i, j, k, get_compressability(m, i)); - grpc_slice_unref(slice); - } - } - } - } - - 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/compression/message_compress_test.cc b/test/core/compression/message_compress_test.cc new file mode 100644 index 0000000000..1395d42739 --- /dev/null +++ b/test/core/compression/message_compress_test.cc @@ -0,0 +1,330 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/compression/message_compress.h" + +#include +#include + +#include +#include +#include + +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/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; + +typedef enum { + SHOULD_NOT_COMPRESS, + SHOULD_COMPRESS, + MAYBE_COMPRESSES +} compressability; + +static void assert_passthrough(grpc_slice value, + grpc_compression_algorithm algorithm, + grpc_slice_split_mode uncompressed_split_mode, + grpc_slice_split_mode compressed_split_mode, + compressability compress_result_check) { + grpc_slice_buffer input; + grpc_slice_buffer compressed_raw; + grpc_slice_buffer compressed; + grpc_slice_buffer output; + grpc_slice final; + int was_compressed; + const char *algorithm_name; + + GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algorithm_name) != 0); + gpr_log( + GPR_INFO, "assert_passthrough: value_length=%" PRIuPTR + " value_hash=0x%08x " + "algorithm='%s' uncompressed_split='%s' compressed_split='%s'", + GRPC_SLICE_LENGTH(value), gpr_murmur_hash3(GRPC_SLICE_START_PTR(value), + GRPC_SLICE_LENGTH(value), 0), + algorithm_name, grpc_slice_split_mode_name(uncompressed_split_mode), + grpc_slice_split_mode_name(compressed_split_mode)); + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&compressed_raw); + grpc_slice_buffer_init(&compressed); + grpc_slice_buffer_init(&output); + + grpc_split_slices_to_buffer(uncompressed_split_mode, &value, 1, &input); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + was_compressed = + grpc_msg_compress(&exec_ctx, algorithm, &input, &compressed_raw); + grpc_exec_ctx_finish(&exec_ctx); + } + GPR_ASSERT(input.count > 0); + + switch (compress_result_check) { + case SHOULD_NOT_COMPRESS: + GPR_ASSERT(was_compressed == 0); + break; + case SHOULD_COMPRESS: + GPR_ASSERT(was_compressed == 1); + break; + case MAYBE_COMPRESSES: + /* no check */ + break; + } + + grpc_split_slice_buffer(compressed_split_mode, &compressed_raw, &compressed); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(grpc_msg_decompress( + &exec_ctx, was_compressed ? algorithm : GRPC_COMPRESS_NONE, &compressed, + &output)); + grpc_exec_ctx_finish(&exec_ctx); + } + + final = grpc_slice_merge(output.slices, output.count); + GPR_ASSERT(grpc_slice_eq(value, final)); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&compressed); + grpc_slice_buffer_destroy(&compressed_raw); + grpc_slice_buffer_destroy(&output); + grpc_slice_unref(final); +} + +static grpc_slice repeated(char c, size_t length) { + grpc_slice out = grpc_slice_malloc(length); + memset(GRPC_SLICE_START_PTR(out), c, length); + return out; +} + +static compressability get_compressability( + test_value id, grpc_compression_algorithm algorithm) { + if (algorithm == GRPC_COMPRESS_NONE) return SHOULD_NOT_COMPRESS; + switch (id) { + case ONE_A: + return SHOULD_NOT_COMPRESS; + case ONE_KB_A: + case ONE_MB_A: + return SHOULD_COMPRESS; + case TEST_VALUE_COUNT: + abort(); + break; + } + return MAYBE_COMPRESSES; +} + +static grpc_slice create_test_value(test_value id) { + switch (id) { + case ONE_A: + return grpc_slice_from_copied_string("a"); + case ONE_KB_A: + return repeated('a', 1024); + case ONE_MB_A: + return repeated('a', 1024 * 1024); + case TEST_VALUE_COUNT: + abort(); + break; + } + return grpc_slice_from_copied_string("bad value"); +} + +static void test_tiny_data_compress(void) { + grpc_slice_buffer input; + grpc_slice_buffer output; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&output); + grpc_slice_buffer_add(&input, create_test_value(ONE_A)); + + for (int i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (i == GRPC_COMPRESS_NONE) continue; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(0 == grpc_msg_compress( + &exec_ctx, static_cast(i), + &input, &output)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(1 == output.count); + } + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_data_crc(void) { + grpc_slice_buffer input; + grpc_slice_buffer corrupted; + grpc_slice_buffer output; + size_t idx; + const uint32_t bad = 0xdeadbeef; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&corrupted); + grpc_slice_buffer_init(&output); + grpc_slice_buffer_add(&input, create_test_value(ONE_MB_A)); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + /* compress it */ + grpc_msg_compress(&exec_ctx, GRPC_COMPRESS_GZIP, &input, &corrupted); + /* corrupt the output by smashing the CRC */ + GPR_ASSERT(corrupted.count > 1); + GPR_ASSERT(GRPC_SLICE_LENGTH(corrupted.slices[1]) > 8); + idx = GRPC_SLICE_LENGTH(corrupted.slices[1]) - 8; + memcpy(GRPC_SLICE_START_PTR(corrupted.slices[1]) + idx, &bad, 4); + + /* try (and fail) to decompress the corrupted compresed buffer */ + GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_GZIP, &corrupted, + &output)); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&corrupted); + grpc_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_data_trailing_garbage(void) { + grpc_slice_buffer input; + grpc_slice_buffer output; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&output); + /* append 0x99 to the end of an otherwise valid stream */ + grpc_slice_buffer_add( + &input, grpc_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 */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_DEFLATE, &input, + &output)); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_data_stream(void) { + grpc_slice_buffer input; + grpc_slice_buffer output; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&output); + grpc_slice_buffer_add(&input, + grpc_slice_from_copied_buffer("\x78\xda\xff\xff", 4)); + + /* try (and fail) to decompress the invalid compresed buffer */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(0 == grpc_msg_decompress(&exec_ctx, GRPC_COMPRESS_DEFLATE, &input, + &output)); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&output); +} + +static void test_bad_compression_algorithm(void) { + grpc_slice_buffer input; + grpc_slice_buffer output; + int was_compressed; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&output); + grpc_slice_buffer_add( + &input, grpc_slice_from_copied_string("Never gonna give you up")); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + was_compressed = grpc_msg_compress(&exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT, + &input, &output); + GPR_ASSERT(0 == was_compressed); + + was_compressed = + grpc_msg_compress(&exec_ctx, static_cast( + GRPC_COMPRESS_ALGORITHMS_COUNT + 123), + &input, &output); + GPR_ASSERT(0 == was_compressed); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&output); +} + +static void test_bad_decompression_algorithm(void) { + grpc_slice_buffer input; + grpc_slice_buffer output; + int was_decompressed; + + grpc_slice_buffer_init(&input); + grpc_slice_buffer_init(&output); + grpc_slice_buffer_add(&input, + grpc_slice_from_copied_string( + "I'm not really compressed but it doesn't matter")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + was_decompressed = grpc_msg_decompress( + &exec_ctx, GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); + GPR_ASSERT(0 == was_decompressed); + + was_decompressed = + grpc_msg_decompress(&exec_ctx, static_cast( + GRPC_COMPRESS_ALGORITHMS_COUNT + 123), + &input, &output); + GPR_ASSERT(0 == was_decompressed); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_slice_buffer_destroy(&input); + grpc_slice_buffer_destroy(&output); +} + +int main(int argc, char **argv) { + unsigned i, j, k, m; + grpc_slice_split_mode uncompressed_split_modes[] = { + GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; + grpc_slice_split_mode compressed_split_modes[] = {GRPC_SLICE_SPLIT_MERGE_ALL, + GRPC_SLICE_SPLIT_IDENTITY, + 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++) { + for (k = 0; k < GPR_ARRAY_SIZE(compressed_split_modes); k++) { + for (m = 0; m < TEST_VALUE_COUNT; m++) { + grpc_slice slice = create_test_value(static_cast(m)); + assert_passthrough( + slice, static_cast(i), + static_cast(j), + static_cast(k), + get_compressability(static_cast(m), + static_cast(i))); + grpc_slice_unref(slice); + } + } + } + } + + 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/compression/stream_compression_test.c b/test/core/compression/stream_compression_test.c deleted file mode 100644 index afed6cd6b5..0000000000 --- a/test/core/compression/stream_compression_test.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include - -#include "src/core/lib/compression/stream_compression.h" - -static void generate_random_payload(char *payload, size_t size) { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - for (i = 0; i < size - 1; ++i) { - payload[i] = chars[rand() % (int)(sizeof(chars) - 1)]; - } - payload[size - 1] = '\0'; -} - -static bool slice_buffer_equals_string(grpc_slice_buffer *buf, - const char *str) { - size_t i; - if (buf->length != strlen(str)) { - return false; - } - size_t pointer = 0; - for (i = 0; i < buf->count; i++) { - size_t slice_len = GRPC_SLICE_LENGTH(buf->slices[i]); - if (0 != strncmp(str + pointer, - (char *)GRPC_SLICE_START_PTR(buf->slices[i]), slice_len)) { - return false; - } - pointer += slice_len; - } - return true; -} - -static void test_stream_compression_simple_compress_decompress() { - const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; - grpc_slice_buffer source, relay, sink; - grpc_slice_buffer_init(&source); - grpc_slice_buffer_init(&relay); - grpc_slice_buffer_init(&sink); - grpc_stream_compression_context *compress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - grpc_stream_compression_context *decompress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - grpc_slice slice = grpc_slice_from_static_string(test_str); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - bool end_of_context; - size_t output_size; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(output_size == sizeof(test_str) - 1); - grpc_stream_compression_context_destroy(compress_ctx); - grpc_stream_compression_context_destroy(decompress_ctx); - - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); - - grpc_slice_buffer_destroy(&source); - grpc_slice_buffer_destroy(&relay); - grpc_slice_buffer_destroy(&sink); -} - -static void -test_stream_compression_simple_compress_decompress_with_output_size_constraint() { - const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; - grpc_slice_buffer source, relay, sink; - grpc_slice_buffer_init(&source); - grpc_slice_buffer_init(&relay); - grpc_slice_buffer_init(&sink); - grpc_stream_compression_context *compress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - grpc_stream_compression_context *decompress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - grpc_slice slice = grpc_slice_from_static_string(test_str); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - grpc_stream_compression_context_destroy(compress_ctx); - - bool end_of_context; - size_t output_size; - size_t max_output_size = 2; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - max_output_size, &end_of_context)); - GPR_ASSERT(output_size == max_output_size); - GPR_ASSERT(end_of_context == false); - grpc_slice slice_recv = grpc_slice_buffer_take_first(&sink); - char *str_recv = (char *)GRPC_SLICE_START_PTR(slice_recv); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice_recv) == max_output_size); - GPR_ASSERT(0 == strncmp(test_str, str_recv, max_output_size)); - grpc_slice_unref(slice_recv); - - size_t remaining_size = sizeof(test_str) - 1 - max_output_size; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - remaining_size, &end_of_context)); - GPR_ASSERT(output_size == remaining_size); - GPR_ASSERT(end_of_context == true); - - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str + max_output_size)); - - grpc_stream_compression_context_destroy(decompress_ctx); - grpc_slice_buffer_destroy(&source); - grpc_slice_buffer_destroy(&relay); - grpc_slice_buffer_destroy(&sink); -} - -#define LARGE_DATA_SIZE (1024 * 1024) -static void -test_stream_compression_simple_compress_decompress_with_large_data() { - char *test_str = gpr_malloc(LARGE_DATA_SIZE * sizeof(char)); - generate_random_payload(test_str, LARGE_DATA_SIZE); - grpc_slice_buffer source, relay, sink; - grpc_slice_buffer_init(&source); - grpc_slice_buffer_init(&relay); - grpc_slice_buffer_init(&sink); - grpc_stream_compression_context *compress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - grpc_stream_compression_context *decompress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - grpc_slice slice = grpc_slice_from_static_string(test_str); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - bool end_of_context; - size_t output_size; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(output_size == LARGE_DATA_SIZE - 1); - grpc_stream_compression_context_destroy(compress_ctx); - grpc_stream_compression_context_destroy(decompress_ctx); - - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); - - grpc_slice_buffer_destroy(&source); - grpc_slice_buffer_destroy(&relay); - grpc_slice_buffer_destroy(&sink); - gpr_free(test_str); -} - -static void test_stream_compression_drop_context() { - const char test_str[] = "aaaaaaabbbbbbbccccccc"; - const char test_str2[] = "dddddddeeeeeeefffffffggggg"; - grpc_slice_buffer source, relay, sink; - grpc_slice_buffer_init(&source); - grpc_slice_buffer_init(&relay); - grpc_slice_buffer_init(&sink); - grpc_stream_compression_context *compress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - grpc_slice slice = grpc_slice_from_static_string(test_str); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - grpc_stream_compression_context_destroy(compress_ctx); - - compress_ctx = grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - slice = grpc_slice_from_static_string(test_str2); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - grpc_stream_compression_context_destroy(compress_ctx); - - /* Concatenate the two compressed sliced into one to test decompressing two - * contexts */ - grpc_slice slice1 = grpc_slice_buffer_take_first(&relay); - grpc_slice slice2 = grpc_slice_buffer_take_first(&relay); - grpc_slice slice3 = - grpc_slice_malloc(GRPC_SLICE_LENGTH(slice1) + GRPC_SLICE_LENGTH(slice2)); - memcpy(GRPC_SLICE_START_PTR(slice3), GRPC_SLICE_START_PTR(slice1), - GRPC_SLICE_LENGTH(slice1)); - memcpy(GRPC_SLICE_START_PTR(slice3) + GRPC_SLICE_LENGTH(slice1), - GRPC_SLICE_START_PTR(slice2), GRPC_SLICE_LENGTH(slice2)); - grpc_slice_unref(slice1); - grpc_slice_unref(slice2); - grpc_slice_buffer_add(&relay, slice3); - - grpc_stream_compression_context *decompress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - bool end_of_context; - size_t output_size; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(end_of_context == true); - GPR_ASSERT(output_size == sizeof(test_str) - 1); - - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); - grpc_stream_compression_context_destroy(decompress_ctx); - grpc_slice_buffer_destroy(&sink); - - grpc_slice_buffer_init(&sink); - decompress_ctx = grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(end_of_context == true); - GPR_ASSERT(output_size == sizeof(test_str2) - 1); - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); - grpc_stream_compression_context_destroy(decompress_ctx); - - grpc_slice_buffer_destroy(&source); - grpc_slice_buffer_destroy(&relay); - grpc_slice_buffer_destroy(&sink); -} - -static void test_stream_compression_sync_flush() { - const char test_str[] = "aaaaaaabbbbbbbccccccc"; - const char test_str2[] = "dddddddeeeeeeefffffffggggg"; - grpc_slice_buffer source, relay, sink; - grpc_slice_buffer_init(&source); - grpc_slice_buffer_init(&relay); - grpc_slice_buffer_init(&sink); - grpc_stream_compression_context *compress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); - grpc_slice slice = grpc_slice_from_static_string(test_str); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_SYNC)); - - grpc_stream_compression_context *decompress_ctx = - grpc_stream_compression_context_create( - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - bool end_of_context; - size_t output_size; - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(end_of_context == false); - GPR_ASSERT(output_size == sizeof(test_str) - 1); - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); - grpc_slice_buffer_destroy(&sink); - - grpc_slice_buffer_init(&sink); - slice = grpc_slice_from_static_string(test_str2); - grpc_slice_buffer_add(&source, slice); - GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, - ~(size_t)0, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); - grpc_stream_compression_context_destroy(compress_ctx); - - GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, - ~(size_t)0, &end_of_context)); - GPR_ASSERT(end_of_context == true); - GPR_ASSERT(output_size == sizeof(test_str2) - 1); - GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); - grpc_stream_compression_context_destroy(decompress_ctx); - - grpc_slice_buffer_destroy(&source); - grpc_slice_buffer_destroy(&relay); - grpc_slice_buffer_destroy(&sink); -} - -int main(int argc, char **argv) { - grpc_init(); - test_stream_compression_simple_compress_decompress(); - test_stream_compression_simple_compress_decompress_with_output_size_constraint(); - test_stream_compression_simple_compress_decompress_with_large_data(); - test_stream_compression_sync_flush(); - test_stream_compression_drop_context(); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/compression/stream_compression_test.cc b/test/core/compression/stream_compression_test.cc new file mode 100644 index 0000000000..d136408710 --- /dev/null +++ b/test/core/compression/stream_compression_test.cc @@ -0,0 +1,298 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +#include "src/core/lib/compression/stream_compression.h" + +static void generate_random_payload(char *payload, size_t size) { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + for (i = 0; i < size - 1; ++i) { + payload[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + payload[size - 1] = '\0'; +} + +static bool slice_buffer_equals_string(grpc_slice_buffer *buf, + const char *str) { + size_t i; + if (buf->length != strlen(str)) { + return false; + } + size_t pointer = 0; + for (i = 0; i < buf->count; i++) { + size_t slice_len = GRPC_SLICE_LENGTH(buf->slices[i]); + if (0 != strncmp(str + pointer, + (char *)GRPC_SLICE_START_PTR(buf->slices[i]), slice_len)) { + return false; + } + pointer += slice_len; + } + return true; +} + +static void test_stream_compression_simple_compress_decompress() { + const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + grpc_stream_compression_context_destroy(compress_ctx); + grpc_stream_compression_context_destroy(decompress_ctx); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +static void +test_stream_compression_simple_compress_decompress_with_output_size_constraint() { + const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + bool end_of_context; + size_t output_size; + size_t max_output_size = 2; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + max_output_size, &end_of_context)); + GPR_ASSERT(output_size == max_output_size); + GPR_ASSERT(end_of_context == false); + grpc_slice slice_recv = grpc_slice_buffer_take_first(&sink); + char *str_recv = (char *)GRPC_SLICE_START_PTR(slice_recv); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_recv) == max_output_size); + GPR_ASSERT(0 == strncmp(test_str, str_recv, max_output_size)); + grpc_slice_unref(slice_recv); + + size_t remaining_size = sizeof(test_str) - 1 - max_output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + remaining_size, &end_of_context)); + GPR_ASSERT(output_size == remaining_size); + GPR_ASSERT(end_of_context == true); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str + max_output_size)); + + grpc_stream_compression_context_destroy(decompress_ctx); + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +#define LARGE_DATA_SIZE (1024 * 1024) +static void +test_stream_compression_simple_compress_decompress_with_large_data() { + char *test_str = + static_cast(gpr_malloc(LARGE_DATA_SIZE * sizeof(char))); + generate_random_payload(test_str, LARGE_DATA_SIZE); + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(output_size == LARGE_DATA_SIZE - 1); + grpc_stream_compression_context_destroy(compress_ctx); + grpc_stream_compression_context_destroy(decompress_ctx); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); + gpr_free(test_str); +} + +static void test_stream_compression_drop_context() { + const char test_str[] = "aaaaaaabbbbbbbccccccc"; + const char test_str2[] = "dddddddeeeeeeefffffffggggg"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + compress_ctx = grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + slice = grpc_slice_from_static_string(test_str2); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + /* Concatenate the two compressed sliced into one to test decompressing two + * contexts */ + grpc_slice slice1 = grpc_slice_buffer_take_first(&relay); + grpc_slice slice2 = grpc_slice_buffer_take_first(&relay); + grpc_slice slice3 = + grpc_slice_malloc(GRPC_SLICE_LENGTH(slice1) + GRPC_SLICE_LENGTH(slice2)); + memcpy(GRPC_SLICE_START_PTR(slice3), GRPC_SLICE_START_PTR(slice1), + GRPC_SLICE_LENGTH(slice1)); + memcpy(GRPC_SLICE_START_PTR(slice3) + GRPC_SLICE_LENGTH(slice1), + GRPC_SLICE_START_PTR(slice2), GRPC_SLICE_LENGTH(slice2)); + grpc_slice_unref(slice1); + grpc_slice_unref(slice2); + grpc_slice_buffer_add(&relay, slice3); + + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + grpc_stream_compression_context_destroy(decompress_ctx); + grpc_slice_buffer_destroy(&sink); + + grpc_slice_buffer_init(&sink); + decompress_ctx = grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str2) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); + grpc_stream_compression_context_destroy(decompress_ctx); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +static void test_stream_compression_sync_flush() { + const char test_str[] = "aaaaaaabbbbbbbccccccc"; + const char test_str2[] = "dddddddeeeeeeefffffffggggg"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_COMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_SYNC)); + + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == false); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + grpc_slice_buffer_destroy(&sink); + + grpc_slice_buffer_init(&sink); + slice = grpc_slice_from_static_string(test_str2); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str2) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); + grpc_stream_compression_context_destroy(decompress_ctx); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +int main(int argc, char **argv) { + grpc_init(); + test_stream_compression_simple_compress_decompress(); + test_stream_compression_simple_compress_decompress_with_output_size_constraint(); + test_stream_compression_simple_compress_decompress_with_large_data(); + test_stream_compression_sync_flush(); + test_stream_compression_drop_context(); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD index 49bfc43646..1589880e1f 100644 --- a/test/core/end2end/BUILD +++ b/test/core/end2end/BUILD @@ -22,7 +22,7 @@ load(":generate_tests.bzl", "grpc_end2end_tests") grpc_cc_library( name = "cq_verifier", - srcs = ["cq_verifier.c"], + srcs = ["cq_verifier.cc"], hdrs = ["cq_verifier.h"], language = "C", visibility = ["//test:__subpackages__"], @@ -36,9 +36,9 @@ grpc_cc_library( grpc_cc_library( name = "ssl_test_data", srcs = [ - "data/client_certs.c", - "data/server1_cert.c", - "data/server1_key.c", + "data/client_certs.cc", + "data/server1_cert.cc", + "data/server1_key.cc", "data/test_root_cert.c", ], hdrs = ["data/ssl_test_data.h"], @@ -49,7 +49,7 @@ grpc_cc_library( grpc_cc_library( name = "http_proxy", - srcs = ["fixtures/http_proxy_fixture.c"], + srcs = ["fixtures/http_proxy_fixture.cc"], hdrs = ["fixtures/http_proxy_fixture.h"], language = "C", deps = [ @@ -61,7 +61,7 @@ grpc_cc_library( grpc_cc_library( name = "proxy", - srcs = ["fixtures/proxy.c"], + srcs = ["fixtures/proxy.cc"], hdrs = ["fixtures/proxy.h"], language = "C", deps = [ diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c deleted file mode 100644 index 2070fa5b02..0000000000 --- a/test/core/end2end/bad_server_response_test.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" -#include "test/core/util/test_tcp_server.h" - -#define HTTP1_RESP \ - "HTTP/1.0 400 Bad Request\n" \ - "Content-Type: text/html; charset=UTF-8\n" \ - "Content-Length: 0\n" \ - "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n" - -#define HTTP2_RESP(STATUS_CODE) \ - "\x00\x00\x00\x04\x00\x00\x00\x00\x00" \ - "\x00\x00>\x01\x04\x00\x00\x00\x01" \ - "\x10\x0e" \ - "content-length\x01" \ - "0" \ - "\x10\x0c" \ - "content-type\x10" \ - "application/grpc" \ - "\x10\x07:status\x03" #STATUS_CODE - -#define UNPARSEABLE_RESP "Bad Request\n" - -#define HTTP2_DETAIL_MSG(STATUS_CODE) \ - "Received http2 header with status: " #STATUS_CODE - -#define HTTP1_DETAIL_MSG "Trying to connect an http1.x server" - -/* TODO(zyc) Check the content of incomming data instead of using this length */ -/* The 'bad' server will start sending responses after reading this amount of - * data from the client. */ -#define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200 - -struct rpc_state { - char *target; - grpc_completion_queue *cq; - grpc_channel *channel; - grpc_call *call; - size_t incoming_data_length; - grpc_slice_buffer temp_incoming_buffer; - grpc_slice_buffer outgoing_buffer; - grpc_endpoint *tcp; - gpr_atm done_atm; - bool write_done; - const char *response_payload; - size_t response_payload_length; -}; - -static int server_port; -static struct rpc_state state; -static grpc_closure on_read; -static grpc_closure on_write; - -static void *tag(intptr_t t) { return (void *)t; } - -static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_ASSERT(error == GRPC_ERROR_NONE); - - gpr_atm_rel_store(&state.done_atm, 1); -} - -static void handle_write(grpc_exec_ctx *exec_ctx) { - grpc_slice slice = grpc_slice_from_copied_buffer( - state.response_payload, state.response_payload_length); - - grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer); - grpc_slice_buffer_add(&state.outgoing_buffer, slice); - grpc_endpoint_write(exec_ctx, state.tcp, &state.outgoing_buffer, &on_write); -} - -static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_ASSERT(error == GRPC_ERROR_NONE); - state.incoming_data_length += state.temp_incoming_buffer.length; - - size_t i; - for (i = 0; i < state.temp_incoming_buffer.count; i++) { - char *dump = grpc_dump_slice(state.temp_incoming_buffer.slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "Server received: %s", dump); - gpr_free(dump); - } - - gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes", - state.incoming_data_length, - SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD); - if (state.incoming_data_length >= - SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD) { - handle_write(exec_ctx); - } 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, - grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - gpr_free(acceptor); - test_tcp_server *server = (test_tcp_server *)arg; - GRPC_CLOSURE_INIT(&on_read, handle_read, NULL, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&on_write, done_write, NULL, grpc_schedule_on_exec_ctx); - grpc_slice_buffer_init(&state.temp_incoming_buffer); - grpc_slice_buffer_init(&state.outgoing_buffer); - state.tcp = tcp; - state.incoming_data_length = 0; - grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset); - grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read); -} - -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 target_port, grpc_status_code expected_status, - const char *expected_detail) { - 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; - cq_verifier *cqv; - grpc_slice details; - - state.cq = grpc_completion_queue_create_for_next(NULL); - cqv = cq_verifier_create(state.cq); - gpr_join_host_port(&state.target, "127.0.0.1", target_port); - state.channel = grpc_insecure_channel_create(state.target, NULL, NULL); - grpc_slice host = grpc_slice_from_static_string("localhost"); - state.call = grpc_channel_create_call( - state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, - grpc_slice_from_static_string("/Service/Method"), &host, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - 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.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->flags = 0; - op->reserved = NULL; - op++; - error = - grpc_call_start_batch(state.call, ops, (size_t)(op - ops), tag(1), NULL); - - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == expected_status); - if (expected_detail != NULL) { - GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string( - expected_detail))); - } - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_slice_unref(details); - cq_verifier_destroy(cqv); -} - -static void cleanup_rpc(grpc_exec_ctx *exec_ctx) { - grpc_event ev; - grpc_slice_buffer_destroy_internal(exec_ctx, &state.temp_incoming_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &state.outgoing_buffer); - grpc_call_unref(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); -} - -typedef struct { - test_tcp_server *server; - gpr_event *signal_when_done; -} poll_args; - -static void actually_poll_server(void *arg) { - poll_args *pa = (poll_args *)arg; - gpr_timespec deadline = n_sec_deadline(10); - while (true) { - bool done = gpr_atm_acq_load(&state.done_atm) != 0; - gpr_timespec time_left = - gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME)); - gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done, - time_left.tv_sec, time_left.tv_nsec); - if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) { - break; - } - test_tcp_server_poll(pa->server, 1); - } - gpr_event_set(pa->signal_when_done, (void *)1); - gpr_free(pa); -} - -static void poll_server_until_read_done(test_tcp_server *server, - gpr_event *signal_when_done) { - gpr_atm_rel_store(&state.done_atm, 0); - state.write_done = 0; - gpr_thd_id id; - poll_args *pa = (poll_args *)gpr_malloc(sizeof(*pa)); - pa->server = server; - pa->signal_when_done = signal_when_done; - gpr_thd_new(&id, actually_poll_server, pa, NULL); -} - -static void run_test(const char *response_payload, - size_t response_payload_length, - grpc_status_code expected_status, - const char *expected_detail) { - test_tcp_server test_server; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_event ev; - - grpc_init(); - gpr_event_init(&ev); - 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); - state.response_payload = response_payload; - state.response_payload_length = response_payload_length; - - /* poll server until sending out the response */ - poll_server_until_read_done(&test_server, &ev); - start_rpc(server_port, expected_status, expected_detail); - gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); - - /* clean up */ - grpc_endpoint_shutdown(&exec_ctx, state.tcp, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - grpc_endpoint_destroy(&exec_ctx, state.tcp); - cleanup_rpc(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); - test_tcp_server_destroy(&test_server); - - grpc_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - /* status defined in hpack static table */ - run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(204)); - - run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(206)); - - run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(304)); - - run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(400)); - - run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(404)); - - run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(500)); - - /* status not defined in hpack static table */ - run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(401)); - - run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(403)); - - run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1, GRPC_STATUS_CANCELLED, - HTTP2_DETAIL_MSG(502)); - - /* unparseable response */ - run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN, - NULL); - - /* http1 response */ - run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE, - HTTP1_DETAIL_MSG); - - return 0; -} diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc new file mode 100644 index 0000000000..2070fa5b02 --- /dev/null +++ b/test/core/end2end/bad_server_response_test.cc @@ -0,0 +1,341 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/core/util/test_tcp_server.h" + +#define HTTP1_RESP \ + "HTTP/1.0 400 Bad Request\n" \ + "Content-Type: text/html; charset=UTF-8\n" \ + "Content-Length: 0\n" \ + "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n" + +#define HTTP2_RESP(STATUS_CODE) \ + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" \ + "\x00\x00>\x01\x04\x00\x00\x00\x01" \ + "\x10\x0e" \ + "content-length\x01" \ + "0" \ + "\x10\x0c" \ + "content-type\x10" \ + "application/grpc" \ + "\x10\x07:status\x03" #STATUS_CODE + +#define UNPARSEABLE_RESP "Bad Request\n" + +#define HTTP2_DETAIL_MSG(STATUS_CODE) \ + "Received http2 header with status: " #STATUS_CODE + +#define HTTP1_DETAIL_MSG "Trying to connect an http1.x server" + +/* TODO(zyc) Check the content of incomming data instead of using this length */ +/* The 'bad' server will start sending responses after reading this amount of + * data from the client. */ +#define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200 + +struct rpc_state { + char *target; + grpc_completion_queue *cq; + grpc_channel *channel; + grpc_call *call; + size_t incoming_data_length; + grpc_slice_buffer temp_incoming_buffer; + grpc_slice_buffer outgoing_buffer; + grpc_endpoint *tcp; + gpr_atm done_atm; + bool write_done; + const char *response_payload; + size_t response_payload_length; +}; + +static int server_port; +static struct rpc_state state; +static grpc_closure on_read; +static grpc_closure on_write; + +static void *tag(intptr_t t) { return (void *)t; } + +static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + + gpr_atm_rel_store(&state.done_atm, 1); +} + +static void handle_write(grpc_exec_ctx *exec_ctx) { + grpc_slice slice = grpc_slice_from_copied_buffer( + state.response_payload, state.response_payload_length); + + grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer); + grpc_slice_buffer_add(&state.outgoing_buffer, slice); + grpc_endpoint_write(exec_ctx, state.tcp, &state.outgoing_buffer, &on_write); +} + +static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + state.incoming_data_length += state.temp_incoming_buffer.length; + + size_t i; + for (i = 0; i < state.temp_incoming_buffer.count; i++) { + char *dump = grpc_dump_slice(state.temp_incoming_buffer.slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "Server received: %s", dump); + gpr_free(dump); + } + + gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes", + state.incoming_data_length, + SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD); + if (state.incoming_data_length >= + SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD) { + handle_write(exec_ctx); + } 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, + grpc_pollset *accepting_pollset, + grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); + test_tcp_server *server = (test_tcp_server *)arg; + GRPC_CLOSURE_INIT(&on_read, handle_read, NULL, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_write, done_write, NULL, grpc_schedule_on_exec_ctx); + grpc_slice_buffer_init(&state.temp_incoming_buffer); + grpc_slice_buffer_init(&state.outgoing_buffer); + state.tcp = tcp; + state.incoming_data_length = 0; + grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset); + grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read); +} + +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 target_port, grpc_status_code expected_status, + const char *expected_detail) { + 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; + cq_verifier *cqv; + grpc_slice details; + + state.cq = grpc_completion_queue_create_for_next(NULL); + cqv = cq_verifier_create(state.cq); + gpr_join_host_port(&state.target, "127.0.0.1", target_port); + state.channel = grpc_insecure_channel_create(state.target, NULL, NULL); + grpc_slice host = grpc_slice_from_static_string("localhost"); + state.call = grpc_channel_create_call( + state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, + grpc_slice_from_static_string("/Service/Method"), &host, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + 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.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->flags = 0; + op->reserved = NULL; + op++; + error = + grpc_call_start_batch(state.call, ops, (size_t)(op - ops), tag(1), NULL); + + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == expected_status); + if (expected_detail != NULL) { + GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string( + expected_detail))); + } + + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_slice_unref(details); + cq_verifier_destroy(cqv); +} + +static void cleanup_rpc(grpc_exec_ctx *exec_ctx) { + grpc_event ev; + grpc_slice_buffer_destroy_internal(exec_ctx, &state.temp_incoming_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &state.outgoing_buffer); + grpc_call_unref(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); +} + +typedef struct { + test_tcp_server *server; + gpr_event *signal_when_done; +} poll_args; + +static void actually_poll_server(void *arg) { + poll_args *pa = (poll_args *)arg; + gpr_timespec deadline = n_sec_deadline(10); + while (true) { + bool done = gpr_atm_acq_load(&state.done_atm) != 0; + gpr_timespec time_left = + gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME)); + gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done, + time_left.tv_sec, time_left.tv_nsec); + if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) { + break; + } + test_tcp_server_poll(pa->server, 1); + } + gpr_event_set(pa->signal_when_done, (void *)1); + gpr_free(pa); +} + +static void poll_server_until_read_done(test_tcp_server *server, + gpr_event *signal_when_done) { + gpr_atm_rel_store(&state.done_atm, 0); + state.write_done = 0; + gpr_thd_id id; + poll_args *pa = (poll_args *)gpr_malloc(sizeof(*pa)); + pa->server = server; + pa->signal_when_done = signal_when_done; + gpr_thd_new(&id, actually_poll_server, pa, NULL); +} + +static void run_test(const char *response_payload, + size_t response_payload_length, + grpc_status_code expected_status, + const char *expected_detail) { + test_tcp_server test_server; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_event ev; + + grpc_init(); + gpr_event_init(&ev); + 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); + state.response_payload = response_payload; + state.response_payload_length = response_payload_length; + + /* poll server until sending out the response */ + poll_server_until_read_done(&test_server, &ev); + start_rpc(server_port, expected_status, expected_detail); + gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); + + /* clean up */ + grpc_endpoint_shutdown(&exec_ctx, state.tcp, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + grpc_endpoint_destroy(&exec_ctx, state.tcp); + cleanup_rpc(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + test_tcp_server_destroy(&test_server); + + grpc_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + /* status defined in hpack static table */ + run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(204)); + + run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(206)); + + run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(304)); + + run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(400)); + + run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(404)); + + run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(500)); + + /* status not defined in hpack static table */ + run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(401)); + + run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(403)); + + run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1, GRPC_STATUS_CANCELLED, + HTTP2_DETAIL_MSG(502)); + + /* unparseable response */ + run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN, + NULL); + + /* http1 response */ + run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE, + HTTP1_DETAIL_MSG); + + return 0; +} diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c deleted file mode 100644 index 40227dece4..0000000000 --- a/test/core/end2end/connection_refused_test.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/service_config.h" - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static void *tag(intptr_t i) { return (void *)i; } - -static void run_test(bool wait_for_ready, bool use_service_config) { - grpc_channel *chan; - grpc_call *call; - grpc_completion_queue *cq; - cq_verifier *cqv; - grpc_op ops[6]; - grpc_op *op; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - grpc_slice details; - - gpr_log(GPR_INFO, "TEST: wait_for_ready=%d use_service_config=%d", - wait_for_ready, use_service_config); - - grpc_init(); - - grpc_metadata_array_init(&trailing_metadata_recv); - - cq = grpc_completion_queue_create_for_next(NULL); - cqv = cq_verifier_create(cq); - - /* if using service config, create channel args */ - grpc_channel_args *args = NULL; - if (use_service_config) { - GPR_ASSERT(wait_for_ready); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"waitForReady\": true\n" - " } ]\n" - "}"; - args = grpc_channel_args_copy_and_add(args, &arg, 1); - } - - /* create a call, channel to a port which will refuse connection */ - int port = grpc_pick_unused_port_or_die(); - char *addr; - gpr_join_host_port(&addr, "127.0.0.1", port); - gpr_log(GPR_INFO, "server: %s", addr); - chan = grpc_insecure_channel_create(addr, args, NULL); - grpc_slice host = grpc_slice_from_static_string("nonexistant"); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2); - call = grpc_channel_create_call( - chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/service/method"), &host, deadline, NULL); - - gpr_free(addr); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = (wait_for_ready && !use_service_config) - ? GRPC_INITIAL_METADATA_WAIT_FOR_READY - : 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->flags = 0; - op->reserved = NULL; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( - call, ops, (size_t)(op - ops), tag(1), NULL)); - /* verify that all tags get completed */ - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - if (wait_for_ready) { - GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); - } else { - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - } - - grpc_completion_queue_shutdown(cq); - while ( - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type != GRPC_QUEUE_SHUTDOWN) - ; - grpc_completion_queue_destroy(cq); - grpc_call_unref(call); - grpc_channel_destroy(chan); - cq_verifier_destroy(cqv); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - if (args != NULL) grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - - grpc_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - run_test(false /* wait_for_ready */, false /* use_service_config */); - run_test(true /* wait_for_ready */, false /* use_service_config */); - run_test(true /* wait_for_ready */, true /* use_service_config */); - return 0; -} diff --git a/test/core/end2end/connection_refused_test.cc b/test/core/end2end/connection_refused_test.cc new file mode 100644 index 0000000000..b295682ce8 --- /dev/null +++ b/test/core/end2end/connection_refused_test.cc @@ -0,0 +1,148 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/service_config.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void *tag(intptr_t i) { return (void *)i; } + +static void run_test(bool wait_for_ready, bool use_service_config) { + grpc_channel *chan; + grpc_call *call; + grpc_completion_queue *cq; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array trailing_metadata_recv; + grpc_status_code status; + grpc_slice details; + + gpr_log(GPR_INFO, "TEST: wait_for_ready=%d use_service_config=%d", + wait_for_ready, use_service_config); + + grpc_init(); + + grpc_metadata_array_init(&trailing_metadata_recv); + + cq = grpc_completion_queue_create_for_next(NULL); + cqv = cq_verifier_create(cq); + + /* if using service config, create channel args */ + grpc_channel_args *args = NULL; + if (use_service_config) { + GPR_ASSERT(wait_for_ready); + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"waitForReady\": true\n" + " } ]\n" + "}"); + args = grpc_channel_args_copy_and_add(args, &arg, 1); + } + + /* create a call, channel to a port which will refuse connection */ + int port = grpc_pick_unused_port_or_die(); + char *addr; + gpr_join_host_port(&addr, "127.0.0.1", port); + gpr_log(GPR_INFO, "server: %s", addr); + chan = grpc_insecure_channel_create(addr, args, NULL); + grpc_slice host = grpc_slice_from_static_string("nonexistant"); + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2); + call = grpc_channel_create_call( + chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/service/method"), &host, deadline, NULL); + + gpr_free(addr); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = (wait_for_ready && !use_service_config) + ? GRPC_INITIAL_METADATA_WAIT_FOR_READY + : 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->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( + call, ops, (size_t)(op - ops), tag(1), NULL)); + /* verify that all tags get completed */ + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + if (wait_for_ready) { + GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); + } else { + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } + + grpc_completion_queue_shutdown(cq); + while ( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type != GRPC_QUEUE_SHUTDOWN) + ; + grpc_completion_queue_destroy(cq); + grpc_call_unref(call); + grpc_channel_destroy(chan); + cq_verifier_destroy(cqv); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + if (args != NULL) grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + + grpc_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + run_test(false /* wait_for_ready */, false /* use_service_config */); + run_test(true /* wait_for_ready */, false /* use_service_config */); + run_test(true /* wait_for_ready */, true /* use_service_config */); + return 0; +} diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c deleted file mode 100644 index bb978923b2..0000000000 --- a/test/core/end2end/cq_verifier.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/cq_verifier.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/event_string.h" - -#define ROOT_EXPECTATION 1000 - -/* a set of metadata we expect to find on an event */ -typedef struct metadata { - size_t count; - size_t cap; - char **keys; - char **values; -} metadata; - -/* details what we expect to find on a single event - and forms a linked - list to detail other expectations */ -typedef struct expectation { - struct expectation *next; - const char *file; - int line; - grpc_completion_type type; - void *tag; - int success; -} expectation; - -/* the verifier itself */ -struct cq_verifier { - /* bound completion queue */ - grpc_completion_queue *cq; - /* start of expectation list */ - expectation *first_expectation; -}; - -cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { - cq_verifier *v = (cq_verifier *)gpr_malloc(sizeof(cq_verifier)); - v->cq = cq; - v->first_expectation = NULL; - return v; -} - -void cq_verifier_destroy(cq_verifier *v) { - cq_verify(v); - gpr_free(v); -} - -static int has_metadata(const grpc_metadata *md, size_t count, const char *key, - const char *value) { - size_t i; - for (i = 0; i < count; i++) { - if (0 == grpc_slice_str_cmp(md[i].key, key) && - 0 == grpc_slice_str_cmp(md[i].value, value)) { - return 1; - } - } - return 0; -} - -int contains_metadata(grpc_metadata_array *array, const char *key, - const char *value) { - return has_metadata(array->metadata, array->count, key, value); -} - -static int has_metadata_slices(const grpc_metadata *md, size_t count, - grpc_slice key, grpc_slice value) { - size_t i; - for (i = 0; i < count; i++) { - if (grpc_slice_eq(md[i].key, key) && grpc_slice_eq(md[i].value, value)) { - return 1; - } - } - return 0; -} - -int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key, - grpc_slice value) { - return has_metadata_slices(array->metadata, array->count, key, value); -} - -static grpc_slice merge_slices(grpc_slice *slices, size_t nslices) { - size_t i; - size_t len = 0; - uint8_t *cursor; - grpc_slice out; - - for (i = 0; i < nslices; i++) { - len += GRPC_SLICE_LENGTH(slices[i]); - } - - out = grpc_slice_malloc(len); - cursor = GRPC_SLICE_START_PTR(out); - - for (i = 0; i < nslices; i++) { - memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]), - GRPC_SLICE_LENGTH(slices[i])); - cursor += GRPC_SLICE_LENGTH(slices[i]); - } - - return out; -} - -int raw_byte_buffer_eq_slice(grpc_byte_buffer *rbb, grpc_slice b) { - grpc_slice a; - int ok; - - if (!rbb) return 0; - - a = merge_slices(rbb->data.raw.slice_buffer.slices, - rbb->data.raw.slice_buffer.count); - ok = GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b) && - 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), - GRPC_SLICE_LENGTH(a)); - grpc_slice_unref(a); - grpc_slice_unref(b); - return ok; -} - -int byte_buffer_eq_slice(grpc_byte_buffer *bb, grpc_slice b) { - grpc_byte_buffer_reader reader; - grpc_byte_buffer *rbb; - int res; - - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, bb) && - "Couldn't init byte buffer reader"); - rbb = grpc_raw_byte_buffer_from_reader(&reader); - res = raw_byte_buffer_eq_slice(rbb, b); - grpc_byte_buffer_reader_destroy(&reader); - grpc_byte_buffer_destroy(rbb); - - return res; -} - -int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) { - grpc_byte_buffer_reader reader; - grpc_byte_buffer *rbb; - int res; - - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, bb) && - "Couldn't init byte buffer reader"); - rbb = grpc_raw_byte_buffer_from_reader(&reader); - res = raw_byte_buffer_eq_slice(rbb, grpc_slice_from_copied_string(str)); - grpc_byte_buffer_reader_destroy(&reader); - grpc_byte_buffer_destroy(rbb); - - return res; -} - -static bool is_probably_integer(void *p) { return ((uintptr_t)p) < 1000000; } - -static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { - char *tmp; - - if (is_probably_integer(e->tag)) { - gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag); - } else { - gpr_asprintf(&tmp, "%p ", e->tag); - } - gpr_strvec_add(buf, tmp); - - switch (e->type) { - case GRPC_OP_COMPLETE: - gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success, - e->file, e->line); - gpr_strvec_add(buf, tmp); - break; - case GRPC_QUEUE_TIMEOUT: - case GRPC_QUEUE_SHUTDOWN: - gpr_log(GPR_ERROR, "not implemented"); - abort(); - break; - } -} - -static void expectations_to_strvec(gpr_strvec *buf, cq_verifier *v) { - expectation *e; - - for (e = v->first_expectation; e != NULL; e = e->next) { - expectation_to_strvec(buf, e); - gpr_strvec_add(buf, gpr_strdup("\n")); - } -} - -static void fail_no_event_received(cq_verifier *v) { - gpr_strvec buf; - char *msg; - gpr_strvec_init(&buf); - gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n")); - expectations_to_strvec(&buf, v); - msg = gpr_strvec_flatten(&buf, NULL); - gpr_log(GPR_ERROR, "%s", msg); - gpr_strvec_destroy(&buf); - gpr_free(msg); - abort(); -} - -static void verify_matches(expectation *e, grpc_event *ev) { - GPR_ASSERT(e->type == ev->type); - switch (e->type) { - case GRPC_OP_COMPLETE: - if (e->success != ev->success) { - gpr_strvec expected; - gpr_strvec_init(&expected); - expectation_to_strvec(&expected, e); - char *s = gpr_strvec_flatten(&expected, NULL); - gpr_strvec_destroy(&expected); - gpr_log(GPR_ERROR, "actual success does not match expected: %s", s); - gpr_free(s); - abort(); - } - break; - case GRPC_QUEUE_SHUTDOWN: - gpr_log(GPR_ERROR, "premature queue shutdown"); - abort(); - break; - case GRPC_QUEUE_TIMEOUT: - gpr_log(GPR_ERROR, "not implemented"); - abort(); - break; - } -} - -void cq_verify(cq_verifier *v) { - const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - while (v->first_expectation != NULL) { - grpc_event ev = grpc_completion_queue_next(v->cq, deadline, NULL); - if (ev.type == GRPC_QUEUE_TIMEOUT) { - fail_no_event_received(v); - break; - } - expectation *e; - expectation *prev = NULL; - for (e = v->first_expectation; e != NULL; e = e->next) { - if (e->tag == ev.tag) { - verify_matches(e, &ev); - if (e == v->first_expectation) v->first_expectation = e->next; - if (prev != NULL) prev->next = e->next; - gpr_free(e); - break; - } - prev = e; - } - if (e == NULL) { - char *s = grpc_event_string(&ev); - gpr_log(GPR_ERROR, "cq returned unexpected event: %s", s); - gpr_free(s); - gpr_strvec expectations; - gpr_strvec_init(&expectations); - expectations_to_strvec(&expectations, v); - s = gpr_strvec_flatten(&expectations, NULL); - gpr_strvec_destroy(&expectations); - gpr_log(GPR_ERROR, "expected tags:\n%s", s); - gpr_free(s); - abort(); - } - } -} - -void cq_verify_empty_timeout(cq_verifier *v, int timeout_sec) { - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(timeout_sec, GPR_TIMESPAN)); - grpc_event ev; - - GPR_ASSERT(v->first_expectation == NULL && "expectation queue must be empty"); - - ev = grpc_completion_queue_next(v->cq, deadline, NULL); - if (ev.type != GRPC_QUEUE_TIMEOUT) { - char *s = grpc_event_string(&ev); - gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s); - gpr_free(s); - abort(); - } -} - -void cq_verify_empty(cq_verifier *v) { cq_verify_empty_timeout(v, 1); } - -static void add(cq_verifier *v, const char *file, int line, - grpc_completion_type type, void *tag, bool success) { - expectation *e = (expectation *)gpr_malloc(sizeof(expectation)); - e->type = type; - e->file = file; - e->line = line; - e->tag = tag; - e->success = success; - e->next = v->first_expectation; - v->first_expectation = e; -} - -void cq_expect_completion(cq_verifier *v, const char *file, int line, void *tag, - bool success) { - add(v, file, line, GRPC_OP_COMPLETE, tag, success); -} diff --git a/test/core/end2end/cq_verifier.cc b/test/core/end2end/cq_verifier.cc new file mode 100644 index 0000000000..bb978923b2 --- /dev/null +++ b/test/core/end2end/cq_verifier.cc @@ -0,0 +1,321 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/cq_verifier.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/event_string.h" + +#define ROOT_EXPECTATION 1000 + +/* a set of metadata we expect to find on an event */ +typedef struct metadata { + size_t count; + size_t cap; + char **keys; + char **values; +} metadata; + +/* details what we expect to find on a single event - and forms a linked + list to detail other expectations */ +typedef struct expectation { + struct expectation *next; + const char *file; + int line; + grpc_completion_type type; + void *tag; + int success; +} expectation; + +/* the verifier itself */ +struct cq_verifier { + /* bound completion queue */ + grpc_completion_queue *cq; + /* start of expectation list */ + expectation *first_expectation; +}; + +cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { + cq_verifier *v = (cq_verifier *)gpr_malloc(sizeof(cq_verifier)); + v->cq = cq; + v->first_expectation = NULL; + return v; +} + +void cq_verifier_destroy(cq_verifier *v) { + cq_verify(v); + gpr_free(v); +} + +static int has_metadata(const grpc_metadata *md, size_t count, const char *key, + const char *value) { + size_t i; + for (i = 0; i < count; i++) { + if (0 == grpc_slice_str_cmp(md[i].key, key) && + 0 == grpc_slice_str_cmp(md[i].value, value)) { + return 1; + } + } + return 0; +} + +int contains_metadata(grpc_metadata_array *array, const char *key, + const char *value) { + return has_metadata(array->metadata, array->count, key, value); +} + +static int has_metadata_slices(const grpc_metadata *md, size_t count, + grpc_slice key, grpc_slice value) { + size_t i; + for (i = 0; i < count; i++) { + if (grpc_slice_eq(md[i].key, key) && grpc_slice_eq(md[i].value, value)) { + return 1; + } + } + return 0; +} + +int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key, + grpc_slice value) { + return has_metadata_slices(array->metadata, array->count, key, value); +} + +static grpc_slice merge_slices(grpc_slice *slices, size_t nslices) { + size_t i; + size_t len = 0; + uint8_t *cursor; + grpc_slice out; + + for (i = 0; i < nslices; i++) { + len += GRPC_SLICE_LENGTH(slices[i]); + } + + out = grpc_slice_malloc(len); + cursor = GRPC_SLICE_START_PTR(out); + + for (i = 0; i < nslices; i++) { + memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]), + GRPC_SLICE_LENGTH(slices[i])); + cursor += GRPC_SLICE_LENGTH(slices[i]); + } + + return out; +} + +int raw_byte_buffer_eq_slice(grpc_byte_buffer *rbb, grpc_slice b) { + grpc_slice a; + int ok; + + if (!rbb) return 0; + + a = merge_slices(rbb->data.raw.slice_buffer.slices, + rbb->data.raw.slice_buffer.count); + ok = GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b) && + 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), + GRPC_SLICE_LENGTH(a)); + grpc_slice_unref(a); + grpc_slice_unref(b); + return ok; +} + +int byte_buffer_eq_slice(grpc_byte_buffer *bb, grpc_slice b) { + grpc_byte_buffer_reader reader; + grpc_byte_buffer *rbb; + int res; + + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, bb) && + "Couldn't init byte buffer reader"); + rbb = grpc_raw_byte_buffer_from_reader(&reader); + res = raw_byte_buffer_eq_slice(rbb, b); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(rbb); + + return res; +} + +int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) { + grpc_byte_buffer_reader reader; + grpc_byte_buffer *rbb; + int res; + + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, bb) && + "Couldn't init byte buffer reader"); + rbb = grpc_raw_byte_buffer_from_reader(&reader); + res = raw_byte_buffer_eq_slice(rbb, grpc_slice_from_copied_string(str)); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(rbb); + + return res; +} + +static bool is_probably_integer(void *p) { return ((uintptr_t)p) < 1000000; } + +static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { + char *tmp; + + if (is_probably_integer(e->tag)) { + gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag); + } else { + gpr_asprintf(&tmp, "%p ", e->tag); + } + gpr_strvec_add(buf, tmp); + + switch (e->type) { + case GRPC_OP_COMPLETE: + gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success, + e->file, e->line); + gpr_strvec_add(buf, tmp); + break; + case GRPC_QUEUE_TIMEOUT: + case GRPC_QUEUE_SHUTDOWN: + gpr_log(GPR_ERROR, "not implemented"); + abort(); + break; + } +} + +static void expectations_to_strvec(gpr_strvec *buf, cq_verifier *v) { + expectation *e; + + for (e = v->first_expectation; e != NULL; e = e->next) { + expectation_to_strvec(buf, e); + gpr_strvec_add(buf, gpr_strdup("\n")); + } +} + +static void fail_no_event_received(cq_verifier *v) { + gpr_strvec buf; + char *msg; + gpr_strvec_init(&buf); + gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n")); + expectations_to_strvec(&buf, v); + msg = gpr_strvec_flatten(&buf, NULL); + gpr_log(GPR_ERROR, "%s", msg); + gpr_strvec_destroy(&buf); + gpr_free(msg); + abort(); +} + +static void verify_matches(expectation *e, grpc_event *ev) { + GPR_ASSERT(e->type == ev->type); + switch (e->type) { + case GRPC_OP_COMPLETE: + if (e->success != ev->success) { + gpr_strvec expected; + gpr_strvec_init(&expected); + expectation_to_strvec(&expected, e); + char *s = gpr_strvec_flatten(&expected, NULL); + gpr_strvec_destroy(&expected); + gpr_log(GPR_ERROR, "actual success does not match expected: %s", s); + gpr_free(s); + abort(); + } + break; + case GRPC_QUEUE_SHUTDOWN: + gpr_log(GPR_ERROR, "premature queue shutdown"); + abort(); + break; + case GRPC_QUEUE_TIMEOUT: + gpr_log(GPR_ERROR, "not implemented"); + abort(); + break; + } +} + +void cq_verify(cq_verifier *v) { + const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); + while (v->first_expectation != NULL) { + grpc_event ev = grpc_completion_queue_next(v->cq, deadline, NULL); + if (ev.type == GRPC_QUEUE_TIMEOUT) { + fail_no_event_received(v); + break; + } + expectation *e; + expectation *prev = NULL; + for (e = v->first_expectation; e != NULL; e = e->next) { + if (e->tag == ev.tag) { + verify_matches(e, &ev); + if (e == v->first_expectation) v->first_expectation = e->next; + if (prev != NULL) prev->next = e->next; + gpr_free(e); + break; + } + prev = e; + } + if (e == NULL) { + char *s = grpc_event_string(&ev); + gpr_log(GPR_ERROR, "cq returned unexpected event: %s", s); + gpr_free(s); + gpr_strvec expectations; + gpr_strvec_init(&expectations); + expectations_to_strvec(&expectations, v); + s = gpr_strvec_flatten(&expectations, NULL); + gpr_strvec_destroy(&expectations); + gpr_log(GPR_ERROR, "expected tags:\n%s", s); + gpr_free(s); + abort(); + } + } +} + +void cq_verify_empty_timeout(cq_verifier *v, int timeout_sec) { + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(timeout_sec, GPR_TIMESPAN)); + grpc_event ev; + + GPR_ASSERT(v->first_expectation == NULL && "expectation queue must be empty"); + + ev = grpc_completion_queue_next(v->cq, deadline, NULL); + if (ev.type != GRPC_QUEUE_TIMEOUT) { + char *s = grpc_event_string(&ev); + gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s); + gpr_free(s); + abort(); + } +} + +void cq_verify_empty(cq_verifier *v) { cq_verify_empty_timeout(v, 1); } + +static void add(cq_verifier *v, const char *file, int line, + grpc_completion_type type, void *tag, bool success) { + expectation *e = (expectation *)gpr_malloc(sizeof(expectation)); + e->type = type; + e->file = file; + e->line = line; + e->tag = tag; + e->success = success; + e->next = v->first_expectation; + v->first_expectation = e; +} + +void cq_expect_completion(cq_verifier *v, const char *file, int line, void *tag, + bool success) { + add(v, file, line, GRPC_OP_COMPLETE, tag, success); +} diff --git a/test/core/end2end/cq_verifier_native.c b/test/core/end2end/cq_verifier_native.c deleted file mode 100644 index f19b15c465..0000000000 --- a/test/core/end2end/cq_verifier_native.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* This check is for testing only. */ -#ifndef GRPC_UV - -#include "test/core/end2end/cq_verifier_internal.h" - -/* the verifier itself */ -struct cq_verifier { - /* bound completion queue */ - grpc_completion_queue *cq; - /* start of expectation list */ - expectation *first_expectation; - uv_timer_t timer; -}; - -cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { - cq_verifier *v = gpr_malloc(sizeof(cq_verifier)); - v->cq = cq; - cq_verifier_set_first_expectation(v, NULL); - return v; -} - -void cq_verifier_destroy(cq_verifier *v) { - cq_verify(v); - gpr_free(v); -} - -expectation *cq_verifier_get_first_expectation(cq_verifier *v) { - return v->first_expectation; -} - -void cq_verifier_set_first_expectation(cq_verifier *v, expectation *e) { - v->first_expectation = e; -} - -grpc_event cq_verifier_next_event(cq_verifier *v, int timeout_seconds) { - const gpr_timespec deadline = - grpc_timeout_seconds_to_deadline(timeout_seconds); - return grpc_completion_queue_next(v->cq, deadline, NULL); -} - -#endif /* GRPC_UV */ diff --git a/test/core/end2end/cq_verifier_native.cc b/test/core/end2end/cq_verifier_native.cc new file mode 100644 index 0000000000..f19b15c465 --- /dev/null +++ b/test/core/end2end/cq_verifier_native.cc @@ -0,0 +1,59 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This check is for testing only. */ +#ifndef GRPC_UV + +#include "test/core/end2end/cq_verifier_internal.h" + +/* the verifier itself */ +struct cq_verifier { + /* bound completion queue */ + grpc_completion_queue *cq; + /* start of expectation list */ + expectation *first_expectation; + uv_timer_t timer; +}; + +cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { + cq_verifier *v = gpr_malloc(sizeof(cq_verifier)); + v->cq = cq; + cq_verifier_set_first_expectation(v, NULL); + return v; +} + +void cq_verifier_destroy(cq_verifier *v) { + cq_verify(v); + gpr_free(v); +} + +expectation *cq_verifier_get_first_expectation(cq_verifier *v) { + return v->first_expectation; +} + +void cq_verifier_set_first_expectation(cq_verifier *v, expectation *e) { + v->first_expectation = e; +} + +grpc_event cq_verifier_next_event(cq_verifier *v, int timeout_seconds) { + const gpr_timespec deadline = + grpc_timeout_seconds_to_deadline(timeout_seconds); + return grpc_completion_queue_next(v->cq, deadline, NULL); +} + +#endif /* GRPC_UV */ diff --git a/test/core/end2end/cq_verifier_uv.c b/test/core/end2end/cq_verifier_uv.c deleted file mode 100644 index fc873b784f..0000000000 --- a/test/core/end2end/cq_verifier_uv.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#ifdef GRPC_UV - -#include - -#include -#include - -#include "test/core/end2end/cq_verifier_internal.h" - -typedef enum timer_state { - TIMER_STARTED, - TIMER_TRIGGERED, - TIMER_CLOSED -} timer_state; - -/* the verifier itself */ -struct cq_verifier { - /* bound completion queue */ - grpc_completion_queue *cq; - /* start of expectation list */ - expectation *first_expectation; - uv_timer_t timer; -}; - -cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { - cq_verifier *v = gpr_malloc(sizeof(cq_verifier)); - v->cq = cq; - v->first_expectation = NULL; - uv_timer_init(uv_default_loop(), &v->timer); - v->timer.data = (void *)TIMER_STARTED; - return v; -} - -static void timer_close_cb(uv_handle_t *handle) { - handle->data = (void *)TIMER_CLOSED; -} - -void cq_verifier_destroy(cq_verifier *v) { - cq_verify(v); - uv_close((uv_handle_t *)&v->timer, timer_close_cb); - while ((timer_state)v->timer.data != TIMER_CLOSED) { - uv_run(uv_default_loop(), UV_RUN_NOWAIT); - } - gpr_free(v); -} - -expectation *cq_verifier_get_first_expectation(cq_verifier *v) { - return v->first_expectation; -} - -void cq_verifier_set_first_expectation(cq_verifier *v, expectation *e) { - v->first_expectation = e; -} - -static void timer_run_cb(uv_timer_t *timer) { - timer->data = (void *)TIMER_TRIGGERED; -} - -grpc_event cq_verifier_next_event(cq_verifier *v, int timeout_seconds) { - uint64_t timeout_ms = - timeout_seconds < 0 ? 0 : (uint64_t)timeout_seconds * 1000; - grpc_event ev; - v->timer.data = (void *)TIMER_STARTED; - uv_timer_start(&v->timer, timer_run_cb, timeout_ms, 0); - ev = grpc_completion_queue_next(v->cq, gpr_inf_past(GPR_CLOCK_MONOTONIC), - NULL); - // Stop the loop if the timer goes off or we get a non-timeout event - while (((timer_state)v->timer.data != TIMER_TRIGGERED) && - ev.type == GRPC_QUEUE_TIMEOUT) { - uv_run(uv_default_loop(), UV_RUN_ONCE); - ev = grpc_completion_queue_next(v->cq, gpr_inf_past(GPR_CLOCK_MONOTONIC), - NULL); - } - return ev; -} - -#endif /* GRPC_UV */ diff --git a/test/core/end2end/cq_verifier_uv.cc b/test/core/end2end/cq_verifier_uv.cc new file mode 100644 index 0000000000..fc873b784f --- /dev/null +++ b/test/core/end2end/cq_verifier_uv.cc @@ -0,0 +1,97 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#ifdef GRPC_UV + +#include + +#include +#include + +#include "test/core/end2end/cq_verifier_internal.h" + +typedef enum timer_state { + TIMER_STARTED, + TIMER_TRIGGERED, + TIMER_CLOSED +} timer_state; + +/* the verifier itself */ +struct cq_verifier { + /* bound completion queue */ + grpc_completion_queue *cq; + /* start of expectation list */ + expectation *first_expectation; + uv_timer_t timer; +}; + +cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { + cq_verifier *v = gpr_malloc(sizeof(cq_verifier)); + v->cq = cq; + v->first_expectation = NULL; + uv_timer_init(uv_default_loop(), &v->timer); + v->timer.data = (void *)TIMER_STARTED; + return v; +} + +static void timer_close_cb(uv_handle_t *handle) { + handle->data = (void *)TIMER_CLOSED; +} + +void cq_verifier_destroy(cq_verifier *v) { + cq_verify(v); + uv_close((uv_handle_t *)&v->timer, timer_close_cb); + while ((timer_state)v->timer.data != TIMER_CLOSED) { + uv_run(uv_default_loop(), UV_RUN_NOWAIT); + } + gpr_free(v); +} + +expectation *cq_verifier_get_first_expectation(cq_verifier *v) { + return v->first_expectation; +} + +void cq_verifier_set_first_expectation(cq_verifier *v, expectation *e) { + v->first_expectation = e; +} + +static void timer_run_cb(uv_timer_t *timer) { + timer->data = (void *)TIMER_TRIGGERED; +} + +grpc_event cq_verifier_next_event(cq_verifier *v, int timeout_seconds) { + uint64_t timeout_ms = + timeout_seconds < 0 ? 0 : (uint64_t)timeout_seconds * 1000; + grpc_event ev; + v->timer.data = (void *)TIMER_STARTED; + uv_timer_start(&v->timer, timer_run_cb, timeout_ms, 0); + ev = grpc_completion_queue_next(v->cq, gpr_inf_past(GPR_CLOCK_MONOTONIC), + NULL); + // Stop the loop if the timer goes off or we get a non-timeout event + while (((timer_state)v->timer.data != TIMER_TRIGGERED) && + ev.type == GRPC_QUEUE_TIMEOUT) { + uv_run(uv_default_loop(), UV_RUN_ONCE); + ev = grpc_completion_queue_next(v->cq, gpr_inf_past(GPR_CLOCK_MONOTONIC), + NULL); + } + return ev; +} + +#endif /* GRPC_UV */ diff --git a/test/core/end2end/data/client_certs.c b/test/core/end2end/data/client_certs.c deleted file mode 100644 index 78770674c4..0000000000 --- a/test/core/end2end/data/client_certs.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const char test_self_signed_client_cert[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, - 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6f, 0x44, 0x43, 0x43, - 0x41, 0x67, 0x6d, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a, - 0x41, 0x4e, 0x49, 0x7a, 0x32, 0x2f, 0x7a, 0x6f, 0x52, 0x69, 0x61, 0x70, - 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, - 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4d, 0x47, 0x6b, 0x78, - 0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x59, - 0x54, 0x41, 0x6b, 0x46, 0x56, 0x4d, 0x52, 0x4d, 0x77, 0x45, 0x51, 0x59, - 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x70, 0x54, 0x62, 0x32, 0x31, - 0x6c, 0x4c, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x53, 0x45, - 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x42, 0x68, - 0x4a, 0x62, 0x6e, 0x52, 0x6c, 0x63, 0x6d, 0x35, 0x6c, 0x64, 0x43, 0x42, - 0x58, 0x0a, 0x61, 0x57, 0x52, 0x6e, 0x61, 0x58, 0x52, 0x7a, 0x49, 0x46, - 0x42, 0x30, 0x65, 0x53, 0x42, 0x4d, 0x64, 0x47, 0x51, 0x78, 0x49, 0x6a, - 0x41, 0x67, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x47, 0x57, - 0x4a, 0x68, 0x5a, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75, 0x64, 0x43, - 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32, - 0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x0a, 0x62, 0x32, 0x30, 0x77, 0x48, - 0x68, 0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x34, 0x4d, - 0x6a, 0x41, 0x77, 0x4f, 0x44, 0x49, 0x31, 0x57, 0x68, 0x63, 0x4e, 0x4d, - 0x6a, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x31, 0x4d, 0x6a, 0x41, 0x77, 0x4f, - 0x44, 0x49, 0x31, 0x57, 0x6a, 0x42, 0x70, 0x4d, 0x51, 0x73, 0x77, 0x43, - 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x42, 0x0a, - 0x56, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, - 0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, 0x53, 0x31, 0x54, - 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, 0x68, 0x4d, 0x42, 0x38, 0x47, - 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x59, 0x53, 0x57, 0x35, 0x30, - 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, 0x67, 0x56, 0x32, 0x6c, 0x6b, - 0x5a, 0x32, 0x6c, 0x30, 0x0a, 0x63, 0x79, 0x42, 0x51, 0x64, 0x48, 0x6b, - 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, - 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x6c, 0x69, 0x59, 0x57, 0x52, - 0x6a, 0x62, 0x47, 0x6c, 0x6c, 0x62, 0x6e, 0x51, 0x75, 0x64, 0x47, 0x56, - 0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39, 0x6e, 0x62, 0x47, 0x55, - 0x75, 0x59, 0x32, 0x39, 0x74, 0x4d, 0x49, 0x47, 0x66, 0x0a, 0x4d, 0x41, - 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, - 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x47, 0x4e, 0x41, 0x44, - 0x43, 0x42, 0x69, 0x51, 0x4b, 0x42, 0x67, 0x51, 0x43, 0x79, 0x58, 0x32, - 0x4a, 0x78, 0x5a, 0x2b, 0x4a, 0x35, 0x49, 0x2b, 0x64, 0x6c, 0x68, 0x52, - 0x4f, 0x56, 0x74, 0x71, 0x6c, 0x4d, 0x51, 0x6e, 0x34, 0x37, 0x42, 0x42, - 0x63, 0x72, 0x0a, 0x6c, 0x32, 0x47, 0x43, 0x6b, 0x76, 0x39, 0x4f, 0x31, - 0x44, 0x31, 0x72, 0x4c, 0x39, 0x34, 0x4b, 0x57, 0x59, 0x62, 0x59, 0x31, - 0x34, 0x48, 0x58, 0x68, 0x69, 0x2f, 0x6e, 0x61, 0x63, 0x42, 0x41, 0x51, - 0x74, 0x43, 0x45, 0x51, 0x77, 0x58, 0x78, 0x70, 0x35, 0x44, 0x4b, 0x65, - 0x6d, 0x47, 0x4f, 0x55, 0x6a, 0x75, 0x36, 0x35, 0x78, 0x4d, 0x39, 0x46, - 0x39, 0x36, 0x2f, 0x33, 0x37, 0x34, 0x47, 0x0a, 0x4d, 0x76, 0x6e, 0x52, - 0x4a, 0x64, 0x6f, 0x35, 0x32, 0x67, 0x4f, 0x73, 0x34, 0x48, 0x4f, 0x30, - 0x63, 0x7a, 0x42, 0x70, 0x66, 0x56, 0x4e, 0x64, 0x58, 0x65, 0x65, 0x6f, - 0x44, 0x2f, 0x52, 0x59, 0x67, 0x77, 0x74, 0x74, 0x66, 0x64, 0x4a, 0x72, - 0x7a, 0x2f, 0x34, 0x61, 0x61, 0x74, 0x73, 0x53, 0x32, 0x51, 0x6b, 0x32, - 0x79, 0x4d, 0x59, 0x70, 0x71, 0x5a, 0x6d, 0x71, 0x45, 0x4d, 0x73, 0x62, - 0x0a, 0x72, 0x68, 0x39, 0x57, 0x32, 0x32, 0x4c, 0x70, 0x33, 0x72, 0x43, - 0x42, 0x76, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6f, 0x31, 0x41, - 0x77, 0x54, 0x6a, 0x41, 0x64, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x51, 0x34, - 0x45, 0x46, 0x67, 0x51, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52, - 0x38, 0x44, 0x73, 0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75, - 0x31, 0x69, 0x30, 0x4d, 0x4d, 0x0a, 0x55, 0x71, 0x41, 0x77, 0x48, 0x77, - 0x59, 0x44, 0x56, 0x52, 0x30, 0x6a, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6f, - 0x41, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52, 0x38, 0x44, 0x73, - 0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75, 0x31, 0x69, 0x30, - 0x4d, 0x4d, 0x55, 0x71, 0x41, 0x77, 0x44, 0x41, 0x59, 0x44, 0x56, 0x52, - 0x30, 0x54, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0a, 0x2f, - 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, - 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4f, 0x42, 0x67, - 0x51, 0x43, 0x49, 0x2f, 0x74, 0x76, 0x53, 0x42, 0x59, 0x48, 0x31, 0x69, - 0x79, 0x66, 0x4c, 0x61, 0x43, 0x54, 0x42, 0x4b, 0x77, 0x70, 0x64, 0x6a, - 0x33, 0x36, 0x2b, 0x4d, 0x6b, 0x52, 0x39, 0x45, 0x65, 0x4a, 0x4a, 0x6d, - 0x49, 0x6d, 0x78, 0x0a, 0x58, 0x2b, 0x62, 0x6a, 0x68, 0x4b, 0x57, 0x58, - 0x77, 0x73, 0x42, 0x58, 0x34, 0x50, 0x44, 0x4d, 0x57, 0x76, 0x64, 0x75, - 0x73, 0x72, 0x2b, 0x2b, 0x51, 0x47, 0x55, 0x59, 0x74, 0x79, 0x6f, 0x79, - 0x61, 0x2b, 0x68, 0x66, 0x59, 0x4d, 0x58, 0x52, 0x68, 0x58, 0x75, 0x61, - 0x33, 0x39, 0x6d, 0x44, 0x35, 0x34, 0x78, 0x67, 0x6c, 0x6f, 0x51, 0x4e, - 0x75, 0x75, 0x39, 0x52, 0x45, 0x44, 0x77, 0x58, 0x0a, 0x46, 0x66, 0x74, - 0x6f, 0x2b, 0x61, 0x4f, 0x77, 0x33, 0x42, 0x63, 0x59, 0x64, 0x75, 0x63, - 0x7a, 0x36, 0x6f, 0x66, 0x78, 0x69, 0x63, 0x46, 0x4b, 0x2f, 0x59, 0x32, - 0x56, 0x65, 0x58, 0x44, 0x75, 0x72, 0x53, 0x4d, 0x70, 0x52, 0x76, 0x35, - 0x54, 0x66, 0x47, 0x66, 0x32, 0x51, 0x72, 0x36, 0x65, 0x4f, 0x4f, 0x64, - 0x61, 0x52, 0x68, 0x6a, 0x36, 0x65, 0x64, 0x37, 0x42, 0x69, 0x62, 0x48, - 0x6b, 0x0a, 0x58, 0x31, 0x56, 0x47, 0x5a, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, - 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x0a, 0x00}; - -const char test_self_signed_client_key[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x64, 0x77, 0x49, 0x42, - 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, - 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, - 0x41, 0x6d, 0x45, 0x77, 0x67, 0x67, 0x4a, 0x64, 0x41, 0x67, 0x45, 0x41, - 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4c, 0x4a, 0x66, 0x59, 0x6e, 0x46, 0x6e, - 0x34, 0x6e, 0x6b, 0x6a, 0x35, 0x32, 0x57, 0x46, 0x0a, 0x45, 0x35, 0x57, - 0x32, 0x71, 0x55, 0x78, 0x43, 0x66, 0x6a, 0x73, 0x45, 0x46, 0x79, 0x75, - 0x58, 0x59, 0x59, 0x4b, 0x53, 0x2f, 0x30, 0x37, 0x55, 0x50, 0x57, 0x73, - 0x76, 0x33, 0x67, 0x70, 0x5a, 0x68, 0x74, 0x6a, 0x58, 0x67, 0x64, 0x65, - 0x47, 0x4c, 0x2b, 0x64, 0x70, 0x77, 0x45, 0x42, 0x43, 0x30, 0x49, 0x52, - 0x44, 0x42, 0x66, 0x47, 0x6e, 0x6b, 0x4d, 0x70, 0x36, 0x59, 0x59, 0x35, - 0x53, 0x0a, 0x4f, 0x37, 0x72, 0x6e, 0x45, 0x7a, 0x30, 0x58, 0x33, 0x72, - 0x2f, 0x66, 0x76, 0x67, 0x59, 0x79, 0x2b, 0x64, 0x45, 0x6c, 0x32, 0x6a, - 0x6e, 0x61, 0x41, 0x36, 0x7a, 0x67, 0x63, 0x37, 0x52, 0x7a, 0x4d, 0x47, - 0x6c, 0x39, 0x55, 0x31, 0x31, 0x64, 0x35, 0x36, 0x67, 0x50, 0x39, 0x46, - 0x69, 0x44, 0x43, 0x32, 0x31, 0x39, 0x30, 0x6d, 0x76, 0x50, 0x2f, 0x68, - 0x70, 0x71, 0x32, 0x78, 0x4c, 0x5a, 0x0a, 0x43, 0x54, 0x62, 0x49, 0x78, - 0x69, 0x6d, 0x70, 0x6d, 0x61, 0x6f, 0x51, 0x79, 0x78, 0x75, 0x75, 0x48, - 0x31, 0x62, 0x62, 0x59, 0x75, 0x6e, 0x65, 0x73, 0x49, 0x47, 0x2f, 0x41, - 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x41, 0x64, 0x71, - 0x4a, 0x43, 0x45, 0x7a, 0x4d, 0x49, 0x79, 0x5a, 0x45, 0x37, 0x6f, 0x61, - 0x57, 0x30, 0x74, 0x4f, 0x70, 0x63, 0x42, 0x30, 0x42, 0x69, 0x50, 0x0a, - 0x46, 0x59, 0x6f, 0x49, 0x76, 0x48, 0x34, 0x42, 0x4b, 0x52, 0x48, 0x38, - 0x65, 0x48, 0x76, 0x52, 0x34, 0x37, 0x36, 0x6d, 0x74, 0x2b, 0x59, 0x64, - 0x44, 0x68, 0x42, 0x50, 0x31, 0x73, 0x63, 0x47, 0x55, 0x6d, 0x59, 0x65, - 0x43, 0x54, 0x34, 0x45, 0x6a, 0x2b, 0x52, 0x67, 0x48, 0x76, 0x32, 0x4c, - 0x50, 0x54, 0x67, 0x56, 0x59, 0x77, 0x54, 0x39, 0x65, 0x63, 0x69, 0x50, - 0x32, 0x2b, 0x45, 0x2f, 0x0a, 0x43, 0x42, 0x43, 0x4e, 0x52, 0x65, 0x6c, - 0x30, 0x53, 0x77, 0x39, 0x4a, 0x65, 0x70, 0x77, 0x57, 0x30, 0x72, 0x2b, - 0x6a, 0x57, 0x4a, 0x74, 0x44, 0x59, 0x31, 0x70, 0x70, 0x36, 0x59, 0x58, - 0x41, 0x67, 0x4e, 0x52, 0x47, 0x58, 0x32, 0x55, 0x66, 0x6c, 0x76, 0x55, - 0x73, 0x54, 0x2b, 0x6f, 0x39, 0x6c, 0x5a, 0x76, 0x61, 0x67, 0x66, 0x39, - 0x6d, 0x6f, 0x4c, 0x54, 0x4d, 0x79, 0x47, 0x76, 0x55, 0x0a, 0x75, 0x4c, - 0x46, 0x6e, 0x73, 0x79, 0x66, 0x4c, 0x69, 0x6d, 0x31, 0x42, 0x34, 0x76, - 0x58, 0x76, 0x57, 0x51, 0x4a, 0x42, 0x41, 0x4e, 0x6f, 0x75, 0x5a, 0x6c, - 0x6c, 0x58, 0x47, 0x5a, 0x6f, 0x53, 0x72, 0x5a, 0x4c, 0x74, 0x52, 0x33, - 0x56, 0x67, 0x56, 0x34, 0x74, 0x7a, 0x52, 0x51, 0x76, 0x4a, 0x78, 0x75, - 0x38, 0x34, 0x6b, 0x4c, 0x65, 0x49, 0x6b, 0x36, 0x34, 0x4f, 0x76, 0x34, - 0x37, 0x58, 0x0a, 0x70, 0x48, 0x56, 0x42, 0x4d, 0x54, 0x52, 0x42, 0x66, - 0x7a, 0x50, 0x45, 0x68, 0x62, 0x42, 0x6f, 0x64, 0x6a, 0x72, 0x31, 0x6d, - 0x35, 0x4f, 0x4c, 0x61, 0x56, 0x4c, 0x71, 0x6b, 0x46, 0x63, 0x58, 0x66, - 0x74, 0x7a, 0x52, 0x43, 0x72, 0x62, 0x57, 0x6f, 0x4b, 0x73, 0x43, 0x51, - 0x51, 0x44, 0x52, 0x53, 0x6f, 0x4c, 0x4c, 0x58, 0x4f, 0x69, 0x4c, 0x72, - 0x74, 0x4a, 0x33, 0x44, 0x4c, 0x4a, 0x43, 0x0a, 0x72, 0x58, 0x37, 0x59, - 0x38, 0x77, 0x72, 0x48, 0x5a, 0x72, 0x71, 0x6b, 0x35, 0x62, 0x4d, 0x64, - 0x5a, 0x4c, 0x47, 0x61, 0x2f, 0x55, 0x58, 0x38, 0x52, 0x61, 0x6e, 0x68, - 0x56, 0x77, 0x33, 0x2b, 0x58, 0x70, 0x2b, 0x75, 0x72, 0x64, 0x31, 0x37, - 0x31, 0x31, 0x75, 0x6d, 0x65, 0x4e, 0x4a, 0x66, 0x7a, 0x75, 0x2f, 0x4d, - 0x43, 0x6b, 0x34, 0x61, 0x31, 0x4b, 0x6b, 0x47, 0x2f, 0x43, 0x55, 0x30, - 0x0a, 0x72, 0x71, 0x73, 0x39, 0x41, 0x6b, 0x41, 0x34, 0x63, 0x53, 0x78, - 0x31, 0x44, 0x44, 0x31, 0x4a, 0x53, 0x47, 0x2b, 0x79, 0x78, 0x4d, 0x4e, - 0x70, 0x73, 0x41, 0x53, 0x31, 0x78, 0x4a, 0x6f, 0x6d, 0x46, 0x49, 0x72, - 0x73, 0x4d, 0x39, 0x76, 0x73, 0x50, 0x74, 0x37, 0x46, 0x64, 0x6e, 0x64, - 0x44, 0x77, 0x72, 0x46, 0x2b, 0x79, 0x2b, 0x43, 0x6f, 0x76, 0x68, 0x44, - 0x6b, 0x47, 0x59, 0x44, 0x6b, 0x0a, 0x52, 0x41, 0x48, 0x68, 0x2b, 0x73, - 0x76, 0x47, 0x66, 0x5a, 0x67, 0x2f, 0x70, 0x51, 0x4b, 0x32, 0x4a, 0x52, - 0x50, 0x69, 0x6d, 0x41, 0x6d, 0x48, 0x68, 0x7a, 0x71, 0x46, 0x41, 0x6b, - 0x45, 0x41, 0x75, 0x36, 0x59, 0x61, 0x37, 0x30, 0x73, 0x32, 0x46, 0x55, - 0x65, 0x42, 0x33, 0x4d, 0x75, 0x39, 0x61, 0x4a, 0x73, 0x32, 0x43, 0x44, - 0x36, 0x68, 0x67, 0x33, 0x64, 0x51, 0x45, 0x56, 0x6b, 0x42, 0x0a, 0x35, - 0x33, 0x44, 0x49, 0x37, 0x54, 0x58, 0x34, 0x38, 0x64, 0x39, 0x6b, 0x47, - 0x57, 0x35, 0x38, 0x56, 0x58, 0x31, 0x78, 0x6e, 0x71, 0x53, 0x30, 0x32, - 0x4c, 0x79, 0x57, 0x71, 0x41, 0x50, 0x63, 0x57, 0x35, 0x71, 0x6d, 0x31, - 0x6b, 0x4c, 0x48, 0x46, 0x4c, 0x64, 0x6e, 0x64, 0x61, 0x50, 0x4e, 0x6d, - 0x42, 0x61, 0x6a, 0x34, 0x51, 0x4a, 0x42, 0x41, 0x4a, 0x75, 0x67, 0x6c, - 0x33, 0x36, 0x37, 0x0a, 0x39, 0x64, 0x39, 0x74, 0x2f, 0x51, 0x4c, 0x54, - 0x53, 0x75, 0x55, 0x4c, 0x4c, 0x61, 0x6f, 0x59, 0x76, 0x32, 0x76, 0x4a, - 0x54, 0x33, 0x73, 0x31, 0x79, 0x39, 0x48, 0x4e, 0x38, 0x39, 0x45, 0x6f, - 0x61, 0x44, 0x44, 0x45, 0x6b, 0x50, 0x56, 0x66, 0x51, 0x75, 0x36, 0x47, - 0x56, 0x45, 0x58, 0x67, 0x49, 0x42, 0x74, 0x69, 0x6d, 0x31, 0x73, 0x49, - 0x2f, 0x56, 0x50, 0x53, 0x7a, 0x49, 0x38, 0x48, 0x0a, 0x61, 0x58, 0x76, - 0x61, 0x54, 0x55, 0x77, 0x62, 0x6c, 0x46, 0x57, 0x53, 0x4d, 0x37, 0x30, - 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, - 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; - -const char test_signed_client_cert[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, - 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x48, 0x7a, 0x43, 0x43, - 0x41, 0x59, 0x67, 0x43, 0x41, 0x51, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4a, - 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x46, - 0x42, 0x51, 0x41, 0x77, 0x56, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, - 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78, - 0x45, 0x7a, 0x41, 0x52, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x67, - 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, 0x57, 0x55, 0x74, 0x55, 0x33, 0x52, - 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4e, - 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56, - 0x79, 0x62, 0x6d, 0x56, 0x30, 0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64, - 0x70, 0x64, 0x48, 0x4d, 0x67, 0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78, - 0x30, 0x0a, 0x5a, 0x44, 0x45, 0x50, 0x4d, 0x41, 0x30, 0x47, 0x41, 0x31, - 0x55, 0x45, 0x41, 0x77, 0x77, 0x47, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x47, - 0x4e, 0x68, 0x4d, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x30, 0x4d, 0x44, - 0x63, 0x78, 0x4e, 0x7a, 0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x4d, 0x6c, - 0x6f, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x63, 0x78, 0x4e, 0x44, - 0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x0a, 0x4d, 0x6c, 0x6f, 0x77, 0x57, - 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, - 0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78, 0x45, 0x7a, 0x41, 0x52, 0x42, - 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, - 0x57, 0x55, 0x74, 0x55, 0x33, 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, - 0x54, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x0a, - 0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56, 0x79, 0x62, 0x6d, 0x56, 0x30, - 0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64, 0x70, 0x64, 0x48, 0x4d, 0x67, - 0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78, 0x30, 0x5a, 0x44, 0x45, 0x54, - 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4b, - 0x64, 0x47, 0x56, 0x7a, 0x64, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75, - 0x64, 0x44, 0x43, 0x42, 0x0a, 0x6e, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, - 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, - 0x46, 0x41, 0x41, 0x4f, 0x42, 0x6a, 0x51, 0x41, 0x77, 0x67, 0x59, 0x6b, - 0x43, 0x67, 0x59, 0x45, 0x41, 0x37, 0x46, 0x52, 0x48, 0x32, 0x36, 0x47, - 0x2b, 0x46, 0x74, 0x35, 0x56, 0x51, 0x67, 0x79, 0x7a, 0x6c, 0x5a, 0x73, - 0x66, 0x53, 0x6e, 0x48, 0x53, 0x5a, 0x36, 0x47, 0x58, 0x0a, 0x62, 0x37, - 0x71, 0x78, 0x6d, 0x6b, 0x32, 0x50, 0x4f, 0x38, 0x54, 0x59, 0x71, 0x4b, - 0x5a, 0x6d, 0x6b, 0x66, 0x4d, 0x77, 0x6b, 0x65, 0x36, 0x52, 0x55, 0x66, - 0x51, 0x56, 0x2b, 0x53, 0x2b, 0x47, 0x7a, 0x52, 0x76, 0x7a, 0x35, 0x4c, - 0x6c, 0x53, 0x33, 0x31, 0x55, 0x31, 0x51, 0x43, 0x70, 0x33, 0x63, 0x67, - 0x77, 0x6b, 0x49, 0x49, 0x41, 0x51, 0x61, 0x31, 0x45, 0x32, 0x68, 0x43, - 0x45, 0x7a, 0x0a, 0x57, 0x33, 0x31, 0x69, 0x76, 0x62, 0x4d, 0x42, 0x79, - 0x52, 0x4b, 0x39, 0x74, 0x46, 0x70, 0x79, 0x6e, 0x34, 0x55, 0x76, 0x38, - 0x4b, 0x50, 0x31, 0x34, 0x4f, 0x62, 0x4b, 0x6a, 0x54, 0x51, 0x71, 0x78, - 0x55, 0x5a, 0x70, 0x35, 0x35, 0x38, 0x44, 0x67, 0x4f, 0x48, 0x67, 0x35, - 0x62, 0x35, 0x6d, 0x47, 0x52, 0x4d, 0x30, 0x70, 0x79, 0x56, 0x31, 0x65, - 0x71, 0x52, 0x4b, 0x36, 0x50, 0x57, 0x77, 0x0a, 0x52, 0x2f, 0x62, 0x6a, - 0x67, 0x6c, 0x6c, 0x69, 0x36, 0x70, 0x6d, 0x6e, 0x72, 0x2b, 0x30, 0x43, - 0x41, 0x77, 0x45, 0x41, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, - 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, - 0x41, 0x41, 0x4f, 0x42, 0x67, 0x51, 0x41, 0x53, 0x74, 0x53, 0x6d, 0x35, - 0x50, 0x4d, 0x37, 0x75, 0x62, 0x52, 0x4f, 0x69, 0x4b, 0x4b, 0x36, 0x2f, - 0x0a, 0x54, 0x32, 0x46, 0x6b, 0x4b, 0x6c, 0x68, 0x69, 0x54, 0x4f, 0x78, - 0x2b, 0x52, 0x79, 0x65, 0x6e, 0x6d, 0x33, 0x45, 0x69, 0x6f, 0x35, 0x39, - 0x65, 0x6d, 0x71, 0x2b, 0x6a, 0x58, 0x6c, 0x2b, 0x31, 0x6e, 0x68, 0x50, - 0x79, 0x53, 0x58, 0x35, 0x47, 0x32, 0x50, 0x51, 0x7a, 0x53, 0x52, 0x35, - 0x76, 0x64, 0x31, 0x64, 0x49, 0x68, 0x77, 0x67, 0x5a, 0x53, 0x52, 0x34, - 0x47, 0x79, 0x74, 0x74, 0x6b, 0x0a, 0x74, 0x52, 0x5a, 0x35, 0x37, 0x6b, - 0x2f, 0x4e, 0x49, 0x31, 0x62, 0x72, 0x55, 0x57, 0x38, 0x6a, 0x6f, 0x69, - 0x45, 0x4f, 0x4d, 0x4a, 0x41, 0x2f, 0x4d, 0x72, 0x37, 0x48, 0x37, 0x61, - 0x73, 0x78, 0x37, 0x77, 0x49, 0x52, 0x59, 0x44, 0x45, 0x39, 0x31, 0x46, - 0x73, 0x38, 0x47, 0x6b, 0x4b, 0x57, 0x64, 0x35, 0x4c, 0x68, 0x6f, 0x50, - 0x41, 0x51, 0x6a, 0x2b, 0x71, 0x64, 0x47, 0x33, 0x35, 0x43, 0x0a, 0x4f, - 0x4f, 0x2b, 0x73, 0x76, 0x64, 0x6b, 0x6d, 0x71, 0x48, 0x30, 0x4b, 0x5a, - 0x6f, 0x33, 0x32, 0x30, 0x5a, 0x55, 0x71, 0x64, 0x6c, 0x32, 0x6f, 0x6f, - 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, - 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; - -const char test_signed_client_key[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x65, 0x51, 0x49, 0x42, - 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, - 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, - 0x41, 0x6d, 0x4d, 0x77, 0x67, 0x67, 0x4a, 0x66, 0x41, 0x67, 0x45, 0x41, - 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4f, 0x78, 0x55, 0x52, 0x39, 0x75, 0x68, - 0x76, 0x68, 0x62, 0x65, 0x56, 0x55, 0x49, 0x4d, 0x0a, 0x73, 0x35, 0x57, - 0x62, 0x48, 0x30, 0x70, 0x78, 0x30, 0x6d, 0x65, 0x68, 0x6c, 0x32, 0x2b, - 0x36, 0x73, 0x5a, 0x70, 0x4e, 0x6a, 0x7a, 0x76, 0x45, 0x32, 0x4b, 0x69, - 0x6d, 0x5a, 0x70, 0x48, 0x7a, 0x4d, 0x4a, 0x48, 0x75, 0x6b, 0x56, 0x48, - 0x30, 0x46, 0x66, 0x6b, 0x76, 0x68, 0x73, 0x30, 0x62, 0x38, 0x2b, 0x53, - 0x35, 0x55, 0x74, 0x39, 0x56, 0x4e, 0x55, 0x41, 0x71, 0x64, 0x33, 0x49, - 0x4d, 0x0a, 0x4a, 0x43, 0x43, 0x41, 0x45, 0x47, 0x74, 0x52, 0x4e, 0x6f, - 0x51, 0x68, 0x4d, 0x31, 0x74, 0x39, 0x59, 0x72, 0x32, 0x7a, 0x41, 0x63, - 0x6b, 0x53, 0x76, 0x62, 0x52, 0x61, 0x63, 0x70, 0x2b, 0x46, 0x4c, 0x2f, - 0x43, 0x6a, 0x39, 0x65, 0x44, 0x6d, 0x79, 0x6f, 0x30, 0x30, 0x4b, 0x73, - 0x56, 0x47, 0x61, 0x65, 0x65, 0x66, 0x41, 0x34, 0x44, 0x68, 0x34, 0x4f, - 0x57, 0x2b, 0x5a, 0x68, 0x6b, 0x54, 0x0a, 0x4e, 0x4b, 0x63, 0x6c, 0x64, - 0x58, 0x71, 0x6b, 0x53, 0x75, 0x6a, 0x31, 0x73, 0x45, 0x66, 0x32, 0x34, - 0x34, 0x4a, 0x5a, 0x59, 0x75, 0x71, 0x5a, 0x70, 0x36, 0x2f, 0x74, 0x41, - 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x45, 0x41, 0x69, - 0x32, 0x4e, 0x53, 0x56, 0x71, 0x70, 0x5a, 0x4d, 0x61, 0x66, 0x45, 0x35, - 0x59, 0x59, 0x55, 0x54, 0x63, 0x4d, 0x47, 0x65, 0x36, 0x51, 0x53, 0x0a, - 0x6b, 0x32, 0x6a, 0x74, 0x70, 0x73, 0x71, 0x59, 0x67, 0x67, 0x67, 0x49, - 0x32, 0x52, 0x6e, 0x4c, 0x4a, 0x2f, 0x32, 0x74, 0x4e, 0x5a, 0x77, 0x59, - 0x49, 0x35, 0x70, 0x77, 0x50, 0x38, 0x51, 0x56, 0x53, 0x62, 0x6e, 0x4d, - 0x61, 0x69, 0x46, 0x34, 0x67, 0x6f, 0x6b, 0x44, 0x35, 0x68, 0x47, 0x64, - 0x72, 0x4e, 0x44, 0x66, 0x54, 0x6e, 0x62, 0x32, 0x76, 0x2b, 0x79, 0x49, - 0x77, 0x59, 0x45, 0x48, 0x0a, 0x30, 0x77, 0x38, 0x2b, 0x6f, 0x47, 0x37, - 0x5a, 0x38, 0x31, 0x4b, 0x6f, 0x64, 0x73, 0x69, 0x5a, 0x53, 0x49, 0x44, - 0x4a, 0x66, 0x54, 0x47, 0x73, 0x41, 0x5a, 0x68, 0x56, 0x4e, 0x77, 0x4f, - 0x7a, 0x39, 0x79, 0x30, 0x56, 0x44, 0x38, 0x42, 0x42, 0x5a, 0x5a, 0x31, - 0x2f, 0x32, 0x37, 0x34, 0x5a, 0x68, 0x35, 0x32, 0x41, 0x55, 0x4b, 0x4c, - 0x6a, 0x5a, 0x53, 0x2f, 0x5a, 0x77, 0x49, 0x62, 0x53, 0x0a, 0x57, 0x32, - 0x79, 0x77, 0x79, 0x61, 0x38, 0x35, 0x35, 0x64, 0x50, 0x6e, 0x48, 0x2f, - 0x77, 0x6a, 0x2b, 0x30, 0x45, 0x43, 0x51, 0x51, 0x44, 0x39, 0x58, 0x38, - 0x44, 0x39, 0x32, 0x30, 0x6b, 0x42, 0x79, 0x54, 0x4e, 0x48, 0x68, 0x42, - 0x47, 0x31, 0x38, 0x62, 0x69, 0x41, 0x45, 0x5a, 0x34, 0x70, 0x78, 0x73, - 0x39, 0x66, 0x30, 0x4f, 0x41, 0x47, 0x38, 0x33, 0x33, 0x33, 0x65, 0x56, - 0x63, 0x49, 0x0a, 0x77, 0x32, 0x6c, 0x4a, 0x44, 0x4c, 0x73, 0x59, 0x44, - 0x5a, 0x72, 0x43, 0x42, 0x32, 0x6f, 0x63, 0x67, 0x41, 0x33, 0x6c, 0x55, - 0x64, 0x6f, 0x7a, 0x6c, 0x7a, 0x50, 0x43, 0x37, 0x59, 0x44, 0x59, 0x77, - 0x38, 0x72, 0x65, 0x67, 0x30, 0x74, 0x6b, 0x69, 0x52, 0x59, 0x35, 0x41, - 0x6b, 0x45, 0x41, 0x37, 0x73, 0x64, 0x4e, 0x7a, 0x4f, 0x65, 0x51, 0x73, - 0x51, 0x52, 0x6e, 0x37, 0x2b, 0x2b, 0x35, 0x0a, 0x30, 0x62, 0x50, 0x39, - 0x44, 0x74, 0x54, 0x2f, 0x69, 0x4f, 0x4e, 0x31, 0x67, 0x62, 0x66, 0x78, - 0x52, 0x7a, 0x43, 0x66, 0x43, 0x66, 0x58, 0x64, 0x6f, 0x4f, 0x74, 0x66, - 0x51, 0x57, 0x49, 0x7a, 0x54, 0x65, 0x50, 0x57, 0x74, 0x55, 0x52, 0x74, - 0x39, 0x58, 0x2f, 0x35, 0x44, 0x39, 0x4e, 0x6f, 0x66, 0x49, 0x30, 0x52, - 0x67, 0x35, 0x57, 0x32, 0x6f, 0x47, 0x79, 0x2f, 0x4d, 0x4c, 0x65, 0x35, - 0x0a, 0x2f, 0x73, 0x58, 0x48, 0x56, 0x51, 0x4a, 0x42, 0x41, 0x49, 0x75, - 0x70, 0x35, 0x58, 0x72, 0x4a, 0x44, 0x6b, 0x51, 0x79, 0x77, 0x4e, 0x5a, - 0x79, 0x41, 0x55, 0x55, 0x32, 0x65, 0x63, 0x6e, 0x32, 0x62, 0x43, 0x57, - 0x42, 0x46, 0x6a, 0x77, 0x74, 0x71, 0x64, 0x2b, 0x4c, 0x42, 0x6d, 0x75, - 0x4d, 0x63, 0x69, 0x49, 0x39, 0x66, 0x4f, 0x4b, 0x73, 0x5a, 0x74, 0x45, - 0x4b, 0x5a, 0x72, 0x7a, 0x2f, 0x0a, 0x55, 0x30, 0x6c, 0x6b, 0x65, 0x4d, - 0x52, 0x6f, 0x53, 0x77, 0x76, 0x58, 0x45, 0x38, 0x77, 0x6d, 0x47, 0x4c, - 0x6a, 0x6a, 0x72, 0x41, 0x62, 0x64, 0x66, 0x6f, 0x68, 0x72, 0x58, 0x46, - 0x6b, 0x43, 0x51, 0x51, 0x44, 0x5a, 0x45, 0x78, 0x2f, 0x4c, 0x74, 0x49, - 0x6c, 0x36, 0x4a, 0x49, 0x4e, 0x4a, 0x51, 0x69, 0x73, 0x77, 0x56, 0x65, - 0x30, 0x74, 0x57, 0x72, 0x36, 0x6b, 0x2b, 0x41, 0x53, 0x50, 0x0a, 0x31, - 0x57, 0x58, 0x6f, 0x54, 0x6d, 0x2b, 0x48, 0x59, 0x70, 0x6f, 0x46, 0x2f, - 0x58, 0x55, 0x76, 0x76, 0x39, 0x4c, 0x63, 0x63, 0x4e, 0x46, 0x31, 0x49, - 0x61, 0x7a, 0x46, 0x6a, 0x33, 0x34, 0x68, 0x77, 0x52, 0x51, 0x77, 0x68, - 0x78, 0x37, 0x77, 0x2f, 0x56, 0x35, 0x32, 0x49, 0x65, 0x62, 0x2b, 0x70, - 0x30, 0x6a, 0x55, 0x4d, 0x59, 0x47, 0x78, 0x41, 0x6b, 0x45, 0x41, 0x6a, - 0x44, 0x68, 0x64, 0x0a, 0x39, 0x70, 0x42, 0x4f, 0x31, 0x66, 0x4b, 0x58, - 0x57, 0x69, 0x58, 0x7a, 0x69, 0x39, 0x5a, 0x4b, 0x66, 0x6f, 0x79, 0x54, - 0x4e, 0x63, 0x55, 0x71, 0x33, 0x65, 0x42, 0x53, 0x56, 0x4b, 0x77, 0x50, - 0x47, 0x32, 0x6e, 0x49, 0x74, 0x67, 0x35, 0x79, 0x63, 0x58, 0x65, 0x6e, - 0x67, 0x6a, 0x54, 0x35, 0x73, 0x67, 0x63, 0x57, 0x44, 0x6e, 0x63, 0x69, - 0x49, 0x7a, 0x57, 0x37, 0x42, 0x49, 0x56, 0x49, 0x0a, 0x4a, 0x69, 0x71, - 0x4f, 0x73, 0x7a, 0x71, 0x39, 0x47, 0x57, 0x45, 0x53, 0x45, 0x72, 0x41, - 0x61, 0x74, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, - 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/client_certs.cc b/test/core/end2end/data/client_certs.cc new file mode 100644 index 0000000000..6e61501234 --- /dev/null +++ b/test/core/end2end/data/client_certs.cc @@ -0,0 +1,330 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/data/ssl_test_data.h" + +const char test_self_signed_client_cert[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6f, 0x44, 0x43, 0x43, + 0x41, 0x67, 0x6d, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a, + 0x41, 0x4e, 0x49, 0x7a, 0x32, 0x2f, 0x7a, 0x6f, 0x52, 0x69, 0x61, 0x70, + 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, + 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4d, 0x47, 0x6b, 0x78, + 0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x59, + 0x54, 0x41, 0x6b, 0x46, 0x56, 0x4d, 0x52, 0x4d, 0x77, 0x45, 0x51, 0x59, + 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x70, 0x54, 0x62, 0x32, 0x31, + 0x6c, 0x4c, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x53, 0x45, + 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x42, 0x68, + 0x4a, 0x62, 0x6e, 0x52, 0x6c, 0x63, 0x6d, 0x35, 0x6c, 0x64, 0x43, 0x42, + 0x58, 0x0a, 0x61, 0x57, 0x52, 0x6e, 0x61, 0x58, 0x52, 0x7a, 0x49, 0x46, + 0x42, 0x30, 0x65, 0x53, 0x42, 0x4d, 0x64, 0x47, 0x51, 0x78, 0x49, 0x6a, + 0x41, 0x67, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x47, 0x57, + 0x4a, 0x68, 0x5a, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75, 0x64, 0x43, + 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32, + 0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x0a, 0x62, 0x32, 0x30, 0x77, 0x48, + 0x68, 0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x34, 0x4d, + 0x6a, 0x41, 0x77, 0x4f, 0x44, 0x49, 0x31, 0x57, 0x68, 0x63, 0x4e, 0x4d, + 0x6a, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x31, 0x4d, 0x6a, 0x41, 0x77, 0x4f, + 0x44, 0x49, 0x31, 0x57, 0x6a, 0x42, 0x70, 0x4d, 0x51, 0x73, 0x77, 0x43, + 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x42, 0x0a, + 0x56, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, + 0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, 0x53, 0x31, 0x54, + 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, 0x68, 0x4d, 0x42, 0x38, 0x47, + 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x59, 0x53, 0x57, 0x35, 0x30, + 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, 0x67, 0x56, 0x32, 0x6c, 0x6b, + 0x5a, 0x32, 0x6c, 0x30, 0x0a, 0x63, 0x79, 0x42, 0x51, 0x64, 0x48, 0x6b, + 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x53, 0x49, 0x77, 0x49, 0x41, 0x59, + 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x6c, 0x69, 0x59, 0x57, 0x52, + 0x6a, 0x62, 0x47, 0x6c, 0x6c, 0x62, 0x6e, 0x51, 0x75, 0x64, 0x47, 0x56, + 0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39, 0x6e, 0x62, 0x47, 0x55, + 0x75, 0x59, 0x32, 0x39, 0x74, 0x4d, 0x49, 0x47, 0x66, 0x0a, 0x4d, 0x41, + 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, + 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x47, 0x4e, 0x41, 0x44, + 0x43, 0x42, 0x69, 0x51, 0x4b, 0x42, 0x67, 0x51, 0x43, 0x79, 0x58, 0x32, + 0x4a, 0x78, 0x5a, 0x2b, 0x4a, 0x35, 0x49, 0x2b, 0x64, 0x6c, 0x68, 0x52, + 0x4f, 0x56, 0x74, 0x71, 0x6c, 0x4d, 0x51, 0x6e, 0x34, 0x37, 0x42, 0x42, + 0x63, 0x72, 0x0a, 0x6c, 0x32, 0x47, 0x43, 0x6b, 0x76, 0x39, 0x4f, 0x31, + 0x44, 0x31, 0x72, 0x4c, 0x39, 0x34, 0x4b, 0x57, 0x59, 0x62, 0x59, 0x31, + 0x34, 0x48, 0x58, 0x68, 0x69, 0x2f, 0x6e, 0x61, 0x63, 0x42, 0x41, 0x51, + 0x74, 0x43, 0x45, 0x51, 0x77, 0x58, 0x78, 0x70, 0x35, 0x44, 0x4b, 0x65, + 0x6d, 0x47, 0x4f, 0x55, 0x6a, 0x75, 0x36, 0x35, 0x78, 0x4d, 0x39, 0x46, + 0x39, 0x36, 0x2f, 0x33, 0x37, 0x34, 0x47, 0x0a, 0x4d, 0x76, 0x6e, 0x52, + 0x4a, 0x64, 0x6f, 0x35, 0x32, 0x67, 0x4f, 0x73, 0x34, 0x48, 0x4f, 0x30, + 0x63, 0x7a, 0x42, 0x70, 0x66, 0x56, 0x4e, 0x64, 0x58, 0x65, 0x65, 0x6f, + 0x44, 0x2f, 0x52, 0x59, 0x67, 0x77, 0x74, 0x74, 0x66, 0x64, 0x4a, 0x72, + 0x7a, 0x2f, 0x34, 0x61, 0x61, 0x74, 0x73, 0x53, 0x32, 0x51, 0x6b, 0x32, + 0x79, 0x4d, 0x59, 0x70, 0x71, 0x5a, 0x6d, 0x71, 0x45, 0x4d, 0x73, 0x62, + 0x0a, 0x72, 0x68, 0x39, 0x57, 0x32, 0x32, 0x4c, 0x70, 0x33, 0x72, 0x43, + 0x42, 0x76, 0x77, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6f, 0x31, 0x41, + 0x77, 0x54, 0x6a, 0x41, 0x64, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x51, 0x34, + 0x45, 0x46, 0x67, 0x51, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52, + 0x38, 0x44, 0x73, 0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75, + 0x31, 0x69, 0x30, 0x4d, 0x4d, 0x0a, 0x55, 0x71, 0x41, 0x77, 0x48, 0x77, + 0x59, 0x44, 0x56, 0x52, 0x30, 0x6a, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6f, + 0x41, 0x55, 0x35, 0x32, 0x33, 0x41, 0x4a, 0x4d, 0x52, 0x38, 0x44, 0x73, + 0x39, 0x56, 0x38, 0x66, 0x68, 0x66, 0x37, 0x67, 0x75, 0x31, 0x69, 0x30, + 0x4d, 0x4d, 0x55, 0x71, 0x41, 0x77, 0x44, 0x41, 0x59, 0x44, 0x56, 0x52, + 0x30, 0x54, 0x42, 0x41, 0x55, 0x77, 0x41, 0x77, 0x45, 0x42, 0x0a, 0x2f, + 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, + 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4f, 0x42, 0x67, + 0x51, 0x43, 0x49, 0x2f, 0x74, 0x76, 0x53, 0x42, 0x59, 0x48, 0x31, 0x69, + 0x79, 0x66, 0x4c, 0x61, 0x43, 0x54, 0x42, 0x4b, 0x77, 0x70, 0x64, 0x6a, + 0x33, 0x36, 0x2b, 0x4d, 0x6b, 0x52, 0x39, 0x45, 0x65, 0x4a, 0x4a, 0x6d, + 0x49, 0x6d, 0x78, 0x0a, 0x58, 0x2b, 0x62, 0x6a, 0x68, 0x4b, 0x57, 0x58, + 0x77, 0x73, 0x42, 0x58, 0x34, 0x50, 0x44, 0x4d, 0x57, 0x76, 0x64, 0x75, + 0x73, 0x72, 0x2b, 0x2b, 0x51, 0x47, 0x55, 0x59, 0x74, 0x79, 0x6f, 0x79, + 0x61, 0x2b, 0x68, 0x66, 0x59, 0x4d, 0x58, 0x52, 0x68, 0x58, 0x75, 0x61, + 0x33, 0x39, 0x6d, 0x44, 0x35, 0x34, 0x78, 0x67, 0x6c, 0x6f, 0x51, 0x4e, + 0x75, 0x75, 0x39, 0x52, 0x45, 0x44, 0x77, 0x58, 0x0a, 0x46, 0x66, 0x74, + 0x6f, 0x2b, 0x61, 0x4f, 0x77, 0x33, 0x42, 0x63, 0x59, 0x64, 0x75, 0x63, + 0x7a, 0x36, 0x6f, 0x66, 0x78, 0x69, 0x63, 0x46, 0x4b, 0x2f, 0x59, 0x32, + 0x56, 0x65, 0x58, 0x44, 0x75, 0x72, 0x53, 0x4d, 0x70, 0x52, 0x76, 0x35, + 0x54, 0x66, 0x47, 0x66, 0x32, 0x51, 0x72, 0x36, 0x65, 0x4f, 0x4f, 0x64, + 0x61, 0x52, 0x68, 0x6a, 0x36, 0x65, 0x64, 0x37, 0x42, 0x69, 0x62, 0x48, + 0x6b, 0x0a, 0x58, 0x31, 0x56, 0x47, 0x5a, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, + 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x0a, 0x00}; + +const char test_self_signed_client_key[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, + 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x64, 0x77, 0x49, 0x42, + 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, + 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, + 0x41, 0x6d, 0x45, 0x77, 0x67, 0x67, 0x4a, 0x64, 0x41, 0x67, 0x45, 0x41, + 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4c, 0x4a, 0x66, 0x59, 0x6e, 0x46, 0x6e, + 0x34, 0x6e, 0x6b, 0x6a, 0x35, 0x32, 0x57, 0x46, 0x0a, 0x45, 0x35, 0x57, + 0x32, 0x71, 0x55, 0x78, 0x43, 0x66, 0x6a, 0x73, 0x45, 0x46, 0x79, 0x75, + 0x58, 0x59, 0x59, 0x4b, 0x53, 0x2f, 0x30, 0x37, 0x55, 0x50, 0x57, 0x73, + 0x76, 0x33, 0x67, 0x70, 0x5a, 0x68, 0x74, 0x6a, 0x58, 0x67, 0x64, 0x65, + 0x47, 0x4c, 0x2b, 0x64, 0x70, 0x77, 0x45, 0x42, 0x43, 0x30, 0x49, 0x52, + 0x44, 0x42, 0x66, 0x47, 0x6e, 0x6b, 0x4d, 0x70, 0x36, 0x59, 0x59, 0x35, + 0x53, 0x0a, 0x4f, 0x37, 0x72, 0x6e, 0x45, 0x7a, 0x30, 0x58, 0x33, 0x72, + 0x2f, 0x66, 0x76, 0x67, 0x59, 0x79, 0x2b, 0x64, 0x45, 0x6c, 0x32, 0x6a, + 0x6e, 0x61, 0x41, 0x36, 0x7a, 0x67, 0x63, 0x37, 0x52, 0x7a, 0x4d, 0x47, + 0x6c, 0x39, 0x55, 0x31, 0x31, 0x64, 0x35, 0x36, 0x67, 0x50, 0x39, 0x46, + 0x69, 0x44, 0x43, 0x32, 0x31, 0x39, 0x30, 0x6d, 0x76, 0x50, 0x2f, 0x68, + 0x70, 0x71, 0x32, 0x78, 0x4c, 0x5a, 0x0a, 0x43, 0x54, 0x62, 0x49, 0x78, + 0x69, 0x6d, 0x70, 0x6d, 0x61, 0x6f, 0x51, 0x79, 0x78, 0x75, 0x75, 0x48, + 0x31, 0x62, 0x62, 0x59, 0x75, 0x6e, 0x65, 0x73, 0x49, 0x47, 0x2f, 0x41, + 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x41, 0x64, 0x71, + 0x4a, 0x43, 0x45, 0x7a, 0x4d, 0x49, 0x79, 0x5a, 0x45, 0x37, 0x6f, 0x61, + 0x57, 0x30, 0x74, 0x4f, 0x70, 0x63, 0x42, 0x30, 0x42, 0x69, 0x50, 0x0a, + 0x46, 0x59, 0x6f, 0x49, 0x76, 0x48, 0x34, 0x42, 0x4b, 0x52, 0x48, 0x38, + 0x65, 0x48, 0x76, 0x52, 0x34, 0x37, 0x36, 0x6d, 0x74, 0x2b, 0x59, 0x64, + 0x44, 0x68, 0x42, 0x50, 0x31, 0x73, 0x63, 0x47, 0x55, 0x6d, 0x59, 0x65, + 0x43, 0x54, 0x34, 0x45, 0x6a, 0x2b, 0x52, 0x67, 0x48, 0x76, 0x32, 0x4c, + 0x50, 0x54, 0x67, 0x56, 0x59, 0x77, 0x54, 0x39, 0x65, 0x63, 0x69, 0x50, + 0x32, 0x2b, 0x45, 0x2f, 0x0a, 0x43, 0x42, 0x43, 0x4e, 0x52, 0x65, 0x6c, + 0x30, 0x53, 0x77, 0x39, 0x4a, 0x65, 0x70, 0x77, 0x57, 0x30, 0x72, 0x2b, + 0x6a, 0x57, 0x4a, 0x74, 0x44, 0x59, 0x31, 0x70, 0x70, 0x36, 0x59, 0x58, + 0x41, 0x67, 0x4e, 0x52, 0x47, 0x58, 0x32, 0x55, 0x66, 0x6c, 0x76, 0x55, + 0x73, 0x54, 0x2b, 0x6f, 0x39, 0x6c, 0x5a, 0x76, 0x61, 0x67, 0x66, 0x39, + 0x6d, 0x6f, 0x4c, 0x54, 0x4d, 0x79, 0x47, 0x76, 0x55, 0x0a, 0x75, 0x4c, + 0x46, 0x6e, 0x73, 0x79, 0x66, 0x4c, 0x69, 0x6d, 0x31, 0x42, 0x34, 0x76, + 0x58, 0x76, 0x57, 0x51, 0x4a, 0x42, 0x41, 0x4e, 0x6f, 0x75, 0x5a, 0x6c, + 0x6c, 0x58, 0x47, 0x5a, 0x6f, 0x53, 0x72, 0x5a, 0x4c, 0x74, 0x52, 0x33, + 0x56, 0x67, 0x56, 0x34, 0x74, 0x7a, 0x52, 0x51, 0x76, 0x4a, 0x78, 0x75, + 0x38, 0x34, 0x6b, 0x4c, 0x65, 0x49, 0x6b, 0x36, 0x34, 0x4f, 0x76, 0x34, + 0x37, 0x58, 0x0a, 0x70, 0x48, 0x56, 0x42, 0x4d, 0x54, 0x52, 0x42, 0x66, + 0x7a, 0x50, 0x45, 0x68, 0x62, 0x42, 0x6f, 0x64, 0x6a, 0x72, 0x31, 0x6d, + 0x35, 0x4f, 0x4c, 0x61, 0x56, 0x4c, 0x71, 0x6b, 0x46, 0x63, 0x58, 0x66, + 0x74, 0x7a, 0x52, 0x43, 0x72, 0x62, 0x57, 0x6f, 0x4b, 0x73, 0x43, 0x51, + 0x51, 0x44, 0x52, 0x53, 0x6f, 0x4c, 0x4c, 0x58, 0x4f, 0x69, 0x4c, 0x72, + 0x74, 0x4a, 0x33, 0x44, 0x4c, 0x4a, 0x43, 0x0a, 0x72, 0x58, 0x37, 0x59, + 0x38, 0x77, 0x72, 0x48, 0x5a, 0x72, 0x71, 0x6b, 0x35, 0x62, 0x4d, 0x64, + 0x5a, 0x4c, 0x47, 0x61, 0x2f, 0x55, 0x58, 0x38, 0x52, 0x61, 0x6e, 0x68, + 0x56, 0x77, 0x33, 0x2b, 0x58, 0x70, 0x2b, 0x75, 0x72, 0x64, 0x31, 0x37, + 0x31, 0x31, 0x75, 0x6d, 0x65, 0x4e, 0x4a, 0x66, 0x7a, 0x75, 0x2f, 0x4d, + 0x43, 0x6b, 0x34, 0x61, 0x31, 0x4b, 0x6b, 0x47, 0x2f, 0x43, 0x55, 0x30, + 0x0a, 0x72, 0x71, 0x73, 0x39, 0x41, 0x6b, 0x41, 0x34, 0x63, 0x53, 0x78, + 0x31, 0x44, 0x44, 0x31, 0x4a, 0x53, 0x47, 0x2b, 0x79, 0x78, 0x4d, 0x4e, + 0x70, 0x73, 0x41, 0x53, 0x31, 0x78, 0x4a, 0x6f, 0x6d, 0x46, 0x49, 0x72, + 0x73, 0x4d, 0x39, 0x76, 0x73, 0x50, 0x74, 0x37, 0x46, 0x64, 0x6e, 0x64, + 0x44, 0x77, 0x72, 0x46, 0x2b, 0x79, 0x2b, 0x43, 0x6f, 0x76, 0x68, 0x44, + 0x6b, 0x47, 0x59, 0x44, 0x6b, 0x0a, 0x52, 0x41, 0x48, 0x68, 0x2b, 0x73, + 0x76, 0x47, 0x66, 0x5a, 0x67, 0x2f, 0x70, 0x51, 0x4b, 0x32, 0x4a, 0x52, + 0x50, 0x69, 0x6d, 0x41, 0x6d, 0x48, 0x68, 0x7a, 0x71, 0x46, 0x41, 0x6b, + 0x45, 0x41, 0x75, 0x36, 0x59, 0x61, 0x37, 0x30, 0x73, 0x32, 0x46, 0x55, + 0x65, 0x42, 0x33, 0x4d, 0x75, 0x39, 0x61, 0x4a, 0x73, 0x32, 0x43, 0x44, + 0x36, 0x68, 0x67, 0x33, 0x64, 0x51, 0x45, 0x56, 0x6b, 0x42, 0x0a, 0x35, + 0x33, 0x44, 0x49, 0x37, 0x54, 0x58, 0x34, 0x38, 0x64, 0x39, 0x6b, 0x47, + 0x57, 0x35, 0x38, 0x56, 0x58, 0x31, 0x78, 0x6e, 0x71, 0x53, 0x30, 0x32, + 0x4c, 0x79, 0x57, 0x71, 0x41, 0x50, 0x63, 0x57, 0x35, 0x71, 0x6d, 0x31, + 0x6b, 0x4c, 0x48, 0x46, 0x4c, 0x64, 0x6e, 0x64, 0x61, 0x50, 0x4e, 0x6d, + 0x42, 0x61, 0x6a, 0x34, 0x51, 0x4a, 0x42, 0x41, 0x4a, 0x75, 0x67, 0x6c, + 0x33, 0x36, 0x37, 0x0a, 0x39, 0x64, 0x39, 0x74, 0x2f, 0x51, 0x4c, 0x54, + 0x53, 0x75, 0x55, 0x4c, 0x4c, 0x61, 0x6f, 0x59, 0x76, 0x32, 0x76, 0x4a, + 0x54, 0x33, 0x73, 0x31, 0x79, 0x39, 0x48, 0x4e, 0x38, 0x39, 0x45, 0x6f, + 0x61, 0x44, 0x44, 0x45, 0x6b, 0x50, 0x56, 0x66, 0x51, 0x75, 0x36, 0x47, + 0x56, 0x45, 0x58, 0x67, 0x49, 0x42, 0x74, 0x69, 0x6d, 0x31, 0x73, 0x49, + 0x2f, 0x56, 0x50, 0x53, 0x7a, 0x49, 0x38, 0x48, 0x0a, 0x61, 0x58, 0x76, + 0x61, 0x54, 0x55, 0x77, 0x62, 0x6c, 0x46, 0x57, 0x53, 0x4d, 0x37, 0x30, + 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, + 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; + +const char test_signed_client_cert[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x48, 0x7a, 0x43, 0x43, + 0x41, 0x59, 0x67, 0x43, 0x41, 0x51, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4a, + 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x46, + 0x42, 0x51, 0x41, 0x77, 0x56, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, + 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78, + 0x45, 0x7a, 0x41, 0x52, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x67, + 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, 0x57, 0x55, 0x74, 0x55, 0x33, 0x52, + 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, 0x54, 0x41, 0x66, 0x42, 0x67, 0x4e, + 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56, + 0x79, 0x62, 0x6d, 0x56, 0x30, 0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64, + 0x70, 0x64, 0x48, 0x4d, 0x67, 0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78, + 0x30, 0x0a, 0x5a, 0x44, 0x45, 0x50, 0x4d, 0x41, 0x30, 0x47, 0x41, 0x31, + 0x55, 0x45, 0x41, 0x77, 0x77, 0x47, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x47, + 0x4e, 0x68, 0x4d, 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x30, 0x4d, 0x44, + 0x63, 0x78, 0x4e, 0x7a, 0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x4d, 0x6c, + 0x6f, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x63, 0x78, 0x4e, 0x44, + 0x49, 0x7a, 0x4e, 0x54, 0x59, 0x77, 0x0a, 0x4d, 0x6c, 0x6f, 0x77, 0x57, + 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, + 0x68, 0x4d, 0x43, 0x51, 0x56, 0x55, 0x78, 0x45, 0x7a, 0x41, 0x52, 0x42, + 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, + 0x57, 0x55, 0x74, 0x55, 0x33, 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, + 0x54, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x0a, + 0x47, 0x45, 0x6c, 0x75, 0x64, 0x47, 0x56, 0x79, 0x62, 0x6d, 0x56, 0x30, + 0x49, 0x46, 0x64, 0x70, 0x5a, 0x47, 0x64, 0x70, 0x64, 0x48, 0x4d, 0x67, + 0x55, 0x48, 0x52, 0x35, 0x49, 0x45, 0x78, 0x30, 0x5a, 0x44, 0x45, 0x54, + 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4b, + 0x64, 0x47, 0x56, 0x7a, 0x64, 0x47, 0x4e, 0x73, 0x61, 0x57, 0x56, 0x75, + 0x64, 0x44, 0x43, 0x42, 0x0a, 0x6e, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, + 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, + 0x46, 0x41, 0x41, 0x4f, 0x42, 0x6a, 0x51, 0x41, 0x77, 0x67, 0x59, 0x6b, + 0x43, 0x67, 0x59, 0x45, 0x41, 0x37, 0x46, 0x52, 0x48, 0x32, 0x36, 0x47, + 0x2b, 0x46, 0x74, 0x35, 0x56, 0x51, 0x67, 0x79, 0x7a, 0x6c, 0x5a, 0x73, + 0x66, 0x53, 0x6e, 0x48, 0x53, 0x5a, 0x36, 0x47, 0x58, 0x0a, 0x62, 0x37, + 0x71, 0x78, 0x6d, 0x6b, 0x32, 0x50, 0x4f, 0x38, 0x54, 0x59, 0x71, 0x4b, + 0x5a, 0x6d, 0x6b, 0x66, 0x4d, 0x77, 0x6b, 0x65, 0x36, 0x52, 0x55, 0x66, + 0x51, 0x56, 0x2b, 0x53, 0x2b, 0x47, 0x7a, 0x52, 0x76, 0x7a, 0x35, 0x4c, + 0x6c, 0x53, 0x33, 0x31, 0x55, 0x31, 0x51, 0x43, 0x70, 0x33, 0x63, 0x67, + 0x77, 0x6b, 0x49, 0x49, 0x41, 0x51, 0x61, 0x31, 0x45, 0x32, 0x68, 0x43, + 0x45, 0x7a, 0x0a, 0x57, 0x33, 0x31, 0x69, 0x76, 0x62, 0x4d, 0x42, 0x79, + 0x52, 0x4b, 0x39, 0x74, 0x46, 0x70, 0x79, 0x6e, 0x34, 0x55, 0x76, 0x38, + 0x4b, 0x50, 0x31, 0x34, 0x4f, 0x62, 0x4b, 0x6a, 0x54, 0x51, 0x71, 0x78, + 0x55, 0x5a, 0x70, 0x35, 0x35, 0x38, 0x44, 0x67, 0x4f, 0x48, 0x67, 0x35, + 0x62, 0x35, 0x6d, 0x47, 0x52, 0x4d, 0x30, 0x70, 0x79, 0x56, 0x31, 0x65, + 0x71, 0x52, 0x4b, 0x36, 0x50, 0x57, 0x77, 0x0a, 0x52, 0x2f, 0x62, 0x6a, + 0x67, 0x6c, 0x6c, 0x69, 0x36, 0x70, 0x6d, 0x6e, 0x72, 0x2b, 0x30, 0x43, + 0x41, 0x77, 0x45, 0x41, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, + 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, + 0x41, 0x41, 0x4f, 0x42, 0x67, 0x51, 0x41, 0x53, 0x74, 0x53, 0x6d, 0x35, + 0x50, 0x4d, 0x37, 0x75, 0x62, 0x52, 0x4f, 0x69, 0x4b, 0x4b, 0x36, 0x2f, + 0x0a, 0x54, 0x32, 0x46, 0x6b, 0x4b, 0x6c, 0x68, 0x69, 0x54, 0x4f, 0x78, + 0x2b, 0x52, 0x79, 0x65, 0x6e, 0x6d, 0x33, 0x45, 0x69, 0x6f, 0x35, 0x39, + 0x65, 0x6d, 0x71, 0x2b, 0x6a, 0x58, 0x6c, 0x2b, 0x31, 0x6e, 0x68, 0x50, + 0x79, 0x53, 0x58, 0x35, 0x47, 0x32, 0x50, 0x51, 0x7a, 0x53, 0x52, 0x35, + 0x76, 0x64, 0x31, 0x64, 0x49, 0x68, 0x77, 0x67, 0x5a, 0x53, 0x52, 0x34, + 0x47, 0x79, 0x74, 0x74, 0x6b, 0x0a, 0x74, 0x52, 0x5a, 0x35, 0x37, 0x6b, + 0x2f, 0x4e, 0x49, 0x31, 0x62, 0x72, 0x55, 0x57, 0x38, 0x6a, 0x6f, 0x69, + 0x45, 0x4f, 0x4d, 0x4a, 0x41, 0x2f, 0x4d, 0x72, 0x37, 0x48, 0x37, 0x61, + 0x73, 0x78, 0x37, 0x77, 0x49, 0x52, 0x59, 0x44, 0x45, 0x39, 0x31, 0x46, + 0x73, 0x38, 0x47, 0x6b, 0x4b, 0x57, 0x64, 0x35, 0x4c, 0x68, 0x6f, 0x50, + 0x41, 0x51, 0x6a, 0x2b, 0x71, 0x64, 0x47, 0x33, 0x35, 0x43, 0x0a, 0x4f, + 0x4f, 0x2b, 0x73, 0x76, 0x64, 0x6b, 0x6d, 0x71, 0x48, 0x30, 0x4b, 0x5a, + 0x6f, 0x33, 0x32, 0x30, 0x5a, 0x55, 0x71, 0x64, 0x6c, 0x32, 0x6f, 0x6f, + 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, + 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; + +const char test_signed_client_key[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, + 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x65, 0x51, 0x49, 0x42, + 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, + 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, + 0x41, 0x6d, 0x4d, 0x77, 0x67, 0x67, 0x4a, 0x66, 0x41, 0x67, 0x45, 0x41, + 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4f, 0x78, 0x55, 0x52, 0x39, 0x75, 0x68, + 0x76, 0x68, 0x62, 0x65, 0x56, 0x55, 0x49, 0x4d, 0x0a, 0x73, 0x35, 0x57, + 0x62, 0x48, 0x30, 0x70, 0x78, 0x30, 0x6d, 0x65, 0x68, 0x6c, 0x32, 0x2b, + 0x36, 0x73, 0x5a, 0x70, 0x4e, 0x6a, 0x7a, 0x76, 0x45, 0x32, 0x4b, 0x69, + 0x6d, 0x5a, 0x70, 0x48, 0x7a, 0x4d, 0x4a, 0x48, 0x75, 0x6b, 0x56, 0x48, + 0x30, 0x46, 0x66, 0x6b, 0x76, 0x68, 0x73, 0x30, 0x62, 0x38, 0x2b, 0x53, + 0x35, 0x55, 0x74, 0x39, 0x56, 0x4e, 0x55, 0x41, 0x71, 0x64, 0x33, 0x49, + 0x4d, 0x0a, 0x4a, 0x43, 0x43, 0x41, 0x45, 0x47, 0x74, 0x52, 0x4e, 0x6f, + 0x51, 0x68, 0x4d, 0x31, 0x74, 0x39, 0x59, 0x72, 0x32, 0x7a, 0x41, 0x63, + 0x6b, 0x53, 0x76, 0x62, 0x52, 0x61, 0x63, 0x70, 0x2b, 0x46, 0x4c, 0x2f, + 0x43, 0x6a, 0x39, 0x65, 0x44, 0x6d, 0x79, 0x6f, 0x30, 0x30, 0x4b, 0x73, + 0x56, 0x47, 0x61, 0x65, 0x65, 0x66, 0x41, 0x34, 0x44, 0x68, 0x34, 0x4f, + 0x57, 0x2b, 0x5a, 0x68, 0x6b, 0x54, 0x0a, 0x4e, 0x4b, 0x63, 0x6c, 0x64, + 0x58, 0x71, 0x6b, 0x53, 0x75, 0x6a, 0x31, 0x73, 0x45, 0x66, 0x32, 0x34, + 0x34, 0x4a, 0x5a, 0x59, 0x75, 0x71, 0x5a, 0x70, 0x36, 0x2f, 0x74, 0x41, + 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x59, 0x45, 0x41, 0x69, + 0x32, 0x4e, 0x53, 0x56, 0x71, 0x70, 0x5a, 0x4d, 0x61, 0x66, 0x45, 0x35, + 0x59, 0x59, 0x55, 0x54, 0x63, 0x4d, 0x47, 0x65, 0x36, 0x51, 0x53, 0x0a, + 0x6b, 0x32, 0x6a, 0x74, 0x70, 0x73, 0x71, 0x59, 0x67, 0x67, 0x67, 0x49, + 0x32, 0x52, 0x6e, 0x4c, 0x4a, 0x2f, 0x32, 0x74, 0x4e, 0x5a, 0x77, 0x59, + 0x49, 0x35, 0x70, 0x77, 0x50, 0x38, 0x51, 0x56, 0x53, 0x62, 0x6e, 0x4d, + 0x61, 0x69, 0x46, 0x34, 0x67, 0x6f, 0x6b, 0x44, 0x35, 0x68, 0x47, 0x64, + 0x72, 0x4e, 0x44, 0x66, 0x54, 0x6e, 0x62, 0x32, 0x76, 0x2b, 0x79, 0x49, + 0x77, 0x59, 0x45, 0x48, 0x0a, 0x30, 0x77, 0x38, 0x2b, 0x6f, 0x47, 0x37, + 0x5a, 0x38, 0x31, 0x4b, 0x6f, 0x64, 0x73, 0x69, 0x5a, 0x53, 0x49, 0x44, + 0x4a, 0x66, 0x54, 0x47, 0x73, 0x41, 0x5a, 0x68, 0x56, 0x4e, 0x77, 0x4f, + 0x7a, 0x39, 0x79, 0x30, 0x56, 0x44, 0x38, 0x42, 0x42, 0x5a, 0x5a, 0x31, + 0x2f, 0x32, 0x37, 0x34, 0x5a, 0x68, 0x35, 0x32, 0x41, 0x55, 0x4b, 0x4c, + 0x6a, 0x5a, 0x53, 0x2f, 0x5a, 0x77, 0x49, 0x62, 0x53, 0x0a, 0x57, 0x32, + 0x79, 0x77, 0x79, 0x61, 0x38, 0x35, 0x35, 0x64, 0x50, 0x6e, 0x48, 0x2f, + 0x77, 0x6a, 0x2b, 0x30, 0x45, 0x43, 0x51, 0x51, 0x44, 0x39, 0x58, 0x38, + 0x44, 0x39, 0x32, 0x30, 0x6b, 0x42, 0x79, 0x54, 0x4e, 0x48, 0x68, 0x42, + 0x47, 0x31, 0x38, 0x62, 0x69, 0x41, 0x45, 0x5a, 0x34, 0x70, 0x78, 0x73, + 0x39, 0x66, 0x30, 0x4f, 0x41, 0x47, 0x38, 0x33, 0x33, 0x33, 0x65, 0x56, + 0x63, 0x49, 0x0a, 0x77, 0x32, 0x6c, 0x4a, 0x44, 0x4c, 0x73, 0x59, 0x44, + 0x5a, 0x72, 0x43, 0x42, 0x32, 0x6f, 0x63, 0x67, 0x41, 0x33, 0x6c, 0x55, + 0x64, 0x6f, 0x7a, 0x6c, 0x7a, 0x50, 0x43, 0x37, 0x59, 0x44, 0x59, 0x77, + 0x38, 0x72, 0x65, 0x67, 0x30, 0x74, 0x6b, 0x69, 0x52, 0x59, 0x35, 0x41, + 0x6b, 0x45, 0x41, 0x37, 0x73, 0x64, 0x4e, 0x7a, 0x4f, 0x65, 0x51, 0x73, + 0x51, 0x52, 0x6e, 0x37, 0x2b, 0x2b, 0x35, 0x0a, 0x30, 0x62, 0x50, 0x39, + 0x44, 0x74, 0x54, 0x2f, 0x69, 0x4f, 0x4e, 0x31, 0x67, 0x62, 0x66, 0x78, + 0x52, 0x7a, 0x43, 0x66, 0x43, 0x66, 0x58, 0x64, 0x6f, 0x4f, 0x74, 0x66, + 0x51, 0x57, 0x49, 0x7a, 0x54, 0x65, 0x50, 0x57, 0x74, 0x55, 0x52, 0x74, + 0x39, 0x58, 0x2f, 0x35, 0x44, 0x39, 0x4e, 0x6f, 0x66, 0x49, 0x30, 0x52, + 0x67, 0x35, 0x57, 0x32, 0x6f, 0x47, 0x79, 0x2f, 0x4d, 0x4c, 0x65, 0x35, + 0x0a, 0x2f, 0x73, 0x58, 0x48, 0x56, 0x51, 0x4a, 0x42, 0x41, 0x49, 0x75, + 0x70, 0x35, 0x58, 0x72, 0x4a, 0x44, 0x6b, 0x51, 0x79, 0x77, 0x4e, 0x5a, + 0x79, 0x41, 0x55, 0x55, 0x32, 0x65, 0x63, 0x6e, 0x32, 0x62, 0x43, 0x57, + 0x42, 0x46, 0x6a, 0x77, 0x74, 0x71, 0x64, 0x2b, 0x4c, 0x42, 0x6d, 0x75, + 0x4d, 0x63, 0x69, 0x49, 0x39, 0x66, 0x4f, 0x4b, 0x73, 0x5a, 0x74, 0x45, + 0x4b, 0x5a, 0x72, 0x7a, 0x2f, 0x0a, 0x55, 0x30, 0x6c, 0x6b, 0x65, 0x4d, + 0x52, 0x6f, 0x53, 0x77, 0x76, 0x58, 0x45, 0x38, 0x77, 0x6d, 0x47, 0x4c, + 0x6a, 0x6a, 0x72, 0x41, 0x62, 0x64, 0x66, 0x6f, 0x68, 0x72, 0x58, 0x46, + 0x6b, 0x43, 0x51, 0x51, 0x44, 0x5a, 0x45, 0x78, 0x2f, 0x4c, 0x74, 0x49, + 0x6c, 0x36, 0x4a, 0x49, 0x4e, 0x4a, 0x51, 0x69, 0x73, 0x77, 0x56, 0x65, + 0x30, 0x74, 0x57, 0x72, 0x36, 0x6b, 0x2b, 0x41, 0x53, 0x50, 0x0a, 0x31, + 0x57, 0x58, 0x6f, 0x54, 0x6d, 0x2b, 0x48, 0x59, 0x70, 0x6f, 0x46, 0x2f, + 0x58, 0x55, 0x76, 0x76, 0x39, 0x4c, 0x63, 0x63, 0x4e, 0x46, 0x31, 0x49, + 0x61, 0x7a, 0x46, 0x6a, 0x33, 0x34, 0x68, 0x77, 0x52, 0x51, 0x77, 0x68, + 0x78, 0x37, 0x77, 0x2f, 0x56, 0x35, 0x32, 0x49, 0x65, 0x62, 0x2b, 0x70, + 0x30, 0x6a, 0x55, 0x4d, 0x59, 0x47, 0x78, 0x41, 0x6b, 0x45, 0x41, 0x6a, + 0x44, 0x68, 0x64, 0x0a, 0x39, 0x70, 0x42, 0x4f, 0x31, 0x66, 0x4b, 0x58, + 0x57, 0x69, 0x58, 0x7a, 0x69, 0x39, 0x5a, 0x4b, 0x66, 0x6f, 0x79, 0x54, + 0x4e, 0x63, 0x55, 0x71, 0x33, 0x65, 0x42, 0x53, 0x56, 0x4b, 0x77, 0x50, + 0x47, 0x32, 0x6e, 0x49, 0x74, 0x67, 0x35, 0x79, 0x63, 0x58, 0x65, 0x6e, + 0x67, 0x6a, 0x54, 0x35, 0x73, 0x67, 0x63, 0x57, 0x44, 0x6e, 0x63, 0x69, + 0x49, 0x7a, 0x57, 0x37, 0x42, 0x49, 0x56, 0x49, 0x0a, 0x4a, 0x69, 0x71, + 0x4f, 0x73, 0x7a, 0x71, 0x39, 0x47, 0x57, 0x45, 0x53, 0x45, 0x72, 0x41, + 0x61, 0x74, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, + 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, + 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/server1_cert.c b/test/core/end2end/data/server1_cert.c deleted file mode 100644 index 8d149607b6..0000000000 --- a/test/core/end2end/data/server1_cert.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const char test_server1_cert[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, - 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6e, 0x44, 0x43, 0x43, - 0x41, 0x67, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, - 0x42, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, - 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x57, - 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, - 0x45, 0x77, 0x4a, 0x42, 0x56, 0x54, 0x45, 0x54, 0x0a, 0x4d, 0x42, 0x45, - 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4d, 0x4b, 0x55, 0x32, 0x39, - 0x74, 0x5a, 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, - 0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4d, - 0x59, 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, - 0x67, 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, 0x30, 0x63, 0x79, 0x42, - 0x51, 0x0a, 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x51, - 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77, - 0x5a, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x59, 0x32, 0x45, 0x77, 0x48, 0x68, - 0x63, 0x4e, 0x4d, 0x54, 0x55, 0x78, 0x4d, 0x54, 0x41, 0x30, 0x4d, 0x44, - 0x49, 0x79, 0x4d, 0x44, 0x49, 0x30, 0x57, 0x68, 0x63, 0x4e, 0x4d, 0x6a, - 0x55, 0x78, 0x4d, 0x54, 0x41, 0x78, 0x0a, 0x4d, 0x44, 0x49, 0x79, 0x4d, - 0x44, 0x49, 0x30, 0x57, 0x6a, 0x42, 0x6c, 0x4d, 0x51, 0x73, 0x77, 0x43, - 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x56, 0x55, - 0x7a, 0x45, 0x52, 0x4d, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, - 0x42, 0x4d, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, - 0x58, 0x4d, 0x78, 0x45, 0x44, 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x0a, - 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4e, 0x6f, 0x61, 0x57, 0x4e, 0x68, - 0x5a, 0x32, 0x38, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4e, 0x56, - 0x42, 0x41, 0x6f, 0x54, 0x44, 0x45, 0x56, 0x34, 0x59, 0x57, 0x31, 0x77, - 0x62, 0x47, 0x55, 0x73, 0x49, 0x45, 0x4e, 0x76, 0x4c, 0x6a, 0x45, 0x61, - 0x4d, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x51, 0x52, - 0x4b, 0x69, 0x35, 0x30, 0x0a, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, - 0x76, 0x62, 0x32, 0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x62, 0x32, 0x30, - 0x77, 0x67, 0x5a, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, - 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, - 0x44, 0x67, 0x59, 0x30, 0x41, 0x4d, 0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47, - 0x42, 0x41, 0x4f, 0x48, 0x44, 0x46, 0x53, 0x63, 0x6f, 0x0a, 0x4c, 0x43, - 0x56, 0x4a, 0x70, 0x59, 0x44, 0x44, 0x4d, 0x34, 0x48, 0x59, 0x74, 0x49, - 0x64, 0x56, 0x36, 0x41, 0x6b, 0x65, 0x2f, 0x73, 0x4d, 0x4e, 0x61, 0x61, - 0x4b, 0x64, 0x4f, 0x44, 0x6a, 0x44, 0x4d, 0x73, 0x75, 0x78, 0x2f, 0x34, - 0x74, 0x44, 0x79, 0x64, 0x6c, 0x75, 0x6d, 0x4e, 0x2b, 0x66, 0x6d, 0x2b, - 0x41, 0x6a, 0x50, 0x45, 0x4b, 0x35, 0x47, 0x48, 0x68, 0x47, 0x6e, 0x31, - 0x42, 0x67, 0x0a, 0x7a, 0x6b, 0x57, 0x46, 0x2b, 0x73, 0x6c, 0x66, 0x33, - 0x42, 0x78, 0x68, 0x72, 0x41, 0x2f, 0x38, 0x64, 0x4e, 0x73, 0x6e, 0x75, - 0x6e, 0x73, 0x74, 0x56, 0x41, 0x37, 0x5a, 0x42, 0x67, 0x41, 0x2f, 0x35, - 0x71, 0x51, 0x78, 0x4d, 0x66, 0x47, 0x41, 0x71, 0x34, 0x77, 0x48, 0x4e, - 0x56, 0x58, 0x37, 0x37, 0x66, 0x42, 0x5a, 0x4f, 0x67, 0x70, 0x39, 0x56, - 0x6c, 0x53, 0x4d, 0x56, 0x66, 0x79, 0x64, 0x0a, 0x39, 0x4e, 0x38, 0x59, - 0x77, 0x62, 0x42, 0x59, 0x41, 0x63, 0x6b, 0x4f, 0x65, 0x55, 0x51, 0x61, - 0x64, 0x54, 0x69, 0x32, 0x58, 0x31, 0x53, 0x36, 0x4f, 0x67, 0x4a, 0x58, - 0x67, 0x51, 0x30, 0x6d, 0x33, 0x4d, 0x57, 0x68, 0x41, 0x67, 0x4d, 0x42, - 0x41, 0x41, 0x47, 0x6a, 0x61, 0x7a, 0x42, 0x70, 0x4d, 0x41, 0x6b, 0x47, - 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x51, 0x43, 0x4d, 0x41, 0x41, 0x77, - 0x0a, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, 0x51, - 0x44, 0x41, 0x67, 0x58, 0x67, 0x4d, 0x45, 0x38, 0x47, 0x41, 0x31, 0x55, - 0x64, 0x45, 0x51, 0x52, 0x49, 0x4d, 0x45, 0x61, 0x43, 0x45, 0x43, 0x6f, - 0x75, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39, - 0x6e, 0x62, 0x47, 0x55, 0x75, 0x5a, 0x6e, 0x4b, 0x43, 0x47, 0x48, 0x64, - 0x68, 0x64, 0x47, 0x56, 0x79, 0x0a, 0x65, 0x6d, 0x39, 0x76, 0x61, 0x53, - 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32, - 0x64, 0x73, 0x5a, 0x53, 0x35, 0x69, 0x5a, 0x59, 0x49, 0x53, 0x4b, 0x69, - 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6e, 0x6c, 0x76, 0x64, 0x58, - 0x52, 0x31, 0x59, 0x6d, 0x55, 0x75, 0x59, 0x32, 0x39, 0x74, 0x68, 0x77, - 0x54, 0x41, 0x71, 0x41, 0x45, 0x44, 0x4d, 0x41, 0x30, 0x47, 0x0a, 0x43, - 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, - 0x77, 0x55, 0x41, 0x41, 0x34, 0x47, 0x42, 0x41, 0x4a, 0x46, 0x58, 0x56, - 0x69, 0x66, 0x51, 0x4e, 0x75, 0x62, 0x31, 0x4c, 0x55, 0x50, 0x34, 0x4a, - 0x6c, 0x6e, 0x58, 0x35, 0x6c, 0x58, 0x4e, 0x6c, 0x6f, 0x38, 0x46, 0x78, - 0x5a, 0x32, 0x61, 0x31, 0x32, 0x41, 0x46, 0x51, 0x73, 0x2b, 0x62, 0x7a, - 0x6f, 0x4a, 0x36, 0x0a, 0x68, 0x4d, 0x30, 0x34, 0x34, 0x45, 0x44, 0x6a, - 0x71, 0x79, 0x78, 0x55, 0x71, 0x53, 0x62, 0x56, 0x65, 0x50, 0x4b, 0x30, - 0x6e, 0x69, 0x33, 0x77, 0x31, 0x66, 0x48, 0x51, 0x42, 0x35, 0x72, 0x59, - 0x39, 0x79, 0x59, 0x43, 0x35, 0x66, 0x38, 0x47, 0x37, 0x61, 0x71, 0x71, - 0x54, 0x59, 0x31, 0x51, 0x4f, 0x68, 0x6f, 0x55, 0x6b, 0x38, 0x5a, 0x54, - 0x53, 0x54, 0x52, 0x70, 0x6e, 0x6b, 0x54, 0x68, 0x0a, 0x79, 0x34, 0x6a, - 0x6a, 0x64, 0x76, 0x54, 0x5a, 0x65, 0x4c, 0x44, 0x56, 0x42, 0x6c, 0x75, - 0x65, 0x5a, 0x55, 0x54, 0x44, 0x52, 0x6d, 0x79, 0x32, 0x66, 0x65, 0x59, - 0x35, 0x61, 0x5a, 0x49, 0x55, 0x31, 0x38, 0x76, 0x46, 0x44, 0x4b, 0x30, - 0x38, 0x64, 0x54, 0x47, 0x30, 0x41, 0x38, 0x37, 0x70, 0x70, 0x70, 0x75, - 0x76, 0x31, 0x4c, 0x4e, 0x49, 0x52, 0x33, 0x6c, 0x6f, 0x76, 0x65, 0x55, - 0x38, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, - 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/server1_cert.cc b/test/core/end2end/data/server1_cert.cc new file mode 100644 index 0000000000..5e017c4da7 --- /dev/null +++ b/test/core/end2end/data/server1_cert.cc @@ -0,0 +1,102 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/data/ssl_test_data.h" + +const char test_server1_cert[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6e, 0x44, 0x43, 0x43, + 0x41, 0x67, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42, + 0x42, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, + 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x57, + 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, + 0x45, 0x77, 0x4a, 0x42, 0x56, 0x54, 0x45, 0x54, 0x0a, 0x4d, 0x42, 0x45, + 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4d, 0x4b, 0x55, 0x32, 0x39, + 0x74, 0x5a, 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, + 0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4d, + 0x59, 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, + 0x67, 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, 0x30, 0x63, 0x79, 0x42, + 0x51, 0x0a, 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x51, + 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77, + 0x5a, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x59, 0x32, 0x45, 0x77, 0x48, 0x68, + 0x63, 0x4e, 0x4d, 0x54, 0x55, 0x78, 0x4d, 0x54, 0x41, 0x30, 0x4d, 0x44, + 0x49, 0x79, 0x4d, 0x44, 0x49, 0x30, 0x57, 0x68, 0x63, 0x4e, 0x4d, 0x6a, + 0x55, 0x78, 0x4d, 0x54, 0x41, 0x78, 0x0a, 0x4d, 0x44, 0x49, 0x79, 0x4d, + 0x44, 0x49, 0x30, 0x57, 0x6a, 0x42, 0x6c, 0x4d, 0x51, 0x73, 0x77, 0x43, + 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x56, 0x55, + 0x7a, 0x45, 0x52, 0x4d, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, + 0x42, 0x4d, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61, + 0x58, 0x4d, 0x78, 0x45, 0x44, 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x0a, + 0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4e, 0x6f, 0x61, 0x57, 0x4e, 0x68, + 0x5a, 0x32, 0x38, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4e, 0x56, + 0x42, 0x41, 0x6f, 0x54, 0x44, 0x45, 0x56, 0x34, 0x59, 0x57, 0x31, 0x77, + 0x62, 0x47, 0x55, 0x73, 0x49, 0x45, 0x4e, 0x76, 0x4c, 0x6a, 0x45, 0x61, + 0x4d, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x51, 0x52, + 0x4b, 0x69, 0x35, 0x30, 0x0a, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, + 0x76, 0x62, 0x32, 0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x62, 0x32, 0x30, + 0x77, 0x67, 0x5a, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, + 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, + 0x44, 0x67, 0x59, 0x30, 0x41, 0x4d, 0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47, + 0x42, 0x41, 0x4f, 0x48, 0x44, 0x46, 0x53, 0x63, 0x6f, 0x0a, 0x4c, 0x43, + 0x56, 0x4a, 0x70, 0x59, 0x44, 0x44, 0x4d, 0x34, 0x48, 0x59, 0x74, 0x49, + 0x64, 0x56, 0x36, 0x41, 0x6b, 0x65, 0x2f, 0x73, 0x4d, 0x4e, 0x61, 0x61, + 0x4b, 0x64, 0x4f, 0x44, 0x6a, 0x44, 0x4d, 0x73, 0x75, 0x78, 0x2f, 0x34, + 0x74, 0x44, 0x79, 0x64, 0x6c, 0x75, 0x6d, 0x4e, 0x2b, 0x66, 0x6d, 0x2b, + 0x41, 0x6a, 0x50, 0x45, 0x4b, 0x35, 0x47, 0x48, 0x68, 0x47, 0x6e, 0x31, + 0x42, 0x67, 0x0a, 0x7a, 0x6b, 0x57, 0x46, 0x2b, 0x73, 0x6c, 0x66, 0x33, + 0x42, 0x78, 0x68, 0x72, 0x41, 0x2f, 0x38, 0x64, 0x4e, 0x73, 0x6e, 0x75, + 0x6e, 0x73, 0x74, 0x56, 0x41, 0x37, 0x5a, 0x42, 0x67, 0x41, 0x2f, 0x35, + 0x71, 0x51, 0x78, 0x4d, 0x66, 0x47, 0x41, 0x71, 0x34, 0x77, 0x48, 0x4e, + 0x56, 0x58, 0x37, 0x37, 0x66, 0x42, 0x5a, 0x4f, 0x67, 0x70, 0x39, 0x56, + 0x6c, 0x53, 0x4d, 0x56, 0x66, 0x79, 0x64, 0x0a, 0x39, 0x4e, 0x38, 0x59, + 0x77, 0x62, 0x42, 0x59, 0x41, 0x63, 0x6b, 0x4f, 0x65, 0x55, 0x51, 0x61, + 0x64, 0x54, 0x69, 0x32, 0x58, 0x31, 0x53, 0x36, 0x4f, 0x67, 0x4a, 0x58, + 0x67, 0x51, 0x30, 0x6d, 0x33, 0x4d, 0x57, 0x68, 0x41, 0x67, 0x4d, 0x42, + 0x41, 0x41, 0x47, 0x6a, 0x61, 0x7a, 0x42, 0x70, 0x4d, 0x41, 0x6b, 0x47, + 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x51, 0x43, 0x4d, 0x41, 0x41, 0x77, + 0x0a, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, 0x51, + 0x44, 0x41, 0x67, 0x58, 0x67, 0x4d, 0x45, 0x38, 0x47, 0x41, 0x31, 0x55, + 0x64, 0x45, 0x51, 0x52, 0x49, 0x4d, 0x45, 0x61, 0x43, 0x45, 0x43, 0x6f, + 0x75, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39, + 0x6e, 0x62, 0x47, 0x55, 0x75, 0x5a, 0x6e, 0x4b, 0x43, 0x47, 0x48, 0x64, + 0x68, 0x64, 0x47, 0x56, 0x79, 0x0a, 0x65, 0x6d, 0x39, 0x76, 0x61, 0x53, + 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32, + 0x64, 0x73, 0x5a, 0x53, 0x35, 0x69, 0x5a, 0x59, 0x49, 0x53, 0x4b, 0x69, + 0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6e, 0x6c, 0x76, 0x64, 0x58, + 0x52, 0x31, 0x59, 0x6d, 0x55, 0x75, 0x59, 0x32, 0x39, 0x74, 0x68, 0x77, + 0x54, 0x41, 0x71, 0x41, 0x45, 0x44, 0x4d, 0x41, 0x30, 0x47, 0x0a, 0x43, + 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, + 0x77, 0x55, 0x41, 0x41, 0x34, 0x47, 0x42, 0x41, 0x4a, 0x46, 0x58, 0x56, + 0x69, 0x66, 0x51, 0x4e, 0x75, 0x62, 0x31, 0x4c, 0x55, 0x50, 0x34, 0x4a, + 0x6c, 0x6e, 0x58, 0x35, 0x6c, 0x58, 0x4e, 0x6c, 0x6f, 0x38, 0x46, 0x78, + 0x5a, 0x32, 0x61, 0x31, 0x32, 0x41, 0x46, 0x51, 0x73, 0x2b, 0x62, 0x7a, + 0x6f, 0x4a, 0x36, 0x0a, 0x68, 0x4d, 0x30, 0x34, 0x34, 0x45, 0x44, 0x6a, + 0x71, 0x79, 0x78, 0x55, 0x71, 0x53, 0x62, 0x56, 0x65, 0x50, 0x4b, 0x30, + 0x6e, 0x69, 0x33, 0x77, 0x31, 0x66, 0x48, 0x51, 0x42, 0x35, 0x72, 0x59, + 0x39, 0x79, 0x59, 0x43, 0x35, 0x66, 0x38, 0x47, 0x37, 0x61, 0x71, 0x71, + 0x54, 0x59, 0x31, 0x51, 0x4f, 0x68, 0x6f, 0x55, 0x6b, 0x38, 0x5a, 0x54, + 0x53, 0x54, 0x52, 0x70, 0x6e, 0x6b, 0x54, 0x68, 0x0a, 0x79, 0x34, 0x6a, + 0x6a, 0x64, 0x76, 0x54, 0x5a, 0x65, 0x4c, 0x44, 0x56, 0x42, 0x6c, 0x75, + 0x65, 0x5a, 0x55, 0x54, 0x44, 0x52, 0x6d, 0x79, 0x32, 0x66, 0x65, 0x59, + 0x35, 0x61, 0x5a, 0x49, 0x55, 0x31, 0x38, 0x76, 0x46, 0x44, 0x4b, 0x30, + 0x38, 0x64, 0x54, 0x47, 0x30, 0x41, 0x38, 0x37, 0x70, 0x70, 0x70, 0x75, + 0x76, 0x31, 0x4c, 0x4e, 0x49, 0x52, 0x33, 0x6c, 0x6f, 0x76, 0x65, 0x55, + 0x38, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/server1_key.c b/test/core/end2end/data/server1_key.c deleted file mode 100644 index eee5cc6d82..0000000000 --- a/test/core/end2end/data/server1_key.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const char test_server1_key[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, - 0x57, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x68, - 0x77, 0x78, 0x55, 0x6e, 0x4b, 0x43, 0x77, 0x6c, 0x53, 0x61, 0x57, 0x41, - 0x77, 0x7a, 0x4f, 0x42, 0x32, 0x4c, 0x53, 0x48, 0x56, 0x65, 0x67, 0x4a, - 0x48, 0x76, 0x37, 0x44, 0x44, 0x57, 0x6d, 0x69, 0x6e, 0x54, 0x67, 0x34, - 0x77, 0x7a, 0x4c, 0x4c, 0x73, 0x66, 0x2b, 0x4c, 0x51, 0x38, 0x6e, 0x5a, - 0x0a, 0x62, 0x70, 0x6a, 0x66, 0x6e, 0x35, 0x76, 0x67, 0x49, 0x7a, 0x78, - 0x43, 0x75, 0x52, 0x68, 0x34, 0x52, 0x70, 0x39, 0x51, 0x59, 0x4d, 0x35, - 0x46, 0x68, 0x66, 0x72, 0x4a, 0x58, 0x39, 0x77, 0x63, 0x59, 0x61, 0x77, - 0x50, 0x2f, 0x48, 0x54, 0x62, 0x4a, 0x37, 0x70, 0x37, 0x4c, 0x56, 0x51, - 0x4f, 0x32, 0x51, 0x59, 0x41, 0x50, 0x2b, 0x61, 0x6b, 0x4d, 0x54, 0x48, - 0x78, 0x67, 0x4b, 0x75, 0x4d, 0x0a, 0x42, 0x7a, 0x56, 0x56, 0x2b, 0x2b, - 0x33, 0x77, 0x57, 0x54, 0x6f, 0x4b, 0x66, 0x56, 0x5a, 0x55, 0x6a, 0x46, - 0x58, 0x38, 0x6e, 0x66, 0x54, 0x66, 0x47, 0x4d, 0x47, 0x77, 0x57, 0x41, - 0x48, 0x4a, 0x44, 0x6e, 0x6c, 0x45, 0x47, 0x6e, 0x55, 0x34, 0x74, 0x6c, - 0x39, 0x55, 0x75, 0x6a, 0x6f, 0x43, 0x56, 0x34, 0x45, 0x4e, 0x4a, 0x74, - 0x7a, 0x46, 0x6f, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0a, 0x41, - 0x6f, 0x47, 0x41, 0x4a, 0x2b, 0x36, 0x68, 0x70, 0x7a, 0x4e, 0x72, 0x32, - 0x34, 0x79, 0x54, 0x51, 0x5a, 0x74, 0x46, 0x57, 0x51, 0x70, 0x44, 0x70, - 0x45, 0x79, 0x46, 0x70, 0x6c, 0x64, 0x64, 0x4b, 0x4a, 0x4d, 0x4f, 0x78, - 0x44, 0x79, 0x61, 0x33, 0x53, 0x39, 0x70, 0x70, 0x4b, 0x33, 0x76, 0x54, - 0x57, 0x72, 0x49, 0x49, 0x54, 0x56, 0x32, 0x78, 0x4e, 0x63, 0x75, 0x63, - 0x77, 0x37, 0x49, 0x0a, 0x63, 0x65, 0x54, 0x62, 0x64, 0x79, 0x72, 0x47, - 0x73, 0x79, 0x6a, 0x73, 0x55, 0x30, 0x2f, 0x48, 0x64, 0x43, 0x63, 0x49, - 0x66, 0x39, 0x79, 0x6d, 0x32, 0x6a, 0x66, 0x6d, 0x47, 0x4c, 0x55, 0x77, - 0x6d, 0x79, 0x68, 0x6c, 0x74, 0x4b, 0x56, 0x77, 0x30, 0x51, 0x59, 0x63, - 0x46, 0x42, 0x30, 0x58, 0x4c, 0x6b, 0x63, 0x30, 0x6e, 0x49, 0x35, 0x59, - 0x76, 0x45, 0x59, 0x6f, 0x65, 0x56, 0x44, 0x67, 0x0a, 0x6f, 0x6d, 0x5a, - 0x49, 0x58, 0x6e, 0x31, 0x45, 0x33, 0x45, 0x57, 0x2b, 0x73, 0x53, 0x49, - 0x57, 0x53, 0x62, 0x6b, 0x4d, 0x75, 0x39, 0x62, 0x59, 0x32, 0x6b, 0x73, - 0x74, 0x4b, 0x58, 0x52, 0x32, 0x55, 0x5a, 0x6d, 0x4d, 0x67, 0x57, 0x44, - 0x74, 0x6d, 0x42, 0x45, 0x50, 0x4d, 0x61, 0x45, 0x43, 0x51, 0x51, 0x44, - 0x36, 0x79, 0x54, 0x34, 0x54, 0x41, 0x5a, 0x4d, 0x35, 0x68, 0x47, 0x42, - 0x62, 0x0a, 0x63, 0x69, 0x42, 0x4b, 0x67, 0x4d, 0x55, 0x50, 0x36, 0x50, - 0x77, 0x4f, 0x68, 0x50, 0x68, 0x4f, 0x4d, 0x50, 0x49, 0x76, 0x69, 0x6a, - 0x4f, 0x35, 0x30, 0x41, 0x69, 0x75, 0x36, 0x69, 0x75, 0x43, 0x56, 0x38, - 0x38, 0x6c, 0x31, 0x51, 0x49, 0x79, 0x33, 0x38, 0x67, 0x57, 0x56, 0x68, - 0x78, 0x6a, 0x4e, 0x72, 0x71, 0x36, 0x50, 0x33, 0x34, 0x36, 0x6a, 0x34, - 0x49, 0x42, 0x67, 0x2b, 0x6b, 0x42, 0x0a, 0x39, 0x61, 0x6c, 0x77, 0x70, - 0x43, 0x4f, 0x44, 0x41, 0x6b, 0x45, 0x41, 0x35, 0x6e, 0x53, 0x6e, 0x6d, - 0x39, 0x6b, 0x36, 0x79, 0x6b, 0x59, 0x65, 0x51, 0x57, 0x4e, 0x53, 0x30, - 0x66, 0x4e, 0x57, 0x69, 0x52, 0x69, 0x6e, 0x43, 0x64, 0x6c, 0x32, 0x33, - 0x41, 0x37, 0x75, 0x73, 0x44, 0x47, 0x53, 0x75, 0x4b, 0x4b, 0x6c, 0x6d, - 0x30, 0x31, 0x39, 0x69, 0x6f, 0x6d, 0x4a, 0x2f, 0x52, 0x67, 0x64, 0x0a, - 0x4d, 0x4b, 0x44, 0x4f, 0x70, 0x30, 0x71, 0x2f, 0x32, 0x4f, 0x6f, 0x73, - 0x74, 0x62, 0x74, 0x65, 0x4f, 0x57, 0x4d, 0x32, 0x4d, 0x52, 0x46, 0x66, - 0x34, 0x6a, 0x4d, 0x48, 0x33, 0x77, 0x79, 0x56, 0x43, 0x77, 0x4a, 0x41, - 0x66, 0x41, 0x64, 0x6a, 0x4a, 0x38, 0x73, 0x7a, 0x6f, 0x4e, 0x4b, 0x54, - 0x52, 0x53, 0x61, 0x67, 0x53, 0x62, 0x68, 0x39, 0x76, 0x57, 0x79, 0x67, - 0x6e, 0x42, 0x32, 0x76, 0x0a, 0x49, 0x42, 0x79, 0x63, 0x36, 0x6c, 0x34, - 0x54, 0x54, 0x75, 0x5a, 0x51, 0x4a, 0x52, 0x47, 0x7a, 0x43, 0x76, 0x65, - 0x61, 0x66, 0x7a, 0x39, 0x6c, 0x6f, 0x76, 0x75, 0x42, 0x33, 0x57, 0x6f, - 0x68, 0x43, 0x41, 0x42, 0x64, 0x51, 0x52, 0x64, 0x39, 0x75, 0x6b, 0x43, - 0x58, 0x4c, 0x32, 0x43, 0x70, 0x73, 0x45, 0x70, 0x71, 0x7a, 0x6b, 0x61, - 0x66, 0x4f, 0x51, 0x4a, 0x41, 0x4a, 0x55, 0x6a, 0x63, 0x0a, 0x55, 0x53, - 0x65, 0x64, 0x44, 0x6c, 0x71, 0x33, 0x7a, 0x47, 0x5a, 0x77, 0x59, 0x4d, - 0x31, 0x59, 0x77, 0x38, 0x64, 0x38, 0x52, 0x75, 0x69, 0x72, 0x42, 0x55, - 0x46, 0x5a, 0x4e, 0x71, 0x4a, 0x65, 0x6c, 0x59, 0x61, 0x69, 0x2b, 0x6e, - 0x52, 0x59, 0x43, 0x6c, 0x44, 0x6b, 0x52, 0x56, 0x46, 0x67, 0x62, 0x35, - 0x79, 0x6b, 0x73, 0x6f, 0x59, 0x79, 0x63, 0x62, 0x71, 0x35, 0x54, 0x78, - 0x47, 0x6f, 0x0a, 0x56, 0x65, 0x71, 0x4b, 0x4f, 0x76, 0x67, 0x50, 0x70, - 0x6a, 0x34, 0x52, 0x57, 0x50, 0x48, 0x6c, 0x4c, 0x77, 0x4a, 0x41, 0x47, - 0x55, 0x4d, 0x6b, 0x33, 0x62, 0x71, 0x54, 0x39, 0x31, 0x78, 0x42, 0x55, - 0x43, 0x6e, 0x4c, 0x52, 0x73, 0x2f, 0x76, 0x66, 0x6f, 0x43, 0x70, 0x48, - 0x70, 0x67, 0x36, 0x65, 0x79, 0x77, 0x51, 0x54, 0x42, 0x44, 0x41, 0x56, - 0x36, 0x78, 0x6b, 0x79, 0x7a, 0x34, 0x61, 0x0a, 0x52, 0x48, 0x33, 0x49, - 0x37, 0x2f, 0x2b, 0x79, 0x6a, 0x33, 0x5a, 0x78, 0x52, 0x32, 0x4a, 0x6f, - 0x57, 0x48, 0x67, 0x55, 0x77, 0x5a, 0x37, 0x6c, 0x5a, 0x6b, 0x31, 0x56, - 0x6e, 0x68, 0x66, 0x66, 0x46, 0x79, 0x65, 0x37, 0x53, 0x42, 0x58, 0x79, - 0x61, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, - 0x44, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, - 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/server1_key.cc b/test/core/end2end/data/server1_key.cc new file mode 100644 index 0000000000..92a77aa21f --- /dev/null +++ b/test/core/end2end/data/server1_key.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/data/ssl_test_data.h" + +const char test_server1_key[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, + 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, + 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, + 0x57, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x68, + 0x77, 0x78, 0x55, 0x6e, 0x4b, 0x43, 0x77, 0x6c, 0x53, 0x61, 0x57, 0x41, + 0x77, 0x7a, 0x4f, 0x42, 0x32, 0x4c, 0x53, 0x48, 0x56, 0x65, 0x67, 0x4a, + 0x48, 0x76, 0x37, 0x44, 0x44, 0x57, 0x6d, 0x69, 0x6e, 0x54, 0x67, 0x34, + 0x77, 0x7a, 0x4c, 0x4c, 0x73, 0x66, 0x2b, 0x4c, 0x51, 0x38, 0x6e, 0x5a, + 0x0a, 0x62, 0x70, 0x6a, 0x66, 0x6e, 0x35, 0x76, 0x67, 0x49, 0x7a, 0x78, + 0x43, 0x75, 0x52, 0x68, 0x34, 0x52, 0x70, 0x39, 0x51, 0x59, 0x4d, 0x35, + 0x46, 0x68, 0x66, 0x72, 0x4a, 0x58, 0x39, 0x77, 0x63, 0x59, 0x61, 0x77, + 0x50, 0x2f, 0x48, 0x54, 0x62, 0x4a, 0x37, 0x70, 0x37, 0x4c, 0x56, 0x51, + 0x4f, 0x32, 0x51, 0x59, 0x41, 0x50, 0x2b, 0x61, 0x6b, 0x4d, 0x54, 0x48, + 0x78, 0x67, 0x4b, 0x75, 0x4d, 0x0a, 0x42, 0x7a, 0x56, 0x56, 0x2b, 0x2b, + 0x33, 0x77, 0x57, 0x54, 0x6f, 0x4b, 0x66, 0x56, 0x5a, 0x55, 0x6a, 0x46, + 0x58, 0x38, 0x6e, 0x66, 0x54, 0x66, 0x47, 0x4d, 0x47, 0x77, 0x57, 0x41, + 0x48, 0x4a, 0x44, 0x6e, 0x6c, 0x45, 0x47, 0x6e, 0x55, 0x34, 0x74, 0x6c, + 0x39, 0x55, 0x75, 0x6a, 0x6f, 0x43, 0x56, 0x34, 0x45, 0x4e, 0x4a, 0x74, + 0x7a, 0x46, 0x6f, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x0a, 0x41, + 0x6f, 0x47, 0x41, 0x4a, 0x2b, 0x36, 0x68, 0x70, 0x7a, 0x4e, 0x72, 0x32, + 0x34, 0x79, 0x54, 0x51, 0x5a, 0x74, 0x46, 0x57, 0x51, 0x70, 0x44, 0x70, + 0x45, 0x79, 0x46, 0x70, 0x6c, 0x64, 0x64, 0x4b, 0x4a, 0x4d, 0x4f, 0x78, + 0x44, 0x79, 0x61, 0x33, 0x53, 0x39, 0x70, 0x70, 0x4b, 0x33, 0x76, 0x54, + 0x57, 0x72, 0x49, 0x49, 0x54, 0x56, 0x32, 0x78, 0x4e, 0x63, 0x75, 0x63, + 0x77, 0x37, 0x49, 0x0a, 0x63, 0x65, 0x54, 0x62, 0x64, 0x79, 0x72, 0x47, + 0x73, 0x79, 0x6a, 0x73, 0x55, 0x30, 0x2f, 0x48, 0x64, 0x43, 0x63, 0x49, + 0x66, 0x39, 0x79, 0x6d, 0x32, 0x6a, 0x66, 0x6d, 0x47, 0x4c, 0x55, 0x77, + 0x6d, 0x79, 0x68, 0x6c, 0x74, 0x4b, 0x56, 0x77, 0x30, 0x51, 0x59, 0x63, + 0x46, 0x42, 0x30, 0x58, 0x4c, 0x6b, 0x63, 0x30, 0x6e, 0x49, 0x35, 0x59, + 0x76, 0x45, 0x59, 0x6f, 0x65, 0x56, 0x44, 0x67, 0x0a, 0x6f, 0x6d, 0x5a, + 0x49, 0x58, 0x6e, 0x31, 0x45, 0x33, 0x45, 0x57, 0x2b, 0x73, 0x53, 0x49, + 0x57, 0x53, 0x62, 0x6b, 0x4d, 0x75, 0x39, 0x62, 0x59, 0x32, 0x6b, 0x73, + 0x74, 0x4b, 0x58, 0x52, 0x32, 0x55, 0x5a, 0x6d, 0x4d, 0x67, 0x57, 0x44, + 0x74, 0x6d, 0x42, 0x45, 0x50, 0x4d, 0x61, 0x45, 0x43, 0x51, 0x51, 0x44, + 0x36, 0x79, 0x54, 0x34, 0x54, 0x41, 0x5a, 0x4d, 0x35, 0x68, 0x47, 0x42, + 0x62, 0x0a, 0x63, 0x69, 0x42, 0x4b, 0x67, 0x4d, 0x55, 0x50, 0x36, 0x50, + 0x77, 0x4f, 0x68, 0x50, 0x68, 0x4f, 0x4d, 0x50, 0x49, 0x76, 0x69, 0x6a, + 0x4f, 0x35, 0x30, 0x41, 0x69, 0x75, 0x36, 0x69, 0x75, 0x43, 0x56, 0x38, + 0x38, 0x6c, 0x31, 0x51, 0x49, 0x79, 0x33, 0x38, 0x67, 0x57, 0x56, 0x68, + 0x78, 0x6a, 0x4e, 0x72, 0x71, 0x36, 0x50, 0x33, 0x34, 0x36, 0x6a, 0x34, + 0x49, 0x42, 0x67, 0x2b, 0x6b, 0x42, 0x0a, 0x39, 0x61, 0x6c, 0x77, 0x70, + 0x43, 0x4f, 0x44, 0x41, 0x6b, 0x45, 0x41, 0x35, 0x6e, 0x53, 0x6e, 0x6d, + 0x39, 0x6b, 0x36, 0x79, 0x6b, 0x59, 0x65, 0x51, 0x57, 0x4e, 0x53, 0x30, + 0x66, 0x4e, 0x57, 0x69, 0x52, 0x69, 0x6e, 0x43, 0x64, 0x6c, 0x32, 0x33, + 0x41, 0x37, 0x75, 0x73, 0x44, 0x47, 0x53, 0x75, 0x4b, 0x4b, 0x6c, 0x6d, + 0x30, 0x31, 0x39, 0x69, 0x6f, 0x6d, 0x4a, 0x2f, 0x52, 0x67, 0x64, 0x0a, + 0x4d, 0x4b, 0x44, 0x4f, 0x70, 0x30, 0x71, 0x2f, 0x32, 0x4f, 0x6f, 0x73, + 0x74, 0x62, 0x74, 0x65, 0x4f, 0x57, 0x4d, 0x32, 0x4d, 0x52, 0x46, 0x66, + 0x34, 0x6a, 0x4d, 0x48, 0x33, 0x77, 0x79, 0x56, 0x43, 0x77, 0x4a, 0x41, + 0x66, 0x41, 0x64, 0x6a, 0x4a, 0x38, 0x73, 0x7a, 0x6f, 0x4e, 0x4b, 0x54, + 0x52, 0x53, 0x61, 0x67, 0x53, 0x62, 0x68, 0x39, 0x76, 0x57, 0x79, 0x67, + 0x6e, 0x42, 0x32, 0x76, 0x0a, 0x49, 0x42, 0x79, 0x63, 0x36, 0x6c, 0x34, + 0x54, 0x54, 0x75, 0x5a, 0x51, 0x4a, 0x52, 0x47, 0x7a, 0x43, 0x76, 0x65, + 0x61, 0x66, 0x7a, 0x39, 0x6c, 0x6f, 0x76, 0x75, 0x42, 0x33, 0x57, 0x6f, + 0x68, 0x43, 0x41, 0x42, 0x64, 0x51, 0x52, 0x64, 0x39, 0x75, 0x6b, 0x43, + 0x58, 0x4c, 0x32, 0x43, 0x70, 0x73, 0x45, 0x70, 0x71, 0x7a, 0x6b, 0x61, + 0x66, 0x4f, 0x51, 0x4a, 0x41, 0x4a, 0x55, 0x6a, 0x63, 0x0a, 0x55, 0x53, + 0x65, 0x64, 0x44, 0x6c, 0x71, 0x33, 0x7a, 0x47, 0x5a, 0x77, 0x59, 0x4d, + 0x31, 0x59, 0x77, 0x38, 0x64, 0x38, 0x52, 0x75, 0x69, 0x72, 0x42, 0x55, + 0x46, 0x5a, 0x4e, 0x71, 0x4a, 0x65, 0x6c, 0x59, 0x61, 0x69, 0x2b, 0x6e, + 0x52, 0x59, 0x43, 0x6c, 0x44, 0x6b, 0x52, 0x56, 0x46, 0x67, 0x62, 0x35, + 0x79, 0x6b, 0x73, 0x6f, 0x59, 0x79, 0x63, 0x62, 0x71, 0x35, 0x54, 0x78, + 0x47, 0x6f, 0x0a, 0x56, 0x65, 0x71, 0x4b, 0x4f, 0x76, 0x67, 0x50, 0x70, + 0x6a, 0x34, 0x52, 0x57, 0x50, 0x48, 0x6c, 0x4c, 0x77, 0x4a, 0x41, 0x47, + 0x55, 0x4d, 0x6b, 0x33, 0x62, 0x71, 0x54, 0x39, 0x31, 0x78, 0x42, 0x55, + 0x43, 0x6e, 0x4c, 0x52, 0x73, 0x2f, 0x76, 0x66, 0x6f, 0x43, 0x70, 0x48, + 0x70, 0x67, 0x36, 0x65, 0x79, 0x77, 0x51, 0x54, 0x42, 0x44, 0x41, 0x56, + 0x36, 0x78, 0x6b, 0x79, 0x7a, 0x34, 0x61, 0x0a, 0x52, 0x48, 0x33, 0x49, + 0x37, 0x2f, 0x2b, 0x79, 0x6a, 0x33, 0x5a, 0x78, 0x52, 0x32, 0x4a, 0x6f, + 0x57, 0x48, 0x67, 0x55, 0x77, 0x5a, 0x37, 0x6c, 0x5a, 0x6b, 0x31, 0x56, + 0x6e, 0x68, 0x66, 0x66, 0x46, 0x79, 0x65, 0x37, 0x53, 0x42, 0x58, 0x79, + 0x61, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, + 0x44, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, + 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/ssl_test_data.h b/test/core/end2end/data/ssl_test_data.h index e9c7dbceb2..303f3a6eda 100644 --- a/test/core/end2end/data/ssl_test_data.h +++ b/test/core/end2end/data/ssl_test_data.h @@ -19,10 +19,6 @@ #ifndef GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H #define GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H -#ifdef __cplusplus -extern "C" { -#endif - extern const char test_root_cert[]; extern const char test_server1_cert[]; extern const char test_server1_key[]; @@ -31,8 +27,4 @@ extern const char test_self_signed_client_key[]; extern const char test_signed_client_cert[]; extern const char test_signed_client_key[]; -#ifdef __cplusplus -} -#endif - #endif /* GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H */ diff --git a/test/core/end2end/data/test_root_cert.c b/test/core/end2end/data/test_root_cert.c deleted file mode 100644 index ef39ca56ab..0000000000 --- a/test/core/end2end/data/test_root_cert.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const char test_root_cert[] = { - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, - 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x49, 0x7a, 0x43, 0x43, - 0x41, 0x59, 0x77, 0x43, 0x43, 0x51, 0x43, 0x46, 0x54, 0x62, 0x46, 0x37, - 0x58, 0x4e, 0x53, 0x76, 0x76, 0x6a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, - 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, - 0x41, 0x44, 0x42, 0x57, 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, - 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x42, 0x0a, 0x56, 0x54, 0x45, - 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, - 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, - 0x30, 0x5a, 0x54, 0x45, 0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, - 0x45, 0x43, 0x67, 0x77, 0x59, 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, - 0x75, 0x5a, 0x58, 0x51, 0x67, 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, - 0x30, 0x0a, 0x63, 0x79, 0x42, 0x51, 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, - 0x52, 0x6b, 0x4d, 0x51, 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, - 0x51, 0x44, 0x44, 0x41, 0x5a, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x59, 0x32, - 0x45, 0x77, 0x48, 0x68, 0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, - 0x45, 0x33, 0x4d, 0x6a, 0x4d, 0x78, 0x4e, 0x7a, 0x55, 0x78, 0x57, 0x68, - 0x63, 0x4e, 0x4d, 0x6a, 0x51, 0x77, 0x0a, 0x4e, 0x7a, 0x45, 0x30, 0x4d, - 0x6a, 0x4d, 0x78, 0x4e, 0x7a, 0x55, 0x78, 0x57, 0x6a, 0x42, 0x57, 0x4d, - 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, - 0x77, 0x4a, 0x42, 0x56, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, - 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, - 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, 0x68, 0x0a, - 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x59, - 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, 0x67, - 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, 0x30, 0x63, 0x79, 0x42, 0x51, - 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x51, 0x38, 0x77, - 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x5a, 0x30, - 0x5a, 0x58, 0x4e, 0x30, 0x0a, 0x59, 0x32, 0x45, 0x77, 0x67, 0x5a, 0x38, - 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, - 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x59, 0x30, - 0x41, 0x4d, 0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4d, 0x42, - 0x41, 0x33, 0x77, 0x56, 0x65, 0x54, 0x47, 0x48, 0x5a, 0x52, 0x31, 0x52, - 0x79, 0x65, 0x2f, 0x69, 0x2b, 0x4a, 0x38, 0x61, 0x32, 0x0a, 0x63, 0x75, - 0x35, 0x67, 0x58, 0x77, 0x46, 0x56, 0x36, 0x54, 0x6e, 0x4f, 0x62, 0x7a, - 0x47, 0x4d, 0x37, 0x62, 0x4c, 0x46, 0x43, 0x4f, 0x35, 0x69, 0x39, 0x76, - 0x34, 0x6d, 0x4c, 0x6f, 0x34, 0x69, 0x46, 0x7a, 0x50, 0x73, 0x48, 0x6d, - 0x57, 0x44, 0x55, 0x78, 0x4b, 0x53, 0x33, 0x59, 0x38, 0x69, 0x58, 0x62, - 0x75, 0x30, 0x65, 0x59, 0x42, 0x6c, 0x4c, 0x6f, 0x4e, 0x59, 0x30, 0x6c, - 0x53, 0x76, 0x0a, 0x78, 0x44, 0x78, 0x33, 0x33, 0x4f, 0x2b, 0x44, 0x75, - 0x77, 0x4d, 0x6d, 0x56, 0x4e, 0x2b, 0x44, 0x7a, 0x53, 0x44, 0x2b, 0x45, - 0x6f, 0x64, 0x39, 0x7a, 0x66, 0x76, 0x77, 0x4f, 0x57, 0x48, 0x73, 0x61, - 0x7a, 0x59, 0x43, 0x5a, 0x54, 0x32, 0x50, 0x68, 0x4e, 0x78, 0x6e, 0x56, - 0x57, 0x49, 0x75, 0x4a, 0x58, 0x56, 0x69, 0x59, 0x34, 0x4a, 0x41, 0x48, - 0x55, 0x47, 0x6f, 0x64, 0x6a, 0x78, 0x2b, 0x0a, 0x51, 0x41, 0x69, 0x36, - 0x79, 0x43, 0x41, 0x75, 0x72, 0x55, 0x5a, 0x47, 0x76, 0x59, 0x58, 0x47, - 0x67, 0x5a, 0x53, 0x42, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x77, - 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, - 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x59, 0x45, 0x41, - 0x51, 0x6f, 0x51, 0x56, 0x44, 0x38, 0x62, 0x77, 0x64, 0x74, 0x57, 0x4a, - 0x0a, 0x41, 0x6e, 0x69, 0x47, 0x42, 0x77, 0x63, 0x43, 0x66, 0x71, 0x59, - 0x79, 0x48, 0x2b, 0x2f, 0x4b, 0x70, 0x41, 0x31, 0x30, 0x41, 0x63, 0x65, - 0x62, 0x4a, 0x56, 0x56, 0x54, 0x79, 0x59, 0x62, 0x59, 0x76, 0x49, 0x39, - 0x51, 0x38, 0x64, 0x36, 0x52, 0x53, 0x56, 0x75, 0x34, 0x50, 0x5a, 0x79, - 0x39, 0x4f, 0x41, 0x4c, 0x48, 0x52, 0x2f, 0x51, 0x72, 0x57, 0x42, 0x64, - 0x59, 0x54, 0x41, 0x79, 0x7a, 0x0a, 0x66, 0x4e, 0x41, 0x6d, 0x63, 0x32, - 0x63, 0x6d, 0x64, 0x6b, 0x53, 0x52, 0x4a, 0x7a, 0x6a, 0x68, 0x49, 0x61, - 0x4f, 0x73, 0x74, 0x6e, 0x51, 0x79, 0x31, 0x4a, 0x2b, 0x46, 0x6b, 0x30, - 0x54, 0x39, 0x58, 0x79, 0x76, 0x51, 0x74, 0x71, 0x34, 0x39, 0x39, 0x79, - 0x46, 0x62, 0x71, 0x39, 0x78, 0x6f, 0x67, 0x55, 0x56, 0x6c, 0x45, 0x47, - 0x48, 0x36, 0x32, 0x78, 0x50, 0x36, 0x76, 0x48, 0x30, 0x59, 0x0a, 0x35, - 0x75, 0x6b, 0x4b, 0x2f, 0x2f, 0x64, 0x43, 0x50, 0x41, 0x7a, 0x41, 0x31, - 0x31, 0x59, 0x75, 0x58, 0x32, 0x72, 0x6e, 0x65, 0x78, 0x30, 0x4a, 0x68, - 0x75, 0x54, 0x51, 0x66, 0x63, 0x49, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, - 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/data/test_root_cert.cc b/test/core/end2end/data/test_root_cert.cc new file mode 100644 index 0000000000..81ca410e14 --- /dev/null +++ b/test/core/end2end/data/test_root_cert.cc @@ -0,0 +1,88 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/data/ssl_test_data.h" + +const char test_root_cert[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x49, 0x7a, 0x43, 0x43, + 0x41, 0x59, 0x77, 0x43, 0x43, 0x51, 0x43, 0x46, 0x54, 0x62, 0x46, 0x37, + 0x58, 0x4e, 0x53, 0x76, 0x76, 0x6a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, + 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, + 0x41, 0x44, 0x42, 0x57, 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, + 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x42, 0x0a, 0x56, 0x54, 0x45, + 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, + 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, + 0x30, 0x5a, 0x54, 0x45, 0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, + 0x45, 0x43, 0x67, 0x77, 0x59, 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, + 0x75, 0x5a, 0x58, 0x51, 0x67, 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, + 0x30, 0x0a, 0x63, 0x79, 0x42, 0x51, 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, + 0x52, 0x6b, 0x4d, 0x51, 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, + 0x51, 0x44, 0x44, 0x41, 0x5a, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x59, 0x32, + 0x45, 0x77, 0x48, 0x68, 0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, + 0x45, 0x33, 0x4d, 0x6a, 0x4d, 0x78, 0x4e, 0x7a, 0x55, 0x78, 0x57, 0x68, + 0x63, 0x4e, 0x4d, 0x6a, 0x51, 0x77, 0x0a, 0x4e, 0x7a, 0x45, 0x30, 0x4d, + 0x6a, 0x4d, 0x78, 0x4e, 0x7a, 0x55, 0x78, 0x57, 0x6a, 0x42, 0x57, 0x4d, + 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, + 0x77, 0x4a, 0x42, 0x56, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45, 0x47, 0x41, + 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39, 0x74, 0x5a, + 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45, 0x68, 0x0a, + 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x59, + 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51, 0x67, + 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, 0x30, 0x63, 0x79, 0x42, 0x51, + 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x51, 0x38, 0x77, + 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x5a, 0x30, + 0x5a, 0x58, 0x4e, 0x30, 0x0a, 0x59, 0x32, 0x45, 0x77, 0x67, 0x5a, 0x38, + 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, + 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x59, 0x30, + 0x41, 0x4d, 0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4d, 0x42, + 0x41, 0x33, 0x77, 0x56, 0x65, 0x54, 0x47, 0x48, 0x5a, 0x52, 0x31, 0x52, + 0x79, 0x65, 0x2f, 0x69, 0x2b, 0x4a, 0x38, 0x61, 0x32, 0x0a, 0x63, 0x75, + 0x35, 0x67, 0x58, 0x77, 0x46, 0x56, 0x36, 0x54, 0x6e, 0x4f, 0x62, 0x7a, + 0x47, 0x4d, 0x37, 0x62, 0x4c, 0x46, 0x43, 0x4f, 0x35, 0x69, 0x39, 0x76, + 0x34, 0x6d, 0x4c, 0x6f, 0x34, 0x69, 0x46, 0x7a, 0x50, 0x73, 0x48, 0x6d, + 0x57, 0x44, 0x55, 0x78, 0x4b, 0x53, 0x33, 0x59, 0x38, 0x69, 0x58, 0x62, + 0x75, 0x30, 0x65, 0x59, 0x42, 0x6c, 0x4c, 0x6f, 0x4e, 0x59, 0x30, 0x6c, + 0x53, 0x76, 0x0a, 0x78, 0x44, 0x78, 0x33, 0x33, 0x4f, 0x2b, 0x44, 0x75, + 0x77, 0x4d, 0x6d, 0x56, 0x4e, 0x2b, 0x44, 0x7a, 0x53, 0x44, 0x2b, 0x45, + 0x6f, 0x64, 0x39, 0x7a, 0x66, 0x76, 0x77, 0x4f, 0x57, 0x48, 0x73, 0x61, + 0x7a, 0x59, 0x43, 0x5a, 0x54, 0x32, 0x50, 0x68, 0x4e, 0x78, 0x6e, 0x56, + 0x57, 0x49, 0x75, 0x4a, 0x58, 0x56, 0x69, 0x59, 0x34, 0x4a, 0x41, 0x48, + 0x55, 0x47, 0x6f, 0x64, 0x6a, 0x78, 0x2b, 0x0a, 0x51, 0x41, 0x69, 0x36, + 0x79, 0x43, 0x41, 0x75, 0x72, 0x55, 0x5a, 0x47, 0x76, 0x59, 0x58, 0x47, + 0x67, 0x5a, 0x53, 0x42, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x77, + 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, + 0x41, 0x51, 0x45, 0x46, 0x42, 0x51, 0x41, 0x44, 0x67, 0x59, 0x45, 0x41, + 0x51, 0x6f, 0x51, 0x56, 0x44, 0x38, 0x62, 0x77, 0x64, 0x74, 0x57, 0x4a, + 0x0a, 0x41, 0x6e, 0x69, 0x47, 0x42, 0x77, 0x63, 0x43, 0x66, 0x71, 0x59, + 0x79, 0x48, 0x2b, 0x2f, 0x4b, 0x70, 0x41, 0x31, 0x30, 0x41, 0x63, 0x65, + 0x62, 0x4a, 0x56, 0x56, 0x54, 0x79, 0x59, 0x62, 0x59, 0x76, 0x49, 0x39, + 0x51, 0x38, 0x64, 0x36, 0x52, 0x53, 0x56, 0x75, 0x34, 0x50, 0x5a, 0x79, + 0x39, 0x4f, 0x41, 0x4c, 0x48, 0x52, 0x2f, 0x51, 0x72, 0x57, 0x42, 0x64, + 0x59, 0x54, 0x41, 0x79, 0x7a, 0x0a, 0x66, 0x4e, 0x41, 0x6d, 0x63, 0x32, + 0x63, 0x6d, 0x64, 0x6b, 0x53, 0x52, 0x4a, 0x7a, 0x6a, 0x68, 0x49, 0x61, + 0x4f, 0x73, 0x74, 0x6e, 0x51, 0x79, 0x31, 0x4a, 0x2b, 0x46, 0x6b, 0x30, + 0x54, 0x39, 0x58, 0x79, 0x76, 0x51, 0x74, 0x71, 0x34, 0x39, 0x39, 0x79, + 0x46, 0x62, 0x71, 0x39, 0x78, 0x6f, 0x67, 0x55, 0x56, 0x6c, 0x45, 0x47, + 0x48, 0x36, 0x32, 0x78, 0x50, 0x36, 0x76, 0x48, 0x30, 0x59, 0x0a, 0x35, + 0x75, 0x6b, 0x4b, 0x2f, 0x2f, 0x64, 0x43, 0x50, 0x41, 0x7a, 0x41, 0x31, + 0x31, 0x59, 0x75, 0x58, 0x32, 0x72, 0x6e, 0x65, 0x78, 0x30, 0x4a, 0x68, + 0x75, 0x54, 0x51, 0x66, 0x63, 0x49, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, + 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00}; diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c deleted file mode 100644 index f9150f145a..0000000000 --- a/test/core/end2end/dualstack_socket_test.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -/* This test exercises IPv4, IPv6, and dualstack sockets in various ways. */ - -static void *tag(intptr_t i) { return (void *)i; } - -static gpr_timespec ms_from_now(int ms) { - return grpc_timeout_milliseconds_to_deadline(ms); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, ms_from_now(5000), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void do_nothing(void *ignored) {} - -void test_connect(const char *server_host, const char *client_host, int port, - int expect_ok) { - char *client_hostport; - char *server_hostport; - grpc_channel *client; - grpc_server *server; - grpc_completion_queue *cq; - grpc_completion_queue *shutdown_cq; - grpc_call *c; - grpc_call *s; - cq_verifier *cqv; - gpr_timespec deadline; - int got_port; - 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_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_call_details call_details; - char *peer; - int picked_port = 0; - - if (port == 0) { - port = grpc_pick_unused_port_or_die(); - picked_port = 1; - } - - gpr_join_host_port(&server_hostport, server_host, port); - - 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); - - /* Create server. */ - cq = grpc_completion_queue_create_for_next(NULL); - server = grpc_server_create(NULL, NULL); - grpc_server_register_completion_queue(server, cq, NULL); - GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port( - server, server_hostport)) > 0); - if (port == 0) { - port = got_port; - } else { - GPR_ASSERT(port == got_port); - } - grpc_server_start(server); - cqv = cq_verifier_create(cq); - - /* Create client. */ - if (client_host[0] == 'i') { - /* for ipv4:/ipv6: addresses, concatenate the port to each of the parts */ - size_t i; - grpc_slice uri_slice; - grpc_slice_buffer uri_parts; - char **hosts_with_port; - - uri_slice = - grpc_slice_new((char *)client_host, strlen(client_host), do_nothing); - grpc_slice_buffer_init(&uri_parts); - grpc_slice_split(uri_slice, ",", &uri_parts); - hosts_with_port = gpr_malloc(sizeof(char *) * uri_parts.count); - for (i = 0; i < uri_parts.count; i++) { - char *uri_part_str = grpc_slice_to_c_string(uri_parts.slices[i]); - gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port); - gpr_free(uri_part_str); - } - client_hostport = gpr_strjoin_sep((const char **)hosts_with_port, - uri_parts.count, ",", NULL); - for (i = 0; i < uri_parts.count; i++) { - gpr_free(hosts_with_port[i]); - } - gpr_free(hosts_with_port); - grpc_slice_buffer_destroy(&uri_parts); - grpc_slice_unref(uri_slice); - } else { - gpr_join_host_port(&client_hostport, client_host, port); - } - client = grpc_insecure_channel_create(client_hostport, NULL, NULL); - - gpr_log(GPR_INFO, "Testing with server=%s client=%s (expecting %s)", - server_hostport, client_hostport, expect_ok ? "success" : "failure"); - - gpr_free(client_hostport); - gpr_free(server_hostport); - - if (expect_ok) { - /* Normal deadline, shouldn't be reached. */ - deadline = ms_from_now(60000); - } else { - /* Give up faster when failure is expected. - BUG: Setting this to 1000 reveals a memory leak (b/18608927). */ - deadline = ms_from_now(1500); - } - - /* Send a trivial request. */ - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); - c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/foo"), &host, - deadline, NULL); - GPR_ASSERT(c); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = expect_ok ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 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.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->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); - - if (expect_ok) { - /* Check for a successful request. */ - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - 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); - - peer = grpc_call_get_peer(c); - gpr_log(GPR_DEBUG, "got peer: '%s'", peer); - gpr_free(peer); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(0 == - grpc_slice_str_cmp(call_details.host, "foo.test.google.fr")); - GPR_ASSERT(was_cancelled == 1); - - grpc_call_unref(s); - } else { - /* Check for a failed connection. */ - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - } - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - - /* Destroy client. */ - grpc_channel_destroy(client); - - /* Destroy server. */ - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), - NULL) - .type == GRPC_OP_COMPLETE); - grpc_server_destroy(server); - grpc_completion_queue_destroy(shutdown_cq); - grpc_completion_queue_shutdown(cq); - drain_cq(cq); - grpc_completion_queue_destroy(cq); - - 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_slice_unref(details); - if (picked_port) { - grpc_recycle_unused_port(port); - } -} - -int external_dns_works(const char *host) { - grpc_resolved_addresses *res = NULL; - grpc_error *error = grpc_blocking_resolve_address(host, "80", &res); - GRPC_ERROR_UNREF(error); - if (res != NULL) { - grpc_resolved_addresses_destroy(res); - return 1; - } - return 0; -} - -int main(int argc, char **argv) { - int do_ipv6 = 1; - - grpc_test_init(argc, argv); - grpc_init(); - - if (!grpc_ipv6_loopback_available()) { - gpr_log(GPR_INFO, "Can't bind to ::1. Skipping IPv6 tests."); - do_ipv6 = 0; - } - - /* For coverage, test with and without dualstack sockets. */ - for (grpc_forbid_dualstack_sockets_for_testing = 0; - grpc_forbid_dualstack_sockets_for_testing <= 1; - grpc_forbid_dualstack_sockets_for_testing++) { - /* :: and 0.0.0.0 are handled identically. */ - test_connect("::", "127.0.0.1", 0, 1); - test_connect("::", "::ffff:127.0.0.1", 0, 1); - test_connect("::", "ipv4:127.0.0.1", 0, 1); - test_connect("::", "ipv6:[::ffff:127.0.0.1]", 0, 1); - test_connect("::", "localhost", 0, 1); - test_connect("0.0.0.0", "127.0.0.1", 0, 1); - test_connect("0.0.0.0", "::ffff:127.0.0.1", 0, 1); - test_connect("0.0.0.0", "ipv4:127.0.0.1", 0, 1); - test_connect("0.0.0.0", "ipv4:127.0.0.1,127.0.0.2,127.0.0.3", 0, 1); - test_connect("0.0.0.0", "ipv6:[::ffff:127.0.0.1],[::ffff:127.0.0.2]", 0, 1); - test_connect("0.0.0.0", "localhost", 0, 1); - if (do_ipv6) { - test_connect("::", "::1", 0, 1); - test_connect("0.0.0.0", "::1", 0, 1); - test_connect("::", "ipv6:[::1]", 0, 1); - test_connect("0.0.0.0", "ipv6:[::1]", 0, 1); - } - - /* These only work when the families agree. */ - test_connect("127.0.0.1", "127.0.0.1", 0, 1); - test_connect("127.0.0.1", "ipv4:127.0.0.1", 0, 1); - if (do_ipv6) { - test_connect("::1", "::1", 0, 1); - test_connect("::1", "127.0.0.1", 0, 0); - test_connect("127.0.0.1", "::1", 0, 0); - test_connect("::1", "ipv6:[::1]", 0, 1); - test_connect("::1", "ipv4:127.0.0.1", 0, 0); - test_connect("127.0.0.1", "ipv6:[::1]", 0, 0); - } - - if (!external_dns_works("loopback46.unittest.grpc.io")) { - gpr_log(GPR_INFO, "Skipping tests that depend on *.unittest.grpc.io."); - } else { - test_connect("loopback46.unittest.grpc.io", "loopback4.unittest.grpc.io", - 0, 1); - test_connect("loopback4.unittest.grpc.io", "loopback46.unittest.grpc.io", - 0, 1); - if (do_ipv6) { - test_connect("loopback46.unittest.grpc.io", - "loopback6.unittest.grpc.io", 0, 1); - test_connect("loopback6.unittest.grpc.io", - "loopback46.unittest.grpc.io", 0, 1); - test_connect("loopback4.unittest.grpc.io", "loopback6.unittest.grpc.io", - 0, 0); - test_connect("loopback6.unittest.grpc.io", "loopback4.unittest.grpc.io", - 0, 0); - } - } - } - - grpc_shutdown(); - - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/end2end/dualstack_socket_test.cc b/test/core/end2end/dualstack_socket_test.cc new file mode 100644 index 0000000000..bfb2e227ac --- /dev/null +++ b/test/core/end2end/dualstack_socket_test.cc @@ -0,0 +1,358 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +/* This test exercises IPv4, IPv6, and dualstack sockets in various ways. */ + +static void *tag(intptr_t i) { return (void *)i; } + +static gpr_timespec ms_from_now(int ms) { + return grpc_timeout_milliseconds_to_deadline(ms); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, ms_from_now(5000), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void do_nothing(void *ignored) {} + +void test_connect(const char *server_host, const char *client_host, int port, + int expect_ok) { + char *client_hostport; + char *server_hostport; + grpc_channel *client; + grpc_server *server; + grpc_completion_queue *cq; + grpc_completion_queue *shutdown_cq; + grpc_call *c; + grpc_call *s; + cq_verifier *cqv; + gpr_timespec deadline; + int got_port; + 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_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + grpc_call_details call_details; + char *peer; + int picked_port = 0; + + if (port == 0) { + port = grpc_pick_unused_port_or_die(); + picked_port = 1; + } + + gpr_join_host_port(&server_hostport, server_host, port); + + 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); + + /* Create server. */ + cq = grpc_completion_queue_create_for_next(NULL); + server = grpc_server_create(NULL, NULL); + grpc_server_register_completion_queue(server, cq, NULL); + GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port( + server, server_hostport)) > 0); + if (port == 0) { + port = got_port; + } else { + GPR_ASSERT(port == got_port); + } + grpc_server_start(server); + cqv = cq_verifier_create(cq); + + /* Create client. */ + if (client_host[0] == 'i') { + /* for ipv4:/ipv6: addresses, concatenate the port to each of the parts */ + size_t i; + grpc_slice uri_slice; + grpc_slice_buffer uri_parts; + char **hosts_with_port; + + uri_slice = + grpc_slice_new((char *)client_host, strlen(client_host), do_nothing); + grpc_slice_buffer_init(&uri_parts); + grpc_slice_split(uri_slice, ",", &uri_parts); + hosts_with_port = + static_cast(gpr_malloc(sizeof(char *) * uri_parts.count)); + for (i = 0; i < uri_parts.count; i++) { + char *uri_part_str = grpc_slice_to_c_string(uri_parts.slices[i]); + gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port); + gpr_free(uri_part_str); + } + client_hostport = gpr_strjoin_sep((const char **)hosts_with_port, + uri_parts.count, ",", NULL); + for (i = 0; i < uri_parts.count; i++) { + gpr_free(hosts_with_port[i]); + } + gpr_free(hosts_with_port); + grpc_slice_buffer_destroy(&uri_parts); + grpc_slice_unref(uri_slice); + } else { + gpr_join_host_port(&client_hostport, client_host, port); + } + client = grpc_insecure_channel_create(client_hostport, NULL, NULL); + + gpr_log(GPR_INFO, "Testing with server=%s client=%s (expecting %s)", + server_hostport, client_hostport, expect_ok ? "success" : "failure"); + + gpr_free(client_hostport); + gpr_free(server_hostport); + + if (expect_ok) { + /* Normal deadline, shouldn't be reached. */ + deadline = ms_from_now(60000); + } else { + /* Give up faster when failure is expected. + BUG: Setting this to 1000 reveals a memory leak (b/18608927). */ + deadline = ms_from_now(1500); + } + + /* Send a trivial request. */ + grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); + c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/foo"), &host, + deadline, NULL); + GPR_ASSERT(c); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = expect_ok ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 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.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->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); + + if (expect_ok) { + /* Check for a successful request. */ + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + 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); + + peer = grpc_call_get_peer(c); + gpr_log(GPR_DEBUG, "got peer: '%s'", peer); + gpr_free(peer); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + GPR_ASSERT(0 == + grpc_slice_str_cmp(call_details.host, "foo.test.google.fr")); + GPR_ASSERT(was_cancelled == 1); + + grpc_call_unref(s); + } else { + /* Check for a failed connection. */ + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + /* Destroy client. */ + grpc_channel_destroy(client); + + /* Destroy server. */ + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(server); + grpc_completion_queue_destroy(shutdown_cq); + grpc_completion_queue_shutdown(cq); + drain_cq(cq); + grpc_completion_queue_destroy(cq); + + 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_slice_unref(details); + if (picked_port) { + grpc_recycle_unused_port(port); + } +} + +int external_dns_works(const char *host) { + grpc_resolved_addresses *res = NULL; + grpc_error *error = grpc_blocking_resolve_address(host, "80", &res); + GRPC_ERROR_UNREF(error); + if (res != NULL) { + grpc_resolved_addresses_destroy(res); + return 1; + } + return 0; +} + +int main(int argc, char **argv) { + int do_ipv6 = 1; + + grpc_test_init(argc, argv); + grpc_init(); + + if (!grpc_ipv6_loopback_available()) { + gpr_log(GPR_INFO, "Can't bind to ::1. Skipping IPv6 tests."); + do_ipv6 = 0; + } + + /* For coverage, test with and without dualstack sockets. */ + for (grpc_forbid_dualstack_sockets_for_testing = 0; + grpc_forbid_dualstack_sockets_for_testing <= 1; + grpc_forbid_dualstack_sockets_for_testing++) { + /* :: and 0.0.0.0 are handled identically. */ + test_connect("::", "127.0.0.1", 0, 1); + test_connect("::", "::ffff:127.0.0.1", 0, 1); + test_connect("::", "ipv4:127.0.0.1", 0, 1); + test_connect("::", "ipv6:[::ffff:127.0.0.1]", 0, 1); + test_connect("::", "localhost", 0, 1); + test_connect("0.0.0.0", "127.0.0.1", 0, 1); + test_connect("0.0.0.0", "::ffff:127.0.0.1", 0, 1); + test_connect("0.0.0.0", "ipv4:127.0.0.1", 0, 1); + test_connect("0.0.0.0", "ipv4:127.0.0.1,127.0.0.2,127.0.0.3", 0, 1); + test_connect("0.0.0.0", "ipv6:[::ffff:127.0.0.1],[::ffff:127.0.0.2]", 0, 1); + test_connect("0.0.0.0", "localhost", 0, 1); + if (do_ipv6) { + test_connect("::", "::1", 0, 1); + test_connect("0.0.0.0", "::1", 0, 1); + test_connect("::", "ipv6:[::1]", 0, 1); + test_connect("0.0.0.0", "ipv6:[::1]", 0, 1); + } + + /* These only work when the families agree. */ + test_connect("127.0.0.1", "127.0.0.1", 0, 1); + test_connect("127.0.0.1", "ipv4:127.0.0.1", 0, 1); + if (do_ipv6) { + test_connect("::1", "::1", 0, 1); + test_connect("::1", "127.0.0.1", 0, 0); + test_connect("127.0.0.1", "::1", 0, 0); + test_connect("::1", "ipv6:[::1]", 0, 1); + test_connect("::1", "ipv4:127.0.0.1", 0, 0); + test_connect("127.0.0.1", "ipv6:[::1]", 0, 0); + } + + if (!external_dns_works("loopback46.unittest.grpc.io")) { + gpr_log(GPR_INFO, "Skipping tests that depend on *.unittest.grpc.io."); + } else { + test_connect("loopback46.unittest.grpc.io", "loopback4.unittest.grpc.io", + 0, 1); + test_connect("loopback4.unittest.grpc.io", "loopback46.unittest.grpc.io", + 0, 1); + if (do_ipv6) { + test_connect("loopback46.unittest.grpc.io", + "loopback6.unittest.grpc.io", 0, 1); + test_connect("loopback6.unittest.grpc.io", + "loopback46.unittest.grpc.io", 0, 1); + test_connect("loopback4.unittest.grpc.io", "loopback6.unittest.grpc.io", + 0, 0); + test_connect("loopback6.unittest.grpc.io", "loopback4.unittest.grpc.io", + 0, 0); + } + } + } + + grpc_shutdown(); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c deleted file mode 100644 index 3236feea56..0000000000 --- a/test/core/end2end/end2end_nosec_tests.c +++ /dev/null @@ -1,518 +0,0 @@ - -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* This file is auto-generated */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include - -#include "test/core/util/debugger_macros.h" - -static bool g_pre_init_called = false; - -extern void authority_not_supported(grpc_end2end_test_config config); -extern void authority_not_supported_pre_init(void); -extern void bad_hostname(grpc_end2end_test_config config); -extern void bad_hostname_pre_init(void); -extern void bad_ping(grpc_end2end_test_config config); -extern void bad_ping_pre_init(void); -extern void binary_metadata(grpc_end2end_test_config config); -extern void binary_metadata_pre_init(void); -extern void cancel_after_accept(grpc_end2end_test_config config); -extern void cancel_after_accept_pre_init(void); -extern void cancel_after_client_done(grpc_end2end_test_config config); -extern void cancel_after_client_done_pre_init(void); -extern void cancel_after_invoke(grpc_end2end_test_config config); -extern void cancel_after_invoke_pre_init(void); -extern void cancel_after_round_trip(grpc_end2end_test_config config); -extern void cancel_after_round_trip_pre_init(void); -extern void cancel_before_invoke(grpc_end2end_test_config config); -extern void cancel_before_invoke_pre_init(void); -extern void cancel_in_a_vacuum(grpc_end2end_test_config config); -extern void cancel_in_a_vacuum_pre_init(void); -extern void cancel_with_status(grpc_end2end_test_config config); -extern void cancel_with_status_pre_init(void); -extern void compressed_payload(grpc_end2end_test_config config); -extern void compressed_payload_pre_init(void); -extern void connectivity(grpc_end2end_test_config config); -extern void connectivity_pre_init(void); -extern void default_host(grpc_end2end_test_config config); -extern void default_host_pre_init(void); -extern void disappearing_server(grpc_end2end_test_config config); -extern void disappearing_server_pre_init(void); -extern void empty_batch(grpc_end2end_test_config config); -extern void empty_batch_pre_init(void); -extern void filter_call_init_fails(grpc_end2end_test_config config); -extern void filter_call_init_fails_pre_init(void); -extern void filter_causes_close(grpc_end2end_test_config config); -extern void filter_causes_close_pre_init(void); -extern void filter_latency(grpc_end2end_test_config config); -extern void filter_latency_pre_init(void); -extern void graceful_server_shutdown(grpc_end2end_test_config config); -extern void graceful_server_shutdown_pre_init(void); -extern void high_initial_seqno(grpc_end2end_test_config config); -extern void high_initial_seqno_pre_init(void); -extern void hpack_size(grpc_end2end_test_config config); -extern void hpack_size_pre_init(void); -extern void idempotent_request(grpc_end2end_test_config config); -extern void idempotent_request_pre_init(void); -extern void invoke_large_request(grpc_end2end_test_config config); -extern void invoke_large_request_pre_init(void); -extern void keepalive_timeout(grpc_end2end_test_config config); -extern void keepalive_timeout_pre_init(void); -extern void large_metadata(grpc_end2end_test_config config); -extern void large_metadata_pre_init(void); -extern void load_reporting_hook(grpc_end2end_test_config config); -extern void load_reporting_hook_pre_init(void); -extern void max_concurrent_streams(grpc_end2end_test_config config); -extern void max_concurrent_streams_pre_init(void); -extern void max_connection_age(grpc_end2end_test_config config); -extern void max_connection_age_pre_init(void); -extern void max_connection_idle(grpc_end2end_test_config config); -extern void max_connection_idle_pre_init(void); -extern void max_message_length(grpc_end2end_test_config config); -extern void max_message_length_pre_init(void); -extern void negative_deadline(grpc_end2end_test_config config); -extern void negative_deadline_pre_init(void); -extern void network_status_change(grpc_end2end_test_config config); -extern void network_status_change_pre_init(void); -extern void no_logging(grpc_end2end_test_config config); -extern void no_logging_pre_init(void); -extern void no_op(grpc_end2end_test_config config); -extern void no_op_pre_init(void); -extern void payload(grpc_end2end_test_config config); -extern void payload_pre_init(void); -extern void ping(grpc_end2end_test_config config); -extern void ping_pre_init(void); -extern void ping_pong_streaming(grpc_end2end_test_config config); -extern void ping_pong_streaming_pre_init(void); -extern void proxy_auth(grpc_end2end_test_config config); -extern void proxy_auth_pre_init(void); -extern void registered_call(grpc_end2end_test_config config); -extern void registered_call_pre_init(void); -extern void request_with_flags(grpc_end2end_test_config config); -extern void request_with_flags_pre_init(void); -extern void request_with_payload(grpc_end2end_test_config config); -extern void request_with_payload_pre_init(void); -extern void resource_quota_server(grpc_end2end_test_config config); -extern void resource_quota_server_pre_init(void); -extern void server_finishes_request(grpc_end2end_test_config config); -extern void server_finishes_request_pre_init(void); -extern void shutdown_finishes_calls(grpc_end2end_test_config config); -extern void shutdown_finishes_calls_pre_init(void); -extern void shutdown_finishes_tags(grpc_end2end_test_config config); -extern void shutdown_finishes_tags_pre_init(void); -extern void simple_cacheable_request(grpc_end2end_test_config config); -extern void simple_cacheable_request_pre_init(void); -extern void simple_delayed_request(grpc_end2end_test_config config); -extern void simple_delayed_request_pre_init(void); -extern void simple_metadata(grpc_end2end_test_config config); -extern void simple_metadata_pre_init(void); -extern void simple_request(grpc_end2end_test_config config); -extern void simple_request_pre_init(void); -extern void stream_compression_compressed_payload(grpc_end2end_test_config config); -extern void stream_compression_compressed_payload_pre_init(void); -extern void stream_compression_payload(grpc_end2end_test_config config); -extern void stream_compression_payload_pre_init(void); -extern void stream_compression_ping_pong_streaming(grpc_end2end_test_config config); -extern void stream_compression_ping_pong_streaming_pre_init(void); -extern void streaming_error_response(grpc_end2end_test_config config); -extern void streaming_error_response_pre_init(void); -extern void trailing_metadata(grpc_end2end_test_config config); -extern void trailing_metadata_pre_init(void); -extern void workaround_cronet_compression(grpc_end2end_test_config config); -extern void workaround_cronet_compression_pre_init(void); -extern void write_buffering(grpc_end2end_test_config config); -extern void write_buffering_pre_init(void); -extern void write_buffering_at_end(grpc_end2end_test_config config); -extern void write_buffering_at_end_pre_init(void); - -void grpc_end2end_tests_pre_init(void) { - GPR_ASSERT(!g_pre_init_called); - g_pre_init_called = true; - grpc_summon_debugger_macros(); - authority_not_supported_pre_init(); - bad_hostname_pre_init(); - bad_ping_pre_init(); - binary_metadata_pre_init(); - cancel_after_accept_pre_init(); - cancel_after_client_done_pre_init(); - cancel_after_invoke_pre_init(); - cancel_after_round_trip_pre_init(); - cancel_before_invoke_pre_init(); - cancel_in_a_vacuum_pre_init(); - cancel_with_status_pre_init(); - compressed_payload_pre_init(); - connectivity_pre_init(); - default_host_pre_init(); - disappearing_server_pre_init(); - empty_batch_pre_init(); - filter_call_init_fails_pre_init(); - filter_causes_close_pre_init(); - filter_latency_pre_init(); - graceful_server_shutdown_pre_init(); - high_initial_seqno_pre_init(); - hpack_size_pre_init(); - idempotent_request_pre_init(); - invoke_large_request_pre_init(); - keepalive_timeout_pre_init(); - large_metadata_pre_init(); - load_reporting_hook_pre_init(); - max_concurrent_streams_pre_init(); - max_connection_age_pre_init(); - max_connection_idle_pre_init(); - max_message_length_pre_init(); - negative_deadline_pre_init(); - network_status_change_pre_init(); - no_logging_pre_init(); - no_op_pre_init(); - payload_pre_init(); - ping_pre_init(); - ping_pong_streaming_pre_init(); - proxy_auth_pre_init(); - registered_call_pre_init(); - request_with_flags_pre_init(); - request_with_payload_pre_init(); - resource_quota_server_pre_init(); - server_finishes_request_pre_init(); - shutdown_finishes_calls_pre_init(); - shutdown_finishes_tags_pre_init(); - simple_cacheable_request_pre_init(); - simple_delayed_request_pre_init(); - simple_metadata_pre_init(); - simple_request_pre_init(); - stream_compression_compressed_payload_pre_init(); - stream_compression_payload_pre_init(); - stream_compression_ping_pong_streaming_pre_init(); - streaming_error_response_pre_init(); - trailing_metadata_pre_init(); - workaround_cronet_compression_pre_init(); - write_buffering_pre_init(); - write_buffering_at_end_pre_init(); -} - -void grpc_end2end_tests(int argc, char **argv, - grpc_end2end_test_config config) { - int i; - - GPR_ASSERT(g_pre_init_called); - - if (argc <= 1) { - authority_not_supported(config); - bad_hostname(config); - bad_ping(config); - binary_metadata(config); - cancel_after_accept(config); - cancel_after_client_done(config); - cancel_after_invoke(config); - cancel_after_round_trip(config); - cancel_before_invoke(config); - cancel_in_a_vacuum(config); - cancel_with_status(config); - compressed_payload(config); - connectivity(config); - default_host(config); - disappearing_server(config); - empty_batch(config); - filter_call_init_fails(config); - filter_causes_close(config); - filter_latency(config); - graceful_server_shutdown(config); - high_initial_seqno(config); - hpack_size(config); - idempotent_request(config); - invoke_large_request(config); - keepalive_timeout(config); - large_metadata(config); - load_reporting_hook(config); - max_concurrent_streams(config); - max_connection_age(config); - max_connection_idle(config); - max_message_length(config); - negative_deadline(config); - network_status_change(config); - no_logging(config); - no_op(config); - payload(config); - ping(config); - ping_pong_streaming(config); - proxy_auth(config); - registered_call(config); - request_with_flags(config); - request_with_payload(config); - resource_quota_server(config); - server_finishes_request(config); - shutdown_finishes_calls(config); - shutdown_finishes_tags(config); - simple_cacheable_request(config); - simple_delayed_request(config); - simple_metadata(config); - simple_request(config); - stream_compression_compressed_payload(config); - stream_compression_payload(config); - stream_compression_ping_pong_streaming(config); - streaming_error_response(config); - trailing_metadata(config); - workaround_cronet_compression(config); - write_buffering(config); - write_buffering_at_end(config); - return; - } - - for (i = 1; i < argc; i++) { - if (0 == strcmp("authority_not_supported", argv[i])) { - authority_not_supported(config); - continue; - } - if (0 == strcmp("bad_hostname", argv[i])) { - bad_hostname(config); - continue; - } - if (0 == strcmp("bad_ping", argv[i])) { - bad_ping(config); - continue; - } - if (0 == strcmp("binary_metadata", argv[i])) { - binary_metadata(config); - continue; - } - if (0 == strcmp("cancel_after_accept", argv[i])) { - cancel_after_accept(config); - continue; - } - if (0 == strcmp("cancel_after_client_done", argv[i])) { - cancel_after_client_done(config); - continue; - } - if (0 == strcmp("cancel_after_invoke", argv[i])) { - cancel_after_invoke(config); - continue; - } - if (0 == strcmp("cancel_after_round_trip", argv[i])) { - cancel_after_round_trip(config); - continue; - } - if (0 == strcmp("cancel_before_invoke", argv[i])) { - cancel_before_invoke(config); - continue; - } - if (0 == strcmp("cancel_in_a_vacuum", argv[i])) { - cancel_in_a_vacuum(config); - continue; - } - if (0 == strcmp("cancel_with_status", argv[i])) { - cancel_with_status(config); - continue; - } - if (0 == strcmp("compressed_payload", argv[i])) { - compressed_payload(config); - continue; - } - if (0 == strcmp("connectivity", argv[i])) { - connectivity(config); - continue; - } - if (0 == strcmp("default_host", argv[i])) { - default_host(config); - continue; - } - if (0 == strcmp("disappearing_server", argv[i])) { - disappearing_server(config); - continue; - } - if (0 == strcmp("empty_batch", argv[i])) { - empty_batch(config); - continue; - } - if (0 == strcmp("filter_call_init_fails", argv[i])) { - filter_call_init_fails(config); - continue; - } - if (0 == strcmp("filter_causes_close", argv[i])) { - filter_causes_close(config); - continue; - } - if (0 == strcmp("filter_latency", argv[i])) { - filter_latency(config); - continue; - } - if (0 == strcmp("graceful_server_shutdown", argv[i])) { - graceful_server_shutdown(config); - continue; - } - if (0 == strcmp("high_initial_seqno", argv[i])) { - high_initial_seqno(config); - continue; - } - if (0 == strcmp("hpack_size", argv[i])) { - hpack_size(config); - continue; - } - if (0 == strcmp("idempotent_request", argv[i])) { - idempotent_request(config); - continue; - } - if (0 == strcmp("invoke_large_request", argv[i])) { - invoke_large_request(config); - continue; - } - if (0 == strcmp("keepalive_timeout", argv[i])) { - keepalive_timeout(config); - continue; - } - if (0 == strcmp("large_metadata", argv[i])) { - large_metadata(config); - continue; - } - if (0 == strcmp("load_reporting_hook", argv[i])) { - load_reporting_hook(config); - continue; - } - if (0 == strcmp("max_concurrent_streams", argv[i])) { - max_concurrent_streams(config); - continue; - } - if (0 == strcmp("max_connection_age", argv[i])) { - max_connection_age(config); - continue; - } - if (0 == strcmp("max_connection_idle", argv[i])) { - max_connection_idle(config); - continue; - } - if (0 == strcmp("max_message_length", argv[i])) { - max_message_length(config); - continue; - } - if (0 == strcmp("negative_deadline", argv[i])) { - negative_deadline(config); - continue; - } - if (0 == strcmp("network_status_change", argv[i])) { - network_status_change(config); - continue; - } - if (0 == strcmp("no_logging", argv[i])) { - no_logging(config); - continue; - } - if (0 == strcmp("no_op", argv[i])) { - no_op(config); - continue; - } - if (0 == strcmp("payload", argv[i])) { - payload(config); - continue; - } - if (0 == strcmp("ping", argv[i])) { - ping(config); - continue; - } - if (0 == strcmp("ping_pong_streaming", argv[i])) { - ping_pong_streaming(config); - continue; - } - if (0 == strcmp("proxy_auth", argv[i])) { - proxy_auth(config); - continue; - } - if (0 == strcmp("registered_call", argv[i])) { - registered_call(config); - continue; - } - if (0 == strcmp("request_with_flags", argv[i])) { - request_with_flags(config); - continue; - } - if (0 == strcmp("request_with_payload", argv[i])) { - request_with_payload(config); - continue; - } - if (0 == strcmp("resource_quota_server", argv[i])) { - resource_quota_server(config); - continue; - } - if (0 == strcmp("server_finishes_request", argv[i])) { - server_finishes_request(config); - continue; - } - if (0 == strcmp("shutdown_finishes_calls", argv[i])) { - shutdown_finishes_calls(config); - continue; - } - if (0 == strcmp("shutdown_finishes_tags", argv[i])) { - shutdown_finishes_tags(config); - continue; - } - if (0 == strcmp("simple_cacheable_request", argv[i])) { - simple_cacheable_request(config); - continue; - } - if (0 == strcmp("simple_delayed_request", argv[i])) { - simple_delayed_request(config); - continue; - } - if (0 == strcmp("simple_metadata", argv[i])) { - simple_metadata(config); - continue; - } - if (0 == strcmp("simple_request", argv[i])) { - simple_request(config); - continue; - } - if (0 == strcmp("stream_compression_compressed_payload", argv[i])) { - stream_compression_compressed_payload(config); - continue; - } - if (0 == strcmp("stream_compression_payload", argv[i])) { - stream_compression_payload(config); - continue; - } - if (0 == strcmp("stream_compression_ping_pong_streaming", argv[i])) { - stream_compression_ping_pong_streaming(config); - continue; - } - if (0 == strcmp("streaming_error_response", argv[i])) { - streaming_error_response(config); - continue; - } - if (0 == strcmp("trailing_metadata", argv[i])) { - trailing_metadata(config); - continue; - } - if (0 == strcmp("workaround_cronet_compression", argv[i])) { - workaround_cronet_compression(config); - continue; - } - if (0 == strcmp("write_buffering", argv[i])) { - write_buffering(config); - continue; - } - if (0 == strcmp("write_buffering_at_end", argv[i])) { - write_buffering_at_end(config); - continue; - } - gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); - abort(); - } -} diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc new file mode 100644 index 0000000000..3236feea56 --- /dev/null +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -0,0 +1,518 @@ + +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This file is auto-generated */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include + +#include "test/core/util/debugger_macros.h" + +static bool g_pre_init_called = false; + +extern void authority_not_supported(grpc_end2end_test_config config); +extern void authority_not_supported_pre_init(void); +extern void bad_hostname(grpc_end2end_test_config config); +extern void bad_hostname_pre_init(void); +extern void bad_ping(grpc_end2end_test_config config); +extern void bad_ping_pre_init(void); +extern void binary_metadata(grpc_end2end_test_config config); +extern void binary_metadata_pre_init(void); +extern void cancel_after_accept(grpc_end2end_test_config config); +extern void cancel_after_accept_pre_init(void); +extern void cancel_after_client_done(grpc_end2end_test_config config); +extern void cancel_after_client_done_pre_init(void); +extern void cancel_after_invoke(grpc_end2end_test_config config); +extern void cancel_after_invoke_pre_init(void); +extern void cancel_after_round_trip(grpc_end2end_test_config config); +extern void cancel_after_round_trip_pre_init(void); +extern void cancel_before_invoke(grpc_end2end_test_config config); +extern void cancel_before_invoke_pre_init(void); +extern void cancel_in_a_vacuum(grpc_end2end_test_config config); +extern void cancel_in_a_vacuum_pre_init(void); +extern void cancel_with_status(grpc_end2end_test_config config); +extern void cancel_with_status_pre_init(void); +extern void compressed_payload(grpc_end2end_test_config config); +extern void compressed_payload_pre_init(void); +extern void connectivity(grpc_end2end_test_config config); +extern void connectivity_pre_init(void); +extern void default_host(grpc_end2end_test_config config); +extern void default_host_pre_init(void); +extern void disappearing_server(grpc_end2end_test_config config); +extern void disappearing_server_pre_init(void); +extern void empty_batch(grpc_end2end_test_config config); +extern void empty_batch_pre_init(void); +extern void filter_call_init_fails(grpc_end2end_test_config config); +extern void filter_call_init_fails_pre_init(void); +extern void filter_causes_close(grpc_end2end_test_config config); +extern void filter_causes_close_pre_init(void); +extern void filter_latency(grpc_end2end_test_config config); +extern void filter_latency_pre_init(void); +extern void graceful_server_shutdown(grpc_end2end_test_config config); +extern void graceful_server_shutdown_pre_init(void); +extern void high_initial_seqno(grpc_end2end_test_config config); +extern void high_initial_seqno_pre_init(void); +extern void hpack_size(grpc_end2end_test_config config); +extern void hpack_size_pre_init(void); +extern void idempotent_request(grpc_end2end_test_config config); +extern void idempotent_request_pre_init(void); +extern void invoke_large_request(grpc_end2end_test_config config); +extern void invoke_large_request_pre_init(void); +extern void keepalive_timeout(grpc_end2end_test_config config); +extern void keepalive_timeout_pre_init(void); +extern void large_metadata(grpc_end2end_test_config config); +extern void large_metadata_pre_init(void); +extern void load_reporting_hook(grpc_end2end_test_config config); +extern void load_reporting_hook_pre_init(void); +extern void max_concurrent_streams(grpc_end2end_test_config config); +extern void max_concurrent_streams_pre_init(void); +extern void max_connection_age(grpc_end2end_test_config config); +extern void max_connection_age_pre_init(void); +extern void max_connection_idle(grpc_end2end_test_config config); +extern void max_connection_idle_pre_init(void); +extern void max_message_length(grpc_end2end_test_config config); +extern void max_message_length_pre_init(void); +extern void negative_deadline(grpc_end2end_test_config config); +extern void negative_deadline_pre_init(void); +extern void network_status_change(grpc_end2end_test_config config); +extern void network_status_change_pre_init(void); +extern void no_logging(grpc_end2end_test_config config); +extern void no_logging_pre_init(void); +extern void no_op(grpc_end2end_test_config config); +extern void no_op_pre_init(void); +extern void payload(grpc_end2end_test_config config); +extern void payload_pre_init(void); +extern void ping(grpc_end2end_test_config config); +extern void ping_pre_init(void); +extern void ping_pong_streaming(grpc_end2end_test_config config); +extern void ping_pong_streaming_pre_init(void); +extern void proxy_auth(grpc_end2end_test_config config); +extern void proxy_auth_pre_init(void); +extern void registered_call(grpc_end2end_test_config config); +extern void registered_call_pre_init(void); +extern void request_with_flags(grpc_end2end_test_config config); +extern void request_with_flags_pre_init(void); +extern void request_with_payload(grpc_end2end_test_config config); +extern void request_with_payload_pre_init(void); +extern void resource_quota_server(grpc_end2end_test_config config); +extern void resource_quota_server_pre_init(void); +extern void server_finishes_request(grpc_end2end_test_config config); +extern void server_finishes_request_pre_init(void); +extern void shutdown_finishes_calls(grpc_end2end_test_config config); +extern void shutdown_finishes_calls_pre_init(void); +extern void shutdown_finishes_tags(grpc_end2end_test_config config); +extern void shutdown_finishes_tags_pre_init(void); +extern void simple_cacheable_request(grpc_end2end_test_config config); +extern void simple_cacheable_request_pre_init(void); +extern void simple_delayed_request(grpc_end2end_test_config config); +extern void simple_delayed_request_pre_init(void); +extern void simple_metadata(grpc_end2end_test_config config); +extern void simple_metadata_pre_init(void); +extern void simple_request(grpc_end2end_test_config config); +extern void simple_request_pre_init(void); +extern void stream_compression_compressed_payload(grpc_end2end_test_config config); +extern void stream_compression_compressed_payload_pre_init(void); +extern void stream_compression_payload(grpc_end2end_test_config config); +extern void stream_compression_payload_pre_init(void); +extern void stream_compression_ping_pong_streaming(grpc_end2end_test_config config); +extern void stream_compression_ping_pong_streaming_pre_init(void); +extern void streaming_error_response(grpc_end2end_test_config config); +extern void streaming_error_response_pre_init(void); +extern void trailing_metadata(grpc_end2end_test_config config); +extern void trailing_metadata_pre_init(void); +extern void workaround_cronet_compression(grpc_end2end_test_config config); +extern void workaround_cronet_compression_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); + +void grpc_end2end_tests_pre_init(void) { + GPR_ASSERT(!g_pre_init_called); + g_pre_init_called = true; + grpc_summon_debugger_macros(); + authority_not_supported_pre_init(); + bad_hostname_pre_init(); + bad_ping_pre_init(); + binary_metadata_pre_init(); + cancel_after_accept_pre_init(); + cancel_after_client_done_pre_init(); + cancel_after_invoke_pre_init(); + cancel_after_round_trip_pre_init(); + cancel_before_invoke_pre_init(); + cancel_in_a_vacuum_pre_init(); + cancel_with_status_pre_init(); + compressed_payload_pre_init(); + connectivity_pre_init(); + default_host_pre_init(); + disappearing_server_pre_init(); + empty_batch_pre_init(); + filter_call_init_fails_pre_init(); + filter_causes_close_pre_init(); + filter_latency_pre_init(); + graceful_server_shutdown_pre_init(); + high_initial_seqno_pre_init(); + hpack_size_pre_init(); + idempotent_request_pre_init(); + invoke_large_request_pre_init(); + keepalive_timeout_pre_init(); + large_metadata_pre_init(); + load_reporting_hook_pre_init(); + max_concurrent_streams_pre_init(); + max_connection_age_pre_init(); + max_connection_idle_pre_init(); + max_message_length_pre_init(); + negative_deadline_pre_init(); + network_status_change_pre_init(); + no_logging_pre_init(); + no_op_pre_init(); + payload_pre_init(); + ping_pre_init(); + ping_pong_streaming_pre_init(); + proxy_auth_pre_init(); + registered_call_pre_init(); + request_with_flags_pre_init(); + request_with_payload_pre_init(); + resource_quota_server_pre_init(); + server_finishes_request_pre_init(); + shutdown_finishes_calls_pre_init(); + shutdown_finishes_tags_pre_init(); + simple_cacheable_request_pre_init(); + simple_delayed_request_pre_init(); + simple_metadata_pre_init(); + simple_request_pre_init(); + stream_compression_compressed_payload_pre_init(); + stream_compression_payload_pre_init(); + stream_compression_ping_pong_streaming_pre_init(); + streaming_error_response_pre_init(); + trailing_metadata_pre_init(); + workaround_cronet_compression_pre_init(); + write_buffering_pre_init(); + write_buffering_at_end_pre_init(); +} + +void grpc_end2end_tests(int argc, char **argv, + grpc_end2end_test_config config) { + int i; + + GPR_ASSERT(g_pre_init_called); + + if (argc <= 1) { + authority_not_supported(config); + bad_hostname(config); + bad_ping(config); + binary_metadata(config); + cancel_after_accept(config); + cancel_after_client_done(config); + cancel_after_invoke(config); + cancel_after_round_trip(config); + cancel_before_invoke(config); + cancel_in_a_vacuum(config); + cancel_with_status(config); + compressed_payload(config); + connectivity(config); + default_host(config); + disappearing_server(config); + empty_batch(config); + filter_call_init_fails(config); + filter_causes_close(config); + filter_latency(config); + graceful_server_shutdown(config); + high_initial_seqno(config); + hpack_size(config); + idempotent_request(config); + invoke_large_request(config); + keepalive_timeout(config); + large_metadata(config); + load_reporting_hook(config); + max_concurrent_streams(config); + max_connection_age(config); + max_connection_idle(config); + max_message_length(config); + negative_deadline(config); + network_status_change(config); + no_logging(config); + no_op(config); + payload(config); + ping(config); + ping_pong_streaming(config); + proxy_auth(config); + registered_call(config); + request_with_flags(config); + request_with_payload(config); + resource_quota_server(config); + server_finishes_request(config); + shutdown_finishes_calls(config); + shutdown_finishes_tags(config); + simple_cacheable_request(config); + simple_delayed_request(config); + simple_metadata(config); + simple_request(config); + stream_compression_compressed_payload(config); + stream_compression_payload(config); + stream_compression_ping_pong_streaming(config); + streaming_error_response(config); + trailing_metadata(config); + workaround_cronet_compression(config); + write_buffering(config); + write_buffering_at_end(config); + return; + } + + for (i = 1; i < argc; i++) { + if (0 == strcmp("authority_not_supported", argv[i])) { + authority_not_supported(config); + continue; + } + if (0 == strcmp("bad_hostname", argv[i])) { + bad_hostname(config); + continue; + } + if (0 == strcmp("bad_ping", argv[i])) { + bad_ping(config); + continue; + } + if (0 == strcmp("binary_metadata", argv[i])) { + binary_metadata(config); + continue; + } + if (0 == strcmp("cancel_after_accept", argv[i])) { + cancel_after_accept(config); + continue; + } + if (0 == strcmp("cancel_after_client_done", argv[i])) { + cancel_after_client_done(config); + continue; + } + if (0 == strcmp("cancel_after_invoke", argv[i])) { + cancel_after_invoke(config); + continue; + } + if (0 == strcmp("cancel_after_round_trip", argv[i])) { + cancel_after_round_trip(config); + continue; + } + if (0 == strcmp("cancel_before_invoke", argv[i])) { + cancel_before_invoke(config); + continue; + } + if (0 == strcmp("cancel_in_a_vacuum", argv[i])) { + cancel_in_a_vacuum(config); + continue; + } + if (0 == strcmp("cancel_with_status", argv[i])) { + cancel_with_status(config); + continue; + } + if (0 == strcmp("compressed_payload", argv[i])) { + compressed_payload(config); + continue; + } + if (0 == strcmp("connectivity", argv[i])) { + connectivity(config); + continue; + } + if (0 == strcmp("default_host", argv[i])) { + default_host(config); + continue; + } + if (0 == strcmp("disappearing_server", argv[i])) { + disappearing_server(config); + continue; + } + if (0 == strcmp("empty_batch", argv[i])) { + empty_batch(config); + continue; + } + if (0 == strcmp("filter_call_init_fails", argv[i])) { + filter_call_init_fails(config); + continue; + } + if (0 == strcmp("filter_causes_close", argv[i])) { + filter_causes_close(config); + continue; + } + if (0 == strcmp("filter_latency", argv[i])) { + filter_latency(config); + continue; + } + if (0 == strcmp("graceful_server_shutdown", argv[i])) { + graceful_server_shutdown(config); + continue; + } + if (0 == strcmp("high_initial_seqno", argv[i])) { + high_initial_seqno(config); + continue; + } + if (0 == strcmp("hpack_size", argv[i])) { + hpack_size(config); + continue; + } + if (0 == strcmp("idempotent_request", argv[i])) { + idempotent_request(config); + continue; + } + if (0 == strcmp("invoke_large_request", argv[i])) { + invoke_large_request(config); + continue; + } + if (0 == strcmp("keepalive_timeout", argv[i])) { + keepalive_timeout(config); + continue; + } + if (0 == strcmp("large_metadata", argv[i])) { + large_metadata(config); + continue; + } + if (0 == strcmp("load_reporting_hook", argv[i])) { + load_reporting_hook(config); + continue; + } + if (0 == strcmp("max_concurrent_streams", argv[i])) { + max_concurrent_streams(config); + continue; + } + if (0 == strcmp("max_connection_age", argv[i])) { + max_connection_age(config); + continue; + } + if (0 == strcmp("max_connection_idle", argv[i])) { + max_connection_idle(config); + continue; + } + if (0 == strcmp("max_message_length", argv[i])) { + max_message_length(config); + continue; + } + if (0 == strcmp("negative_deadline", argv[i])) { + negative_deadline(config); + continue; + } + if (0 == strcmp("network_status_change", argv[i])) { + network_status_change(config); + continue; + } + if (0 == strcmp("no_logging", argv[i])) { + no_logging(config); + continue; + } + if (0 == strcmp("no_op", argv[i])) { + no_op(config); + continue; + } + if (0 == strcmp("payload", argv[i])) { + payload(config); + continue; + } + if (0 == strcmp("ping", argv[i])) { + ping(config); + continue; + } + if (0 == strcmp("ping_pong_streaming", argv[i])) { + ping_pong_streaming(config); + continue; + } + if (0 == strcmp("proxy_auth", argv[i])) { + proxy_auth(config); + continue; + } + if (0 == strcmp("registered_call", argv[i])) { + registered_call(config); + continue; + } + if (0 == strcmp("request_with_flags", argv[i])) { + request_with_flags(config); + continue; + } + if (0 == strcmp("request_with_payload", argv[i])) { + request_with_payload(config); + continue; + } + if (0 == strcmp("resource_quota_server", argv[i])) { + resource_quota_server(config); + continue; + } + if (0 == strcmp("server_finishes_request", argv[i])) { + server_finishes_request(config); + continue; + } + if (0 == strcmp("shutdown_finishes_calls", argv[i])) { + shutdown_finishes_calls(config); + continue; + } + if (0 == strcmp("shutdown_finishes_tags", argv[i])) { + shutdown_finishes_tags(config); + continue; + } + if (0 == strcmp("simple_cacheable_request", argv[i])) { + simple_cacheable_request(config); + continue; + } + if (0 == strcmp("simple_delayed_request", argv[i])) { + simple_delayed_request(config); + continue; + } + if (0 == strcmp("simple_metadata", argv[i])) { + simple_metadata(config); + continue; + } + if (0 == strcmp("simple_request", argv[i])) { + simple_request(config); + continue; + } + if (0 == strcmp("stream_compression_compressed_payload", argv[i])) { + stream_compression_compressed_payload(config); + continue; + } + if (0 == strcmp("stream_compression_payload", argv[i])) { + stream_compression_payload(config); + continue; + } + if (0 == strcmp("stream_compression_ping_pong_streaming", argv[i])) { + stream_compression_ping_pong_streaming(config); + continue; + } + if (0 == strcmp("streaming_error_response", argv[i])) { + streaming_error_response(config); + continue; + } + if (0 == strcmp("trailing_metadata", argv[i])) { + trailing_metadata(config); + continue; + } + if (0 == strcmp("workaround_cronet_compression", argv[i])) { + workaround_cronet_compression(config); + continue; + } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } + gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); + abort(); + } +} diff --git a/test/core/end2end/end2end_test_utils.c b/test/core/end2end/end2end_test_utils.c deleted file mode 100644 index c1f119548a..0000000000 --- a/test/core/end2end/end2end_test_utils.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include - -const char *get_host_override_string(const char *str, - grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - return str; - } else { - return NULL; - } -} - -const grpc_slice *get_host_override_slice(const char *str, - grpc_end2end_test_config config) { - const char *r = get_host_override_string(str, config); - if (r != NULL) { - static grpc_slice ret; - ret = grpc_slice_from_static_string(r); - return &ret; - } - return NULL; -} - -void validate_host_override_string(const char *pattern, grpc_slice str, - grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern)); - } -} diff --git a/test/core/end2end/end2end_test_utils.cc b/test/core/end2end/end2end_test_utils.cc new file mode 100644 index 0000000000..c1f119548a --- /dev/null +++ b/test/core/end2end/end2end_test_utils.cc @@ -0,0 +1,50 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include + +const char *get_host_override_string(const char *str, + grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { + return str; + } else { + return NULL; + } +} + +const grpc_slice *get_host_override_slice(const char *str, + grpc_end2end_test_config config) { + const char *r = get_host_override_string(str, config); + if (r != NULL) { + static grpc_slice ret; + ret = grpc_slice_from_static_string(r); + return &ret; + } + return NULL; +} + +void validate_host_override_string(const char *pattern, grpc_slice str, + grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { + GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern)); + } +} diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c deleted file mode 100644 index ca9443b642..0000000000 --- a/test/core/end2end/end2end_tests.c +++ /dev/null @@ -1,526 +0,0 @@ - -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* This file is auto-generated */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include - -#include "test/core/util/debugger_macros.h" - -static bool g_pre_init_called = false; - -extern void authority_not_supported(grpc_end2end_test_config config); -extern void authority_not_supported_pre_init(void); -extern void bad_hostname(grpc_end2end_test_config config); -extern void bad_hostname_pre_init(void); -extern void bad_ping(grpc_end2end_test_config config); -extern void bad_ping_pre_init(void); -extern void binary_metadata(grpc_end2end_test_config config); -extern void binary_metadata_pre_init(void); -extern void call_creds(grpc_end2end_test_config config); -extern void call_creds_pre_init(void); -extern void cancel_after_accept(grpc_end2end_test_config config); -extern void cancel_after_accept_pre_init(void); -extern void cancel_after_client_done(grpc_end2end_test_config config); -extern void cancel_after_client_done_pre_init(void); -extern void cancel_after_invoke(grpc_end2end_test_config config); -extern void cancel_after_invoke_pre_init(void); -extern void cancel_after_round_trip(grpc_end2end_test_config config); -extern void cancel_after_round_trip_pre_init(void); -extern void cancel_before_invoke(grpc_end2end_test_config config); -extern void cancel_before_invoke_pre_init(void); -extern void cancel_in_a_vacuum(grpc_end2end_test_config config); -extern void cancel_in_a_vacuum_pre_init(void); -extern void cancel_with_status(grpc_end2end_test_config config); -extern void cancel_with_status_pre_init(void); -extern void compressed_payload(grpc_end2end_test_config config); -extern void compressed_payload_pre_init(void); -extern void connectivity(grpc_end2end_test_config config); -extern void connectivity_pre_init(void); -extern void default_host(grpc_end2end_test_config config); -extern void default_host_pre_init(void); -extern void disappearing_server(grpc_end2end_test_config config); -extern void disappearing_server_pre_init(void); -extern void empty_batch(grpc_end2end_test_config config); -extern void empty_batch_pre_init(void); -extern void filter_call_init_fails(grpc_end2end_test_config config); -extern void filter_call_init_fails_pre_init(void); -extern void filter_causes_close(grpc_end2end_test_config config); -extern void filter_causes_close_pre_init(void); -extern void filter_latency(grpc_end2end_test_config config); -extern void filter_latency_pre_init(void); -extern void graceful_server_shutdown(grpc_end2end_test_config config); -extern void graceful_server_shutdown_pre_init(void); -extern void high_initial_seqno(grpc_end2end_test_config config); -extern void high_initial_seqno_pre_init(void); -extern void hpack_size(grpc_end2end_test_config config); -extern void hpack_size_pre_init(void); -extern void idempotent_request(grpc_end2end_test_config config); -extern void idempotent_request_pre_init(void); -extern void invoke_large_request(grpc_end2end_test_config config); -extern void invoke_large_request_pre_init(void); -extern void keepalive_timeout(grpc_end2end_test_config config); -extern void keepalive_timeout_pre_init(void); -extern void large_metadata(grpc_end2end_test_config config); -extern void large_metadata_pre_init(void); -extern void load_reporting_hook(grpc_end2end_test_config config); -extern void load_reporting_hook_pre_init(void); -extern void max_concurrent_streams(grpc_end2end_test_config config); -extern void max_concurrent_streams_pre_init(void); -extern void max_connection_age(grpc_end2end_test_config config); -extern void max_connection_age_pre_init(void); -extern void max_connection_idle(grpc_end2end_test_config config); -extern void max_connection_idle_pre_init(void); -extern void max_message_length(grpc_end2end_test_config config); -extern void max_message_length_pre_init(void); -extern void negative_deadline(grpc_end2end_test_config config); -extern void negative_deadline_pre_init(void); -extern void network_status_change(grpc_end2end_test_config config); -extern void network_status_change_pre_init(void); -extern void no_logging(grpc_end2end_test_config config); -extern void no_logging_pre_init(void); -extern void no_op(grpc_end2end_test_config config); -extern void no_op_pre_init(void); -extern void payload(grpc_end2end_test_config config); -extern void payload_pre_init(void); -extern void ping(grpc_end2end_test_config config); -extern void ping_pre_init(void); -extern void ping_pong_streaming(grpc_end2end_test_config config); -extern void ping_pong_streaming_pre_init(void); -extern void proxy_auth(grpc_end2end_test_config config); -extern void proxy_auth_pre_init(void); -extern void registered_call(grpc_end2end_test_config config); -extern void registered_call_pre_init(void); -extern void request_with_flags(grpc_end2end_test_config config); -extern void request_with_flags_pre_init(void); -extern void request_with_payload(grpc_end2end_test_config config); -extern void request_with_payload_pre_init(void); -extern void resource_quota_server(grpc_end2end_test_config config); -extern void resource_quota_server_pre_init(void); -extern void server_finishes_request(grpc_end2end_test_config config); -extern void server_finishes_request_pre_init(void); -extern void shutdown_finishes_calls(grpc_end2end_test_config config); -extern void shutdown_finishes_calls_pre_init(void); -extern void shutdown_finishes_tags(grpc_end2end_test_config config); -extern void shutdown_finishes_tags_pre_init(void); -extern void simple_cacheable_request(grpc_end2end_test_config config); -extern void simple_cacheable_request_pre_init(void); -extern void simple_delayed_request(grpc_end2end_test_config config); -extern void simple_delayed_request_pre_init(void); -extern void simple_metadata(grpc_end2end_test_config config); -extern void simple_metadata_pre_init(void); -extern void simple_request(grpc_end2end_test_config config); -extern void simple_request_pre_init(void); -extern void stream_compression_compressed_payload(grpc_end2end_test_config config); -extern void stream_compression_compressed_payload_pre_init(void); -extern void stream_compression_payload(grpc_end2end_test_config config); -extern void stream_compression_payload_pre_init(void); -extern void stream_compression_ping_pong_streaming(grpc_end2end_test_config config); -extern void stream_compression_ping_pong_streaming_pre_init(void); -extern void streaming_error_response(grpc_end2end_test_config config); -extern void streaming_error_response_pre_init(void); -extern void trailing_metadata(grpc_end2end_test_config config); -extern void trailing_metadata_pre_init(void); -extern void workaround_cronet_compression(grpc_end2end_test_config config); -extern void workaround_cronet_compression_pre_init(void); -extern void write_buffering(grpc_end2end_test_config config); -extern void write_buffering_pre_init(void); -extern void write_buffering_at_end(grpc_end2end_test_config config); -extern void write_buffering_at_end_pre_init(void); - -void grpc_end2end_tests_pre_init(void) { - GPR_ASSERT(!g_pre_init_called); - g_pre_init_called = true; - grpc_summon_debugger_macros(); - authority_not_supported_pre_init(); - bad_hostname_pre_init(); - bad_ping_pre_init(); - binary_metadata_pre_init(); - call_creds_pre_init(); - cancel_after_accept_pre_init(); - cancel_after_client_done_pre_init(); - cancel_after_invoke_pre_init(); - cancel_after_round_trip_pre_init(); - cancel_before_invoke_pre_init(); - cancel_in_a_vacuum_pre_init(); - cancel_with_status_pre_init(); - compressed_payload_pre_init(); - connectivity_pre_init(); - default_host_pre_init(); - disappearing_server_pre_init(); - empty_batch_pre_init(); - filter_call_init_fails_pre_init(); - filter_causes_close_pre_init(); - filter_latency_pre_init(); - graceful_server_shutdown_pre_init(); - high_initial_seqno_pre_init(); - hpack_size_pre_init(); - idempotent_request_pre_init(); - invoke_large_request_pre_init(); - keepalive_timeout_pre_init(); - large_metadata_pre_init(); - load_reporting_hook_pre_init(); - max_concurrent_streams_pre_init(); - max_connection_age_pre_init(); - max_connection_idle_pre_init(); - max_message_length_pre_init(); - negative_deadline_pre_init(); - network_status_change_pre_init(); - no_logging_pre_init(); - no_op_pre_init(); - payload_pre_init(); - ping_pre_init(); - ping_pong_streaming_pre_init(); - proxy_auth_pre_init(); - registered_call_pre_init(); - request_with_flags_pre_init(); - request_with_payload_pre_init(); - resource_quota_server_pre_init(); - server_finishes_request_pre_init(); - shutdown_finishes_calls_pre_init(); - shutdown_finishes_tags_pre_init(); - simple_cacheable_request_pre_init(); - simple_delayed_request_pre_init(); - simple_metadata_pre_init(); - simple_request_pre_init(); - stream_compression_compressed_payload_pre_init(); - stream_compression_payload_pre_init(); - stream_compression_ping_pong_streaming_pre_init(); - streaming_error_response_pre_init(); - trailing_metadata_pre_init(); - workaround_cronet_compression_pre_init(); - write_buffering_pre_init(); - write_buffering_at_end_pre_init(); -} - -void grpc_end2end_tests(int argc, char **argv, - grpc_end2end_test_config config) { - int i; - - GPR_ASSERT(g_pre_init_called); - - if (argc <= 1) { - authority_not_supported(config); - bad_hostname(config); - bad_ping(config); - binary_metadata(config); - call_creds(config); - cancel_after_accept(config); - cancel_after_client_done(config); - cancel_after_invoke(config); - cancel_after_round_trip(config); - cancel_before_invoke(config); - cancel_in_a_vacuum(config); - cancel_with_status(config); - compressed_payload(config); - connectivity(config); - default_host(config); - disappearing_server(config); - empty_batch(config); - filter_call_init_fails(config); - filter_causes_close(config); - filter_latency(config); - graceful_server_shutdown(config); - high_initial_seqno(config); - hpack_size(config); - idempotent_request(config); - invoke_large_request(config); - keepalive_timeout(config); - large_metadata(config); - load_reporting_hook(config); - max_concurrent_streams(config); - max_connection_age(config); - max_connection_idle(config); - max_message_length(config); - negative_deadline(config); - network_status_change(config); - no_logging(config); - no_op(config); - payload(config); - ping(config); - ping_pong_streaming(config); - proxy_auth(config); - registered_call(config); - request_with_flags(config); - request_with_payload(config); - resource_quota_server(config); - server_finishes_request(config); - shutdown_finishes_calls(config); - shutdown_finishes_tags(config); - simple_cacheable_request(config); - simple_delayed_request(config); - simple_metadata(config); - simple_request(config); - stream_compression_compressed_payload(config); - stream_compression_payload(config); - stream_compression_ping_pong_streaming(config); - streaming_error_response(config); - trailing_metadata(config); - workaround_cronet_compression(config); - write_buffering(config); - write_buffering_at_end(config); - return; - } - - for (i = 1; i < argc; i++) { - if (0 == strcmp("authority_not_supported", argv[i])) { - authority_not_supported(config); - continue; - } - if (0 == strcmp("bad_hostname", argv[i])) { - bad_hostname(config); - continue; - } - if (0 == strcmp("bad_ping", argv[i])) { - bad_ping(config); - continue; - } - if (0 == strcmp("binary_metadata", argv[i])) { - binary_metadata(config); - continue; - } - if (0 == strcmp("call_creds", argv[i])) { - call_creds(config); - continue; - } - if (0 == strcmp("cancel_after_accept", argv[i])) { - cancel_after_accept(config); - continue; - } - if (0 == strcmp("cancel_after_client_done", argv[i])) { - cancel_after_client_done(config); - continue; - } - if (0 == strcmp("cancel_after_invoke", argv[i])) { - cancel_after_invoke(config); - continue; - } - if (0 == strcmp("cancel_after_round_trip", argv[i])) { - cancel_after_round_trip(config); - continue; - } - if (0 == strcmp("cancel_before_invoke", argv[i])) { - cancel_before_invoke(config); - continue; - } - if (0 == strcmp("cancel_in_a_vacuum", argv[i])) { - cancel_in_a_vacuum(config); - continue; - } - if (0 == strcmp("cancel_with_status", argv[i])) { - cancel_with_status(config); - continue; - } - if (0 == strcmp("compressed_payload", argv[i])) { - compressed_payload(config); - continue; - } - if (0 == strcmp("connectivity", argv[i])) { - connectivity(config); - continue; - } - if (0 == strcmp("default_host", argv[i])) { - default_host(config); - continue; - } - if (0 == strcmp("disappearing_server", argv[i])) { - disappearing_server(config); - continue; - } - if (0 == strcmp("empty_batch", argv[i])) { - empty_batch(config); - continue; - } - if (0 == strcmp("filter_call_init_fails", argv[i])) { - filter_call_init_fails(config); - continue; - } - if (0 == strcmp("filter_causes_close", argv[i])) { - filter_causes_close(config); - continue; - } - if (0 == strcmp("filter_latency", argv[i])) { - filter_latency(config); - continue; - } - if (0 == strcmp("graceful_server_shutdown", argv[i])) { - graceful_server_shutdown(config); - continue; - } - if (0 == strcmp("high_initial_seqno", argv[i])) { - high_initial_seqno(config); - continue; - } - if (0 == strcmp("hpack_size", argv[i])) { - hpack_size(config); - continue; - } - if (0 == strcmp("idempotent_request", argv[i])) { - idempotent_request(config); - continue; - } - if (0 == strcmp("invoke_large_request", argv[i])) { - invoke_large_request(config); - continue; - } - if (0 == strcmp("keepalive_timeout", argv[i])) { - keepalive_timeout(config); - continue; - } - if (0 == strcmp("large_metadata", argv[i])) { - large_metadata(config); - continue; - } - if (0 == strcmp("load_reporting_hook", argv[i])) { - load_reporting_hook(config); - continue; - } - if (0 == strcmp("max_concurrent_streams", argv[i])) { - max_concurrent_streams(config); - continue; - } - if (0 == strcmp("max_connection_age", argv[i])) { - max_connection_age(config); - continue; - } - if (0 == strcmp("max_connection_idle", argv[i])) { - max_connection_idle(config); - continue; - } - if (0 == strcmp("max_message_length", argv[i])) { - max_message_length(config); - continue; - } - if (0 == strcmp("negative_deadline", argv[i])) { - negative_deadline(config); - continue; - } - if (0 == strcmp("network_status_change", argv[i])) { - network_status_change(config); - continue; - } - if (0 == strcmp("no_logging", argv[i])) { - no_logging(config); - continue; - } - if (0 == strcmp("no_op", argv[i])) { - no_op(config); - continue; - } - if (0 == strcmp("payload", argv[i])) { - payload(config); - continue; - } - if (0 == strcmp("ping", argv[i])) { - ping(config); - continue; - } - if (0 == strcmp("ping_pong_streaming", argv[i])) { - ping_pong_streaming(config); - continue; - } - if (0 == strcmp("proxy_auth", argv[i])) { - proxy_auth(config); - continue; - } - if (0 == strcmp("registered_call", argv[i])) { - registered_call(config); - continue; - } - if (0 == strcmp("request_with_flags", argv[i])) { - request_with_flags(config); - continue; - } - if (0 == strcmp("request_with_payload", argv[i])) { - request_with_payload(config); - continue; - } - if (0 == strcmp("resource_quota_server", argv[i])) { - resource_quota_server(config); - continue; - } - if (0 == strcmp("server_finishes_request", argv[i])) { - server_finishes_request(config); - continue; - } - if (0 == strcmp("shutdown_finishes_calls", argv[i])) { - shutdown_finishes_calls(config); - continue; - } - if (0 == strcmp("shutdown_finishes_tags", argv[i])) { - shutdown_finishes_tags(config); - continue; - } - if (0 == strcmp("simple_cacheable_request", argv[i])) { - simple_cacheable_request(config); - continue; - } - if (0 == strcmp("simple_delayed_request", argv[i])) { - simple_delayed_request(config); - continue; - } - if (0 == strcmp("simple_metadata", argv[i])) { - simple_metadata(config); - continue; - } - if (0 == strcmp("simple_request", argv[i])) { - simple_request(config); - continue; - } - if (0 == strcmp("stream_compression_compressed_payload", argv[i])) { - stream_compression_compressed_payload(config); - continue; - } - if (0 == strcmp("stream_compression_payload", argv[i])) { - stream_compression_payload(config); - continue; - } - if (0 == strcmp("stream_compression_ping_pong_streaming", argv[i])) { - stream_compression_ping_pong_streaming(config); - continue; - } - if (0 == strcmp("streaming_error_response", argv[i])) { - streaming_error_response(config); - continue; - } - if (0 == strcmp("trailing_metadata", argv[i])) { - trailing_metadata(config); - continue; - } - if (0 == strcmp("workaround_cronet_compression", argv[i])) { - workaround_cronet_compression(config); - continue; - } - if (0 == strcmp("write_buffering", argv[i])) { - write_buffering(config); - continue; - } - if (0 == strcmp("write_buffering_at_end", argv[i])) { - write_buffering_at_end(config); - continue; - } - gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); - abort(); - } -} diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc new file mode 100644 index 0000000000..ca9443b642 --- /dev/null +++ b/test/core/end2end/end2end_tests.cc @@ -0,0 +1,526 @@ + +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This file is auto-generated */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include + +#include "test/core/util/debugger_macros.h" + +static bool g_pre_init_called = false; + +extern void authority_not_supported(grpc_end2end_test_config config); +extern void authority_not_supported_pre_init(void); +extern void bad_hostname(grpc_end2end_test_config config); +extern void bad_hostname_pre_init(void); +extern void bad_ping(grpc_end2end_test_config config); +extern void bad_ping_pre_init(void); +extern void binary_metadata(grpc_end2end_test_config config); +extern void binary_metadata_pre_init(void); +extern void call_creds(grpc_end2end_test_config config); +extern void call_creds_pre_init(void); +extern void cancel_after_accept(grpc_end2end_test_config config); +extern void cancel_after_accept_pre_init(void); +extern void cancel_after_client_done(grpc_end2end_test_config config); +extern void cancel_after_client_done_pre_init(void); +extern void cancel_after_invoke(grpc_end2end_test_config config); +extern void cancel_after_invoke_pre_init(void); +extern void cancel_after_round_trip(grpc_end2end_test_config config); +extern void cancel_after_round_trip_pre_init(void); +extern void cancel_before_invoke(grpc_end2end_test_config config); +extern void cancel_before_invoke_pre_init(void); +extern void cancel_in_a_vacuum(grpc_end2end_test_config config); +extern void cancel_in_a_vacuum_pre_init(void); +extern void cancel_with_status(grpc_end2end_test_config config); +extern void cancel_with_status_pre_init(void); +extern void compressed_payload(grpc_end2end_test_config config); +extern void compressed_payload_pre_init(void); +extern void connectivity(grpc_end2end_test_config config); +extern void connectivity_pre_init(void); +extern void default_host(grpc_end2end_test_config config); +extern void default_host_pre_init(void); +extern void disappearing_server(grpc_end2end_test_config config); +extern void disappearing_server_pre_init(void); +extern void empty_batch(grpc_end2end_test_config config); +extern void empty_batch_pre_init(void); +extern void filter_call_init_fails(grpc_end2end_test_config config); +extern void filter_call_init_fails_pre_init(void); +extern void filter_causes_close(grpc_end2end_test_config config); +extern void filter_causes_close_pre_init(void); +extern void filter_latency(grpc_end2end_test_config config); +extern void filter_latency_pre_init(void); +extern void graceful_server_shutdown(grpc_end2end_test_config config); +extern void graceful_server_shutdown_pre_init(void); +extern void high_initial_seqno(grpc_end2end_test_config config); +extern void high_initial_seqno_pre_init(void); +extern void hpack_size(grpc_end2end_test_config config); +extern void hpack_size_pre_init(void); +extern void idempotent_request(grpc_end2end_test_config config); +extern void idempotent_request_pre_init(void); +extern void invoke_large_request(grpc_end2end_test_config config); +extern void invoke_large_request_pre_init(void); +extern void keepalive_timeout(grpc_end2end_test_config config); +extern void keepalive_timeout_pre_init(void); +extern void large_metadata(grpc_end2end_test_config config); +extern void large_metadata_pre_init(void); +extern void load_reporting_hook(grpc_end2end_test_config config); +extern void load_reporting_hook_pre_init(void); +extern void max_concurrent_streams(grpc_end2end_test_config config); +extern void max_concurrent_streams_pre_init(void); +extern void max_connection_age(grpc_end2end_test_config config); +extern void max_connection_age_pre_init(void); +extern void max_connection_idle(grpc_end2end_test_config config); +extern void max_connection_idle_pre_init(void); +extern void max_message_length(grpc_end2end_test_config config); +extern void max_message_length_pre_init(void); +extern void negative_deadline(grpc_end2end_test_config config); +extern void negative_deadline_pre_init(void); +extern void network_status_change(grpc_end2end_test_config config); +extern void network_status_change_pre_init(void); +extern void no_logging(grpc_end2end_test_config config); +extern void no_logging_pre_init(void); +extern void no_op(grpc_end2end_test_config config); +extern void no_op_pre_init(void); +extern void payload(grpc_end2end_test_config config); +extern void payload_pre_init(void); +extern void ping(grpc_end2end_test_config config); +extern void ping_pre_init(void); +extern void ping_pong_streaming(grpc_end2end_test_config config); +extern void ping_pong_streaming_pre_init(void); +extern void proxy_auth(grpc_end2end_test_config config); +extern void proxy_auth_pre_init(void); +extern void registered_call(grpc_end2end_test_config config); +extern void registered_call_pre_init(void); +extern void request_with_flags(grpc_end2end_test_config config); +extern void request_with_flags_pre_init(void); +extern void request_with_payload(grpc_end2end_test_config config); +extern void request_with_payload_pre_init(void); +extern void resource_quota_server(grpc_end2end_test_config config); +extern void resource_quota_server_pre_init(void); +extern void server_finishes_request(grpc_end2end_test_config config); +extern void server_finishes_request_pre_init(void); +extern void shutdown_finishes_calls(grpc_end2end_test_config config); +extern void shutdown_finishes_calls_pre_init(void); +extern void shutdown_finishes_tags(grpc_end2end_test_config config); +extern void shutdown_finishes_tags_pre_init(void); +extern void simple_cacheable_request(grpc_end2end_test_config config); +extern void simple_cacheable_request_pre_init(void); +extern void simple_delayed_request(grpc_end2end_test_config config); +extern void simple_delayed_request_pre_init(void); +extern void simple_metadata(grpc_end2end_test_config config); +extern void simple_metadata_pre_init(void); +extern void simple_request(grpc_end2end_test_config config); +extern void simple_request_pre_init(void); +extern void stream_compression_compressed_payload(grpc_end2end_test_config config); +extern void stream_compression_compressed_payload_pre_init(void); +extern void stream_compression_payload(grpc_end2end_test_config config); +extern void stream_compression_payload_pre_init(void); +extern void stream_compression_ping_pong_streaming(grpc_end2end_test_config config); +extern void stream_compression_ping_pong_streaming_pre_init(void); +extern void streaming_error_response(grpc_end2end_test_config config); +extern void streaming_error_response_pre_init(void); +extern void trailing_metadata(grpc_end2end_test_config config); +extern void trailing_metadata_pre_init(void); +extern void workaround_cronet_compression(grpc_end2end_test_config config); +extern void workaround_cronet_compression_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); + +void grpc_end2end_tests_pre_init(void) { + GPR_ASSERT(!g_pre_init_called); + g_pre_init_called = true; + grpc_summon_debugger_macros(); + authority_not_supported_pre_init(); + bad_hostname_pre_init(); + bad_ping_pre_init(); + binary_metadata_pre_init(); + call_creds_pre_init(); + cancel_after_accept_pre_init(); + cancel_after_client_done_pre_init(); + cancel_after_invoke_pre_init(); + cancel_after_round_trip_pre_init(); + cancel_before_invoke_pre_init(); + cancel_in_a_vacuum_pre_init(); + cancel_with_status_pre_init(); + compressed_payload_pre_init(); + connectivity_pre_init(); + default_host_pre_init(); + disappearing_server_pre_init(); + empty_batch_pre_init(); + filter_call_init_fails_pre_init(); + filter_causes_close_pre_init(); + filter_latency_pre_init(); + graceful_server_shutdown_pre_init(); + high_initial_seqno_pre_init(); + hpack_size_pre_init(); + idempotent_request_pre_init(); + invoke_large_request_pre_init(); + keepalive_timeout_pre_init(); + large_metadata_pre_init(); + load_reporting_hook_pre_init(); + max_concurrent_streams_pre_init(); + max_connection_age_pre_init(); + max_connection_idle_pre_init(); + max_message_length_pre_init(); + negative_deadline_pre_init(); + network_status_change_pre_init(); + no_logging_pre_init(); + no_op_pre_init(); + payload_pre_init(); + ping_pre_init(); + ping_pong_streaming_pre_init(); + proxy_auth_pre_init(); + registered_call_pre_init(); + request_with_flags_pre_init(); + request_with_payload_pre_init(); + resource_quota_server_pre_init(); + server_finishes_request_pre_init(); + shutdown_finishes_calls_pre_init(); + shutdown_finishes_tags_pre_init(); + simple_cacheable_request_pre_init(); + simple_delayed_request_pre_init(); + simple_metadata_pre_init(); + simple_request_pre_init(); + stream_compression_compressed_payload_pre_init(); + stream_compression_payload_pre_init(); + stream_compression_ping_pong_streaming_pre_init(); + streaming_error_response_pre_init(); + trailing_metadata_pre_init(); + workaround_cronet_compression_pre_init(); + write_buffering_pre_init(); + write_buffering_at_end_pre_init(); +} + +void grpc_end2end_tests(int argc, char **argv, + grpc_end2end_test_config config) { + int i; + + GPR_ASSERT(g_pre_init_called); + + if (argc <= 1) { + authority_not_supported(config); + bad_hostname(config); + bad_ping(config); + binary_metadata(config); + call_creds(config); + cancel_after_accept(config); + cancel_after_client_done(config); + cancel_after_invoke(config); + cancel_after_round_trip(config); + cancel_before_invoke(config); + cancel_in_a_vacuum(config); + cancel_with_status(config); + compressed_payload(config); + connectivity(config); + default_host(config); + disappearing_server(config); + empty_batch(config); + filter_call_init_fails(config); + filter_causes_close(config); + filter_latency(config); + graceful_server_shutdown(config); + high_initial_seqno(config); + hpack_size(config); + idempotent_request(config); + invoke_large_request(config); + keepalive_timeout(config); + large_metadata(config); + load_reporting_hook(config); + max_concurrent_streams(config); + max_connection_age(config); + max_connection_idle(config); + max_message_length(config); + negative_deadline(config); + network_status_change(config); + no_logging(config); + no_op(config); + payload(config); + ping(config); + ping_pong_streaming(config); + proxy_auth(config); + registered_call(config); + request_with_flags(config); + request_with_payload(config); + resource_quota_server(config); + server_finishes_request(config); + shutdown_finishes_calls(config); + shutdown_finishes_tags(config); + simple_cacheable_request(config); + simple_delayed_request(config); + simple_metadata(config); + simple_request(config); + stream_compression_compressed_payload(config); + stream_compression_payload(config); + stream_compression_ping_pong_streaming(config); + streaming_error_response(config); + trailing_metadata(config); + workaround_cronet_compression(config); + write_buffering(config); + write_buffering_at_end(config); + return; + } + + for (i = 1; i < argc; i++) { + if (0 == strcmp("authority_not_supported", argv[i])) { + authority_not_supported(config); + continue; + } + if (0 == strcmp("bad_hostname", argv[i])) { + bad_hostname(config); + continue; + } + if (0 == strcmp("bad_ping", argv[i])) { + bad_ping(config); + continue; + } + if (0 == strcmp("binary_metadata", argv[i])) { + binary_metadata(config); + continue; + } + if (0 == strcmp("call_creds", argv[i])) { + call_creds(config); + continue; + } + if (0 == strcmp("cancel_after_accept", argv[i])) { + cancel_after_accept(config); + continue; + } + if (0 == strcmp("cancel_after_client_done", argv[i])) { + cancel_after_client_done(config); + continue; + } + if (0 == strcmp("cancel_after_invoke", argv[i])) { + cancel_after_invoke(config); + continue; + } + if (0 == strcmp("cancel_after_round_trip", argv[i])) { + cancel_after_round_trip(config); + continue; + } + if (0 == strcmp("cancel_before_invoke", argv[i])) { + cancel_before_invoke(config); + continue; + } + if (0 == strcmp("cancel_in_a_vacuum", argv[i])) { + cancel_in_a_vacuum(config); + continue; + } + if (0 == strcmp("cancel_with_status", argv[i])) { + cancel_with_status(config); + continue; + } + if (0 == strcmp("compressed_payload", argv[i])) { + compressed_payload(config); + continue; + } + if (0 == strcmp("connectivity", argv[i])) { + connectivity(config); + continue; + } + if (0 == strcmp("default_host", argv[i])) { + default_host(config); + continue; + } + if (0 == strcmp("disappearing_server", argv[i])) { + disappearing_server(config); + continue; + } + if (0 == strcmp("empty_batch", argv[i])) { + empty_batch(config); + continue; + } + if (0 == strcmp("filter_call_init_fails", argv[i])) { + filter_call_init_fails(config); + continue; + } + if (0 == strcmp("filter_causes_close", argv[i])) { + filter_causes_close(config); + continue; + } + if (0 == strcmp("filter_latency", argv[i])) { + filter_latency(config); + continue; + } + if (0 == strcmp("graceful_server_shutdown", argv[i])) { + graceful_server_shutdown(config); + continue; + } + if (0 == strcmp("high_initial_seqno", argv[i])) { + high_initial_seqno(config); + continue; + } + if (0 == strcmp("hpack_size", argv[i])) { + hpack_size(config); + continue; + } + if (0 == strcmp("idempotent_request", argv[i])) { + idempotent_request(config); + continue; + } + if (0 == strcmp("invoke_large_request", argv[i])) { + invoke_large_request(config); + continue; + } + if (0 == strcmp("keepalive_timeout", argv[i])) { + keepalive_timeout(config); + continue; + } + if (0 == strcmp("large_metadata", argv[i])) { + large_metadata(config); + continue; + } + if (0 == strcmp("load_reporting_hook", argv[i])) { + load_reporting_hook(config); + continue; + } + if (0 == strcmp("max_concurrent_streams", argv[i])) { + max_concurrent_streams(config); + continue; + } + if (0 == strcmp("max_connection_age", argv[i])) { + max_connection_age(config); + continue; + } + if (0 == strcmp("max_connection_idle", argv[i])) { + max_connection_idle(config); + continue; + } + if (0 == strcmp("max_message_length", argv[i])) { + max_message_length(config); + continue; + } + if (0 == strcmp("negative_deadline", argv[i])) { + negative_deadline(config); + continue; + } + if (0 == strcmp("network_status_change", argv[i])) { + network_status_change(config); + continue; + } + if (0 == strcmp("no_logging", argv[i])) { + no_logging(config); + continue; + } + if (0 == strcmp("no_op", argv[i])) { + no_op(config); + continue; + } + if (0 == strcmp("payload", argv[i])) { + payload(config); + continue; + } + if (0 == strcmp("ping", argv[i])) { + ping(config); + continue; + } + if (0 == strcmp("ping_pong_streaming", argv[i])) { + ping_pong_streaming(config); + continue; + } + if (0 == strcmp("proxy_auth", argv[i])) { + proxy_auth(config); + continue; + } + if (0 == strcmp("registered_call", argv[i])) { + registered_call(config); + continue; + } + if (0 == strcmp("request_with_flags", argv[i])) { + request_with_flags(config); + continue; + } + if (0 == strcmp("request_with_payload", argv[i])) { + request_with_payload(config); + continue; + } + if (0 == strcmp("resource_quota_server", argv[i])) { + resource_quota_server(config); + continue; + } + if (0 == strcmp("server_finishes_request", argv[i])) { + server_finishes_request(config); + continue; + } + if (0 == strcmp("shutdown_finishes_calls", argv[i])) { + shutdown_finishes_calls(config); + continue; + } + if (0 == strcmp("shutdown_finishes_tags", argv[i])) { + shutdown_finishes_tags(config); + continue; + } + if (0 == strcmp("simple_cacheable_request", argv[i])) { + simple_cacheable_request(config); + continue; + } + if (0 == strcmp("simple_delayed_request", argv[i])) { + simple_delayed_request(config); + continue; + } + if (0 == strcmp("simple_metadata", argv[i])) { + simple_metadata(config); + continue; + } + if (0 == strcmp("simple_request", argv[i])) { + simple_request(config); + continue; + } + if (0 == strcmp("stream_compression_compressed_payload", argv[i])) { + stream_compression_compressed_payload(config); + continue; + } + if (0 == strcmp("stream_compression_payload", argv[i])) { + stream_compression_payload(config); + continue; + } + if (0 == strcmp("stream_compression_ping_pong_streaming", argv[i])) { + stream_compression_ping_pong_streaming(config); + continue; + } + if (0 == strcmp("streaming_error_response", argv[i])) { + streaming_error_response(config); + continue; + } + if (0 == strcmp("trailing_metadata", argv[i])) { + trailing_metadata(config); + continue; + } + if (0 == strcmp("workaround_cronet_compression", argv[i])) { + workaround_cronet_compression(config); + continue; + } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } + gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); + abort(); + } +} diff --git a/test/core/end2end/fixtures/h2_census.c b/test/core/end2end/fixtures/h2_census.c deleted file mode 100644 index 9870ccb34a..0000000000 --- a/test/core/end2end/fixtures/h2_census.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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); - GPR_ASSERT(f->client); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -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_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - 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+census", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc new file mode 100644 index 0000000000..d7058187b4 --- /dev/null +++ b/test/core/end2end/fixtures/h2_census.cc @@ -0,0 +1,133 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.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 = static_cast( + 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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +static grpc_arg make_census_enable_arg(void) { + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(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 = + static_cast(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); + GPR_ASSERT(f->client); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + fullstack_fixture_data *ffd = + static_cast(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_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + 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 = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack+census", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_compress.c b/test/core/end2end/fixtures/h2_compress.c deleted file mode 100644 index 9866dea7eb..0000000000 --- a/test/core/end2end/fixtures/h2_compress.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_compression_fixture_data { - char *localaddr; - grpc_channel_args *client_args_compression; - grpc_channel_args *server_args_compression; -} fullstack_compression_fixture_data; - -static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_compression( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - int port = grpc_pick_unused_port_or_die(); - fullstack_compression_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_compression_fixture_data)); - memset(ffd, 0, sizeof(fullstack_compression_fixture_data)); - - gpr_join_host_port(&ffd->localaddr, "localhost", port); - - memset(&f, 0, sizeof(f)); - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -void chttp2_init_client_fullstack_compression(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - fullstack_compression_fixture_data *ffd = f->fixture_data; - if (ffd->client_args_compression != NULL) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, ffd->client_args_compression); - grpc_exec_ctx_finish(&exec_ctx); - } - ffd->client_args_compression = grpc_channel_args_set_compression_algorithm( - client_args, GRPC_COMPRESS_GZIP); - f->client = grpc_insecure_channel_create(ffd->localaddr, - ffd->client_args_compression, NULL); -} - -void chttp2_init_server_fullstack_compression(grpc_end2end_test_fixture *f, - grpc_channel_args *server_args) { - fullstack_compression_fixture_data *ffd = f->fixture_data; - if (ffd->server_args_compression != NULL) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, ffd->server_args_compression); - grpc_exec_ctx_finish(&exec_ctx); - } - ffd->server_args_compression = grpc_channel_args_set_compression_algorithm( - server_args, GRPC_COMPRESS_GZIP); - if (f->server) { - grpc_server_destroy(f->server); - } - f->server = grpc_server_create(ffd->server_args_compression, 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_compression(grpc_end2end_test_fixture *f) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - fullstack_compression_fixture_data *ffd = f->fixture_data; - grpc_channel_args_destroy(&exec_ctx, ffd->client_args_compression); - grpc_channel_args_destroy(&exec_ctx, ffd->server_args_compression); - gpr_free(ffd->localaddr); - gpr_free(ffd); - grpc_exec_ctx_finish(&exec_ctx); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/fullstack_compression", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_fullstack_compression, - chttp2_init_client_fullstack_compression, - chttp2_init_server_fullstack_compression, - chttp2_tear_down_fullstack_compression}, -}; - -int main(int argc, char **argv) { - size_t i; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc new file mode 100644 index 0000000000..bdfeef259d --- /dev/null +++ b/test/core/end2end/fixtures/h2_compress.cc @@ -0,0 +1,135 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_compression_fixture_data { + char *localaddr; + grpc_channel_args *client_args_compression; + grpc_channel_args *server_args_compression; +} fullstack_compression_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack_compression( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + fullstack_compression_fixture_data *ffd = + static_cast( + gpr_malloc(sizeof(fullstack_compression_fixture_data))); + memset(ffd, 0, sizeof(fullstack_compression_fixture_data)); + + gpr_join_host_port(&ffd->localaddr, "localhost", port); + + memset(&f, 0, sizeof(f)); + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack_compression(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_compression_fixture_data *ffd = + static_cast(f->fixture_data); + if (ffd->client_args_compression != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, ffd->client_args_compression); + grpc_exec_ctx_finish(&exec_ctx); + } + ffd->client_args_compression = grpc_channel_args_set_compression_algorithm( + client_args, GRPC_COMPRESS_GZIP); + f->client = grpc_insecure_channel_create(ffd->localaddr, + ffd->client_args_compression, NULL); +} + +void chttp2_init_server_fullstack_compression(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + fullstack_compression_fixture_data *ffd = + static_cast(f->fixture_data); + if (ffd->server_args_compression != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, ffd->server_args_compression); + grpc_exec_ctx_finish(&exec_ctx); + } + ffd->server_args_compression = grpc_channel_args_set_compression_algorithm( + server_args, GRPC_COMPRESS_GZIP); + if (f->server) { + grpc_server_destroy(f->server); + } + f->server = grpc_server_create(ffd->server_args_compression, 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_compression(grpc_end2end_test_fixture *f) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + fullstack_compression_fixture_data *ffd = + static_cast(f->fixture_data); + grpc_channel_args_destroy(&exec_ctx, ffd->client_args_compression); + grpc_channel_args_destroy(&exec_ctx, ffd->server_args_compression); + gpr_free(ffd->localaddr); + gpr_free(ffd); + grpc_exec_ctx_finish(&exec_ctx); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack_compression", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_fullstack_compression, + chttp2_init_client_fullstack_compression, + chttp2_init_server_fullstack_compression, + chttp2_tear_down_fullstack_compression}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c deleted file mode 100644 index e622d952be..0000000000 --- a/test/core/end2end/fixtures/h2_fakesec.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_secure_fixture_data { - char *localaddr; -} fullstack_secure_fixture_data; - -static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -static void process_auth_failure(void *state, grpc_auth_context *ctx, - const grpc_metadata *md, size_t md_count, - grpc_process_auth_metadata_done_cb cb, - void *user_data) { - GPR_ASSERT(state == NULL); - cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); -} - -static void chttp2_init_client_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args, - grpc_channel_credentials *creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = - grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); - GPR_ASSERT(f->client != NULL); - grpc_channel_credentials_release(creds); -} - -static void chttp2_init_server_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args, - grpc_server_credentials *server_creds) { - fullstack_secure_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_secure_http2_port(f->server, ffd->localaddr, - server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(f->server); -} - -void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - gpr_free(ffd->localaddr); - gpr_free(ffd); -} - -static void chttp2_init_client_fake_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_channel_credentials *fake_ts_creds = - grpc_fake_transport_security_credentials_create(); - chttp2_init_client_secure_fullstack(f, client_args, fake_ts_creds); -} - -static int fail_server_auth_check(grpc_channel_args *server_args) { - size_t i; - if (server_args == NULL) return 0; - for (i = 0; i < server_args->num_args; i++) { - if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == - 0) { - return 1; - } - } - return 0; -} - -static void chttp2_init_server_fake_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { - grpc_server_credentials *fake_ts_creds = - grpc_fake_transport_security_server_credentials_create(); - if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; - grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds, - processor); - } - chttp2_init_server_secure_fullstack(f, server_args, fake_ts_creds); -} - -/* All test configurations */ - -static grpc_end2end_test_config configs[] = { - {"chttp2/fake_secure_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_secure_fullstack, - chttp2_init_client_fake_secure_fullstack, - chttp2_init_server_fake_secure_fullstack, - chttp2_tear_down_secure_fullstack}, -}; - -int main(int argc, char **argv) { - size_t i; - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc new file mode 100644 index 0000000000..7cbcfcca91 --- /dev/null +++ b/test/core/end2end/fixtures/h2_fakesec.cc @@ -0,0 +1,155 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_secure_fixture_data { + char *localaddr; +} fullstack_secure_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = + static_cast( + gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +static void process_auth_failure(void *state, grpc_auth_context *ctx, + const grpc_metadata *md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void *user_data) { + GPR_ASSERT(state == NULL); + cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); +} + +static void chttp2_init_client_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args, + grpc_channel_credentials *creds) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); + GPR_ASSERT(f->client != NULL); + grpc_channel_credentials_release(creds); +} + +static void chttp2_init_server_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args, + grpc_server_credentials *server_creds) { + fullstack_secure_fixture_data *ffd = + static_cast(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_secure_http2_port(f->server, ffd->localaddr, + server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(f->server); +} + +void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +static void chttp2_init_client_fake_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { + grpc_channel_credentials *fake_ts_creds = + grpc_fake_transport_security_credentials_create(); + chttp2_init_client_secure_fullstack(f, client_args, fake_ts_creds); +} + +static int fail_server_auth_check(grpc_channel_args *server_args) { + size_t i; + if (server_args == NULL) return 0; + for (i = 0; i < server_args->num_args; i++) { + if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == + 0) { + return 1; + } + } + return 0; +} + +static void chttp2_init_server_fake_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { + grpc_server_credentials *fake_ts_creds = + grpc_fake_transport_security_server_credentials_create(); + if (fail_server_auth_check(server_args)) { + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; + grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds, + processor); + } + chttp2_init_server_secure_fullstack(f, server_args, fake_ts_creds); +} + +/* All test configurations */ + +static grpc_end2end_test_config configs[] = { + {"chttp2/fake_secure_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_secure_fullstack, + chttp2_init_client_fake_secure_fullstack, + chttp2_init_server_fake_secure_fullstack, + chttp2_tear_down_secure_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_fd.c b/test/core/end2end/fixtures/h2_fd.c deleted file mode 100644 index e82c120221..0000000000 --- a/test/core/end2end/fixtures/h2_fd.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" -#include "src/core/lib/iomgr/unix_sockets_posix.h" -#include "test/core/util/test_config.h" - -typedef struct { int fd_pair[2]; } sp_fixture_data; - -static void create_sockets(int sv[2]) { - int flags; - grpc_create_socketpair_if_unix(sv); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE); -} - -static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - sp_fixture_data *fixture_data = gpr_malloc(sizeof(*fixture_data)); - - grpc_end2end_test_fixture f; - memset(&f, 0, sizeof(f)); - f.fixture_data = fixture_data; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - create_sockets(fixture_data->fd_pair); - - return f; -} - -static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - sp_fixture_data *sfd = f->fixture_data; - - GPR_ASSERT(!f->client); - f->client = grpc_insecure_channel_create_from_fd( - "fixture_client", sfd->fd_pair[0], client_args); - GPR_ASSERT(f->client); - - grpc_exec_ctx_finish(&exec_ctx); -} - -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; - sp_fixture_data *sfd = f->fixture_data; - GPR_ASSERT(!f->server); - f->server = grpc_server_create(server_args, NULL); - GPR_ASSERT(f->server); - grpc_server_register_completion_queue(f->server, f->cq, NULL); - grpc_server_start(f->server); - - grpc_server_add_insecure_channel_from_fd(f->server, NULL, sfd->fd_pair[1]); - - grpc_exec_ctx_finish(&exec_ctx); -} - -static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { - gpr_free(f->fixture_data); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, - chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, -}; - -int main(int argc, char **argv) { - size_t i; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc new file mode 100644 index 0000000000..2dc7898d56 --- /dev/null +++ b/test/core/end2end/fixtures/h2_fd.cc @@ -0,0 +1,126 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "test/core/util/test_config.h" + +typedef struct { int fd_pair[2]; } sp_fixture_data; + +static void create_sockets(int sv[2]) { + int flags; + grpc_create_socketpair_if_unix(sv); + flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); + GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE); +} + +static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + sp_fixture_data *fixture_data = + static_cast(gpr_malloc(sizeof(*fixture_data))); + + grpc_end2end_test_fixture f; + memset(&f, 0, sizeof(f)); + f.fixture_data = fixture_data; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + create_sockets(fixture_data->fd_pair); + + return f; +} + +static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + sp_fixture_data *sfd = static_cast(f->fixture_data); + + GPR_ASSERT(!f->client); + f->client = grpc_insecure_channel_create_from_fd( + "fixture_client", sfd->fd_pair[0], client_args); + GPR_ASSERT(f->client); + + grpc_exec_ctx_finish(&exec_ctx); +} + +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; + sp_fixture_data *sfd = static_cast(f->fixture_data); + GPR_ASSERT(!f->server); + f->server = grpc_server_create(server_args, NULL); + GPR_ASSERT(f->server); + grpc_server_register_completion_queue(f->server, f->cq, NULL); + grpc_server_start(f->server); + + grpc_server_add_insecure_channel_from_fd(f->server, NULL, sfd->fd_pair[1]); + + grpc_exec_ctx_finish(&exec_ctx); +} + +static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { + gpr_free(f->fixture_data); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, + chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/end2end/fixtures/h2_full+pipe.c b/test/core/end2end/fixtures/h2_full+pipe.c deleted file mode 100644 index c764bd704a..0000000000 --- a/test/core/end2end/fixtures/h2_full+pipe.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test requires posix wakeup fds -#ifdef GRPC_POSIX_WAKEUP_FD - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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 | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} - -#else /* GRPC_POSIX_WAKEUP_FD */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_WAKEUP_FD */ diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc new file mode 100644 index 0000000000..beff1be239 --- /dev/null +++ b/test/core/end2end/fixtures/h2_full+pipe.cc @@ -0,0 +1,124 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test requires posix wakeup fds +#ifdef GRPC_POSIX_WAKEUP_FD + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.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 = static_cast( + 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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(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 = + static_cast(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 = + static_cast(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 | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} + +#else /* GRPC_POSIX_WAKEUP_FD */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_WAKEUP_FD */ diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c deleted file mode 100644 index 7eb29e0d32..0000000000 --- a/test/core/end2end/fixtures/h2_full+trace.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -#include "test/core/end2end/end2end_tests.h" - -#include -#ifdef GRPC_POSIX_SOCKET -#include -#endif - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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 | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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; - - /* force tracing on, with a value to force many - code paths in trace.c to be taken */ - gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all"); - -#ifdef GRPC_POSIX_SOCKET - g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; -#else - g_fixture_slowdown_factor = 10; -#endif - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc new file mode 100644 index 0000000000..efed0c536f --- /dev/null +++ b/test/core/end2end/fixtures/h2_full+trace.cc @@ -0,0 +1,130 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#include "test/core/end2end/end2end_tests.h" + +#include +#ifdef GRPC_POSIX_SOCKET +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.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 = static_cast( + 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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(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 = + static_cast(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 = + static_cast(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 | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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; + + /* force tracing on, with a value to force many + code paths in trace.c to be taken */ + gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all"); + +#ifdef GRPC_POSIX_SOCKET + g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; +#else + g_fixture_slowdown_factor = 10; +#endif + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); + GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); + GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_full+workarounds.c b/test/core/end2end/fixtures/h2_full+workarounds.c deleted file mode 100644 index a98e5ad57f..0000000000 --- a/test/core/end2end/fixtures/h2_full+workarounds.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static char *workarounds_arg[GRPC_MAX_WORKAROUND_ID] = { - GRPC_ARG_WORKAROUND_CRONET_COMPRESSION}; - -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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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) { - int i; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - fullstack_fixture_data *ffd = f->fixture_data; - grpc_arg args[GRPC_MAX_WORKAROUND_ID]; - for (i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) { - args[i].key = workarounds_arg[i]; - args[i].type = GRPC_ARG_INTEGER; - args[i].value.integer = 1; - } - grpc_channel_args *server_args_new = - grpc_channel_args_copy_and_add(server_args, args, GRPC_MAX_WORKAROUND_ID); - if (f->server) { - grpc_server_destroy(f->server); - } - f->server = grpc_server_create(server_args_new, 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); - grpc_channel_args_destroy(&exec_ctx, server_args_new); - grpc_exec_ctx_finish(&exec_ctx); -} - -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 | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_WORKAROUNDS, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc new file mode 100644 index 0000000000..d4930ce90d --- /dev/null +++ b/test/core/end2end/fixtures/h2_full+workarounds.cc @@ -0,0 +1,127 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static char *workarounds_arg[GRPC_MAX_WORKAROUND_ID] = { + const_cast(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION)}; + +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 = static_cast( + 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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(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) { + int i; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + fullstack_fixture_data *ffd = + static_cast(f->fixture_data); + grpc_arg args[GRPC_MAX_WORKAROUND_ID]; + for (i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) { + args[i].key = workarounds_arg[i]; + args[i].type = GRPC_ARG_INTEGER; + args[i].value.integer = 1; + } + grpc_channel_args *server_args_new = + grpc_channel_args_copy_and_add(server_args, args, GRPC_MAX_WORKAROUND_ID); + if (f->server) { + grpc_server_destroy(f->server); + } + f->server = grpc_server_create(server_args_new, 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); + grpc_channel_args_destroy(&exec_ctx, server_args_new); + grpc_exec_ctx_finish(&exec_ctx); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = + static_cast(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 | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | + FEATURE_MASK_SUPPORTS_WORKAROUNDS, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_full.c b/test/core/end2end/fixtures/h2_full.c deleted file mode 100644 index ae68bd9698..0000000000 --- a/test/core/end2end/fixtures/h2_full.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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 | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc new file mode 100644 index 0000000000..d132198157 --- /dev/null +++ b/test/core/end2end/fixtures/h2_full.cc @@ -0,0 +1,110 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.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 = static_cast( + 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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(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 = + static_cast(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 = + static_cast(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 | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c deleted file mode 100644 index 6145892365..0000000000 --- a/test/core/end2end/fixtures/h2_http_proxy.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/fixtures/http_proxy_fixture.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_fixture_data { - char *server_addr; - grpc_end2end_http_proxy *proxy; -} 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; - memset(&f, 0, sizeof(f)); - fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); - const int server_port = grpc_pick_unused_port_or_die(); - gpr_join_host_port(&ffd->server_addr, "localhost", server_port); - - /* Passing client_args to proxy_create for the case of checking for proxy auth - */ - ffd->proxy = grpc_end2end_http_proxy_create(client_args); - - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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; - char *proxy_uri; - - /* If testing for proxy auth, add credentials to proxy uri */ - const grpc_arg *proxy_auth_arg = - grpc_channel_args_find(client_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); - if (proxy_auth_arg == NULL || proxy_auth_arg->type != GRPC_ARG_STRING) { - gpr_asprintf(&proxy_uri, "http://%s", - grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); - } else { - gpr_asprintf(&proxy_uri, "http://%s@%s", proxy_auth_arg->value.string, - grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); - } - gpr_setenv("http_proxy", proxy_uri); - gpr_free(proxy_uri); - f->client = grpc_insecure_channel_create(ffd->server_addr, 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->server_addr)); - 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->server_addr); - grpc_end2end_http_proxy_destroy(ffd->proxy); - gpr_free(ffd); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc new file mode 100644 index 0000000000..5630b491b0 --- /dev/null +++ b/test/core/end2end/fixtures/h2_http_proxy.cc @@ -0,0 +1,132 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/fixtures/http_proxy_fixture.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_fixture_data { + char *server_addr; + grpc_end2end_http_proxy *proxy; +} 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; + memset(&f, 0, sizeof(f)); + fullstack_fixture_data *ffd = static_cast( + gpr_malloc(sizeof(fullstack_fixture_data))); + const int server_port = grpc_pick_unused_port_or_die(); + gpr_join_host_port(&ffd->server_addr, "localhost", server_port); + + /* Passing client_args to proxy_create for the case of checking for proxy auth + */ + ffd->proxy = grpc_end2end_http_proxy_create(client_args); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(f->fixture_data); + char *proxy_uri; + + /* If testing for proxy auth, add credentials to proxy uri */ + const grpc_arg *proxy_auth_arg = + grpc_channel_args_find(client_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + if (proxy_auth_arg == NULL || proxy_auth_arg->type != GRPC_ARG_STRING) { + gpr_asprintf(&proxy_uri, "http://%s", + grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); + } else { + gpr_asprintf(&proxy_uri, "http://%s@%s", proxy_auth_arg->value.string, + grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); + } + gpr_setenv("http_proxy", proxy_uri); + gpr_free(proxy_uri); + f->client = grpc_insecure_channel_create(ffd->server_addr, 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 = + static_cast(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->server_addr)); + grpc_server_start(f->server); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd->server_addr); + grpc_end2end_http_proxy_destroy(ffd->proxy); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_load_reporting.c b/test/core/end2end/fixtures/h2_load_reporting.c deleted file mode 100644 index 8a05bb722a..0000000000 --- a/test/core/end2end/fixtures/h2_load_reporting.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct load_reporting_fixture_data { - char *localaddr; -} load_reporting_fixture_data; - -static grpc_end2end_test_fixture chttp2_create_fixture_load_reporting( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - int port = grpc_pick_unused_port_or_die(); - load_reporting_fixture_data *ffd = - gpr_malloc(sizeof(load_reporting_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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -void chttp2_init_client_load_reporting(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - load_reporting_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_load_reporting(grpc_end2end_test_fixture *f, - grpc_channel_args *server_args) { - load_reporting_fixture_data *ffd = f->fixture_data; - grpc_arg arg = grpc_load_reporting_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_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - 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_load_reporting(grpc_end2end_test_fixture *f) { - load_reporting_fixture_data *ffd = f->fixture_data; - gpr_free(ffd->localaddr); - gpr_free(ffd); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/fullstack+load_reporting", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_load_reporting, chttp2_init_client_load_reporting, - chttp2_init_server_load_reporting, chttp2_tear_down_load_reporting}, -}; - -int main(int argc, char **argv) { - size_t i; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_load_reporting.cc b/test/core/end2end/fixtures/h2_load_reporting.cc new file mode 100644 index 0000000000..e461f13e06 --- /dev/null +++ b/test/core/end2end/fixtures/h2_load_reporting.cc @@ -0,0 +1,120 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct load_reporting_fixture_data { + char *localaddr; +} load_reporting_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_load_reporting( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + int port = grpc_pick_unused_port_or_die(); + load_reporting_fixture_data *ffd = static_cast( + gpr_malloc(sizeof(load_reporting_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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_load_reporting(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + load_reporting_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL); + GPR_ASSERT(f->client); +} + +void chttp2_init_server_load_reporting(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + load_reporting_fixture_data *ffd = + static_cast(f->fixture_data); + grpc_arg arg = grpc_load_reporting_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_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + 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_load_reporting(grpc_end2end_test_fixture *f) { + load_reporting_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack+load_reporting", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_load_reporting, chttp2_init_client_load_reporting, + chttp2_init_server_load_reporting, chttp2_tear_down_load_reporting}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c deleted file mode 100644 index ee1d0b1416..0000000000 --- a/test/core/end2end/fixtures/h2_oauth2.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static const char oauth2_md[] = "Bearer aaslkfjs424535asdf"; -static const char *client_identity_property_name = "smurf_name"; -static const char *client_identity = "Brainy Smurf"; - -typedef struct fullstack_secure_fixture_data { - char *localaddr; -} fullstack_secure_fixture_data; - -static const grpc_metadata *find_metadata(const grpc_metadata *md, - size_t md_count, const char *key, - const char *value) { - size_t i; - for (i = 0; i < md_count; i++) { - if (grpc_slice_str_cmp(md[i].key, key) == 0 && - grpc_slice_str_cmp(md[i].value, value) == 0) { - return &md[i]; - } - } - return NULL; -} - -typedef struct { size_t pseudo_refcount; } test_processor_state; - -static void process_oauth2_success(void *state, grpc_auth_context *ctx, - const grpc_metadata *md, size_t md_count, - grpc_process_auth_metadata_done_cb cb, - void *user_data) { - const grpc_metadata *oauth2 = - find_metadata(md, md_count, "authorization", oauth2_md); - test_processor_state *s; - - GPR_ASSERT(state != NULL); - s = (test_processor_state *)state; - GPR_ASSERT(s->pseudo_refcount == 1); - GPR_ASSERT(oauth2 != NULL); - grpc_auth_context_add_cstring_property(ctx, client_identity_property_name, - client_identity); - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( - ctx, client_identity_property_name) == 1); - cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_OK, NULL); -} - -static void process_oauth2_failure(void *state, grpc_auth_context *ctx, - const grpc_metadata *md, size_t md_count, - grpc_process_auth_metadata_done_cb cb, - void *user_data) { - const grpc_metadata *oauth2 = - find_metadata(md, md_count, "authorization", oauth2_md); - test_processor_state *s; - GPR_ASSERT(state != NULL); - s = (test_processor_state *)state; - GPR_ASSERT(s->pseudo_refcount == 1); - GPR_ASSERT(oauth2 != NULL); - cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); -} - -static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -static void chttp2_init_client_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args, - grpc_channel_credentials *creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = - grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); - GPR_ASSERT(f->client != NULL); - grpc_channel_credentials_release(creds); -} - -static void chttp2_init_server_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args, - grpc_server_credentials *server_creds) { - fullstack_secure_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_secure_http2_port(f->server, ffd->localaddr, - server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(f->server); -} - -void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - gpr_free(ffd->localaddr); - gpr_free(ffd); -} - -static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL, NULL); - grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create( - &exec_ctx, "authorization", oauth2_md, true /* is_async */); - grpc_channel_credentials *ssl_oauth2_creds = - grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); - chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds); - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_channel_credentials_release(ssl_creds); - grpc_call_credentials_release(oauth2_creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static int fail_server_auth_check(grpc_channel_args *server_args) { - size_t i; - if (server_args == NULL) return 0; - for (i = 0; i < server_args->num_args; i++) { - if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == - 0) { - return 1; - } - } - return 0; -} - -static void processor_destroy(void *state) { - test_processor_state *s = (test_processor_state *)state; - GPR_ASSERT((s->pseudo_refcount--) == 1); - gpr_free(s); -} - -static grpc_auth_metadata_processor test_processor_create(int failing) { - test_processor_state *s = gpr_malloc(sizeof(*s)); - grpc_auth_metadata_processor result; - s->pseudo_refcount = 1; - result.state = s; - result.destroy = processor_destroy; - if (failing) { - result.process = process_oauth2_failure; - } else { - result.process = process_oauth2_success; - } - return result; -} - -static void chttp2_init_server_simple_ssl_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); - grpc_server_credentials_set_auth_metadata_processor( - ssl_creds, test_processor_create(fail_server_auth_check(server_args))); - chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); -} - -/* All test configurations */ - -static grpc_end2end_test_config configs[] = { - {"chttp2/simple_ssl_with_oauth2_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_secure_fullstack, - chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, - chttp2_init_server_simple_ssl_secure_fullstack, - chttp2_tear_down_secure_fullstack}, -}; - -int main(int argc, char **argv) { - size_t i; - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc new file mode 100644 index 0000000000..f1e49f20cd --- /dev/null +++ b/test/core/end2end/fixtures/h2_oauth2.cc @@ -0,0 +1,235 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static const char oauth2_md[] = "Bearer aaslkfjs424535asdf"; +static const char *client_identity_property_name = "smurf_name"; +static const char *client_identity = "Brainy Smurf"; + +typedef struct fullstack_secure_fixture_data { + char *localaddr; +} fullstack_secure_fixture_data; + +static const grpc_metadata *find_metadata(const grpc_metadata *md, + size_t md_count, const char *key, + const char *value) { + size_t i; + for (i = 0; i < md_count; i++) { + if (grpc_slice_str_cmp(md[i].key, key) == 0 && + grpc_slice_str_cmp(md[i].value, value) == 0) { + return &md[i]; + } + } + return NULL; +} + +typedef struct { size_t pseudo_refcount; } test_processor_state; + +static void process_oauth2_success(void *state, grpc_auth_context *ctx, + const grpc_metadata *md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void *user_data) { + const grpc_metadata *oauth2 = + find_metadata(md, md_count, "authorization", oauth2_md); + test_processor_state *s; + + GPR_ASSERT(state != NULL); + s = (test_processor_state *)state; + GPR_ASSERT(s->pseudo_refcount == 1); + GPR_ASSERT(oauth2 != NULL); + grpc_auth_context_add_cstring_property(ctx, client_identity_property_name, + client_identity); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( + ctx, client_identity_property_name) == 1); + cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_OK, NULL); +} + +static void process_oauth2_failure(void *state, grpc_auth_context *ctx, + const grpc_metadata *md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void *user_data) { + const grpc_metadata *oauth2 = + find_metadata(md, md_count, "authorization", oauth2_md); + test_processor_state *s; + GPR_ASSERT(state != NULL); + s = (test_processor_state *)state; + GPR_ASSERT(s->pseudo_refcount == 1); + GPR_ASSERT(oauth2 != NULL); + cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); +} + +static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = + static_cast( + gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +static void chttp2_init_client_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args, + grpc_channel_credentials *creds) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); + GPR_ASSERT(f->client != NULL); + grpc_channel_credentials_release(creds); +} + +static void chttp2_init_server_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args, + grpc_server_credentials *server_creds) { + fullstack_secure_fixture_data *ffd = + static_cast(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_secure_http2_port(f->server, ffd->localaddr, + server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(f->server); +} + +void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); + grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create( + &exec_ctx, "authorization", oauth2_md, true /* is_async */); + grpc_channel_credentials *ssl_oauth2_creds = + grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds); + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_channel_credentials_release(ssl_creds); + grpc_call_credentials_release(oauth2_creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static int fail_server_auth_check(grpc_channel_args *server_args) { + size_t i; + if (server_args == NULL) return 0; + for (i = 0; i < server_args->num_args; i++) { + if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == + 0) { + return 1; + } + } + return 0; +} + +static void processor_destroy(void *state) { + test_processor_state *s = (test_processor_state *)state; + GPR_ASSERT((s->pseudo_refcount--) == 1); + gpr_free(s); +} + +static grpc_auth_metadata_processor test_processor_create(int failing) { + test_processor_state *s = + static_cast(gpr_malloc(sizeof(*s))); + grpc_auth_metadata_processor result; + s->pseudo_refcount = 1; + result.state = s; + result.destroy = processor_destroy; + if (failing) { + result.process = process_oauth2_failure; + } else { + result.process = process_oauth2_success; + } + return result; +} + +static void chttp2_init_server_simple_ssl_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); + grpc_server_credentials_set_auth_metadata_processor( + ssl_creds, test_processor_create(fail_server_auth_check(server_args))); + chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); +} + +/* All test configurations */ + +static grpc_end2end_test_config configs[] = { + {"chttp2/simple_ssl_with_oauth2_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_secure_fullstack, + chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, + chttp2_init_server_simple_ssl_secure_fullstack, + chttp2_tear_down_secure_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_proxy.c b/test/core/end2end/fixtures/h2_proxy.c deleted file mode 100644 index 069130baf4..0000000000 --- a/test/core/end2end/fixtures/h2_proxy.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/end2end/fixtures/proxy.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_fixture_data { - grpc_end2end_proxy *proxy; -} fullstack_fixture_data; - -static grpc_server *create_proxy_server(const char *port, - grpc_channel_args *server_args) { - grpc_server *s = grpc_server_create(server_args, NULL); - GPR_ASSERT(grpc_server_add_insecure_http2_port(s, port)); - return s; -} - -static grpc_channel *create_proxy_client(const char *target, - grpc_channel_args *client_args) { - return grpc_insecure_channel_create(target, client_args, NULL); -} - -static const grpc_end2end_proxy_def proxy_def = {create_proxy_server, - create_proxy_client}; - -static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); - memset(&f, 0, sizeof(f)); - - ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); - - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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( - grpc_end2end_proxy_get_client_target(ffd->proxy), 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, grpc_end2end_proxy_get_server_port(ffd->proxy))); - grpc_server_start(f->server); -} - -void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { - fullstack_fixture_data *ffd = f->fixture_data; - grpc_end2end_proxy_destroy(ffd->proxy); - gpr_free(ffd); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/fullstack+proxy", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc new file mode 100644 index 0000000000..e1eb9687d0 --- /dev/null +++ b/test/core/end2end/fixtures/h2_proxy.cc @@ -0,0 +1,128 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/end2end/fixtures/proxy.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_fixture_data { + grpc_end2end_proxy *proxy; +} fullstack_fixture_data; + +static grpc_server *create_proxy_server(const char *port, + grpc_channel_args *server_args) { + grpc_server *s = grpc_server_create(server_args, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(s, port)); + return s; +} + +static grpc_channel *create_proxy_client(const char *target, + grpc_channel_args *client_args) { + return grpc_insecure_channel_create(target, client_args, NULL); +} + +static const grpc_end2end_proxy_def proxy_def = {create_proxy_server, + create_proxy_client}; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + fullstack_fixture_data *ffd = static_cast( + gpr_malloc(sizeof(fullstack_fixture_data))); + memset(&f, 0, sizeof(f)); + + ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = grpc_insecure_channel_create( + grpc_end2end_proxy_get_client_target(ffd->proxy), 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 = + static_cast(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, grpc_end2end_proxy_get_server_port(ffd->proxy))); + grpc_server_start(f->server); +} + +void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { + fullstack_fixture_data *ffd = + static_cast(f->fixture_data); + grpc_end2end_proxy_destroy(ffd->proxy); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack+proxy", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, 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 deleted file mode 100644 index 39ccb84b52..0000000000 --- a/test/core/end2end/fixtures/h2_sockpair+trace.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -#include "test/core/end2end/end2end_tests.h" - -#include -#ifdef GRPC_POSIX_SOCKET -#include -#endif - -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/client/http_client_filter.h" -#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/completion_queue.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -/* 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_end2end_test_fixture *f = ts; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); - grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, - grpc_server_get_channel_args(f->server)); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - grpc_end2end_test_fixture *f; - grpc_channel_args *client_args; -} sp_client_setup; - -static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport) { - sp_client_setup *cs = ts; - - cs->f->client = - grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, - GRPC_CLIENT_DIRECT_CHANNEL, transport); -} - -static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_endpoint_pair *sfd = gpr_malloc(sizeof(grpc_endpoint_pair)); - - grpc_end2end_test_fixture f; - memset(&f, 0, sizeof(f)); - f.fixture_data = sfd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); - - return f; -} - -static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_transport *transport; - sp_client_setup cs; - cs.client_args = client_args; - cs.f = f; - 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); - grpc_exec_ctx_finish(&exec_ctx); -} - -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_transport *transport; - GPR_ASSERT(!f->server); - f->server = grpc_server_create(server_args, NULL); - 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, 0); - server_setup_transport(f, transport); - grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { - gpr_free(f->fixture_data); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, - chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, -}; - -int main(int argc, char **argv) { - size_t i; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - /* force tracing on, with a value to force many - code paths in trace.c to be taken */ - gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all"); -#ifdef GRPC_POSIX_SOCKET - g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; -#else - g_fixture_slowdown_factor = 10; -#endif - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - grpc_exec_ctx_finish(&exec_ctx); - - GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc new file mode 100644 index 0000000000..81d0768969 --- /dev/null +++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc @@ -0,0 +1,163 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#include "test/core/end2end/end2end_tests.h" + +#include +#ifdef GRPC_POSIX_SOCKET +#include +#endif + +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/client/http_client_filter.h" +#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +/* 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_end2end_test_fixture *f = static_cast(ts); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); + grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, + grpc_server_get_channel_args(f->server)); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + grpc_end2end_test_fixture *f; + grpc_channel_args *client_args; +} sp_client_setup; + +static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, + grpc_transport *transport) { + sp_client_setup *cs = static_cast(ts); + + cs->f->client = + grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); +} + +static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_endpoint_pair *sfd = + static_cast(gpr_malloc(sizeof(grpc_endpoint_pair))); + + grpc_end2end_test_fixture f; + memset(&f, 0, sizeof(f)); + f.fixture_data = sfd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); + + return f; +} + +static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_transport *transport; + sp_client_setup cs; + cs.client_args = client_args; + cs.f = f; + 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); + grpc_exec_ctx_finish(&exec_ctx); +} + +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 = static_cast(f->fixture_data); + grpc_transport *transport; + GPR_ASSERT(!f->server); + f->server = grpc_server_create(server_args, NULL); + 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, 0); + server_setup_transport(f, transport); + grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { + gpr_free(f->fixture_data); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, + chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, +}; + +int main(int argc, char **argv) { + size_t i; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + /* force tracing on, with a value to force many + code paths in trace.c to be taken */ + gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all"); +#ifdef GRPC_POSIX_SOCKET + g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; +#else + g_fixture_slowdown_factor = 10; +#endif + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + grpc_exec_ctx_finish(&exec_ctx); + + GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); + GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); + GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c deleted file mode 100644 index 03566ead9b..0000000000 --- a/test/core/end2end/fixtures/h2_sockpair.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/client/http_client_filter.h" -#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/completion_queue.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -/* 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_end2end_test_fixture *f = ts; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); - grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, - grpc_server_get_channel_args(f->server)); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - grpc_end2end_test_fixture *f; - grpc_channel_args *client_args; -} sp_client_setup; - -static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport) { - sp_client_setup *cs = ts; - - cs->f->client = - grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, - GRPC_CLIENT_DIRECT_CHANNEL, transport); -} - -static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_endpoint_pair *sfd = gpr_malloc(sizeof(grpc_endpoint_pair)); - - grpc_end2end_test_fixture f; - memset(&f, 0, sizeof(f)); - f.fixture_data = sfd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); - - return f; -} - -static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_transport *transport; - sp_client_setup cs; - cs.client_args = client_args; - cs.f = f; - 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); - grpc_exec_ctx_finish(&exec_ctx); -} - -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_transport *transport; - GPR_ASSERT(!f->server); - f->server = grpc_server_create(server_args, NULL); - 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, 0); - server_setup_transport(f, transport); - grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { - gpr_free(f->fixture_data); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, - chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, -}; - -int main(int argc, char **argv) { - size_t i; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc new file mode 100644 index 0000000000..78b5ad8877 --- /dev/null +++ b/test/core/end2end/fixtures/h2_sockpair.cc @@ -0,0 +1,142 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/client/http_client_filter.h" +#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +/* 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_end2end_test_fixture *f = static_cast(ts); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); + grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, + grpc_server_get_channel_args(f->server)); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + grpc_end2end_test_fixture *f; + grpc_channel_args *client_args; +} sp_client_setup; + +static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, + grpc_transport *transport) { + sp_client_setup *cs = static_cast(ts); + + cs->f->client = + grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); +} + +static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_endpoint_pair *sfd = + static_cast(gpr_malloc(sizeof(grpc_endpoint_pair))); + + grpc_end2end_test_fixture f; + memset(&f, 0, sizeof(f)); + f.fixture_data = sfd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + *sfd = grpc_iomgr_create_endpoint_pair("fixture", NULL); + + return f; +} + +static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_transport *transport; + sp_client_setup cs; + cs.client_args = client_args; + cs.f = f; + 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); + grpc_exec_ctx_finish(&exec_ctx); +} + +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 = static_cast(f->fixture_data); + grpc_transport *transport; + GPR_ASSERT(!f->server); + f->server = grpc_server_create(server_args, NULL); + 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, 0); + server_setup_transport(f, transport); + grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { + gpr_free(f->fixture_data); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_socketpair, chttp2_init_client_socketpair, + chttp2_init_server_socketpair, chttp2_tear_down_socketpair}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c deleted file mode 100644 index c75a3876d5..0000000000 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/client/http_client_filter.h" -#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/completion_queue.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -/* 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_end2end_test_fixture *f = ts; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); - grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, - grpc_server_get_channel_args(f->server)); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - grpc_end2end_test_fixture *f; - grpc_channel_args *client_args; -} sp_client_setup; - -static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, - grpc_transport *transport) { - sp_client_setup *cs = ts; - - cs->f->client = - grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, - GRPC_CLIENT_DIRECT_CHANNEL, transport); -} - -static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_endpoint_pair *sfd = gpr_malloc(sizeof(grpc_endpoint_pair)); - - grpc_end2end_test_fixture f; - memset(&f, 0, sizeof(f)); - f.fixture_data = sfd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = 1}, - {.key = GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = 1}, - {.key = GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = 1}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - *sfd = grpc_iomgr_create_endpoint_pair("fixture", &args); - - return f; -} - -static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_pair *sfd = f->fixture_data; - grpc_transport *transport; - sp_client_setup cs; - cs.client_args = client_args; - cs.f = f; - 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); - grpc_exec_ctx_finish(&exec_ctx); -} - -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_transport *transport; - GPR_ASSERT(!f->server); - f->server = grpc_server_create(server_args, NULL); - 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, 0); - server_setup_transport(f, transport); - grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { - gpr_free(f->fixture_data); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"chttp2/socketpair_one_byte_at_a_time", - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, chttp2_create_fixture_socketpair, - chttp2_init_client_socketpair, chttp2_init_server_socketpair, - chttp2_tear_down_socketpair}, -}; - -int main(int argc, char **argv) { - size_t i; - - g_fixture_slowdown_factor = 2; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc new file mode 100644 index 0000000000..b144771f2a --- /dev/null +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc @@ -0,0 +1,156 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/client/http_client_filter.h" +#include "src/core/ext/filters/http/message_compress/message_compress_filter.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +/* 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_end2end_test_fixture *f = static_cast(ts); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); + grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, + grpc_server_get_channel_args(f->server)); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + grpc_end2end_test_fixture *f; + grpc_channel_args *client_args; +} sp_client_setup; + +static void client_setup_transport(grpc_exec_ctx *exec_ctx, void *ts, + grpc_transport *transport) { + sp_client_setup *cs = static_cast(ts); + + cs->f->client = + grpc_channel_create(exec_ctx, "socketpair-target", cs->client_args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); +} + +static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_endpoint_pair *sfd = + static_cast(gpr_malloc(sizeof(grpc_endpoint_pair))); + + grpc_end2end_test_fixture f; + memset(&f, 0, sizeof(f)); + f.fixture_data = sfd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + grpc_arg a[3]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = 1; + a[1].key = const_cast(GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE); + a[1].type = GRPC_ARG_INTEGER; + a[1].value.integer = 1; + a[2].key = const_cast(GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE); + a[2].type = GRPC_ARG_INTEGER; + a[2].value.integer = 1; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + *sfd = grpc_iomgr_create_endpoint_pair("fixture", &args); + + return f; +} + +static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_pair *sfd = static_cast(f->fixture_data); + grpc_transport *transport; + sp_client_setup cs; + cs.client_args = client_args; + cs.f = f; + 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); + grpc_exec_ctx_finish(&exec_ctx); +} + +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 = static_cast(f->fixture_data); + grpc_transport *transport; + GPR_ASSERT(!f->server); + f->server = grpc_server_create(server_args, NULL); + 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, 0); + server_setup_transport(f, transport); + grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) { + gpr_free(f->fixture_data); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/socketpair_one_byte_at_a_time", + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, chttp2_create_fixture_socketpair, + chttp2_init_client_socketpair, chttp2_init_server_socketpair, + chttp2_tear_down_socketpair}, +}; + +int main(int argc, char **argv) { + size_t i; + + g_fixture_slowdown_factor = 2; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c deleted file mode 100644 index 0bac464e69..0000000000 --- a/test/core/end2end/fixtures/h2_ssl.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/support/tmpfile.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_secure_fixture_data { - char *localaddr; -} fullstack_secure_fixture_data; - -static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -static void process_auth_failure(void *state, grpc_auth_context *ctx, - const grpc_metadata *md, size_t md_count, - grpc_process_auth_metadata_done_cb cb, - void *user_data) { - GPR_ASSERT(state == NULL); - cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); -} - -static void chttp2_init_client_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args, - grpc_channel_credentials *creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = - grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); - GPR_ASSERT(f->client != NULL); - grpc_channel_credentials_release(creds); -} - -static void chttp2_init_server_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args, - grpc_server_credentials *server_creds) { - fullstack_secure_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_secure_http2_port(f->server, ffd->localaddr, - server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(f->server); -} - -void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - gpr_free(ffd->localaddr); - gpr_free(ffd); -} - -static void chttp2_init_client_simple_ssl_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(NULL, NULL, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); - chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static int fail_server_auth_check(grpc_channel_args *server_args) { - size_t i; - if (server_args == NULL) return 0; - for (i = 0; i < server_args->num_args; i++) { - if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == - 0) { - return 1; - } - } - return 0; -} - -static void chttp2_init_server_simple_ssl_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { - grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); - if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; - grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); - } - chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); -} - -/* All test configurations */ - -static grpc_end2end_test_config configs[] = { - {"chttp2/simple_ssl_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_secure_fullstack, - chttp2_init_client_simple_ssl_secure_fullstack, - chttp2_init_server_simple_ssl_secure_fullstack, - chttp2_tear_down_secure_fullstack}, -}; - -int main(int argc, char **argv) { - size_t i; - FILE *roots_file; - size_t roots_size = strlen(test_root_cert); - char *roots_filename; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - - /* Set the SSL roots env var. */ - roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); - GPR_ASSERT(roots_filename != NULL); - GPR_ASSERT(roots_file != NULL); - GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); - fclose(roots_file); - gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - /* Cleanup. */ - remove(roots_filename); - gpr_free(roots_filename); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc new file mode 100644 index 0000000000..045a8b7f05 --- /dev/null +++ b/test/core/end2end/fixtures/h2_ssl.cc @@ -0,0 +1,188 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_secure_fixture_data { + char *localaddr; +} fullstack_secure_fixture_data; + +static grpc_end2end_test_fixture chttp2_create_fixture_secure_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_secure_fixture_data *ffd = + static_cast( + gpr_malloc(sizeof(fullstack_secure_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_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +static void process_auth_failure(void *state, grpc_auth_context *ctx, + const grpc_metadata *md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void *user_data) { + GPR_ASSERT(state == NULL); + cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); +} + +static void chttp2_init_client_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args, + grpc_channel_credentials *creds) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); + GPR_ASSERT(f->client != NULL); + grpc_channel_credentials_release(creds); +} + +static void chttp2_init_server_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args, + grpc_server_credentials *server_creds) { + fullstack_secure_fixture_data *ffd = + static_cast(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_secure_http2_port(f->server, ffd->localaddr, + server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(f->server); +} + +void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +static void chttp2_init_client_simple_ssl_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static int fail_server_auth_check(grpc_channel_args *server_args) { + size_t i; + if (server_args == NULL) return 0; + for (i = 0; i < server_args->num_args; i++) { + if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == + 0) { + return 1; + } + } + return 0; +} + +static void chttp2_init_server_simple_ssl_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { + grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); + if (fail_server_auth_check(server_args)) { + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; + grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); + } + chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); +} + +/* All test configurations */ + +static grpc_end2end_test_config configs[] = { + {"chttp2/simple_ssl_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_secure_fullstack, + chttp2_init_client_simple_ssl_secure_fullstack, + chttp2_init_server_simple_ssl_secure_fullstack, + chttp2_tear_down_secure_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + FILE *roots_file; + size_t roots_size = strlen(test_root_cert); + char *roots_filename; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + + /* Set the SSL roots env var. */ + roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); + GPR_ASSERT(roots_filename != NULL); + GPR_ASSERT(roots_file != NULL); + GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); + fclose(roots_file); + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); + + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + /* Cleanup. */ + remove(roots_filename); + gpr_free(roots_filename); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c deleted file mode 100644 index 8bc7183510..0000000000 --- a/test/core/end2end/fixtures/h2_ssl_proxy.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/support/tmpfile.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/end2end/fixtures/proxy.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct fullstack_secure_fixture_data { - grpc_end2end_proxy *proxy; -} fullstack_secure_fixture_data; - -static grpc_server *create_proxy_server(const char *port, - grpc_channel_args *server_args) { - grpc_server *s = grpc_server_create(server_args, NULL); - grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); - GPR_ASSERT(grpc_server_add_secure_http2_port(s, port, ssl_creds)); - grpc_server_credentials_release(ssl_creds); - return s; -} - -static grpc_channel *create_proxy_client(const char *target, - grpc_channel_args *client_args) { - grpc_channel *channel; - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(NULL, NULL, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); - channel = - grpc_secure_channel_create(ssl_creds, target, new_client_args, NULL); - grpc_channel_credentials_release(ssl_creds); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_exec_ctx_finish(&exec_ctx); - } - return channel; -} - -static const grpc_end2end_proxy_def proxy_def = {create_proxy_server, - create_proxy_client}; - -static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - fullstack_secure_fixture_data *ffd = - gpr_malloc(sizeof(fullstack_secure_fixture_data)); - memset(&f, 0, sizeof(f)); - - ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); - - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -static void process_auth_failure(void *state, grpc_auth_context *ctx, - const grpc_metadata *md, size_t md_count, - grpc_process_auth_metadata_done_cb cb, - void *user_data) { - GPR_ASSERT(state == NULL); - cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); -} - -static void chttp2_init_client_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args, - grpc_channel_credentials *creds) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = grpc_secure_channel_create( - creds, grpc_end2end_proxy_get_client_target(ffd->proxy), client_args, - NULL); - GPR_ASSERT(f->client != NULL); - grpc_channel_credentials_release(creds); -} - -static void chttp2_init_server_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args, - grpc_server_credentials *server_creds) { - fullstack_secure_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_secure_http2_port( - f->server, grpc_end2end_proxy_get_server_port(ffd->proxy), server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(f->server); -} - -void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { - fullstack_secure_fixture_data *ffd = f->fixture_data; - grpc_end2end_proxy_destroy(ffd->proxy); - gpr_free(ffd); -} - -static void chttp2_init_client_simple_ssl_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(NULL, NULL, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); - chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static int fail_server_auth_check(grpc_channel_args *server_args) { - size_t i; - if (server_args == NULL) return 0; - for (i = 0; i < server_args->num_args; i++) { - if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == - 0) { - return 1; - } - } - return 0; -} - -static void chttp2_init_server_simple_ssl_secure_fullstack( - grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { - grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); - if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; - grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); - } - chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); -} - -/* All test configurations */ - -static grpc_end2end_test_config configs[] = { - {"chttp2/simple_ssl_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - chttp2_create_fixture_secure_fullstack, - chttp2_init_client_simple_ssl_secure_fullstack, - chttp2_init_server_simple_ssl_secure_fullstack, - chttp2_tear_down_secure_fullstack}, -}; - -int main(int argc, char **argv) { - size_t i; - FILE *roots_file; - size_t roots_size = strlen(test_root_cert); - char *roots_filename; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - - /* Set the SSL roots env var. */ - roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); - GPR_ASSERT(roots_filename != NULL); - GPR_ASSERT(roots_file != NULL); - GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); - fclose(roots_file); - gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - /* Cleanup. */ - remove(roots_filename); - gpr_free(roots_filename); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc new file mode 100644 index 0000000000..b9b68c8780 --- /dev/null +++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc @@ -0,0 +1,227 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/end2end/fixtures/proxy.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct fullstack_secure_fixture_data { + grpc_end2end_proxy *proxy; +} fullstack_secure_fixture_data; + +static grpc_server *create_proxy_server(const char *port, + grpc_channel_args *server_args) { + grpc_server *s = grpc_server_create(server_args, NULL); + grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(s, port, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + return s; +} + +static grpc_channel *create_proxy_client(const char *target, + grpc_channel_args *client_args) { + grpc_channel *channel; + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + channel = + grpc_secure_channel_create(ssl_creds, target, new_client_args, NULL); + grpc_channel_credentials_release(ssl_creds); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } + return channel; +} + +static const grpc_end2end_proxy_def proxy_def = {create_proxy_server, + create_proxy_client}; + +static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + fullstack_secure_fixture_data *ffd = + static_cast( + gpr_malloc(sizeof(fullstack_secure_fixture_data))); + memset(&f, 0, sizeof(f)); + + ffd->proxy = grpc_end2end_proxy_create(&proxy_def, client_args, server_args); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +static void process_auth_failure(void *state, grpc_auth_context *ctx, + const grpc_metadata *md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, + void *user_data) { + GPR_ASSERT(state == NULL); + cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); +} + +static void chttp2_init_client_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args, + grpc_channel_credentials *creds) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + f->client = grpc_secure_channel_create( + creds, grpc_end2end_proxy_get_client_target(ffd->proxy), client_args, + NULL); + GPR_ASSERT(f->client != NULL); + grpc_channel_credentials_release(creds); +} + +static void chttp2_init_server_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args, + grpc_server_credentials *server_creds) { + fullstack_secure_fixture_data *ffd = + static_cast(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_secure_http2_port( + f->server, grpc_end2end_proxy_get_server_port(ffd->proxy), server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(f->server); +} + +void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { + fullstack_secure_fixture_data *ffd = + static_cast(f->fixture_data); + grpc_end2end_proxy_destroy(ffd->proxy); + gpr_free(ffd); +} + +static void chttp2_init_client_simple_ssl_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static int fail_server_auth_check(grpc_channel_args *server_args) { + size_t i; + if (server_args == NULL) return 0; + for (i = 0; i < server_args->num_args; i++) { + if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == + 0) { + return 1; + } + } + return 0; +} + +static void chttp2_init_server_simple_ssl_secure_fullstack( + grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { + grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); + if (fail_server_auth_check(server_args)) { + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; + grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); + } + chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); +} + +/* All test configurations */ + +static grpc_end2end_test_config configs[] = { + {"chttp2/simple_ssl_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + chttp2_create_fixture_secure_fullstack, + chttp2_init_client_simple_ssl_secure_fullstack, + chttp2_init_server_simple_ssl_secure_fullstack, + chttp2_tear_down_secure_fullstack}, +}; + +int main(int argc, char **argv) { + size_t i; + FILE *roots_file; + size_t roots_size = strlen(test_root_cert); + char *roots_filename; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + + /* Set the SSL roots env var. */ + roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); + GPR_ASSERT(roots_filename != NULL); + GPR_ASSERT(roots_file != NULL); + GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); + fclose(roots_file); + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); + + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + /* Cleanup. */ + remove(roots_filename); + gpr_free(roots_filename); + + return 0; +} diff --git a/test/core/end2end/fixtures/h2_uds.c b/test/core/end2end/fixtures/h2_uds.c deleted file mode 100644 index 05a31985e7..0000000000 --- a/test/core/end2end/fixtures/h2_uds.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.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 int unique = 1; - -static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); - memset(&f, 0, sizeof(f)); - - gpr_asprintf(&ffd->localaddr, "unix:/tmp/grpc_fullstack_test.%d.%d", getpid(), - unique++); - - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(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_uds", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - 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_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc new file mode 100644 index 0000000000..f9336b5edc --- /dev/null +++ b/test/core/end2end/fixtures/h2_uds.cc @@ -0,0 +1,115 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.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 int unique = 1; + +static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + fullstack_fixture_data *ffd = static_cast( + gpr_malloc(sizeof(fullstack_fixture_data))); + memset(&f, 0, sizeof(f)); + + gpr_asprintf(&ffd->localaddr, "unix:/tmp/grpc_fullstack_test.%d.%d", getpid(), + unique++); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + fullstack_fixture_data *ffd = + static_cast(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 = + static_cast(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 = + static_cast(f->fixture_data); + gpr_free(ffd->localaddr); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"chttp2/fullstack_uds", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, + 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_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c deleted file mode 100644 index d29401fdc3..0000000000 --- a/test/core/end2end/fixtures/http_proxy_fixture.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/fixtures/http_proxy_fixture.h" - -#include "src/core/lib/iomgr/sockaddr.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/http/parser.h" -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/combiner.h" -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/pollset.h" -#include "src/core/lib/iomgr/pollset_set.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/lib/iomgr/timer.h" -#include "src/core/lib/slice/b64.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/port.h" - -struct grpc_end2end_http_proxy { - char* proxy_name; - gpr_thd_id thd; - grpc_tcp_server* server; - grpc_channel_args* channel_args; - gpr_mu* mu; - grpc_pollset* pollset; - gpr_refcount users; - - grpc_combiner* combiner; -}; - -// -// Connection handling -// - -typedef struct proxy_connection { - grpc_end2end_http_proxy* proxy; - - grpc_endpoint* client_endpoint; - grpc_endpoint* server_endpoint; - - gpr_refcount refcount; - - grpc_pollset_set* pollset_set; - - grpc_closure on_read_request_done; - grpc_closure on_server_connect_done; - grpc_closure on_write_response_done; - grpc_closure on_client_read_done; - grpc_closure on_client_write_done; - grpc_closure on_server_read_done; - grpc_closure on_server_write_done; - - grpc_slice_buffer client_read_buffer; - grpc_slice_buffer client_deferred_write_buffer; - grpc_slice_buffer client_write_buffer; - grpc_slice_buffer server_read_buffer; - grpc_slice_buffer server_deferred_write_buffer; - grpc_slice_buffer server_write_buffer; - - grpc_http_parser http_parser; - grpc_http_request http_request; -} proxy_connection; - -static void proxy_connection_ref(proxy_connection* conn, const char* reason) { - gpr_ref(&conn->refcount); -} - -// Helper function to destroy the proxy connection. -static void proxy_connection_unref(grpc_exec_ctx* exec_ctx, - proxy_connection* conn, const char* reason) { - if (gpr_unref(&conn->refcount)) { - gpr_log(GPR_DEBUG, "endpoints: %p %p", conn->client_endpoint, - conn->server_endpoint); - grpc_endpoint_destroy(exec_ctx, conn->client_endpoint); - if (conn->server_endpoint != NULL) { - grpc_endpoint_destroy(exec_ctx, conn->server_endpoint); - } - grpc_pollset_set_destroy(exec_ctx, conn->pollset_set); - grpc_slice_buffer_destroy_internal(exec_ctx, &conn->client_read_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, - &conn->client_deferred_write_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &conn->client_write_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &conn->server_read_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, - &conn->server_deferred_write_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &conn->server_write_buffer); - grpc_http_parser_destroy(&conn->http_parser); - grpc_http_request_destroy(&conn->http_request); - gpr_unref(&conn->proxy->users); - gpr_free(conn); - } -} - -// Helper function to shut down the proxy connection. -// Does NOT take ownership of a reference to error. -static void proxy_connection_failed(grpc_exec_ctx* exec_ctx, - proxy_connection* conn, bool is_client, - const char* prefix, grpc_error* error) { - const char* msg = grpc_error_string(error); - gpr_log(GPR_INFO, "%s: %s", prefix, msg); - - grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint, - GRPC_ERROR_REF(error)); - if (conn->server_endpoint != NULL) { - grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint, - GRPC_ERROR_REF(error)); - } - proxy_connection_unref(exec_ctx, conn, "conn_failed"); -} - -// Callback for writing proxy data to the client. -static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy client write", error); - return; - } - // Clear write buffer (the data we just wrote). - grpc_slice_buffer_reset_and_unref(&conn->client_write_buffer); - // If more data was read from the server since we started this write, - // write that data now. - if (conn->client_deferred_write_buffer.length > 0) { - grpc_slice_buffer_move_into(&conn->client_deferred_write_buffer, - &conn->client_write_buffer); - grpc_endpoint_write(exec_ctx, conn->client_endpoint, - &conn->client_write_buffer, - &conn->on_client_write_done); - } else { - // No more writes. Unref the connection. - proxy_connection_unref(exec_ctx, conn, "write_done"); - } -} - -// Callback for writing proxy data to the backend server. -static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, false /* is_client */, - "HTTP proxy server write", error); - return; - } - // Clear write buffer (the data we just wrote). - grpc_slice_buffer_reset_and_unref(&conn->server_write_buffer); - // If more data was read from the client since we started this write, - // write that data now. - if (conn->server_deferred_write_buffer.length > 0) { - grpc_slice_buffer_move_into(&conn->server_deferred_write_buffer, - &conn->server_write_buffer); - grpc_endpoint_write(exec_ctx, conn->server_endpoint, - &conn->server_write_buffer, - &conn->on_server_write_done); - } else { - // No more writes. Unref the connection. - proxy_connection_unref(exec_ctx, conn, "server_write"); - } -} - -// Callback for reading data from the client, which will be proxied to -// the backend server. -static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy client read", error); - return; - } - // If there is already a pending write (i.e., server_write_buffer is - // not empty), then move the read data into server_deferred_write_buffer, - // and the next write will be requested in on_server_write_done(), when - // the current write is finished. - // - // Otherwise, move the read data into the write buffer and write it. - if (conn->server_write_buffer.length > 0) { - grpc_slice_buffer_move_into(&conn->client_read_buffer, - &conn->server_deferred_write_buffer); - } else { - grpc_slice_buffer_move_into(&conn->client_read_buffer, - &conn->server_write_buffer); - proxy_connection_ref(conn, "client_read"); - grpc_endpoint_write(exec_ctx, conn->server_endpoint, - &conn->server_write_buffer, - &conn->on_server_write_done); - } - // Read more data. - grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, - &conn->on_client_read_done); -} - -// Callback for reading data from the backend server, which will be -// proxied to the client. -static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, false /* is_client */, - "HTTP proxy server read", error); - return; - } - // If there is already a pending write (i.e., client_write_buffer is - // not empty), then move the read data into client_deferred_write_buffer, - // and the next write will be requested in on_client_write_done(), when - // the current write is finished. - // - // Otherwise, move the read data into the write buffer and write it. - if (conn->client_write_buffer.length > 0) { - grpc_slice_buffer_move_into(&conn->server_read_buffer, - &conn->client_deferred_write_buffer); - } else { - grpc_slice_buffer_move_into(&conn->server_read_buffer, - &conn->client_write_buffer); - proxy_connection_ref(conn, "server_read"); - grpc_endpoint_write(exec_ctx, conn->client_endpoint, - &conn->client_write_buffer, - &conn->on_client_write_done); - } - // Read more data. - grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, - &conn->on_server_read_done); -} - -// Callback to write the HTTP response for the CONNECT request. -static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy write response", error); - return; - } - // Clear write buffer. - grpc_slice_buffer_reset_and_unref(&conn->client_write_buffer); - // Start reading from both client and server. One of the read - // requests inherits our ref to conn, but we need to take a new ref - // for the other one. - proxy_connection_ref(conn, "client_read"); - proxy_connection_ref(conn, "server_read"); - proxy_connection_unref(exec_ctx, conn, "write_response"); - grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, - &conn->on_client_read_done); - grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, - &conn->on_server_read_done); -} - -// Callback to connect to the backend server specified by the HTTP -// CONNECT request. -static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - if (error != GRPC_ERROR_NONE) { - // TODO(roth): Technically, in this case, we should handle the error - // by returning an HTTP response to the client indicating that the - // connection failed. However, for the purposes of this test code, - // it's fine to pretend this is a client-side error, which will - // cause the client connection to be dropped. - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy server connect", error); - return; - } - // We've established a connection, so send back a 200 response code to - // the client. - // The write callback inherits our reference to conn. - grpc_slice slice = - grpc_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); - grpc_slice_buffer_add(&conn->client_write_buffer, slice); - grpc_endpoint_write(exec_ctx, conn->client_endpoint, - &conn->client_write_buffer, - &conn->on_write_response_done); -} - -/** - * Parses the proxy auth header value to check if it matches :- - * Basic - * Returns true if it matches, false otherwise - */ -static bool proxy_auth_header_matches(grpc_exec_ctx* exec_ctx, - char* proxy_auth_header_val, - char* expected_cred) { - GPR_ASSERT(proxy_auth_header_val != NULL); - GPR_ASSERT(expected_cred != NULL); - if (strncmp(proxy_auth_header_val, "Basic ", 6) != 0) { - return false; - } - proxy_auth_header_val += 6; - grpc_slice decoded_slice = - grpc_base64_decode(exec_ctx, proxy_auth_header_val, 0); - const bool header_matches = - grpc_slice_str_cmp(decoded_slice, expected_cred) == 0; - grpc_slice_unref_internal(exec_ctx, decoded_slice); - return header_matches; -} - -// Callback to read the HTTP CONNECT request. -// TODO(roth): Technically, for any of the failure modes handled by this -// function, we should handle the error by returning an HTTP response to -// the client indicating that the request failed. However, for the purposes -// of this test code, it's fine to pretend this is a client-side error, -// which will cause the client connection to be dropped. -static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - proxy_connection* conn = (proxy_connection*)arg; - gpr_log(GPR_DEBUG, "on_read_request_done: %p %s", conn, - grpc_error_string(error)); - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy read request", error); - return; - } - // Read request and feed it to the parser. - for (size_t i = 0; i < conn->client_read_buffer.count; ++i) { - if (GRPC_SLICE_LENGTH(conn->client_read_buffer.slices[i]) > 0) { - error = grpc_http_parser_parse(&conn->http_parser, - conn->client_read_buffer.slices[i], NULL); - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy request parse", error); - GRPC_ERROR_UNREF(error); - return; - } - } - } - grpc_slice_buffer_reset_and_unref(&conn->client_read_buffer); - // If we're not done reading the request, read more data. - if (conn->http_parser.state != GRPC_HTTP_BODY) { - grpc_endpoint_read(exec_ctx, conn->client_endpoint, - &conn->client_read_buffer, &conn->on_read_request_done); - return; - } - // Make sure we got a CONNECT request. - if (strcmp(conn->http_request.method, "CONNECT") != 0) { - char* msg; - gpr_asprintf(&msg, "HTTP proxy got request method %s", - conn->http_request.method); - error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); - gpr_free(msg); - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy read request", error); - GRPC_ERROR_UNREF(error); - return; - } - // If proxy auth is being used, check if the header is present and as expected - const grpc_arg* proxy_auth_arg = grpc_channel_args_find( - conn->proxy->channel_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); - if (proxy_auth_arg != NULL && proxy_auth_arg->type == GRPC_ARG_STRING) { - bool client_authenticated = false; - for (size_t i = 0; i < conn->http_request.hdr_count; i++) { - if (strcmp(conn->http_request.hdrs[i].key, "Proxy-Authorization") == 0) { - client_authenticated = proxy_auth_header_matches( - exec_ctx, conn->http_request.hdrs[i].value, - proxy_auth_arg->value.string); - break; - } - } - if (!client_authenticated) { - const char* msg = "HTTP Connect could not verify authentication"; - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(msg); - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy read request", error); - GRPC_ERROR_UNREF(error); - return; - } - } - // Resolve address. - grpc_resolved_addresses* resolved_addresses = NULL; - error = grpc_blocking_resolve_address(conn->http_request.path, "80", - &resolved_addresses); - if (error != GRPC_ERROR_NONE) { - proxy_connection_failed(exec_ctx, conn, true /* is_client */, - "HTTP proxy DNS lookup", error); - GRPC_ERROR_UNREF(error); - return; - } - GPR_ASSERT(resolved_addresses->naddrs >= 1); - // Connect to requested address. - // The connection callback inherits our reference to conn. - const grpc_millis deadline = - grpc_exec_ctx_now(exec_ctx) + 10 * GPR_MS_PER_SEC; - grpc_tcp_client_connect(exec_ctx, &conn->on_server_connect_done, - &conn->server_endpoint, conn->pollset_set, NULL, - &resolved_addresses->addrs[0], deadline); - grpc_resolved_addresses_destroy(resolved_addresses); -} - -static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, - grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, - grpc_tcp_server_acceptor* acceptor) { - gpr_free(acceptor); - grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; - // Instantiate proxy_connection. - proxy_connection* conn = (proxy_connection*)gpr_zalloc(sizeof(*conn)); - gpr_ref(&proxy->users); - conn->client_endpoint = endpoint; - conn->proxy = proxy; - gpr_ref_init(&conn->refcount, 1); - conn->pollset_set = grpc_pollset_set_create(); - grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset); - grpc_endpoint_add_to_pollset_set(exec_ctx, endpoint, conn->pollset_set); - GRPC_CLOSURE_INIT(&conn->on_read_request_done, on_read_request_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_server_connect_done, on_server_connect_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_write_response_done, on_write_response_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_client_read_done, on_client_read_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_client_write_done, on_client_write_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_server_read_done, on_server_read_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - GRPC_CLOSURE_INIT(&conn->on_server_write_done, on_server_write_done, conn, - grpc_combiner_scheduler(conn->proxy->combiner)); - grpc_slice_buffer_init(&conn->client_read_buffer); - grpc_slice_buffer_init(&conn->client_deferred_write_buffer); - grpc_slice_buffer_init(&conn->client_write_buffer); - grpc_slice_buffer_init(&conn->server_read_buffer); - grpc_slice_buffer_init(&conn->server_deferred_write_buffer); - grpc_slice_buffer_init(&conn->server_write_buffer); - grpc_http_parser_init(&conn->http_parser, GRPC_HTTP_REQUEST, - &conn->http_request); - grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, - &conn->on_read_request_done); -} - -// -// Proxy class -// - -static void thread_main(void* arg) { - grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - do { - gpr_ref(&proxy->users); - grpc_pollset_worker* worker = NULL; - gpr_mu_lock(proxy->mu); - GRPC_LOG_IF_ERROR( - "grpc_pollset_work", - grpc_pollset_work(&exec_ctx, proxy->pollset, &worker, - grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC)); - gpr_mu_unlock(proxy->mu); - grpc_exec_ctx_flush(&exec_ctx); - } while (!gpr_unref(&proxy->users)); - grpc_exec_ctx_finish(&exec_ctx); -} - -grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( - grpc_channel_args* args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_end2end_http_proxy* proxy = - (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy)); - memset(proxy, 0, sizeof(*proxy)); - proxy->combiner = grpc_combiner_create(); - gpr_ref_init(&proxy->users, 1); - // Construct proxy address. - const int proxy_port = grpc_pick_unused_port_or_die(); - gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); - gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); - // Create TCP server. - proxy->channel_args = grpc_channel_args_copy(args); - grpc_error* error = grpc_tcp_server_create( - &exec_ctx, NULL, proxy->channel_args, &proxy->server); - GPR_ASSERT(error == GRPC_ERROR_NONE); - // Bind to port. - grpc_resolved_address resolved_addr; - struct sockaddr_in* addr = (struct sockaddr_in*)resolved_addr.addr; - memset(&resolved_addr, 0, sizeof(resolved_addr)); - addr->sin_family = AF_INET; - grpc_sockaddr_set_port(&resolved_addr, proxy_port); - int port; - error = grpc_tcp_server_add_port(proxy->server, &resolved_addr, &port); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(port == proxy_port); - // Start server. - proxy->pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(proxy->pollset, &proxy->mu); - grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept, - proxy); - grpc_exec_ctx_finish(&exec_ctx); - // Start proxy thread. - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); - return proxy; -} - -static void destroy_pollset(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - grpc_pollset* pollset = (grpc_pollset*)arg; - grpc_pollset_destroy(exec_ctx, pollset); - gpr_free(pollset); -} - -void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { - gpr_unref(&proxy->users); // Signal proxy thread to shutdown. - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_thd_join(proxy->thd); - grpc_tcp_server_shutdown_listeners(&exec_ctx, proxy->server); - grpc_tcp_server_unref(&exec_ctx, proxy->server); - gpr_free(proxy->proxy_name); - grpc_channel_args_destroy(&exec_ctx, proxy->channel_args); - grpc_pollset_shutdown(&exec_ctx, proxy->pollset, - GRPC_CLOSURE_CREATE(destroy_pollset, proxy->pollset, - grpc_schedule_on_exec_ctx)); - GRPC_COMBINER_UNREF(&exec_ctx, proxy->combiner, "test"); - gpr_free(proxy); - grpc_exec_ctx_finish(&exec_ctx); -} - -const char* grpc_end2end_http_proxy_get_proxy_name( - grpc_end2end_http_proxy* proxy) { - return proxy->proxy_name; -} diff --git a/test/core/end2end/fixtures/http_proxy_fixture.cc b/test/core/end2end/fixtures/http_proxy_fixture.cc new file mode 100644 index 0000000000..d29401fdc3 --- /dev/null +++ b/test/core/end2end/fixtures/http_proxy_fixture.cc @@ -0,0 +1,550 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/fixtures/http_proxy_fixture.h" + +#include "src/core/lib/iomgr/sockaddr.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/iomgr/tcp_server.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/slice/b64.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +struct grpc_end2end_http_proxy { + char* proxy_name; + gpr_thd_id thd; + grpc_tcp_server* server; + grpc_channel_args* channel_args; + gpr_mu* mu; + grpc_pollset* pollset; + gpr_refcount users; + + grpc_combiner* combiner; +}; + +// +// Connection handling +// + +typedef struct proxy_connection { + grpc_end2end_http_proxy* proxy; + + grpc_endpoint* client_endpoint; + grpc_endpoint* server_endpoint; + + gpr_refcount refcount; + + grpc_pollset_set* pollset_set; + + grpc_closure on_read_request_done; + grpc_closure on_server_connect_done; + grpc_closure on_write_response_done; + grpc_closure on_client_read_done; + grpc_closure on_client_write_done; + grpc_closure on_server_read_done; + grpc_closure on_server_write_done; + + grpc_slice_buffer client_read_buffer; + grpc_slice_buffer client_deferred_write_buffer; + grpc_slice_buffer client_write_buffer; + grpc_slice_buffer server_read_buffer; + grpc_slice_buffer server_deferred_write_buffer; + grpc_slice_buffer server_write_buffer; + + grpc_http_parser http_parser; + grpc_http_request http_request; +} proxy_connection; + +static void proxy_connection_ref(proxy_connection* conn, const char* reason) { + gpr_ref(&conn->refcount); +} + +// Helper function to destroy the proxy connection. +static void proxy_connection_unref(grpc_exec_ctx* exec_ctx, + proxy_connection* conn, const char* reason) { + if (gpr_unref(&conn->refcount)) { + gpr_log(GPR_DEBUG, "endpoints: %p %p", conn->client_endpoint, + conn->server_endpoint); + grpc_endpoint_destroy(exec_ctx, conn->client_endpoint); + if (conn->server_endpoint != NULL) { + grpc_endpoint_destroy(exec_ctx, conn->server_endpoint); + } + grpc_pollset_set_destroy(exec_ctx, conn->pollset_set); + grpc_slice_buffer_destroy_internal(exec_ctx, &conn->client_read_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, + &conn->client_deferred_write_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &conn->client_write_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &conn->server_read_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, + &conn->server_deferred_write_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &conn->server_write_buffer); + grpc_http_parser_destroy(&conn->http_parser); + grpc_http_request_destroy(&conn->http_request); + gpr_unref(&conn->proxy->users); + gpr_free(conn); + } +} + +// Helper function to shut down the proxy connection. +// Does NOT take ownership of a reference to error. +static void proxy_connection_failed(grpc_exec_ctx* exec_ctx, + proxy_connection* conn, bool is_client, + const char* prefix, grpc_error* error) { + const char* msg = grpc_error_string(error); + gpr_log(GPR_INFO, "%s: %s", prefix, msg); + + grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint, + GRPC_ERROR_REF(error)); + if (conn->server_endpoint != NULL) { + grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint, + GRPC_ERROR_REF(error)); + } + proxy_connection_unref(exec_ctx, conn, "conn_failed"); +} + +// Callback for writing proxy data to the client. +static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy client write", error); + return; + } + // Clear write buffer (the data we just wrote). + grpc_slice_buffer_reset_and_unref(&conn->client_write_buffer); + // If more data was read from the server since we started this write, + // write that data now. + if (conn->client_deferred_write_buffer.length > 0) { + grpc_slice_buffer_move_into(&conn->client_deferred_write_buffer, + &conn->client_write_buffer); + grpc_endpoint_write(exec_ctx, conn->client_endpoint, + &conn->client_write_buffer, + &conn->on_client_write_done); + } else { + // No more writes. Unref the connection. + proxy_connection_unref(exec_ctx, conn, "write_done"); + } +} + +// Callback for writing proxy data to the backend server. +static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, false /* is_client */, + "HTTP proxy server write", error); + return; + } + // Clear write buffer (the data we just wrote). + grpc_slice_buffer_reset_and_unref(&conn->server_write_buffer); + // If more data was read from the client since we started this write, + // write that data now. + if (conn->server_deferred_write_buffer.length > 0) { + grpc_slice_buffer_move_into(&conn->server_deferred_write_buffer, + &conn->server_write_buffer); + grpc_endpoint_write(exec_ctx, conn->server_endpoint, + &conn->server_write_buffer, + &conn->on_server_write_done); + } else { + // No more writes. Unref the connection. + proxy_connection_unref(exec_ctx, conn, "server_write"); + } +} + +// Callback for reading data from the client, which will be proxied to +// the backend server. +static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy client read", error); + return; + } + // If there is already a pending write (i.e., server_write_buffer is + // not empty), then move the read data into server_deferred_write_buffer, + // and the next write will be requested in on_server_write_done(), when + // the current write is finished. + // + // Otherwise, move the read data into the write buffer and write it. + if (conn->server_write_buffer.length > 0) { + grpc_slice_buffer_move_into(&conn->client_read_buffer, + &conn->server_deferred_write_buffer); + } else { + grpc_slice_buffer_move_into(&conn->client_read_buffer, + &conn->server_write_buffer); + proxy_connection_ref(conn, "client_read"); + grpc_endpoint_write(exec_ctx, conn->server_endpoint, + &conn->server_write_buffer, + &conn->on_server_write_done); + } + // Read more data. + grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, + &conn->on_client_read_done); +} + +// Callback for reading data from the backend server, which will be +// proxied to the client. +static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, false /* is_client */, + "HTTP proxy server read", error); + return; + } + // If there is already a pending write (i.e., client_write_buffer is + // not empty), then move the read data into client_deferred_write_buffer, + // and the next write will be requested in on_client_write_done(), when + // the current write is finished. + // + // Otherwise, move the read data into the write buffer and write it. + if (conn->client_write_buffer.length > 0) { + grpc_slice_buffer_move_into(&conn->server_read_buffer, + &conn->client_deferred_write_buffer); + } else { + grpc_slice_buffer_move_into(&conn->server_read_buffer, + &conn->client_write_buffer); + proxy_connection_ref(conn, "server_read"); + grpc_endpoint_write(exec_ctx, conn->client_endpoint, + &conn->client_write_buffer, + &conn->on_client_write_done); + } + // Read more data. + grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, + &conn->on_server_read_done); +} + +// Callback to write the HTTP response for the CONNECT request. +static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy write response", error); + return; + } + // Clear write buffer. + grpc_slice_buffer_reset_and_unref(&conn->client_write_buffer); + // Start reading from both client and server. One of the read + // requests inherits our ref to conn, but we need to take a new ref + // for the other one. + proxy_connection_ref(conn, "client_read"); + proxy_connection_ref(conn, "server_read"); + proxy_connection_unref(exec_ctx, conn, "write_response"); + grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, + &conn->on_client_read_done); + grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, + &conn->on_server_read_done); +} + +// Callback to connect to the backend server specified by the HTTP +// CONNECT request. +static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + if (error != GRPC_ERROR_NONE) { + // TODO(roth): Technically, in this case, we should handle the error + // by returning an HTTP response to the client indicating that the + // connection failed. However, for the purposes of this test code, + // it's fine to pretend this is a client-side error, which will + // cause the client connection to be dropped. + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy server connect", error); + return; + } + // We've established a connection, so send back a 200 response code to + // the client. + // The write callback inherits our reference to conn. + grpc_slice slice = + grpc_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); + grpc_slice_buffer_add(&conn->client_write_buffer, slice); + grpc_endpoint_write(exec_ctx, conn->client_endpoint, + &conn->client_write_buffer, + &conn->on_write_response_done); +} + +/** + * Parses the proxy auth header value to check if it matches :- + * Basic + * Returns true if it matches, false otherwise + */ +static bool proxy_auth_header_matches(grpc_exec_ctx* exec_ctx, + char* proxy_auth_header_val, + char* expected_cred) { + GPR_ASSERT(proxy_auth_header_val != NULL); + GPR_ASSERT(expected_cred != NULL); + if (strncmp(proxy_auth_header_val, "Basic ", 6) != 0) { + return false; + } + proxy_auth_header_val += 6; + grpc_slice decoded_slice = + grpc_base64_decode(exec_ctx, proxy_auth_header_val, 0); + const bool header_matches = + grpc_slice_str_cmp(decoded_slice, expected_cred) == 0; + grpc_slice_unref_internal(exec_ctx, decoded_slice); + return header_matches; +} + +// Callback to read the HTTP CONNECT request. +// TODO(roth): Technically, for any of the failure modes handled by this +// function, we should handle the error by returning an HTTP response to +// the client indicating that the request failed. However, for the purposes +// of this test code, it's fine to pretend this is a client-side error, +// which will cause the client connection to be dropped. +static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + proxy_connection* conn = (proxy_connection*)arg; + gpr_log(GPR_DEBUG, "on_read_request_done: %p %s", conn, + grpc_error_string(error)); + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy read request", error); + return; + } + // Read request and feed it to the parser. + for (size_t i = 0; i < conn->client_read_buffer.count; ++i) { + if (GRPC_SLICE_LENGTH(conn->client_read_buffer.slices[i]) > 0) { + error = grpc_http_parser_parse(&conn->http_parser, + conn->client_read_buffer.slices[i], NULL); + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy request parse", error); + GRPC_ERROR_UNREF(error); + return; + } + } + } + grpc_slice_buffer_reset_and_unref(&conn->client_read_buffer); + // If we're not done reading the request, read more data. + if (conn->http_parser.state != GRPC_HTTP_BODY) { + grpc_endpoint_read(exec_ctx, conn->client_endpoint, + &conn->client_read_buffer, &conn->on_read_request_done); + return; + } + // Make sure we got a CONNECT request. + if (strcmp(conn->http_request.method, "CONNECT") != 0) { + char* msg; + gpr_asprintf(&msg, "HTTP proxy got request method %s", + conn->http_request.method); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + gpr_free(msg); + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy read request", error); + GRPC_ERROR_UNREF(error); + return; + } + // If proxy auth is being used, check if the header is present and as expected + const grpc_arg* proxy_auth_arg = grpc_channel_args_find( + conn->proxy->channel_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + if (proxy_auth_arg != NULL && proxy_auth_arg->type == GRPC_ARG_STRING) { + bool client_authenticated = false; + for (size_t i = 0; i < conn->http_request.hdr_count; i++) { + if (strcmp(conn->http_request.hdrs[i].key, "Proxy-Authorization") == 0) { + client_authenticated = proxy_auth_header_matches( + exec_ctx, conn->http_request.hdrs[i].value, + proxy_auth_arg->value.string); + break; + } + } + if (!client_authenticated) { + const char* msg = "HTTP Connect could not verify authentication"; + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(msg); + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy read request", error); + GRPC_ERROR_UNREF(error); + return; + } + } + // Resolve address. + grpc_resolved_addresses* resolved_addresses = NULL; + error = grpc_blocking_resolve_address(conn->http_request.path, "80", + &resolved_addresses); + if (error != GRPC_ERROR_NONE) { + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy DNS lookup", error); + GRPC_ERROR_UNREF(error); + return; + } + GPR_ASSERT(resolved_addresses->naddrs >= 1); + // Connect to requested address. + // The connection callback inherits our reference to conn. + const grpc_millis deadline = + grpc_exec_ctx_now(exec_ctx) + 10 * GPR_MS_PER_SEC; + grpc_tcp_client_connect(exec_ctx, &conn->on_server_connect_done, + &conn->server_endpoint, conn->pollset_set, NULL, + &resolved_addresses->addrs[0], deadline); + grpc_resolved_addresses_destroy(resolved_addresses); +} + +static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, + grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, + grpc_tcp_server_acceptor* acceptor) { + gpr_free(acceptor); + grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; + // Instantiate proxy_connection. + proxy_connection* conn = (proxy_connection*)gpr_zalloc(sizeof(*conn)); + gpr_ref(&proxy->users); + conn->client_endpoint = endpoint; + conn->proxy = proxy; + gpr_ref_init(&conn->refcount, 1); + conn->pollset_set = grpc_pollset_set_create(); + grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset); + grpc_endpoint_add_to_pollset_set(exec_ctx, endpoint, conn->pollset_set); + GRPC_CLOSURE_INIT(&conn->on_read_request_done, on_read_request_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_server_connect_done, on_server_connect_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_write_response_done, on_write_response_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_client_read_done, on_client_read_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_client_write_done, on_client_write_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_server_read_done, on_server_read_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + GRPC_CLOSURE_INIT(&conn->on_server_write_done, on_server_write_done, conn, + grpc_combiner_scheduler(conn->proxy->combiner)); + grpc_slice_buffer_init(&conn->client_read_buffer); + grpc_slice_buffer_init(&conn->client_deferred_write_buffer); + grpc_slice_buffer_init(&conn->client_write_buffer); + grpc_slice_buffer_init(&conn->server_read_buffer); + grpc_slice_buffer_init(&conn->server_deferred_write_buffer); + grpc_slice_buffer_init(&conn->server_write_buffer); + grpc_http_parser_init(&conn->http_parser, GRPC_HTTP_REQUEST, + &conn->http_request); + grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, + &conn->on_read_request_done); +} + +// +// Proxy class +// + +static void thread_main(void* arg) { + grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + do { + gpr_ref(&proxy->users); + grpc_pollset_worker* worker = NULL; + gpr_mu_lock(proxy->mu); + GRPC_LOG_IF_ERROR( + "grpc_pollset_work", + grpc_pollset_work(&exec_ctx, proxy->pollset, &worker, + grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC)); + gpr_mu_unlock(proxy->mu); + grpc_exec_ctx_flush(&exec_ctx); + } while (!gpr_unref(&proxy->users)); + grpc_exec_ctx_finish(&exec_ctx); +} + +grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( + grpc_channel_args* args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_end2end_http_proxy* proxy = + (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy)); + memset(proxy, 0, sizeof(*proxy)); + proxy->combiner = grpc_combiner_create(); + gpr_ref_init(&proxy->users, 1); + // Construct proxy address. + const int proxy_port = grpc_pick_unused_port_or_die(); + gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); + gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); + // Create TCP server. + proxy->channel_args = grpc_channel_args_copy(args); + grpc_error* error = grpc_tcp_server_create( + &exec_ctx, NULL, proxy->channel_args, &proxy->server); + GPR_ASSERT(error == GRPC_ERROR_NONE); + // Bind to port. + grpc_resolved_address resolved_addr; + struct sockaddr_in* addr = (struct sockaddr_in*)resolved_addr.addr; + memset(&resolved_addr, 0, sizeof(resolved_addr)); + addr->sin_family = AF_INET; + grpc_sockaddr_set_port(&resolved_addr, proxy_port); + int port; + error = grpc_tcp_server_add_port(proxy->server, &resolved_addr, &port); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(port == proxy_port); + // Start server. + proxy->pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(proxy->pollset, &proxy->mu); + grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept, + proxy); + grpc_exec_ctx_finish(&exec_ctx); + // Start proxy thread. + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); + return proxy; +} + +static void destroy_pollset(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + grpc_pollset* pollset = (grpc_pollset*)arg; + grpc_pollset_destroy(exec_ctx, pollset); + gpr_free(pollset); +} + +void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { + gpr_unref(&proxy->users); // Signal proxy thread to shutdown. + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_thd_join(proxy->thd); + grpc_tcp_server_shutdown_listeners(&exec_ctx, proxy->server); + grpc_tcp_server_unref(&exec_ctx, proxy->server); + gpr_free(proxy->proxy_name); + grpc_channel_args_destroy(&exec_ctx, proxy->channel_args); + grpc_pollset_shutdown(&exec_ctx, proxy->pollset, + GRPC_CLOSURE_CREATE(destroy_pollset, proxy->pollset, + grpc_schedule_on_exec_ctx)); + GRPC_COMBINER_UNREF(&exec_ctx, proxy->combiner, "test"); + gpr_free(proxy); + grpc_exec_ctx_finish(&exec_ctx); +} + +const char* grpc_end2end_http_proxy_get_proxy_name( + grpc_end2end_http_proxy* proxy) { + return proxy->proxy_name; +} diff --git a/test/core/end2end/fixtures/inproc.c b/test/core/end2end/fixtures/inproc.c deleted file mode 100644 index 6f742f0293..0000000000 --- a/test/core/end2end/fixtures/inproc.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/http/server/http_server_filter.h" -#include "src/core/ext/transport/inproc/inproc_transport.h" -#include "src/core/lib/channel/connected_channel.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct inproc_fixture_data { - bool dummy; // reserved for future expansion. Struct can't be empty -} inproc_fixture_data; - -static grpc_end2end_test_fixture inproc_create_fixture( - grpc_channel_args *client_args, grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - inproc_fixture_data *ffd = gpr_malloc(sizeof(inproc_fixture_data)); - memset(&f, 0, sizeof(f)); - - f.fixture_data = ffd; - f.cq = grpc_completion_queue_create_for_next(NULL); - f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - - return f; -} - -void inproc_init_client(grpc_end2end_test_fixture *f, - grpc_channel_args *client_args) { - f->client = grpc_inproc_channel_create(f->server, client_args, NULL); - GPR_ASSERT(f->client); -} - -void inproc_init_server(grpc_end2end_test_fixture *f, - grpc_channel_args *server_args) { - 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); - grpc_server_start(f->server); -} - -void inproc_tear_down(grpc_end2end_test_fixture *f) { - inproc_fixture_data *ffd = f->fixture_data; - gpr_free(ffd); -} - -/* All test configurations */ -static grpc_end2end_test_config configs[] = { - {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, inproc_create_fixture, - inproc_init_client, inproc_init_server, inproc_tear_down}, -}; - -int main(int argc, char **argv) { - size_t i; - - grpc_test_init(argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc new file mode 100644 index 0000000000..c075dc629f --- /dev/null +++ b/test/core/end2end/fixtures/inproc.cc @@ -0,0 +1,98 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/http/server/http_server_filter.h" +#include "src/core/ext/transport/inproc/inproc_transport.h" +#include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct inproc_fixture_data { + bool dummy; // reserved for future expansion. Struct can't be empty +} inproc_fixture_data; + +static grpc_end2end_test_fixture inproc_create_fixture( + grpc_channel_args *client_args, grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + inproc_fixture_data *ffd = static_cast( + gpr_malloc(sizeof(inproc_fixture_data))); + memset(&f, 0, sizeof(f)); + + f.fixture_data = ffd; + f.cq = grpc_completion_queue_create_for_next(NULL); + f.shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + + return f; +} + +void inproc_init_client(grpc_end2end_test_fixture *f, + grpc_channel_args *client_args) { + f->client = grpc_inproc_channel_create(f->server, client_args, NULL); + GPR_ASSERT(f->client); +} + +void inproc_init_server(grpc_end2end_test_fixture *f, + grpc_channel_args *server_args) { + 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); + grpc_server_start(f->server); +} + +void inproc_tear_down(grpc_end2end_test_fixture *f) { + inproc_fixture_data *ffd = + static_cast(f->fixture_data); + gpr_free(ffd); +} + +/* All test configurations */ +static grpc_end2end_test_config configs[] = { + {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, inproc_create_fixture, + inproc_init_client, inproc_init_server, inproc_tear_down}, +}; + +int main(int argc, char **argv) { + size_t i; + + grpc_test_init(argc, argv); + grpc_end2end_tests_pre_init(); + grpc_init(); + + for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { + grpc_end2end_tests(argc, argv, configs[i]); + } + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c deleted file mode 100644 index 6a2d75da09..0000000000 --- a/test/core/end2end/fixtures/proxy.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/fixtures/proxy.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "test/core/util/port.h" - -struct grpc_end2end_proxy { - gpr_thd_id thd; - char *proxy_port; - char *server_port; - grpc_completion_queue *cq; - grpc_server *server; - grpc_channel *client; - - int shutdown; - - /* requested call */ - grpc_call *new_call; - grpc_call_details new_call_details; - grpc_metadata_array new_call_metadata; -}; - -typedef struct { - void (*func)(void *arg, int success); - void *arg; -} closure; - -typedef struct { - gpr_refcount refs; - grpc_end2end_proxy *proxy; - - grpc_call *c2p; - grpc_call *p2s; - - grpc_metadata_array c2p_initial_metadata; - grpc_metadata_array p2s_initial_metadata; - - grpc_byte_buffer *c2p_msg; - grpc_byte_buffer *p2s_msg; - - grpc_metadata_array p2s_trailing_metadata; - grpc_status_code p2s_status; - grpc_slice p2s_status_details; - - int c2p_server_cancelled; -} proxy_call; - -static void thread_main(void *arg); -static void request_call(grpc_end2end_proxy *proxy); - -grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - gpr_thd_options opt = gpr_thd_options_default(); - int proxy_port = grpc_pick_unused_port_or_die(); - int server_port = grpc_pick_unused_port_or_die(); - - grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)gpr_malloc(sizeof(*proxy)); - memset(proxy, 0, sizeof(*proxy)); - - gpr_join_host_port(&proxy->proxy_port, "localhost", proxy_port); - gpr_join_host_port(&proxy->server_port, "localhost", server_port); - - gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port, - proxy->server_port); - - proxy->cq = grpc_completion_queue_create_for_next(NULL); - proxy->server = def->create_server(proxy->proxy_port, server_args); - proxy->client = def->create_client(proxy->server_port, client_args); - - grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL); - grpc_server_start(proxy->server); - - grpc_call_details_init(&proxy->new_call_details); - gpr_thd_options_set_joinable(&opt); - GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); - - request_call(proxy); - - return proxy; -} - -static closure *new_closure(void (*func)(void *arg, int success), void *arg) { - closure *cl = (closure *)gpr_malloc(sizeof(*cl)); - cl->func = func; - cl->arg = arg; - return cl; -} - -static void shutdown_complete(void *arg, int success) { - grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; - proxy->shutdown = 1; - grpc_completion_queue_shutdown(proxy->cq); -} - -void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy) { - grpc_server_shutdown_and_notify(proxy->server, proxy->cq, - new_closure(shutdown_complete, proxy)); - gpr_thd_join(proxy->thd); - gpr_free(proxy->proxy_port); - gpr_free(proxy->server_port); - grpc_server_destroy(proxy->server); - grpc_channel_destroy(proxy->client); - grpc_completion_queue_destroy(proxy->cq); - grpc_call_details_destroy(&proxy->new_call_details); - gpr_free(proxy); -} - -static void unrefpc(proxy_call *pc, const char *reason) { - if (gpr_unref(&pc->refs)) { - grpc_call_unref(pc->c2p); - grpc_call_unref(pc->p2s); - grpc_metadata_array_destroy(&pc->c2p_initial_metadata); - grpc_metadata_array_destroy(&pc->p2s_initial_metadata); - grpc_metadata_array_destroy(&pc->p2s_trailing_metadata); - grpc_slice_unref(pc->p2s_status_details); - gpr_free(pc); - } -} - -static void refpc(proxy_call *pc, const char *reason) { gpr_ref(&pc->refs); } - -static void on_c2p_sent_initial_metadata(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - unrefpc(pc, "on_c2p_sent_initial_metadata"); -} - -static void on_p2s_recv_initial_metadata(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - memset(&op, 0, sizeof(op)); - if (!pc->proxy->shutdown) { - op.op = GRPC_OP_SEND_INITIAL_METADATA; - op.flags = 0; - op.reserved = NULL; - op.data.send_initial_metadata.count = pc->p2s_initial_metadata.count; - op.data.send_initial_metadata.metadata = pc->p2s_initial_metadata.metadata; - refpc(pc, "on_c2p_sent_initial_metadata"); - err = grpc_call_start_batch( - pc->c2p, &op, 1, new_closure(on_c2p_sent_initial_metadata, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } - - unrefpc(pc, "on_p2s_recv_initial_metadata"); -} - -static void on_p2s_sent_initial_metadata(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - unrefpc(pc, "on_p2s_sent_initial_metadata"); -} - -static void on_c2p_recv_msg(void *arg, int success); - -static void on_p2s_sent_message(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - grpc_byte_buffer_destroy(pc->c2p_msg); - if (!pc->proxy->shutdown && success) { - op.op = GRPC_OP_RECV_MESSAGE; - op.flags = 0; - op.reserved = NULL; - op.data.recv_message.recv_message = &pc->c2p_msg; - refpc(pc, "on_c2p_recv_msg"); - err = grpc_call_start_batch(pc->c2p, &op, 1, - new_closure(on_c2p_recv_msg, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } - - unrefpc(pc, "on_p2s_sent_message"); -} - -static void on_p2s_sent_close(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - unrefpc(pc, "on_p2s_sent_close"); -} - -static void on_c2p_recv_msg(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - if (!pc->proxy->shutdown && success) { - if (pc->c2p_msg != NULL) { - op.op = GRPC_OP_SEND_MESSAGE; - op.flags = 0; - op.reserved = NULL; - op.data.send_message.send_message = pc->c2p_msg; - refpc(pc, "on_p2s_sent_message"); - err = grpc_call_start_batch(pc->p2s, &op, 1, - new_closure(on_p2s_sent_message, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } else { - op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op.flags = 0; - op.reserved = NULL; - refpc(pc, "on_p2s_sent_close"); - err = grpc_call_start_batch(pc->p2s, &op, 1, - new_closure(on_p2s_sent_close, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } - } else { - if (pc->c2p_msg != NULL) { - grpc_byte_buffer_destroy(pc->c2p_msg); - } - } - - unrefpc(pc, "on_c2p_recv_msg"); -} - -static void on_p2s_recv_msg(void *arg, int success); - -static void on_c2p_sent_message(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - grpc_byte_buffer_destroy(pc->p2s_msg); - if (!pc->proxy->shutdown && success) { - op.op = GRPC_OP_RECV_MESSAGE; - op.flags = 0; - op.reserved = NULL; - op.data.recv_message.recv_message = &pc->p2s_msg; - refpc(pc, "on_p2s_recv_msg"); - err = grpc_call_start_batch(pc->p2s, &op, 1, - new_closure(on_p2s_recv_msg, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } - - unrefpc(pc, "on_c2p_sent_message"); -} - -static void on_p2s_recv_msg(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - if (!pc->proxy->shutdown && success && pc->p2s_msg) { - op.op = GRPC_OP_SEND_MESSAGE; - op.flags = 0; - op.reserved = NULL; - op.data.send_message.send_message = pc->p2s_msg; - refpc(pc, "on_c2p_sent_message"); - err = grpc_call_start_batch(pc->c2p, &op, 1, - new_closure(on_c2p_sent_message, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } else { - grpc_byte_buffer_destroy(pc->p2s_msg); - } - unrefpc(pc, "on_p2s_recv_msg"); -} - -static void on_c2p_sent_status(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - unrefpc(pc, "on_c2p_sent_status"); -} - -static void on_p2s_status(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - grpc_op op; - grpc_call_error err; - - if (!pc->proxy->shutdown) { - GPR_ASSERT(success); - op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op.flags = 0; - op.reserved = NULL; - op.data.send_status_from_server.trailing_metadata_count = - pc->p2s_trailing_metadata.count; - op.data.send_status_from_server.trailing_metadata = - pc->p2s_trailing_metadata.metadata; - op.data.send_status_from_server.status = pc->p2s_status; - op.data.send_status_from_server.status_details = &pc->p2s_status_details; - refpc(pc, "on_c2p_sent_status"); - err = grpc_call_start_batch(pc->c2p, &op, 1, - new_closure(on_c2p_sent_status, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - } - - unrefpc(pc, "on_p2s_status"); -} - -static void on_c2p_closed(void *arg, int success) { - proxy_call *pc = (proxy_call *)arg; - unrefpc(pc, "on_c2p_closed"); -} - -static void on_new_call(void *arg, int success) { - grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; - grpc_call_error err; - - if (success) { - grpc_op op; - memset(&op, 0, sizeof(op)); - proxy_call *pc = (proxy_call *)gpr_malloc(sizeof(*pc)); - memset(pc, 0, sizeof(*pc)); - pc->proxy = proxy; - GPR_SWAP(grpc_metadata_array, pc->c2p_initial_metadata, - proxy->new_call_metadata); - pc->c2p = proxy->new_call; - pc->p2s = grpc_channel_create_call( - proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq, - proxy->new_call_details.method, &proxy->new_call_details.host, - proxy->new_call_details.deadline, NULL); - gpr_ref_init(&pc->refs, 1); - - op.reserved = NULL; - - op.op = GRPC_OP_RECV_INITIAL_METADATA; - op.flags = 0; - op.data.recv_initial_metadata.recv_initial_metadata = - &pc->p2s_initial_metadata; - refpc(pc, "on_p2s_recv_initial_metadata"); - err = grpc_call_start_batch( - pc->p2s, &op, 1, new_closure(on_p2s_recv_initial_metadata, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - op.op = GRPC_OP_SEND_INITIAL_METADATA; - op.flags = proxy->new_call_details.flags; - op.data.send_initial_metadata.count = pc->c2p_initial_metadata.count; - op.data.send_initial_metadata.metadata = pc->c2p_initial_metadata.metadata; - refpc(pc, "on_p2s_sent_initial_metadata"); - err = grpc_call_start_batch( - pc->p2s, &op, 1, new_closure(on_p2s_sent_initial_metadata, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - op.op = GRPC_OP_RECV_MESSAGE; - op.flags = 0; - op.data.recv_message.recv_message = &pc->c2p_msg; - refpc(pc, "on_c2p_recv_msg"); - err = grpc_call_start_batch(pc->c2p, &op, 1, - new_closure(on_c2p_recv_msg, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - op.op = GRPC_OP_RECV_MESSAGE; - op.flags = 0; - op.data.recv_message.recv_message = &pc->p2s_msg; - refpc(pc, "on_p2s_recv_msg"); - err = grpc_call_start_batch(pc->p2s, &op, 1, - new_closure(on_p2s_recv_msg, pc), NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op.flags = 0; - op.data.recv_status_on_client.trailing_metadata = - &pc->p2s_trailing_metadata; - op.data.recv_status_on_client.status = &pc->p2s_status; - op.data.recv_status_on_client.status_details = &pc->p2s_status_details; - refpc(pc, "on_p2s_status"); - err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc), - NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - op.op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op.flags = 0; - op.data.recv_close_on_server.cancelled = &pc->c2p_server_cancelled; - refpc(pc, "on_c2p_closed"); - err = grpc_call_start_batch(pc->c2p, &op, 1, new_closure(on_c2p_closed, pc), - NULL); - GPR_ASSERT(err == GRPC_CALL_OK); - - request_call(proxy); - - grpc_call_details_destroy(&proxy->new_call_details); - grpc_call_details_init(&proxy->new_call_details); - - unrefpc(pc, "init"); - } else { - GPR_ASSERT(proxy->new_call == NULL); - } -} - -static void request_call(grpc_end2end_proxy *proxy) { - proxy->new_call = NULL; - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - proxy->server, &proxy->new_call, - &proxy->new_call_details, - &proxy->new_call_metadata, proxy->cq, - proxy->cq, new_closure(on_new_call, proxy))); -} - -static void thread_main(void *arg) { - grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; - closure *cl; - for (;;) { - grpc_event ev = grpc_completion_queue_next( - proxy->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); - switch (ev.type) { - case GRPC_QUEUE_TIMEOUT: - gpr_log(GPR_ERROR, "Should never reach here"); - abort(); - case GRPC_QUEUE_SHUTDOWN: - return; - case GRPC_OP_COMPLETE: - cl = (closure *)ev.tag; - cl->func(cl->arg, ev.success); - gpr_free(cl); - break; - } - } -} - -const char *grpc_end2end_proxy_get_client_target(grpc_end2end_proxy *proxy) { - return proxy->proxy_port; -} - -const char *grpc_end2end_proxy_get_server_port(grpc_end2end_proxy *proxy) { - return proxy->server_port; -} diff --git a/test/core/end2end/fixtures/proxy.cc b/test/core/end2end/fixtures/proxy.cc new file mode 100644 index 0000000000..6a2d75da09 --- /dev/null +++ b/test/core/end2end/fixtures/proxy.cc @@ -0,0 +1,437 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/fixtures/proxy.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "test/core/util/port.h" + +struct grpc_end2end_proxy { + gpr_thd_id thd; + char *proxy_port; + char *server_port; + grpc_completion_queue *cq; + grpc_server *server; + grpc_channel *client; + + int shutdown; + + /* requested call */ + grpc_call *new_call; + grpc_call_details new_call_details; + grpc_metadata_array new_call_metadata; +}; + +typedef struct { + void (*func)(void *arg, int success); + void *arg; +} closure; + +typedef struct { + gpr_refcount refs; + grpc_end2end_proxy *proxy; + + grpc_call *c2p; + grpc_call *p2s; + + grpc_metadata_array c2p_initial_metadata; + grpc_metadata_array p2s_initial_metadata; + + grpc_byte_buffer *c2p_msg; + grpc_byte_buffer *p2s_msg; + + grpc_metadata_array p2s_trailing_metadata; + grpc_status_code p2s_status; + grpc_slice p2s_status_details; + + int c2p_server_cancelled; +} proxy_call; + +static void thread_main(void *arg); +static void request_call(grpc_end2end_proxy *proxy); + +grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + gpr_thd_options opt = gpr_thd_options_default(); + int proxy_port = grpc_pick_unused_port_or_die(); + int server_port = grpc_pick_unused_port_or_die(); + + grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)gpr_malloc(sizeof(*proxy)); + memset(proxy, 0, sizeof(*proxy)); + + gpr_join_host_port(&proxy->proxy_port, "localhost", proxy_port); + gpr_join_host_port(&proxy->server_port, "localhost", server_port); + + gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port, + proxy->server_port); + + proxy->cq = grpc_completion_queue_create_for_next(NULL); + proxy->server = def->create_server(proxy->proxy_port, server_args); + proxy->client = def->create_client(proxy->server_port, client_args); + + grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL); + grpc_server_start(proxy->server); + + grpc_call_details_init(&proxy->new_call_details); + gpr_thd_options_set_joinable(&opt); + GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); + + request_call(proxy); + + return proxy; +} + +static closure *new_closure(void (*func)(void *arg, int success), void *arg) { + closure *cl = (closure *)gpr_malloc(sizeof(*cl)); + cl->func = func; + cl->arg = arg; + return cl; +} + +static void shutdown_complete(void *arg, int success) { + grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; + proxy->shutdown = 1; + grpc_completion_queue_shutdown(proxy->cq); +} + +void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy) { + grpc_server_shutdown_and_notify(proxy->server, proxy->cq, + new_closure(shutdown_complete, proxy)); + gpr_thd_join(proxy->thd); + gpr_free(proxy->proxy_port); + gpr_free(proxy->server_port); + grpc_server_destroy(proxy->server); + grpc_channel_destroy(proxy->client); + grpc_completion_queue_destroy(proxy->cq); + grpc_call_details_destroy(&proxy->new_call_details); + gpr_free(proxy); +} + +static void unrefpc(proxy_call *pc, const char *reason) { + if (gpr_unref(&pc->refs)) { + grpc_call_unref(pc->c2p); + grpc_call_unref(pc->p2s); + grpc_metadata_array_destroy(&pc->c2p_initial_metadata); + grpc_metadata_array_destroy(&pc->p2s_initial_metadata); + grpc_metadata_array_destroy(&pc->p2s_trailing_metadata); + grpc_slice_unref(pc->p2s_status_details); + gpr_free(pc); + } +} + +static void refpc(proxy_call *pc, const char *reason) { gpr_ref(&pc->refs); } + +static void on_c2p_sent_initial_metadata(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + unrefpc(pc, "on_c2p_sent_initial_metadata"); +} + +static void on_p2s_recv_initial_metadata(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + memset(&op, 0, sizeof(op)); + if (!pc->proxy->shutdown) { + op.op = GRPC_OP_SEND_INITIAL_METADATA; + op.flags = 0; + op.reserved = NULL; + op.data.send_initial_metadata.count = pc->p2s_initial_metadata.count; + op.data.send_initial_metadata.metadata = pc->p2s_initial_metadata.metadata; + refpc(pc, "on_c2p_sent_initial_metadata"); + err = grpc_call_start_batch( + pc->c2p, &op, 1, new_closure(on_c2p_sent_initial_metadata, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } + + unrefpc(pc, "on_p2s_recv_initial_metadata"); +} + +static void on_p2s_sent_initial_metadata(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + unrefpc(pc, "on_p2s_sent_initial_metadata"); +} + +static void on_c2p_recv_msg(void *arg, int success); + +static void on_p2s_sent_message(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + grpc_byte_buffer_destroy(pc->c2p_msg); + if (!pc->proxy->shutdown && success) { + op.op = GRPC_OP_RECV_MESSAGE; + op.flags = 0; + op.reserved = NULL; + op.data.recv_message.recv_message = &pc->c2p_msg; + refpc(pc, "on_c2p_recv_msg"); + err = grpc_call_start_batch(pc->c2p, &op, 1, + new_closure(on_c2p_recv_msg, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } + + unrefpc(pc, "on_p2s_sent_message"); +} + +static void on_p2s_sent_close(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + unrefpc(pc, "on_p2s_sent_close"); +} + +static void on_c2p_recv_msg(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + if (!pc->proxy->shutdown && success) { + if (pc->c2p_msg != NULL) { + op.op = GRPC_OP_SEND_MESSAGE; + op.flags = 0; + op.reserved = NULL; + op.data.send_message.send_message = pc->c2p_msg; + refpc(pc, "on_p2s_sent_message"); + err = grpc_call_start_batch(pc->p2s, &op, 1, + new_closure(on_p2s_sent_message, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } else { + op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op.flags = 0; + op.reserved = NULL; + refpc(pc, "on_p2s_sent_close"); + err = grpc_call_start_batch(pc->p2s, &op, 1, + new_closure(on_p2s_sent_close, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } + } else { + if (pc->c2p_msg != NULL) { + grpc_byte_buffer_destroy(pc->c2p_msg); + } + } + + unrefpc(pc, "on_c2p_recv_msg"); +} + +static void on_p2s_recv_msg(void *arg, int success); + +static void on_c2p_sent_message(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + grpc_byte_buffer_destroy(pc->p2s_msg); + if (!pc->proxy->shutdown && success) { + op.op = GRPC_OP_RECV_MESSAGE; + op.flags = 0; + op.reserved = NULL; + op.data.recv_message.recv_message = &pc->p2s_msg; + refpc(pc, "on_p2s_recv_msg"); + err = grpc_call_start_batch(pc->p2s, &op, 1, + new_closure(on_p2s_recv_msg, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } + + unrefpc(pc, "on_c2p_sent_message"); +} + +static void on_p2s_recv_msg(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + if (!pc->proxy->shutdown && success && pc->p2s_msg) { + op.op = GRPC_OP_SEND_MESSAGE; + op.flags = 0; + op.reserved = NULL; + op.data.send_message.send_message = pc->p2s_msg; + refpc(pc, "on_c2p_sent_message"); + err = grpc_call_start_batch(pc->c2p, &op, 1, + new_closure(on_c2p_sent_message, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } else { + grpc_byte_buffer_destroy(pc->p2s_msg); + } + unrefpc(pc, "on_p2s_recv_msg"); +} + +static void on_c2p_sent_status(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + unrefpc(pc, "on_c2p_sent_status"); +} + +static void on_p2s_status(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + grpc_op op; + grpc_call_error err; + + if (!pc->proxy->shutdown) { + GPR_ASSERT(success); + op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op.flags = 0; + op.reserved = NULL; + op.data.send_status_from_server.trailing_metadata_count = + pc->p2s_trailing_metadata.count; + op.data.send_status_from_server.trailing_metadata = + pc->p2s_trailing_metadata.metadata; + op.data.send_status_from_server.status = pc->p2s_status; + op.data.send_status_from_server.status_details = &pc->p2s_status_details; + refpc(pc, "on_c2p_sent_status"); + err = grpc_call_start_batch(pc->c2p, &op, 1, + new_closure(on_c2p_sent_status, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + } + + unrefpc(pc, "on_p2s_status"); +} + +static void on_c2p_closed(void *arg, int success) { + proxy_call *pc = (proxy_call *)arg; + unrefpc(pc, "on_c2p_closed"); +} + +static void on_new_call(void *arg, int success) { + grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; + grpc_call_error err; + + if (success) { + grpc_op op; + memset(&op, 0, sizeof(op)); + proxy_call *pc = (proxy_call *)gpr_malloc(sizeof(*pc)); + memset(pc, 0, sizeof(*pc)); + pc->proxy = proxy; + GPR_SWAP(grpc_metadata_array, pc->c2p_initial_metadata, + proxy->new_call_metadata); + pc->c2p = proxy->new_call; + pc->p2s = grpc_channel_create_call( + proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq, + proxy->new_call_details.method, &proxy->new_call_details.host, + proxy->new_call_details.deadline, NULL); + gpr_ref_init(&pc->refs, 1); + + op.reserved = NULL; + + op.op = GRPC_OP_RECV_INITIAL_METADATA; + op.flags = 0; + op.data.recv_initial_metadata.recv_initial_metadata = + &pc->p2s_initial_metadata; + refpc(pc, "on_p2s_recv_initial_metadata"); + err = grpc_call_start_batch( + pc->p2s, &op, 1, new_closure(on_p2s_recv_initial_metadata, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + op.op = GRPC_OP_SEND_INITIAL_METADATA; + op.flags = proxy->new_call_details.flags; + op.data.send_initial_metadata.count = pc->c2p_initial_metadata.count; + op.data.send_initial_metadata.metadata = pc->c2p_initial_metadata.metadata; + refpc(pc, "on_p2s_sent_initial_metadata"); + err = grpc_call_start_batch( + pc->p2s, &op, 1, new_closure(on_p2s_sent_initial_metadata, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + op.op = GRPC_OP_RECV_MESSAGE; + op.flags = 0; + op.data.recv_message.recv_message = &pc->c2p_msg; + refpc(pc, "on_c2p_recv_msg"); + err = grpc_call_start_batch(pc->c2p, &op, 1, + new_closure(on_c2p_recv_msg, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + op.op = GRPC_OP_RECV_MESSAGE; + op.flags = 0; + op.data.recv_message.recv_message = &pc->p2s_msg; + refpc(pc, "on_p2s_recv_msg"); + err = grpc_call_start_batch(pc->p2s, &op, 1, + new_closure(on_p2s_recv_msg, pc), NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op.flags = 0; + op.data.recv_status_on_client.trailing_metadata = + &pc->p2s_trailing_metadata; + op.data.recv_status_on_client.status = &pc->p2s_status; + op.data.recv_status_on_client.status_details = &pc->p2s_status_details; + refpc(pc, "on_p2s_status"); + err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc), + NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + op.op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op.flags = 0; + op.data.recv_close_on_server.cancelled = &pc->c2p_server_cancelled; + refpc(pc, "on_c2p_closed"); + err = grpc_call_start_batch(pc->c2p, &op, 1, new_closure(on_c2p_closed, pc), + NULL); + GPR_ASSERT(err == GRPC_CALL_OK); + + request_call(proxy); + + grpc_call_details_destroy(&proxy->new_call_details); + grpc_call_details_init(&proxy->new_call_details); + + unrefpc(pc, "init"); + } else { + GPR_ASSERT(proxy->new_call == NULL); + } +} + +static void request_call(grpc_end2end_proxy *proxy) { + proxy->new_call = NULL; + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + proxy->server, &proxy->new_call, + &proxy->new_call_details, + &proxy->new_call_metadata, proxy->cq, + proxy->cq, new_closure(on_new_call, proxy))); +} + +static void thread_main(void *arg) { + grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg; + closure *cl; + for (;;) { + grpc_event ev = grpc_completion_queue_next( + proxy->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); + switch (ev.type) { + case GRPC_QUEUE_TIMEOUT: + gpr_log(GPR_ERROR, "Should never reach here"); + abort(); + case GRPC_QUEUE_SHUTDOWN: + return; + case GRPC_OP_COMPLETE: + cl = (closure *)ev.tag; + cl->func(cl->arg, ev.success); + gpr_free(cl); + break; + } + } +} + +const char *grpc_end2end_proxy_get_client_target(grpc_end2end_proxy *proxy) { + return proxy->proxy_port; +} + +const char *grpc_end2end_proxy_get_server_port(grpc_end2end_proxy *proxy) { + return proxy->server_port; +} diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c deleted file mode 100644 index 0a787bbf30..0000000000 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/iomgr/timer.h" -#include "src/core/lib/iomgr/timer_manager.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/surface/server.h" -#include "src/core/lib/transport/metadata.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/passthru_endpoint.h" - -//////////////////////////////////////////////////////////////////////////////// -// logging - -bool squelch = true; -bool leak_check = true; - -static void dont_log(gpr_log_func_args *args) {} - -//////////////////////////////////////////////////////////////////////////////// -// global state - -static gpr_timespec g_now; -static grpc_server *g_server; -static grpc_channel *g_channel; -static grpc_resource_quota *g_resource_quota; - -extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); - -static gpr_timespec now_impl(gpr_clock_type clock_type) { - GPR_ASSERT(clock_type != GPR_TIMESPAN); - gpr_timespec ts = g_now; - ts.clock_type = clock_type; - return ts; -} - -//////////////////////////////////////////////////////////////////////////////// -// input_stream: allows easy access to input bytes, and allows reading a little -// past the end (avoiding needing to check everywhere) - -typedef struct { - const uint8_t *cur; - const uint8_t *end; -} input_stream; - -static uint8_t next_byte(input_stream *inp) { - if (inp->cur == inp->end) { - return 0; - } - return *inp->cur++; -} - -static void end(input_stream *inp) { inp->cur = inp->end; } - -static char *read_string(input_stream *inp, bool *special) { - char *str = NULL; - size_t cap = 0; - size_t sz = 0; - char c; - do { - if (cap == sz) { - cap = GPR_MAX(3 * cap / 2, cap + 8); - str = gpr_realloc(str, cap); - } - c = (char)next_byte(inp); - str[sz++] = c; - } while (c != 0 && c != 1); - if (special != NULL) { - *special = (c == 1); - } - if (c == 1) { - str[sz - 1] = 0; - } - return str; -} - -static void read_buffer(input_stream *inp, char **buffer, size_t *length, - bool *special) { - *length = next_byte(inp); - if (*length == 255) { - if (special != NULL) *special = true; - *length = next_byte(inp); - } else { - if (special != NULL) *special = false; - } - *buffer = gpr_malloc(*length); - for (size_t i = 0; i < *length; i++) { - (*buffer)[i] = (char)next_byte(inp); - } -} - -static grpc_slice maybe_intern(grpc_slice s, bool intern) { - grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s); - grpc_slice_unref(s); - return r; -} - -static grpc_slice read_string_like_slice(input_stream *inp) { - bool special; - char *s = read_string(inp, &special); - grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special); - gpr_free(s); - return r; -} - -static grpc_slice read_buffer_like_slice(input_stream *inp) { - char *buffer; - size_t length; - bool special; - read_buffer(inp, &buffer, &length, &special); - grpc_slice r = - maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special); - gpr_free(buffer); - return r; -} - -static uint32_t read_uint22(input_stream *inp) { - uint8_t b = next_byte(inp); - uint32_t x = b & 0x7f; - if (b & 0x80) { - x <<= 7; - b = next_byte(inp); - x |= b & 0x7f; - if (b & 0x80) { - x <<= 8; - x |= next_byte(inp); - } - } - return x; -} - -static uint32_t read_uint32(input_stream *inp) { - uint8_t b = next_byte(inp); - uint32_t x = b & 0x7f; - if (b & 0x80) { - x <<= 7; - b = next_byte(inp); - x |= b & 0x7f; - if (b & 0x80) { - x <<= 7; - b = next_byte(inp); - x |= b & 0x7f; - if (b & 0x80) { - x <<= 7; - b = next_byte(inp); - x |= b & 0x7f; - if (b & 0x80) { - x = (x << 4) | (next_byte(inp) & 0x0f); - } - } - } - } - return x; -} - -static grpc_byte_buffer *read_message(input_stream *inp) { - grpc_slice slice = grpc_slice_malloc(read_uint22(inp)); - memset(GRPC_SLICE_START_PTR(slice), 0, GRPC_SLICE_LENGTH(slice)); - grpc_byte_buffer *out = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - return out; -} - -static int read_int(input_stream *inp) { return (int)read_uint32(inp); } - -static grpc_channel_args *read_args(input_stream *inp) { - size_t n = next_byte(inp); - grpc_arg *args = gpr_malloc(sizeof(*args) * n); - for (size_t i = 0; i < n; i++) { - switch (next_byte(inp)) { - case 1: - args[i].type = GRPC_ARG_STRING; - args[i].key = read_string(inp, NULL); - args[i].value.string = read_string(inp, NULL); - break; - case 2: - args[i].type = GRPC_ARG_INTEGER; - args[i].key = read_string(inp, NULL); - args[i].value.integer = read_int(inp); - break; - case 3: - args[i].type = GRPC_ARG_POINTER; - args[i].key = gpr_strdup(GRPC_ARG_RESOURCE_QUOTA); - args[i].value.pointer.vtable = grpc_resource_quota_arg_vtable(); - args[i].value.pointer.p = g_resource_quota; - grpc_resource_quota_ref(g_resource_quota); - break; - default: - end(inp); - n = i; - break; - } - } - grpc_channel_args *a = gpr_malloc(sizeof(*a)); - a->args = args; - a->num_args = n; - return a; -} - -typedef struct cred_artifact_ctx { - int num_release; - char *release[3]; -} cred_artifact_ctx; -#define CRED_ARTIFACT_CTX_INIT \ - { \ - 0, { 0 } \ - } - -static void cred_artifact_ctx_finish(cred_artifact_ctx *ctx) { - for (int i = 0; i < ctx->num_release; i++) { - gpr_free(ctx->release[i]); - } -} - -static const char *read_cred_artifact(cred_artifact_ctx *ctx, input_stream *inp, - const char **builtins, - size_t num_builtins) { - uint8_t b = next_byte(inp); - if (b == 0) return NULL; - if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp, NULL); - if (b >= num_builtins + 1) { - end(inp); - return NULL; - } - return builtins[b - 1]; -} - -static grpc_channel_credentials *read_ssl_channel_creds(input_stream *inp) { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - static const char *builtin_root_certs[] = {test_root_cert}; - static const char *builtin_private_keys[] = { - test_server1_key, test_self_signed_client_key, test_signed_client_key}; - static const char *builtin_cert_chains[] = { - test_server1_cert, test_self_signed_client_cert, test_signed_client_cert}; - const char *root_certs = read_cred_artifact( - &ctx, inp, builtin_root_certs, GPR_ARRAY_SIZE(builtin_root_certs)); - const char *private_key = read_cred_artifact( - &ctx, inp, builtin_private_keys, GPR_ARRAY_SIZE(builtin_private_keys)); - const char *certs = read_cred_artifact(&ctx, inp, builtin_cert_chains, - GPR_ARRAY_SIZE(builtin_cert_chains)); - grpc_ssl_pem_key_cert_pair key_cert_pair = {private_key, certs}; - grpc_channel_credentials *creds = grpc_ssl_credentials_create( - root_certs, private_key != NULL && certs != NULL ? &key_cert_pair : NULL, - NULL); - cred_artifact_ctx_finish(&ctx); - return creds; -} - -static grpc_call_credentials *read_call_creds(input_stream *inp) { - switch (next_byte(inp)) { - default: - end(inp); - return NULL; - case 0: - return NULL; - case 1: { - grpc_call_credentials *c1 = read_call_creds(inp); - grpc_call_credentials *c2 = read_call_creds(inp); - if (c1 != NULL && c2 != NULL) { - grpc_call_credentials *out = - grpc_composite_call_credentials_create(c1, c2, NULL); - grpc_call_credentials_release(c1); - grpc_call_credentials_release(c2); - return out; - } else if (c1 != NULL) { - return c1; - } else if (c2 != NULL) { - return c2; - } else { - return NULL; - } - GPR_UNREACHABLE_CODE(return NULL); - } - case 2: { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - const char *access_token = read_cred_artifact(&ctx, inp, NULL, 0); - grpc_call_credentials *out = - access_token == NULL ? NULL : grpc_access_token_credentials_create( - access_token, NULL); - cred_artifact_ctx_finish(&ctx); - return out; - } - case 3: { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - const char *auth_token = read_cred_artifact(&ctx, inp, NULL, 0); - const char *auth_selector = read_cred_artifact(&ctx, inp, NULL, 0); - grpc_call_credentials *out = auth_token == NULL || auth_selector == NULL - ? NULL - : grpc_google_iam_credentials_create( - auth_token, auth_selector, NULL); - cred_artifact_ctx_finish(&ctx); - return out; - } - /* TODO(ctiller): more cred types here */ - } -} - -static grpc_channel_credentials *read_channel_creds(input_stream *inp) { - switch (next_byte(inp)) { - case 0: - return read_ssl_channel_creds(inp); - break; - case 1: { - grpc_channel_credentials *c1 = read_channel_creds(inp); - grpc_call_credentials *c2 = read_call_creds(inp); - if (c1 != NULL && c2 != NULL) { - grpc_channel_credentials *out = - grpc_composite_channel_credentials_create(c1, c2, NULL); - grpc_channel_credentials_release(c1); - grpc_call_credentials_release(c2); - return out; - } else if (c1) { - return c1; - } else if (c2) { - grpc_call_credentials_release(c2); - return NULL; - } else { - return NULL; - } - GPR_UNREACHABLE_CODE(return NULL); - } - case 2: - return NULL; - default: - end(inp); - return NULL; - } -} - -static bool is_eof(input_stream *inp) { return inp->cur == inp->end; } - -//////////////////////////////////////////////////////////////////////////////// -// dns resolution - -typedef struct addr_req { - grpc_timer timer; - char *addr; - grpc_closure *on_done; - grpc_resolved_addresses **addrs; - grpc_lb_addresses **lb_addrs; -} addr_req; - -static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - addr_req *r = arg; - - if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) { - if (r->addrs != NULL) { - grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs)); - addrs->naddrs = 1; - addrs->addrs = gpr_malloc(sizeof(*addrs->addrs)); - addrs->addrs[0].len = 0; - *r->addrs = addrs; - } else if (r->lb_addrs != NULL) { - grpc_lb_addresses *lb_addrs = grpc_lb_addresses_create(1, NULL); - grpc_lb_addresses_set_address(lb_addrs, 0, NULL, 0, NULL, NULL, NULL); - *r->lb_addrs = lb_addrs; - } - GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, GRPC_ERROR_NONE); - } else { - GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Resolution failed", &error, 1)); - } - - gpr_free(r->addr); - gpr_free(r); -} - -void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, - const char *default_port, - grpc_pollset_set *interested_parties, - grpc_closure *on_done, - grpc_resolved_addresses **addresses) { - addr_req *r = gpr_malloc(sizeof(*r)); - r->addr = gpr_strdup(addr); - r->on_done = on_done; - r->addrs = addresses; - r->lb_addrs = NULL; - grpc_timer_init( - exec_ctx, &r->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), - GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); -} - -grpc_ares_request *my_dns_lookup_ares( - grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, - const char *default_port, grpc_pollset_set *interested_parties, - grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, - char **service_config_json) { - addr_req *r = gpr_malloc(sizeof(*r)); - r->addr = gpr_strdup(addr); - r->on_done = on_done; - r->addrs = NULL; - r->lb_addrs = lb_addrs; - grpc_timer_init( - exec_ctx, &r->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), - GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -// client connection - -// defined in tcp_client_posix.c -extern void (*grpc_tcp_client_connect_impl)( - grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, - grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, - const grpc_resolved_address *addr, gpr_timespec deadline); - -static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - grpc_endpoint **ep, gpr_timespec deadline); - -typedef struct { - grpc_timer timer; - grpc_closure *closure; - grpc_endpoint **ep; - gpr_timespec deadline; -} future_connect; - -static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - future_connect *fc = arg; - if (error != GRPC_ERROR_NONE) { - *fc->ep = NULL; - GRPC_CLOSURE_SCHED(exec_ctx, fc->closure, GRPC_ERROR_REF(error)); - } else if (g_server != NULL) { - grpc_endpoint *client; - grpc_endpoint *server; - grpc_passthru_endpoint_create(&client, &server, g_resource_quota, NULL); - *fc->ep = client; - - grpc_transport *transport = - grpc_create_chttp2_transport(exec_ctx, NULL, server, 0); - grpc_server_setup_transport(exec_ctx, g_server, transport, NULL, NULL); - grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); - - GRPC_CLOSURE_SCHED(exec_ctx, fc->closure, GRPC_ERROR_NONE); - } else { - sched_connect(exec_ctx, fc->closure, fc->ep, fc->deadline); - } - gpr_free(fc); -} - -static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, - grpc_endpoint **ep, gpr_timespec deadline) { - if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) { - *ep = NULL; - GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Connect deadline exceeded")); - return; - } - - future_connect *fc = gpr_malloc(sizeof(*fc)); - fc->closure = closure; - fc->ep = ep; - fc->deadline = deadline; - grpc_timer_init( - exec_ctx, &fc->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), - GRPC_CLOSURE_CREATE(do_connect, fc, grpc_schedule_on_exec_ctx)); -} - -static void my_tcp_client_connect(grpc_exec_ctx *exec_ctx, - grpc_closure *closure, grpc_endpoint **ep, - grpc_pollset_set *interested_parties, - const grpc_channel_args *channel_args, - const grpc_resolved_address *addr, - gpr_timespec deadline) { - sched_connect(exec_ctx, closure, ep, deadline); -} - -//////////////////////////////////////////////////////////////////////////////// -// test driver - -typedef struct validator { - void (*validate)(void *arg, bool success); - void *arg; -} validator; - -static validator *create_validator(void (*validate)(void *arg, bool success), - void *arg) { - validator *v = gpr_malloc(sizeof(*v)); - v->validate = validate; - v->arg = arg; - return v; -} - -static void assert_success_and_decrement(void *counter, bool success) { - GPR_ASSERT(success); - --*(int *)counter; -} - -static void decrement(void *counter, bool success) { --*(int *)counter; } - -typedef struct connectivity_watch { - int *counter; - gpr_timespec deadline; -} connectivity_watch; - -static connectivity_watch *make_connectivity_watch(gpr_timespec s, - int *counter) { - connectivity_watch *o = gpr_malloc(sizeof(*o)); - o->deadline = s; - o->counter = counter; - return o; -} - -static void validate_connectivity_watch(void *p, bool success) { - connectivity_watch *w = p; - if (!success) { - GPR_ASSERT(gpr_time_cmp(gpr_now(w->deadline.clock_type), w->deadline) >= 0); - } - --*w->counter; - gpr_free(w); -} - -static void free_non_null(void *p) { - GPR_ASSERT(p != NULL); - gpr_free(p); -} - -typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type; - -#define DONE_FLAG_CALL_CLOSED ((uint64_t)(1 << 0)) - -typedef struct call_state { - call_state_type type; - grpc_call *call; - grpc_byte_buffer *recv_message; - grpc_status_code status; - grpc_metadata_array recv_initial_metadata; - grpc_metadata_array recv_trailing_metadata; - grpc_slice recv_status_details; - int cancelled; - int pending_ops; - grpc_call_details call_details; - grpc_byte_buffer *send_message; - // starts at 0, individual flags from DONE_FLAG_xxx are set - // as different operations are completed - uint64_t done_flags; - - // array of pointers to free later - size_t num_to_free; - size_t cap_to_free; - void **to_free; - - // array of slices to unref - size_t num_slices_to_unref; - size_t cap_slices_to_unref; - grpc_slice **slices_to_unref; - - struct call_state *next; - struct call_state *prev; -} call_state; - -static call_state *g_active_call; - -static call_state *new_call(call_state *sibling, call_state_type type) { - call_state *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - if (sibling != NULL) { - c->next = sibling; - c->prev = sibling->prev; - c->next->prev = c->prev->next = c; - } else { - c->next = c->prev = c; - } - c->type = type; - return c; -} - -static call_state *maybe_delete_call_state(call_state *call) { - call_state *next = call->next; - - if (call->call != NULL) return next; - if (call->pending_ops != 0) return next; - - if (call == g_active_call) { - g_active_call = call->next; - GPR_ASSERT(call != g_active_call); - } - - call->prev->next = call->next; - call->next->prev = call->prev; - grpc_metadata_array_destroy(&call->recv_initial_metadata); - grpc_metadata_array_destroy(&call->recv_trailing_metadata); - grpc_slice_unref(call->recv_status_details); - grpc_call_details_destroy(&call->call_details); - - for (size_t i = 0; i < call->num_slices_to_unref; i++) { - grpc_slice_unref(*call->slices_to_unref[i]); - gpr_free(call->slices_to_unref[i]); - } - for (size_t i = 0; i < call->num_to_free; i++) { - gpr_free(call->to_free[i]); - } - gpr_free(call->to_free); - gpr_free(call->slices_to_unref); - - gpr_free(call); - - return next; -} - -static void add_to_free(call_state *call, void *p) { - if (call->num_to_free == call->cap_to_free) { - call->cap_to_free = GPR_MAX(8, 2 * call->cap_to_free); - call->to_free = - gpr_realloc(call->to_free, sizeof(*call->to_free) * call->cap_to_free); - } - call->to_free[call->num_to_free++] = p; -} - -static grpc_slice *add_slice_to_unref(call_state *call, grpc_slice s) { - if (call->num_slices_to_unref == call->cap_slices_to_unref) { - call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref); - call->slices_to_unref = - gpr_realloc(call->slices_to_unref, - sizeof(*call->slices_to_unref) * call->cap_slices_to_unref); - } - call->slices_to_unref[call->num_slices_to_unref] = - gpr_malloc(sizeof(grpc_slice)); - *call->slices_to_unref[call->num_slices_to_unref++] = s; - return call->slices_to_unref[call->num_slices_to_unref - 1]; -} - -static void read_metadata(input_stream *inp, size_t *count, - grpc_metadata **metadata, call_state *cs) { - *count = next_byte(inp); - if (*count) { - *metadata = gpr_malloc(*count * sizeof(**metadata)); - memset(*metadata, 0, *count * sizeof(**metadata)); - for (size_t i = 0; i < *count; i++) { - (*metadata)[i].key = read_string_like_slice(inp); - (*metadata)[i].value = read_buffer_like_slice(inp); - (*metadata)[i].flags = read_uint32(inp); - add_slice_to_unref(cs, (*metadata)[i].key); - add_slice_to_unref(cs, (*metadata)[i].value); - } - } else { - *metadata = gpr_malloc(1); - } - add_to_free(cs, *metadata); -} - -static call_state *destroy_call(call_state *call) { - grpc_call_unref(call->call); - call->call = NULL; - return maybe_delete_call_state(call); -} - -static void finished_request_call(void *csp, bool success) { - call_state *cs = csp; - GPR_ASSERT(cs->pending_ops > 0); - --cs->pending_ops; - if (success) { - GPR_ASSERT(cs->call != NULL); - cs->type = SERVER; - } else { - maybe_delete_call_state(cs); - } -} - -typedef struct { - call_state *cs; - uint8_t has_ops; -} batch_info; - -static void finished_batch(void *p, bool success) { - batch_info *bi = p; - --bi->cs->pending_ops; - if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE)) && - (bi->cs->done_flags & DONE_FLAG_CALL_CLOSED)) { - GPR_ASSERT(bi->cs->recv_message == NULL); - } - if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE) && - bi->cs->recv_message != NULL)) { - grpc_byte_buffer_destroy(bi->cs->recv_message); - bi->cs->recv_message = NULL; - } - if ((bi->has_ops & (1u << GRPC_OP_SEND_MESSAGE))) { - grpc_byte_buffer_destroy(bi->cs->send_message); - bi->cs->send_message = NULL; - } - if ((bi->has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) || - (bi->has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) { - bi->cs->done_flags |= DONE_FLAG_CALL_CLOSED; - } - maybe_delete_call_state(bi->cs); - gpr_free(bi); -} - -static validator *make_finished_batch_validator(call_state *cs, - uint8_t has_ops) { - batch_info *bi = gpr_malloc(sizeof(*bi)); - bi->cs = cs; - bi->has_ops = has_ops; - return create_validator(finished_batch, bi); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_test_only_set_slice_hash_seed(0); - char *grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER"); - if (squelch && grpc_trace_fuzzer == NULL) gpr_set_log_function(dont_log); - gpr_free(grpc_trace_fuzzer); - input_stream inp = {data, data + size}; - grpc_tcp_client_connect_impl = my_tcp_client_connect; - gpr_now_impl = now_impl; - grpc_init(); - grpc_timer_manager_set_threading(false); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_executor_set_threading(&exec_ctx, false); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resolve_address = my_resolve_address; - grpc_dns_lookup_ares = my_dns_lookup_ares; - - GPR_ASSERT(g_channel == NULL); - GPR_ASSERT(g_server == NULL); - - bool server_shutdown = false; - int pending_server_shutdowns = 0; - int pending_channel_watches = 0; - int pending_pings = 0; - - g_active_call = new_call(NULL, ROOT); - g_resource_quota = grpc_resource_quota_create("api_fuzzer"); - - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - while (!is_eof(&inp) || g_channel != NULL || g_server != NULL || - pending_channel_watches > 0 || pending_pings > 0 || - g_active_call->type != ROOT || g_active_call->next != g_active_call) { - if (is_eof(&inp)) { - if (g_channel != NULL) { - grpc_channel_destroy(g_channel); - g_channel = NULL; - } - if (g_server != NULL) { - if (!server_shutdown) { - grpc_server_shutdown_and_notify( - g_server, cq, create_validator(assert_success_and_decrement, - &pending_server_shutdowns)); - server_shutdown = true; - pending_server_shutdowns++; - } else if (pending_server_shutdowns == 0) { - grpc_server_destroy(g_server); - g_server = NULL; - } - } - call_state *s = g_active_call; - do { - if (s->type != PENDING_SERVER && s->call != NULL) { - s = destroy_call(s); - } else { - s = s->next; - } - } while (s != g_active_call); - - g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN)); - } - - grpc_timer_manager_tick(); - - switch (next_byte(&inp)) { - // terminate on bad bytes - default: - end(&inp); - break; - // tickle completion queue - case 0: { - grpc_event ev = grpc_completion_queue_next( - cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - switch (ev.type) { - case GRPC_OP_COMPLETE: { - validator *v = ev.tag; - v->validate(v->arg, ev.success); - gpr_free(v); - break; - } - case GRPC_QUEUE_TIMEOUT: - break; - case GRPC_QUEUE_SHUTDOWN: - abort(); - break; - } - break; - } - // increment global time - case 1: { - g_now = gpr_time_add( - g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); - break; - } - // create an insecure channel - case 2: { - if (g_channel == NULL) { - char *target = read_string(&inp, NULL); - char *target_uri; - gpr_asprintf(&target_uri, "dns:%s", target); - grpc_channel_args *args = read_args(&inp); - g_channel = grpc_insecure_channel_create(target_uri, args, NULL); - GPR_ASSERT(g_channel != NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - gpr_free(target_uri); - gpr_free(target); - } else { - end(&inp); - } - break; - } - // destroy a channel - case 3: { - if (g_channel != NULL) { - grpc_channel_destroy(g_channel); - g_channel = NULL; - } else { - end(&inp); - } - break; - } - // bring up a server - case 4: { - if (g_server == NULL) { - grpc_channel_args *args = read_args(&inp); - g_server = grpc_server_create(args, NULL); - GPR_ASSERT(g_server != NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_server_register_completion_queue(g_server, cq, NULL); - grpc_server_start(g_server); - server_shutdown = false; - GPR_ASSERT(pending_server_shutdowns == 0); - } else { - end(&inp); - } - break; - } - // begin server shutdown - case 5: { - if (g_server != NULL) { - grpc_server_shutdown_and_notify( - g_server, cq, create_validator(assert_success_and_decrement, - &pending_server_shutdowns)); - pending_server_shutdowns++; - server_shutdown = true; - } else { - end(&inp); - } - break; - } - // cancel all calls if shutdown - case 6: { - if (g_server != NULL && server_shutdown) { - grpc_server_cancel_all_calls(g_server); - } else { - end(&inp); - } - break; - } - // destroy server - case 7: { - if (g_server != NULL && server_shutdown && - pending_server_shutdowns == 0) { - grpc_server_destroy(g_server); - g_server = NULL; - } else { - end(&inp); - } - break; - } - // check connectivity - case 8: { - if (g_channel != NULL) { - uint8_t try_to_connect = next_byte(&inp); - if (try_to_connect == 0 || try_to_connect == 1) { - grpc_channel_check_connectivity_state(g_channel, try_to_connect); - } else { - end(&inp); - } - } else { - end(&inp); - } - break; - } - // watch connectivity - case 9: { - if (g_channel != NULL) { - grpc_connectivity_state st = - grpc_channel_check_connectivity_state(g_channel, 0); - if (st != GRPC_CHANNEL_SHUTDOWN) { - gpr_timespec deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); - grpc_channel_watch_connectivity_state( - g_channel, st, deadline, cq, - create_validator(validate_connectivity_watch, - make_connectivity_watch( - deadline, &pending_channel_watches))); - pending_channel_watches++; - } - } else { - end(&inp); - } - break; - } - // create a call - case 10: { - bool ok = true; - if (g_channel == NULL) ok = false; - grpc_call *parent_call = NULL; - if (g_active_call->type != ROOT) { - if (g_active_call->call == NULL || g_active_call->type == CLIENT) { - end(&inp); - break; - } - parent_call = g_active_call->call; - } - uint32_t propagation_mask = read_uint32(&inp); - grpc_slice method = read_string_like_slice(&inp); - if (GRPC_SLICE_LENGTH(method) == 0) { - ok = false; - } - grpc_slice host = read_string_like_slice(&inp); - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); - - if (ok) { - call_state *cs = new_call(g_active_call, CLIENT); - cs->call = - grpc_channel_create_call(g_channel, parent_call, propagation_mask, - cq, method, &host, deadline, NULL); - } else { - end(&inp); - } - grpc_slice_unref(method); - grpc_slice_unref(host); - break; - } - // switch the 'current' call - case 11: { - g_active_call = g_active_call->next; - break; - } - // queue some ops on a call - case 12: { - if (g_active_call->type == PENDING_SERVER || - g_active_call->type == ROOT || g_active_call->call == NULL) { - end(&inp); - break; - } - size_t num_ops = next_byte(&inp); - if (num_ops > 6) { - end(&inp); - break; - } - grpc_op *ops = gpr_malloc(sizeof(grpc_op) * num_ops); - if (num_ops > 0) memset(ops, 0, sizeof(grpc_op) * num_ops); - bool ok = true; - size_t i; - grpc_op *op; - uint8_t has_ops = 0; - for (i = 0; i < num_ops; i++) { - op = &ops[i]; - switch (next_byte(&inp)) { - default: - /* invalid value */ - op->op = (grpc_op_type)-1; - ok = false; - break; - case GRPC_OP_SEND_INITIAL_METADATA: - op->op = GRPC_OP_SEND_INITIAL_METADATA; - has_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA; - read_metadata(&inp, &op->data.send_initial_metadata.count, - &op->data.send_initial_metadata.metadata, - g_active_call); - break; - case GRPC_OP_SEND_MESSAGE: - op->op = GRPC_OP_SEND_MESSAGE; - if (g_active_call->send_message != NULL) { - ok = false; - } else { - has_ops |= 1 << GRPC_OP_SEND_MESSAGE; - g_active_call->send_message = - op->data.send_message.send_message = read_message(&inp); - } - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - has_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT; - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - has_ops |= 1 << GRPC_OP_SEND_STATUS_FROM_SERVER; - read_metadata( - &inp, - &op->data.send_status_from_server.trailing_metadata_count, - &op->data.send_status_from_server.trailing_metadata, - g_active_call); - op->data.send_status_from_server.status = next_byte(&inp); - op->data.send_status_from_server.status_details = - add_slice_to_unref(g_active_call, - read_buffer_like_slice(&inp)); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - op->op = GRPC_OP_RECV_INITIAL_METADATA; - has_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &g_active_call->recv_initial_metadata; - break; - case GRPC_OP_RECV_MESSAGE: - op->op = GRPC_OP_RECV_MESSAGE; - has_ops |= 1 << GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &g_active_call->recv_message; - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.status = &g_active_call->status; - op->data.recv_status_on_client.trailing_metadata = - &g_active_call->recv_trailing_metadata; - op->data.recv_status_on_client.status_details = - &g_active_call->recv_status_details; - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - has_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = - &g_active_call->cancelled; - break; - } - op->reserved = NULL; - op->flags = read_uint32(&inp); - } - if (ok) { - validator *v = make_finished_batch_validator(g_active_call, has_ops); - g_active_call->pending_ops++; - grpc_call_error error = - grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL); - if (error != GRPC_CALL_OK) { - v->validate(v->arg, false); - gpr_free(v); - } - } else { - end(&inp); - } - if (!ok && (has_ops & (1 << GRPC_OP_SEND_MESSAGE))) { - grpc_byte_buffer_destroy(g_active_call->send_message); - g_active_call->send_message = NULL; - } - gpr_free(ops); - - break; - } - // cancel current call - case 13: { - if (g_active_call->type != ROOT && g_active_call->call != NULL) { - grpc_call_cancel(g_active_call->call, NULL); - } else { - end(&inp); - } - break; - } - // get a calls peer - case 14: { - if (g_active_call->type != ROOT && g_active_call->call != NULL) { - free_non_null(grpc_call_get_peer(g_active_call->call)); - } else { - end(&inp); - } - break; - } - // get a channels target - case 15: { - if (g_channel != NULL) { - free_non_null(grpc_channel_get_target(g_channel)); - } else { - end(&inp); - } - break; - } - // send a ping on a channel - case 16: { - if (g_channel != NULL) { - pending_pings++; - grpc_channel_ping(g_channel, cq, - create_validator(decrement, &pending_pings), NULL); - } else { - end(&inp); - } - break; - } - // enable a tracer - case 17: { - char *tracer = read_string(&inp, NULL); - grpc_tracer_set_enabled(tracer, 1); - gpr_free(tracer); - break; - } - // disable a tracer - case 18: { - char *tracer = read_string(&inp, NULL); - grpc_tracer_set_enabled(tracer, 0); - gpr_free(tracer); - break; - } - // request a server call - case 19: { - if (g_server == NULL) { - end(&inp); - break; - } - call_state *cs = new_call(g_active_call, PENDING_SERVER); - cs->pending_ops++; - validator *v = create_validator(finished_request_call, cs); - grpc_call_error error = - grpc_server_request_call(g_server, &cs->call, &cs->call_details, - &cs->recv_initial_metadata, cq, cq, v); - if (error != GRPC_CALL_OK) { - v->validate(v->arg, false); - gpr_free(v); - } - break; - } - // destroy a call - case 20: { - if (g_active_call->type != ROOT && - g_active_call->type != PENDING_SERVER && - g_active_call->call != NULL) { - destroy_call(g_active_call); - } else { - end(&inp); - } - break; - } - // resize the buffer pool - case 21: { - grpc_resource_quota_resize(g_resource_quota, read_uint22(&inp)); - break; - } - // create a secure channel - case 22: { - if (g_channel == NULL) { - char *target = read_string(&inp, NULL); - char *target_uri; - gpr_asprintf(&target_uri, "dns:%s", target); - grpc_channel_args *args = read_args(&inp); - grpc_channel_credentials *creds = read_channel_creds(&inp); - g_channel = grpc_secure_channel_create(creds, target_uri, args, NULL); - GPR_ASSERT(g_channel != NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - gpr_free(target_uri); - gpr_free(target); - grpc_channel_credentials_release(creds); - } else { - end(&inp); - } - break; - } - } - } - - GPR_ASSERT(g_channel == NULL); - GPR_ASSERT(g_server == NULL); - GPR_ASSERT(g_active_call->type == ROOT); - GPR_ASSERT(g_active_call->next == g_active_call); - gpr_free(g_active_call); - - grpc_completion_queue_shutdown(cq); - GPR_ASSERT( - grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL) - .type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cq); - - grpc_resource_quota_unref(g_resource_quota); - - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc new file mode 100644 index 0000000000..2db8ed474a --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -0,0 +1,1227 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/timer_manager.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/surface/server.h" +#include "src/core/lib/transport/metadata.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/passthru_endpoint.h" + +//////////////////////////////////////////////////////////////////////////////// +// logging + +bool squelch = true; +bool leak_check = true; + +static void dont_log(gpr_log_func_args *args) {} + +//////////////////////////////////////////////////////////////////////////////// +// global state + +static gpr_timespec g_now; +static grpc_server *g_server; +static grpc_channel *g_channel; +static grpc_resource_quota *g_resource_quota; + +extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); + +static gpr_timespec now_impl(gpr_clock_type clock_type) { + GPR_ASSERT(clock_type != GPR_TIMESPAN); + gpr_timespec ts = g_now; + ts.clock_type = clock_type; + return ts; +} + +//////////////////////////////////////////////////////////////////////////////// +// input_stream: allows easy access to input bytes, and allows reading a little +// past the end (avoiding needing to check everywhere) + +typedef struct { + const uint8_t *cur; + const uint8_t *end; +} input_stream; + +static uint8_t next_byte(input_stream *inp) { + if (inp->cur == inp->end) { + return 0; + } + return *inp->cur++; +} + +static void end(input_stream *inp) { inp->cur = inp->end; } + +static char *read_string(input_stream *inp, bool *special) { + char *str = NULL; + size_t cap = 0; + size_t sz = 0; + char c; + do { + if (cap == sz) { + cap = GPR_MAX(3 * cap / 2, cap + 8); + str = static_cast(gpr_realloc(str, cap)); + } + c = (char)next_byte(inp); + str[sz++] = c; + } while (c != 0 && c != 1); + if (special != NULL) { + *special = (c == 1); + } + if (c == 1) { + str[sz - 1] = 0; + } + return str; +} + +static void read_buffer(input_stream *inp, char **buffer, size_t *length, + bool *special) { + *length = next_byte(inp); + if (*length == 255) { + if (special != NULL) *special = true; + *length = next_byte(inp); + } else { + if (special != NULL) *special = false; + } + *buffer = static_cast(gpr_malloc(*length)); + for (size_t i = 0; i < *length; i++) { + (*buffer)[i] = (char)next_byte(inp); + } +} + +static grpc_slice maybe_intern(grpc_slice s, bool intern) { + grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s); + grpc_slice_unref(s); + return r; +} + +static grpc_slice read_string_like_slice(input_stream *inp) { + bool special; + char *s = read_string(inp, &special); + grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special); + gpr_free(s); + return r; +} + +static grpc_slice read_buffer_like_slice(input_stream *inp) { + char *buffer; + size_t length; + bool special; + read_buffer(inp, &buffer, &length, &special); + grpc_slice r = + maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special); + gpr_free(buffer); + return r; +} + +static uint32_t read_uint22(input_stream *inp) { + uint8_t b = next_byte(inp); + uint32_t x = b & 0x7f; + if (b & 0x80) { + x <<= 7; + b = next_byte(inp); + x |= b & 0x7f; + if (b & 0x80) { + x <<= 8; + x |= next_byte(inp); + } + } + return x; +} + +static uint32_t read_uint32(input_stream *inp) { + uint8_t b = next_byte(inp); + uint32_t x = b & 0x7f; + if (b & 0x80) { + x <<= 7; + b = next_byte(inp); + x |= b & 0x7f; + if (b & 0x80) { + x <<= 7; + b = next_byte(inp); + x |= b & 0x7f; + if (b & 0x80) { + x <<= 7; + b = next_byte(inp); + x |= b & 0x7f; + if (b & 0x80) { + x = (x << 4) | (next_byte(inp) & 0x0f); + } + } + } + } + return x; +} + +static grpc_byte_buffer *read_message(input_stream *inp) { + grpc_slice slice = grpc_slice_malloc(read_uint22(inp)); + memset(GRPC_SLICE_START_PTR(slice), 0, GRPC_SLICE_LENGTH(slice)); + grpc_byte_buffer *out = grpc_raw_byte_buffer_create(&slice, 1); + grpc_slice_unref(slice); + return out; +} + +static int read_int(input_stream *inp) { return (int)read_uint32(inp); } + +static grpc_channel_args *read_args(input_stream *inp) { + size_t n = next_byte(inp); + grpc_arg *args = static_cast(gpr_malloc(sizeof(*args) * n)); + for (size_t i = 0; i < n; i++) { + switch (next_byte(inp)) { + case 1: + args[i].type = GRPC_ARG_STRING; + args[i].key = read_string(inp, NULL); + args[i].value.string = read_string(inp, NULL); + break; + case 2: + args[i].type = GRPC_ARG_INTEGER; + args[i].key = read_string(inp, NULL); + args[i].value.integer = read_int(inp); + break; + case 3: + args[i].type = GRPC_ARG_POINTER; + args[i].key = gpr_strdup(GRPC_ARG_RESOURCE_QUOTA); + args[i].value.pointer.vtable = grpc_resource_quota_arg_vtable(); + args[i].value.pointer.p = g_resource_quota; + grpc_resource_quota_ref(g_resource_quota); + break; + default: + end(inp); + n = i; + break; + } + } + grpc_channel_args *a = + static_cast(gpr_malloc(sizeof(*a))); + a->args = args; + a->num_args = n; + return a; +} + +typedef struct cred_artifact_ctx { + int num_release; + char *release[3]; +} cred_artifact_ctx; +#define CRED_ARTIFACT_CTX_INIT \ + { \ + 0, { 0 } \ + } + +static void cred_artifact_ctx_finish(cred_artifact_ctx *ctx) { + for (int i = 0; i < ctx->num_release; i++) { + gpr_free(ctx->release[i]); + } +} + +static const char *read_cred_artifact(cred_artifact_ctx *ctx, input_stream *inp, + const char **builtins, + size_t num_builtins) { + uint8_t b = next_byte(inp); + if (b == 0) return NULL; + if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp, NULL); + if (b >= num_builtins + 1) { + end(inp); + return NULL; + } + return builtins[b - 1]; +} + +static grpc_channel_credentials *read_ssl_channel_creds(input_stream *inp) { + cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; + static const char *builtin_root_certs[] = {test_root_cert}; + static const char *builtin_private_keys[] = { + test_server1_key, test_self_signed_client_key, test_signed_client_key}; + static const char *builtin_cert_chains[] = { + test_server1_cert, test_self_signed_client_cert, test_signed_client_cert}; + const char *root_certs = read_cred_artifact( + &ctx, inp, builtin_root_certs, GPR_ARRAY_SIZE(builtin_root_certs)); + const char *private_key = read_cred_artifact( + &ctx, inp, builtin_private_keys, GPR_ARRAY_SIZE(builtin_private_keys)); + const char *certs = read_cred_artifact(&ctx, inp, builtin_cert_chains, + GPR_ARRAY_SIZE(builtin_cert_chains)); + grpc_ssl_pem_key_cert_pair key_cert_pair = {private_key, certs}; + grpc_channel_credentials *creds = grpc_ssl_credentials_create( + root_certs, private_key != NULL && certs != NULL ? &key_cert_pair : NULL, + NULL); + cred_artifact_ctx_finish(&ctx); + return creds; +} + +static grpc_call_credentials *read_call_creds(input_stream *inp) { + switch (next_byte(inp)) { + default: + end(inp); + return NULL; + case 0: + return NULL; + case 1: { + grpc_call_credentials *c1 = read_call_creds(inp); + grpc_call_credentials *c2 = read_call_creds(inp); + if (c1 != NULL && c2 != NULL) { + grpc_call_credentials *out = + grpc_composite_call_credentials_create(c1, c2, NULL); + grpc_call_credentials_release(c1); + grpc_call_credentials_release(c2); + return out; + } else if (c1 != NULL) { + return c1; + } else if (c2 != NULL) { + return c2; + } else { + return NULL; + } + GPR_UNREACHABLE_CODE(return NULL); + } + case 2: { + cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; + const char *access_token = read_cred_artifact(&ctx, inp, NULL, 0); + grpc_call_credentials *out = + access_token == NULL ? NULL : grpc_access_token_credentials_create( + access_token, NULL); + cred_artifact_ctx_finish(&ctx); + return out; + } + case 3: { + cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; + const char *auth_token = read_cred_artifact(&ctx, inp, NULL, 0); + const char *auth_selector = read_cred_artifact(&ctx, inp, NULL, 0); + grpc_call_credentials *out = auth_token == NULL || auth_selector == NULL + ? NULL + : grpc_google_iam_credentials_create( + auth_token, auth_selector, NULL); + cred_artifact_ctx_finish(&ctx); + return out; + } + /* TODO(ctiller): more cred types here */ + } +} + +static grpc_channel_credentials *read_channel_creds(input_stream *inp) { + switch (next_byte(inp)) { + case 0: + return read_ssl_channel_creds(inp); + break; + case 1: { + grpc_channel_credentials *c1 = read_channel_creds(inp); + grpc_call_credentials *c2 = read_call_creds(inp); + if (c1 != NULL && c2 != NULL) { + grpc_channel_credentials *out = + grpc_composite_channel_credentials_create(c1, c2, NULL); + grpc_channel_credentials_release(c1); + grpc_call_credentials_release(c2); + return out; + } else if (c1) { + return c1; + } else if (c2) { + grpc_call_credentials_release(c2); + return NULL; + } else { + return NULL; + } + GPR_UNREACHABLE_CODE(return NULL); + } + case 2: + return NULL; + default: + end(inp); + return NULL; + } +} + +static bool is_eof(input_stream *inp) { return inp->cur == inp->end; } + +//////////////////////////////////////////////////////////////////////////////// +// dns resolution + +typedef struct addr_req { + grpc_timer timer; + char *addr; + grpc_closure *on_done; + grpc_resolved_addresses **addrs; + grpc_lb_addresses **lb_addrs; +} addr_req; + +static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + addr_req *r = static_cast(arg); + + if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) { + if (r->addrs != NULL) { + grpc_resolved_addresses *addrs = + static_cast(gpr_malloc(sizeof(*addrs))); + addrs->naddrs = 1; + addrs->addrs = static_cast( + gpr_malloc(sizeof(*addrs->addrs))); + addrs->addrs[0].len = 0; + *r->addrs = addrs; + } else if (r->lb_addrs != NULL) { + grpc_lb_addresses *lb_addrs = grpc_lb_addresses_create(1, NULL); + grpc_lb_addresses_set_address(lb_addrs, 0, NULL, 0, NULL, NULL, NULL); + *r->lb_addrs = lb_addrs; + } + GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, GRPC_ERROR_NONE); + } else { + GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Resolution failed", &error, 1)); + } + + gpr_free(r->addr); + gpr_free(r); +} + +void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, + const char *default_port, + grpc_pollset_set *interested_parties, + grpc_closure *on_done, + grpc_resolved_addresses **addresses) { + addr_req *r = static_cast(gpr_malloc(sizeof(*r))); + r->addr = gpr_strdup(addr); + r->on_done = on_done; + r->addrs = addresses; + r->lb_addrs = NULL; + grpc_timer_init( + exec_ctx, &r->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), + GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); +} + +grpc_ares_request *my_dns_lookup_ares( + grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, + const char *default_port, grpc_pollset_set *interested_parties, + grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, + char **service_config_json) { + addr_req *r = static_cast(gpr_malloc(sizeof(*r))); + r->addr = gpr_strdup(addr); + r->on_done = on_done; + r->addrs = NULL; + r->lb_addrs = lb_addrs; + grpc_timer_init( + exec_ctx, &r->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), + GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// client connection + +// defined in tcp_client_posix.c +extern void (*grpc_tcp_client_connect_impl)( + grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, + grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, + const grpc_resolved_address *addr, gpr_timespec deadline); + +static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_endpoint **ep, gpr_timespec deadline); + +typedef struct { + grpc_timer timer; + grpc_closure *closure; + grpc_endpoint **ep; + gpr_timespec deadline; +} future_connect; + +static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + future_connect *fc = static_cast(arg); + if (error != GRPC_ERROR_NONE) { + *fc->ep = NULL; + GRPC_CLOSURE_SCHED(exec_ctx, fc->closure, GRPC_ERROR_REF(error)); + } else if (g_server != NULL) { + grpc_endpoint *client; + grpc_endpoint *server; + grpc_passthru_endpoint_create(&client, &server, g_resource_quota, NULL); + *fc->ep = client; + + grpc_transport *transport = + grpc_create_chttp2_transport(exec_ctx, NULL, server, 0); + grpc_server_setup_transport(exec_ctx, g_server, transport, NULL, NULL); + grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); + + GRPC_CLOSURE_SCHED(exec_ctx, fc->closure, GRPC_ERROR_NONE); + } else { + sched_connect(exec_ctx, fc->closure, fc->ep, fc->deadline); + } + gpr_free(fc); +} + +static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_endpoint **ep, gpr_timespec deadline) { + if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) { + *ep = NULL; + GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Connect deadline exceeded")); + return; + } + + future_connect *fc = static_cast(gpr_malloc(sizeof(*fc))); + fc->closure = closure; + fc->ep = ep; + fc->deadline = deadline; + grpc_timer_init( + exec_ctx, &fc->timer, GPR_MS_PER_SEC + grpc_exec_ctx_now(exec_ctx), + GRPC_CLOSURE_CREATE(do_connect, fc, grpc_schedule_on_exec_ctx)); +} + +static void my_tcp_client_connect(grpc_exec_ctx *exec_ctx, + grpc_closure *closure, grpc_endpoint **ep, + grpc_pollset_set *interested_parties, + const grpc_channel_args *channel_args, + const grpc_resolved_address *addr, + gpr_timespec deadline) { + sched_connect(exec_ctx, closure, ep, deadline); +} + +//////////////////////////////////////////////////////////////////////////////// +// test driver + +typedef struct validator { + void (*validate)(void *arg, bool success); + void *arg; +} validator; + +static validator *create_validator(void (*validate)(void *arg, bool success), + void *arg) { + validator *v = static_cast(gpr_malloc(sizeof(*v))); + v->validate = validate; + v->arg = arg; + return v; +} + +static void assert_success_and_decrement(void *counter, bool success) { + GPR_ASSERT(success); + --*(int *)counter; +} + +static void decrement(void *counter, bool success) { --*(int *)counter; } + +typedef struct connectivity_watch { + int *counter; + gpr_timespec deadline; +} connectivity_watch; + +static connectivity_watch *make_connectivity_watch(gpr_timespec s, + int *counter) { + connectivity_watch *o = + static_cast(gpr_malloc(sizeof(*o))); + o->deadline = s; + o->counter = counter; + return o; +} + +static void validate_connectivity_watch(void *p, bool success) { + connectivity_watch *w = static_cast(p); + if (!success) { + GPR_ASSERT(gpr_time_cmp(gpr_now(w->deadline.clock_type), w->deadline) >= 0); + } + --*w->counter; + gpr_free(w); +} + +static void free_non_null(void *p) { + GPR_ASSERT(p != NULL); + gpr_free(p); +} + +typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type; + +#define DONE_FLAG_CALL_CLOSED ((uint64_t)(1 << 0)) + +typedef struct call_state { + call_state_type type; + grpc_call *call; + grpc_byte_buffer *recv_message; + grpc_status_code status; + grpc_metadata_array recv_initial_metadata; + grpc_metadata_array recv_trailing_metadata; + grpc_slice recv_status_details; + int cancelled; + int pending_ops; + grpc_call_details call_details; + grpc_byte_buffer *send_message; + // starts at 0, individual flags from DONE_FLAG_xxx are set + // as different operations are completed + uint64_t done_flags; + + // array of pointers to free later + size_t num_to_free; + size_t cap_to_free; + void **to_free; + + // array of slices to unref + size_t num_slices_to_unref; + size_t cap_slices_to_unref; + grpc_slice **slices_to_unref; + + struct call_state *next; + struct call_state *prev; +} call_state; + +static call_state *g_active_call; + +static call_state *new_call(call_state *sibling, call_state_type type) { + call_state *c = static_cast(gpr_malloc(sizeof(*c))); + memset(c, 0, sizeof(*c)); + if (sibling != NULL) { + c->next = sibling; + c->prev = sibling->prev; + c->next->prev = c->prev->next = c; + } else { + c->next = c->prev = c; + } + c->type = type; + return c; +} + +static call_state *maybe_delete_call_state(call_state *call) { + call_state *next = call->next; + + if (call->call != NULL) return next; + if (call->pending_ops != 0) return next; + + if (call == g_active_call) { + g_active_call = call->next; + GPR_ASSERT(call != g_active_call); + } + + call->prev->next = call->next; + call->next->prev = call->prev; + grpc_metadata_array_destroy(&call->recv_initial_metadata); + grpc_metadata_array_destroy(&call->recv_trailing_metadata); + grpc_slice_unref(call->recv_status_details); + grpc_call_details_destroy(&call->call_details); + + for (size_t i = 0; i < call->num_slices_to_unref; i++) { + grpc_slice_unref(*call->slices_to_unref[i]); + gpr_free(call->slices_to_unref[i]); + } + for (size_t i = 0; i < call->num_to_free; i++) { + gpr_free(call->to_free[i]); + } + gpr_free(call->to_free); + gpr_free(call->slices_to_unref); + + gpr_free(call); + + return next; +} + +static void add_to_free(call_state *call, void *p) { + if (call->num_to_free == call->cap_to_free) { + call->cap_to_free = GPR_MAX(8, 2 * call->cap_to_free); + call->to_free = static_cast( + gpr_realloc(call->to_free, sizeof(*call->to_free) * call->cap_to_free)); + } + call->to_free[call->num_to_free++] = p; +} + +static grpc_slice *add_slice_to_unref(call_state *call, grpc_slice s) { + if (call->num_slices_to_unref == call->cap_slices_to_unref) { + call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref); + call->slices_to_unref = static_cast(gpr_realloc( + call->slices_to_unref, + sizeof(*call->slices_to_unref) * call->cap_slices_to_unref)); + } + call->slices_to_unref[call->num_slices_to_unref] = + static_cast(gpr_malloc(sizeof(grpc_slice))); + *call->slices_to_unref[call->num_slices_to_unref++] = s; + return call->slices_to_unref[call->num_slices_to_unref - 1]; +} + +static void read_metadata(input_stream *inp, size_t *count, + grpc_metadata **metadata, call_state *cs) { + *count = next_byte(inp); + if (*count) { + *metadata = + static_cast(gpr_malloc(*count * sizeof(**metadata))); + memset(*metadata, 0, *count * sizeof(**metadata)); + for (size_t i = 0; i < *count; i++) { + (*metadata)[i].key = read_string_like_slice(inp); + (*metadata)[i].value = read_buffer_like_slice(inp); + (*metadata)[i].flags = read_uint32(inp); + add_slice_to_unref(cs, (*metadata)[i].key); + add_slice_to_unref(cs, (*metadata)[i].value); + } + } else { + *metadata = static_cast(gpr_malloc(1)); + } + add_to_free(cs, *metadata); +} + +static call_state *destroy_call(call_state *call) { + grpc_call_unref(call->call); + call->call = NULL; + return maybe_delete_call_state(call); +} + +static void finished_request_call(void *csp, bool success) { + call_state *cs = static_cast(csp); + GPR_ASSERT(cs->pending_ops > 0); + --cs->pending_ops; + if (success) { + GPR_ASSERT(cs->call != NULL); + cs->type = SERVER; + } else { + maybe_delete_call_state(cs); + } +} + +typedef struct { + call_state *cs; + uint8_t has_ops; +} batch_info; + +static void finished_batch(void *p, bool success) { + batch_info *bi = static_cast(p); + --bi->cs->pending_ops; + if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE)) && + (bi->cs->done_flags & DONE_FLAG_CALL_CLOSED)) { + GPR_ASSERT(bi->cs->recv_message == NULL); + } + if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE) && + bi->cs->recv_message != NULL)) { + grpc_byte_buffer_destroy(bi->cs->recv_message); + bi->cs->recv_message = NULL; + } + if ((bi->has_ops & (1u << GRPC_OP_SEND_MESSAGE))) { + grpc_byte_buffer_destroy(bi->cs->send_message); + bi->cs->send_message = NULL; + } + if ((bi->has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) || + (bi->has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) { + bi->cs->done_flags |= DONE_FLAG_CALL_CLOSED; + } + maybe_delete_call_state(bi->cs); + gpr_free(bi); +} + +static validator *make_finished_batch_validator(call_state *cs, + uint8_t has_ops) { + batch_info *bi = static_cast(gpr_malloc(sizeof(*bi))); + bi->cs = cs; + bi->has_ops = has_ops; + return create_validator(finished_batch, bi); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_test_only_set_slice_hash_seed(0); + char *grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER"); + if (squelch && grpc_trace_fuzzer == NULL) gpr_set_log_function(dont_log); + gpr_free(grpc_trace_fuzzer); + input_stream inp = {data, data + size}; + grpc_tcp_client_connect_impl = my_tcp_client_connect; + gpr_now_impl = now_impl; + grpc_init(); + grpc_timer_manager_set_threading(false); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_executor_set_threading(&exec_ctx, false); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resolve_address = my_resolve_address; + grpc_dns_lookup_ares = my_dns_lookup_ares; + + GPR_ASSERT(g_channel == NULL); + GPR_ASSERT(g_server == NULL); + + bool server_shutdown = false; + int pending_server_shutdowns = 0; + int pending_channel_watches = 0; + int pending_pings = 0; + + g_active_call = new_call(NULL, ROOT); + g_resource_quota = grpc_resource_quota_create("api_fuzzer"); + + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + while (!is_eof(&inp) || g_channel != NULL || g_server != NULL || + pending_channel_watches > 0 || pending_pings > 0 || + g_active_call->type != ROOT || g_active_call->next != g_active_call) { + if (is_eof(&inp)) { + if (g_channel != NULL) { + grpc_channel_destroy(g_channel); + g_channel = NULL; + } + if (g_server != NULL) { + if (!server_shutdown) { + grpc_server_shutdown_and_notify( + g_server, cq, create_validator(assert_success_and_decrement, + &pending_server_shutdowns)); + server_shutdown = true; + pending_server_shutdowns++; + } else if (pending_server_shutdowns == 0) { + grpc_server_destroy(g_server); + g_server = NULL; + } + } + call_state *s = g_active_call; + do { + if (s->type != PENDING_SERVER && s->call != NULL) { + s = destroy_call(s); + } else { + s = s->next; + } + } while (s != g_active_call); + + g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN)); + } + + grpc_timer_manager_tick(); + + switch (next_byte(&inp)) { + // terminate on bad bytes + default: + end(&inp); + break; + // tickle completion queue + case 0: { + grpc_event ev = grpc_completion_queue_next( + cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + switch (ev.type) { + case GRPC_OP_COMPLETE: { + validator *v = static_cast(ev.tag); + v->validate(v->arg, ev.success); + gpr_free(v); + break; + } + case GRPC_QUEUE_TIMEOUT: + break; + case GRPC_QUEUE_SHUTDOWN: + abort(); + break; + } + break; + } + // increment global time + case 1: { + g_now = gpr_time_add( + g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); + break; + } + // create an insecure channel + case 2: { + if (g_channel == NULL) { + char *target = read_string(&inp, NULL); + char *target_uri; + gpr_asprintf(&target_uri, "dns:%s", target); + grpc_channel_args *args = read_args(&inp); + g_channel = grpc_insecure_channel_create(target_uri, args, NULL); + GPR_ASSERT(g_channel != NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + gpr_free(target_uri); + gpr_free(target); + } else { + end(&inp); + } + break; + } + // destroy a channel + case 3: { + if (g_channel != NULL) { + grpc_channel_destroy(g_channel); + g_channel = NULL; + } else { + end(&inp); + } + break; + } + // bring up a server + case 4: { + if (g_server == NULL) { + grpc_channel_args *args = read_args(&inp); + g_server = grpc_server_create(args, NULL); + GPR_ASSERT(g_server != NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_server_register_completion_queue(g_server, cq, NULL); + grpc_server_start(g_server); + server_shutdown = false; + GPR_ASSERT(pending_server_shutdowns == 0); + } else { + end(&inp); + } + break; + } + // begin server shutdown + case 5: { + if (g_server != NULL) { + grpc_server_shutdown_and_notify( + g_server, cq, create_validator(assert_success_and_decrement, + &pending_server_shutdowns)); + pending_server_shutdowns++; + server_shutdown = true; + } else { + end(&inp); + } + break; + } + // cancel all calls if shutdown + case 6: { + if (g_server != NULL && server_shutdown) { + grpc_server_cancel_all_calls(g_server); + } else { + end(&inp); + } + break; + } + // destroy server + case 7: { + if (g_server != NULL && server_shutdown && + pending_server_shutdowns == 0) { + grpc_server_destroy(g_server); + g_server = NULL; + } else { + end(&inp); + } + break; + } + // check connectivity + case 8: { + if (g_channel != NULL) { + uint8_t try_to_connect = next_byte(&inp); + if (try_to_connect == 0 || try_to_connect == 1) { + grpc_channel_check_connectivity_state(g_channel, try_to_connect); + } else { + end(&inp); + } + } else { + end(&inp); + } + break; + } + // watch connectivity + case 9: { + if (g_channel != NULL) { + grpc_connectivity_state st = + grpc_channel_check_connectivity_state(g_channel, 0); + if (st != GRPC_CHANNEL_SHUTDOWN) { + gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); + grpc_channel_watch_connectivity_state( + g_channel, st, deadline, cq, + create_validator(validate_connectivity_watch, + make_connectivity_watch( + deadline, &pending_channel_watches))); + pending_channel_watches++; + } + } else { + end(&inp); + } + break; + } + // create a call + case 10: { + bool ok = true; + if (g_channel == NULL) ok = false; + grpc_call *parent_call = NULL; + if (g_active_call->type != ROOT) { + if (g_active_call->call == NULL || g_active_call->type == CLIENT) { + end(&inp); + break; + } + parent_call = g_active_call->call; + } + uint32_t propagation_mask = read_uint32(&inp); + grpc_slice method = read_string_like_slice(&inp); + if (GRPC_SLICE_LENGTH(method) == 0) { + ok = false; + } + grpc_slice host = read_string_like_slice(&inp); + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); + + if (ok) { + call_state *cs = new_call(g_active_call, CLIENT); + cs->call = + grpc_channel_create_call(g_channel, parent_call, propagation_mask, + cq, method, &host, deadline, NULL); + } else { + end(&inp); + } + grpc_slice_unref(method); + grpc_slice_unref(host); + break; + } + // switch the 'current' call + case 11: { + g_active_call = g_active_call->next; + break; + } + // queue some ops on a call + case 12: { + if (g_active_call->type == PENDING_SERVER || + g_active_call->type == ROOT || g_active_call->call == NULL) { + end(&inp); + break; + } + size_t num_ops = next_byte(&inp); + if (num_ops > 6) { + end(&inp); + break; + } + grpc_op *ops = + static_cast(gpr_malloc(sizeof(grpc_op) * num_ops)); + if (num_ops > 0) memset(ops, 0, sizeof(grpc_op) * num_ops); + bool ok = true; + size_t i; + grpc_op *op; + uint8_t has_ops = 0; + for (i = 0; i < num_ops; i++) { + op = &ops[i]; + switch (next_byte(&inp)) { + default: + /* invalid value */ + op->op = (grpc_op_type)-1; + ok = false; + break; + case GRPC_OP_SEND_INITIAL_METADATA: + op->op = GRPC_OP_SEND_INITIAL_METADATA; + has_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA; + read_metadata(&inp, &op->data.send_initial_metadata.count, + &op->data.send_initial_metadata.metadata, + g_active_call); + break; + case GRPC_OP_SEND_MESSAGE: + op->op = GRPC_OP_SEND_MESSAGE; + if (g_active_call->send_message != NULL) { + ok = false; + } else { + has_ops |= 1 << GRPC_OP_SEND_MESSAGE; + g_active_call->send_message = + op->data.send_message.send_message = read_message(&inp); + } + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + has_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT; + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + has_ops |= 1 << GRPC_OP_SEND_STATUS_FROM_SERVER; + read_metadata( + &inp, + &op->data.send_status_from_server.trailing_metadata_count, + &op->data.send_status_from_server.trailing_metadata, + g_active_call); + op->data.send_status_from_server.status = + static_cast(next_byte(&inp)); + op->data.send_status_from_server.status_details = + add_slice_to_unref(g_active_call, + read_buffer_like_slice(&inp)); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + op->op = GRPC_OP_RECV_INITIAL_METADATA; + has_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &g_active_call->recv_initial_metadata; + break; + case GRPC_OP_RECV_MESSAGE: + op->op = GRPC_OP_RECV_MESSAGE; + has_ops |= 1 << GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &g_active_call->recv_message; + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.status = &g_active_call->status; + op->data.recv_status_on_client.trailing_metadata = + &g_active_call->recv_trailing_metadata; + op->data.recv_status_on_client.status_details = + &g_active_call->recv_status_details; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + has_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = + &g_active_call->cancelled; + break; + } + op->reserved = NULL; + op->flags = read_uint32(&inp); + } + if (ok) { + validator *v = make_finished_batch_validator(g_active_call, has_ops); + g_active_call->pending_ops++; + grpc_call_error error = + grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL); + if (error != GRPC_CALL_OK) { + v->validate(v->arg, false); + gpr_free(v); + } + } else { + end(&inp); + } + if (!ok && (has_ops & (1 << GRPC_OP_SEND_MESSAGE))) { + grpc_byte_buffer_destroy(g_active_call->send_message); + g_active_call->send_message = NULL; + } + gpr_free(ops); + + break; + } + // cancel current call + case 13: { + if (g_active_call->type != ROOT && g_active_call->call != NULL) { + grpc_call_cancel(g_active_call->call, NULL); + } else { + end(&inp); + } + break; + } + // get a calls peer + case 14: { + if (g_active_call->type != ROOT && g_active_call->call != NULL) { + free_non_null(grpc_call_get_peer(g_active_call->call)); + } else { + end(&inp); + } + break; + } + // get a channels target + case 15: { + if (g_channel != NULL) { + free_non_null(grpc_channel_get_target(g_channel)); + } else { + end(&inp); + } + break; + } + // send a ping on a channel + case 16: { + if (g_channel != NULL) { + pending_pings++; + grpc_channel_ping(g_channel, cq, + create_validator(decrement, &pending_pings), NULL); + } else { + end(&inp); + } + break; + } + // enable a tracer + case 17: { + char *tracer = read_string(&inp, NULL); + grpc_tracer_set_enabled(tracer, 1); + gpr_free(tracer); + break; + } + // disable a tracer + case 18: { + char *tracer = read_string(&inp, NULL); + grpc_tracer_set_enabled(tracer, 0); + gpr_free(tracer); + break; + } + // request a server call + case 19: { + if (g_server == NULL) { + end(&inp); + break; + } + call_state *cs = new_call(g_active_call, PENDING_SERVER); + cs->pending_ops++; + validator *v = create_validator(finished_request_call, cs); + grpc_call_error error = + grpc_server_request_call(g_server, &cs->call, &cs->call_details, + &cs->recv_initial_metadata, cq, cq, v); + if (error != GRPC_CALL_OK) { + v->validate(v->arg, false); + gpr_free(v); + } + break; + } + // destroy a call + case 20: { + if (g_active_call->type != ROOT && + g_active_call->type != PENDING_SERVER && + g_active_call->call != NULL) { + destroy_call(g_active_call); + } else { + end(&inp); + } + break; + } + // resize the buffer pool + case 21: { + grpc_resource_quota_resize(g_resource_quota, read_uint22(&inp)); + break; + } + // create a secure channel + case 22: { + if (g_channel == NULL) { + char *target = read_string(&inp, NULL); + char *target_uri; + gpr_asprintf(&target_uri, "dns:%s", target); + grpc_channel_args *args = read_args(&inp); + grpc_channel_credentials *creds = read_channel_creds(&inp); + g_channel = grpc_secure_channel_create(creds, target_uri, args, NULL); + GPR_ASSERT(g_channel != NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + gpr_free(target_uri); + gpr_free(target); + grpc_channel_credentials_release(creds); + } else { + end(&inp); + } + break; + } + } + } + + GPR_ASSERT(g_channel == NULL); + GPR_ASSERT(g_server == NULL); + GPR_ASSERT(g_active_call->type == ROOT); + GPR_ASSERT(g_active_call->next == g_active_call); + gpr_free(g_active_call); + + grpc_completion_queue_shutdown(cq); + GPR_ASSERT( + grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL) + .type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + + grpc_resource_quota_unref(g_resource_quota); + + grpc_shutdown(); + return 0; +} diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c deleted file mode 100644 index 88ba6bad83..0000000000 --- a/test/core/end2end/fuzzers/client_fuzzer.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/channel.h" -#include "test/core/util/memory_counters.h" -#include "test/core/util/mock_endpoint.h" - -bool squelch = true; -bool leak_check = true; - -static void discard_write(grpc_slice slice) {} - -static void *tag(int n) { return (void *)(uintptr_t)n; } - -static void dont_log(gpr_log_func_args *args) {} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_test_only_set_slice_hash_seed(0); - struct grpc_memory_counters counters; - if (squelch) gpr_set_log_function(dont_log); - if (leak_check) grpc_memory_counters_init(); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_executor_set_threading(&exec_ctx, false); - - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("client_fuzzer"); - grpc_endpoint *mock_endpoint = - grpc_mock_endpoint_create(discard_write, resource_quota); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_transport *transport = - grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 1); - grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); - - grpc_channel *channel = grpc_channel_create( - &exec_ctx, "test-target", NULL, GRPC_CLIENT_DIRECT_CHANNEL, transport); - grpc_slice host = grpc_slice_from_static_string("localhost"); - grpc_call *call = grpc_channel_create_call( - channel, NULL, 0, cq, grpc_slice_from_static_string("/foo"), &host, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array_init(&initial_metadata_recv); - grpc_byte_buffer *response_payload_recv = NULL; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_status_code status; - grpc_slice details = grpc_empty_slice(); - - grpc_op ops[6]; - memset(ops, 0, sizeof(ops)); - grpc_op *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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->flags = 0; - op->reserved = NULL; - op++; - grpc_call_error error = - grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); - int requested_calls = 1; - GPR_ASSERT(GRPC_CALL_OK == error); - - grpc_mock_endpoint_put_read( - &exec_ctx, mock_endpoint, - grpc_slice_from_copied_buffer((const char *)data, size)); - - grpc_event ev; - while (1) { - grpc_exec_ctx_flush(&exec_ctx); - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - switch (ev.type) { - case GRPC_QUEUE_TIMEOUT: - goto done; - case GRPC_QUEUE_SHUTDOWN: - break; - case GRPC_OP_COMPLETE: - requested_calls--; - break; - } - } - -done: - if (requested_calls) { - grpc_call_cancel(call, NULL); - } - for (int i = 0; i < requested_calls; i++) { - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - } - grpc_completion_queue_shutdown(cq); - for (int i = 0; i < requested_calls; i++) { - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); - } - grpc_call_unref(call); - grpc_completion_queue_destroy(cq); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_slice_unref(details); - grpc_channel_destroy(channel); - if (response_payload_recv != NULL) { - grpc_byte_buffer_destroy(response_payload_recv); - } - grpc_shutdown(); - if (leak_check) { - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); - } - return 0; -} diff --git a/test/core/end2end/fuzzers/client_fuzzer.cc b/test/core/end2end/fuzzers/client_fuzzer.cc new file mode 100644 index 0000000000..88ba6bad83 --- /dev/null +++ b/test/core/end2end/fuzzers/client_fuzzer.cc @@ -0,0 +1,157 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/channel.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/mock_endpoint.h" + +bool squelch = true; +bool leak_check = true; + +static void discard_write(grpc_slice slice) {} + +static void *tag(int n) { return (void *)(uintptr_t)n; } + +static void dont_log(gpr_log_func_args *args) {} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_test_only_set_slice_hash_seed(0); + struct grpc_memory_counters counters; + if (squelch) gpr_set_log_function(dont_log); + if (leak_check) grpc_memory_counters_init(); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_executor_set_threading(&exec_ctx, false); + + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("client_fuzzer"); + grpc_endpoint *mock_endpoint = + grpc_mock_endpoint_create(discard_write, resource_quota); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_transport *transport = + grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 1); + grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); + + grpc_channel *channel = grpc_channel_create( + &exec_ctx, "test-target", NULL, GRPC_CLIENT_DIRECT_CHANNEL, transport); + grpc_slice host = grpc_slice_from_static_string("localhost"); + grpc_call *call = grpc_channel_create_call( + channel, NULL, 0, cq, grpc_slice_from_static_string("/foo"), &host, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array_init(&initial_metadata_recv); + grpc_byte_buffer *response_payload_recv = NULL; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_status_code status; + grpc_slice details = grpc_empty_slice(); + + grpc_op ops[6]; + memset(ops, 0, sizeof(ops)); + grpc_op *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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->flags = 0; + op->reserved = NULL; + op++; + grpc_call_error error = + grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); + int requested_calls = 1; + GPR_ASSERT(GRPC_CALL_OK == error); + + grpc_mock_endpoint_put_read( + &exec_ctx, mock_endpoint, + grpc_slice_from_copied_buffer((const char *)data, size)); + + grpc_event ev; + while (1) { + grpc_exec_ctx_flush(&exec_ctx); + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + switch (ev.type) { + case GRPC_QUEUE_TIMEOUT: + goto done; + case GRPC_QUEUE_SHUTDOWN: + break; + case GRPC_OP_COMPLETE: + requested_calls--; + break; + } + } + +done: + if (requested_calls) { + grpc_call_cancel(call, NULL); + } + for (int i = 0; i < requested_calls; i++) { + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + } + grpc_completion_queue_shutdown(cq); + for (int i = 0; i < requested_calls; i++) { + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + } + grpc_call_unref(call); + grpc_completion_queue_destroy(cq); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_slice_unref(details); + grpc_channel_destroy(channel); + if (response_payload_recv != NULL) { + grpc_byte_buffer_destroy(response_payload_recv); + } + grpc_shutdown(); + if (leak_check) { + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); + } + return 0; +} diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c deleted file mode 100644 index ef4c0a4bfd..0000000000 --- a/test/core/end2end/fuzzers/server_fuzzer.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/server.h" -#include "test/core/util/memory_counters.h" -#include "test/core/util/mock_endpoint.h" - -bool squelch = true; -bool leak_check = true; - -static void discard_write(grpc_slice slice) {} - -static void *tag(int n) { return (void *)(uintptr_t)n; } -static int detag(void *p) { return (int)(uintptr_t)p; } - -static void dont_log(gpr_log_func_args *args) {} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_test_only_set_slice_hash_seed(0); - struct grpc_memory_counters counters; - if (squelch) gpr_set_log_function(dont_log); - if (leak_check) grpc_memory_counters_init(); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_executor_set_threading(&exec_ctx, false); - - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("server_fuzzer"); - grpc_endpoint *mock_endpoint = - grpc_mock_endpoint_create(discard_write, resource_quota); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - grpc_mock_endpoint_put_read( - &exec_ctx, mock_endpoint, - grpc_slice_from_copied_buffer((const char *)data, size)); - - grpc_server *server = grpc_server_create(NULL, NULL); - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_server_register_completion_queue(server, cq, NULL); - // TODO(ctiller): add registered methods (one for POST, one for PUT) - // void *registered_method = - // grpc_server_register_method(server, "/reg", NULL, 0); - grpc_server_start(server); - grpc_transport *transport = - grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 0); - grpc_server_setup_transport(&exec_ctx, server, transport, NULL, NULL); - grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); - - grpc_call *call1 = NULL; - grpc_call_details call_details1; - grpc_metadata_array request_metadata1; - grpc_call_details_init(&call_details1); - grpc_metadata_array_init(&request_metadata1); - int requested_calls = 0; - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(server, &call1, &call_details1, - &request_metadata1, cq, cq, tag(1))); - requested_calls++; - - grpc_event ev; - while (1) { - grpc_exec_ctx_flush(&exec_ctx); - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - switch (ev.type) { - case GRPC_QUEUE_TIMEOUT: - goto done; - case GRPC_QUEUE_SHUTDOWN: - break; - case GRPC_OP_COMPLETE: - switch (detag(ev.tag)) { - case 1: - requested_calls--; - // TODO(ctiller): keep reading that call! - break; - } - } - } - -done: - if (call1 != NULL) grpc_call_unref(call1); - grpc_call_details_destroy(&call_details1); - grpc_metadata_array_destroy(&request_metadata1); - grpc_server_shutdown_and_notify(server, cq, tag(0xdead)); - grpc_server_cancel_all_calls(server); - for (int i = 0; i <= requested_calls; i++) { - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - } - grpc_completion_queue_shutdown(cq); - for (int i = 0; i <= requested_calls; i++) { - ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); - } - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_shutdown(); - if (leak_check) { - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); - } - return 0; -} diff --git a/test/core/end2end/fuzzers/server_fuzzer.cc b/test/core/end2end/fuzzers/server_fuzzer.cc new file mode 100644 index 0000000000..ef4c0a4bfd --- /dev/null +++ b/test/core/end2end/fuzzers/server_fuzzer.cc @@ -0,0 +1,123 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/server.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/mock_endpoint.h" + +bool squelch = true; +bool leak_check = true; + +static void discard_write(grpc_slice slice) {} + +static void *tag(int n) { return (void *)(uintptr_t)n; } +static int detag(void *p) { return (int)(uintptr_t)p; } + +static void dont_log(gpr_log_func_args *args) {} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_test_only_set_slice_hash_seed(0); + struct grpc_memory_counters counters; + if (squelch) gpr_set_log_function(dont_log); + if (leak_check) grpc_memory_counters_init(); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_executor_set_threading(&exec_ctx, false); + + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("server_fuzzer"); + grpc_endpoint *mock_endpoint = + grpc_mock_endpoint_create(discard_write, resource_quota); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + grpc_mock_endpoint_put_read( + &exec_ctx, mock_endpoint, + grpc_slice_from_copied_buffer((const char *)data, size)); + + grpc_server *server = grpc_server_create(NULL, NULL); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_server_register_completion_queue(server, cq, NULL); + // TODO(ctiller): add registered methods (one for POST, one for PUT) + // void *registered_method = + // grpc_server_register_method(server, "/reg", NULL, 0); + grpc_server_start(server); + grpc_transport *transport = + grpc_create_chttp2_transport(&exec_ctx, NULL, mock_endpoint, 0); + grpc_server_setup_transport(&exec_ctx, server, transport, NULL, NULL); + grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); + + grpc_call *call1 = NULL; + grpc_call_details call_details1; + grpc_metadata_array request_metadata1; + grpc_call_details_init(&call_details1); + grpc_metadata_array_init(&request_metadata1); + int requested_calls = 0; + + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(server, &call1, &call_details1, + &request_metadata1, cq, cq, tag(1))); + requested_calls++; + + grpc_event ev; + while (1) { + grpc_exec_ctx_flush(&exec_ctx); + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + switch (ev.type) { + case GRPC_QUEUE_TIMEOUT: + goto done; + case GRPC_QUEUE_SHUTDOWN: + break; + case GRPC_OP_COMPLETE: + switch (detag(ev.tag)) { + case 1: + requested_calls--; + // TODO(ctiller): keep reading that call! + break; + } + } + } + +done: + if (call1 != NULL) grpc_call_unref(call1); + grpc_call_details_destroy(&call_details1); + grpc_metadata_array_destroy(&request_metadata1); + grpc_server_shutdown_and_notify(server, cq, tag(0xdead)); + grpc_server_cancel_all_calls(server); + for (int i = 0; i <= requested_calls; i++) { + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + } + grpc_completion_queue_shutdown(cq); + for (int i = 0; i <= requested_calls; i++) { + ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + } + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + if (leak_check) { + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); + } + return 0; +} diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index f7f996d5c1..7c8e7f420a 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -220,9 +220,9 @@ def main(): 'build': 'private', 'language': 'c', 'secure': True, - 'src': ['test/core/end2end/end2end_tests.c', - 'test/core/end2end/end2end_test_utils.c'] + [ - 'test/core/end2end/tests/%s.c' % t + 'src': ['test/core/end2end/end2end_tests.cc', + 'test/core/end2end/end2end_test_utils.cc'] + [ + 'test/core/end2end/tests/%s.cc' % t for t in sorted(END2END_TESTS.keys())], 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', 'test/core/end2end/end2end_tests.h'], @@ -235,9 +235,9 @@ def main(): 'build': 'private', 'language': 'c', 'secure': False, - 'src': ['test/core/end2end/end2end_nosec_tests.c', - 'test/core/end2end/end2end_test_utils.c'] + [ - 'test/core/end2end/tests/%s.c' % t + 'src': ['test/core/end2end/end2end_nosec_tests.cc', + 'test/core/end2end/end2end_test_utils.cc'] + [ + 'test/core/end2end/tests/%s.cc' % t for t in sorted(END2END_TESTS.keys()) if not END2END_TESTS[t].secure], 'headers': ['test/core/end2end/tests/cancel_test_helpers.h', @@ -252,7 +252,7 @@ def main(): 'build': 'test', 'language': 'c', 'run': False, - 'src': ['test/core/end2end/fixtures/%s.c' % f], + 'src': ['test/core/end2end/fixtures/%s.cc' % f], 'platforms': END2END_FIXTURES[f].platforms, 'ci_platforms': (END2END_FIXTURES[f].platforms if END2END_FIXTURES[f].ci_mac else without( @@ -269,7 +269,7 @@ def main(): 'build': 'test', 'language': 'c', 'secure': False, - 'src': ['test/core/end2end/fixtures/%s.c' % f], + 'src': ['test/core/end2end/fixtures/%s.cc' % f], 'run': False, 'platforms': END2END_FIXTURES[f].platforms, 'ci_platforms': (END2END_FIXTURES[f].platforms diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 89a95edfd7..94f9f98a2a 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -186,8 +186,8 @@ def compatible(fopt, topt): def grpc_end2end_tests(): grpc_cc_library( name = 'end2end_tests', - srcs = ['end2end_tests.c', 'end2end_test_utils.c'] + [ - 'tests/%s.c' % t + srcs = ['end2end_tests.cc', 'end2end_test_utils.cc'] + [ + 'tests/%s.cc' % t for t in sorted(END2END_TESTS.keys())], hdrs = [ 'tests/cancel_test_helpers.h', @@ -205,7 +205,7 @@ def grpc_end2end_tests(): for f, fopt in END2END_FIXTURES.items(): grpc_cc_binary( name = '%s_test' % f, - srcs = ['fixtures/%s.c' % f], + srcs = ['fixtures/%s.cc' % f], language = "C", deps = [ ':end2end_tests', diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c deleted file mode 100644 index c3aca13249..0000000000 --- a/test/core/end2end/goaway_server_test.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" - -#include -#include -#include -#include -#include -#include "src/core/ext/filters/client_channel/lb_policy_factory.h" -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static void *tag(intptr_t i) { return (void *)i; } - -static gpr_mu g_mu; -static int g_resolve_port = -1; -static void (*iomgr_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr, - const char *default_port, - grpc_pollset_set *interested_parties, - grpc_closure *on_done, - grpc_resolved_addresses **addresses); - -static grpc_ares_request *(*iomgr_dns_lookup_ares)( - grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, - const char *default_port, grpc_pollset_set *interested_parties, - grpc_closure *on_done, grpc_lb_addresses **addresses, bool check_grpclb, - char **service_config_json); - -static void set_resolve_port(int port) { - gpr_mu_lock(&g_mu); - g_resolve_port = port; - gpr_mu_unlock(&g_mu); -} - -static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, - const char *default_port, - grpc_pollset_set *interested_parties, - grpc_closure *on_done, - grpc_resolved_addresses **addrs) { - if (0 != strcmp(addr, "test")) { - iomgr_resolve_address(exec_ctx, addr, default_port, interested_parties, - on_done, addrs); - return; - } - - grpc_error *error = GRPC_ERROR_NONE; - gpr_mu_lock(&g_mu); - if (g_resolve_port < 0) { - gpr_mu_unlock(&g_mu); - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); - } else { - *addrs = gpr_malloc(sizeof(**addrs)); - (*addrs)->naddrs = 1; - (*addrs)->addrs = gpr_malloc(sizeof(*(*addrs)->addrs)); - memset((*addrs)->addrs, 0, sizeof(*(*addrs)->addrs)); - struct sockaddr_in *sa = (struct sockaddr_in *)(*addrs)->addrs[0].addr; - sa->sin_family = AF_INET; - sa->sin_addr.s_addr = htonl(0x7f000001); - sa->sin_port = htons((uint16_t)g_resolve_port); - (*addrs)->addrs[0].len = sizeof(*sa); - gpr_mu_unlock(&g_mu); - } - GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); -} - -static grpc_ares_request *my_dns_lookup_ares( - grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, - const char *default_port, grpc_pollset_set *interested_parties, - grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, - char **service_config_json) { - if (0 != strcmp(addr, "test")) { - return iomgr_dns_lookup_ares(exec_ctx, dns_server, addr, default_port, - interested_parties, on_done, lb_addrs, - check_grpclb, service_config_json); - } - - grpc_error *error = GRPC_ERROR_NONE; - gpr_mu_lock(&g_mu); - if (g_resolve_port < 0) { - gpr_mu_unlock(&g_mu); - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); - } else { - *lb_addrs = grpc_lb_addresses_create(1, NULL); - struct sockaddr_in *sa = gpr_zalloc(sizeof(struct sockaddr_in)); - sa->sin_family = AF_INET; - sa->sin_addr.s_addr = htonl(0x7f000001); - sa->sin_port = htons((uint16_t)g_resolve_port); - grpc_lb_addresses_set_address(*lb_addrs, 0, sa, sizeof(*sa), false, NULL, - NULL); - gpr_free(sa); - gpr_mu_unlock(&g_mu); - } - GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); - return NULL; -} - -int main(int argc, char **argv) { - grpc_completion_queue *cq; - cq_verifier *cqv; - grpc_op ops[6]; - grpc_op *op; - - grpc_test_init(argc, argv); - - gpr_mu_init(&g_mu); - grpc_init(); - iomgr_resolve_address = grpc_resolve_address; - iomgr_dns_lookup_ares = grpc_dns_lookup_ares; - grpc_resolve_address = my_resolve_address; - grpc_dns_lookup_ares = my_dns_lookup_ares; - - int was_cancelled1; - int was_cancelled2; - - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array request_metadata1; - grpc_call_details request_details1; - grpc_status_code status1; - grpc_slice details1; - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&request_metadata1); - grpc_call_details_init(&request_details1); - - grpc_metadata_array trailing_metadata_recv2; - grpc_metadata_array request_metadata2; - grpc_call_details request_details2; - grpc_status_code status2; - grpc_slice details2; - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_metadata_array_init(&request_metadata2); - grpc_call_details_init(&request_details2); - - cq = grpc_completion_queue_create_for_next(NULL); - cqv = cq_verifier_create(cq); - - /* reserve two ports */ - int port1 = grpc_pick_unused_port_or_die(); - int port2 = grpc_pick_unused_port_or_die(); - - char *addr; - - grpc_channel_args client_args; - grpc_arg arg_array[1]; - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = 1000; - client_args.args = arg_array; - client_args.num_args = 1; - - /* create a channel that picks first amongst the servers */ - grpc_channel *chan = grpc_insecure_channel_create("test", &client_args, NULL); - /* and an initial call to them */ - grpc_slice host = grpc_slice_from_static_string("127.0.0.1"); - grpc_call *call1 = - grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/foo"), &host, - grpc_timeout_seconds_to_deadline(20), NULL); - /* send initial metadata to probe connectivity */ - memset(ops, 0, sizeof(ops)); - op = 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(call1, ops, - (size_t)(op - ops), - tag(0x101), NULL)); - /* and receive status to probe termination */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = NULL; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call1, ops, - (size_t)(op - ops), - tag(0x102), NULL)); - - /* bring a server up on the first port */ - grpc_server *server1 = grpc_server_create(NULL, NULL); - gpr_asprintf(&addr, "127.0.0.1:%d", port1); - grpc_server_add_insecure_http2_port(server1, addr); - grpc_server_register_completion_queue(server1, cq, NULL); - gpr_free(addr); - grpc_server_start(server1); - - /* request a call to the server */ - grpc_call *server_call1; - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(server1, &server_call1, &request_details1, - &request_metadata1, cq, cq, tag(0x301))); - - set_resolve_port(port1); - - /* first call should now start */ - CQ_EXPECT_COMPLETION(cqv, tag(0x101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0x301), 1); - cq_verify(cqv); - - GPR_ASSERT(GRPC_CHANNEL_READY == - grpc_channel_check_connectivity_state(chan, 0)); - grpc_channel_watch_connectivity_state(chan, GRPC_CHANNEL_READY, - gpr_inf_future(GPR_CLOCK_REALTIME), cq, - tag(0x9999)); - - /* listen for close on the server call to probe for finishing */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled1; - op->flags = 0; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call1, ops, - (size_t)(op - ops), - tag(0x302), NULL)); - - /* shutdown first server: - * we should see a connectivity change and then nothing */ - set_resolve_port(-1); - grpc_server_shutdown_and_notify(server1, cq, tag(0xdead1)); - CQ_EXPECT_COMPLETION(cqv, tag(0x9999), 1); - cq_verify(cqv); - cq_verify_empty(cqv); - - /* and a new call: should go through to server2 when we start it */ - grpc_call *call2 = - grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/foo"), &host, - grpc_timeout_seconds_to_deadline(20), NULL); - /* send initial metadata to probe connectivity */ - memset(ops, 0, sizeof(ops)); - op = 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(call2, ops, - (size_t)(op - ops), - tag(0x201), NULL)); - /* and receive status to probe termination */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = NULL; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call2, ops, - (size_t)(op - ops), - tag(0x202), NULL)); - - /* and bring up second server */ - set_resolve_port(port2); - grpc_server *server2 = grpc_server_create(NULL, NULL); - gpr_asprintf(&addr, "127.0.0.1:%d", port2); - grpc_server_add_insecure_http2_port(server2, addr); - grpc_server_register_completion_queue(server2, cq, NULL); - gpr_free(addr); - grpc_server_start(server2); - - /* request a call to the server */ - grpc_call *server_call2; - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(server2, &server_call2, &request_details2, - &request_metadata2, cq, cq, tag(0x401))); - - /* second call should now start */ - CQ_EXPECT_COMPLETION(cqv, tag(0x201), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0x401), 1); - cq_verify(cqv); - - /* listen for close on the server call to probe for finishing */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled2; - op->flags = 0; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call2, ops, - (size_t)(op - ops), - tag(0x402), NULL)); - - /* shutdown second server: we should see nothing */ - grpc_server_shutdown_and_notify(server2, cq, tag(0xdead2)); - cq_verify_empty(cqv); - - grpc_call_cancel(call1, NULL); - grpc_call_cancel(call2, NULL); - - /* now everything else should finish */ - CQ_EXPECT_COMPLETION(cqv, tag(0x102), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0x202), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0x302), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0x402), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead2), 1); - cq_verify(cqv); - - grpc_call_unref(call1); - grpc_call_unref(call2); - grpc_call_unref(server_call1); - grpc_call_unref(server_call2); - grpc_server_destroy(server1); - grpc_server_destroy(server2); - grpc_channel_destroy(chan); - - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&request_metadata1); - grpc_call_details_destroy(&request_details1); - grpc_slice_unref(details1); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata2); - grpc_call_details_destroy(&request_details2); - grpc_slice_unref(details2); - - cq_verifier_destroy(cqv); - grpc_completion_queue_destroy(cq); - - grpc_shutdown(); - gpr_mu_destroy(&g_mu); - - return 0; -} diff --git a/test/core/end2end/goaway_server_test.cc b/test/core/end2end/goaway_server_test.cc new file mode 100644 index 0000000000..c0d7fb81b5 --- /dev/null +++ b/test/core/end2end/goaway_server_test.cc @@ -0,0 +1,359 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + +#include +#include +#include +#include +#include +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void *tag(intptr_t i) { return (void *)i; } + +static gpr_mu g_mu; +static int g_resolve_port = -1; +static void (*iomgr_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr, + const char *default_port, + grpc_pollset_set *interested_parties, + grpc_closure *on_done, + grpc_resolved_addresses **addresses); + +static grpc_ares_request *(*iomgr_dns_lookup_ares)( + grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, + const char *default_port, grpc_pollset_set *interested_parties, + grpc_closure *on_done, grpc_lb_addresses **addresses, bool check_grpclb, + char **service_config_json); + +static void set_resolve_port(int port) { + gpr_mu_lock(&g_mu); + g_resolve_port = port; + gpr_mu_unlock(&g_mu); +} + +static void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr, + const char *default_port, + grpc_pollset_set *interested_parties, + grpc_closure *on_done, + grpc_resolved_addresses **addrs) { + if (0 != strcmp(addr, "test")) { + iomgr_resolve_address(exec_ctx, addr, default_port, interested_parties, + on_done, addrs); + return; + } + + grpc_error *error = GRPC_ERROR_NONE; + gpr_mu_lock(&g_mu); + if (g_resolve_port < 0) { + gpr_mu_unlock(&g_mu); + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); + } else { + *addrs = + static_cast(gpr_malloc(sizeof(**addrs))); + (*addrs)->naddrs = 1; + (*addrs)->addrs = static_cast( + gpr_malloc(sizeof(*(*addrs)->addrs))); + memset((*addrs)->addrs, 0, sizeof(*(*addrs)->addrs)); + struct sockaddr_in *sa = (struct sockaddr_in *)(*addrs)->addrs[0].addr; + sa->sin_family = AF_INET; + sa->sin_addr.s_addr = htonl(0x7f000001); + sa->sin_port = htons((uint16_t)g_resolve_port); + (*addrs)->addrs[0].len = sizeof(*sa); + gpr_mu_unlock(&g_mu); + } + GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); +} + +static grpc_ares_request *my_dns_lookup_ares( + grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr, + const char *default_port, grpc_pollset_set *interested_parties, + grpc_closure *on_done, grpc_lb_addresses **lb_addrs, bool check_grpclb, + char **service_config_json) { + if (0 != strcmp(addr, "test")) { + return iomgr_dns_lookup_ares(exec_ctx, dns_server, addr, default_port, + interested_parties, on_done, lb_addrs, + check_grpclb, service_config_json); + } + + grpc_error *error = GRPC_ERROR_NONE; + gpr_mu_lock(&g_mu); + if (g_resolve_port < 0) { + gpr_mu_unlock(&g_mu); + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure"); + } else { + *lb_addrs = grpc_lb_addresses_create(1, NULL); + struct sockaddr_in *sa = static_cast( + gpr_zalloc(sizeof(struct sockaddr_in))); + sa->sin_family = AF_INET; + sa->sin_addr.s_addr = htonl(0x7f000001); + sa->sin_port = htons((uint16_t)g_resolve_port); + grpc_lb_addresses_set_address(*lb_addrs, 0, sa, sizeof(*sa), false, NULL, + NULL); + gpr_free(sa); + gpr_mu_unlock(&g_mu); + } + GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); + return NULL; +} + +int main(int argc, char **argv) { + grpc_completion_queue *cq; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + + grpc_test_init(argc, argv); + + gpr_mu_init(&g_mu); + grpc_init(); + iomgr_resolve_address = grpc_resolve_address; + iomgr_dns_lookup_ares = grpc_dns_lookup_ares; + grpc_resolve_address = my_resolve_address; + grpc_dns_lookup_ares = my_dns_lookup_ares; + + int was_cancelled1; + int was_cancelled2; + + grpc_metadata_array trailing_metadata_recv1; + grpc_metadata_array request_metadata1; + grpc_call_details request_details1; + grpc_status_code status1; + grpc_slice details1; + grpc_metadata_array_init(&trailing_metadata_recv1); + grpc_metadata_array_init(&request_metadata1); + grpc_call_details_init(&request_details1); + + grpc_metadata_array trailing_metadata_recv2; + grpc_metadata_array request_metadata2; + grpc_call_details request_details2; + grpc_status_code status2; + grpc_slice details2; + grpc_metadata_array_init(&trailing_metadata_recv2); + grpc_metadata_array_init(&request_metadata2); + grpc_call_details_init(&request_details2); + + cq = grpc_completion_queue_create_for_next(NULL); + cqv = cq_verifier_create(cq); + + /* reserve two ports */ + int port1 = grpc_pick_unused_port_or_die(); + int port2 = grpc_pick_unused_port_or_die(); + + char *addr; + + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + + /* create a channel that picks first amongst the servers */ + grpc_channel *chan = grpc_insecure_channel_create("test", &client_args, NULL); + /* and an initial call to them */ + grpc_slice host = grpc_slice_from_static_string("127.0.0.1"); + grpc_call *call1 = + grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/foo"), &host, + grpc_timeout_seconds_to_deadline(20), NULL); + /* send initial metadata to probe connectivity */ + memset(ops, 0, sizeof(ops)); + op = 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(call1, ops, + (size_t)(op - ops), + tag(0x101), NULL)); + /* and receive status to probe termination */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; + op->data.recv_status_on_client.status = &status1; + op->data.recv_status_on_client.status_details = &details1; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call1, ops, + (size_t)(op - ops), + tag(0x102), NULL)); + + /* bring a server up on the first port */ + grpc_server *server1 = grpc_server_create(NULL, NULL); + gpr_asprintf(&addr, "127.0.0.1:%d", port1); + grpc_server_add_insecure_http2_port(server1, addr); + grpc_server_register_completion_queue(server1, cq, NULL); + gpr_free(addr); + grpc_server_start(server1); + + /* request a call to the server */ + grpc_call *server_call1; + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(server1, &server_call1, &request_details1, + &request_metadata1, cq, cq, tag(0x301))); + + set_resolve_port(port1); + + /* first call should now start */ + CQ_EXPECT_COMPLETION(cqv, tag(0x101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0x301), 1); + cq_verify(cqv); + + GPR_ASSERT(GRPC_CHANNEL_READY == + grpc_channel_check_connectivity_state(chan, 0)); + grpc_channel_watch_connectivity_state(chan, GRPC_CHANNEL_READY, + gpr_inf_future(GPR_CLOCK_REALTIME), cq, + tag(0x9999)); + + /* listen for close on the server call to probe for finishing */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled1; + op->flags = 0; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call1, ops, + (size_t)(op - ops), + tag(0x302), NULL)); + + /* shutdown first server: + * we should see a connectivity change and then nothing */ + set_resolve_port(-1); + grpc_server_shutdown_and_notify(server1, cq, tag(0xdead1)); + CQ_EXPECT_COMPLETION(cqv, tag(0x9999), 1); + cq_verify(cqv); + cq_verify_empty(cqv); + + /* and a new call: should go through to server2 when we start it */ + grpc_call *call2 = + grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/foo"), &host, + grpc_timeout_seconds_to_deadline(20), NULL); + /* send initial metadata to probe connectivity */ + memset(ops, 0, sizeof(ops)); + op = 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(call2, ops, + (size_t)(op - ops), + tag(0x201), NULL)); + /* and receive status to probe termination */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; + op->data.recv_status_on_client.status = &status2; + op->data.recv_status_on_client.status_details = &details2; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call2, ops, + (size_t)(op - ops), + tag(0x202), NULL)); + + /* and bring up second server */ + set_resolve_port(port2); + grpc_server *server2 = grpc_server_create(NULL, NULL); + gpr_asprintf(&addr, "127.0.0.1:%d", port2); + grpc_server_add_insecure_http2_port(server2, addr); + grpc_server_register_completion_queue(server2, cq, NULL); + gpr_free(addr); + grpc_server_start(server2); + + /* request a call to the server */ + grpc_call *server_call2; + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(server2, &server_call2, &request_details2, + &request_metadata2, cq, cq, tag(0x401))); + + /* second call should now start */ + CQ_EXPECT_COMPLETION(cqv, tag(0x201), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0x401), 1); + cq_verify(cqv); + + /* listen for close on the server call to probe for finishing */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled2; + op->flags = 0; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(server_call2, ops, + (size_t)(op - ops), + tag(0x402), NULL)); + + /* shutdown second server: we should see nothing */ + grpc_server_shutdown_and_notify(server2, cq, tag(0xdead2)); + cq_verify_empty(cqv); + + grpc_call_cancel(call1, NULL); + grpc_call_cancel(call2, NULL); + + /* now everything else should finish */ + CQ_EXPECT_COMPLETION(cqv, tag(0x102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0x202), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0x302), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0x402), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead2), 1); + cq_verify(cqv); + + grpc_call_unref(call1); + grpc_call_unref(call2); + grpc_call_unref(server_call1); + grpc_call_unref(server_call2); + grpc_server_destroy(server1); + grpc_server_destroy(server2); + grpc_channel_destroy(chan); + + grpc_metadata_array_destroy(&trailing_metadata_recv1); + grpc_metadata_array_destroy(&request_metadata1); + grpc_call_details_destroy(&request_details1); + grpc_slice_unref(details1); + grpc_metadata_array_destroy(&trailing_metadata_recv2); + grpc_metadata_array_destroy(&request_metadata2); + grpc_call_details_destroy(&request_details2); + grpc_slice_unref(details2); + + cq_verifier_destroy(cqv); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_mu_destroy(&g_mu); + + return 0; +} diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c deleted file mode 100644 index e3fd5a8fbe..0000000000 --- a/test/core/end2end/invalid_call_argument_test.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static void *tag(intptr_t 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; - grpc_slice details; - 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 = grpc_pick_unused_port_or_die(); - 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(5); - g_state.cq = grpc_completion_queue_create_for_next(NULL); - g_state.cqv = cq_verifier_create(g_state.cq); - g_state.details = grpc_empty_slice(); - memset(g_state.ops, 0, sizeof(g_state.ops)); - - if (is_client) { - /* create a call, channel to a non existant server */ - g_state.chan = - grpc_insecure_channel_create("nonexistant:54321", NULL, NULL); - grpc_slice host = grpc_slice_from_static_string("nonexistant"); - g_state.call = grpc_channel_create_call( - g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, - grpc_slice_from_static_string("/Foo"), &host, 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); - 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); - grpc_slice host = grpc_slice_from_static_string("bar"); - g_state.call = grpc_channel_create_call( - g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, - grpc_slice_from_static_string("/Foo"), &host, 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 = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - 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_completion_queue *shutdown_cq; - grpc_call_unref(g_state.call); - cq_verifier_destroy(g_state.cqv); - grpc_channel_destroy(g_state.chan); - grpc_slice_unref(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) { - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_call_unref(g_state.server_call); - grpc_server_shutdown_and_notify(g_state.server, shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), - NULL) - .type == GRPC_OP_COMPLETE); - grpc_completion_queue_destroy(shutdown_cq); - 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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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.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() { - gpr_log(GPR_INFO, "test_send_messages_at_the_same_time"); - - grpc_op *op; - grpc_slice request_payload_slice = - grpc_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.send_message = request_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.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() { - gpr_log(GPR_INFO, "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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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() { - gpr_log(GPR_INFO, "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.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.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() { - gpr_log(GPR_INFO, "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.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() { - gpr_log(GPR_INFO, "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.recv_message = &payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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->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->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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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->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() { - gpr_log(GPR_INFO, "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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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() { - gpr_log(GPR_INFO, "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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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() { - gpr_log(GPR_INFO, "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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 = &status_details; - 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() { - gpr_log(GPR_INFO, "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() { - gpr_log(GPR_INFO, "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(); -} - -static void test_invalid_initial_metadata_reserved_key() { - gpr_log(GPR_INFO, "test_invalid_initial_metadata_reserved_key"); - - grpc_metadata metadata; - metadata.key = grpc_slice_from_static_string(":start_with_colon"); - metadata.value = grpc_slice_from_static_string("value"); - - grpc_op *op; - prepare_test(1); - op = g_state.ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &metadata; - 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(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_invalid_initial_metadata_reserved_key(); - 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/invalid_call_argument_test.cc b/test/core/end2end/invalid_call_argument_test.cc new file mode 100644 index 0000000000..ac704a6bc0 --- /dev/null +++ b/test/core/end2end/invalid_call_argument_test.cc @@ -0,0 +1,615 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void *tag(intptr_t 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; + grpc_slice details; + 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 = grpc_pick_unused_port_or_die(); + 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(5); + g_state.cq = grpc_completion_queue_create_for_next(NULL); + g_state.cqv = cq_verifier_create(g_state.cq); + g_state.details = grpc_empty_slice(); + memset(g_state.ops, 0, sizeof(g_state.ops)); + + if (is_client) { + /* create a call, channel to a non existant server */ + g_state.chan = + grpc_insecure_channel_create("nonexistant:54321", NULL, NULL); + grpc_slice host = grpc_slice_from_static_string("nonexistant"); + g_state.call = grpc_channel_create_call( + g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, + grpc_slice_from_static_string("/Foo"), &host, 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); + 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); + grpc_slice host = grpc_slice_from_static_string("bar"); + g_state.call = grpc_channel_create_call( + g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, + grpc_slice_from_static_string("/Foo"), &host, 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 = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + 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_completion_queue *shutdown_cq; + grpc_call_unref(g_state.call); + cq_verifier_destroy(g_state.cqv); + grpc_channel_destroy(g_state.chan); + grpc_slice_unref(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) { + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_call_unref(g_state.server_call); + grpc_server_shutdown_and_notify(g_state.server, shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_destroy(shutdown_cq); + 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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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.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() { + gpr_log(GPR_INFO, "test_send_messages_at_the_same_time"); + + grpc_op *op; + grpc_slice request_payload_slice = + grpc_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.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = static_cast(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() { + gpr_log(GPR_INFO, "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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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() { + gpr_log(GPR_INFO, "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.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.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() { + gpr_log(GPR_INFO, "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.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() { + gpr_log(GPR_INFO, "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.recv_message = &payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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->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->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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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->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() { + gpr_log(GPR_INFO, "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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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() { + gpr_log(GPR_INFO, "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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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() { + gpr_log(GPR_INFO, "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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 = &status_details; + 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() { + gpr_log(GPR_INFO, "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() { + gpr_log(GPR_INFO, "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(); +} + +static void test_invalid_initial_metadata_reserved_key() { + gpr_log(GPR_INFO, "test_invalid_initial_metadata_reserved_key"); + + grpc_metadata metadata; + metadata.key = grpc_slice_from_static_string(":start_with_colon"); + metadata.value = grpc_slice_from_static_string("value"); + + grpc_op *op; + prepare_test(1); + op = g_state.ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = &metadata; + 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(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_invalid_initial_metadata_reserved_key(); + 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/multiple_server_queues_test.c b/test/core/end2end/multiple_server_queues_test.c deleted file mode 100644 index f231c62dd0..0000000000 --- a/test/core/end2end/multiple_server_queues_test.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_completion_queue *cq1; - grpc_completion_queue *cq2; - grpc_completion_queue *cq3; - grpc_completion_queue_attributes attr; - - grpc_server *server; - - grpc_test_init(argc, argv); - grpc_init(); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_NEXT; - attr.cq_polling_type = GRPC_CQ_DEFAULT_POLLING; - cq1 = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - attr.cq_polling_type = GRPC_CQ_NON_LISTENING; - cq2 = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - attr.cq_polling_type = GRPC_CQ_NON_POLLING; - cq3 = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - server = grpc_server_create(NULL, NULL); - grpc_server_register_completion_queue(server, cq1, NULL); - grpc_server_add_insecure_http2_port(server, "[::]:0"); - grpc_server_register_completion_queue(server, cq2, NULL); - grpc_server_register_completion_queue(server, cq3, NULL); - - grpc_server_start(server); - grpc_server_shutdown_and_notify(server, cq2, NULL); - grpc_completion_queue_next(cq2, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); /* cue queue hang */ - grpc_completion_queue_shutdown(cq1); - grpc_completion_queue_shutdown(cq2); - grpc_completion_queue_shutdown(cq3); - - grpc_completion_queue_next(cq1, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_completion_queue_next(cq2, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_completion_queue_next(cq3, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq1); - grpc_completion_queue_destroy(cq2); - grpc_completion_queue_destroy(cq3); - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/multiple_server_queues_test.cc b/test/core/end2end/multiple_server_queues_test.cc new file mode 100644 index 0000000000..f231c62dd0 --- /dev/null +++ b/test/core/end2end/multiple_server_queues_test.cc @@ -0,0 +1,71 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_completion_queue *cq1; + grpc_completion_queue *cq2; + grpc_completion_queue *cq3; + grpc_completion_queue_attributes attr; + + grpc_server *server; + + grpc_test_init(argc, argv); + grpc_init(); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + attr.cq_polling_type = GRPC_CQ_DEFAULT_POLLING; + cq1 = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + attr.cq_polling_type = GRPC_CQ_NON_LISTENING; + cq2 = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + attr.cq_polling_type = GRPC_CQ_NON_POLLING; + cq3 = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + server = grpc_server_create(NULL, NULL); + grpc_server_register_completion_queue(server, cq1, NULL); + grpc_server_add_insecure_http2_port(server, "[::]:0"); + grpc_server_register_completion_queue(server, cq2, NULL); + grpc_server_register_completion_queue(server, cq3, NULL); + + grpc_server_start(server); + grpc_server_shutdown_and_notify(server, cq2, NULL); + grpc_completion_queue_next(cq2, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); /* cue queue hang */ + grpc_completion_queue_shutdown(cq1); + grpc_completion_queue_shutdown(cq2); + grpc_completion_queue_shutdown(cq3); + + grpc_completion_queue_next(cq1, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_completion_queue_next(cq2, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_completion_queue_next(cq3, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq1); + grpc_completion_queue_destroy(cq2); + grpc_completion_queue_destroy(cq3); + grpc_shutdown(); + return 0; +} diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c deleted file mode 100644 index 962499bb4f..0000000000 --- a/test/core/end2end/no_server_test.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/test_config.h" - -static void *tag(intptr_t i) { return (void *)i; } - -int main(int argc, char **argv) { - grpc_channel *chan; - grpc_call *call; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2); - grpc_completion_queue *cq; - cq_verifier *cqv; - grpc_op ops[6]; - grpc_op *op; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - grpc_slice details; - - grpc_test_init(argc, argv); - grpc_init(); - - grpc_metadata_array_init(&trailing_metadata_recv); - - cq = grpc_completion_queue_create_for_next(NULL); - cqv = cq_verifier_create(cq); - - /* create a call, channel to a non existant server */ - chan = grpc_insecure_channel_create("nonexistant:54321", NULL, NULL); - grpc_slice host = grpc_slice_from_static_string("nonexistant"); - call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/Foo"), &host, - deadline, NULL); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( - call, ops, (size_t)(op - ops), tag(1), NULL)); - /* verify that all tags get completed */ - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); - - grpc_completion_queue_shutdown(cq); - while ( - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type != GRPC_QUEUE_SHUTDOWN) - ; - grpc_completion_queue_destroy(cq); - grpc_call_unref(call); - grpc_channel_destroy(chan); - cq_verifier_destroy(cqv); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/no_server_test.cc b/test/core/end2end/no_server_test.cc new file mode 100644 index 0000000000..962499bb4f --- /dev/null +++ b/test/core/end2end/no_server_test.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/test_config.h" + +static void *tag(intptr_t i) { return (void *)i; } + +int main(int argc, char **argv) { + grpc_channel *chan; + grpc_call *call; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2); + grpc_completion_queue *cq; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array trailing_metadata_recv; + grpc_status_code status; + grpc_slice details; + + grpc_test_init(argc, argv); + grpc_init(); + + grpc_metadata_array_init(&trailing_metadata_recv); + + cq = grpc_completion_queue_create_for_next(NULL); + cqv = cq_verifier_create(cq); + + /* create a call, channel to a non existant server */ + chan = grpc_insecure_channel_create("nonexistant:54321", NULL, NULL); + grpc_slice host = grpc_slice_from_static_string("nonexistant"); + call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/Foo"), &host, + deadline, NULL); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( + call, ops, (size_t)(op - ops), tag(1), NULL)); + /* verify that all tags get completed */ + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); + + grpc_completion_queue_shutdown(cq); + while ( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type != GRPC_QUEUE_SHUTDOWN) + ; + grpc_completion_queue_destroy(cq); + grpc_call_unref(call); + grpc_channel_destroy(chan); + cq_verifier_destroy(cqv); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/end2end/tests/authority_not_supported.c b/test/core/end2end/tests/authority_not_supported.c deleted file mode 100644 index b54d6d0d6f..0000000000 --- a/test/core/end2end/tests/authority_not_supported.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Request/response with metadata and payload.*/ -static void test_with_authority_header(grpc_end2end_test_config config) { - grpc_call *c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_end2end_test_fixture f = - begin_test(config, "test_with_authority_header", NULL, NULL); - 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_byte_buffer *response_payload_recv = NULL; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), &host, - deadline, NULL); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_CANCELLED); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void authority_not_supported(grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - return; - } - test_with_authority_header(config); -} - -void authority_not_supported_pre_init(void) {} diff --git a/test/core/end2end/tests/authority_not_supported.cc b/test/core/end2end/tests/authority_not_supported.cc new file mode 100644 index 0000000000..b54d6d0d6f --- /dev/null +++ b/test/core/end2end/tests/authority_not_supported.cc @@ -0,0 +1,188 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Request/response with metadata and payload.*/ +static void test_with_authority_header(grpc_end2end_test_config config) { + grpc_call *c; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), + grpc_slice_from_static_string("val1"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key2"), + grpc_slice_from_static_string("val2"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_end2end_test_fixture f = + begin_test(config, "test_with_authority_header", NULL, NULL); + 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_byte_buffer *response_payload_recv = NULL; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), &host, + deadline, NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_c; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_CANCELLED); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void authority_not_supported(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { + return; + } + test_with_authority_header(config); +} + +void authority_not_supported_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c deleted file mode 100644 index 32093f2ecf..0000000000 --- a/test/core/end2end/tests/bad_hostname.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); - config.init_server(&f, server_args); - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_fixture f) { - grpc_call *c; - 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_slice details; - - grpc_slice host = grpc_slice_from_static_string("slartibartfast.local"); - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), &host, - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_INTERNAL); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request", NULL, NULL); - simple_request_body(f); - end_test(&f); - config.tear_down_data(&f); -} - -void bad_hostname(grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) { - test_invoke_simple_request(config); - } -} - -void bad_hostname_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_hostname.cc b/test/core/end2end/tests/bad_hostname.cc new file mode 100644 index 0000000000..32093f2ecf --- /dev/null +++ b/test/core/end2end/tests/bad_hostname.cc @@ -0,0 +1,171 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_client(&f, client_args); + config.init_server(&f, server_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_fixture f) { + grpc_call *c; + 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_slice details; + + grpc_slice host = grpc_slice_from_static_string("slartibartfast.local"); + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), &host, + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_INTERNAL); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(f); + end_test(&f); + config.tear_down_data(&f); +} + +void bad_hostname(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) { + test_invoke_simple_request(config); + } +} + +void bad_hostname_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_ping.c b/test/core/end2end/tests/bad_ping.c deleted file mode 100644 index 34cc8e78cd..0000000000 --- a/test/core/end2end/tests/bad_ping.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" - -#define MAX_PING_STRIKES 1 - -static void *tag(intptr_t t) { return (void *)t; } - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), - NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture *f) { - if (!f->server) return; - 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_bad_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_arg client_a[] = { - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS, - .value.integer = 10}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, - .value.integer = 0}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_BDP_PROBE, - .value.integer = 0}}; - grpc_arg server_a[] = { - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, - .value.integer = 300000 /* 5 minutes */}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MAX_PING_STRIKES, - .value.integer = MAX_PING_STRIKES}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_BDP_PROBE, - .value.integer = 0}}; - grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(client_a), - .args = client_a}; - grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), - .args = server_a}; - - config.init_client(&f, &client_args); - config.init_server(&f, &server_args); - - grpc_call *c; - grpc_call *s; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - 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_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - 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.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->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); - - // Send too many pings to the server to trigger the punishment: - // Each ping will trigger a ping strike, and we need at least MAX_PING_STRIKES - // strikes to trigger the punishment. So (MAX_PING_STRIKES + 1) pings are - // needed here. - int i; - for (i = 1; i <= MAX_PING_STRIKES + 1; i++) { - grpc_channel_ping(f.client, f.cq, tag(200 + i), NULL); - CQ_EXPECT_COMPLETION(cqv, tag(200 + i), 1); - if (i == MAX_PING_STRIKES + 1) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - } - cq_verify(cqv); - } - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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_verify(cqv); - - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); - cq_verify(cqv); - - grpc_call_unref(s); - - // The connection should be closed immediately after the misbehaved pings, - // the in-progress RPC should fail. - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void bad_ping(grpc_end2end_test_config config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_bad_ping(config); -} - -void bad_ping_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc new file mode 100644 index 0000000000..50e02ed720 --- /dev/null +++ b/test/core/end2end/tests/bad_ping.cc @@ -0,0 +1,227 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" + +#define MAX_PING_STRIKES 1 + +static void *tag(intptr_t t) { return (void *)t; } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), + NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_bad_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_arg client_a[3]; + client_a[0].type = GRPC_ARG_INTEGER; + client_a[0].key = + const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); + client_a[0].value.integer = 10; + client_a[1].type = GRPC_ARG_INTEGER; + client_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA); + client_a[1].value.integer = 0; + client_a[2].type = GRPC_ARG_INTEGER; + client_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); + client_a[2].value.integer = 0; + grpc_arg server_a[3]; + server_a[0].type = GRPC_ARG_INTEGER; + server_a[0].key = + const_cast(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS); + server_a[0].value.integer = 300000 /* 5 minutes */; + server_a[1].type = GRPC_ARG_INTEGER; + server_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES); + server_a[1].value.integer = MAX_PING_STRIKES; + server_a[2].type = GRPC_ARG_INTEGER; + server_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); + server_a[2].value.integer = 0; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + + config.init_client(&f, &client_args); + config.init_server(&f, &server_args); + + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); + 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_slice details; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + 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.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->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); + + // Send too many pings to the server to trigger the punishment: + // Each ping will trigger a ping strike, and we need at least MAX_PING_STRIKES + // strikes to trigger the punishment. So (MAX_PING_STRIKES + 1) pings are + // needed here. + int i; + for (i = 1; i <= MAX_PING_STRIKES + 1; i++) { + grpc_channel_ping(f.client, f.cq, tag(200 + i), NULL); + CQ_EXPECT_COMPLETION(cqv, tag(200 + i), 1); + if (i == MAX_PING_STRIKES + 1) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + } + cq_verify(cqv); + } + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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_verify(cqv); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); + cq_verify(cqv); + + grpc_call_unref(s); + + // The connection should be closed immediately after the misbehaved pings, + // the in-progress RPC should fail. + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void bad_ping(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + test_bad_ping(config); +} + +void bad_ping_pre_init(void) {} diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c deleted file mode 100644 index e949daee1d..0000000000 --- a/test/core/end2end/tests/binary_metadata.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Request/response with metadata and payload.*/ -static void test_request_response_with_metadata_and_payload( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = { - {grpc_slice_from_static_string("key1-bin"), - grpc_slice_from_static_string( - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key2-bin"), - grpc_slice_from_static_string( - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_metadata meta_s[2] = { - {grpc_slice_from_static_string("key3-bin"), - grpc_slice_from_static_string( - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key4-bin"), - grpc_slice_from_static_string( - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_end2end_test_fixture f = begin_test( - config, "test_request_response_with_metadata_and_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_string = grpc_slice_from_static_string( - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12" - "\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24" - "\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36" - "\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48" - "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a" - "\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c" - "\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e" - "\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2" - "\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4" - "\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6" - "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" - "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea" - "\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc" - "\xfd\xfe\xff"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT( - 0 == - grpc_slice_str_cmp( - details, - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" - "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" - "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" - "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" - "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" - "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" - "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" - "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" - "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0" - "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" - "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" - "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" - "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0" - "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata( - &request_metadata_recv, "key1-bin", - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc")); - GPR_ASSERT(contains_metadata( - &request_metadata_recv, "key2-bin", - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d")); - GPR_ASSERT(contains_metadata( - &initial_metadata_recv, "key3-bin", - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee")); - GPR_ASSERT(contains_metadata( - &initial_metadata_recv, "key4-bin", - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void binary_metadata(grpc_end2end_test_config config) { - test_request_response_with_metadata_and_payload(config); -} - -void binary_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/binary_metadata.cc b/test/core/end2end/tests/binary_metadata.cc new file mode 100644 index 0000000000..e949daee1d --- /dev/null +++ b/test/core/end2end/tests/binary_metadata.cc @@ -0,0 +1,320 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Request/response with metadata and payload.*/ +static void test_request_response_with_metadata_and_payload( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_metadata meta_c[2] = { + {grpc_slice_from_static_string("key1-bin"), + grpc_slice_from_static_string( + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key2-bin"), + grpc_slice_from_static_string( + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_metadata meta_s[2] = { + {grpc_slice_from_static_string("key3-bin"), + grpc_slice_from_static_string( + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key4-bin"), + grpc_slice_from_static_string( + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_end2end_test_fixture f = begin_test( + config, "test_request_response_with_metadata_and_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_c; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_s; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_string = grpc_slice_from_static_string( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12" + "\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24" + "\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36" + "\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48" + "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a" + "\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c" + "\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e" + "\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2" + "\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4" + "\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6" + "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" + "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea" + "\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc" + "\xfd\xfe\xff"); + op->data.send_status_from_server.status_details = &status_string; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT( + 0 == + grpc_slice_str_cmp( + details, + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" + "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" + "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" + "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" + "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" + "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" + "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" + "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0" + "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" + "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" + "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0" + "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); + GPR_ASSERT(contains_metadata( + &request_metadata_recv, "key1-bin", + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc")); + GPR_ASSERT(contains_metadata( + &request_metadata_recv, "key2-bin", + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d")); + GPR_ASSERT(contains_metadata( + &initial_metadata_recv, "key3-bin", + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee")); + GPR_ASSERT(contains_metadata( + &initial_metadata_recv, "key4-bin", + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void binary_metadata(grpc_end2end_test_config config) { + test_request_response_with_metadata_and_payload(config); +} + +void binary_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c deleted file mode 100644 index 600005c9a9..0000000000 --- a/test/core/end2end/tests/call_creds.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static const char iam_token[] = "token"; -static const char iam_selector[] = "selector"; -static const char overridden_iam_token[] = "overridden_token"; -static const char overridden_iam_selector[] = "overridden_selector"; - -typedef enum { NONE, OVERRIDE, DESTROY } override_mode; - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - int fail_server_auth_check) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - f = config.create_fixture(NULL, NULL); - config.init_client(&f, NULL); - if (fail_server_auth_check) { - grpc_arg fail_auth_arg = { - GRPC_ARG_STRING, FAIL_AUTH_CHECK_SERVER_ARG_NAME, {NULL}}; - grpc_channel_args args; - args.num_args = 1; - args.args = &fail_auth_arg; - config.init_server(&f, &args); - } else { - config.init_server(&f, NULL); - } - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void print_auth_context(int is_client, const grpc_auth_context *ctx) { - const grpc_auth_property *p; - grpc_auth_property_iterator it; - gpr_log(GPR_INFO, "%s peer:", is_client ? "client" : "server"); - gpr_log(GPR_INFO, "\tauthenticated: %s", - grpc_auth_context_peer_is_authenticated(ctx) ? "YES" : "NO"); - it = grpc_auth_context_peer_identity(ctx); - while ((p = grpc_auth_property_iterator_next(&it)) != NULL) { - gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value); - } - gpr_log(GPR_INFO, "\tall properties:"); - it = grpc_auth_context_property_iterator(ctx); - while ((p = grpc_auth_property_iterator_next(&it)) != NULL) { - gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value); - } -} - -static void request_response_with_payload_and_call_creds( - const char *test_name, grpc_end2end_test_config config, - override_mode mode) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_end2end_test_fixture f; - cq_verifier *cqv; - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_call_credentials *creds = NULL; - grpc_auth_context *s_auth_context = NULL; - grpc_auth_context *c_auth_context = NULL; - - f = begin_test(config, test_name, 0); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); - GPR_ASSERT(creds != NULL); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - switch (mode) { - case NONE: - break; - case OVERRIDE: - grpc_call_credentials_release(creds); - creds = grpc_google_iam_credentials_create(overridden_iam_token, - overridden_iam_selector, NULL); - GPR_ASSERT(creds != NULL); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - break; - case DESTROY: - GPR_ASSERT(grpc_call_set_credentials(c, NULL) == GRPC_CALL_OK); - break; - } - grpc_call_credentials_release(creds); - - 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - s_auth_context = grpc_call_auth_context(s); - GPR_ASSERT(s_auth_context != NULL); - print_auth_context(0, s_auth_context); - grpc_auth_context_release(s_auth_context); - - c_auth_context = grpc_call_auth_context(c); - GPR_ASSERT(c_auth_context != NULL); - print_auth_context(1, c_auth_context); - grpc_auth_context_release(c_auth_context); - - /* Cannot set creds on the server call object. */ - GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - - switch (mode) { - case NONE: - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - iam_token)); - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - iam_selector)); - break; - case OVERRIDE: - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - overridden_iam_token)); - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - overridden_iam_selector)); - break; - case DESTROY: - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - iam_token)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - iam_selector)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - overridden_iam_token)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - overridden_iam_selector)); - break; - } - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -static void test_request_response_with_payload_and_call_creds( - grpc_end2end_test_config config) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_call_creds", config, NONE); -} - -static void test_request_response_with_payload_and_overridden_call_creds( - grpc_end2end_test_config config) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_overridden_call_creds", config, - OVERRIDE); -} - -static void test_request_response_with_payload_and_deleted_call_creds( - grpc_end2end_test_config config) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_deleted_call_creds", config, - DESTROY); -} - -static void test_request_with_server_rejecting_client_creds( - grpc_end2end_test_config config) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_end2end_test_fixture f; - gpr_timespec deadline = five_seconds_from_now(); - cq_verifier *cqv; - 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_slice details; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_call_credentials *creds; - - f = begin_test(config, "test_request_with_server_rejecting_client_creds", 1); - cqv = cq_verifier_create(f.cq); - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); - GPR_ASSERT(creds != NULL); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - grpc_call_credentials_release(creds); - - 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); - - memset(ops, 0, sizeof(ops)); - 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->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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(error == GRPC_CALL_OK); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void call_creds(grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) { - test_request_response_with_payload_and_call_creds(config); - test_request_response_with_payload_and_overridden_call_creds(config); - test_request_response_with_payload_and_deleted_call_creds(config); - test_request_with_server_rejecting_client_creds(config); - } -} - -void call_creds_pre_init(void) {} diff --git a/test/core/end2end/tests/call_creds.cc b/test/core/end2end/tests/call_creds.cc new file mode 100644 index 0000000000..dfe6d19160 --- /dev/null +++ b/test/core/end2end/tests/call_creds.cc @@ -0,0 +1,479 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static const char iam_token[] = "token"; +static const char iam_selector[] = "selector"; +static const char overridden_iam_token[] = "overridden_token"; +static const char overridden_iam_selector[] = "overridden_selector"; + +typedef enum { NONE, OVERRIDE, DESTROY } override_mode; + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + int fail_server_auth_check) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(NULL, NULL); + config.init_client(&f, NULL); + if (fail_server_auth_check) { + grpc_arg fail_auth_arg = { + GRPC_ARG_STRING, + const_cast(FAIL_AUTH_CHECK_SERVER_ARG_NAME), + {NULL}}; + grpc_channel_args args; + args.num_args = 1; + args.args = &fail_auth_arg; + config.init_server(&f, &args); + } else { + config.init_server(&f, NULL); + } + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void print_auth_context(int is_client, const grpc_auth_context *ctx) { + const grpc_auth_property *p; + grpc_auth_property_iterator it; + gpr_log(GPR_INFO, "%s peer:", is_client ? "client" : "server"); + gpr_log(GPR_INFO, "\tauthenticated: %s", + grpc_auth_context_peer_is_authenticated(ctx) ? "YES" : "NO"); + it = grpc_auth_context_peer_identity(ctx); + while ((p = grpc_auth_property_iterator_next(&it)) != NULL) { + gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value); + } + gpr_log(GPR_INFO, "\tall properties:"); + it = grpc_auth_context_property_iterator(ctx); + while ((p = grpc_auth_property_iterator_next(&it)) != NULL) { + gpr_log(GPR_INFO, "\t\t%s: %s", p->name, p->value); + } +} + +static void request_response_with_payload_and_call_creds( + const char *test_name, grpc_end2end_test_config config, + override_mode mode) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_end2end_test_fixture f; + cq_verifier *cqv; + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + grpc_call_credentials *creds = NULL; + grpc_auth_context *s_auth_context = NULL; + grpc_auth_context *c_auth_context = NULL; + + f = begin_test(config, test_name, 0); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); + GPR_ASSERT(creds != NULL); + GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); + switch (mode) { + case NONE: + break; + case OVERRIDE: + grpc_call_credentials_release(creds); + creds = grpc_google_iam_credentials_create(overridden_iam_token, + overridden_iam_selector, NULL); + GPR_ASSERT(creds != NULL); + GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); + break; + case DESTROY: + GPR_ASSERT(grpc_call_set_credentials(c, NULL) == GRPC_CALL_OK); + break; + } + grpc_call_credentials_release(creds); + + 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + s_auth_context = grpc_call_auth_context(s); + GPR_ASSERT(s_auth_context != NULL); + print_auth_context(0, s_auth_context); + grpc_auth_context_release(s_auth_context); + + c_auth_context = grpc_call_auth_context(c); + GPR_ASSERT(c_auth_context != NULL); + print_auth_context(1, c_auth_context); + grpc_auth_context_release(c_auth_context); + + /* Cannot set creds on the server call object. */ + GPR_ASSERT(grpc_call_set_credentials(s, NULL) != GRPC_CALL_OK); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); + + switch (mode) { + case NONE: + GPR_ASSERT(contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + iam_token)); + GPR_ASSERT(contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + iam_selector)); + break; + case OVERRIDE: + GPR_ASSERT(contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + overridden_iam_token)); + GPR_ASSERT(contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + overridden_iam_selector)); + break; + case DESTROY: + GPR_ASSERT(!contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + iam_token)); + GPR_ASSERT(!contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + iam_selector)); + GPR_ASSERT(!contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + overridden_iam_token)); + GPR_ASSERT(!contains_metadata(&request_metadata_recv, + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + overridden_iam_selector)); + break; + } + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +static void test_request_response_with_payload_and_call_creds( + grpc_end2end_test_config config) { + request_response_with_payload_and_call_creds( + "test_request_response_with_payload_and_call_creds", config, NONE); +} + +static void test_request_response_with_payload_and_overridden_call_creds( + grpc_end2end_test_config config) { + request_response_with_payload_and_call_creds( + "test_request_response_with_payload_and_overridden_call_creds", config, + OVERRIDE); +} + +static void test_request_response_with_payload_and_deleted_call_creds( + grpc_end2end_test_config config) { + request_response_with_payload_and_call_creds( + "test_request_response_with_payload_and_deleted_call_creds", config, + DESTROY); +} + +static void test_request_with_server_rejecting_client_creds( + grpc_end2end_test_config config) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_end2end_test_fixture f; + gpr_timespec deadline = five_seconds_from_now(); + cq_verifier *cqv; + 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_slice details; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_call_credentials *creds; + + f = begin_test(config, "test_request_with_server_rejecting_client_creds", 1); + cqv = cq_verifier_create(f.cq); + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); + GPR_ASSERT(creds != NULL); + GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); + grpc_call_credentials_release(creds); + + 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); + + memset(ops, 0, sizeof(ops)); + 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->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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(error == GRPC_CALL_OK); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void call_creds(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) { + test_request_response_with_payload_and_call_creds(config); + test_request_response_with_payload_and_overridden_call_creds(config); + test_request_response_with_payload_and_deleted_call_creds(config); + test_request_with_server_rejecting_client_creds(config); + } +} + +void call_creds_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c deleted file mode 100644 index c3ac0c3201..0000000000 --- a/test/core/end2end/tests/cancel_after_accept.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/service_config.h" - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - cancellation_mode mode, - bool use_service_config, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, - mode.name, use_service_config ? "service_config" : "client_api"); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel after accept, no payload */ -static void test_cancel_after_accept(grpc_end2end_test_config config, - cancellation_mode mode, - bool use_service_config) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_call *s; - 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_slice details; - grpc_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - grpc_channel_args *args = NULL; - if (use_service_config) { - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"timeout\": \"5s\"\n" - " } ]\n" - "}"; - args = grpc_channel_args_copy_and_add(args, &arg, 1); - } - - grpc_end2end_test_fixture f = begin_test(config, "cancel_after_accept", mode, - use_service_config, args, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = use_service_config - ? gpr_inf_future(GPR_CLOCK_MONOTONIC) - : five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/service/method"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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->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_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - 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(2)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_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_MESSAGE; - op->data.send_message.send_message = response_payload; - 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(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); - - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); - - if (args != NULL) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_after_accept(grpc_end2end_test_config config) { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_after_accept(config, cancellation_modes[i], - false /* use_service_config */); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - test_cancel_after_accept(config, cancellation_modes[i], - true /* use_service_config */); - } - } -} - -void cancel_after_accept_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_accept.cc b/test/core/end2end/tests/cancel_after_accept.cc new file mode 100644 index 0000000000..58e807b83b --- /dev/null +++ b/test/core/end2end/tests/cancel_after_accept.cc @@ -0,0 +1,271 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/service_config.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + cancellation_mode mode, + bool use_service_config, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, + mode.name, use_service_config ? "service_config" : "client_api"); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel after accept, no payload */ +static void test_cancel_after_accept(grpc_end2end_test_config config, + cancellation_mode mode, + bool use_service_config) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_call *s; + 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_slice details; + grpc_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + int was_cancelled = 2; + + grpc_channel_args *args = NULL; + if (use_service_config) { + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}"); + args = grpc_channel_args_copy_and_add(args, &arg, 1); + } + + grpc_end2end_test_fixture f = begin_test(config, "cancel_after_accept", mode, + use_service_config, args, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = use_service_config + ? gpr_inf_future(GPR_CLOCK_MONOTONIC) + : five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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->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_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + 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(2)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_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_MESSAGE; + op->data.send_message.send_message = response_payload; + 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(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); + + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); + GPR_ASSERT(was_cancelled == 1); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + grpc_call_unref(s); + + if (args != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_after_accept(grpc_end2end_test_config config) { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_after_accept(config, cancellation_modes[i], + false /* use_service_config */); + if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && + cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { + test_cancel_after_accept(config, cancellation_modes[i], + true /* use_service_config */); + } + } +} + +void cancel_after_accept_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c deleted file mode 100644 index 0e2a751d83..0000000000 --- a/test/core/end2end/tests/cancel_after_client_done.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - cancellation_mode mode, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, - mode.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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel after accept with a writes closed, no payload */ -static void test_cancel_after_accept_and_writes_closed( - grpc_end2end_test_config config, cancellation_mode mode) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_call *s; - grpc_end2end_test_fixture f = begin_test( - config, "test_cancel_after_accept_and_writes_closed", mode, NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - 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_slice details; - grpc_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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->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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - 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(2)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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++; - 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.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); - - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_after_client_done(grpc_end2end_test_config config) { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]); - } -} - -void cancel_after_client_done_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_client_done.cc b/test/core/end2end/tests/cancel_after_client_done.cc new file mode 100644 index 0000000000..0e2a751d83 --- /dev/null +++ b/test/core/end2end/tests/cancel_after_client_done.cc @@ -0,0 +1,235 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + cancellation_mode mode, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, + mode.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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel after accept with a writes closed, no payload */ +static void test_cancel_after_accept_and_writes_closed( + grpc_end2end_test_config config, cancellation_mode mode) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_call *s; + grpc_end2end_test_fixture f = begin_test( + config, "test_cancel_after_accept_and_writes_closed", mode, NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + 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_slice details; + grpc_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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->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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + 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(2)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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++; + 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.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); + + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); + GPR_ASSERT(was_cancelled == 1); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_after_client_done(grpc_end2end_test_config config) { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]); + } +} + +void cancel_after_client_done_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c deleted file mode 100644 index aad9fdbf94..0000000000 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - cancellation_mode mode, - size_t test_ops, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/%s [%" PRIdPTR " ops]", test_name, - config.name, mode.name, test_ops); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); - grpc_event ev = grpc_completion_queue_next( - f->cq, grpc_timeout_seconds_to_deadline(5), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag(1000)); - 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel after invoke, no payload */ -static void test_cancel_after_invoke(grpc_end2end_test_config config, - cancellation_mode mode, size_t test_ops) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_end2end_test_fixture f = begin_test(config, "test_cancel_after_invoke", - mode, test_ops, NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - 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_slice details; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, test_ops, tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_after_invoke(grpc_end2end_test_config config) { - unsigned i, j; - - for (j = 3; j < 6; j++) { - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_after_invoke(config, cancellation_modes[i], j); - } - } -} - -void cancel_after_invoke_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_invoke.cc b/test/core/end2end/tests/cancel_after_invoke.cc new file mode 100644 index 0000000000..aad9fdbf94 --- /dev/null +++ b/test/core/end2end/tests/cancel_after_invoke.cc @@ -0,0 +1,195 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + cancellation_mode mode, + size_t test_ops, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/%s [%" PRIdPTR " ops]", test_name, + config.name, mode.name, test_ops); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); + grpc_event ev = grpc_completion_queue_next( + f->cq, grpc_timeout_seconds_to_deadline(5), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag(1000)); + 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel after invoke, no payload */ +static void test_cancel_after_invoke(grpc_end2end_test_config config, + cancellation_mode mode, size_t test_ops) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_end2end_test_fixture f = begin_test(config, "test_cancel_after_invoke", + mode, test_ops, NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + 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_slice details; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, test_ops, tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_after_invoke(grpc_end2end_test_config config) { + unsigned i, j; + + for (j = 3; j < 6; j++) { + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_after_invoke(config, cancellation_modes[i], j); + } + } +} + +void cancel_after_invoke_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_round_trip.c b/test/core/end2end/tests/cancel_after_round_trip.c deleted file mode 100644 index bc41bd3a6d..0000000000 --- a/test/core/end2end/tests/cancel_after_round_trip.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/service_config.h" - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - cancellation_mode mode, - bool use_service_config, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, - mode.name, use_service_config ? "service_config" : "client_api"); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel after accept, no payload */ -static void test_cancel_after_round_trip(grpc_end2end_test_config config, - cancellation_mode mode, - bool use_service_config) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_call *s; - 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_slice details; - grpc_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload1 = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer *response_payload2 = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - grpc_channel_args *args = NULL; - if (use_service_config) { - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"timeout\": \"5s\"\n" - " } ]\n" - "}"; - args = grpc_channel_args_copy_and_add(args, &arg, 1); - } - - grpc_end2end_test_fixture f = begin_test( - config, "cancel_after_round_trip", mode, use_service_config, args, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = use_service_config - ? gpr_inf_future(GPR_CLOCK_MONOTONIC) - : five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/service/method"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_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_MESSAGE; - op->data.send_message.send_message = response_payload1; - 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); - - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - request_payload_recv = NULL; - response_payload_recv = NULL; - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload2; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - cq_verify(cqv); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload1); - grpc_byte_buffer_destroy(response_payload2); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); - - if (args != NULL) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, args); - grpc_exec_ctx_finish(&exec_ctx); - } - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_after_round_trip(grpc_end2end_test_config config) { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_after_round_trip(config, cancellation_modes[i], - false /* use_service_config */); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - test_cancel_after_round_trip(config, cancellation_modes[i], - true /* use_service_config */); - } - } -} - -void cancel_after_round_trip_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_after_round_trip.cc b/test/core/end2end/tests/cancel_after_round_trip.cc new file mode 100644 index 0000000000..202eeb5fb6 --- /dev/null +++ b/test/core/end2end/tests/cancel_after_round_trip.cc @@ -0,0 +1,304 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/service_config.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + cancellation_mode mode, + bool use_service_config, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, + mode.name, use_service_config ? "service_config" : "client_api"); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel after accept, no payload */ +static void test_cancel_after_round_trip(grpc_end2end_test_config config, + cancellation_mode mode, + bool use_service_config) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_call *s; + 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_slice details; + grpc_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload1 = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_byte_buffer *response_payload2 = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + int was_cancelled = 2; + + grpc_channel_args *args = NULL; + if (use_service_config) { + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}"); + args = grpc_channel_args_copy_and_add(args, &arg, 1); + } + + grpc_end2end_test_fixture f = begin_test( + config, "cancel_after_round_trip", mode, use_service_config, args, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = use_service_config + ? gpr_inf_future(GPR_CLOCK_MONOTONIC) + : five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_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_MESSAGE; + op->data.send_message.send_message = response_payload1; + 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); + + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + request_payload_recv = NULL; + response_payload_recv = NULL; + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload2; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + cq_verify(cqv); + + GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); + GPR_ASSERT(was_cancelled == 1); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload1); + grpc_byte_buffer_destroy(response_payload2); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + grpc_call_unref(s); + + if (args != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, args); + grpc_exec_ctx_finish(&exec_ctx); + } + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_after_round_trip(grpc_end2end_test_config config) { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_after_round_trip(config, cancellation_modes[i], + false /* use_service_config */); + if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && + cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { + test_cancel_after_round_trip(config, cancellation_modes[i], + true /* use_service_config */); + } + } +} + +void cancel_after_round_trip_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c deleted file mode 100644 index 397e8b8ba6..0000000000 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - size_t num_ops, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, - config.name, num_ops); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel before invoke */ -static void test_cancel_before_invoke(grpc_end2end_test_config config, - size_t test_ops) { - grpc_op ops[6]; - grpc_op *op; - grpc_call *c; - grpc_end2end_test_fixture f = - begin_test(config, "cancel_before_invoke", test_ops, NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - 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_slice details; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, NULL)); - - 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); - - memset(ops, 0, sizeof(ops)); - 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->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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, test_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_CANCELLED); - - 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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_before_invoke(grpc_end2end_test_config config) { - size_t i; - for (i = 1; i <= 6; i++) { - test_cancel_before_invoke(config, i); - } -} - -void cancel_before_invoke_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_before_invoke.cc b/test/core/end2end/tests/cancel_before_invoke.cc new file mode 100644 index 0000000000..397e8b8ba6 --- /dev/null +++ b/test/core/end2end/tests/cancel_before_invoke.cc @@ -0,0 +1,190 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + size_t num_ops, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, + config.name, num_ops); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel before invoke */ +static void test_cancel_before_invoke(grpc_end2end_test_config config, + size_t test_ops) { + grpc_op ops[6]; + grpc_op *op; + grpc_call *c; + grpc_end2end_test_fixture f = + begin_test(config, "cancel_before_invoke", test_ops, NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + 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_slice details; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, NULL)); + + 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); + + memset(ops, 0, sizeof(ops)); + 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->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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, test_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_CANCELLED); + + 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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(details); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_before_invoke(grpc_end2end_test_config config) { + size_t i; + for (i = 1; i <= 6; i++) { + test_cancel_before_invoke(config, i); + } +} + +void cancel_before_invoke_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c deleted file mode 100644 index cd9551bef9..0000000000 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - cancellation_mode mode, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, - mode.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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Cancel and do nothing */ -static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, - cancellation_mode mode) { - grpc_call *c; - grpc_end2end_test_fixture f = - begin_test(config, "test_cancel_in_a_vacuum", mode, NULL, NULL); - cq_verifier *v_client = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); - - grpc_call_unref(c); - - cq_verifier_destroy(v_client); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_in_a_vacuum(grpc_end2end_test_config config) { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_in_a_vacuum(config, cancellation_modes[i]); - } -} - -void cancel_in_a_vacuum_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.cc b/test/core/end2end/tests/cancel_in_a_vacuum.cc new file mode 100644 index 0000000000..cd9551bef9 --- /dev/null +++ b/test/core/end2end/tests/cancel_in_a_vacuum.cc @@ -0,0 +1,123 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + cancellation_mode mode, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, + mode.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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Cancel and do nothing */ +static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, + cancellation_mode mode) { + grpc_call *c; + grpc_end2end_test_fixture f = + begin_test(config, "test_cancel_in_a_vacuum", mode, NULL, NULL); + cq_verifier *v_client = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); + + grpc_call_unref(c); + + cq_verifier_destroy(v_client); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_in_a_vacuum(grpc_end2end_test_config config) { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { + test_cancel_in_a_vacuum(config, cancellation_modes[i]); + } +} + +void cancel_in_a_vacuum_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c deleted file mode 100644 index ab8c4f4187..0000000000 --- a/test/core/end2end/tests/cancel_with_status.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char *test_name, - size_t num_ops, - grpc_channel_args *client_args, - grpc_channel_args *server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, - config.name, num_ops); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); - grpc_event ev = grpc_completion_queue_next( - f->cq, grpc_timeout_seconds_to_deadline(5), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag(1000)); - 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f, size_t num_ops) { - grpc_call *c; - 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; - grpc_slice details; - - gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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); - - char *dynamic_string = gpr_strdup("xyz"); - grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, - (const char *)dynamic_string, NULL); - // The API of \a description allows for it to be a dynamic/non-const - // string, test this guarantee. - gpr_free(dynamic_string); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(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", num_ops, NULL, NULL); - simple_request_body(config, f, num_ops); - end_test(&f); - config.tear_down_data(&f); -} - -void cancel_with_status(grpc_end2end_test_config config) { - size_t i; - for (i = 1; i <= 4; i++) { - test_invoke_simple_request(config, i); - } -} - -void cancel_with_status_pre_init(void) {} diff --git a/test/core/end2end/tests/cancel_with_status.cc b/test/core/end2end/tests/cancel_with_status.cc new file mode 100644 index 0000000000..ab8c4f4187 --- /dev/null +++ b/test/core/end2end/tests/cancel_with_status.cc @@ -0,0 +1,183 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + size_t num_ops, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, + config.name, num_ops); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); + grpc_event ev = grpc_completion_queue_next( + f->cq, grpc_timeout_seconds_to_deadline(5), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag(1000)); + 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f, size_t num_ops) { + grpc_call *c; + 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; + grpc_slice details; + + gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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); + + char *dynamic_string = gpr_strdup("xyz"); + grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, + (const char *)dynamic_string, NULL); + // The API of \a description allows for it to be a dynamic/non-const + // string, test this guarantee. + gpr_free(dynamic_string); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_call_unref(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", num_ops, NULL, NULL); + simple_request_body(config, f, num_ops); + end_test(&f); + config.tear_down_data(&f); +} + +void cancel_with_status(grpc_end2end_test_config config) { + size_t i; + for (i = 1; i <= 4; i++) { + test_invoke_simple_request(config, i); + } +} + +void cancel_with_status_pre_init(void) {} diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c deleted file mode 100644 index ba03773036..0000000000 --- a/test/core/end2end/tests/compressed_payload.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/call_test_only.h" -#include "src/core/lib/transport/static_metadata.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void request_for_disabled_algorithm( - grpc_end2end_test_config config, const char *test_name, - uint32_t send_flags_bitmask, - grpc_compression_algorithm algorithm_to_disable, - grpc_compression_algorithm requested_client_compression_algorithm, - grpc_status_code expected_error, grpc_metadata *client_metadata) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice; - grpc_byte_buffer *request_payload; - grpc_channel_args *client_args; - grpc_channel_args *server_args; - grpc_end2end_test_fixture f; - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - cq_verifier *cqv; - char str[1024]; - - memset(str, 'x', 1023); - str[1023] = '\0'; - request_payload_slice = grpc_slice_from_copied_string(str); - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - client_args = grpc_channel_args_set_compression_algorithm( - NULL, requested_client_compression_algorithm); - server_args = - grpc_channel_args_set_compression_algorithm(NULL, GRPC_COMPRESS_NONE); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - server_args = grpc_channel_args_compression_algorithm_set_state( - &exec_ctx, &server_args, algorithm_to_disable, false); - grpc_exec_ctx_finish(&exec_ctx); - } - - f = begin_test(config, test_name, client_args, server_args); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_metadata != NULL) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_metadata; - } else { - op->data.send_initial_metadata.count = 0; - } - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = send_flags_bitmask; - 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.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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(101), true); - CQ_EXPECT_COMPLETION(cqv, tag(1), true); - 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_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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), false); - - op = ops; - 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(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), true); - cq_verify(cqv); - - /* call was cancelled (closed) ... */ - GPR_ASSERT(was_cancelled != 0); - /* with a certain error */ - GPR_ASSERT(status == expected_error); - - const char *algo_name = NULL; - GPR_ASSERT(grpc_compression_algorithm_name(algorithm_to_disable, &algo_name)); - char *expected_details = NULL; - gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.", - algo_name); - /* and we expect a specific reason for it */ - GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details)); - gpr_free(expected_details); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_slice_unref(request_payload_slice); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - end_test(&f); - config.tear_down_data(&f); -} - -static void request_with_payload_template( - grpc_end2end_test_config config, const char *test_name, - uint32_t client_send_flags_bitmask, - grpc_compression_algorithm default_client_channel_compression_algorithm, - grpc_compression_algorithm default_server_channel_compression_algorithm, - grpc_compression_algorithm expected_algorithm_from_client, - grpc_compression_algorithm expected_algorithm_from_server, - grpc_metadata *client_init_metadata, bool set_server_level, - grpc_compression_level server_compression_level, - bool send_message_before_initial_metadata) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice; - grpc_byte_buffer *request_payload = NULL; - grpc_channel_args *client_args; - grpc_channel_args *server_args; - grpc_end2end_test_fixture f; - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload; - grpc_byte_buffer *response_payload_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - cq_verifier *cqv; - char request_str[1024]; - char response_str[1024]; - - memset(request_str, 'x', 1023); - request_str[1023] = '\0'; - - memset(response_str, 'y', 1023); - response_str[1023] = '\0'; - - request_payload_slice = grpc_slice_from_copied_string(request_str); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string(response_str); - - client_args = grpc_channel_args_set_compression_algorithm( - NULL, default_client_channel_compression_algorithm); - server_args = grpc_channel_args_set_compression_algorithm( - NULL, default_server_channel_compression_algorithm); - - f = begin_test(config, test_name, client_args, server_args); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - if (send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), true); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_init_metadata != NULL) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_init_metadata; - } else { - op->data.send_initial_metadata.count = 0; - } - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(100), true); - cq_verify(cqv); - - GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( - s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_NONE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_DEFLATE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_GZIP) != 0); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - if (set_server_level) { - op->data.send_initial_metadata.maybe_compression_level.is_set = true; - op->data.send_initial_metadata.maybe_compression_level.level = - server_compression_level; - } - 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(101), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (int i = 0; i < 2; i++) { - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - if (i > 0 || !send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); - GPR_ASSERT(request_payload_recv->data.raw.compression == - expected_algorithm_from_client); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - cq_verify(cqv); - - GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); - if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { - const grpc_compression_algorithm algo_for_server_level = - grpc_call_compression_for_level(s, server_compression_level); - GPR_ASSERT(response_payload_recv->data.raw.compression == - algo_for_server_level); - } else { - GPR_ASSERT(response_payload_recv->data.raw.compression == - expected_algorithm_from_server); - } - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(4), 1); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_request_with_exceptionally_uncompressed_payload( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_exceptionally_uncompressed_payload", - GRPC_WRITE_NO_COMPRESS, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, NULL, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, false); -} - -static void test_invoke_request_with_uncompressed_payload( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_uncompressed_payload", 0, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - false); -} - -static void test_invoke_request_with_compressed_payload( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - false); -} - -static void test_invoke_request_with_send_message_before_initial_metadata( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - true); -} - -static void test_invoke_request_with_server_level( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */, - NULL, true, GRPC_COMPRESS_LEVEL_HIGH, false); -} - -static void test_invoke_request_with_compressed_payload_md_override( - grpc_end2end_test_config config) { - grpc_metadata gzip_compression_override; - grpc_metadata identity_compression_override; - - gzip_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; - gzip_compression_override.value = grpc_slice_from_static_string("gzip"); - memset(&gzip_compression_override.internal_data, 0, - sizeof(gzip_compression_override.internal_data)); - - identity_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; - identity_compression_override.value = - grpc_slice_from_static_string("identity"); - memset(&identity_compression_override.internal_data, 0, - sizeof(identity_compression_override.internal_data)); - - /* Channel default NONE (aka IDENTITY), call override to GZIP */ - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_1", 0, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); - - /* Channel default DEFLATE, call override to GZIP */ - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_2", 0, - GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); - - /* Channel default DEFLATE, call override to NONE (aka IDENTITY) */ - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_3", 0, - GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, &identity_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); -} - -static void test_invoke_request_with_disabled_algorithm( - grpc_end2end_test_config config) { - request_for_disabled_algorithm( - config, "test_invoke_request_with_disabled_algorithm", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_STATUS_UNIMPLEMENTED, NULL); -} - -void compressed_payload(grpc_end2end_test_config config) { - test_invoke_request_with_exceptionally_uncompressed_payload(config); - test_invoke_request_with_uncompressed_payload(config); - test_invoke_request_with_compressed_payload(config); - test_invoke_request_with_send_message_before_initial_metadata(config); - test_invoke_request_with_server_level(config); - test_invoke_request_with_compressed_payload_md_override(config); - test_invoke_request_with_disabled_algorithm(config); -} - -void compressed_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/compressed_payload.cc b/test/core/end2end/tests/compressed_payload.cc new file mode 100644 index 0000000000..ba03773036 --- /dev/null +++ b/test/core/end2end/tests/compressed_payload.cc @@ -0,0 +1,648 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/call_test_only.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void request_for_disabled_algorithm( + grpc_end2end_test_config config, const char *test_name, + uint32_t send_flags_bitmask, + grpc_compression_algorithm algorithm_to_disable, + grpc_compression_algorithm requested_client_compression_algorithm, + grpc_status_code expected_error, grpc_metadata *client_metadata) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char str[1024]; + + memset(str, 'x', 1023); + str[1023] = '\0'; + request_payload_slice = grpc_slice_from_copied_string(str); + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + + client_args = grpc_channel_args_set_compression_algorithm( + NULL, requested_client_compression_algorithm); + server_args = + grpc_channel_args_set_compression_algorithm(NULL, GRPC_COMPRESS_NONE); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + server_args = grpc_channel_args_compression_algorithm_set_state( + &exec_ctx, &server_args, algorithm_to_disable, false); + grpc_exec_ctx_finish(&exec_ctx); + } + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = send_flags_bitmask; + 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.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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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), false); + + op = ops; + 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(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + cq_verify(cqv); + + /* call was cancelled (closed) ... */ + GPR_ASSERT(was_cancelled != 0); + /* with a certain error */ + GPR_ASSERT(status == expected_error); + + const char *algo_name = NULL; + GPR_ASSERT(grpc_compression_algorithm_name(algorithm_to_disable, &algo_name)); + char *expected_details = NULL; + gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.", + algo_name); + /* and we expect a specific reason for it */ + GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details)); + gpr_free(expected_details); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_slice_unref(request_payload_slice); + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +static void request_with_payload_template( + grpc_end2end_test_config config, const char *test_name, + uint32_t client_send_flags_bitmask, + grpc_compression_algorithm default_client_channel_compression_algorithm, + grpc_compression_algorithm default_server_channel_compression_algorithm, + grpc_compression_algorithm expected_algorithm_from_client, + grpc_compression_algorithm expected_algorithm_from_server, + grpc_metadata *client_init_metadata, bool set_server_level, + grpc_compression_level server_compression_level, + bool send_message_before_initial_metadata) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload = NULL; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char request_str[1024]; + char response_str[1024]; + + memset(request_str, 'x', 1023); + request_str[1023] = '\0'; + + memset(response_str, 'y', 1023); + response_str[1023] = '\0'; + + request_payload_slice = grpc_slice_from_copied_string(request_str); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string(response_str); + + client_args = grpc_channel_args_set_compression_algorithm( + NULL, default_client_channel_compression_algorithm); + server_args = grpc_channel_args_set_compression_algorithm( + NULL, default_server_channel_compression_algorithm); + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + if (send_message_before_initial_metadata) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_init_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_init_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), true); + cq_verify(cqv); + + GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( + s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_NONE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_DEFLATE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_GZIP) != 0); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + if (set_server_level) { + op->data.send_initial_metadata.maybe_compression_level.is_set = true; + op->data.send_initial_metadata.maybe_compression_level.level = + server_compression_level; + } + 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(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (int i = 0; i < 2; i++) { + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + if (i > 0 || !send_message_before_initial_metadata) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); + GPR_ASSERT(request_payload_recv->data.raw.compression == + expected_algorithm_from_client); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + + GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); + if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { + const grpc_compression_algorithm algo_for_server_level = + grpc_call_compression_for_level(s, server_compression_level); + GPR_ASSERT(response_payload_recv->data.raw.compression == + algo_for_server_level); + } else { + GPR_ASSERT(response_payload_recv->data.raw.compression == + expected_algorithm_from_server); + } + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_request_with_exceptionally_uncompressed_payload( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_exceptionally_uncompressed_payload", + GRPC_WRITE_NO_COMPRESS, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, + GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, NULL, false, + /* ignored */ GRPC_COMPRESS_LEVEL_NONE, false); +} + +static void test_invoke_request_with_uncompressed_payload( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_uncompressed_payload", 0, + GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, + GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, + false); +} + +static void test_invoke_request_with_compressed_payload( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload", 0, + GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, + GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, + false); +} + +static void test_invoke_request_with_send_message_before_initial_metadata( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload", 0, + GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, + GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, + true); +} + +static void test_invoke_request_with_server_level( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE, + GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */, + NULL, true, GRPC_COMPRESS_LEVEL_HIGH, false); +} + +static void test_invoke_request_with_compressed_payload_md_override( + grpc_end2end_test_config config) { + grpc_metadata gzip_compression_override; + grpc_metadata identity_compression_override; + + gzip_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; + gzip_compression_override.value = grpc_slice_from_static_string("gzip"); + memset(&gzip_compression_override.internal_data, 0, + sizeof(gzip_compression_override.internal_data)); + + identity_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; + identity_compression_override.value = + grpc_slice_from_static_string("identity"); + memset(&identity_compression_override.internal_data, 0, + sizeof(identity_compression_override.internal_data)); + + /* Channel default NONE (aka IDENTITY), call override to GZIP */ + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload_md_override_1", 0, + GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, + GRPC_COMPRESS_NONE, &gzip_compression_override, false, + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); + + /* Channel default DEFLATE, call override to GZIP */ + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload_md_override_2", 0, + GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, + GRPC_COMPRESS_NONE, &gzip_compression_override, false, + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); + + /* Channel default DEFLATE, call override to NONE (aka IDENTITY) */ + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload_md_override_3", 0, + GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, + GRPC_COMPRESS_NONE, &identity_compression_override, false, + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); +} + +static void test_invoke_request_with_disabled_algorithm( + grpc_end2end_test_config config) { + request_for_disabled_algorithm( + config, "test_invoke_request_with_disabled_algorithm", 0, + GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_STATUS_UNIMPLEMENTED, NULL); +} + +void compressed_payload(grpc_end2end_test_config config) { + test_invoke_request_with_exceptionally_uncompressed_payload(config); + test_invoke_request_with_uncompressed_payload(config); + test_invoke_request_with_compressed_payload(config); + test_invoke_request_with_send_message_before_initial_metadata(config); + test_invoke_request_with_server_level(config); + test_invoke_request_with_compressed_payload_md_override(config); + test_invoke_request_with_disabled_algorithm(config); +} + +void compressed_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/connectivity.c b/test/core/end2end/tests/connectivity.c deleted file mode 100644 index 610243ee3a..0000000000 --- a/test/core/end2end/tests/connectivity.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t t) { return (void *)t; } - -typedef struct { - gpr_event started; - grpc_channel *channel; - grpc_completion_queue *cq; -} child_events; - -static void child_thread(void *arg) { - child_events *ce = (child_events *)arg; - grpc_event ev; - gpr_event_set(&ce->started, (void *)1); - gpr_log(GPR_DEBUG, "verifying"); - ev = grpc_completion_queue_next(ce->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), - NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag(1)); - GPR_ASSERT(ev.success == 0); -} - -static void test_connectivity(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); - grpc_connectivity_state state; - cq_verifier *cqv = cq_verifier_create(f.cq); - child_events ce; - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_id thdid; - - grpc_channel_args client_args; - grpc_arg arg_array[1]; - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = 1000; - client_args.args = arg_array; - client_args.num_args = 1; - - config.init_client(&f, &client_args); - - ce.channel = f.client; - ce.cq = f.cq; - gpr_event_init(&ce.started); - gpr_thd_options_set_joinable(&thdopt); - GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt)); - - gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - - /* channels should start life in IDLE, and stay there */ - GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == - GRPC_CHANNEL_IDLE); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); - GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == - GRPC_CHANNEL_IDLE); - - /* start watching for a change */ - gpr_log(GPR_DEBUG, "watching"); - grpc_channel_watch_connectivity_state( - f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1)); - - /* eventually the child thread completion should trigger */ - gpr_thd_join(thdid); - - /* check that we're still in idle, and start connecting */ - GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == - GRPC_CHANNEL_IDLE); - /* start watching for a change */ - grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, - grpc_timeout_seconds_to_deadline(3), - f.cq, tag(2)); - - /* and now the watch should trigger */ - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - state = grpc_channel_check_connectivity_state(f.client, 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING); - - /* quickly followed by a transition to TRANSIENT_FAILURE */ - grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING, - grpc_timeout_seconds_to_deadline(3), - f.cq, tag(3)); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - cq_verify(cqv); - state = grpc_channel_check_connectivity_state(f.client, 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING); - - gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); - - /* now let's bring up a server to connect to */ - config.init_server(&f, NULL); - - gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); - - /* 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(4)); - CQ_EXPECT_COMPLETION(cqv, tag(4), 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); - } - - /* bring down the server again */ - /* we should go immediately to TRANSIENT_FAILURE */ - gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); - - grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY, - grpc_timeout_seconds_to_deadline(3), - f.cq, tag(5)); - - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - - CQ_EXPECT_COMPLETION(cqv, tag(5), 1); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); - 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_IDLE); - - /* cleanup server */ - grpc_server_destroy(f.server); - - gpr_log(GPR_DEBUG, "*** SHUTDOWN SERVER ***"); - - grpc_channel_destroy(f.client); - grpc_completion_queue_shutdown(f.cq); - grpc_completion_queue_destroy(f.cq); - - /* shutdown_cq is not used in this test */ - grpc_completion_queue_destroy(f.shutdown_cq); - config.tear_down_data(&f); - - cq_verifier_destroy(cqv); -} - -void connectivity(grpc_end2end_test_config config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_connectivity(config); -} - -void connectivity_pre_init(void) {} diff --git a/test/core/end2end/tests/connectivity.cc b/test/core/end2end/tests/connectivity.cc new file mode 100644 index 0000000000..2cba25965a --- /dev/null +++ b/test/core/end2end/tests/connectivity.cc @@ -0,0 +1,173 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +typedef struct { + gpr_event started; + grpc_channel *channel; + grpc_completion_queue *cq; +} child_events; + +static void child_thread(void *arg) { + child_events *ce = (child_events *)arg; + grpc_event ev; + gpr_event_set(&ce->started, (void *)1); + gpr_log(GPR_DEBUG, "verifying"); + ev = grpc_completion_queue_next(ce->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), + NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag(1)); + GPR_ASSERT(ev.success == 0); +} + +static void test_connectivity(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + grpc_connectivity_state state; + cq_verifier *cqv = cq_verifier_create(f.cq); + child_events ce; + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_id thdid; + + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + + config.init_client(&f, &client_args); + + ce.channel = f.client; + ce.cq = f.cq; + gpr_event_init(&ce.started); + gpr_thd_options_set_joinable(&thdopt); + GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt)); + + gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + + /* channels should start life in IDLE, and stay there */ + GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == + GRPC_CHANNEL_IDLE); + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); + GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == + GRPC_CHANNEL_IDLE); + + /* start watching for a change */ + gpr_log(GPR_DEBUG, "watching"); + grpc_channel_watch_connectivity_state( + f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1)); + + /* eventually the child thread completion should trigger */ + gpr_thd_join(thdid); + + /* check that we're still in idle, and start connecting */ + GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == + GRPC_CHANNEL_IDLE); + /* start watching for a change */ + grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, + grpc_timeout_seconds_to_deadline(3), + f.cq, tag(2)); + + /* and now the watch should trigger */ + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(f.client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || + state == GRPC_CHANNEL_CONNECTING); + + /* quickly followed by a transition to TRANSIENT_FAILURE */ + grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING, + grpc_timeout_seconds_to_deadline(3), + f.cq, tag(3)); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + state = grpc_channel_check_connectivity_state(f.client, 0); + GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || + state == GRPC_CHANNEL_CONNECTING); + + gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); + + /* now let's bring up a server to connect to */ + config.init_server(&f, NULL); + + gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); + + /* 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(4)); + CQ_EXPECT_COMPLETION(cqv, tag(4), 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); + } + + /* bring down the server again */ + /* we should go immediately to TRANSIENT_FAILURE */ + gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); + + grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY, + grpc_timeout_seconds_to_deadline(3), + f.cq, tag(5)); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + + CQ_EXPECT_COMPLETION(cqv, tag(5), 1); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); + 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_IDLE); + + /* cleanup server */ + grpc_server_destroy(f.server); + + gpr_log(GPR_DEBUG, "*** SHUTDOWN SERVER ***"); + + grpc_channel_destroy(f.client); + grpc_completion_queue_shutdown(f.cq); + grpc_completion_queue_destroy(f.cq); + + /* shutdown_cq is not used in this test */ + grpc_completion_queue_destroy(f.shutdown_cq); + config.tear_down_data(&f); + + cq_verifier_destroy(cqv); +} + +void connectivity(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + test_connectivity(config); +} + +void connectivity_pre_init(void) {} diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c deleted file mode 100644 index d1db9b342a..0000000000 --- a/test/core/end2end/tests/default_host.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_client(&f, client_args); - config.init_server(&f, server_args); - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), NULL, - deadline, NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(error == GRPC_CALL_OK); - - error = - grpc_server_request_call(f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101)); - GPR_ASSERT(error == GRPC_CALL_OK); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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(error == GRPC_CALL_OK); - - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9)); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request", NULL, NULL); - simple_request_body(f); - end_test(&f); - config.tear_down_data(&f); -} - -void default_host(grpc_end2end_test_config config) { - if ((config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) == 0) - return; - if ((config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) == 0) - return; - test_invoke_simple_request(config); -} - -void default_host_pre_init(void) {} diff --git a/test/core/end2end/tests/default_host.cc b/test/core/end2end/tests/default_host.cc new file mode 100644 index 0000000000..d1db9b342a --- /dev/null +++ b/test/core/end2end/tests/default_host.cc @@ -0,0 +1,225 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_client(&f, client_args); + config.init_server(&f, server_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), NULL, + deadline, NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(error == GRPC_CALL_OK); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(error == GRPC_CALL_OK); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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(error == GRPC_CALL_OK); + + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9)); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(f); + end_test(&f); + config.tear_down_data(&f); +} + +void default_host(grpc_end2end_test_config config) { + if ((config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) == 0) + return; + if ((config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) == 0) + return; + test_invoke_simple_request(config); +} + +void default_host_pre_init(void) {} diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c deleted file mode 100644 index 19e4c05605..0000000000 --- a/test/core/end2end/tests/disappearing_server.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture *f) { - if (!f->server) return; - 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); - - /* Note: shutdown_cq was unused in this test */ - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void do_request_and_shutdown_server(grpc_end2end_test_config config, - grpc_end2end_test_fixture *f, - cq_verifier *cqv) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - /* should be able to shut down the server early - - and still complete the request */ - grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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_EXPECT_COMPLETION(cqv, tag(1000), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); -} - -static void disappearing_server_test(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - - gpr_log(GPR_INFO, "Running test: %s/%s", "disappearing_server_test", - config.name); - - config.init_client(&f, NULL); - config.init_server(&f, NULL); - - do_request_and_shutdown_server(config, &f, cqv); - - /* now destroy and recreate the server */ - config.init_server(&f, NULL); - - do_request_and_shutdown_server(config, &f, cqv); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); -} - -void disappearing_server(grpc_end2end_test_config config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - disappearing_server_test(config); -} - -void disappearing_server_pre_init(void) {} diff --git a/test/core/end2end/tests/disappearing_server.cc b/test/core/end2end/tests/disappearing_server.cc new file mode 100644 index 0000000000..19e4c05605 --- /dev/null +++ b/test/core/end2end/tests/disappearing_server.cc @@ -0,0 +1,211 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + 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); + + /* Note: shutdown_cq was unused in this test */ + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void do_request_and_shutdown_server(grpc_end2end_test_config config, + grpc_end2end_test_fixture *f, + cq_verifier *cqv) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + /* should be able to shut down the server early + - and still complete the request */ + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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_EXPECT_COMPLETION(cqv, tag(1000), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); +} + +static void disappearing_server_test(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + + gpr_log(GPR_INFO, "Running test: %s/%s", "disappearing_server_test", + config.name); + + config.init_client(&f, NULL); + config.init_server(&f, NULL); + + do_request_and_shutdown_server(config, &f, cqv); + + /* now destroy and recreate the server */ + config.init_server(&f, NULL); + + do_request_and_shutdown_server(config, &f, cqv); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +void disappearing_server(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + disappearing_server_test(config); +} + +void disappearing_server_pre_init(void) {} diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c deleted file mode 100644 index ee57c16780..0000000000 --- a/test/core/end2end/tests/empty_batch.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void empty_batch_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - cq_verifier *cqv = cq_verifier_create(f.cq); - grpc_call_error error; - grpc_op *op = NULL; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - error = grpc_call_start_batch(c, op, 0, tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - grpc_call_unref(c); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_empty_body(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_empty_body", NULL, NULL); - empty_batch_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -void empty_batch(grpc_end2end_test_config config) { - test_invoke_empty_body(config); -} - -void empty_batch_pre_init(void) {} diff --git a/test/core/end2end/tests/empty_batch.cc b/test/core/end2end/tests/empty_batch.cc new file mode 100644 index 0000000000..ee57c16780 --- /dev/null +++ b/test/core/end2end/tests/empty_batch.cc @@ -0,0 +1,127 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void empty_batch_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_call_error error; + grpc_op *op = NULL; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + error = grpc_call_start_batch(c, op, 0, tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_empty_body(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_empty_body", NULL, NULL); + empty_batch_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +void empty_batch(grpc_end2end_test_config config) { + test_invoke_empty_body(config); +} + +void empty_batch_pre_init(void) {} diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c deleted file mode 100644 index 09e9dbcd7b..0000000000 --- a/test/core/end2end/tests/filter_call_init_fails.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/surface/channel_init.h" -#include "test/core/end2end/cq_verifier.h" - -enum { TIMEOUT = 200000 }; - -static bool g_enable_server_channel_filter = false; -static bool g_enable_client_channel_filter = false; -static bool g_enable_client_subchannel_filter = false; - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -// Simple request via a SERVER_CHANNEL filter that always fails to -// initialize the call. -static void test_server_channel_filter(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "filter_call_init_fails", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -// Simple request via a CLIENT_CHANNEL or CLIENT_DIRECT_CHANNEL filter -// that always fails to initialize the call. -static void test_client_channel_filter(grpc_end2end_test_config config) { - grpc_call *c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = five_seconds_from_now(); - grpc_end2end_test_fixture f = - begin_test(config, "filter_call_init_fails", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -// Simple request via a CLIENT_SUBCHANNEL filter that always fails to -// initialize the call. -static void test_client_subchannel_filter(grpc_end2end_test_config config) { - grpc_call *c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = five_seconds_from_now(); - grpc_end2end_test_fixture f = - begin_test(config, "filter_call_init_fails", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - - // Reset and create a new call. (The first call uses a different code - // path in client_channel.c than subsequent calls on the same channel, - // and we need to test both.) - grpc_call_unref(c); - status = GRPC_STATUS_OK; - grpc_slice_unref(details); - details = grpc_empty_slice(); - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -/******************************************************************************* - * Test filter - always fails to initialize a call - */ - -static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_element_args *args) { - return grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("access denied"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_PERMISSION_DENIED); -} - -static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) {} - -static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) {} - -static const grpc_channel_filter test_filter = { - grpc_call_next_op, - grpc_channel_next_op, - 0, - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - destroy_call_elem, - 0, - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "filter_call_init_fails"}; - -/******************************************************************************* - * Registration - */ - -static bool maybe_add_server_channel_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, - void *arg) { - if (g_enable_server_channel_filter) { - // Want to add the filter as close to the end as possible, to make - // sure that all of the filters work well together. However, we - // can't add it at the very end, because the connected channel filter - // must be the last one. So we add it right before the last one. - grpc_channel_stack_builder_iterator *it = - grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); - const bool retval = grpc_channel_stack_builder_add_filter_before( - it, &test_filter, NULL, NULL); - grpc_channel_stack_builder_iterator_destroy(it); - return retval; - } else { - return true; - } -} - -static bool maybe_add_client_channel_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, - void *arg) { - if (g_enable_client_channel_filter) { - // Want to add the filter as close to the end as possible, to make - // sure that all of the filters work well together. However, we - // can't add it at the very end, because the connected channel filter - // must be the last one. So we add it right before the last one. - grpc_channel_stack_builder_iterator *it = - grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); - const bool retval = grpc_channel_stack_builder_add_filter_before( - it, &test_filter, NULL, NULL); - grpc_channel_stack_builder_iterator_destroy(it); - return retval; - } else { - return true; - } -} - -static bool maybe_add_client_subchannel_filter( - grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { - if (g_enable_client_subchannel_filter) { - // Want to add the filter as close to the end as possible, to make - // sure that all of the filters work well together. However, we - // can't add it at the very end, because the client channel filter - // must be the last one. So we add it right before the last one. - grpc_channel_stack_builder_iterator *it = - grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); - const bool retval = grpc_channel_stack_builder_add_filter_before( - it, &test_filter, NULL, NULL); - grpc_channel_stack_builder_iterator_destroy(it); - return retval; - } else { - return true; - } -} - -static void init_plugin(void) { - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_server_channel_filter, NULL); - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_client_channel_filter, NULL); - grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, - maybe_add_client_subchannel_filter, NULL); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - maybe_add_client_channel_filter, NULL); -} - -static void destroy_plugin(void) {} - -void filter_call_init_fails(grpc_end2end_test_config config) { - gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter."); - g_enable_server_channel_filter = true; - test_server_channel_filter(config); - g_enable_server_channel_filter = false; - gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter."); - g_enable_client_channel_filter = true; - test_client_channel_filter(config); - g_enable_client_channel_filter = false; - if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) { - gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); - g_enable_client_subchannel_filter = true; - test_client_subchannel_filter(config); - g_enable_client_subchannel_filter = false; - } -} - -void filter_call_init_fails_pre_init(void) { - grpc_register_plugin(init_plugin, destroy_plugin); -} diff --git a/test/core/end2end/tests/filter_call_init_fails.cc b/test/core/end2end/tests/filter_call_init_fails.cc new file mode 100644 index 0000000000..09e9dbcd7b --- /dev/null +++ b/test/core/end2end/tests/filter_call_init_fails.cc @@ -0,0 +1,531 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/channel_init.h" +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static bool g_enable_server_channel_filter = false; +static bool g_enable_client_channel_filter = false; +static bool g_enable_client_subchannel_filter = false; + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Simple request via a SERVER_CHANNEL filter that always fails to +// initialize the call. +static void test_server_channel_filter(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "filter_call_init_fails", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +// Simple request via a CLIENT_CHANNEL or CLIENT_DIRECT_CHANNEL filter +// that always fails to initialize the call. +static void test_client_channel_filter(grpc_end2end_test_config config) { + grpc_call *c; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + gpr_timespec deadline = five_seconds_from_now(); + grpc_end2end_test_fixture f = + begin_test(config, "filter_call_init_fails", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +// Simple request via a CLIENT_SUBCHANNEL filter that always fails to +// initialize the call. +static void test_client_subchannel_filter(grpc_end2end_test_config config) { + grpc_call *c; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + gpr_timespec deadline = five_seconds_from_now(); + grpc_end2end_test_fixture f = + begin_test(config, "filter_call_init_fails", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); + + // Reset and create a new call. (The first call uses a different code + // path in client_channel.c than subsequent calls on the same channel, + // and we need to test both.) + grpc_call_unref(c); + status = GRPC_STATUS_OK; + grpc_slice_unref(details); + details = grpc_empty_slice(); + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +/******************************************************************************* + * Test filter - always fails to initialize a call + */ + +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + return grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("access denied"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_PERMISSION_DENIED); +} + +static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) {} + +static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +static const grpc_channel_filter test_filter = { + grpc_call_next_op, + grpc_channel_next_op, + 0, + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + 0, + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "filter_call_init_fails"}; + +/******************************************************************************* + * Registration + */ + +static bool maybe_add_server_channel_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, + void *arg) { + if (g_enable_server_channel_filter) { + // Want to add the filter as close to the end as possible, to make + // sure that all of the filters work well together. However, we + // can't add it at the very end, because the connected channel filter + // must be the last one. So we add it right before the last one. + grpc_channel_stack_builder_iterator *it = + grpc_channel_stack_builder_create_iterator_at_last(builder); + GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); + const bool retval = grpc_channel_stack_builder_add_filter_before( + it, &test_filter, NULL, NULL); + grpc_channel_stack_builder_iterator_destroy(it); + return retval; + } else { + return true; + } +} + +static bool maybe_add_client_channel_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, + void *arg) { + if (g_enable_client_channel_filter) { + // Want to add the filter as close to the end as possible, to make + // sure that all of the filters work well together. However, we + // can't add it at the very end, because the connected channel filter + // must be the last one. So we add it right before the last one. + grpc_channel_stack_builder_iterator *it = + grpc_channel_stack_builder_create_iterator_at_last(builder); + GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); + const bool retval = grpc_channel_stack_builder_add_filter_before( + it, &test_filter, NULL, NULL); + grpc_channel_stack_builder_iterator_destroy(it); + return retval; + } else { + return true; + } +} + +static bool maybe_add_client_subchannel_filter( + grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { + if (g_enable_client_subchannel_filter) { + // Want to add the filter as close to the end as possible, to make + // sure that all of the filters work well together. However, we + // can't add it at the very end, because the client channel filter + // must be the last one. So we add it right before the last one. + grpc_channel_stack_builder_iterator *it = + grpc_channel_stack_builder_create_iterator_at_last(builder); + GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); + const bool retval = grpc_channel_stack_builder_add_filter_before( + it, &test_filter, NULL, NULL); + grpc_channel_stack_builder_iterator_destroy(it); + return retval; + } else { + return true; + } +} + +static void init_plugin(void) { + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + maybe_add_server_channel_filter, NULL); + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + maybe_add_client_channel_filter, NULL); + grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, + maybe_add_client_subchannel_filter, NULL); + grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, + maybe_add_client_channel_filter, NULL); +} + +static void destroy_plugin(void) {} + +void filter_call_init_fails(grpc_end2end_test_config config) { + gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter."); + g_enable_server_channel_filter = true; + test_server_channel_filter(config); + g_enable_server_channel_filter = false; + gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter."); + g_enable_client_channel_filter = true; + test_client_channel_filter(config); + g_enable_client_channel_filter = false; + if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) { + gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); + g_enable_client_subchannel_filter = true; + test_client_subchannel_filter(config); + g_enable_client_subchannel_filter = false; + } +} + +void filter_call_init_fails_pre_init(void) { + grpc_register_plugin(init_plugin, destroy_plugin); +} diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c deleted file mode 100644 index ee7aeb3f33..0000000000 --- a/test/core/end2end/tests/filter_causes_close.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/surface/channel_init.h" -#include "test/core/end2end/cq_verifier.h" - -static bool g_enable_filter = false; - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Simple request via a server filter that always closes the stream.*/ -static void test_request(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "filter_causes_close", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == - grpc_slice_str_cmp(details, "Failure that's not preventable.")); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -/******************************************************************************* - * Test filter - always closes incoming requests - */ - -typedef struct { grpc_closure *recv_im_ready; } call_data; - -typedef struct { uint8_t unused; } channel_data; - -static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_call_element *elem = (grpc_call_element *)arg; - call_data *calld = (call_data *)elem->call_data; - GRPC_CLOSURE_RUN( - exec_ctx, calld->recv_im_ready, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Failure that's not preventable.", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_PERMISSION_DENIED)); -} - -static void start_transport_stream_op_batch( - grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_transport_stream_op_batch *op) { - call_data *calld = (call_data *)elem->call_data; - if (op->recv_initial_metadata) { - calld->recv_im_ready = - op->payload->recv_initial_metadata.recv_initial_metadata_ready; - op->payload->recv_initial_metadata.recv_initial_metadata_ready = - GRPC_CLOSURE_CREATE(recv_im_ready, elem, grpc_schedule_on_exec_ctx); - } - grpc_call_next_op(exec_ctx, elem, op); -} - -static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) {} - -static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) {} - -static const grpc_channel_filter test_filter = { - start_transport_stream_op_batch, - grpc_channel_next_op, - sizeof(call_data), - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - destroy_call_elem, - sizeof(channel_data), - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "filter_causes_close"}; - -/******************************************************************************* - * Registration - */ - -static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, void *arg) { - if (g_enable_filter) { - return grpc_channel_stack_builder_prepend_filter(builder, &test_filter, - NULL, NULL); - } else { - return true; - } -} - -static void init_plugin(void) { - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter, - NULL); -} - -static void destroy_plugin(void) {} - -void filter_causes_close(grpc_end2end_test_config config) { - g_enable_filter = true; - test_request(config); - g_enable_filter = false; -} - -void filter_causes_close_pre_init(void) { - grpc_register_plugin(init_plugin, destroy_plugin); -} diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc new file mode 100644 index 0000000000..ee7aeb3f33 --- /dev/null +++ b/test/core/end2end/tests/filter_causes_close.cc @@ -0,0 +1,282 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/channel_init.h" +#include "test/core/end2end/cq_verifier.h" + +static bool g_enable_filter = false; + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Simple request via a server filter that always closes the stream.*/ +static void test_request(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "filter_causes_close", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); + GPR_ASSERT(0 == + grpc_slice_str_cmp(details, "Failure that's not preventable.")); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +/******************************************************************************* + * Test filter - always closes incoming requests + */ + +typedef struct { grpc_closure *recv_im_ready; } call_data; + +typedef struct { uint8_t unused; } channel_data; + +static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_call_element *elem = (grpc_call_element *)arg; + call_data *calld = (call_data *)elem->call_data; + GRPC_CLOSURE_RUN( + exec_ctx, calld->recv_im_ready, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Failure that's not preventable.", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_PERMISSION_DENIED)); +} + +static void start_transport_stream_op_batch( + grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *op) { + call_data *calld = (call_data *)elem->call_data; + if (op->recv_initial_metadata) { + calld->recv_im_ready = + op->payload->recv_initial_metadata.recv_initial_metadata_ready; + op->payload->recv_initial_metadata.recv_initial_metadata_ready = + GRPC_CLOSURE_CREATE(recv_im_ready, elem, grpc_schedule_on_exec_ctx); + } + grpc_call_next_op(exec_ctx, elem, op); +} + +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) {} + +static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +static const grpc_channel_filter test_filter = { + start_transport_stream_op_batch, + grpc_channel_next_op, + sizeof(call_data), + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + sizeof(channel_data), + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "filter_causes_close"}; + +/******************************************************************************* + * Registration + */ + +static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, void *arg) { + if (g_enable_filter) { + return grpc_channel_stack_builder_prepend_filter(builder, &test_filter, + NULL, NULL); + } else { + return true; + } +} + +static void init_plugin(void) { + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter, + NULL); +} + +static void destroy_plugin(void) {} + +void filter_causes_close(grpc_end2end_test_config config) { + g_enable_filter = true; + test_request(config); + g_enable_filter = false; +} + +void filter_causes_close_pre_init(void) { + grpc_register_plugin(init_plugin, destroy_plugin); +} diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c deleted file mode 100644 index c24934f05d..0000000000 --- a/test/core/end2end/tests/filter_latency.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/surface/channel_init.h" -#include "test/core/end2end/cq_verifier.h" - -enum { TIMEOUT = 200000 }; - -static bool g_enable_filter = false; -static gpr_mu g_mu; -static gpr_timespec g_client_latency; -static gpr_timespec g_server_latency; - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -// Simple request via a server filter that saves the reported latency value. -static void test_request(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "filter_latency", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_mu_lock(&g_mu); - g_client_latency = gpr_time_0(GPR_TIMESPAN); - g_server_latency = gpr_time_0(GPR_TIMESPAN); - gpr_mu_unlock(&g_mu); - const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_string = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_string; - 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 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(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_unref(s); - grpc_call_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); - - const gpr_timespec end_time = gpr_now(GPR_CLOCK_MONOTONIC); - const gpr_timespec max_latency = gpr_time_sub(end_time, start_time); - - // Perform checks after test tear-down - // Guards against the case that there's outstanding channel-related work on a - // call prior to verification - gpr_mu_lock(&g_mu); - GPR_ASSERT(gpr_time_cmp(max_latency, g_client_latency) >= 0); - GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_client_latency) <= 0); - GPR_ASSERT(gpr_time_cmp(max_latency, g_server_latency) >= 0); - GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_server_latency) <= 0); - // Server latency should always be smaller than client latency, however since - // we only calculate latency at destruction time, and that might mean that we - // need to wait for outstanding channel-related work, this isn't verifiable - // right now (the server MAY hold on to the call for longer than the client). - // GPR_ASSERT(gpr_time_cmp(g_server_latency, g_client_latency) < 0); - gpr_mu_unlock(&g_mu); -} - -/******************************************************************************* - * Test latency filter - */ - -static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) { - gpr_mu_lock(&g_mu); - g_client_latency = final_info->stats.latency; - gpr_mu_unlock(&g_mu); -} - -static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - const grpc_call_final_info *final_info, - grpc_closure *ignored) { - gpr_mu_lock(&g_mu); - g_server_latency = final_info->stats.latency; - gpr_mu_unlock(&g_mu); -} - -static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - return GRPC_ERROR_NONE; -} - -static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) {} - -static const grpc_channel_filter test_client_filter = { - grpc_call_next_op, - grpc_channel_next_op, - 0, - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - client_destroy_call_elem, - 0, - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "client_filter_latency"}; - -static const grpc_channel_filter test_server_filter = { - grpc_call_next_op, - grpc_channel_next_op, - 0, - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - server_destroy_call_elem, - 0, - init_channel_elem, - destroy_channel_elem, - grpc_channel_next_get_info, - "server_filter_latency"}; - -/******************************************************************************* - * Registration - */ - -static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, - grpc_channel_stack_builder *builder, void *arg) { - grpc_channel_filter *filter = (grpc_channel_filter *)arg; - if (g_enable_filter) { - // Want to add the filter as close to the end as possible, to make - // sure that all of the filters work well together. However, we - // can't add it at the very end, because the connected channel filter - // must be the last one. So we add it right before the last one. - grpc_channel_stack_builder_iterator *it = - grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); - const bool retval = - grpc_channel_stack_builder_add_filter_before(it, filter, NULL, NULL); - grpc_channel_stack_builder_iterator_destroy(it); - return retval; - } else { - return true; - } -} - -static void init_plugin(void) { - gpr_mu_init(&g_mu); - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_filter, - (void *)&test_client_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - maybe_add_filter, - (void *)&test_client_filter); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_filter, - (void *)&test_server_filter); -} - -static void destroy_plugin(void) { gpr_mu_destroy(&g_mu); } - -void filter_latency(grpc_end2end_test_config config) { - g_enable_filter = true; - test_request(config); - g_enable_filter = false; -} - -void filter_latency_pre_init(void) { - grpc_register_plugin(init_plugin, destroy_plugin); -} diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc new file mode 100644 index 0000000000..c24934f05d --- /dev/null +++ b/test/core/end2end/tests/filter_latency.cc @@ -0,0 +1,356 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/channel_init.h" +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static bool g_enable_filter = false; +static gpr_mu g_mu; +static gpr_timespec g_client_latency; +static gpr_timespec g_server_latency; + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Simple request via a server filter that saves the reported latency value. +static void test_request(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "filter_latency", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_mu_lock(&g_mu); + g_client_latency = gpr_time_0(GPR_TIMESPAN); + g_server_latency = gpr_time_0(GPR_TIMESPAN); + gpr_mu_unlock(&g_mu); + const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_string = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_string; + 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 == grpc_slice_str_cmp(details, "xyz")); + + grpc_slice_unref(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_unref(s); + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); + + const gpr_timespec end_time = gpr_now(GPR_CLOCK_MONOTONIC); + const gpr_timespec max_latency = gpr_time_sub(end_time, start_time); + + // Perform checks after test tear-down + // Guards against the case that there's outstanding channel-related work on a + // call prior to verification + gpr_mu_lock(&g_mu); + GPR_ASSERT(gpr_time_cmp(max_latency, g_client_latency) >= 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_client_latency) <= 0); + GPR_ASSERT(gpr_time_cmp(max_latency, g_server_latency) >= 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_server_latency) <= 0); + // Server latency should always be smaller than client latency, however since + // we only calculate latency at destruction time, and that might mean that we + // need to wait for outstanding channel-related work, this isn't verifiable + // right now (the server MAY hold on to the call for longer than the client). + // GPR_ASSERT(gpr_time_cmp(g_server_latency, g_client_latency) < 0); + gpr_mu_unlock(&g_mu); +} + +/******************************************************************************* + * Test latency filter + */ + +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) { + gpr_mu_lock(&g_mu); + g_client_latency = final_info->stats.latency; + gpr_mu_unlock(&g_mu); +} + +static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) { + gpr_mu_lock(&g_mu); + g_server_latency = final_info->stats.latency; + gpr_mu_unlock(&g_mu); +} + +static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +static const grpc_channel_filter test_client_filter = { + grpc_call_next_op, + grpc_channel_next_op, + 0, + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + client_destroy_call_elem, + 0, + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "client_filter_latency"}; + +static const grpc_channel_filter test_server_filter = { + grpc_call_next_op, + grpc_channel_next_op, + 0, + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + server_destroy_call_elem, + 0, + init_channel_elem, + destroy_channel_elem, + grpc_channel_next_get_info, + "server_filter_latency"}; + +/******************************************************************************* + * Registration + */ + +static bool maybe_add_filter(grpc_exec_ctx *exec_ctx, + grpc_channel_stack_builder *builder, void *arg) { + grpc_channel_filter *filter = (grpc_channel_filter *)arg; + if (g_enable_filter) { + // Want to add the filter as close to the end as possible, to make + // sure that all of the filters work well together. However, we + // can't add it at the very end, because the connected channel filter + // must be the last one. So we add it right before the last one. + grpc_channel_stack_builder_iterator *it = + grpc_channel_stack_builder_create_iterator_at_last(builder); + GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); + const bool retval = + grpc_channel_stack_builder_add_filter_before(it, filter, NULL, NULL); + grpc_channel_stack_builder_iterator_destroy(it); + return retval; + } else { + return true; + } +} + +static void init_plugin(void) { + gpr_mu_init(&g_mu); + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + maybe_add_filter, + (void *)&test_client_filter); + grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, + maybe_add_filter, + (void *)&test_client_filter); + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + maybe_add_filter, + (void *)&test_server_filter); +} + +static void destroy_plugin(void) { gpr_mu_destroy(&g_mu); } + +void filter_latency(grpc_end2end_test_config config) { + g_enable_filter = true; + test_request(config); + g_enable_filter = false; +} + +void filter_latency_pre_init(void) { + grpc_register_plugin(init_plugin, destroy_plugin); +} diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c deleted file mode 100644 index 9b3ff98195..0000000000 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture *f) { - if (!f->server) return; - 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); - /* Note: shutdown_cq is not used in this test */ - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_early_server_shutdown_finishes_inflight_calls( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_end2end_test_fixture f = begin_test( - config, "test_early_server_shutdown_finishes_inflight_calls", NULL, NULL); - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = n_seconds_from_now(10); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - 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.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->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); - - /* shutdown and destroy the server */ - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - cq_verify_empty(cqv); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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(0xdead), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - grpc_call_unref(s); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); -} - -void graceful_server_shutdown(grpc_end2end_test_config config) { - test_early_server_shutdown_finishes_inflight_calls(config); -} - -void graceful_server_shutdown_pre_init(void) {} diff --git a/test/core/end2end/tests/graceful_server_shutdown.cc b/test/core/end2end/tests/graceful_server_shutdown.cc new file mode 100644 index 0000000000..9b3ff98195 --- /dev/null +++ b/test/core/end2end/tests/graceful_server_shutdown.cc @@ -0,0 +1,206 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + 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); + /* Note: shutdown_cq is not used in this test */ + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_early_server_shutdown_finishes_inflight_calls( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_end2end_test_fixture f = begin_test( + config, "test_early_server_shutdown_finishes_inflight_calls", NULL, NULL); + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = n_seconds_from_now(10); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + 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.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->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); + + /* shutdown and destroy the server */ + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + cq_verify_empty(cqv); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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(0xdead), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + grpc_call_unref(s); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +void graceful_server_shutdown(grpc_end2end_test_config config) { + test_early_server_shutdown_finishes_inflight_calls(config); +} + +void graceful_server_shutdown_pre_init(void) {} diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c deleted file mode 100644 index 04b94838bb..0000000000 --- a/test/core/end2end/tests/high_initial_seqno.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - /* TODO(ctiller): this rate limits the test, and it should be removed when - retry has been implemented; until then cross-thread chatter - may result in some requests needing to be cancelled due to - seqno exhaustion. */ - cq_verify_empty(cqv); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_10_simple_requests(grpc_end2end_test_config config, - int initial_sequence_number) { - int i; - 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; - client_arg.value.integer = initial_sequence_number; - - client_args.num_args = 1; - client_args.args = &client_arg; - - 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(config, f); - gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); - } - end_test(&f); - config.tear_down_data(&f); - gpr_free(name); -} - -void high_initial_seqno(grpc_end2end_test_config config) { - test_invoke_10_simple_requests(config, 16777213); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) { - test_invoke_10_simple_requests(config, 2147483645); - } -} - -void high_initial_seqno_pre_init(void) {} diff --git a/test/core/end2end/tests/high_initial_seqno.cc b/test/core/end2end/tests/high_initial_seqno.cc new file mode 100644 index 0000000000..2b72d09e68 --- /dev/null +++ b/test/core/end2end/tests/high_initial_seqno.cc @@ -0,0 +1,239 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + /* TODO(ctiller): this rate limits the test, and it should be removed when + retry has been implemented; until then cross-thread chatter + may result in some requests needing to be cancelled due to + seqno exhaustion. */ + cq_verify_empty(cqv); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_10_simple_requests(grpc_end2end_test_config config, + int initial_sequence_number) { + int i; + 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 = const_cast(GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); + client_arg.value.integer = initial_sequence_number; + + client_args.num_args = 1; + client_args.args = &client_arg; + + 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(config, f); + gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); + } + end_test(&f); + config.tear_down_data(&f); + gpr_free(name); +} + +void high_initial_seqno(grpc_end2end_test_config config) { + test_invoke_10_simple_requests(config, 16777213); + if (config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) { + test_invoke_10_simple_requests(config, 2147483645); + } +} + +void high_initial_seqno_pre_init(void) {} diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c deleted file mode 100644 index 9358c119b1..0000000000 --- a/test/core/end2end/tests/hpack_size.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f, size_t index) { - grpc_call *c; - grpc_call *s; - 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]; - grpc_slice details; - int was_cancelled = 2; - - memset(extra_metadata, 0, sizeof(extra_metadata)); - extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name"); - extra_metadata[0].value = grpc_slice_from_static_string( - hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]); - extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name"); - extra_metadata[1].value = grpc_slice_from_static_string( - hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]); - extra_metadata[2].key = grpc_slice_from_static_string("dragon"); - extra_metadata[2].value = - grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(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(config, f, i); - } - end_test(&f); - config.tear_down_data(&f); - gpr_free(name); -} - -void hpack_size(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]); - } - } -} - -void hpack_size_pre_init(void) {} diff --git a/test/core/end2end/tests/hpack_size.cc b/test/core/end2end/tests/hpack_size.cc new file mode 100644 index 0000000000..e838be9f8b --- /dev/null +++ b/test/core/end2end/tests/hpack_size.cc @@ -0,0 +1,397 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f, size_t index) { + grpc_call *c; + grpc_call *s; + 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]; + grpc_slice details; + int was_cancelled = 2; + + memset(extra_metadata, 0, sizeof(extra_metadata)); + extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name"); + extra_metadata[0].value = grpc_slice_from_static_string( + hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]); + extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name"); + extra_metadata[1].value = grpc_slice_from_static_string( + hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]); + extra_metadata[2].key = grpc_slice_from_static_string("dragon"); + extra_metadata[2].value = + grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(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 = const_cast(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 = const_cast(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(config, f, i); + } + end_test(&f); + config.tear_down_data(&f); + gpr_free(name); +} + +void hpack_size(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]); + } + } +} + +void hpack_size_pre_init(void) {} diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c deleted file mode 100644 index 829ece6631..0000000000 --- a/test/core/end2end/tests/idempotent_request.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - 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.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->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); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request", NULL, NULL); - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); - for (i = 0; i < 10; i++) { - simple_request_body(config, f); - gpr_log(GPR_INFO, "Passed simple request %d", i); - } - end_test(&f); - config.tear_down_data(&f); -} - -void idempotent_request(grpc_end2end_test_config config) { - int i; - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - } - test_invoke_10_simple_requests(config); -} - -void idempotent_request_pre_init(void) {} diff --git a/test/core/end2end/tests/idempotent_request.cc b/test/core/end2end/tests/idempotent_request.cc new file mode 100644 index 0000000000..829ece6631 --- /dev/null +++ b/test/core/end2end/tests/idempotent_request.cc @@ -0,0 +1,242 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + 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.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->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); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + gpr_log(GPR_INFO, "Passed simple request %d", i); + } + end_test(&f); + config.tear_down_data(&f); +} + +void idempotent_request(grpc_end2end_test_config config) { + int i; + for (i = 0; i < 10; i++) { + test_invoke_simple_request(config); + } + test_invoke_10_simple_requests(config); +} + +void idempotent_request_pre_init(void) {} diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c deleted file mode 100644 index ff269fa3ee..0000000000 --- a/test/core/end2end/tests/invoke_large_request.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, n_seconds_from_now(5), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static grpc_slice large_slice(void) { - grpc_slice slice = grpc_slice_malloc(1000000); - memset(GRPC_SLICE_START_PTR(slice), 'x', GRPC_SLICE_LENGTH(slice)); - return slice; -} - -static void test_invoke_large_request(grpc_end2end_test_config config, - int max_frame_size, int lookahead_bytes) { - char *name; - gpr_asprintf(&name, - "test_invoke_large_request:max_frame_size=%d:lookahead_bytes=%d", - max_frame_size, lookahead_bytes); - - grpc_arg args[2]; - args[0].type = GRPC_ARG_INTEGER; - args[0].key = GRPC_ARG_HTTP2_MAX_FRAME_SIZE; - args[0].value.integer = max_frame_size; - args[1].type = GRPC_ARG_INTEGER; - args[1].key = GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES; - args[1].value.integer = lookahead_bytes; - grpc_channel_args channel_args = {GPR_ARRAY_SIZE(args), args}; - - grpc_end2end_test_fixture f = - begin_test(config, name, &channel_args, &channel_args); - gpr_free(name); - - grpc_slice request_payload_slice = large_slice(); - grpc_slice response_payload_slice = large_slice(); - grpc_call *c; - grpc_call *s; - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = n_seconds_from_now(30); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - end_test(&f); - config.tear_down_data(&f); -} - -void invoke_large_request(grpc_end2end_test_config config) { - test_invoke_large_request(config, 16384, 65536); - test_invoke_large_request(config, 32768, 65536); - - test_invoke_large_request(config, 1000000 - 1, 65536); - test_invoke_large_request(config, 1000000, 65536); - test_invoke_large_request(config, 1000000 + 1, 65536); - test_invoke_large_request(config, 1000000 + 2, 65536); - test_invoke_large_request(config, 1000000 + 3, 65536); - test_invoke_large_request(config, 1000000 + 4, 65536); - test_invoke_large_request(config, 1000000 + 5, 65536); - test_invoke_large_request(config, 1000000 + 6, 65536); - - test_invoke_large_request(config, 1000000 - 1, 2000000); - test_invoke_large_request(config, 1000000, 2000000); - test_invoke_large_request(config, 1000000 + 1, 2000000); - test_invoke_large_request(config, 1000000 + 2, 2000000); - test_invoke_large_request(config, 1000000 + 3, 2000000); - test_invoke_large_request(config, 1000000 + 4, 2000000); - test_invoke_large_request(config, 1000000 + 5, 2000000); - test_invoke_large_request(config, 1000000 + 6, 2000000); -} - -void invoke_large_request_pre_init(void) {} diff --git a/test/core/end2end/tests/invoke_large_request.cc b/test/core/end2end/tests/invoke_large_request.cc new file mode 100644 index 0000000000..c0e63103a8 --- /dev/null +++ b/test/core/end2end/tests/invoke_large_request.cc @@ -0,0 +1,285 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, n_seconds_from_now(5), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static grpc_slice large_slice(void) { + grpc_slice slice = grpc_slice_malloc(1000000); + memset(GRPC_SLICE_START_PTR(slice), 'x', GRPC_SLICE_LENGTH(slice)); + return slice; +} + +static void test_invoke_large_request(grpc_end2end_test_config config, + int max_frame_size, int lookahead_bytes) { + char *name; + gpr_asprintf(&name, + "test_invoke_large_request:max_frame_size=%d:lookahead_bytes=%d", + max_frame_size, lookahead_bytes); + + grpc_arg args[2]; + args[0].type = GRPC_ARG_INTEGER; + args[0].key = const_cast(GRPC_ARG_HTTP2_MAX_FRAME_SIZE); + args[0].value.integer = max_frame_size; + args[1].type = GRPC_ARG_INTEGER; + args[1].key = const_cast(GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES); + args[1].value.integer = lookahead_bytes; + grpc_channel_args channel_args = {GPR_ARRAY_SIZE(args), args}; + + grpc_end2end_test_fixture f = + begin_test(config, name, &channel_args, &channel_args); + gpr_free(name); + + grpc_slice request_payload_slice = large_slice(); + grpc_slice response_payload_slice = large_slice(); + grpc_call *c; + grpc_call *s; + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = n_seconds_from_now(30); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + end_test(&f); + config.tear_down_data(&f); +} + +void invoke_large_request(grpc_end2end_test_config config) { + test_invoke_large_request(config, 16384, 65536); + test_invoke_large_request(config, 32768, 65536); + + test_invoke_large_request(config, 1000000 - 1, 65536); + test_invoke_large_request(config, 1000000, 65536); + test_invoke_large_request(config, 1000000 + 1, 65536); + test_invoke_large_request(config, 1000000 + 2, 65536); + test_invoke_large_request(config, 1000000 + 3, 65536); + test_invoke_large_request(config, 1000000 + 4, 65536); + test_invoke_large_request(config, 1000000 + 5, 65536); + test_invoke_large_request(config, 1000000 + 6, 65536); + + test_invoke_large_request(config, 1000000 - 1, 2000000); + test_invoke_large_request(config, 1000000, 2000000); + test_invoke_large_request(config, 1000000 + 1, 2000000); + test_invoke_large_request(config, 1000000 + 2, 2000000); + test_invoke_large_request(config, 1000000 + 3, 2000000); + test_invoke_large_request(config, 1000000 + 4, 2000000); + test_invoke_large_request(config, 1000000 + 5, 2000000); + test_invoke_large_request(config, 1000000 + 6, 2000000); +} + +void invoke_large_request_pre_init(void) {} diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c deleted file mode 100644 index 0053368ecc..0000000000 --- a/test/core/end2end/tests/keepalive_timeout.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "src/core/ext/transport/chttp2/transport/frame_ping.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/support/env.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), - five_seconds_from_now(), 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request, server replies with a payload, then waits for the - keepalive watchdog timeouts before returning status. */ -static void test_keepalive_timeout(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - grpc_arg keepalive_arg_elems[] = {{.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_KEEPALIVE_TIME_MS, - .value.integer = 1500}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_KEEPALIVE_TIMEOUT_MS, - .value.integer = 0}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_BDP_PROBE, - .value.integer = 0}}; - grpc_channel_args keepalive_args = { - .num_args = GPR_ARRAY_SIZE(keepalive_arg_elems), - .args = keepalive_arg_elems}; - - grpc_end2end_test_fixture f = - begin_test(config, "keepalive_timeout", &keepalive_args, NULL); - 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_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - /* Disable ping ack to trigger the keepalive timeout */ - grpc_set_disable_ping_ack(true); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - cq_verify(cqv); - - char *details_str = grpc_slice_to_c_string(details); - char *method_str = grpc_slice_to_c_string(call_details.method); - GPR_ASSERT(status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - - gpr_free(details_str); - gpr_free(method_str); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void keepalive_timeout(grpc_end2end_test_config config) { - test_keepalive_timeout(config); -} - -void keepalive_timeout_pre_init(void) {} diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc new file mode 100644 index 0000000000..721c1364d0 --- /dev/null +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -0,0 +1,228 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/ext/transport/chttp2/transport/frame_ping.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/env.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + five_seconds_from_now(), 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request, server replies with a payload, then waits for the + keepalive watchdog timeouts before returning status. */ +static void test_keepalive_timeout(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + grpc_arg keepalive_arg_elems[3]; + keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); + keepalive_arg_elems[0].value.integer = 1500; + keepalive_arg_elems[1].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[1].key = + const_cast(GRPC_ARG_KEEPALIVE_TIMEOUT_MS); + keepalive_arg_elems[1].value.integer = 0; + keepalive_arg_elems[2].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); + keepalive_arg_elems[2].value.integer = 0; + grpc_channel_args keepalive_args = {GPR_ARRAY_SIZE(keepalive_arg_elems), + keepalive_arg_elems}; + + grpc_end2end_test_fixture f = + begin_test(config, "keepalive_timeout", &keepalive_args, NULL); + 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_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + /* Disable ping ack to trigger the keepalive timeout */ + grpc_set_disable_ping_ack(true); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + + char *details_str = grpc_slice_to_c_string(details); + char *method_str = grpc_slice_to_c_string(call_details.method); + GPR_ASSERT(status == GRPC_STATUS_INTERNAL); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + + gpr_free(details_str); + gpr_free(method_str); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void keepalive_timeout(grpc_end2end_test_config config) { + test_keepalive_timeout(config); +} + +void keepalive_timeout_pre_init(void) {} diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c deleted file mode 100644 index 81a45d827a..0000000000 --- a/test/core/end2end/tests/large_metadata.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -// Request with a large amount of metadata. -static void test_request_with_large_metadata(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_metadata meta; - const size_t large_size = 64 * 1024; - grpc_arg arg = {GRPC_ARG_INTEGER, - GRPC_ARG_MAX_METADATA_SIZE, - {.integer = (int)large_size + 1024}}; - grpc_channel_args args = {1, &arg}; - grpc_end2end_test_fixture f = - begin_test(config, "test_request_with_large_metadata", &args, &args); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - meta.key = grpc_slice_from_static_string("key"); - meta.value = grpc_slice_malloc(large_size); - memset(GRPC_SLICE_START_PTR(meta.value), 'a', large_size); - - 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); - - memset(ops, 0, sizeof(ops)); - // Client: send request. - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &meta; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - memset(ops, 0, sizeof(ops)); - // Server: send initial metadata and receive request. - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - // Server: receive close and send status. This should trigger - // completion of request on client. - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(contains_metadata_slices(&request_metadata_recv, - grpc_slice_from_static_string("key"), - meta.value)); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - grpc_slice_unref(meta.value); - - end_test(&f); - config.tear_down_data(&f); -} - -void large_metadata(grpc_end2end_test_config config) { - test_request_with_large_metadata(config); -} - -void large_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/large_metadata.cc b/test/core/end2end/tests/large_metadata.cc new file mode 100644 index 0000000000..c2aa4d187b --- /dev/null +++ b/test/core/end2end/tests/large_metadata.cc @@ -0,0 +1,253 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Request with a large amount of metadata. +static void test_request_with_large_metadata(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_metadata meta; + const size_t large_size = 64 * 1024; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(GRPC_ARG_MAX_METADATA_SIZE); + arg.value.integer = (int)large_size + 1024; + grpc_channel_args args = {1, &arg}; + grpc_end2end_test_fixture f = + begin_test(config, "test_request_with_large_metadata", &args, &args); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + meta.key = grpc_slice_from_static_string("key"); + meta.value = grpc_slice_malloc(large_size); + memset(GRPC_SLICE_START_PTR(meta.value), 'a', large_size); + + 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); + + memset(ops, 0, sizeof(ops)); + // Client: send request. + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = &meta; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + memset(ops, 0, sizeof(ops)); + // Server: send initial metadata and receive request. + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + // Server: receive close and send status. This should trigger + // completion of request on client. + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(contains_metadata_slices(&request_metadata_recv, + grpc_slice_from_static_string("key"), + meta.value)); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + grpc_slice_unref(meta.value); + + end_test(&f); + config.tear_down_data(&f); +} + +void large_metadata(grpc_end2end_test_config config) { + test_request_with_large_metadata(config); +} + +void large_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c deleted file mode 100644 index 7b503790db..0000000000 --- a/test/core/end2end/tests/load_reporting_hook.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/transport/static_metadata.h" - -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" - -enum { TIMEOUT = 200000 }; - -static void *tag(intptr_t t) { return (void *)t; } - -typedef struct { - gpr_mu mu; - intptr_t channel_id; - intptr_t call_id; - - char *initial_md_str; - char *trailing_md_str; - char *method_name; - - uint64_t incoming_bytes; - uint64_t outgoing_bytes; - - grpc_status_code call_final_status; - - bool fully_processed; -} load_reporting_data; - -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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void request_response_with_payload( - grpc_end2end_test_config config, grpc_end2end_test_fixture f, - const char *method_name, const char *request_msg, const char *response_msg, - grpc_metadata *initial_lr_metadata, grpc_metadata *trailing_lr_metadata) { - grpc_slice request_payload_slice = grpc_slice_from_static_string(request_msg); - grpc_slice response_payload_slice = - grpc_slice_from_static_string(response_msg); - grpc_call *c; - grpc_call *s; - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string(method_name), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - GPR_ASSERT(initial_lr_metadata != NULL); - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = initial_lr_metadata; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - GPR_ASSERT(trailing_lr_metadata != NULL); - op->data.send_status_from_server.trailing_metadata_count = 1; - op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -/* override the default for testing purposes */ -extern void (*g_load_reporting_fn)( - const grpc_load_reporting_call_data *call_data); - -static void test_load_reporting_hook(grpc_end2end_test_config config) { - /* TODO(dgq): this test is currently a noop until LR is fully defined. - * Leaving the rest here, as it'll likely be reusable. */ - - /* Introduce load reporting for the server through its arguments */ - grpc_arg arg = grpc_load_reporting_enable_arg(); - grpc_channel_args *lr_server_args = - grpc_channel_args_copy_and_add(NULL, &arg, 1); - - grpc_end2end_test_fixture f = - begin_test(config, "test_load_reporting_hook", NULL, lr_server_args); - - const char *method_name = "/gRPCFTW"; - const char *request_msg = "the msg from the client"; - const char *response_msg = "... and the response from the server"; - - grpc_metadata initial_lr_metadata; - grpc_metadata trailing_lr_metadata; - - initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN; - initial_lr_metadata.value = grpc_slice_from_static_string("client-token"); - memset(&initial_lr_metadata.internal_data, 0, - sizeof(initial_lr_metadata.internal_data)); - - trailing_lr_metadata.key = GRPC_MDSTR_LB_COST_BIN; - trailing_lr_metadata.value = grpc_slice_from_static_string("server-token"); - memset(&trailing_lr_metadata.internal_data, 0, - sizeof(trailing_lr_metadata.internal_data)); - - request_response_with_payload(config, f, method_name, request_msg, - response_msg, &initial_lr_metadata, - &trailing_lr_metadata); - end_test(&f); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, lr_server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - config.tear_down_data(&f); -} - -void load_reporting_hook(grpc_end2end_test_config config) { - test_load_reporting_hook(config); -} - -void load_reporting_hook_pre_init(void) {} diff --git a/test/core/end2end/tests/load_reporting_hook.cc b/test/core/end2end/tests/load_reporting_hook.cc new file mode 100644 index 0000000000..7b503790db --- /dev/null +++ b/test/core/end2end/tests/load_reporting_hook.cc @@ -0,0 +1,314 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" +#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/transport/static_metadata.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/end2end_tests.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(intptr_t t) { return (void *)t; } + +typedef struct { + gpr_mu mu; + intptr_t channel_id; + intptr_t call_id; + + char *initial_md_str; + char *trailing_md_str; + char *method_name; + + uint64_t incoming_bytes; + uint64_t outgoing_bytes; + + grpc_status_code call_final_status; + + bool fully_processed; +} load_reporting_data; + +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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void request_response_with_payload( + grpc_end2end_test_config config, grpc_end2end_test_fixture f, + const char *method_name, const char *request_msg, const char *response_msg, + grpc_metadata *initial_lr_metadata, grpc_metadata *trailing_lr_metadata) { + grpc_slice request_payload_slice = grpc_slice_from_static_string(request_msg); + grpc_slice response_payload_slice = + grpc_slice_from_static_string(response_msg); + grpc_call *c; + grpc_call *s; + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string(method_name), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + GPR_ASSERT(initial_lr_metadata != NULL); + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = initial_lr_metadata; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + GPR_ASSERT(trailing_lr_metadata != NULL); + op->data.send_status_from_server.trailing_metadata_count = 1; + op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); +} + +/* override the default for testing purposes */ +extern void (*g_load_reporting_fn)( + const grpc_load_reporting_call_data *call_data); + +static void test_load_reporting_hook(grpc_end2end_test_config config) { + /* TODO(dgq): this test is currently a noop until LR is fully defined. + * Leaving the rest here, as it'll likely be reusable. */ + + /* Introduce load reporting for the server through its arguments */ + grpc_arg arg = grpc_load_reporting_enable_arg(); + grpc_channel_args *lr_server_args = + grpc_channel_args_copy_and_add(NULL, &arg, 1); + + grpc_end2end_test_fixture f = + begin_test(config, "test_load_reporting_hook", NULL, lr_server_args); + + const char *method_name = "/gRPCFTW"; + const char *request_msg = "the msg from the client"; + const char *response_msg = "... and the response from the server"; + + grpc_metadata initial_lr_metadata; + grpc_metadata trailing_lr_metadata; + + initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN; + initial_lr_metadata.value = grpc_slice_from_static_string("client-token"); + memset(&initial_lr_metadata.internal_data, 0, + sizeof(initial_lr_metadata.internal_data)); + + trailing_lr_metadata.key = GRPC_MDSTR_LB_COST_BIN; + trailing_lr_metadata.value = grpc_slice_from_static_string("server-token"); + memset(&trailing_lr_metadata.internal_data, 0, + sizeof(trailing_lr_metadata.internal_data)); + + request_response_with_payload(config, f, method_name, request_msg, + response_msg, &initial_lr_metadata, + &trailing_lr_metadata); + end_test(&f); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, lr_server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + config.tear_down_data(&f); +} + +void load_reporting_hook(grpc_end2end_test_config config) { + test_load_reporting_hook(config); +} + +void load_reporting_hook_pre_init(void) {} diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c deleted file mode 100644 index d18c13997c..0000000000 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_max_concurrent_streams(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call *c1; - grpc_call *c2; - grpc_call *s1; - grpc_call *s2; - int live_call; - gpr_timespec deadline; - cq_verifier *cqv; - grpc_event ev; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1; - grpc_status_code status2; - grpc_slice details2; - grpc_op ops[6]; - grpc_op *op; - int was_cancelled; - int got_client_start; - int got_server_start; - - server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS; - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - f = begin_test(config, "test_max_concurrent_streams", NULL, &server_args); - cqv = cq_verifier_create(f.cq); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - - /* perform a ping-pong to ensure that settings have had a chance to round - trip */ - simple_request_body(config, f); - /* perform another one to make sure that the one stream case still works */ - simple_request_body(config, f); - - /* start two requests - ensuring that the second is not accepted until - the first completes */ - deadline = n_seconds_from_now(1000); - c1 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/alpha"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/beta"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s1, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - got_client_start = 0; - got_server_start = 0; - live_call = -1; - while (!got_client_start || !got_server_start) { - ev = grpc_completion_queue_next(f.cq, grpc_timeout_seconds_to_deadline(3), - NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.success); - if (ev.tag == tag(101)) { - GPR_ASSERT(!got_server_start); - got_server_start = 1; - } else { - GPR_ASSERT(!got_client_start); - GPR_ASSERT(ev.tag == tag(301) || ev.tag == tag(401)); - /* The /alpha or /beta calls started above could be invoked (but NOT - * both); - * check this here */ - /* We'll get tag 303 or 403, we want 300, 400 */ - live_call = ((int)(intptr_t)ev.tag) - 1; - got_client_start = 1; - } - } - GPR_ASSERT(live_call == 300 || live_call == 400); - - memset(ops, 0, sizeof(ops)); - 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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s1, 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(live_call + 2), 1); - /* first request is finished, we should be able to start the second */ - live_call = (live_call == 300) ? 400 : 300; - CQ_EXPECT_COMPLETION(cqv, tag(live_call + 1), 1); - cq_verify(cqv); - - grpc_call_details_destroy(&call_details); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s2, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(201))); - CQ_EXPECT_COMPLETION(cqv, tag(201), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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 = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s2, ops, (size_t)(op - ops), tag(202), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(live_call + 2), 1); - CQ_EXPECT_COMPLETION(cqv, tag(202), 1); - cq_verify(cqv); - - cq_verifier_destroy(cqv); - - grpc_call_unref(c1); - grpc_call_unref(s1); - grpc_call_unref(c2); - grpc_call_unref(s2); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - end_test(&f); - config.tear_down_data(&f); -} - -static void test_max_concurrent_streams_with_timeout_on_first( - grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call *c1; - grpc_call *c2; - grpc_call *s1; - grpc_call *s2; - cq_verifier *cqv; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1 = grpc_empty_slice(); - grpc_status_code status2; - grpc_slice details2 = grpc_empty_slice(); - grpc_op ops[6]; - grpc_op *op; - int was_cancelled; - - server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS; - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_first", - NULL, &server_args); - cqv = cq_verifier_create(f.cq); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - - /* perform a ping-pong to ensure that settings have had a chance to round - trip */ - simple_request_body(config, f); - /* perform another one to make sure that the one stream case still works */ - simple_request_body(config, f); - - /* start two requests - ensuring that the second is not accepted until - the first completes */ - c1 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/alpha"), - get_host_override_slice("foo.test.google.fr:1234", config), - n_seconds_from_now(3), NULL); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/beta"), - get_host_override_slice("foo.test.google.fr:1234", config), - n_seconds_from_now(1000), NULL); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s1, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(301), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv2; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s2, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(201))); - - CQ_EXPECT_COMPLETION(cqv, tag(302), 1); - /* first request is finished, we should be able to start the second */ - CQ_EXPECT_COMPLETION(cqv, tag(401), 1); - CQ_EXPECT_COMPLETION(cqv, tag(201), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s2, ops, (size_t)(op - ops), tag(202), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(402), 1); - CQ_EXPECT_COMPLETION(cqv, tag(202), 1); - cq_verify(cqv); - - cq_verifier_destroy(cqv); - - grpc_call_unref(c1); - grpc_call_unref(s1); - grpc_call_unref(c2); - grpc_call_unref(s2); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - end_test(&f); - config.tear_down_data(&f); -} - -static void test_max_concurrent_streams_with_timeout_on_second( - grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call *c1; - grpc_call *c2; - grpc_call *s1; - cq_verifier *cqv; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1 = grpc_empty_slice(); - grpc_status_code status2; - grpc_slice details2 = grpc_empty_slice(); - grpc_op ops[6]; - grpc_op *op; - int was_cancelled; - - server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS; - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_second", - NULL, &server_args); - cqv = cq_verifier_create(f.cq); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - - /* perform a ping-pong to ensure that settings have had a chance to round - trip */ - simple_request_body(config, f); - /* perform another one to make sure that the one stream case still works */ - simple_request_body(config, f); - - /* start two requests - ensuring that the second is not accepted until - the first completes , and the second request will timeout in the - concurrent_list */ - c1 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/alpha"), - get_host_override_slice("foo.test.google.fr:1234", config), - n_seconds_from_now(1000), NULL); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/beta"), - get_host_override_slice("foo.test.google.fr:1234", config), - n_seconds_from_now(3), NULL); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s1, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(301), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv2; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - /* the second request is time out*/ - CQ_EXPECT_COMPLETION(cqv, tag(401), 0); - CQ_EXPECT_COMPLETION(cqv, tag(402), 1); - cq_verify(cqv); - - /* second request is finished because of time out, so destroy the second call - */ - grpc_call_unref(c2); - - /* now reply the first call */ - memset(ops, 0, sizeof(ops)); - 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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s1, ops, (size_t)(op - ops), tag(102), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(302), 1); - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - cq_verify(cqv); - - cq_verifier_destroy(cqv); - - grpc_call_unref(c1); - grpc_call_unref(s1); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - end_test(&f); - config.tear_down_data(&f); -} - -void max_concurrent_streams(grpc_end2end_test_config config) { - test_max_concurrent_streams_with_timeout_on_first(config); - test_max_concurrent_streams_with_timeout_on_second(config); - test_max_concurrent_streams(config); -} - -void max_concurrent_streams_pre_init(void) {} diff --git a/test/core/end2end/tests/max_concurrent_streams.cc b/test/core/end2end/tests/max_concurrent_streams.cc new file mode 100644 index 0000000000..deb44bbc3e --- /dev/null +++ b/test/core/end2end/tests/max_concurrent_streams.cc @@ -0,0 +1,831 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_max_concurrent_streams(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + grpc_arg server_arg; + grpc_channel_args server_args; + grpc_call *c1; + grpc_call *c2; + grpc_call *s1; + grpc_call *s2; + int live_call; + gpr_timespec deadline; + cq_verifier *cqv; + grpc_event ev; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_recv1; + grpc_metadata_array trailing_metadata_recv1; + grpc_metadata_array initial_metadata_recv2; + grpc_metadata_array trailing_metadata_recv2; + grpc_status_code status1; + grpc_call_error error; + grpc_slice details1; + grpc_status_code status2; + grpc_slice details2; + grpc_op ops[6]; + grpc_op *op; + int was_cancelled; + int got_client_start; + int got_server_start; + + server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); + server_arg.type = GRPC_ARG_INTEGER; + server_arg.value.integer = 1; + + server_args.num_args = 1; + server_args.args = &server_arg; + + f = begin_test(config, "test_max_concurrent_streams", NULL, &server_args); + cqv = cq_verifier_create(f.cq); + + grpc_metadata_array_init(&request_metadata_recv); + grpc_metadata_array_init(&initial_metadata_recv1); + grpc_metadata_array_init(&trailing_metadata_recv1); + grpc_metadata_array_init(&initial_metadata_recv2); + grpc_metadata_array_init(&trailing_metadata_recv2); + grpc_call_details_init(&call_details); + + /* perform a ping-pong to ensure that settings have had a chance to round + trip */ + simple_request_body(config, f); + /* perform another one to make sure that the one stream case still works */ + simple_request_body(config, f); + + /* start two requests - ensuring that the second is not accepted until + the first completes */ + deadline = n_seconds_from_now(1000); + c1 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/alpha"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c1); + c2 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/beta"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c2); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s1, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; + op->data.recv_status_on_client.status = &status1; + op->data.recv_status_on_client.status_details = &details1; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv1; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; + op->data.recv_status_on_client.status = &status2; + op->data.recv_status_on_client.status_details = &details2; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv1; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + got_client_start = 0; + got_server_start = 0; + live_call = -1; + while (!got_client_start || !got_server_start) { + ev = grpc_completion_queue_next(f.cq, grpc_timeout_seconds_to_deadline(3), + NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.success); + if (ev.tag == tag(101)) { + GPR_ASSERT(!got_server_start); + got_server_start = 1; + } else { + GPR_ASSERT(!got_client_start); + GPR_ASSERT(ev.tag == tag(301) || ev.tag == tag(401)); + /* The /alpha or /beta calls started above could be invoked (but NOT + * both); + * check this here */ + /* We'll get tag 303 or 403, we want 300, 400 */ + live_call = ((int)(intptr_t)ev.tag) - 1; + got_client_start = 1; + } + } + GPR_ASSERT(live_call == 300 || live_call == 400); + + memset(ops, 0, sizeof(ops)); + 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_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s1, 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(live_call + 2), 1); + /* first request is finished, we should be able to start the second */ + live_call = (live_call == 300) ? 400 : 300; + CQ_EXPECT_COMPLETION(cqv, tag(live_call + 1), 1); + cq_verify(cqv); + + grpc_call_details_destroy(&call_details); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s2, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(201))); + CQ_EXPECT_COMPLETION(cqv, tag(201), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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 = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s2, ops, (size_t)(op - ops), tag(202), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(live_call + 2), 1); + CQ_EXPECT_COMPLETION(cqv, tag(202), 1); + cq_verify(cqv); + + cq_verifier_destroy(cqv); + + grpc_call_unref(c1); + grpc_call_unref(s1); + grpc_call_unref(c2); + grpc_call_unref(s2); + + grpc_slice_unref(details1); + grpc_slice_unref(details2); + grpc_metadata_array_destroy(&initial_metadata_recv1); + grpc_metadata_array_destroy(&trailing_metadata_recv1); + grpc_metadata_array_destroy(&initial_metadata_recv2); + grpc_metadata_array_destroy(&trailing_metadata_recv2); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + end_test(&f); + config.tear_down_data(&f); +} + +static void test_max_concurrent_streams_with_timeout_on_first( + grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + grpc_arg server_arg; + grpc_channel_args server_args; + grpc_call *c1; + grpc_call *c2; + grpc_call *s1; + grpc_call *s2; + cq_verifier *cqv; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_recv1; + grpc_metadata_array trailing_metadata_recv1; + grpc_metadata_array initial_metadata_recv2; + grpc_metadata_array trailing_metadata_recv2; + grpc_status_code status1; + grpc_call_error error; + grpc_slice details1 = grpc_empty_slice(); + grpc_status_code status2; + grpc_slice details2 = grpc_empty_slice(); + grpc_op ops[6]; + grpc_op *op; + int was_cancelled; + + server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); + server_arg.type = GRPC_ARG_INTEGER; + server_arg.value.integer = 1; + + server_args.num_args = 1; + server_args.args = &server_arg; + + f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_first", + NULL, &server_args); + cqv = cq_verifier_create(f.cq); + + grpc_metadata_array_init(&request_metadata_recv); + grpc_metadata_array_init(&initial_metadata_recv1); + grpc_metadata_array_init(&trailing_metadata_recv1); + grpc_metadata_array_init(&initial_metadata_recv2); + grpc_metadata_array_init(&trailing_metadata_recv2); + grpc_call_details_init(&call_details); + + /* perform a ping-pong to ensure that settings have had a chance to round + trip */ + simple_request_body(config, f); + /* perform another one to make sure that the one stream case still works */ + simple_request_body(config, f); + + /* start two requests - ensuring that the second is not accepted until + the first completes */ + c1 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/alpha"), + get_host_override_slice("foo.test.google.fr:1234", config), + n_seconds_from_now(3), NULL); + GPR_ASSERT(c1); + c2 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/beta"), + get_host_override_slice("foo.test.google.fr:1234", config), + n_seconds_from_now(1000), NULL); + GPR_ASSERT(c2); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s1, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; + op->data.recv_status_on_client.status = &status1; + op->data.recv_status_on_client.status_details = &details1; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv1; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(301), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; + op->data.recv_status_on_client.status = &status2; + op->data.recv_status_on_client.status_details = &details2; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv2; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + grpc_call_details_destroy(&call_details); + grpc_call_details_init(&call_details); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s2, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(201))); + + CQ_EXPECT_COMPLETION(cqv, tag(302), 1); + /* first request is finished, we should be able to start the second */ + CQ_EXPECT_COMPLETION(cqv, tag(401), 1); + CQ_EXPECT_COMPLETION(cqv, tag(201), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s2, ops, (size_t)(op - ops), tag(202), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(402), 1); + CQ_EXPECT_COMPLETION(cqv, tag(202), 1); + cq_verify(cqv); + + cq_verifier_destroy(cqv); + + grpc_call_unref(c1); + grpc_call_unref(s1); + grpc_call_unref(c2); + grpc_call_unref(s2); + + grpc_slice_unref(details1); + grpc_slice_unref(details2); + grpc_metadata_array_destroy(&initial_metadata_recv1); + grpc_metadata_array_destroy(&trailing_metadata_recv1); + grpc_metadata_array_destroy(&initial_metadata_recv2); + grpc_metadata_array_destroy(&trailing_metadata_recv2); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + end_test(&f); + config.tear_down_data(&f); +} + +static void test_max_concurrent_streams_with_timeout_on_second( + grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + grpc_arg server_arg; + grpc_channel_args server_args; + grpc_call *c1; + grpc_call *c2; + grpc_call *s1; + cq_verifier *cqv; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_recv1; + grpc_metadata_array trailing_metadata_recv1; + grpc_metadata_array initial_metadata_recv2; + grpc_metadata_array trailing_metadata_recv2; + grpc_status_code status1; + grpc_call_error error; + grpc_slice details1 = grpc_empty_slice(); + grpc_status_code status2; + grpc_slice details2 = grpc_empty_slice(); + grpc_op ops[6]; + grpc_op *op; + int was_cancelled; + + server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); + server_arg.type = GRPC_ARG_INTEGER; + server_arg.value.integer = 1; + + server_args.num_args = 1; + server_args.args = &server_arg; + + f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_second", + NULL, &server_args); + cqv = cq_verifier_create(f.cq); + + grpc_metadata_array_init(&request_metadata_recv); + grpc_metadata_array_init(&initial_metadata_recv1); + grpc_metadata_array_init(&trailing_metadata_recv1); + grpc_metadata_array_init(&initial_metadata_recv2); + grpc_metadata_array_init(&trailing_metadata_recv2); + grpc_call_details_init(&call_details); + + /* perform a ping-pong to ensure that settings have had a chance to round + trip */ + simple_request_body(config, f); + /* perform another one to make sure that the one stream case still works */ + simple_request_body(config, f); + + /* start two requests - ensuring that the second is not accepted until + the first completes , and the second request will timeout in the + concurrent_list */ + c1 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/alpha"), + get_host_override_slice("foo.test.google.fr:1234", config), + n_seconds_from_now(1000), NULL); + GPR_ASSERT(c1); + c2 = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/beta"), + get_host_override_slice("foo.test.google.fr:1234", config), + n_seconds_from_now(3), NULL); + GPR_ASSERT(c2); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s1, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; + op->data.recv_status_on_client.status = &status1; + op->data.recv_status_on_client.status_details = &details1; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv1; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(301), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; + op->data.recv_status_on_client.status = &status2; + op->data.recv_status_on_client.status_details = &details2; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv2; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* the second request is time out*/ + CQ_EXPECT_COMPLETION(cqv, tag(401), 0); + CQ_EXPECT_COMPLETION(cqv, tag(402), 1); + cq_verify(cqv); + + /* second request is finished because of time out, so destroy the second call + */ + grpc_call_unref(c2); + + /* now reply the first call */ + memset(ops, 0, sizeof(ops)); + 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_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s1, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(302), 1); + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + cq_verify(cqv); + + cq_verifier_destroy(cqv); + + grpc_call_unref(c1); + grpc_call_unref(s1); + + grpc_slice_unref(details1); + grpc_slice_unref(details2); + grpc_metadata_array_destroy(&initial_metadata_recv1); + grpc_metadata_array_destroy(&trailing_metadata_recv1); + grpc_metadata_array_destroy(&initial_metadata_recv2); + grpc_metadata_array_destroy(&trailing_metadata_recv2); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + end_test(&f); + config.tear_down_data(&f); +} + +void max_concurrent_streams(grpc_end2end_test_config config) { + test_max_concurrent_streams_with_timeout_on_first(config); + test_max_concurrent_streams_with_timeout_on_second(config); + test_max_concurrent_streams(config); +} + +void max_concurrent_streams_pre_init(void) {} diff --git a/test/core/end2end/tests/max_connection_age.c b/test/core/end2end/tests/max_connection_age.c deleted file mode 100644 index b6daa59d7b..0000000000 --- a/test/core/end2end/tests/max_connection_age.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" - -#define MAX_CONNECTION_AGE_MS 500 -#define MAX_CONNECTION_AGE_GRACE_MS 1000 -#define MAX_CONNECTION_IDLE_MS 9999 - -#define MAX_CONNECTION_AGE_JITTER_MULTIPLIER 1.1 -#define CALL_DEADLINE_S 10 -/* The amount of time we wait for the connection to time out, but after it the - connection should not use up its grace period. It should be a number between - MAX_CONNECTION_AGE_MS and MAX_CONNECTION_AGE_MS + - MAX_CONNECTION_AGE_GRACE_MS */ -#define CQ_MAX_CONNECTION_AGE_WAIT_TIME_S 1 -/* The amount of time we wait after the connection reaches its max age, it - should be shorter than CALL_DEADLINE_S - CQ_MAX_CONNECTION_AGE_WAIT_TIME_S */ -#define CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S 2 -/* The grace period for the test to observe the channel shutdown process */ -#define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000 - -static void *tag(intptr_t t) { return (void *)t; } - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), - NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture *f) { - if (!f->server) return; - 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_max_age_forcibly_close(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, - .value.integer = MAX_CONNECTION_AGE_MS}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, - .value.integer = MAX_CONNECTION_AGE_GRACE_MS}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, - .value.integer = MAX_CONNECTION_IDLE_MS}}; - grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), - .args = server_a}; - - config.init_client(&f, NULL); - config.init_server(&f, &server_args); - - grpc_call *c; - grpc_call *s; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); - 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_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - 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.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->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), true); - cq_verify(cqv); - - gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline( - (int)(MAX_CONNECTION_AGE_MS * MAX_CONNECTION_AGE_JITTER_MULTIPLIER) + - MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS); - - /* Wait for the channel to reach its max age */ - cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); - - /* After the channel reaches its max age, we still do nothing here. And wait - for it to use up its max age grace period. */ - CQ_EXPECT_COMPLETION(cqv, tag(1), true); - cq_verify(cqv); - - gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC); - GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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), true); - cq_verify(cqv); - - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); - cq_verify(cqv); - - grpc_call_unref(s); - - /* The connection should be closed immediately after the max age grace period, - the in-progress RPC should fail. */ - GPR_ASSERT(status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_max_age_gracefully_close(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, - .value.integer = MAX_CONNECTION_AGE_MS}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, - .value.integer = INT_MAX}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, - .value.integer = MAX_CONNECTION_IDLE_MS}}; - grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), - .args = server_a}; - - config.init_client(&f, NULL); - config.init_server(&f, &server_args); - - grpc_call *c; - grpc_call *s; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); - 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_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - 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.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->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), true); - cq_verify(cqv); - - /* Wait for the channel to reach its max age */ - cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); - - /* The connection is shutting down gracefully. In-progress rpc should not be - closed, hence the completion queue should see nothing here. */ - cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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), true); - CQ_EXPECT_COMPLETION(cqv, tag(1), true); - cq_verify(cqv); - - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); - cq_verify(cqv); - - grpc_call_unref(s); - - /* The connection is closed gracefully with goaway, the rpc should still be - completed. */ - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - cq_verifier_destroy(cqv); - end_test(&f); - config.tear_down_data(&f); -} - -void max_connection_age(grpc_end2end_test_config config) { - test_max_age_forcibly_close(config); - test_max_age_gracefully_close(config); -} - -void max_connection_age_pre_init(void) {} diff --git a/test/core/end2end/tests/max_connection_age.cc b/test/core/end2end/tests/max_connection_age.cc new file mode 100644 index 0000000000..01cae9e3e0 --- /dev/null +++ b/test/core/end2end/tests/max_connection_age.cc @@ -0,0 +1,366 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" + +#define MAX_CONNECTION_AGE_MS 500 +#define MAX_CONNECTION_AGE_GRACE_MS 1000 +#define MAX_CONNECTION_IDLE_MS 9999 + +#define MAX_CONNECTION_AGE_JITTER_MULTIPLIER 1.1 +#define CALL_DEADLINE_S 10 +/* The amount of time we wait for the connection to time out, but after it the + connection should not use up its grace period. It should be a number between + MAX_CONNECTION_AGE_MS and MAX_CONNECTION_AGE_MS + + MAX_CONNECTION_AGE_GRACE_MS */ +#define CQ_MAX_CONNECTION_AGE_WAIT_TIME_S 1 +/* The amount of time we wait after the connection reaches its max age, it + should be shorter than CALL_DEADLINE_S - CQ_MAX_CONNECTION_AGE_WAIT_TIME_S */ +#define CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S 2 +/* The grace period for the test to observe the channel shutdown process */ +#define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000 + +static void *tag(intptr_t t) { return (void *)t; } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), + NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_max_age_forcibly_close(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_arg server_a[3]; + server_a[0].type = GRPC_ARG_INTEGER; + server_a[0].key = const_cast(GRPC_ARG_MAX_CONNECTION_AGE_MS); + server_a[0].value.integer = MAX_CONNECTION_AGE_MS; + server_a[1].type = GRPC_ARG_INTEGER; + server_a[1].key = const_cast(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS); + server_a[1].value.integer = MAX_CONNECTION_AGE_GRACE_MS; + server_a[2].type = GRPC_ARG_INTEGER; + server_a[2].key = const_cast(GRPC_ARG_MAX_CONNECTION_IDLE_MS); + server_a[2].value.integer = MAX_CONNECTION_IDLE_MS; + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + + config.init_client(&f, NULL); + config.init_server(&f, &server_args); + + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); + 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_slice details; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + 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.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->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), true); + cq_verify(cqv); + + gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline( + (int)(MAX_CONNECTION_AGE_MS * MAX_CONNECTION_AGE_JITTER_MULTIPLIER) + + MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS); + + /* Wait for the channel to reach its max age */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); + + /* After the channel reaches its max age, we still do nothing here. And wait + for it to use up its max age grace period. */ + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC); + GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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), true); + cq_verify(cqv); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); + cq_verify(cqv); + + grpc_call_unref(s); + + /* The connection should be closed immediately after the max age grace period, + the in-progress RPC should fail. */ + GPR_ASSERT(status == GRPC_STATUS_INTERNAL); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_max_age_gracefully_close(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_arg server_a[3]; + server_a[0].type = GRPC_ARG_INTEGER; + server_a[0].key = const_cast(GRPC_ARG_MAX_CONNECTION_AGE_MS); + server_a[0].value.integer = MAX_CONNECTION_AGE_MS; + server_a[1].type = GRPC_ARG_INTEGER; + server_a[1].key = const_cast(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS); + server_a[1].value.integer = INT_MAX; + server_a[2].type = GRPC_ARG_INTEGER; + server_a[2].key = const_cast(GRPC_ARG_MAX_CONNECTION_IDLE_MS); + server_a[2].value.integer = MAX_CONNECTION_IDLE_MS; + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + + config.init_client(&f, NULL); + config.init_server(&f, &server_args); + + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); + 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_slice details; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + 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.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->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), true); + cq_verify(cqv); + + /* Wait for the channel to reach its max age */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S); + + /* The connection is shutting down gracefully. In-progress rpc should not be + closed, hence the completion queue should see nothing here. */ + cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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), true); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true); + cq_verify(cqv); + + grpc_call_unref(s); + + /* The connection is closed gracefully with goaway, the rpc should still be + completed. */ + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + cq_verifier_destroy(cqv); + end_test(&f); + config.tear_down_data(&f); +} + +void max_connection_age(grpc_end2end_test_config config) { + test_max_age_forcibly_close(config); + test_max_age_gracefully_close(config); +} + +void max_connection_age_pre_init(void) {} diff --git a/test/core/end2end/tests/max_connection_idle.c b/test/core/end2end/tests/max_connection_idle.c deleted file mode 100644 index f26b0be40e..0000000000 --- a/test/core/end2end/tests/max_connection_idle.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" - -#define MAX_CONNECTION_IDLE_MS 500 -#define MAX_CONNECTION_AGE_MS 9999 - -static void *tag(intptr_t t) { return (void *)t; } - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), - NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture *f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call( - f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(0 == call_details.flags); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_max_connection_idle(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); - grpc_connectivity_state state = GRPC_CHANNEL_IDLE; - cq_verifier *cqv = cq_verifier_create(f.cq); - - grpc_arg client_a[] = {{.type = GRPC_ARG_INTEGER, - .key = "grpc.testing.fixed_reconnect_backoff_ms", - .value.integer = 1000}}; - grpc_arg server_a[] = {{.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_IDLE_MS, - .value.integer = MAX_CONNECTION_IDLE_MS}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_MAX_CONNECTION_AGE_MS, - .value.integer = MAX_CONNECTION_AGE_MS}}; - grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(client_a), - .args = client_a}; - grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), - .args = server_a}; - - config.init_client(&f, &client_args); - config.init_server(&f, &server_args); - - /* 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); - } - - /* Use a simple request to cancel and reset the max idle timer */ - simple_request_body(config, &f); - - /* wait for the channel to reach its maximum idle time */ - grpc_channel_watch_connectivity_state( - f.client, GRPC_CHANNEL_READY, - grpc_timeout_milliseconds_to_deadline(MAX_CONNECTION_IDLE_MS + 3000), - 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_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); - - grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); - CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); - cq_verify(cqv); - - grpc_server_destroy(f.server); - grpc_channel_destroy(f.client); - grpc_completion_queue_shutdown(f.cq); - drain_cq(f.cq); - grpc_completion_queue_destroy(f.cq); - grpc_completion_queue_destroy(f.shutdown_cq); - config.tear_down_data(&f); - - cq_verifier_destroy(cqv); -} - -void max_connection_idle(grpc_end2end_test_config config) { - test_max_connection_idle(config); -} - -void max_connection_idle_pre_init(void) {} diff --git a/test/core/end2end/tests/max_connection_idle.cc b/test/core/end2end/tests/max_connection_idle.cc new file mode 100644 index 0000000000..a44d15452c --- /dev/null +++ b/test/core/end2end/tests/max_connection_idle.cc @@ -0,0 +1,241 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" + +#define MAX_CONNECTION_IDLE_MS 500 +#define MAX_CONNECTION_AGE_MS 9999 + +static void *tag(intptr_t t) { return (void *)t; } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), + NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture *f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); + c = grpc_channel_create_call( + f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_max_connection_idle(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + cq_verifier *cqv = cq_verifier_create(f.cq); + + grpc_arg client_a[1]; + client_a[0].type = GRPC_ARG_INTEGER; + client_a[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + client_a[0].value.integer = 1000; + grpc_arg server_a[2]; + server_a[0].type = GRPC_ARG_INTEGER; + server_a[0].key = const_cast(GRPC_ARG_MAX_CONNECTION_IDLE_MS); + server_a[0].value.integer = MAX_CONNECTION_IDLE_MS; + server_a[1].type = GRPC_ARG_INTEGER; + server_a[1].key = const_cast(GRPC_ARG_MAX_CONNECTION_AGE_MS); + server_a[1].value.integer = MAX_CONNECTION_AGE_MS; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + + config.init_client(&f, &client_args); + config.init_server(&f, &server_args); + + /* 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); + } + + /* Use a simple request to cancel and reset the max idle timer */ + simple_request_body(config, &f); + + /* wait for the channel to reach its maximum idle time */ + grpc_channel_watch_connectivity_state( + f.client, GRPC_CHANNEL_READY, + grpc_timeout_milliseconds_to_deadline(MAX_CONNECTION_IDLE_MS + 3000), + 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_TRANSIENT_FAILURE || + state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); + + grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); + CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); + cq_verify(cqv); + + grpc_server_destroy(f.server); + grpc_channel_destroy(f.client); + grpc_completion_queue_shutdown(f.cq); + drain_cq(f.cq); + grpc_completion_queue_destroy(f.cq); + grpc_completion_queue_destroy(f.shutdown_cq); + config.tear_down_data(&f); + + cq_verifier_destroy(cqv); +} + +void max_connection_idle(grpc_end2end_test_config config) { + test_max_connection_idle(config); +} + +void max_connection_idle_pre_init(void) {} diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c deleted file mode 100644 index 01eb8d365e..0000000000 --- a/test/core/end2end/tests/max_message_length.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/service_config.h" - -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); - // We intentionally do not pass the client and server args to - // create_fixture(), since we don't want the limit enforced on the - // proxy, only on the backend server. - f = config.create_fixture(NULL, NULL); - config.init_server(&f, server_args); - config.init_client(&f, client_args); - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); - grpc_event ev = grpc_completion_queue_next( - f->cq, grpc_timeout_seconds_to_deadline(5), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag(1000)); - 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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -// Test with request larger than the limit. -// If send_limit is true, applies send limit on client; otherwise, applies -// recv limit on server. -static void test_max_message_length_on_request(grpc_end2end_test_config config, - bool send_limit, - bool use_service_config, - bool use_string_json_value) { - gpr_log(GPR_INFO, - "testing request with send_limit=%d use_service_config=%d " - "use_string_json_value=%d", - send_limit, use_service_config, use_string_json_value); - - grpc_end2end_test_fixture f; - grpc_call *c = NULL; - grpc_call *s = NULL; - cq_verifier *cqv; - grpc_op ops[6]; - grpc_op *op; - grpc_slice request_payload_slice = - grpc_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 = NULL; - 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_slice details; - int was_cancelled = 2; - - grpc_channel_args *client_args = NULL; - grpc_channel_args *server_args = NULL; - if (use_service_config) { - // We don't currently support service configs on the server side. - GPR_ASSERT(send_limit); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = - use_string_json_value - ? "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxRequestMessageBytes\": \"5\"\n" - " } ]\n" - "}" - : "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxRequestMessageBytes\": 5\n" - " } ]\n" - "}"; - client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - } else { - // Set limit via channel args. - grpc_arg arg; - arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH - : GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH; - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 5; - grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - if (send_limit) { - client_args = args; - } else { - server_args = args; - } - } - - f = begin_test(config, "test_max_request_message_length", client_args, - server_args); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - if (client_args != NULL) grpc_channel_args_destroy(&exec_ctx, client_args); - if (server_args != NULL) grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - cqv = cq_verifier_create(f.cq); - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/service/method"), - get_host_override_slice("foo.test.google.fr:1234", config), - gpr_inf_future(GPR_CLOCK_REALTIME), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - if (send_limit) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - goto done; - } - - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.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); - - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - -done: - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT( - grpc_slice_str_cmp( - details, send_limit - ? "Sent message larger than max (11 vs. 5)" - : "Received message larger than max (11 vs. 5)") == 0); - - grpc_slice_unref(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_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(recv_payload); - - grpc_call_unref(c); - if (s != NULL) grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); -} - -// Test with response larger than the limit. -// If send_limit is true, applies send limit on server; otherwise, applies -// recv limit on client. -static void test_max_message_length_on_response(grpc_end2end_test_config config, - bool send_limit, - bool use_service_config, - bool use_string_json_value) { - gpr_log(GPR_INFO, - "testing response with send_limit=%d use_service_config=%d " - "use_string_json_value=%d", - send_limit, use_service_config, use_string_json_value); - - grpc_end2end_test_fixture f; - grpc_call *c = NULL; - grpc_call *s = NULL; - cq_verifier *cqv; - grpc_op ops[6]; - grpc_op *op; - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer *recv_payload = NULL; - 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_slice details; - int was_cancelled = 2; - - grpc_channel_args *client_args = NULL; - grpc_channel_args *server_args = NULL; - if (use_service_config) { - // We don't currently support service configs on the server side. - GPR_ASSERT(!send_limit); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.string = - use_string_json_value - ? "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxResponseMessageBytes\": \"5\"\n" - " } ]\n" - "}" - : "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxResponseMessageBytes\": 5\n" - " } ]\n" - "}"; - client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - } else { - // Set limit via channel args. - grpc_arg arg; - arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH - : GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH; - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 5; - grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - if (send_limit) { - server_args = args; - } else { - client_args = args; - } - } - - f = begin_test(config, "test_max_response_message_length", client_args, - server_args); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - if (client_args != NULL) grpc_channel_args_destroy(&exec_ctx, client_args); - if (server_args != NULL) grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - cqv = cq_verifier_create(f.cq); - - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/service/method"), - get_host_override_slice("foo.test.google.fr:1234", config), - gpr_inf_future(GPR_CLOCK_REALTIME), 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); - - memset(ops, 0, sizeof(ops)); - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &recv_payload; - 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->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); - - memset(ops, 0, sizeof(ops)); - 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_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(0 == - grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234")); - - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT( - grpc_slice_str_cmp( - details, send_limit - ? "Sent message larger than max (11 vs. 5)" - : "Received message larger than max (11 vs. 5)") == 0); - - grpc_slice_unref(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_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(recv_payload); - - grpc_call_unref(c); - if (s != NULL) grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); -} - -void max_message_length(grpc_end2end_test_config config) { - test_max_message_length_on_request(config, false /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, true /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - true /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - true /* use_service_config */, - true /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - true /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - true /* use_service_config */, - true /* use_string_json_value */); -} - -void max_message_length_pre_init(void) {} diff --git a/test/core/end2end/tests/max_message_length.cc b/test/core/end2end/tests/max_message_length.cc new file mode 100644 index 0000000000..2ee7b0be42 --- /dev/null +++ b/test/core/end2end/tests/max_message_length.cc @@ -0,0 +1,511 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/service_config.h" + +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %s/%s", test_name, config.name); + // We intentionally do not pass the client and server args to + // create_fixture(), since we don't want the limit enforced on the + // proxy, only on the backend server. + f = config.create_fixture(NULL, NULL); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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)); + grpc_event ev = grpc_completion_queue_next( + f->cq, grpc_timeout_seconds_to_deadline(5), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag(1000)); + 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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Test with request larger than the limit. +// If send_limit is true, applies send limit on client; otherwise, applies +// recv limit on server. +static void test_max_message_length_on_request(grpc_end2end_test_config config, + bool send_limit, + bool use_service_config, + bool use_string_json_value) { + gpr_log(GPR_INFO, + "testing request with send_limit=%d use_service_config=%d " + "use_string_json_value=%d", + send_limit, use_service_config, use_string_json_value); + + grpc_end2end_test_fixture f; + grpc_call *c = NULL; + grpc_call *s = NULL; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + grpc_slice request_payload_slice = + grpc_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 = NULL; + 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_slice details; + int was_cancelled = 2; + + grpc_channel_args *client_args = NULL; + grpc_channel_args *server_args = NULL; + if (use_service_config) { + // We don't currently support service configs on the server side. + GPR_ASSERT(send_limit); + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = + use_string_json_value + ? const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxRequestMessageBytes\": \"5\"\n" + " } ]\n" + "}") + : const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxRequestMessageBytes\": 5\n" + " } ]\n" + "}"); + client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); + } else { + // Set limit via channel args. + grpc_arg arg; + arg.key = send_limit + ? const_cast(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) + : const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); + arg.type = GRPC_ARG_INTEGER; + arg.value.integer = 5; + grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); + if (send_limit) { + client_args = args; + } else { + server_args = args; + } + } + + f = begin_test(config, "test_max_request_message_length", client_args, + server_args); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + if (client_args != NULL) grpc_channel_args_destroy(&exec_ctx, client_args); + if (server_args != NULL) grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + cqv = cq_verifier_create(f.cq); + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + get_host_override_slice("foo.test.google.fr:1234", config), + gpr_inf_future(GPR_CLOCK_REALTIME), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + if (send_limit) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + goto done; + } + + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.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); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + +done: + GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); + GPR_ASSERT( + grpc_slice_str_cmp( + details, send_limit + ? "Sent message larger than max (11 vs. 5)" + : "Received message larger than max (11 vs. 5)") == 0); + + grpc_slice_unref(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_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(recv_payload); + + grpc_call_unref(c); + if (s != NULL) grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +// Test with response larger than the limit. +// If send_limit is true, applies send limit on server; otherwise, applies +// recv limit on client. +static void test_max_message_length_on_response(grpc_end2end_test_config config, + bool send_limit, + bool use_service_config, + bool use_string_json_value) { + gpr_log(GPR_INFO, + "testing response with send_limit=%d use_service_config=%d " + "use_string_json_value=%d", + send_limit, use_service_config, use_string_json_value); + + grpc_end2end_test_fixture f; + grpc_call *c = NULL; + grpc_call *s = NULL; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_byte_buffer *recv_payload = NULL; + 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_slice details; + int was_cancelled = 2; + + grpc_channel_args *client_args = NULL; + grpc_channel_args *server_args = NULL; + if (use_service_config) { + // We don't currently support service configs on the server side. + GPR_ASSERT(!send_limit); + grpc_arg arg; + arg.type = GRPC_ARG_STRING; + arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); + arg.value.string = const_cast( + use_string_json_value + ? "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxResponseMessageBytes\": \"5\"\n" + " } ]\n" + "}" + : "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxResponseMessageBytes\": 5\n" + " } ]\n" + "}"); + client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); + } else { + // Set limit via channel args. + grpc_arg arg; + arg.key = send_limit + ? const_cast(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) + : const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); + arg.type = GRPC_ARG_INTEGER; + arg.value.integer = 5; + grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); + if (send_limit) { + server_args = args; + } else { + client_args = args; + } + } + + f = begin_test(config, "test_max_response_message_length", client_args, + server_args); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + if (client_args != NULL) grpc_channel_args_destroy(&exec_ctx, client_args); + if (server_args != NULL) grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + cqv = cq_verifier_create(f.cq); + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + get_host_override_slice("foo.test.google.fr:1234", config), + gpr_inf_future(GPR_CLOCK_REALTIME), 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); + + memset(ops, 0, sizeof(ops)); + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &recv_payload; + 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->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); + + memset(ops, 0, sizeof(ops)); + 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_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); + GPR_ASSERT(0 == + grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234")); + + GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); + GPR_ASSERT( + grpc_slice_str_cmp( + details, send_limit + ? "Sent message larger than max (11 vs. 5)" + : "Received message larger than max (11 vs. 5)") == 0); + + grpc_slice_unref(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_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(recv_payload); + + grpc_call_unref(c); + if (s != NULL) grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +void max_message_length(grpc_end2end_test_config config) { + test_max_message_length_on_request(config, false /* send_limit */, + false /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_request(config, true /* send_limit */, + false /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_response(config, false /* send_limit */, + false /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_response(config, true /* send_limit */, + false /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_request(config, true /* send_limit */, + true /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_request(config, true /* send_limit */, + true /* use_service_config */, + true /* use_string_json_value */); + test_max_message_length_on_response(config, false /* send_limit */, + true /* use_service_config */, + false /* use_string_json_value */); + test_max_message_length_on_response(config, false /* send_limit */, + true /* use_service_config */, + true /* use_string_json_value */); +} + +void max_message_length_pre_init(void) {} diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c deleted file mode 100644 index c8667f4f4d..0000000000 --- a/test/core/end2end/tests/negative_deadline.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f, size_t num_ops) { - grpc_call *c; - 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; - grpc_slice details; - - gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); - - gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(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(config, f, num_ops); - end_test(&f); - config.tear_down_data(&f); -} - -void negative_deadline(grpc_end2end_test_config config) { - size_t i; - for (i = 1; i <= 4; i++) { - test_invoke_simple_request(config, i); - } -} - -void negative_deadline_pre_init(void) {} diff --git a/test/core/end2end/tests/negative_deadline.cc b/test/core/end2end/tests/negative_deadline.cc new file mode 100644 index 0000000000..c8667f4f4d --- /dev/null +++ b/test/core/end2end/tests/negative_deadline.cc @@ -0,0 +1,172 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f, size_t num_ops) { + grpc_call *c; + 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; + grpc_slice details; + + gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); + + gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_call_unref(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(config, f, num_ops); + end_test(&f); + config.tear_down_data(&f); +} + +void negative_deadline(grpc_end2end_test_config config) { + size_t i; + for (i = 1; i <= 4; i++) { + test_invoke_simple_request(config, i); + } +} + +void negative_deadline_pre_init(void) {} diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c deleted file mode 100644 index 4d77174e22..0000000000 --- a/test/core/end2end/tests/network_status_change.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -/* this is a private API but exposed here for testing*/ -extern void grpc_network_status_shutdown_all_endpoints(); - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(500); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test_invoke_network_status_change(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - 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_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - // Simulate the network loss event - grpc_network_status_shutdown_all_endpoints(); - - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - // TODO(makdharma) Update this when the shutdown_all_endpoints is implemented. - // Expected behavior of a RPC when network is lost. - // GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(status == GRPC_STATUS_OK); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void network_status_change(grpc_end2end_test_config config) { - if (config.feature_mask & - FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE) { - return; - } - test_invoke_network_status_change(config); -} - -void network_status_change_pre_init(void) {} diff --git a/test/core/end2end/tests/network_status_change.cc b/test/core/end2end/tests/network_status_change.cc new file mode 100644 index 0000000000..4d77174e22 --- /dev/null +++ b/test/core/end2end/tests/network_status_change.cc @@ -0,0 +1,239 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +/* this is a private API but exposed here for testing*/ +extern void grpc_network_status_shutdown_all_endpoints(); + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(500); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_network_status_change(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + // Simulate the network loss event + grpc_network_status_shutdown_all_endpoints(); + + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + // TODO(makdharma) Update this when the shutdown_all_endpoints is implemented. + // Expected behavior of a RPC when network is lost. + // GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(status == GRPC_STATUS_OK); + + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void network_status_change(grpc_end2end_test_config config) { + if (config.feature_mask & + FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE) { + return; + } + test_invoke_network_status_change(config); +} + +void network_status_change_pre_init(void) {} diff --git a/test/core/end2end/tests/no_logging.c b/test/core/end2end/tests/no_logging.c deleted file mode 100644 index f7d50c24dd..0000000000 --- a/test/core/end2end/tests/no_logging.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -enum { TIMEOUT = 200000 }; - -static void *tag(intptr_t t) { return (void *)t; } - -extern void gpr_default_log(gpr_log_func_args *args); - -static void test_no_log(gpr_log_func_args *args) { - char *message = NULL; - gpr_asprintf(&message, "Unwanted log: %s", args->message); - args->message = message; - gpr_default_log(args); - gpr_free(message); - abort(); -} - -static void test_no_error_log(gpr_log_func_args *args) { - if (args->severity == GPR_LOG_SEVERITY_ERROR) { - test_no_log(args); - } -} - -static gpr_atm g_log_func = (gpr_atm)gpr_default_log; - -static void log_dispatcher_func(gpr_log_func_args *args) { - gpr_log_func log_func = (gpr_log_func)gpr_atm_no_barrier_load(&g_log_func); - log_func(args); -} - -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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(0 == call_details.flags); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request_with_no_error_logging", - NULL, NULL); - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_10_simple_requests_with_no_error_logging", - NULL, NULL); - for (i = 0; i < 10; i++) { - simple_request_body(config, f); - gpr_log(GPR_INFO, "Passed simple request %d", i); - } - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_no_error_logging_in_entire_process( - grpc_end2end_test_config config) { - int i; - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_error_log); - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - } - test_invoke_10_simple_requests(config); - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); -} - -static void test_no_logging_in_one_request(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_no_logging_in_last_request", NULL, NULL); - for (i = 0; i < 10; i++) { - simple_request_body(config, f); - } - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_log); - simple_request_body(config, f); - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); - end_test(&f); - config.tear_down_data(&f); -} - -void no_logging(grpc_end2end_test_config config) { - gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); - grpc_tracer_set_enabled("all", 0); - gpr_set_log_function(log_dispatcher_func); - test_no_logging_in_one_request(config); - test_no_error_logging_in_entire_process(config); - gpr_set_log_function(gpr_default_log); -} - -void no_logging_pre_init(void) {} diff --git a/test/core/end2end/tests/no_logging.cc b/test/core/end2end/tests/no_logging.cc new file mode 100644 index 0000000000..d898ef0581 --- /dev/null +++ b/test/core/end2end/tests/no_logging.cc @@ -0,0 +1,296 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(intptr_t t) { return (void *)t; } + +extern "C" void gpr_default_log(gpr_log_func_args *args); + +static void test_no_log(gpr_log_func_args *args) { + char *message = NULL; + gpr_asprintf(&message, "Unwanted log: %s", args->message); + args->message = message; + gpr_default_log(args); + gpr_free(message); + abort(); +} + +static void test_no_error_log(gpr_log_func_args *args) { + if (args->severity == GPR_LOG_SEVERITY_ERROR) { + test_no_log(args); + } +} + +static gpr_atm g_log_func = (gpr_atm)gpr_default_log; + +static void log_dispatcher_func(gpr_log_func_args *args) { + gpr_log_func log_func = (gpr_log_func)gpr_atm_no_barrier_load(&g_log_func); + log_func(args); +} + +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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request_with_no_error_logging", + NULL, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_10_simple_requests_with_no_error_logging", + NULL, NULL); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + gpr_log(GPR_INFO, "Passed simple request %d", i); + } + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_no_error_logging_in_entire_process( + grpc_end2end_test_config config) { + int i; + gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_error_log); + for (i = 0; i < 10; i++) { + test_invoke_simple_request(config); + } + test_invoke_10_simple_requests(config); + gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); +} + +static void test_no_logging_in_one_request(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_no_logging_in_last_request", NULL, NULL); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + } + gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_log); + simple_request_body(config, f); + gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); + end_test(&f); + config.tear_down_data(&f); +} + +void no_logging(grpc_end2end_test_config config) { + gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); + grpc_tracer_set_enabled("all", 0); + gpr_set_log_function(log_dispatcher_func); + test_no_logging_in_one_request(config); + test_no_error_logging_in_entire_process(config); + gpr_set_log_function(gpr_default_log); +} + +void no_logging_pre_init(void) {} diff --git a/test/core/end2end/tests/no_op.c b/test/core/end2end/tests/no_op.c deleted file mode 100644 index 8400c27486..0000000000 --- a/test/core/end2end/tests/no_op.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_no_op(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = begin_test(config, "no-op", NULL, NULL); - end_test(&f); - config.tear_down_data(&f); -} - -void no_op(grpc_end2end_test_config config) { test_no_op(config); } - -void no_op_pre_init(void) {} diff --git a/test/core/end2end/tests/no_op.cc b/test/core/end2end/tests/no_op.cc new file mode 100644 index 0000000000..8400c27486 --- /dev/null +++ b/test/core/end2end/tests/no_op.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_no_op(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = begin_test(config, "no-op", NULL, NULL); + end_test(&f); + config.tear_down_data(&f); +} + +void no_op(grpc_end2end_test_config config) { test_no_op(config); } + +void no_op_pre_init(void) {} diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c deleted file mode 100644 index d98eed68e0..0000000000 --- a/test/core/end2end/tests/payload.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Creates and returns a grpc_slice containing random alphanumeric characters. - */ -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char *output; - const size_t output_size = 1024 * 1024; - output = (char *)gpr_malloc(output_size); - for (i = 0; i < output_size - 1; ++i) { - output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; - } - output[output_size - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; -} - -static void request_response_with_payload(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - /* Create large request and response bodies. These are big enough to require - * multiple round trips to deliver to the peer, and their exact contents of - * will be verified on completion. */ - grpc_slice request_payload_slice = generate_random_slice(); - grpc_slice response_payload_slice = generate_random_slice(); - - grpc_call *c; - grpc_call *s; - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = n_seconds_from_now(60); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -/* Client sends a request with payload, server reads then returns a response - payload and status. */ -static void test_invoke_request_response_with_payload( - grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = begin_test( - config, "test_invoke_request_response_with_payload", NULL, NULL); - request_response_with_payload(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_10_request_response_with_payload( - grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = begin_test( - config, "test_invoke_10_request_response_with_payload", NULL, NULL); - for (i = 0; i < 10; i++) { - request_response_with_payload(config, f); - } - end_test(&f); - config.tear_down_data(&f); -} - -void payload(grpc_end2end_test_config config) { - test_invoke_request_response_with_payload(config); - test_invoke_10_request_response_with_payload(config); -} - -void payload_pre_init(void) {} diff --git a/test/core/end2end/tests/payload.cc b/test/core/end2end/tests/payload.cc new file mode 100644 index 0000000000..d98eed68e0 --- /dev/null +++ b/test/core/end2end/tests/payload.cc @@ -0,0 +1,288 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Creates and returns a grpc_slice containing random alphanumeric characters. + */ +static grpc_slice generate_random_slice() { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + char *output; + const size_t output_size = 1024 * 1024; + output = (char *)gpr_malloc(output_size); + for (i = 0; i < output_size - 1; ++i) { + output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + output[output_size - 1] = '\0'; + grpc_slice out = grpc_slice_from_copied_string(output); + gpr_free(output); + return out; +} + +static void request_response_with_payload(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + /* Create large request and response bodies. These are big enough to require + * multiple round trips to deliver to the peer, and their exact contents of + * will be verified on completion. */ + grpc_slice request_payload_slice = generate_random_slice(); + grpc_slice response_payload_slice = generate_random_slice(); + + grpc_call *c; + grpc_call *s; + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = n_seconds_from_now(60); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); + GPR_ASSERT( + byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); +} + +/* Client sends a request with payload, server reads then returns a response + payload and status. */ +static void test_invoke_request_response_with_payload( + grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = begin_test( + config, "test_invoke_request_response_with_payload", NULL, NULL); + request_response_with_payload(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_10_request_response_with_payload( + grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = begin_test( + config, "test_invoke_10_request_response_with_payload", NULL, NULL); + for (i = 0; i < 10; i++) { + request_response_with_payload(config, f); + } + end_test(&f); + config.tear_down_data(&f); +} + +void payload(grpc_end2end_test_config config) { + test_invoke_request_response_with_payload(config); + test_invoke_10_request_response_with_payload(config); +} + +void payload_pre_init(void) {} diff --git a/test/core/end2end/tests/ping.c b/test/core/end2end/tests/ping.c deleted file mode 100644 index 23c82569ba..0000000000 --- a/test/core/end2end/tests/ping.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include -#include -#include -#include - -#include "test/core/end2end/cq_verifier.h" - -#define PING_NUM 5 - -static void *tag(intptr_t t) { return (void *)t; } - -static void test_ping(grpc_end2end_test_config config, - int min_time_between_pings_ms) { - 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; - - grpc_arg client_a[] = { - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS, - .value.integer = 10}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, - .value.integer = 0}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, - .value.integer = 1}}; - grpc_arg server_a[] = { - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, - .value.integer = 0}, - {.type = GRPC_ARG_INTEGER, - .key = GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, - .value.integer = 1}}; - grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(client_a), - .args = client_a}; - grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a), - .args = server_a}; - - config.init_client(&f, &client_args); - config.init_server(&f, &server_args); - - 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, - gpr_time_add(grpc_timeout_seconds_to_deadline(3), - gpr_time_from_millis(min_time_between_pings_ms * PING_NUM, - GPR_TIMESPAN)), - 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 <= PING_NUM; 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); - - /* f.shutdown_cq is not used in this test */ - grpc_completion_queue_destroy(f.shutdown_cq); - config.tear_down_data(&f); - - cq_verifier_destroy(cqv); -} - -void ping(grpc_end2end_test_config config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_ping(config, 0); - test_ping(config, 100); -} - -void ping_pre_init(void) {} diff --git a/test/core/end2end/tests/ping.cc b/test/core/end2end/tests/ping.cc new file mode 100644 index 0000000000..e6b0e55b01 --- /dev/null +++ b/test/core/end2end/tests/ping.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include +#include +#include + +#include "test/core/end2end/cq_verifier.h" + +#define PING_NUM 5 + +static void *tag(intptr_t t) { return (void *)t; } + +static void test_ping(grpc_end2end_test_config config, + int min_time_between_pings_ms) { + 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; + + grpc_arg client_a[3]; + client_a[0].type = GRPC_ARG_INTEGER; + client_a[0].key = + const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); + client_a[0].value.integer = 10; + client_a[1].type = GRPC_ARG_INTEGER; + client_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA); + client_a[1].value.integer = 0; + client_a[2].type = GRPC_ARG_INTEGER; + client_a[2].key = const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS); + client_a[2].value.integer = 1; + grpc_arg server_a[2]; + server_a[0].type = GRPC_ARG_INTEGER; + server_a[0].key = + const_cast(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS); + server_a[0].value.integer = 0; + server_a[1].type = GRPC_ARG_INTEGER; + server_a[1].key = const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS); + server_a[1].value.integer = 1; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + + config.init_client(&f, &client_args); + config.init_server(&f, &server_args); + + 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, + gpr_time_add(grpc_timeout_seconds_to_deadline(3), + gpr_time_from_millis(min_time_between_pings_ms * PING_NUM, + GPR_TIMESPAN)), + 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 <= PING_NUM; 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); + + /* f.shutdown_cq is not used in this test */ + grpc_completion_queue_destroy(f.shutdown_cq); + config.tear_down_data(&f); + + cq_verifier_destroy(cqv); +} + +void ping(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + test_ping(config, 0); + test_ping(config, 100); +} + +void ping_pre_init(void) {} diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c deleted file mode 100644 index 1c44262c3d..0000000000 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client pings and server pongs. Repeat messages rounds before finishing. */ -static void test_pingpong_streaming(grpc_end2end_test_config config, - int messages) { - grpc_end2end_test_fixture f = - begin_test(config, "test_pingpong_streaming", NULL, NULL); - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - grpc_byte_buffer *request_payload; - grpc_byte_buffer *request_payload_recv; - grpc_byte_buffer *response_payload; - grpc_byte_buffer *response_payload_recv; - int i; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(100), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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_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(101), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (i = 0; i < messages; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - cq_verify(cqv); - - grpc_call_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - 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_slice_unref(details); - - end_test(&f); - config.tear_down_data(&f); -} - -void ping_pong_streaming(grpc_end2end_test_config config) { - int i; - - for (i = 1; i < 10; i++) { - test_pingpong_streaming(config, i); - } -} - -void ping_pong_streaming_pre_init(void) {} diff --git a/test/core/end2end/tests/ping_pong_streaming.cc b/test/core/end2end/tests/ping_pong_streaming.cc new file mode 100644 index 0000000000..1c44262c3d --- /dev/null +++ b/test/core/end2end/tests/ping_pong_streaming.cc @@ -0,0 +1,276 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client pings and server pongs. Repeat messages rounds before finishing. */ +static void test_pingpong_streaming(grpc_end2end_test_config config, + int messages) { + grpc_end2end_test_fixture f = + begin_test(config, "test_pingpong_streaming", NULL, NULL); + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + grpc_byte_buffer *request_payload; + grpc_byte_buffer *request_payload_recv; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + int i; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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_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(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (i = 0; i < messages; i++) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + 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_slice_unref(details); + + end_test(&f); + config.tear_down_data(&f); +} + +void ping_pong_streaming(grpc_end2end_test_config config) { + int i; + + for (i = 1; i < 10; i++) { + test_pingpong_streaming(config, i); + } +} + +void ping_pong_streaming_pre_init(void) {} diff --git a/test/core/end2end/tests/proxy_auth.c b/test/core/end2end/tests/proxy_auth.c deleted file mode 100644 index d922049bcb..0000000000 --- a/test/core/end2end/tests/proxy_auth.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * This test is for checking whether proxy authentication is working with HTTP - * Connect. - */ -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/http_proxy_fixture.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(0 == call_details.flags); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_proxy_auth(grpc_end2end_test_config config) { - /* Indicate that the proxy requires user auth */ - grpc_arg client_arg = {.type = GRPC_ARG_STRING, - .key = GRPC_ARG_HTTP_PROXY_AUTH_CREDS, - .value.string = GRPC_TEST_HTTP_PROXY_AUTH_CREDS}; - grpc_channel_args client_args = {.num_args = 1, .args = &client_arg}; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_proxy_auth", &client_args, NULL); - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -void proxy_auth(grpc_end2end_test_config config) { - test_invoke_proxy_auth(config); -} - -void proxy_auth_pre_init(void) {} diff --git a/test/core/end2end/tests/proxy_auth.cc b/test/core/end2end/tests/proxy_auth.cc new file mode 100644 index 0000000000..fe87399f03 --- /dev/null +++ b/test/core/end2end/tests/proxy_auth.cc @@ -0,0 +1,236 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * This test is for checking whether proxy authentication is working with HTTP + * Connect. + */ +#include "test/core/end2end/end2end_tests.h" +#include "test/core/end2end/fixtures/http_proxy_fixture.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_proxy_auth(grpc_end2end_test_config config) { + /* Indicate that the proxy requires user auth */ + grpc_arg client_arg; + client_arg.type = GRPC_ARG_STRING; + client_arg.key = const_cast(GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + client_arg.value.string = const_cast(GRPC_TEST_HTTP_PROXY_AUTH_CREDS); + grpc_channel_args client_args = {1, &client_arg}; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_proxy_auth", &client_args, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +void proxy_auth(grpc_end2end_test_config config) { + test_invoke_proxy_auth(config); +} + +void proxy_auth_pre_init(void) {} diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c deleted file mode 100644 index 4598029818..0000000000 --- a/test/core/end2end/tests/registered_call.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f, void *rc) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_registered_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, rc, 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_simple_request", NULL, NULL); - void *rc = grpc_channel_register_call( - f.client, "/foo", - get_host_override_string("foo.test.google.fr:1234", config), NULL); - - simple_request_body(config, f, rc); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); - void *rc = grpc_channel_register_call( - f.client, "/foo", - get_host_override_string("foo.test.google.fr:1234", config), NULL); - - for (i = 0; i < 10; i++) { - simple_request_body(config, f, rc); - gpr_log(GPR_INFO, "Passed simple request %d", i); - } - end_test(&f); - config.tear_down_data(&f); -} - -void registered_call(grpc_end2end_test_config config) { - test_invoke_simple_request(config); - test_invoke_10_simple_requests(config); -} - -void registered_call_pre_init(void) {} diff --git a/test/core/end2end/tests/registered_call.cc b/test/core/end2end/tests/registered_call.cc new file mode 100644 index 0000000000..4598029818 --- /dev/null +++ b/test/core/end2end/tests/registered_call.cc @@ -0,0 +1,227 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f, void *rc) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_registered_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, rc, 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_simple_request", NULL, NULL); + void *rc = grpc_channel_register_call( + f.client, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), NULL); + + simple_request_body(config, f, rc); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); + void *rc = grpc_channel_register_call( + f.client, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), NULL); + + for (i = 0; i < 10; i++) { + simple_request_body(config, f, rc); + gpr_log(GPR_INFO, "Passed simple request %d", i); + } + end_test(&f); + config.tear_down_data(&f); +} + +void registered_call(grpc_end2end_test_config config) { + test_invoke_simple_request(config); + test_invoke_10_simple_requests(config); +} + +void registered_call_pre_init(void) {} diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c deleted file mode 100644 index dfb7d58743..0000000000 --- a/test/core/end2end/tests/request_with_flags.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "src/core/lib/transport/byte_stream.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_invoke_request_with_flags( - grpc_end2end_test_config config, uint32_t *flags_for_op, - grpc_call_error call_start_batch_expected_result) { - grpc_call *c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_flags", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_call_error expectation; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = flags_for_op[op->op]; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = flags_for_op[op->op]; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = flags_for_op[op->op]; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = flags_for_op[op->op]; - 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->flags = flags_for_op[op->op]; - op->reserved = NULL; - op++; - expectation = call_start_batch_expected_result; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(expectation == error); - - if (expectation == GRPC_CALL_OK) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - grpc_slice_unref(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_unref(c); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void request_with_flags(grpc_end2end_test_config config) { - size_t i; - uint32_t flags_for_op[GRPC_OP_RECV_CLOSE_ON_SERVER + 1]; - - { - /* check that all grpc_op_types fail when their flag value is set to an - * invalid value */ - int indices[] = {GRPC_OP_SEND_INITIAL_METADATA, GRPC_OP_SEND_MESSAGE, - GRPC_OP_SEND_CLOSE_FROM_CLIENT, - GRPC_OP_RECV_INITIAL_METADATA, - GRPC_OP_RECV_STATUS_ON_CLIENT}; - for (i = 0; i < GPR_ARRAY_SIZE(indices); ++i) { - memset(flags_for_op, 0, sizeof(flags_for_op)); - flags_for_op[indices[i]] = 0xDEADBEEF; - test_invoke_request_with_flags(config, flags_for_op, - GRPC_CALL_ERROR_INVALID_FLAGS); - } - } - { - /* check valid operation with allowed flags for GRPC_OP_SEND_BUFFER */ - uint32_t flags[] = {GRPC_WRITE_BUFFER_HINT, GRPC_WRITE_NO_COMPRESS, - GRPC_WRITE_INTERNAL_COMPRESS}; - for (i = 0; i < GPR_ARRAY_SIZE(flags); ++i) { - memset(flags_for_op, 0, sizeof(flags_for_op)); - flags_for_op[GRPC_OP_SEND_MESSAGE] = flags[i]; - test_invoke_request_with_flags(config, flags_for_op, GRPC_CALL_OK); - } - } -} - -void request_with_flags_pre_init(void) {} diff --git a/test/core/end2end/tests/request_with_flags.cc b/test/core/end2end/tests/request_with_flags.cc new file mode 100644 index 0000000000..dfb7d58743 --- /dev/null +++ b/test/core/end2end/tests/request_with_flags.cc @@ -0,0 +1,208 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/lib/transport/byte_stream.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_invoke_request_with_flags( + grpc_end2end_test_config config, uint32_t *flags_for_op, + grpc_call_error call_start_batch_expected_result) { + grpc_call *c; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_flags", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + grpc_call_error expectation; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = flags_for_op[op->op]; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = flags_for_op[op->op]; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = flags_for_op[op->op]; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = flags_for_op[op->op]; + 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->flags = flags_for_op[op->op]; + op->reserved = NULL; + op++; + expectation = call_start_batch_expected_result; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(expectation == error); + + if (expectation == GRPC_CALL_OK) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + grpc_slice_unref(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_unref(c); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void request_with_flags(grpc_end2end_test_config config) { + size_t i; + uint32_t flags_for_op[GRPC_OP_RECV_CLOSE_ON_SERVER + 1]; + + { + /* check that all grpc_op_types fail when their flag value is set to an + * invalid value */ + int indices[] = {GRPC_OP_SEND_INITIAL_METADATA, GRPC_OP_SEND_MESSAGE, + GRPC_OP_SEND_CLOSE_FROM_CLIENT, + GRPC_OP_RECV_INITIAL_METADATA, + GRPC_OP_RECV_STATUS_ON_CLIENT}; + for (i = 0; i < GPR_ARRAY_SIZE(indices); ++i) { + memset(flags_for_op, 0, sizeof(flags_for_op)); + flags_for_op[indices[i]] = 0xDEADBEEF; + test_invoke_request_with_flags(config, flags_for_op, + GRPC_CALL_ERROR_INVALID_FLAGS); + } + } + { + /* check valid operation with allowed flags for GRPC_OP_SEND_BUFFER */ + uint32_t flags[] = {GRPC_WRITE_BUFFER_HINT, GRPC_WRITE_NO_COMPRESS, + GRPC_WRITE_INTERNAL_COMPRESS}; + for (i = 0; i < GPR_ARRAY_SIZE(flags); ++i) { + memset(flags_for_op, 0, sizeof(flags_for_op)); + flags_for_op[GRPC_OP_SEND_MESSAGE] = flags[i]; + test_invoke_request_with_flags(config, flags_for_op, GRPC_CALL_OK); + } + } +} + +void request_with_flags_pre_init(void) {} diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c deleted file mode 100644 index 575e54c7d9..0000000000 --- a/test/core/end2end/tests/request_with_payload.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test_invoke_request_with_payload(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.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->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); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void request_with_payload(grpc_end2end_test_config config) { - test_invoke_request_with_payload(config); -} - -void request_with_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/request_with_payload.cc b/test/core/end2end/tests/request_with_payload.cc new file mode 100644 index 0000000000..575e54c7d9 --- /dev/null +++ b/test/core/end2end/tests/request_with_payload.cc @@ -0,0 +1,230 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.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->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); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void request_with_payload(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void request_with_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c deleted file mode 100644 index 93befeee0c..0000000000 --- a/test/core/end2end/tests/resource_quota_server.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Creates and returns a grpc_slice containing random alphanumeric characters. - */ -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char *output; - const size_t output_size = 1024 * 1024; - output = (char *)gpr_malloc(output_size); - for (i = 0; i < output_size - 1; ++i) { - output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; - } - output[output_size - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; -} - -void resource_quota_server(grpc_end2end_test_config config) { - if (config.feature_mask & - FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER) { - return; - } - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("test_server"); - grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024); - -#define NUM_CALLS 100 -#define CLIENT_BASE_TAG 0x1000 -#define SERVER_START_BASE_TAG 0x2000 -#define SERVER_RECV_BASE_TAG 0x3000 -#define SERVER_END_BASE_TAG 0x4000 - - grpc_arg arg; - arg.key = GRPC_ARG_RESOURCE_QUOTA; - arg.type = GRPC_ARG_POINTER; - arg.value.pointer.p = resource_quota; - arg.value.pointer.vtable = grpc_resource_quota_arg_vtable(); - grpc_channel_args args = {1, &arg}; - - grpc_end2end_test_fixture f = - begin_test(config, "resource_quota_server", NULL, &args); - - /* Create large request and response bodies. These are big enough to require - * multiple round trips to deliver to the peer, and their exact contents of - * will be verified on completion. */ - grpc_slice request_payload_slice = generate_random_slice(); - - grpc_call **client_calls = - (grpc_call **)malloc(sizeof(grpc_call *) * NUM_CALLS); - grpc_call **server_calls = - (grpc_call **)malloc(sizeof(grpc_call *) * NUM_CALLS); - grpc_metadata_array *initial_metadata_recv = - (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); - grpc_metadata_array *trailing_metadata_recv = - (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); - grpc_metadata_array *request_metadata_recv = - (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); - grpc_call_details *call_details = - (grpc_call_details *)malloc(sizeof(grpc_call_details) * NUM_CALLS); - grpc_status_code *status = - (grpc_status_code *)malloc(sizeof(grpc_status_code) * NUM_CALLS); - grpc_slice *details = (grpc_slice *)malloc(sizeof(grpc_slice) * NUM_CALLS); - grpc_byte_buffer **request_payload = - (grpc_byte_buffer **)malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS); - grpc_byte_buffer **request_payload_recv = - (grpc_byte_buffer **)malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS); - int *was_cancelled = (int *)malloc(sizeof(int) * NUM_CALLS); - grpc_call_error error; - int pending_client_calls = 0; - int pending_server_start_calls = 0; - int pending_server_recv_calls = 0; - int pending_server_end_calls = 0; - int cancelled_calls_on_client = 0; - int cancelled_calls_on_server = 0; - int deadline_exceeded = 0; - int unavailable = 0; - - grpc_op ops[6]; - grpc_op *op; - - for (int i = 0; i < NUM_CALLS; i++) { - grpc_metadata_array_init(&initial_metadata_recv[i]); - grpc_metadata_array_init(&trailing_metadata_recv[i]); - grpc_metadata_array_init(&request_metadata_recv[i]); - grpc_call_details_init(&call_details[i]); - request_payload[i] = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - request_payload_recv[i] = NULL; - was_cancelled[i] = 0; - } - - for (int i = 0; i < NUM_CALLS; i++) { - error = grpc_server_request_call( - f.server, &server_calls[i], &call_details[i], &request_metadata_recv[i], - f.cq, f.cq, tag(SERVER_START_BASE_TAG + i)); - GPR_ASSERT(GRPC_CALL_OK == error); - - pending_server_start_calls++; - } - - for (int i = 0; i < NUM_CALLS; i++) { - client_calls[i] = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr", config), - n_seconds_from_now(60), NULL); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload[i]; - 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.recv_initial_metadata = - &initial_metadata_recv[i]; - 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[i]; - op->data.recv_status_on_client.status = &status[i]; - op->data.recv_status_on_client.status_details = &details[i]; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(client_calls[i], ops, (size_t)(op - ops), - tag(CLIENT_BASE_TAG + i), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - pending_client_calls++; - } - - while (pending_client_calls + pending_server_recv_calls + - pending_server_end_calls > - 0) { - grpc_event ev = - grpc_completion_queue_next(f.cq, n_seconds_from_now(60), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - - int ev_tag = (int)(intptr_t)ev.tag; - if (ev_tag < CLIENT_BASE_TAG) { - abort(); /* illegal tag */ - } else if (ev_tag < SERVER_START_BASE_TAG) { - /* client call finished */ - int call_id = ev_tag - CLIENT_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - switch (status[call_id]) { - case GRPC_STATUS_RESOURCE_EXHAUSTED: - cancelled_calls_on_client++; - break; - case GRPC_STATUS_DEADLINE_EXCEEDED: - deadline_exceeded++; - break; - case GRPC_STATUS_UNAVAILABLE: - unavailable++; - break; - case GRPC_STATUS_OK: - break; - default: - gpr_log(GPR_ERROR, "Unexpected status code: %d", status[call_id]); - abort(); - } - GPR_ASSERT(pending_client_calls > 0); - - grpc_metadata_array_destroy(&initial_metadata_recv[call_id]); - grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]); - grpc_call_unref(client_calls[call_id]); - grpc_slice_unref(details[call_id]); - grpc_byte_buffer_destroy(request_payload[call_id]); - - pending_client_calls--; - } else if (ev_tag < SERVER_RECV_BASE_TAG) { - /* new incoming call to the server */ - int call_id = ev_tag - SERVER_START_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv[call_id]; - op->flags = 0; - op->reserved = NULL; - op++; - error = - grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops), - tag(SERVER_RECV_BASE_TAG + call_id), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(pending_server_start_calls > 0); - pending_server_start_calls--; - pending_server_recv_calls++; - - grpc_call_details_destroy(&call_details[call_id]); - grpc_metadata_array_destroy(&request_metadata_recv[call_id]); - } else if (ev_tag < SERVER_END_BASE_TAG) { - /* finished read on the server */ - int call_id = ev_tag - SERVER_RECV_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - if (ev.success) { - if (request_payload_recv[call_id] != NULL) { - grpc_byte_buffer_destroy(request_payload_recv[call_id]); - request_payload_recv[call_id] = NULL; - } - } else { - GPR_ASSERT(request_payload_recv[call_id] == NULL); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled[call_id]; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = - grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops), - tag(SERVER_END_BASE_TAG + call_id), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(pending_server_recv_calls > 0); - pending_server_recv_calls--; - pending_server_end_calls++; - } else { - int call_id = ev_tag - SERVER_END_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - if (was_cancelled[call_id]) { - cancelled_calls_on_server++; - } - GPR_ASSERT(pending_server_end_calls > 0); - pending_server_end_calls--; - - grpc_call_unref(server_calls[call_id]); - } - } - - gpr_log(GPR_INFO, - "Done. %d total calls: %d cancelled at server, %d cancelled at " - "client, %d timed out, %d unavailable.", - NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client, - deadline_exceeded, unavailable); - - grpc_slice_unref(request_payload_slice); - grpc_resource_quota_unref(resource_quota); - - end_test(&f); - config.tear_down_data(&f); - - free(client_calls); - free(server_calls); - free(initial_metadata_recv); - free(trailing_metadata_recv); - free(request_metadata_recv); - free(call_details); - free(status); - free(details); - free(request_payload); - free(request_payload_recv); - free(was_cancelled); -} - -void resource_quota_server_pre_init(void) {} diff --git a/test/core/end2end/tests/resource_quota_server.cc b/test/core/end2end/tests/resource_quota_server.cc new file mode 100644 index 0000000000..e710e39e1d --- /dev/null +++ b/test/core/end2end/tests/resource_quota_server.cc @@ -0,0 +1,377 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Creates and returns a grpc_slice containing random alphanumeric characters. + */ +static grpc_slice generate_random_slice() { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + char *output; + const size_t output_size = 1024 * 1024; + output = (char *)gpr_malloc(output_size); + for (i = 0; i < output_size - 1; ++i) { + output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + output[output_size - 1] = '\0'; + grpc_slice out = grpc_slice_from_copied_string(output); + gpr_free(output); + return out; +} + +void resource_quota_server(grpc_end2end_test_config config) { + if (config.feature_mask & + FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER) { + return; + } + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("test_server"); + grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024); + +#define NUM_CALLS 100 +#define CLIENT_BASE_TAG 0x1000 +#define SERVER_START_BASE_TAG 0x2000 +#define SERVER_RECV_BASE_TAG 0x3000 +#define SERVER_END_BASE_TAG 0x4000 + + grpc_arg arg; + arg.key = const_cast(GRPC_ARG_RESOURCE_QUOTA); + arg.type = GRPC_ARG_POINTER; + arg.value.pointer.p = resource_quota; + arg.value.pointer.vtable = grpc_resource_quota_arg_vtable(); + grpc_channel_args args = {1, &arg}; + + grpc_end2end_test_fixture f = + begin_test(config, "resource_quota_server", NULL, &args); + + /* Create large request and response bodies. These are big enough to require + * multiple round trips to deliver to the peer, and their exact contents of + * will be verified on completion. */ + grpc_slice request_payload_slice = generate_random_slice(); + + grpc_call **client_calls = + (grpc_call **)malloc(sizeof(grpc_call *) * NUM_CALLS); + grpc_call **server_calls = + (grpc_call **)malloc(sizeof(grpc_call *) * NUM_CALLS); + grpc_metadata_array *initial_metadata_recv = + (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); + grpc_metadata_array *trailing_metadata_recv = + (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); + grpc_metadata_array *request_metadata_recv = + (grpc_metadata_array *)malloc(sizeof(grpc_metadata_array) * NUM_CALLS); + grpc_call_details *call_details = + (grpc_call_details *)malloc(sizeof(grpc_call_details) * NUM_CALLS); + grpc_status_code *status = + (grpc_status_code *)malloc(sizeof(grpc_status_code) * NUM_CALLS); + grpc_slice *details = (grpc_slice *)malloc(sizeof(grpc_slice) * NUM_CALLS); + grpc_byte_buffer **request_payload = + (grpc_byte_buffer **)malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS); + grpc_byte_buffer **request_payload_recv = + (grpc_byte_buffer **)malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS); + int *was_cancelled = (int *)malloc(sizeof(int) * NUM_CALLS); + grpc_call_error error; + int pending_client_calls = 0; + int pending_server_start_calls = 0; + int pending_server_recv_calls = 0; + int pending_server_end_calls = 0; + int cancelled_calls_on_client = 0; + int cancelled_calls_on_server = 0; + int deadline_exceeded = 0; + int unavailable = 0; + + grpc_op ops[6]; + grpc_op *op; + + for (int i = 0; i < NUM_CALLS; i++) { + grpc_metadata_array_init(&initial_metadata_recv[i]); + grpc_metadata_array_init(&trailing_metadata_recv[i]); + grpc_metadata_array_init(&request_metadata_recv[i]); + grpc_call_details_init(&call_details[i]); + request_payload[i] = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + request_payload_recv[i] = NULL; + was_cancelled[i] = 0; + } + + for (int i = 0; i < NUM_CALLS; i++) { + error = grpc_server_request_call( + f.server, &server_calls[i], &call_details[i], &request_metadata_recv[i], + f.cq, f.cq, tag(SERVER_START_BASE_TAG + i)); + GPR_ASSERT(GRPC_CALL_OK == error); + + pending_server_start_calls++; + } + + for (int i = 0; i < NUM_CALLS; i++) { + client_calls[i] = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr", config), + n_seconds_from_now(60), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload[i]; + 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.recv_initial_metadata = + &initial_metadata_recv[i]; + 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[i]; + op->data.recv_status_on_client.status = &status[i]; + op->data.recv_status_on_client.status_details = &details[i]; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(client_calls[i], ops, (size_t)(op - ops), + tag(CLIENT_BASE_TAG + i), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + pending_client_calls++; + } + + while (pending_client_calls + pending_server_recv_calls + + pending_server_end_calls > + 0) { + grpc_event ev = + grpc_completion_queue_next(f.cq, n_seconds_from_now(60), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + + int ev_tag = (int)(intptr_t)ev.tag; + if (ev_tag < CLIENT_BASE_TAG) { + abort(); /* illegal tag */ + } else if (ev_tag < SERVER_START_BASE_TAG) { + /* client call finished */ + int call_id = ev_tag - CLIENT_BASE_TAG; + GPR_ASSERT(call_id >= 0); + GPR_ASSERT(call_id < NUM_CALLS); + switch (status[call_id]) { + case GRPC_STATUS_RESOURCE_EXHAUSTED: + cancelled_calls_on_client++; + break; + case GRPC_STATUS_DEADLINE_EXCEEDED: + deadline_exceeded++; + break; + case GRPC_STATUS_UNAVAILABLE: + unavailable++; + break; + case GRPC_STATUS_OK: + break; + default: + gpr_log(GPR_ERROR, "Unexpected status code: %d", status[call_id]); + abort(); + } + GPR_ASSERT(pending_client_calls > 0); + + grpc_metadata_array_destroy(&initial_metadata_recv[call_id]); + grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]); + grpc_call_unref(client_calls[call_id]); + grpc_slice_unref(details[call_id]); + grpc_byte_buffer_destroy(request_payload[call_id]); + + pending_client_calls--; + } else if (ev_tag < SERVER_RECV_BASE_TAG) { + /* new incoming call to the server */ + int call_id = ev_tag - SERVER_START_BASE_TAG; + GPR_ASSERT(call_id >= 0); + GPR_ASSERT(call_id < NUM_CALLS); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv[call_id]; + op->flags = 0; + op->reserved = NULL; + op++; + error = + grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops), + tag(SERVER_RECV_BASE_TAG + call_id), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(pending_server_start_calls > 0); + pending_server_start_calls--; + pending_server_recv_calls++; + + grpc_call_details_destroy(&call_details[call_id]); + grpc_metadata_array_destroy(&request_metadata_recv[call_id]); + } else if (ev_tag < SERVER_END_BASE_TAG) { + /* finished read on the server */ + int call_id = ev_tag - SERVER_RECV_BASE_TAG; + GPR_ASSERT(call_id >= 0); + GPR_ASSERT(call_id < NUM_CALLS); + + if (ev.success) { + if (request_payload_recv[call_id] != NULL) { + grpc_byte_buffer_destroy(request_payload_recv[call_id]); + request_payload_recv[call_id] = NULL; + } + } else { + GPR_ASSERT(request_payload_recv[call_id] == NULL); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled[call_id]; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = + grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops), + tag(SERVER_END_BASE_TAG + call_id), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(pending_server_recv_calls > 0); + pending_server_recv_calls--; + pending_server_end_calls++; + } else { + int call_id = ev_tag - SERVER_END_BASE_TAG; + GPR_ASSERT(call_id >= 0); + GPR_ASSERT(call_id < NUM_CALLS); + + if (was_cancelled[call_id]) { + cancelled_calls_on_server++; + } + GPR_ASSERT(pending_server_end_calls > 0); + pending_server_end_calls--; + + grpc_call_unref(server_calls[call_id]); + } + } + + gpr_log(GPR_INFO, + "Done. %d total calls: %d cancelled at server, %d cancelled at " + "client, %d timed out, %d unavailable.", + NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client, + deadline_exceeded, unavailable); + + grpc_slice_unref(request_payload_slice); + grpc_resource_quota_unref(resource_quota); + + end_test(&f); + config.tear_down_data(&f); + + free(client_calls); + free(server_calls); + free(initial_metadata_recv); + free(trailing_metadata_recv); + free(request_metadata_recv); + free(call_details); + free(status); + free(details); + free(request_payload); + free(request_payload_recv); + free(was_cancelled); +} + +void resource_quota_server_pre_init(void) {} diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c deleted file mode 100644 index 49b9f27396..0000000000 --- a/test/core/end2end/tests/server_finishes_request.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request", NULL, NULL); - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -void server_finishes_request(grpc_end2end_test_config config) { - test_invoke_simple_request(config); -} - -void server_finishes_request_pre_init(void) {} diff --git a/test/core/end2end/tests/server_finishes_request.cc b/test/core/end2end/tests/server_finishes_request.cc new file mode 100644 index 0000000000..49b9f27396 --- /dev/null +++ b/test/core/end2end/tests/server_finishes_request.cc @@ -0,0 +1,206 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +void server_finishes_request(grpc_end2end_test_config config) { + test_invoke_simple_request(config); +} + +void server_finishes_request_pre_init(void) {} diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c deleted file mode 100644 index f90359f09a..0000000000 --- a/test/core/end2end/tests/shutdown_finishes_calls.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -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_client(f); - - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); - /* f->shutdown_cq is not used in this test */ - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_early_server_shutdown_finishes_inflight_calls( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_end2end_test_fixture f = begin_test( - config, "test_early_server_shutdown_finishes_inflight_calls", NULL, NULL); - 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_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = NULL; - 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.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->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); - - memset(ops, 0, sizeof(ops)); - op = ops; - 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); - - /* shutdown and destroy the server */ - grpc_server_shutdown_and_notify(f.server, f.cq, tag(1000)); - grpc_server_cancel_all_calls(f.server); - - CQ_EXPECT_COMPLETION(cqv, tag(1000), 1); - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - grpc_server_destroy(f.server); - - // new code should give INTERNAL, some older code will give UNAVAILABLE - GPR_ASSERT(status == GRPC_STATUS_INTERNAL || - status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - end_test(&f); - config.tear_down_data(&f); -} - -void shutdown_finishes_calls(grpc_end2end_test_config config) { - test_early_server_shutdown_finishes_inflight_calls(config); -} - -void shutdown_finishes_calls_pre_init(void) {} diff --git a/test/core/end2end/tests/shutdown_finishes_calls.cc b/test/core/end2end/tests/shutdown_finishes_calls.cc new file mode 100644 index 0000000000..f90359f09a --- /dev/null +++ b/test/core/end2end/tests/shutdown_finishes_calls.cc @@ -0,0 +1,189 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +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_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + /* f->shutdown_cq is not used in this test */ + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_early_server_shutdown_finishes_inflight_calls( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_end2end_test_fixture f = begin_test( + config, "test_early_server_shutdown_finishes_inflight_calls", NULL, NULL); + 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_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->data.send_initial_metadata.metadata = NULL; + 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.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->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); + + memset(ops, 0, sizeof(ops)); + op = ops; + 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); + + /* shutdown and destroy the server */ + grpc_server_shutdown_and_notify(f.server, f.cq, tag(1000)); + grpc_server_cancel_all_calls(f.server); + + CQ_EXPECT_COMPLETION(cqv, tag(1000), 1); + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + grpc_server_destroy(f.server); + + // new code should give INTERNAL, some older code will give UNAVAILABLE + GPR_ASSERT(status == GRPC_STATUS_INTERNAL || + status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +void shutdown_finishes_calls(grpc_end2end_test_config config) { + test_early_server_shutdown_finishes_inflight_calls(config); +} + +void shutdown_finishes_calls_pre_init(void) {} diff --git a/test/core/end2end/tests/shutdown_finishes_tags.c b/test/core/end2end/tests/shutdown_finishes_tags.c deleted file mode 100644 index 7914cc95ba..0000000000 --- a/test/core/end2end/tests/shutdown_finishes_tags.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -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_client(f); - - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); - /* f->shutdown_cq is not used in this test */ - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void test_early_server_shutdown_finishes_tags( - grpc_end2end_test_config config) { - grpc_end2end_test_fixture f = begin_test( - config, "test_early_server_shutdown_finishes_tags", NULL, NULL); - cq_verifier *cqv = cq_verifier_create(f.cq); - grpc_call *s = (grpc_call *)(uintptr_t)1; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - /* upon shutdown, the server should finish all requested calls indicating - no new call */ - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - grpc_server_shutdown_and_notify(f.server, f.cq, tag(1000)); - CQ_EXPECT_COMPLETION(cqv, tag(101), 0); - CQ_EXPECT_COMPLETION(cqv, tag(1000), 1); - cq_verify(cqv); - GPR_ASSERT(s == NULL); - - grpc_server_destroy(f.server); - - end_test(&f); - config.tear_down_data(&f); - cq_verifier_destroy(cqv); -} - -void shutdown_finishes_tags(grpc_end2end_test_config config) { - test_early_server_shutdown_finishes_tags(config); -} - -void shutdown_finishes_tags_pre_init(void) {} diff --git a/test/core/end2end/tests/shutdown_finishes_tags.cc b/test/core/end2end/tests/shutdown_finishes_tags.cc new file mode 100644 index 0000000000..7914cc95ba --- /dev/null +++ b/test/core/end2end/tests/shutdown_finishes_tags.cc @@ -0,0 +1,110 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +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_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + /* f->shutdown_cq is not used in this test */ + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void test_early_server_shutdown_finishes_tags( + grpc_end2end_test_config config) { + grpc_end2end_test_fixture f = begin_test( + config, "test_early_server_shutdown_finishes_tags", NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_call *s = (grpc_call *)(uintptr_t)1; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + /* upon shutdown, the server should finish all requested calls indicating + no new call */ + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + grpc_server_shutdown_and_notify(f.server, f.cq, tag(1000)); + CQ_EXPECT_COMPLETION(cqv, tag(101), 0); + CQ_EXPECT_COMPLETION(cqv, tag(1000), 1); + cq_verify(cqv); + GPR_ASSERT(s == NULL); + + grpc_server_destroy(f.server); + + end_test(&f); + config.tear_down_data(&f); + cq_verifier_destroy(cqv); +} + +void shutdown_finishes_tags(grpc_end2end_test_config config) { + test_early_server_shutdown_finishes_tags(config); +} + +void shutdown_finishes_tags_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_cacheable_request.c b/test/core/end2end/tests/simple_cacheable_request.c deleted file mode 100644 index faa5c193dc..0000000000 --- a/test/core/end2end/tests/simple_cacheable_request.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -enum { TIMEOUT = 200000 }; - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Request/response with metadata and payload.*/ -static void test_cacheable_request_response_with_metadata_and_payload( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), - grpc_slice_from_static_string("val3"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key4"), - grpc_slice_from_static_string("val4"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_end2end_test_fixture f = begin_test( - config, "test_cacheable_request_response_with_metadata_and_payload", NULL, - NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { - // Our simple proxy does not support cacheable requests - } else { - GPR_ASSERT(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST & call_details.flags); - } - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void simple_cacheable_request(grpc_end2end_test_config config) { - test_cacheable_request_response_with_metadata_and_payload(config); -} - -void simple_cacheable_request_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_cacheable_request.cc b/test/core/end2end/tests/simple_cacheable_request.cc new file mode 100644 index 0000000000..faa5c193dc --- /dev/null +++ b/test/core/end2end/tests/simple_cacheable_request.cc @@ -0,0 +1,280 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Request/response with metadata and payload.*/ +static void test_cacheable_request_response_with_metadata_and_payload( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), + grpc_slice_from_static_string("val1"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key2"), + grpc_slice_from_static_string("val2"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), + grpc_slice_from_static_string("val3"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key4"), + grpc_slice_from_static_string("val4"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_end2end_test_fixture f = begin_test( + config, "test_cacheable_request_response_with_metadata_and_payload", NULL, + NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_c; + op->flags = GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_s; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { + // Our simple proxy does not support cacheable requests + } else { + GPR_ASSERT(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST & call_details.flags); + } + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void simple_cacheable_request(grpc_end2end_test_config config) { + test_cacheable_request_response_with_metadata_and_payload(config); +} + +void simple_cacheable_request_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c deleted file mode 100644 index c3f66a07aa..0000000000 --- a/test/core/end2end/tests/simple_delayed_request.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t t) { return (void *)t; } - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_delayed_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture *f, - grpc_channel_args *client_args, - grpc_channel_args *server_args, - long delay_us) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - - config.init_client(f, client_args); - config.init_server(f, server_args); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - 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.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->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); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); -} - -static void test_simple_delayed_request_short(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - grpc_channel_args client_args; - grpc_arg arg_array[1]; - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = 1000; - client_args.args = arg_array; - client_args.num_args = 1; - - gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_short", - config.name); - f = config.create_fixture(NULL, NULL); - - simple_delayed_request_body(config, &f, &client_args, NULL, 100000); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_simple_delayed_request_long(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - grpc_channel_args client_args; - grpc_arg arg_array[1]; - arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; - arg_array[0].value.integer = 1000; - client_args.args = arg_array; - client_args.num_args = 1; - - gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_long", - config.name); - f = config.create_fixture(NULL, NULL); - /* This timeout should be longer than a single retry */ - simple_delayed_request_body(config, &f, &client_args, NULL, 1500000); - end_test(&f); - config.tear_down_data(&f); -} - -void simple_delayed_request(grpc_end2end_test_config config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_simple_delayed_request_short(config); - test_simple_delayed_request_long(config); -} - -void simple_delayed_request_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_delayed_request.cc b/test/core/end2end/tests/simple_delayed_request.cc new file mode 100644 index 0000000000..a4cbcbfedf --- /dev/null +++ b/test/core/end2end/tests/simple_delayed_request.cc @@ -0,0 +1,235 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_delayed_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture *f, + grpc_channel_args *client_args, + grpc_channel_args *server_args, + long delay_us) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + + config.init_client(f, client_args); + config.init_server(f, server_args); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + 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.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->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); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_simple_delayed_request_short(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + + gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_short", + config.name); + f = config.create_fixture(NULL, NULL); + + simple_delayed_request_body(config, &f, &client_args, NULL, 100000); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_simple_delayed_request_long(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = + const_cast("grpc.testing.fixed_reconnect_backoff_ms"); + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + + gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_long", + config.name); + f = config.create_fixture(NULL, NULL); + /* This timeout should be longer than a single retry */ + simple_delayed_request_body(config, &f, &client_args, NULL, 1500000); + end_test(&f); + config.tear_down_data(&f); +} + +void simple_delayed_request(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); + test_simple_delayed_request_short(config); + test_simple_delayed_request_long(config); +} + +void simple_delayed_request_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c deleted file mode 100644 index 17e7f696e2..0000000000 --- a/test/core/end2end/tests/simple_metadata.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Request/response with metadata and payload.*/ -static void test_request_response_with_metadata_and_payload( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), - grpc_slice_from_static_string("val3"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key4"), - grpc_slice_from_static_string("val4"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_end2end_test_fixture f = begin_test( - config, "test_request_response_with_metadata_and_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void simple_metadata(grpc_end2end_test_config config) { - test_request_response_with_metadata_and_payload(config); -} - -void simple_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_metadata.cc b/test/core/end2end/tests/simple_metadata.cc new file mode 100644 index 0000000000..17e7f696e2 --- /dev/null +++ b/test/core/end2end/tests/simple_metadata.cc @@ -0,0 +1,272 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Request/response with metadata and payload.*/ +static void test_request_response_with_metadata_and_payload( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), + grpc_slice_from_static_string("val1"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key2"), + grpc_slice_from_static_string("val2"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), + grpc_slice_from_static_string("val3"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key4"), + grpc_slice_from_static_string("val4"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_end2end_test_fixture f = begin_test( + config, "test_request_response_with_metadata_and_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_c; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_s; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void simple_metadata(grpc_end2end_test_config config) { + test_request_response_with_metadata_and_payload(config); +} + +void simple_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c deleted file mode 100644 index 7ce7e1f285..0000000000 --- a/test/core/end2end/tests/simple_request.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/debug/stats.h" -#include "src/core/lib/support/string.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void simple_request_body(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - char *peer; - grpc_stats_data *before = gpr_malloc(sizeof(grpc_stats_data)); - grpc_stats_data *after = gpr_malloc(sizeof(grpc_stats_data)); - - grpc_stats_collect(before); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - NULL); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - 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); - - memset(ops, 0, sizeof(ops)); - 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.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->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); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != NULL); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - 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 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(0 == call_details.flags); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_stats_collect(after); - - char *stats = grpc_stats_data_as_json(after); - gpr_log(GPR_DEBUG, "%s", stats); - gpr_free(stats); - - int expected_calls = 1; - if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { - expected_calls *= 2; - } - GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] - - before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] == - expected_calls); - GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_SERVER_CALLS_CREATED] - - before->counters[GRPC_STATS_COUNTER_SERVER_CALLS_CREATED] == - expected_calls); - gpr_free(before); - gpr_free(after); -} - -static void test_invoke_simple_request(grpc_end2end_test_config config) { - grpc_end2end_test_fixture f; - - f = begin_test(config, "test_invoke_simple_request", NULL, NULL); - simple_request_body(config, f); - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); - for (i = 0; i < 10; i++) { - simple_request_body(config, f); - gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); - } - end_test(&f); - config.tear_down_data(&f); -} - -void simple_request(grpc_end2end_test_config config) { - int i; - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - } - test_invoke_10_simple_requests(config); -} - -void simple_request_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc new file mode 100644 index 0000000000..48c9824894 --- /dev/null +++ b/test/core/end2end/tests/simple_request.cc @@ -0,0 +1,268 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/debug/stats.h" +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + char *peer; + grpc_stats_data *before = + static_cast(gpr_malloc(sizeof(grpc_stats_data))); + grpc_stats_data *after = + static_cast(gpr_malloc(sizeof(grpc_stats_data))); + + grpc_stats_collect(before); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + 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); + + memset(ops, 0, sizeof(ops)); + 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.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->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); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + 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 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_stats_collect(after); + + char *stats = grpc_stats_data_as_json(after); + gpr_log(GPR_DEBUG, "%s", stats); + gpr_free(stats); + + int expected_calls = 1; + if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { + expected_calls *= 2; + } + GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] - + before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] == + expected_calls); + GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_SERVER_CALLS_CREATED] - + before->counters[GRPC_STATS_COUNTER_SERVER_CALLS_CREATED] == + expected_calls); + gpr_free(before); + gpr_free(after); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_simple_request", NULL, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_10_simple_requests", NULL, NULL); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); + } + end_test(&f); + config.tear_down_data(&f); +} + +void simple_request(grpc_end2end_test_config config) { + int i; + for (i = 0; i < 10; i++) { + test_invoke_simple_request(config); + } + test_invoke_10_simple_requests(config); +} + +void simple_request_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_compressed_payload.c b/test/core/end2end/tests/stream_compression_compressed_payload.c deleted file mode 100644 index 8b47741cd4..0000000000 --- a/test/core/end2end/tests/stream_compression_compressed_payload.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/call_test_only.h" -#include "src/core/lib/transport/static_metadata.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void request_for_disabled_algorithm( - grpc_end2end_test_config config, const char *test_name, - uint32_t send_flags_bitmask, - grpc_stream_compression_algorithm algorithm_to_disable, - grpc_stream_compression_algorithm requested_client_compression_algorithm, - grpc_status_code expected_error, grpc_metadata *client_metadata) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice; - grpc_byte_buffer *request_payload; - grpc_channel_args *client_args; - grpc_channel_args *server_args; - grpc_end2end_test_fixture f; - 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_byte_buffer *request_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - cq_verifier *cqv; - char str[1024]; - - memset(str, 'x', 1023); - str[1023] = '\0'; - request_payload_slice = grpc_slice_from_copied_string(str); - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - client_args = grpc_channel_args_set_stream_compression_algorithm( - NULL, requested_client_compression_algorithm); - server_args = grpc_channel_args_set_stream_compression_algorithm( - NULL, GRPC_STREAM_COMPRESS_NONE); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - server_args = grpc_channel_args_stream_compression_algorithm_set_state( - &exec_ctx, &server_args, algorithm_to_disable, false); - grpc_exec_ctx_finish(&exec_ctx); - } - - f = begin_test(config, test_name, client_args, server_args); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_metadata != NULL) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_metadata; - } else { - op->data.send_initial_metadata.count = 0; - } - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = send_flags_bitmask; - 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.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->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); - - CQ_EXPECT_COMPLETION(cqv, tag(101), true); - CQ_EXPECT_COMPLETION(cqv, tag(1), true); - 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_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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), false); - - op = ops; - 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(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), true); - cq_verify(cqv); - - /* call was cancelled (closed) ... */ - GPR_ASSERT(was_cancelled != 0); - /* with a certain error */ - GPR_ASSERT(status == expected_error); - - const char *algo_name = NULL; - GPR_ASSERT( - grpc_stream_compression_algorithm_name(algorithm_to_disable, &algo_name)); - char *expected_details = NULL; - gpr_asprintf(&expected_details, - "Stream compression algorithm '%s' is disabled.", algo_name); - /* and we expect a specific reason for it */ - GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details)); - gpr_free(expected_details); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_slice_unref(request_payload_slice); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - end_test(&f); - config.tear_down_data(&f); -} - -static void request_with_payload_template( - grpc_end2end_test_config config, const char *test_name, - uint32_t client_send_flags_bitmask, - grpc_stream_compression_algorithm - default_client_channel_compression_algorithm, - grpc_stream_compression_algorithm - default_server_channel_compression_algorithm, - grpc_stream_compression_algorithm expected_client_compression_algorithm, - grpc_stream_compression_algorithm expected_server_compression_algorithm, - grpc_metadata *client_init_metadata, bool set_server_level, - grpc_stream_compression_level server_compression_level, - bool send_message_before_initial_metadata, - bool set_default_server_message_compression_algorithm, - grpc_compression_algorithm default_server_message_compression_algorithm) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice; - grpc_byte_buffer *request_payload = NULL; - grpc_channel_args *client_args; - grpc_channel_args *server_args; - grpc_end2end_test_fixture f; - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload; - grpc_byte_buffer *response_payload_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - cq_verifier *cqv; - char request_str[1024]; - char response_str[1024]; - - memset(request_str, 'x', 1023); - request_str[1023] = '\0'; - - memset(response_str, 'y', 1023); - response_str[1023] = '\0'; - - request_payload_slice = grpc_slice_from_copied_string(request_str); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string(response_str); - - client_args = grpc_channel_args_set_stream_compression_algorithm( - NULL, default_client_channel_compression_algorithm); - if (set_default_server_message_compression_algorithm) { - server_args = grpc_channel_args_set_compression_algorithm( - NULL, default_server_message_compression_algorithm); - } else { - server_args = grpc_channel_args_set_stream_compression_algorithm( - NULL, default_server_channel_compression_algorithm); - } - - f = begin_test(config, test_name, client_args, server_args); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - if (send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), true); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_init_metadata != NULL) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_init_metadata; - } else { - op->data.send_initial_metadata.count = 0; - } - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(100), true); - cq_verify(cqv); - - GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( - s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_NONE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_DEFLATE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_GZIP) != 0); - GPR_ASSERT( - GPR_BITCOUNT(grpc_call_test_only_get_stream_encodings_accepted_by_peer( - s)) == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT( - GPR_BITGET(grpc_call_test_only_get_stream_encodings_accepted_by_peer(s), - GRPC_STREAM_COMPRESS_NONE) != 0); - GPR_ASSERT( - GPR_BITGET(grpc_call_test_only_get_stream_encodings_accepted_by_peer(s), - GRPC_STREAM_COMPRESS_GZIP) != 0); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - if (set_server_level) { - op->data.send_initial_metadata.maybe_stream_compression_level.is_set = true; - op->data.send_initial_metadata.maybe_stream_compression_level.level = - server_compression_level; - } - 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(101), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (int i = 0; i < 2; i++) { - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - if (i > 0 || !send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - cq_verify(cqv); - - GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(4), 1); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - end_test(&f); - config.tear_down_data(&f); -} - -static void test_invoke_request_with_compressed_payload( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, NULL, - false, /* ignored */ - GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, GRPC_COMPRESS_NONE); -} - -static void test_invoke_request_with_send_message_before_initial_metadata( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_send_message_before_initial_metadata", - 0, GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, NULL, - false, /* ignored */ - GRPC_STREAM_COMPRESS_LEVEL_NONE, true, false, GRPC_COMPRESS_NONE); -} - -static void test_invoke_request_with_server_level( - grpc_end2end_test_config config) { - request_with_payload_template( - config, "test_invoke_request_with_server_level", 0, - GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, - GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_GZIP, - /* ignored */ NULL, true, GRPC_STREAM_COMPRESS_LEVEL_HIGH, false, false, - GRPC_COMPRESS_NONE); -} - -static void test_invoke_request_with_compressed_payload_md_override( - grpc_end2end_test_config config) { - grpc_metadata gzip_compression_override; - grpc_metadata identity_compression_override; - - gzip_compression_override.key = - GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST; - gzip_compression_override.value = grpc_slice_from_static_string("gzip"); - memset(&gzip_compression_override.internal_data, 0, - sizeof(gzip_compression_override.internal_data)); - - identity_compression_override.key = - GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST; - identity_compression_override.value = - grpc_slice_from_static_string("identity"); - memset(&identity_compression_override.internal_data, 0, - sizeof(identity_compression_override.internal_data)); - - /* Channel default NONE (aka IDENTITY), call override to stream GZIP */ - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_1", 0, - GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_NONE, - &gzip_compression_override, false, - /*ignored*/ GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, - GRPC_COMPRESS_NONE); - - /* Channel default stream GZIP, call override to NONE (aka IDENTITY) */ - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_3", 0, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_NONE, - GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, - &identity_compression_override, false, - /*ignored*/ GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, - GRPC_COMPRESS_NONE); -} - -static void test_invoke_request_with_disabled_algorithm( - grpc_end2end_test_config config) { - request_for_disabled_algorithm( - config, "test_invoke_request_with_disabled_algorithm", 0, - GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, - GRPC_STATUS_UNIMPLEMENTED, NULL); -} - -static void test_stream_compression_override_message_compression( - grpc_end2end_test_config config) { - grpc_stream_compression_level level = GRPC_STREAM_COMPRESS_LEVEL_MED; - request_with_payload_template( - config, "test_stream_compression_override_message_compression", 0, - GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, - GRPC_STREAM_COMPRESS_NONE, - grpc_stream_compression_algorithm_for_level( - level, (1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1), - /* ignored */ NULL, true, level, false, true, GRPC_COMPRESS_GZIP); -} - -void stream_compression_compressed_payload(grpc_end2end_test_config config) { - test_invoke_request_with_compressed_payload(config); - test_invoke_request_with_send_message_before_initial_metadata(config); - test_invoke_request_with_server_level(config); - test_invoke_request_with_compressed_payload_md_override(config); - test_invoke_request_with_disabled_algorithm(config); - test_stream_compression_override_message_compression(config); -} - -void stream_compression_compressed_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_compressed_payload.cc b/test/core/end2end/tests/stream_compression_compressed_payload.cc new file mode 100644 index 0000000000..8b47741cd4 --- /dev/null +++ b/test/core/end2end/tests/stream_compression_compressed_payload.cc @@ -0,0 +1,653 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/call_test_only.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void request_for_disabled_algorithm( + grpc_end2end_test_config config, const char *test_name, + uint32_t send_flags_bitmask, + grpc_stream_compression_algorithm algorithm_to_disable, + grpc_stream_compression_algorithm requested_client_compression_algorithm, + grpc_status_code expected_error, grpc_metadata *client_metadata) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + 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_byte_buffer *request_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char str[1024]; + + memset(str, 'x', 1023); + str[1023] = '\0'; + request_payload_slice = grpc_slice_from_copied_string(str); + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + + client_args = grpc_channel_args_set_stream_compression_algorithm( + NULL, requested_client_compression_algorithm); + server_args = grpc_channel_args_set_stream_compression_algorithm( + NULL, GRPC_STREAM_COMPRESS_NONE); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + server_args = grpc_channel_args_stream_compression_algorithm_set_state( + &exec_ctx, &server_args, algorithm_to_disable, false); + grpc_exec_ctx_finish(&exec_ctx); + } + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = send_flags_bitmask; + 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.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->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); + + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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), false); + + op = ops; + 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(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + cq_verify(cqv); + + /* call was cancelled (closed) ... */ + GPR_ASSERT(was_cancelled != 0); + /* with a certain error */ + GPR_ASSERT(status == expected_error); + + const char *algo_name = NULL; + GPR_ASSERT( + grpc_stream_compression_algorithm_name(algorithm_to_disable, &algo_name)); + char *expected_details = NULL; + gpr_asprintf(&expected_details, + "Stream compression algorithm '%s' is disabled.", algo_name); + /* and we expect a specific reason for it */ + GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details)); + gpr_free(expected_details); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_slice_unref(request_payload_slice); + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +static void request_with_payload_template( + grpc_end2end_test_config config, const char *test_name, + uint32_t client_send_flags_bitmask, + grpc_stream_compression_algorithm + default_client_channel_compression_algorithm, + grpc_stream_compression_algorithm + default_server_channel_compression_algorithm, + grpc_stream_compression_algorithm expected_client_compression_algorithm, + grpc_stream_compression_algorithm expected_server_compression_algorithm, + grpc_metadata *client_init_metadata, bool set_server_level, + grpc_stream_compression_level server_compression_level, + bool send_message_before_initial_metadata, + bool set_default_server_message_compression_algorithm, + grpc_compression_algorithm default_server_message_compression_algorithm) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload = NULL; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char request_str[1024]; + char response_str[1024]; + + memset(request_str, 'x', 1023); + request_str[1023] = '\0'; + + memset(response_str, 'y', 1023); + response_str[1023] = '\0'; + + request_payload_slice = grpc_slice_from_copied_string(request_str); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string(response_str); + + client_args = grpc_channel_args_set_stream_compression_algorithm( + NULL, default_client_channel_compression_algorithm); + if (set_default_server_message_compression_algorithm) { + server_args = grpc_channel_args_set_compression_algorithm( + NULL, default_server_message_compression_algorithm); + } else { + server_args = grpc_channel_args_set_stream_compression_algorithm( + NULL, default_server_channel_compression_algorithm); + } + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + if (send_message_before_initial_metadata) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_init_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_init_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), true); + cq_verify(cqv); + + GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( + s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_NONE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_DEFLATE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_GZIP) != 0); + GPR_ASSERT( + GPR_BITCOUNT(grpc_call_test_only_get_stream_encodings_accepted_by_peer( + s)) == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT( + GPR_BITGET(grpc_call_test_only_get_stream_encodings_accepted_by_peer(s), + GRPC_STREAM_COMPRESS_NONE) != 0); + GPR_ASSERT( + GPR_BITGET(grpc_call_test_only_get_stream_encodings_accepted_by_peer(s), + GRPC_STREAM_COMPRESS_GZIP) != 0); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + if (set_server_level) { + op->data.send_initial_metadata.maybe_stream_compression_level.is_set = true; + op->data.send_initial_metadata.maybe_stream_compression_level.level = + server_compression_level; + } + 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(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (int i = 0; i < 2; i++) { + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + if (i > 0 || !send_message_before_initial_metadata) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + + GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +static void test_invoke_request_with_compressed_payload( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload", 0, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, NULL, + false, /* ignored */ + GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, GRPC_COMPRESS_NONE); +} + +static void test_invoke_request_with_send_message_before_initial_metadata( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_send_message_before_initial_metadata", + 0, GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, NULL, + false, /* ignored */ + GRPC_STREAM_COMPRESS_LEVEL_NONE, true, false, GRPC_COMPRESS_NONE); +} + +static void test_invoke_request_with_server_level( + grpc_end2end_test_config config) { + request_with_payload_template( + config, "test_invoke_request_with_server_level", 0, + GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, + GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_GZIP, + /* ignored */ NULL, true, GRPC_STREAM_COMPRESS_LEVEL_HIGH, false, false, + GRPC_COMPRESS_NONE); +} + +static void test_invoke_request_with_compressed_payload_md_override( + grpc_end2end_test_config config) { + grpc_metadata gzip_compression_override; + grpc_metadata identity_compression_override; + + gzip_compression_override.key = + GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST; + gzip_compression_override.value = grpc_slice_from_static_string("gzip"); + memset(&gzip_compression_override.internal_data, 0, + sizeof(gzip_compression_override.internal_data)); + + identity_compression_override.key = + GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST; + identity_compression_override.value = + grpc_slice_from_static_string("identity"); + memset(&identity_compression_override.internal_data, 0, + sizeof(identity_compression_override.internal_data)); + + /* Channel default NONE (aka IDENTITY), call override to stream GZIP */ + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload_md_override_1", 0, + GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_NONE, + &gzip_compression_override, false, + /*ignored*/ GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, + GRPC_COMPRESS_NONE); + + /* Channel default stream GZIP, call override to NONE (aka IDENTITY) */ + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload_md_override_3", 0, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_NONE, + GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, + &identity_compression_override, false, + /*ignored*/ GRPC_STREAM_COMPRESS_LEVEL_NONE, false, false, + GRPC_COMPRESS_NONE); +} + +static void test_invoke_request_with_disabled_algorithm( + grpc_end2end_test_config config) { + request_for_disabled_algorithm( + config, "test_invoke_request_with_disabled_algorithm", 0, + GRPC_STREAM_COMPRESS_GZIP, GRPC_STREAM_COMPRESS_GZIP, + GRPC_STATUS_UNIMPLEMENTED, NULL); +} + +static void test_stream_compression_override_message_compression( + grpc_end2end_test_config config) { + grpc_stream_compression_level level = GRPC_STREAM_COMPRESS_LEVEL_MED; + request_with_payload_template( + config, "test_stream_compression_override_message_compression", 0, + GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE, + GRPC_STREAM_COMPRESS_NONE, + grpc_stream_compression_algorithm_for_level( + level, (1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1), + /* ignored */ NULL, true, level, false, true, GRPC_COMPRESS_GZIP); +} + +void stream_compression_compressed_payload(grpc_end2end_test_config config) { + test_invoke_request_with_compressed_payload(config); + test_invoke_request_with_send_message_before_initial_metadata(config); + test_invoke_request_with_server_level(config); + test_invoke_request_with_compressed_payload_md_override(config); + test_invoke_request_with_disabled_algorithm(config); + test_stream_compression_override_message_compression(config); +} + +void stream_compression_compressed_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_payload.c b/test/core/end2end/tests/stream_compression_payload.c deleted file mode 100644 index e47d2aa93c..0000000000 --- a/test/core/end2end/tests/stream_compression_payload.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/call.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Creates and returns a grpc_slice containing random alphanumeric characters. - */ -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char *output; - const size_t output_size = 1024 * 1024; - output = (char *)gpr_malloc(output_size); - for (i = 0; i < output_size - 1; ++i) { - output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; - } - output[output_size - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; -} - -static void request_response_with_payload(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - /* Create large request and response bodies. These are big enough to require - * multiple round trips to deliver to the peer, and their exact contents of - * will be verified on completion. */ - grpc_slice request_payload_slice = generate_random_slice(); - grpc_slice response_payload_slice = generate_random_slice(); - - grpc_call *c; - grpc_call *s; - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = n_seconds_from_now(60); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - 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_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -/* Client sends a request with payload, server reads then returns a response - payload and status. */ -static void test_invoke_request_response_with_payload( - grpc_end2end_test_config config) { - grpc_channel_args *client_args = - grpc_channel_args_set_stream_compression_algorithm( - NULL, GRPC_STREAM_COMPRESS_GZIP); - grpc_channel_args *server_args = - grpc_channel_args_set_stream_compression_algorithm( - NULL, GRPC_STREAM_COMPRESS_GZIP); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_response_with_payload", - client_args, server_args); - request_response_with_payload(config, f); - end_test(&f); - config.tear_down_data(&f); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_invoke_10_request_response_with_payload( - grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = begin_test( - config, "test_invoke_10_request_response_with_payload", NULL, NULL); - for (i = 0; i < 10; i++) { - request_response_with_payload(config, f); - } - end_test(&f); - config.tear_down_data(&f); -} - -void stream_compression_payload(grpc_end2end_test_config config) { - test_invoke_request_response_with_payload(config); - test_invoke_10_request_response_with_payload(config); -} - -void stream_compression_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_payload.cc b/test/core/end2end/tests/stream_compression_payload.cc new file mode 100644 index 0000000000..e47d2aa93c --- /dev/null +++ b/test/core/end2end/tests/stream_compression_payload.cc @@ -0,0 +1,305 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Creates and returns a grpc_slice containing random alphanumeric characters. + */ +static grpc_slice generate_random_slice() { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + char *output; + const size_t output_size = 1024 * 1024; + output = (char *)gpr_malloc(output_size); + for (i = 0; i < output_size - 1; ++i) { + output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + output[output_size - 1] = '\0'; + grpc_slice out = grpc_slice_from_copied_string(output); + gpr_free(output); + return out; +} + +static void request_response_with_payload(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + /* Create large request and response bodies. These are big enough to require + * multiple round trips to deliver to the peer, and their exact contents of + * will be verified on completion. */ + grpc_slice request_payload_slice = generate_random_slice(); + grpc_slice response_payload_slice = generate_random_slice(); + + grpc_call *c; + grpc_call *s; + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = n_seconds_from_now(60); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); + GPR_ASSERT( + byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); +} + +/* Client sends a request with payload, server reads then returns a response + payload and status. */ +static void test_invoke_request_response_with_payload( + grpc_end2end_test_config config) { + grpc_channel_args *client_args = + grpc_channel_args_set_stream_compression_algorithm( + NULL, GRPC_STREAM_COMPRESS_GZIP); + grpc_channel_args *server_args = + grpc_channel_args_set_stream_compression_algorithm( + NULL, GRPC_STREAM_COMPRESS_GZIP); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_response_with_payload", + client_args, server_args); + request_response_with_payload(config, f); + end_test(&f); + config.tear_down_data(&f); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_invoke_10_request_response_with_payload( + grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = begin_test( + config, "test_invoke_10_request_response_with_payload", NULL, NULL); + for (i = 0; i < 10; i++) { + request_response_with_payload(config, f); + } + end_test(&f); + config.tear_down_data(&f); +} + +void stream_compression_payload(grpc_end2end_test_config config) { + test_invoke_request_response_with_payload(config); + test_invoke_10_request_response_with_payload(config); +} + +void stream_compression_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_ping_pong_streaming.c b/test/core/end2end/tests/stream_compression_ping_pong_streaming.c deleted file mode 100644 index 4c1a34cc64..0000000000 --- a/test/core/end2end/tests/stream_compression_ping_pong_streaming.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/call.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client pings and server pongs. Repeat messages rounds before finishing. */ -static void test_pingpong_streaming(grpc_end2end_test_config config, - int messages) { - grpc_channel_args *client_args = - grpc_channel_args_set_stream_compression_algorithm( - NULL, GRPC_STREAM_COMPRESS_GZIP); - grpc_channel_args *server_args = - grpc_channel_args_set_stream_compression_algorithm( - NULL, GRPC_STREAM_COMPRESS_GZIP); - grpc_end2end_test_fixture f = - begin_test(config, "test_pingpong_streaming", client_args, server_args); - grpc_call *c; - grpc_call *s; - 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_slice details; - int was_cancelled = 2; - grpc_byte_buffer *request_payload; - grpc_byte_buffer *request_payload_recv; - grpc_byte_buffer *response_payload; - grpc_byte_buffer *response_payload_recv; - int i; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - 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_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(100), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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_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(101), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (i = 0; i < messages; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = 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; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - cq_verify(cqv); - - grpc_call_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - 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_slice_unref(details); - - end_test(&f); - config.tear_down_data(&f); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -void stream_compression_ping_pong_streaming(grpc_end2end_test_config config) { - int i; - - for (i = 1; i < 10; i++) { - test_pingpong_streaming(config, i); - } -} - -void stream_compression_ping_pong_streaming_pre_init(void) {} diff --git a/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc new file mode 100644 index 0000000000..4c1a34cc64 --- /dev/null +++ b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc @@ -0,0 +1,291 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client pings and server pongs. Repeat messages rounds before finishing. */ +static void test_pingpong_streaming(grpc_end2end_test_config config, + int messages) { + grpc_channel_args *client_args = + grpc_channel_args_set_stream_compression_algorithm( + NULL, GRPC_STREAM_COMPRESS_GZIP); + grpc_channel_args *server_args = + grpc_channel_args_set_stream_compression_algorithm( + NULL, GRPC_STREAM_COMPRESS_GZIP); + grpc_end2end_test_fixture f = + begin_test(config, "test_pingpong_streaming", client_args, server_args); + grpc_call *c; + grpc_call *s; + 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_slice details; + int was_cancelled = 2; + grpc_byte_buffer *request_payload; + grpc_byte_buffer *request_payload_recv; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + int i; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + 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_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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_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(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (i = 0; i < messages; i++) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = 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; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + 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_slice_unref(details); + + end_test(&f); + config.tear_down_data(&f); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +void stream_compression_ping_pong_streaming(grpc_end2end_test_config config) { + int i; + + for (i = 1; i < 10; i++) { + test_pingpong_streaming(config, i); + } +} + +void stream_compression_ping_pong_streaming_pre_init(void) {} diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c deleted file mode 100644 index 8891b8674c..0000000000 --- a/test/core/end2end/tests/streaming_error_response.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** \file Verify that status ordering rules are obeyed. - \ref doc/status_ordering.md */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, - bool request_status_early) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s/request_status_early=%s", test_name, - config.name, request_status_early ? "true" : "false"); - 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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test(grpc_end2end_test_config config, bool request_status_early) { - grpc_call *c; - grpc_call *s; - grpc_slice response_payload1_slice = grpc_slice_from_copied_string("hello"); - grpc_byte_buffer *response_payload1 = - grpc_raw_byte_buffer_create(&response_payload1_slice, 1); - grpc_slice response_payload2_slice = grpc_slice_from_copied_string("world"); - grpc_byte_buffer *response_payload2 = - grpc_raw_byte_buffer_create(&response_payload2_slice, 1); - grpc_end2end_test_fixture f = begin_test(config, "streaming_error_response", - NULL, NULL, request_status_early); - 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_byte_buffer *response_payload1_recv = NULL; - grpc_byte_buffer *response_payload2_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload1_recv; - op++; - if (request_status_early) { - 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++; - } - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload1; - 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); - if (!request_status_early) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - } - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload2; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - - if (!request_status_early) { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload2_recv; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_FAILED_PRECONDITION; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - if (request_status_early) { - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - } - cq_verify(cqv); - - if (!request_status_early) { - memset(ops, 0, sizeof(ops)); - 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++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - cq_verify(cqv); - - GPR_ASSERT(response_payload1_recv != NULL); - GPR_ASSERT(response_payload2_recv != NULL); - } - - GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(response_payload1); - grpc_byte_buffer_destroy(response_payload2); - grpc_byte_buffer_destroy(response_payload1_recv); - grpc_byte_buffer_destroy(response_payload2_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void streaming_error_response(grpc_end2end_test_config config) { - test(config, false); - test(config, true); -} - -void streaming_error_response_pre_init(void) {} diff --git a/test/core/end2end/tests/streaming_error_response.cc b/test/core/end2end/tests/streaming_error_response.cc new file mode 100644 index 0000000000..8891b8674c --- /dev/null +++ b/test/core/end2end/tests/streaming_error_response.cc @@ -0,0 +1,270 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** \file Verify that status ordering rules are obeyed. + \ref doc/status_ordering.md */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, + bool request_status_early) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s/request_status_early=%s", test_name, + config.name, request_status_early ? "true" : "false"); + 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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test(grpc_end2end_test_config config, bool request_status_early) { + grpc_call *c; + grpc_call *s; + grpc_slice response_payload1_slice = grpc_slice_from_copied_string("hello"); + grpc_byte_buffer *response_payload1 = + grpc_raw_byte_buffer_create(&response_payload1_slice, 1); + grpc_slice response_payload2_slice = grpc_slice_from_copied_string("world"); + grpc_byte_buffer *response_payload2 = + grpc_raw_byte_buffer_create(&response_payload2_slice, 1); + grpc_end2end_test_fixture f = begin_test(config, "streaming_error_response", + NULL, NULL, request_status_early); + 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_byte_buffer *response_payload1_recv = NULL; + grpc_byte_buffer *response_payload2_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload1_recv; + op++; + if (request_status_early) { + 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++; + } + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload1; + 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); + if (!request_status_early) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + } + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + + if (!request_status_early) { + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload2_recv; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + } + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_FAILED_PRECONDITION; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + if (request_status_early) { + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + } + cq_verify(cqv); + + if (!request_status_early) { + memset(ops, 0, sizeof(ops)); + 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++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + cq_verify(cqv); + + GPR_ASSERT(response_payload1_recv != NULL); + GPR_ASSERT(response_payload2_recv != NULL); + } + + GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(response_payload1); + grpc_byte_buffer_destroy(response_payload2); + grpc_byte_buffer_destroy(response_payload1_recv); + grpc_byte_buffer_destroy(response_payload2_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void streaming_error_response(grpc_end2end_test_config config) { + test(config, false); + test(config, true); +} + +void streaming_error_response_pre_init(void) {} diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c deleted file mode 100644 index 7aa78a04b8..0000000000 --- a/test/core/end2end/tests/trailing_metadata.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Request/response with metadata and payload.*/ -static void test_request_response_with_metadata_and_payload( - grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), - grpc_slice_from_static_string("val3"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key4"), - grpc_slice_from_static_string("val4"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"), - grpc_slice_from_static_string("val5"), - 0, - {{NULL, NULL, NULL, NULL}}}, - {grpc_slice_from_static_string("key6"), - grpc_slice_from_static_string("val6"), - 0, - {{NULL, NULL, NULL, NULL}}}}; - grpc_end2end_test_fixture f = begin_test( - config, "test_request_response_with_metadata_and_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload_recv = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - 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.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_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->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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 2; - op->data.send_status_from_server.trailing_metadata = meta_t; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); - GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5")); - GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void trailing_metadata(grpc_end2end_test_config config) { - test_request_response_with_metadata_and_payload(config); -} - -void trailing_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/trailing_metadata.cc b/test/core/end2end/tests/trailing_metadata.cc new file mode 100644 index 0000000000..7aa78a04b8 --- /dev/null +++ b/test/core/end2end/tests/trailing_metadata.cc @@ -0,0 +1,282 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Request/response with metadata and payload.*/ +static void test_request_response_with_metadata_and_payload( + grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), + grpc_slice_from_static_string("val1"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key2"), + grpc_slice_from_static_string("val2"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), + grpc_slice_from_static_string("val3"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key4"), + grpc_slice_from_static_string("val4"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"), + grpc_slice_from_static_string("val5"), + 0, + {{NULL, NULL, NULL, NULL}}}, + {grpc_slice_from_static_string("key6"), + grpc_slice_from_static_string("val6"), + 0, + {{NULL, NULL, NULL, NULL}}}}; + grpc_end2end_test_fixture f = begin_test( + config, "test_request_response_with_metadata_and_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload_recv = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_c; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + 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.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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->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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 2; + op->data.send_initial_metadata.metadata = meta_s; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 2; + op->data.send_status_from_server.trailing_metadata = meta_t; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); + GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); + GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); + GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5")); + GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(&f); + config.tear_down_data(&f); +} + +void trailing_metadata(grpc_end2end_test_config config) { + test_request_response_with_metadata_and_payload(config); +} + +void trailing_metadata_pre_init(void) {} diff --git a/test/core/end2end/tests/workaround_cronet_compression.c b/test/core/end2end/tests/workaround_cronet_compression.c deleted file mode 100644 index 44e8e04643..0000000000 --- a/test/core/end2end/tests/workaround_cronet_compression.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/call_test_only.h" -#include "src/core/lib/transport/static_metadata.h" -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -static void request_with_payload_template( - grpc_end2end_test_config config, const char *test_name, - uint32_t client_send_flags_bitmask, - grpc_compression_algorithm default_client_channel_compression_algorithm, - grpc_compression_algorithm default_server_channel_compression_algorithm, - grpc_compression_algorithm expected_algorithm_from_client, - grpc_compression_algorithm expected_algorithm_from_server, - grpc_metadata *client_init_metadata, bool set_server_level, - grpc_compression_level server_compression_level, - char *user_agent_override) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice; - grpc_byte_buffer *request_payload; - grpc_channel_args *client_args; - grpc_channel_args *server_args; - grpc_end2end_test_fixture f; - 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_byte_buffer *request_payload_recv = NULL; - grpc_byte_buffer *response_payload; - grpc_byte_buffer *response_payload_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - cq_verifier *cqv; - char request_str[1024]; - char response_str[1024]; - - memset(request_str, 'x', 1023); - request_str[1023] = '\0'; - - memset(response_str, 'y', 1023); - response_str[1023] = '\0'; - - request_payload_slice = grpc_slice_from_copied_string(request_str); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string(response_str); - - client_args = grpc_channel_args_set_compression_algorithm( - NULL, default_client_channel_compression_algorithm); - server_args = grpc_channel_args_set_compression_algorithm( - NULL, default_server_channel_compression_algorithm); - - if (user_agent_override) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *client_args_old = client_args; - grpc_arg arg; - arg.key = GRPC_ARG_PRIMARY_USER_AGENT_STRING; - arg.type = GRPC_ARG_STRING; - arg.value.string = user_agent_override; - client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); - grpc_channel_args_destroy(&exec_ctx, client_args_old); - grpc_exec_ctx_finish(&exec_ctx); - } - - f = begin_test(config, test_name, client_args, server_args); - cqv = cq_verifier_create(f.cq); - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_init_metadata != NULL) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_init_metadata; - } else { - op->data.send_initial_metadata.count = 0; - } - op->flags = 0; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.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->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(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(100), true); - cq_verify(cqv); - - GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( - s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_NONE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_DEFLATE) != 0); - GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_GZIP) != 0); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - if (set_server_level) { - op->data.send_initial_metadata.maybe_compression_level.is_set = true; - op->data.send_initial_metadata.maybe_compression_level.level = - server_compression_level; - } - 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(101), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (int i = 0; i < 2; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = NULL; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - 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_verify(cqv); - - GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); - GPR_ASSERT(request_payload_recv->data.raw.compression == - expected_algorithm_from_client); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(2), 1); - cq_verify(cqv); - - GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); - if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { - const grpc_compression_algorithm algo_for_server_level = - grpc_call_compression_for_level(s, server_compression_level); - GPR_ASSERT(response_payload_recv->data.raw.compression == - algo_for_server_level); - } else { - GPR_ASSERT(response_payload_recv->data.raw.compression == - expected_algorithm_from_server); - } - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - CQ_EXPECT_COMPLETION(cqv, tag(3), 1); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - CQ_EXPECT_COMPLETION(cqv, tag(104), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, client_args); - grpc_channel_args_destroy(&exec_ctx, server_args); - grpc_exec_ctx_finish(&exec_ctx); - } - - end_test(&f); - config.tear_down_data(&f); -} - -typedef struct workaround_cronet_compression_config { - char *user_agent_override; - grpc_compression_algorithm expected_algorithm_from_server; -} workaround_cronet_compression_config; - -static workaround_cronet_compression_config workaround_configs[] = { - {NULL, GRPC_COMPRESS_GZIP}, - {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; cronet_http; gentle)", - GRPC_COMPRESS_NONE}, - {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; chttp2; gentle)", - GRPC_COMPRESS_GZIP}, - {"grpc-objc/1.4.0 grpc-c/3.0.0-dev (ios; cronet_http; gentle)", - GRPC_COMPRESS_GZIP}}; -static const size_t workaround_configs_num = - sizeof(workaround_configs) / sizeof(*workaround_configs); - -static void test_workaround_cronet_compression( - grpc_end2end_test_config config) { - for (uint32_t i = 0; i < workaround_configs_num; i++) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - workaround_configs[i].expected_algorithm_from_server, NULL, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - workaround_configs[i].user_agent_override); - } -} - -void workaround_cronet_compression(grpc_end2end_test_config config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_WORKAROUNDS) { - test_workaround_cronet_compression(config); - } -} - -void workaround_cronet_compression_pre_init(void) {} diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc new file mode 100644 index 0000000000..17e59ad6d4 --- /dev/null +++ b/test/core/end2end/tests/workaround_cronet_compression.cc @@ -0,0 +1,399 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/call_test_only.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void request_with_payload_template( + grpc_end2end_test_config config, const char *test_name, + uint32_t client_send_flags_bitmask, + grpc_compression_algorithm default_client_channel_compression_algorithm, + grpc_compression_algorithm default_server_channel_compression_algorithm, + grpc_compression_algorithm expected_algorithm_from_client, + grpc_compression_algorithm expected_algorithm_from_server, + grpc_metadata *client_init_metadata, bool set_server_level, + grpc_compression_level server_compression_level, + char *user_agent_override) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + 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_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char request_str[1024]; + char response_str[1024]; + + memset(request_str, 'x', 1023); + request_str[1023] = '\0'; + + memset(response_str, 'y', 1023); + response_str[1023] = '\0'; + + request_payload_slice = grpc_slice_from_copied_string(request_str); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string(response_str); + + client_args = grpc_channel_args_set_compression_algorithm( + NULL, default_client_channel_compression_algorithm); + server_args = grpc_channel_args_set_compression_algorithm( + NULL, default_server_channel_compression_algorithm); + + if (user_agent_override) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *client_args_old = client_args; + grpc_arg arg; + arg.key = const_cast(GRPC_ARG_PRIMARY_USER_AGENT_STRING); + arg.type = GRPC_ARG_STRING; + arg.value.string = user_agent_override; + client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); + grpc_channel_args_destroy(&exec_ctx, client_args_old); + grpc_exec_ctx_finish(&exec_ctx); + } + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_init_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_init_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.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->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(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), true); + cq_verify(cqv); + + GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( + s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_NONE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_DEFLATE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_GZIP) != 0); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + if (set_server_level) { + op->data.send_initial_metadata.maybe_compression_level.is_set = true; + op->data.send_initial_metadata.maybe_compression_level.level = + server_compression_level; + } + 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(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (int i = 0; i < 2; i++) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + 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_verify(cqv); + + GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); + GPR_ASSERT(request_payload_recv->data.raw.compression == + expected_algorithm_from_client); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); + if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { + const grpc_compression_algorithm algo_for_server_level = + grpc_call_compression_for_level(s, server_compression_level); + GPR_ASSERT(response_payload_recv->data.raw.compression == + algo_for_server_level); + } else { + GPR_ASSERT(response_payload_recv->data.raw.compression == + expected_algorithm_from_server); + } + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +typedef struct workaround_cronet_compression_config { + char *user_agent_override; + grpc_compression_algorithm expected_algorithm_from_server; +} workaround_cronet_compression_config; + +static workaround_cronet_compression_config workaround_configs[] = { + {NULL, GRPC_COMPRESS_GZIP}, + {const_cast( + "grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; cronet_http; gentle)"), + GRPC_COMPRESS_NONE}, + {const_cast( + "grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; chttp2; gentle)"), + GRPC_COMPRESS_GZIP}, + {const_cast( + "grpc-objc/1.4.0 grpc-c/3.0.0-dev (ios; cronet_http; gentle)"), + GRPC_COMPRESS_GZIP}}; +static const size_t workaround_configs_num = + sizeof(workaround_configs) / sizeof(*workaround_configs); + +static void test_workaround_cronet_compression( + grpc_end2end_test_config config) { + for (uint32_t i = 0; i < workaround_configs_num; i++) { + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload", 0, + GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, + workaround_configs[i].expected_algorithm_from_server, NULL, false, + /* ignored */ GRPC_COMPRESS_LEVEL_NONE, + workaround_configs[i].user_agent_override); + } +} + +void workaround_cronet_compression(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_WORKAROUNDS) { + test_workaround_cronet_compression(config); + } +} + +void workaround_cronet_compression_pre_init(void) {} diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c deleted file mode 100644 index d7d1e5fa3d..0000000000 --- a/test/core/end2end/tests/write_buffering.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test_invoke_request_with_payload(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice1 = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload1 = - grpc_raw_byte_buffer_create(&request_payload_slice1, 1); - grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); - grpc_byte_buffer *request_payload2 = - grpc_raw_byte_buffer_create(&request_payload_slice2, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv1 = NULL; - grpc_byte_buffer *request_payload_recv2 = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ - CQ_EXPECT_COMPLETION(cqv, tag(101), true); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload1; - op->flags = GRPC_WRITE_BUFFER_HINT; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - /* recv message should not succeed yet - it's buffered at the client still */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv1; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(2), true); - CQ_EXPECT_COMPLETION(cqv, tag(3), true); - CQ_EXPECT_COMPLETION(cqv, tag(102), true); - cq_verify(cqv); - - /* send another message, this time not buffered */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload2; - op->flags = 0; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - /* now the first send should match up with the first recv */ - CQ_EXPECT_COMPLETION(cqv, tag(103), true); - CQ_EXPECT_COMPLETION(cqv, tag(4), true); - cq_verify(cqv); - - /* and the next recv should be ready immediately also */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv2; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(104), true); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - 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->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(105), 1); - CQ_EXPECT_COMPLETION(cqv, tag(4), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload1); - grpc_byte_buffer_destroy(request_payload_recv1); - grpc_byte_buffer_destroy(request_payload2); - grpc_byte_buffer_destroy(request_payload_recv2); - - end_test(&f); - config.tear_down_data(&f); -} - -void write_buffering(grpc_end2end_test_config config) { - test_invoke_request_with_payload(config); -} - -void write_buffering_pre_init(void) {} diff --git a/test/core/end2end/tests/write_buffering.cc b/test/core/end2end/tests/write_buffering.cc new file mode 100644 index 0000000000..d7d1e5fa3d --- /dev/null +++ b/test/core/end2end/tests/write_buffering.cc @@ -0,0 +1,280 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice1 = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload1 = + grpc_raw_byte_buffer_create(&request_payload_slice1, 1); + grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); + grpc_byte_buffer *request_payload2 = + grpc_raw_byte_buffer_create(&request_payload_slice2, 1); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details = grpc_empty_slice(); + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload1; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send another message, this time not buffered */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload2; + op->flags = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + 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->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload1); + grpc_byte_buffer_destroy(request_payload_recv1); + grpc_byte_buffer_destroy(request_payload2); + grpc_byte_buffer_destroy(request_payload_recv2); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_pre_init(void) {} diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c deleted file mode 100644 index 6113843390..0000000000 --- a/test/core/end2end/tests/write_buffering_at_end.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(5); -} - -static void drain_cq(grpc_completion_queue *cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test_invoke_request_with_payload(grpc_end2end_test_config config) { - grpc_call *c; - grpc_call *s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer *request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_payload", NULL, NULL); - 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_byte_buffer *request_payload_recv1 = NULL; - grpc_byte_buffer *request_payload_recv2 = NULL; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call( - f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), 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); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ - CQ_EXPECT_COMPLETION(cqv, tag(101), true); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = GRPC_WRITE_BUFFER_HINT; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - /* recv message should not succeed yet - it's buffered at the client still */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv1; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(2), true); - CQ_EXPECT_COMPLETION(cqv, tag(3), true); - CQ_EXPECT_COMPLETION(cqv, tag(102), true); - cq_verify(cqv); - - /* send end of stream: should release the buffering */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - /* now the first send should match up with the first recv */ - CQ_EXPECT_COMPLETION(cqv, tag(103), true); - CQ_EXPECT_COMPLETION(cqv, tag(4), true); - cq_verify(cqv); - - /* and the next recv should be ready immediately also (and empty) */ - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv2; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(104), true); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - 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_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = NULL; - op++; - error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(105), 1); - CQ_EXPECT_COMPLETION(cqv, tag(4), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); - GPR_ASSERT(request_payload_recv2 == NULL); - - grpc_slice_unref(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_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv1); - - end_test(&f); - config.tear_down_data(&f); -} - -void write_buffering_at_end(grpc_end2end_test_config config) { - test_invoke_request_with_payload(config); -} - -void write_buffering_at_end_pre_init(void) {} diff --git a/test/core/end2end/tests/write_buffering_at_end.cc b/test/core/end2end/tests/write_buffering_at_end.cc new file mode 100644 index 0000000000..6113843390 --- /dev/null +++ b/test/core/end2end/tests/write_buffering_at_end.cc @@ -0,0 +1,269 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t 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, "Running test: %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_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), 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->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_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); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + 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_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details = grpc_empty_slice(); + int was_cancelled = 2; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send end of stream: should release the buffering */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also (and empty) */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + 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_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(request_payload_recv2 == NULL); + + grpc_slice_unref(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_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv1); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering_at_end(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_at_end_pre_init(void) {} diff --git a/test/core/fling/client.c b/test/core/fling/client.c deleted file mode 100644 index be7bfc2280..0000000000 --- a/test/core/fling/client.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include "src/core/lib/profiling/timers.h" -#include "test/core/util/grpc_profiler.h" -#include "test/core/util/test_config.h" - -static gpr_histogram *histogram; -static grpc_byte_buffer *the_buffer; -static grpc_channel *channel; -static grpc_completion_queue *cq; -static grpc_call *call; -static grpc_op ops[6]; -static grpc_op stream_init_ops[2]; -static grpc_op stream_step_ops[2]; -static grpc_metadata_array initial_metadata_recv; -static grpc_metadata_array trailing_metadata_recv; -static grpc_byte_buffer *response_payload_recv = NULL; -static grpc_status_code status; -static grpc_slice details; -static grpc_op *op; - -static void init_ping_pong_request(void) { - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = the_buffer; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - 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++; -} - -static void step_ping_pong_request(void) { - GPR_TIMER_BEGIN("ping_pong", 1); - grpc_slice host = grpc_slice_from_static_string("localhost"); - call = grpc_channel_create_call( - channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/Reflector/reflectUnary"), &host, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call, ops, - (size_t)(op - ops), - (void *)1, NULL)); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_call_unref(call); - grpc_byte_buffer_destroy(response_payload_recv); - call = NULL; - GPR_TIMER_END("ping_pong", 1); -} - -static void init_ping_pong_stream(void) { - grpc_metadata_array_init(&initial_metadata_recv); - - grpc_call_error error; - grpc_slice host = grpc_slice_from_static_string("localhost"); - call = grpc_channel_create_call( - channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/Reflector/reflectStream"), &host, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - stream_init_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - stream_init_ops[0].data.send_initial_metadata.count = 0; - stream_init_ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; - stream_init_ops[1].data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv; - error = grpc_call_start_batch(call, stream_init_ops, 2, (void *)1, NULL); - GPR_ASSERT(GRPC_CALL_OK == error); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - grpc_metadata_array_init(&initial_metadata_recv); - - stream_step_ops[0].op = GRPC_OP_SEND_MESSAGE; - stream_step_ops[0].data.send_message.send_message = the_buffer; - stream_step_ops[1].op = GRPC_OP_RECV_MESSAGE; - stream_step_ops[1].data.recv_message.recv_message = &response_payload_recv; -} - -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) { - gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME); - return 1e9 * (double)tv.tv_sec + tv.tv_nsec; -} - -typedef struct { - const char *name; - void (*init)(); - void (*do_one_step)(); -} scenario; - -static const scenario scenarios[] = { - {"ping-pong-request", init_ping_pong_request, step_ping_pong_request}, - {"ping-pong-stream", init_ping_pong_stream, step_ping_pong_stream}, -}; - -int main(int argc, char **argv) { - grpc_slice slice = grpc_slice_from_copied_string("x"); - double start, stop; - unsigned i; - - char *fake_argv[1]; - - int payload_size = 1; - int secure = 0; - char *target = "localhost:443"; - gpr_cmdline *cl; - grpc_event event; - 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); - - int warmup_seconds = 1; - int benchmark_seconds = 5; - - cl = gpr_cmdline_create("fling client"); - gpr_cmdline_add_int(cl, "payload_size", "Size of the payload to send", - &payload_size); - gpr_cmdline_add_string(cl, "target", "Target host:port", &target); - gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); - gpr_cmdline_add_string(cl, "scenario", "Scenario", &scenario_name); - gpr_cmdline_add_int(cl, "warmup", "Warmup seconds", &warmup_seconds); - gpr_cmdline_add_int(cl, "benchmark", "Benchmark seconds", &benchmark_seconds); - gpr_cmdline_parse(cl, argc, argv); - gpr_cmdline_destroy(cl); - - for (i = 0; i < GPR_ARRAY_SIZE(scenarios); i++) { - if (0 == strcmp(scenarios[i].name, scenario_name)) { - sc = scenarios[i]; - } - } - if (!sc.name) { - fprintf(stderr, "unsupported scenario '%s'. Valid are:", scenario_name); - for (i = 0; i < GPR_ARRAY_SIZE(scenarios); i++) { - fprintf(stderr, " %s", scenarios[i].name); - } - return 1; - } - - channel = grpc_insecure_channel_create(target, NULL, NULL); - cq = grpc_completion_queue_create_for_next(NULL); - the_buffer = grpc_raw_byte_buffer_create(&slice, (size_t)payload_size); - histogram = gpr_histogram_create(0.01, 60e9); - - sc.init(); - - gpr_timespec end_warmup = grpc_timeout_seconds_to_deadline(warmup_seconds); - gpr_timespec end_profiling = - grpc_timeout_seconds_to_deadline(warmup_seconds + benchmark_seconds); - - while (gpr_time_cmp(gpr_now(end_warmup.clock_type), end_warmup) < 0) { - sc.do_one_step(); - } - - gpr_log(GPR_INFO, "start profiling"); - grpc_profiler_start("client.prof"); - while (gpr_time_cmp(gpr_now(end_profiling.clock_type), end_profiling) < 0) { - start = now(); - sc.do_one_step(); - stop = now(); - gpr_histogram_add(histogram, stop - start); - } - grpc_profiler_stop(); - - if (call) { - grpc_call_unref(call); - } - - grpc_channel_destroy(channel); - grpc_completion_queue_shutdown(cq); - do { - event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); - } while (event.type != GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cq); - grpc_byte_buffer_destroy(the_buffer); - grpc_slice_unref(slice); - - gpr_log(GPR_INFO, "latency (50/95/99/99.9): %f/%f/%f/%f", - gpr_histogram_percentile(histogram, 50), - gpr_histogram_percentile(histogram, 95), - gpr_histogram_percentile(histogram, 99), - gpr_histogram_percentile(histogram, 99.9)); - gpr_histogram_destroy(histogram); - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/fling/client.cc b/test/core/fling/client.cc new file mode 100644 index 0000000000..356ec4bb28 --- /dev/null +++ b/test/core/fling/client.cc @@ -0,0 +1,244 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include "src/core/lib/profiling/timers.h" +#include "test/core/util/grpc_profiler.h" +#include "test/core/util/test_config.h" + +static gpr_histogram *histogram; +static grpc_byte_buffer *the_buffer; +static grpc_channel *channel; +static grpc_completion_queue *cq; +static grpc_call *call; +static grpc_op ops[6]; +static grpc_op stream_init_ops[2]; +static grpc_op stream_step_ops[2]; +static grpc_metadata_array initial_metadata_recv; +static grpc_metadata_array trailing_metadata_recv; +static grpc_byte_buffer *response_payload_recv = NULL; +static grpc_status_code status; +static grpc_slice details; +static grpc_op *op; + +static void init_ping_pong_request(void) { + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + op = ops; + + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = the_buffer; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + 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++; +} + +static void step_ping_pong_request(void) { + GPR_TIMER_BEGIN("ping_pong", 1); + grpc_slice host = grpc_slice_from_static_string("localhost"); + call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/Reflector/reflectUnary"), &host, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call, ops, + (size_t)(op - ops), + (void *)1, NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_call_unref(call); + grpc_byte_buffer_destroy(response_payload_recv); + call = NULL; + GPR_TIMER_END("ping_pong", 1); +} + +static void init_ping_pong_stream(void) { + grpc_metadata_array_init(&initial_metadata_recv); + + grpc_call_error error; + grpc_slice host = grpc_slice_from_static_string("localhost"); + call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/Reflector/reflectStream"), &host, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + stream_init_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; + stream_init_ops[0].data.send_initial_metadata.count = 0; + stream_init_ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; + stream_init_ops[1].data.recv_initial_metadata.recv_initial_metadata = + &initial_metadata_recv; + error = grpc_call_start_batch(call, stream_init_ops, 2, (void *)1, NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_metadata_array_init(&initial_metadata_recv); + + stream_step_ops[0].op = GRPC_OP_SEND_MESSAGE; + stream_step_ops[0].data.send_message.send_message = the_buffer; + stream_step_ops[1].op = GRPC_OP_RECV_MESSAGE; + stream_step_ops[1].data.recv_message.recv_message = &response_payload_recv; +} + +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) { + gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME); + return 1e9 * (double)tv.tv_sec + tv.tv_nsec; +} + +typedef struct { + const char *name; + void (*init)(); + void (*do_one_step)(); +} scenario; + +static const scenario scenarios[] = { + {"ping-pong-request", init_ping_pong_request, step_ping_pong_request}, + {"ping-pong-stream", init_ping_pong_stream, step_ping_pong_stream}, +}; + +int main(int argc, char **argv) { + grpc_slice slice = grpc_slice_from_copied_string("x"); + double start, stop; + unsigned i; + + char *fake_argv[1]; + + int payload_size = 1; + int secure = 0; + const char *target = "localhost:443"; + gpr_cmdline *cl; + grpc_event event; + const 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); + + int warmup_seconds = 1; + int benchmark_seconds = 5; + + cl = gpr_cmdline_create("fling client"); + gpr_cmdline_add_int(cl, "payload_size", "Size of the payload to send", + &payload_size); + gpr_cmdline_add_string(cl, "target", "Target host:port", &target); + gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); + gpr_cmdline_add_string(cl, "scenario", "Scenario", &scenario_name); + gpr_cmdline_add_int(cl, "warmup", "Warmup seconds", &warmup_seconds); + gpr_cmdline_add_int(cl, "benchmark", "Benchmark seconds", &benchmark_seconds); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + for (i = 0; i < GPR_ARRAY_SIZE(scenarios); i++) { + if (0 == strcmp(scenarios[i].name, scenario_name)) { + sc = scenarios[i]; + } + } + if (!sc.name) { + fprintf(stderr, "unsupported scenario '%s'. Valid are:", scenario_name); + for (i = 0; i < GPR_ARRAY_SIZE(scenarios); i++) { + fprintf(stderr, " %s", scenarios[i].name); + } + return 1; + } + + channel = grpc_insecure_channel_create(target, NULL, NULL); + cq = grpc_completion_queue_create_for_next(NULL); + the_buffer = grpc_raw_byte_buffer_create(&slice, (size_t)payload_size); + histogram = gpr_histogram_create(0.01, 60e9); + + sc.init(); + + gpr_timespec end_warmup = grpc_timeout_seconds_to_deadline(warmup_seconds); + gpr_timespec end_profiling = + grpc_timeout_seconds_to_deadline(warmup_seconds + benchmark_seconds); + + while (gpr_time_cmp(gpr_now(end_warmup.clock_type), end_warmup) < 0) { + sc.do_one_step(); + } + + gpr_log(GPR_INFO, "start profiling"); + grpc_profiler_start("client.prof"); + while (gpr_time_cmp(gpr_now(end_profiling.clock_type), end_profiling) < 0) { + start = now(); + sc.do_one_step(); + stop = now(); + gpr_histogram_add(histogram, stop - start); + } + grpc_profiler_stop(); + + if (call) { + grpc_call_unref(call); + } + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + do { + event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + } while (event.type != GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + grpc_byte_buffer_destroy(the_buffer); + grpc_slice_unref(slice); + + gpr_log(GPR_INFO, "latency (50/95/99/99.9): %f/%f/%f/%f", + gpr_histogram_percentile(histogram, 50), + gpr_histogram_percentile(histogram, 95), + gpr_histogram_percentile(histogram, 99), + gpr_histogram_percentile(histogram, 99.9)); + gpr_histogram_destroy(histogram); + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/fling/fling_stream_test.c b/test/core/fling/fling_stream_test.c deleted file mode 100644 index 566d9ae6f0..0000000000 --- a/test/core/fling/fling_stream_test.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/util/port.h" - -int main(int argc, char **argv) { - char *me = argv[0]; - char *lslash = strrchr(me, '/'); - char root[1024]; - int port = grpc_pick_unused_port_or_die(); - char *args[10]; - int status; - gpr_subprocess *svr, *cli; - /* figure out where we are */ - if (lslash) { - memcpy(root, me, (size_t)(lslash - me)); - root[lslash - me] = 0; - } else { - strcpy(root, "."); - } - /* start the server */ - gpr_asprintf(&args[0], "%s/fling_server%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--bind"; - gpr_join_host_port(&args[2], "::", port); - args[3] = "--no-secure"; - svr = gpr_subprocess_create(4, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* start the client */ - gpr_asprintf(&args[0], "%s/fling_client%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--target"; - gpr_join_host_port(&args[2], "127.0.0.1", port); - args[3] = "--scenario=ping-pong-stream"; - args[4] = "--no-secure"; - args[5] = 0; - cli = gpr_subprocess_create(6, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* wait for completion */ - printf("waiting for client\n"); - if ((status = gpr_subprocess_join(cli))) { - gpr_subprocess_destroy(cli); - gpr_subprocess_destroy(svr); - return status; - } - gpr_subprocess_destroy(cli); - - gpr_subprocess_interrupt(svr); - status = gpr_subprocess_join(svr); - gpr_subprocess_destroy(svr); - return status; -} diff --git a/test/core/fling/fling_stream_test.cc b/test/core/fling/fling_stream_test.cc new file mode 100644 index 0000000000..4e3b63e192 --- /dev/null +++ b/test/core/fling/fling_stream_test.cc @@ -0,0 +1,79 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + gpr_subprocess *svr, *cli; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + gpr_asprintf(&args[0], "%s/fling_server%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--bind"); + gpr_join_host_port(&args[2], "::", port); + args[3] = const_cast("--no-secure"); + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* start the client */ + gpr_asprintf(&args[0], "%s/fling_client%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--target"); + gpr_join_host_port(&args[2], "127.0.0.1", port); + args[3] = const_cast("--scenario=ping-pong-stream"); + args[4] = const_cast("--no-secure"); + args[5] = 0; + cli = gpr_subprocess_create(6, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* wait for completion */ + printf("waiting for client\n"); + if ((status = gpr_subprocess_join(cli))) { + gpr_subprocess_destroy(cli); + gpr_subprocess_destroy(svr); + return status; + } + gpr_subprocess_destroy(cli); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/fling/fling_test.c b/test/core/fling/fling_test.c deleted file mode 100644 index 90b48e7737..0000000000 --- a/test/core/fling/fling_test.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/util/port.h" - -int main(int argc, char **argv) { - char *me = argv[0]; - char *lslash = strrchr(me, '/'); - char root[1024]; - int port = grpc_pick_unused_port_or_die(); - char *args[10]; - int status; - gpr_subprocess *svr, *cli; - /* figure out where we are */ - if (lslash) { - memcpy(root, me, (size_t)(lslash - me)); - root[lslash - me] = 0; - } else { - strcpy(root, "."); - } - /* start the server */ - gpr_asprintf(&args[0], "%s/fling_server%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--bind"; - gpr_join_host_port(&args[2], "::", port); - args[3] = "--no-secure"; - svr = gpr_subprocess_create(4, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* start the client */ - gpr_asprintf(&args[0], "%s/fling_client%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--target"; - gpr_join_host_port(&args[2], "127.0.0.1", port); - args[3] = "--scenario=ping-pong-request"; - args[4] = "--no-secure"; - args[5] = 0; - cli = gpr_subprocess_create(6, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* wait for completion */ - printf("waiting for client\n"); - if ((status = gpr_subprocess_join(cli))) { - gpr_subprocess_destroy(cli); - gpr_subprocess_destroy(svr); - return status; - } - gpr_subprocess_destroy(cli); - - gpr_subprocess_interrupt(svr); - status = gpr_subprocess_join(svr); - gpr_subprocess_destroy(svr); - return status; -} diff --git a/test/core/fling/fling_test.cc b/test/core/fling/fling_test.cc new file mode 100644 index 0000000000..a7681d572a --- /dev/null +++ b/test/core/fling/fling_test.cc @@ -0,0 +1,79 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +int main(int argc, const char **argv) { + const char *me = argv[0]; + const char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + gpr_subprocess *svr, *cli; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + gpr_asprintf(&args[0], "%s/fling_server%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--bind"); + gpr_join_host_port(&args[2], "::", port); + args[3] = const_cast("--no-secure"); + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* start the client */ + gpr_asprintf(&args[0], "%s/fling_client%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--target"); + gpr_join_host_port(&args[2], "127.0.0.1", port); + args[3] = const_cast("--scenario=ping-pong-request"); + args[4] = const_cast("--no-secure"); + args[5] = 0; + cli = gpr_subprocess_create(6, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* wait for completion */ + printf("waiting for client\n"); + if ((status = gpr_subprocess_join(cli))) { + gpr_subprocess_destroy(cli); + gpr_subprocess_destroy(svr); + return status; + } + gpr_subprocess_destroy(cli); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/fling/server.c b/test/core/fling/server.c deleted file mode 100644 index b3a7fa21ec..0000000000 --- a/test/core/fling/server.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#ifndef _WIN32 -/* This is for _exit() below, which is temporary. */ -#include -#endif - -#include -#include -#include -#include -#include -#include "src/core/lib/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; -static grpc_call *call; -static grpc_call_details call_details; -static grpc_metadata_array request_metadata_recv; -static grpc_metadata_array initial_metadata_send; -static grpc_byte_buffer *payload_buffer = NULL; -/* Used to drain the terminal read in unary calls. */ -static grpc_byte_buffer *terminal_buffer = NULL; - -static grpc_op read_op; -static grpc_op metadata_send_op; -static grpc_op write_op; -static grpc_op status_op[2]; -static int was_cancelled = 2; -static grpc_op unary_ops[6]; -static int got_sigint = 0; - -static void *tag(intptr_t t) { return (void *)t; } - -typedef enum { - FLING_SERVER_NEW_REQUEST = 1, - FLING_SERVER_READ_FOR_UNARY, - FLING_SERVER_BATCH_OPS_FOR_UNARY, - FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING, - FLING_SERVER_READ_FOR_STREAMING, - FLING_SERVER_WRITE_FOR_STREAMING, - FLING_SERVER_SEND_STATUS_FOR_STREAMING -} fling_server_tags; - -typedef struct { - gpr_refcount pending_ops; - uint32_t flags; -} call_state; - -static void request_call(void) { - grpc_metadata_array_init(&request_metadata_recv); - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(server, &call, &call_details, - &request_metadata_recv, cq, cq, - tag(FLING_SERVER_NEW_REQUEST))); -} - -static void handle_unary_method(void) { - grpc_op *op; - grpc_call_error error; - - grpc_metadata_array_init(&initial_metadata_send); - - op = unary_ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &terminal_buffer; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - if (payload_buffer == NULL) { - gpr_log(GPR_INFO, "NULL payload buffer !!!"); - } - op->data.send_message.send_message = payload_buffer; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status_details = NULL; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - - error = grpc_call_start_batch(call, unary_ops, (size_t)(op - unary_ops), - tag(FLING_SERVER_BATCH_OPS_FOR_UNARY), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); -} - -static void send_initial_metadata(void) { - grpc_call_error error; - void *tagarg = tag(FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING); - grpc_metadata_array_init(&initial_metadata_send); - metadata_send_op.op = GRPC_OP_SEND_INITIAL_METADATA; - metadata_send_op.data.send_initial_metadata.count = 0; - error = grpc_call_start_batch(call, &metadata_send_op, 1, tagarg, NULL); - - GPR_ASSERT(GRPC_CALL_OK == error); -} - -static void start_read_op(int t) { - grpc_call_error error; - /* Starting read at server */ - read_op.op = GRPC_OP_RECV_MESSAGE; - read_op.data.recv_message.recv_message = &payload_buffer; - error = grpc_call_start_batch(call, &read_op, 1, tag(t), NULL); - GPR_ASSERT(GRPC_CALL_OK == error); -} - -static void start_write_op(void) { - grpc_call_error error; - void *tagarg = tag(FLING_SERVER_WRITE_FOR_STREAMING); - /* Starting write at server */ - write_op.op = GRPC_OP_SEND_MESSAGE; - if (payload_buffer == NULL) { - gpr_log(GPR_INFO, "NULL payload buffer !!!"); - } - write_op.data.send_message.send_message = payload_buffer; - error = grpc_call_start_batch(call, &write_op, 1, tagarg, NULL); - GPR_ASSERT(GRPC_CALL_OK == error); -} - -static void start_send_status(void) { - grpc_call_error error; - void *tagarg = tag(FLING_SERVER_SEND_STATUS_FOR_STREAMING); - status_op[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER; - status_op[0].data.send_status_from_server.status = GRPC_STATUS_OK; - status_op[0].data.send_status_from_server.trailing_metadata_count = 0; - status_op[0].data.send_status_from_server.status_details = NULL; - status_op[1].op = GRPC_OP_RECV_CLOSE_ON_SERVER; - status_op[1].data.recv_close_on_server.cancelled = &was_cancelled; - - error = grpc_call_start_batch(call, status_op, 2, tagarg, NULL); - GPR_ASSERT(GRPC_CALL_OK == error); -} - -/* We have some sort of deadlock, so let's not exit gracefully for now. - When that is resolved, please remove the #include above. */ -static void sigint_handler(int x) { _exit(0); } - -int main(int argc, char **argv) { - grpc_event ev; - call_state *s; - char *addr_buf = NULL; - gpr_cmdline *cl; - grpc_completion_queue *shutdown_cq; - int shutdown_started = 0; - int shutdown_finished = 0; - - int secure = 0; - char *addr = NULL; - - 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); - - grpc_init(); - srand((unsigned)clock()); - - cl = gpr_cmdline_create("fling server"); - gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); - gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); - gpr_cmdline_parse(cl, argc, argv); - gpr_cmdline_destroy(cl); - - if (addr == NULL) { - gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); - addr = addr_buf; - } - gpr_log(GPR_INFO, "creating server on: %s", addr); - - cq = grpc_completion_queue_create_for_next(NULL); - if (secure) { - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *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); - } else { - server = grpc_server_create(NULL, NULL); - GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); - } - grpc_server_register_completion_queue(server, cq, NULL); - grpc_server_start(server); - - gpr_free(addr_buf); - addr = addr_buf = NULL; - - grpc_call_details_init(&call_details); - - request_call(); - - grpc_profiler_start("server.prof"); - signal(SIGINT, sigint_handler); - while (!shutdown_finished) { - if (got_sigint && !shutdown_started) { - gpr_log(GPR_INFO, "Shutting down due to SIGINT"); - - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); - - GPR_ASSERT( - grpc_completion_queue_pluck(shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), NULL) - .type == GRPC_OP_COMPLETE); - grpc_completion_queue_destroy(shutdown_cq); - - 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); - s = ev.tag; - switch (ev.type) { - case GRPC_OP_COMPLETE: - switch ((intptr_t)s) { - case FLING_SERVER_NEW_REQUEST: - if (call != NULL) { - if (0 == grpc_slice_str_cmp(call_details.method, - "/Reflector/reflectStream")) { - /* Received streaming call. Send metadata here. */ - start_read_op(FLING_SERVER_READ_FOR_STREAMING); - send_initial_metadata(); - } else { - /* Received unary call. Can do all ops in one batch. */ - start_read_op(FLING_SERVER_READ_FOR_UNARY); - } - } else { - GPR_ASSERT(shutdown_started); - } - /* request_call(); - */ - break; - case FLING_SERVER_READ_FOR_STREAMING: - if (payload_buffer != NULL) { - /* Received payload from client. */ - start_write_op(); - } else { - /* Received end of stream from client. */ - start_send_status(); - } - break; - case FLING_SERVER_WRITE_FOR_STREAMING: - /* Write completed at server */ - grpc_byte_buffer_destroy(payload_buffer); - payload_buffer = NULL; - start_read_op(FLING_SERVER_READ_FOR_STREAMING); - break; - case FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING: - /* Metadata send completed at server */ - break; - case FLING_SERVER_SEND_STATUS_FOR_STREAMING: - /* Send status and close completed at server */ - grpc_call_unref(call); - if (!shutdown_started) request_call(); - break; - case FLING_SERVER_READ_FOR_UNARY: - /* Finished payload read for unary. Start all reamaining - * unary ops in a batch. - */ - handle_unary_method(); - break; - case FLING_SERVER_BATCH_OPS_FOR_UNARY: - /* Finished unary call. */ - grpc_byte_buffer_destroy(payload_buffer); - payload_buffer = NULL; - grpc_call_unref(call); - if (!shutdown_started) request_call(); - break; - } - break; - case GRPC_QUEUE_SHUTDOWN: - GPR_ASSERT(shutdown_started); - shutdown_finished = 1; - break; - case GRPC_QUEUE_TIMEOUT: - break; - } - } - grpc_profiler_stop(); - grpc_call_details_destroy(&call_details); - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_shutdown(); - return 0; -} diff --git a/test/core/fling/server.cc b/test/core/fling/server.cc new file mode 100644 index 0000000000..34e5f79f0b --- /dev/null +++ b/test/core/fling/server.cc @@ -0,0 +1,324 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#ifndef _WIN32 +/* This is for _exit() below, which is temporary. */ +#include +#endif + +#include +#include +#include +#include +#include +#include "src/core/lib/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; +static grpc_call *call; +static grpc_call_details call_details; +static grpc_metadata_array request_metadata_recv; +static grpc_metadata_array initial_metadata_send; +static grpc_byte_buffer *payload_buffer = NULL; +/* Used to drain the terminal read in unary calls. */ +static grpc_byte_buffer *terminal_buffer = NULL; + +static grpc_op read_op; +static grpc_op metadata_send_op; +static grpc_op write_op; +static grpc_op status_op[2]; +static int was_cancelled = 2; +static grpc_op unary_ops[6]; +static int got_sigint = 0; + +static void *tag(intptr_t t) { return (void *)t; } + +typedef enum { + FLING_SERVER_NEW_REQUEST = 1, + FLING_SERVER_READ_FOR_UNARY, + FLING_SERVER_BATCH_OPS_FOR_UNARY, + FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING, + FLING_SERVER_READ_FOR_STREAMING, + FLING_SERVER_WRITE_FOR_STREAMING, + FLING_SERVER_SEND_STATUS_FOR_STREAMING +} fling_server_tags; + +typedef struct { + gpr_refcount pending_ops; + uint32_t flags; +} call_state; + +static void request_call(void) { + grpc_metadata_array_init(&request_metadata_recv); + GPR_ASSERT(GRPC_CALL_OK == + grpc_server_request_call(server, &call, &call_details, + &request_metadata_recv, cq, cq, + tag(FLING_SERVER_NEW_REQUEST))); +} + +static void handle_unary_method(void) { + grpc_op *op; + grpc_call_error error; + + grpc_metadata_array_init(&initial_metadata_send); + + op = unary_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &terminal_buffer; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + if (payload_buffer == NULL) { + gpr_log(GPR_INFO, "NULL payload buffer !!!"); + } + op->data.send_message.send_message = payload_buffer; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status_details = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op++; + + error = grpc_call_start_batch(call, unary_ops, (size_t)(op - unary_ops), + tag(FLING_SERVER_BATCH_OPS_FOR_UNARY), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); +} + +static void send_initial_metadata(void) { + grpc_call_error error; + void *tagarg = tag(FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING); + grpc_metadata_array_init(&initial_metadata_send); + metadata_send_op.op = GRPC_OP_SEND_INITIAL_METADATA; + metadata_send_op.data.send_initial_metadata.count = 0; + error = grpc_call_start_batch(call, &metadata_send_op, 1, tagarg, NULL); + + GPR_ASSERT(GRPC_CALL_OK == error); +} + +static void start_read_op(int t) { + grpc_call_error error; + /* Starting read at server */ + read_op.op = GRPC_OP_RECV_MESSAGE; + read_op.data.recv_message.recv_message = &payload_buffer; + error = grpc_call_start_batch(call, &read_op, 1, tag(t), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); +} + +static void start_write_op(void) { + grpc_call_error error; + void *tagarg = tag(FLING_SERVER_WRITE_FOR_STREAMING); + /* Starting write at server */ + write_op.op = GRPC_OP_SEND_MESSAGE; + if (payload_buffer == NULL) { + gpr_log(GPR_INFO, "NULL payload buffer !!!"); + } + write_op.data.send_message.send_message = payload_buffer; + error = grpc_call_start_batch(call, &write_op, 1, tagarg, NULL); + GPR_ASSERT(GRPC_CALL_OK == error); +} + +static void start_send_status(void) { + grpc_call_error error; + void *tagarg = tag(FLING_SERVER_SEND_STATUS_FOR_STREAMING); + status_op[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER; + status_op[0].data.send_status_from_server.status = GRPC_STATUS_OK; + status_op[0].data.send_status_from_server.trailing_metadata_count = 0; + status_op[0].data.send_status_from_server.status_details = NULL; + status_op[1].op = GRPC_OP_RECV_CLOSE_ON_SERVER; + status_op[1].data.recv_close_on_server.cancelled = &was_cancelled; + + error = grpc_call_start_batch(call, status_op, 2, tagarg, NULL); + GPR_ASSERT(GRPC_CALL_OK == error); +} + +/* We have some sort of deadlock, so let's not exit gracefully for now. + When that is resolved, please remove the #include above. */ +static void sigint_handler(int x) { _exit(0); } + +int main(int argc, char **argv) { + grpc_event ev; + call_state *s; + char *addr_buf = NULL; + gpr_cmdline *cl; + grpc_completion_queue *shutdown_cq; + int shutdown_started = 0; + int shutdown_finished = 0; + + int secure = 0; + const char *addr = NULL; + + 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); + + grpc_init(); + srand((unsigned)clock()); + + cl = gpr_cmdline_create("fling server"); + gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); + gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + if (addr == NULL) { + gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); + addr = addr_buf; + } + gpr_log(GPR_INFO, "creating server on: %s", addr); + + cq = grpc_completion_queue_create_for_next(NULL); + if (secure) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *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); + } else { + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); + } + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + gpr_free(addr_buf); + addr = addr_buf = NULL; + + grpc_call_details_init(&call_details); + + request_call(); + + grpc_profiler_start("server.prof"); + signal(SIGINT, sigint_handler); + while (!shutdown_finished) { + if (got_sigint && !shutdown_started) { + gpr_log(GPR_INFO, "Shutting down due to SIGINT"); + + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); + + GPR_ASSERT( + grpc_completion_queue_pluck(shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_destroy(shutdown_cq); + + 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); + s = static_cast(ev.tag); + switch (ev.type) { + case GRPC_OP_COMPLETE: + switch ((intptr_t)s) { + case FLING_SERVER_NEW_REQUEST: + if (call != NULL) { + if (0 == grpc_slice_str_cmp(call_details.method, + "/Reflector/reflectStream")) { + /* Received streaming call. Send metadata here. */ + start_read_op(FLING_SERVER_READ_FOR_STREAMING); + send_initial_metadata(); + } else { + /* Received unary call. Can do all ops in one batch. */ + start_read_op(FLING_SERVER_READ_FOR_UNARY); + } + } else { + GPR_ASSERT(shutdown_started); + } + /* request_call(); + */ + break; + case FLING_SERVER_READ_FOR_STREAMING: + if (payload_buffer != NULL) { + /* Received payload from client. */ + start_write_op(); + } else { + /* Received end of stream from client. */ + start_send_status(); + } + break; + case FLING_SERVER_WRITE_FOR_STREAMING: + /* Write completed at server */ + grpc_byte_buffer_destroy(payload_buffer); + payload_buffer = NULL; + start_read_op(FLING_SERVER_READ_FOR_STREAMING); + break; + case FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING: + /* Metadata send completed at server */ + break; + case FLING_SERVER_SEND_STATUS_FOR_STREAMING: + /* Send status and close completed at server */ + grpc_call_unref(call); + if (!shutdown_started) request_call(); + break; + case FLING_SERVER_READ_FOR_UNARY: + /* Finished payload read for unary. Start all reamaining + * unary ops in a batch. + */ + handle_unary_method(); + break; + case FLING_SERVER_BATCH_OPS_FOR_UNARY: + /* Finished unary call. */ + grpc_byte_buffer_destroy(payload_buffer); + payload_buffer = NULL; + grpc_call_unref(call); + if (!shutdown_started) request_call(); + break; + } + break; + case GRPC_QUEUE_SHUTDOWN: + GPR_ASSERT(shutdown_started); + shutdown_finished = 1; + break; + case GRPC_QUEUE_TIMEOUT: + break; + } + } + grpc_profiler_stop(); + grpc_call_details_destroy(&call_details); + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + return 0; +} diff --git a/test/core/handshake/client_ssl.c b/test/core/handshake/client_ssl.c deleted file mode 100644 index de660fe1c4..0000000000 --- a/test/core/handshake/client_ssl.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/load_file.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" - -// Arguments for TLS server thread. -typedef struct { - int socket; - char *alpn_preferred; -} server_args; - -// Based on https://wiki.openssl.org/index.php/Simple_TLS_Server. -// Pick an arbitrary unused port and return it in *out_port. Return -// an fd>=0 on success. -static int create_socket(int *out_port) { - int s; - struct sockaddr_in addr; - socklen_t addr_len; - *out_port = -1; - - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("Unable to create socket"); - return -1; - } - - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("Unable to bind"); - gpr_log(GPR_ERROR, "%s", "Unable to bind to any port"); - close(s); - return -1; - } - - if (listen(s, 1) < 0) { - perror("Unable to listen"); - close(s); - return -1; - } - - addr_len = sizeof(addr); - if (getsockname(s, (struct sockaddr *)&addr, &addr_len) != 0 || - addr_len > sizeof(addr)) { - perror("getsockname"); - gpr_log(GPR_ERROR, "%s", "Unable to get socket local address"); - close(s); - return -1; - } - - *out_port = ntohs(addr.sin_port); - return s; -} - -// Server callback during ALPN negotiation. See man page for -// SSL_CTX_set_alpn_select_cb. -static int alpn_select_cb(SSL *ssl, const uint8_t **out, uint8_t *out_len, - const uint8_t *in, unsigned in_len, void *arg) { - const uint8_t *alpn_preferred = (const uint8_t *)arg; - - *out = alpn_preferred; - *out_len = (uint8_t)strlen((char *)alpn_preferred); - - // Validate that the ALPN list includes "h2" and "grpc-exp", that "grpc-exp" - // precedes "h2". - bool grpc_exp_seen = false; - bool h2_seen = false; - const char *inp = (const char *)in; - const char *in_end = inp + in_len; - while (inp < in_end) { - const size_t length = (size_t)*inp++; - if (length == strlen("grpc-exp") && strncmp(inp, "grpc-exp", length) == 0) { - grpc_exp_seen = true; - GPR_ASSERT(!h2_seen); - } - if (length == strlen("h2") && strncmp(inp, "h2", length) == 0) { - h2_seen = true; - GPR_ASSERT(grpc_exp_seen); - } - inp += length; - } - - GPR_ASSERT(inp == in_end); - GPR_ASSERT(grpc_exp_seen); - GPR_ASSERT(h2_seen); - - return SSL_TLSEXT_ERR_OK; -} - -// Minimal TLS server. This is largely based on the example at -// https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core -// internals in src/core/tsi/ssl_transport_security.c. -static void server_thread(void *arg) { - const server_args *args = (server_args *)arg; - - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - - const SSL_METHOD *method = TLSv1_2_server_method(); - SSL_CTX *ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - abort(); - } - - // Load key pair. - if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - - // Set the cipher list to match the one expressed in - // src/core/tsi/ssl_transport_security.c. - const char *cipher_list = - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" - "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; - if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Couldn't set server cipher list."); - abort(); - } - - // Register the ALPN selection callback. - SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred); - - // bind/listen/accept at TCP layer. - const int sock = args->socket; - gpr_log(GPR_INFO, "Server listening"); - struct sockaddr_in addr; - socklen_t len = sizeof(addr); - const int client = accept(sock, (struct sockaddr *)&addr, &len); - if (client < 0) { - perror("Unable to accept"); - abort(); - } - - // Establish a SSL* and accept at SSL layer. - SSL *ssl = SSL_new(ctx); - GPR_ASSERT(ssl); - SSL_set_fd(ssl, client); - if (SSL_accept(ssl) <= 0) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Handshake failed."); - } else { - gpr_log(GPR_INFO, "Handshake successful."); - } - - // Wait until the client drops its connection. - char buf; - while (SSL_read(ssl, &buf, sizeof(buf)) > 0) - ; - - SSL_free(ssl); - close(client); - close(sock); - SSL_CTX_free(ctx); - EVP_cleanup(); -} - -// This test launches a minimal TLS server on a separate thread and then -// establishes a TLS handshake via the core library to the server. The TLS -// server validates ALPN aspects of the handshake and supplies the protocol -// specified in the server_alpn_preferred argument to the client. -static bool client_ssl_test(char *server_alpn_preferred) { - bool success = true; - - grpc_init(); - - // Find a port we can bind to. Retries added to handle flakes in port server - // and port picking. - int port = -1; - int server_socket = -1; - int socket_retries = 30; - while (server_socket == -1 && socket_retries-- > 0) { - server_socket = create_socket(&port); - if (server_socket == -1) { - sleep(1); - } - } - GPR_ASSERT(server_socket > 0 && port > 0); - - // Launch the TLS server thread. - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_id thdid; - gpr_thd_options_set_joinable(&thdopt); - server_args args = {.socket = server_socket, - .alpn_preferred = server_alpn_preferred}; - GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt)); - - // Load key pair and establish client SSL credentials. - grpc_ssl_pem_key_cert_pair pem_key_cert_pair; - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); - const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); - pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL); - - // Establish a channel pointing at the TLS server. Since the gRPC runtime is - // lazy, this won't necessarily establish a connection yet. - char *target; - gpr_asprintf(&target, "127.0.0.1:%d", port); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args grpc_args; - grpc_args.num_args = 1; - grpc_args.args = &ssl_name_override; - grpc_channel *channel = - grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL); - GPR_ASSERT(channel); - gpr_free(target); - - // Initially the channel will be idle, the - // grpc_channel_check_connectivity_state triggers an attempt to connect. - GPR_ASSERT(grpc_channel_check_connectivity_state( - channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE); - - // Wait a bounded number of times for the channel to be ready. When the - // channel is ready, the initial TLS handshake will have successfully - // completed and we know that the client's ALPN list satisfied the server. - int retries = 10; - grpc_connectivity_state state = GRPC_CHANNEL_IDLE; - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - while (state != GRPC_CHANNEL_READY && retries-- > 0) { - grpc_channel_watch_connectivity_state( - channel, state, grpc_timeout_seconds_to_deadline(3), cq, NULL); - gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - state = - grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */); - } - grpc_completion_queue_destroy(cq); - if (retries < 0) { - success = false; - } - - grpc_channel_destroy(channel); - grpc_channel_credentials_release(ssl_creds); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); - - gpr_thd_join(thdid); - - grpc_shutdown(); - - return success; -} - -int main(int argc, char *argv[]) { - // Handshake succeeeds when the server has grpc-exp as the ALPN preference. - GPR_ASSERT(client_ssl_test("grpc-exp")); - // Handshake succeeeds when the server has h2 as the ALPN preference. This - // covers legacy gRPC servers which don't support grpc-exp. - GPR_ASSERT(client_ssl_test("h2")); - // Handshake fails when the server uses a fake protocol as its ALPN - // preference. This validates the client is correctly validating ALPN returns - // and sanity checks the client_ssl_test. - GPR_ASSERT(!client_ssl_test("foo")); - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/handshake/client_ssl.cc b/test/core/handshake/client_ssl.cc new file mode 100644 index 0000000000..f501948b96 --- /dev/null +++ b/test/core/handshake/client_ssl.cc @@ -0,0 +1,323 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" + +// Arguments for TLS server thread. +typedef struct { + int socket; + char *alpn_preferred; +} server_args; + +// Based on https://wiki.openssl.org/index.php/Simple_TLS_Server. +// Pick an arbitrary unused port and return it in *out_port. Return +// an fd>=0 on success. +static int create_socket(int *out_port) { + int s; + struct sockaddr_in addr; + socklen_t addr_len; + *out_port = -1; + + addr.sin_family = AF_INET; + addr.sin_port = 0; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + return -1; + } + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("Unable to bind"); + gpr_log(GPR_ERROR, "%s", "Unable to bind to any port"); + close(s); + return -1; + } + + if (listen(s, 1) < 0) { + perror("Unable to listen"); + close(s); + return -1; + } + + addr_len = sizeof(addr); + if (getsockname(s, (struct sockaddr *)&addr, &addr_len) != 0 || + addr_len > sizeof(addr)) { + perror("getsockname"); + gpr_log(GPR_ERROR, "%s", "Unable to get socket local address"); + close(s); + return -1; + } + + *out_port = ntohs(addr.sin_port); + return s; +} + +// Server callback during ALPN negotiation. See man page for +// SSL_CTX_set_alpn_select_cb. +static int alpn_select_cb(SSL *ssl, const uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg) { + const uint8_t *alpn_preferred = (const uint8_t *)arg; + + *out = alpn_preferred; + *out_len = (uint8_t)strlen((char *)alpn_preferred); + + // Validate that the ALPN list includes "h2" and "grpc-exp", that "grpc-exp" + // precedes "h2". + bool grpc_exp_seen = false; + bool h2_seen = false; + const char *inp = (const char *)in; + const char *in_end = inp + in_len; + while (inp < in_end) { + const size_t length = (size_t)*inp++; + if (length == strlen("grpc-exp") && strncmp(inp, "grpc-exp", length) == 0) { + grpc_exp_seen = true; + GPR_ASSERT(!h2_seen); + } + if (length == strlen("h2") && strncmp(inp, "h2", length) == 0) { + h2_seen = true; + GPR_ASSERT(grpc_exp_seen); + } + inp += length; + } + + GPR_ASSERT(inp == in_end); + GPR_ASSERT(grpc_exp_seen); + GPR_ASSERT(h2_seen); + + return SSL_TLSEXT_ERR_OK; +} + +// Minimal TLS server. This is largely based on the example at +// https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core +// internals in src/core/tsi/ssl_transport_security.c. +static void server_thread(void *arg) { + const server_args *args = (server_args *)arg; + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + + const SSL_METHOD *method = TLSv1_2_server_method(); + SSL_CTX *ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + abort(); + } + + // Load key pair. + if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + + // Set the cipher list to match the one expressed in + // src/core/tsi/ssl_transport_security.c. + const char *cipher_list = + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" + "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; + if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Couldn't set server cipher list."); + abort(); + } + + // Register the ALPN selection callback. + SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred); + + // bind/listen/accept at TCP layer. + const int sock = args->socket; + gpr_log(GPR_INFO, "Server listening"); + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + const int client = accept(sock, (struct sockaddr *)&addr, &len); + if (client < 0) { + perror("Unable to accept"); + abort(); + } + + // Establish a SSL* and accept at SSL layer. + SSL *ssl = SSL_new(ctx); + GPR_ASSERT(ssl); + SSL_set_fd(ssl, client); + if (SSL_accept(ssl) <= 0) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Handshake failed."); + } else { + gpr_log(GPR_INFO, "Handshake successful."); + } + + // Wait until the client drops its connection. + char buf; + while (SSL_read(ssl, &buf, sizeof(buf)) > 0) + ; + + SSL_free(ssl); + close(client); + close(sock); + SSL_CTX_free(ctx); + EVP_cleanup(); +} + +// This test launches a minimal TLS server on a separate thread and then +// establishes a TLS handshake via the core library to the server. The TLS +// server validates ALPN aspects of the handshake and supplies the protocol +// specified in the server_alpn_preferred argument to the client. +static bool client_ssl_test(char *server_alpn_preferred) { + bool success = true; + + grpc_init(); + + // Find a port we can bind to. Retries added to handle flakes in port server + // and port picking. + int port = -1; + int server_socket = -1; + int socket_retries = 30; + while (server_socket == -1 && socket_retries-- > 0) { + server_socket = create_socket(&port); + if (server_socket == -1) { + sleep(1); + } + } + GPR_ASSERT(server_socket > 0 && port > 0); + + // Launch the TLS server thread. + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_id thdid; + gpr_thd_options_set_joinable(&thdopt); + server_args args = {server_socket, server_alpn_preferred}; + GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt)); + + // Load key pair and establish client SSL credentials. + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_slice ca_slice, cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); + const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); + pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL); + + // Establish a channel pointing at the TLS server. Since the gRPC runtime is + // lazy, this won't necessarily establish a connection yet. + char *target; + gpr_asprintf(&target, "127.0.0.1:%d", port); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args grpc_args; + grpc_args.num_args = 1; + grpc_args.args = &ssl_name_override; + grpc_channel *channel = + grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL); + GPR_ASSERT(channel); + gpr_free(target); + + // Initially the channel will be idle, the + // grpc_channel_check_connectivity_state triggers an attempt to connect. + GPR_ASSERT(grpc_channel_check_connectivity_state( + channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE); + + // Wait a bounded number of times for the channel to be ready. When the + // channel is ready, the initial TLS handshake will have successfully + // completed and we know that the client's ALPN list satisfied the server. + int retries = 10; + grpc_connectivity_state state = GRPC_CHANNEL_IDLE; + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + while (state != GRPC_CHANNEL_READY && retries-- > 0) { + grpc_channel_watch_connectivity_state( + channel, state, grpc_timeout_seconds_to_deadline(3), cq, NULL); + gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + state = + grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */); + } + grpc_completion_queue_destroy(cq); + if (retries < 0) { + success = false; + } + + grpc_channel_destroy(channel); + grpc_channel_credentials_release(ssl_creds); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + grpc_slice_unref(ca_slice); + + gpr_thd_join(thdid); + + grpc_shutdown(); + + return success; +} + +int main(int argc, char *argv[]) { + // Handshake succeeeds when the server has grpc-exp as the ALPN preference. + GPR_ASSERT(client_ssl_test(const_cast("grpc-exp"))); + // Handshake succeeeds when the server has h2 as the ALPN preference. This + // covers legacy gRPC servers which don't support grpc-exp. + GPR_ASSERT(client_ssl_test(const_cast("h2"))); + // Handshake fails when the server uses a fake protocol as its ALPN + // preference. This validates the client is correctly validating ALPN returns + // and sanity checks the client_ssl_test. + GPR_ASSERT(!client_ssl_test(const_cast("foo"))); + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/handshake/server_ssl.c b/test/core/handshake/server_ssl.c deleted file mode 100644 index 85a8b4de41..0000000000 --- a/test/core/handshake/server_ssl.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/load_file.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" - -// Handshake completed signal to server thread. -static gpr_event client_handshake_complete; - -static int create_socket(int port) { - int s; - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons((uint16_t)port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("Unable to create socket"); - return -1; - } - - if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("Unable to connect"); - return -1; - } - - return s; -} - -// Simple gRPC server. This listens until client_handshake_complete occurs. -static void server_thread(void *arg) { - const int port = *(int *)arg; - - // Load key pair and establish server SSL credentials. - grpc_ssl_pem_key_cert_pair pem_key_cert_pair; - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); - const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); - pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); - grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( - ca_cert, &pem_key_cert_pair, 1, 0, NULL); - - // Start server listening on local port. - char *addr; - gpr_asprintf(&addr, "127.0.0.1:%d", port); - grpc_server *server = grpc_server_create(NULL, NULL); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); - free(addr); - - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - grpc_server_register_completion_queue(server, cq, NULL); - grpc_server_start(server); - - // Wait a bounded number of time until client_handshake_complete is set, - // sleeping between polls. - int retries = 10; - while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); - } - - gpr_log(GPR_INFO, "Shutting down server"); - grpc_server_shutdown_and_notify(server, cq, NULL); - grpc_completion_queue_shutdown(cq); - - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_server_credentials_release(ssl_creds); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); -} - -// This test launches a gRPC server on a separate thread and then establishes a -// TLS handshake via a minimal TLS client. The TLS client has configurable (via -// alpn_list) ALPN settings and can probe at the supported ALPN preferences -// using this (via alpn_expected). -static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, - const char *alpn_expected) { - bool success = true; - - grpc_init(); - int port = grpc_pick_unused_port_or_die(); - gpr_event_init(&client_handshake_complete); - - // Launch the gRPC server thread. - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_id thdid; - gpr_thd_options_set_joinable(&thdopt); - GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); - - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - - const SSL_METHOD *method = TLSv1_2_client_method(); - SSL_CTX *ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - abort(); - } - - // Load key pair. - if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - - // Set the cipher list to match the one expressed in - // src/core/tsi/ssl_transport_security.c. - const char *cipher_list = - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" - "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; - if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Couldn't set server cipher list."); - abort(); - } - - // Configure ALPN list the client will send to the server. This must match the - // wire format, see documentation for SSL_CTX_set_alpn_protos. - unsigned int alpn_protos_len = alpn_list_len; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - alpn_protos_len += (unsigned int)strlen(alpn_list[i]); - } - unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); - unsigned char *p = alpn_protos; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - const uint8_t len = (uint8_t)strlen(alpn_list[i]); - *p++ = len; - memcpy(p, alpn_list[i], len); - p += len; - } - GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); - - // Try and connect to server. We allow a bounded number of retries as we might - // be racing with the server setup on its separate thread. - int retries = 10; - int sock = -1; - while (sock == -1 && retries-- > 0) { - sock = create_socket(port); - if (sock < 0) { - sleep(1); - } - } - GPR_ASSERT(sock > 0); - gpr_log(GPR_INFO, "Connected to server on port %d", port); - - // Establish a SSL* and connect at SSL layer. - SSL *ssl = SSL_new(ctx); - GPR_ASSERT(ssl); - SSL_set_fd(ssl, sock); - if (SSL_connect(ssl) <= 0) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Handshake failed."); - success = false; - } else { - gpr_log(GPR_INFO, "Handshake successful."); - // Validate ALPN preferred by server matches alpn_expected. - const unsigned char *alpn_selected; - unsigned int alpn_selected_len; - SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); - if (strlen(alpn_expected) != alpn_selected_len || - strncmp((const char *)alpn_selected, alpn_expected, - alpn_selected_len) != 0) { - gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); - success = false; - } - } - gpr_event_set(&client_handshake_complete, &client_handshake_complete); - - SSL_free(ssl); - gpr_free(alpn_protos); - SSL_CTX_free(ctx); - EVP_cleanup(); - close(sock); - - gpr_thd_join(thdid); - - grpc_shutdown(); - - return success; -} - -int main(int argc, char *argv[]) { - // Handshake succeeeds when the client supplies the standard ALPN list. - const char *full_alpn_list[] = {"grpc-exp", "h2"}; - GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); - // Handshake succeeeds when the client supplies only h2 as the ALPN list. This - // covers legacy gRPC clients which don't support grpc-exp. - const char *h2_only_alpn_list[] = {"h2"}; - GPR_ASSERT(server_ssl_test(h2_only_alpn_list, 1, "h2")); - // Handshake succeeds when the client supplies superfluous ALPN entries and - // also when h2 precedes gprc-exp. - const char *extra_alpn_list[] = {"foo", "h2", "bar", "grpc-exp"}; - GPR_ASSERT(server_ssl_test(extra_alpn_list, 4, "h2")); - // Handshake fails when the client uses a fake protocol as its only ALPN - // preference. This validates the server is correctly validating ALPN - // and sanity checks the server_ssl_test. - const char *fake_alpn_list[] = {"foo"}; - GPR_ASSERT(!server_ssl_test(fake_alpn_list, 1, "foo")); - return 0; -} diff --git a/test/core/handshake/server_ssl.cc b/test/core/handshake/server_ssl.cc new file mode 100644 index 0000000000..7b24459688 --- /dev/null +++ b/test/core/handshake/server_ssl.cc @@ -0,0 +1,256 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" + +// Handshake completed signal to server thread. +static gpr_event client_handshake_complete; + +static int create_socket(int port) { + int s; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons((uint16_t)port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + return -1; + } + + if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("Unable to connect"); + return -1; + } + + return s; +} + +// Simple gRPC server. This listens until client_handshake_complete occurs. +static void server_thread(void *arg) { + const int port = *(int *)arg; + + // Load key pair and establish server SSL credentials. + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_slice ca_slice, cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); + const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); + pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); + grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( + ca_cert, &pem_key_cert_pair, 1, 0, NULL); + + // Start server listening on local port. + char *addr; + gpr_asprintf(&addr, "127.0.0.1:%d", port); + grpc_server *server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + free(addr); + + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + // Wait a bounded number of time until client_handshake_complete is set, + // sleeping between polls. + int retries = 10; + while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + } + + gpr_log(GPR_INFO, "Shutting down server"); + grpc_server_shutdown_and_notify(server, cq, NULL); + grpc_completion_queue_shutdown(cq); + + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_server_credentials_release(ssl_creds); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + grpc_slice_unref(ca_slice); +} + +// This test launches a gRPC server on a separate thread and then establishes a +// TLS handshake via a minimal TLS client. The TLS client has configurable (via +// alpn_list) ALPN settings and can probe at the supported ALPN preferences +// using this (via alpn_expected). +static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, + const char *alpn_expected) { + bool success = true; + + grpc_init(); + int port = grpc_pick_unused_port_or_die(); + gpr_event_init(&client_handshake_complete); + + // Launch the gRPC server thread. + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_id thdid; + gpr_thd_options_set_joinable(&thdopt); + GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + + const SSL_METHOD *method = TLSv1_2_client_method(); + SSL_CTX *ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + abort(); + } + + // Load key pair. + if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + + // Set the cipher list to match the one expressed in + // src/core/tsi/ssl_transport_security.c. + const char *cipher_list = + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" + "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; + if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Couldn't set server cipher list."); + abort(); + } + + // Configure ALPN list the client will send to the server. This must match the + // wire format, see documentation for SSL_CTX_set_alpn_protos. + unsigned int alpn_protos_len = alpn_list_len; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + alpn_protos_len += (unsigned int)strlen(alpn_list[i]); + } + unsigned char *alpn_protos = + static_cast(gpr_malloc(alpn_protos_len)); + unsigned char *p = alpn_protos; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + const uint8_t len = (uint8_t)strlen(alpn_list[i]); + *p++ = len; + memcpy(p, alpn_list[i], len); + p += len; + } + GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); + + // Try and connect to server. We allow a bounded number of retries as we might + // be racing with the server setup on its separate thread. + int retries = 10; + int sock = -1; + while (sock == -1 && retries-- > 0) { + sock = create_socket(port); + if (sock < 0) { + sleep(1); + } + } + GPR_ASSERT(sock > 0); + gpr_log(GPR_INFO, "Connected to server on port %d", port); + + // Establish a SSL* and connect at SSL layer. + SSL *ssl = SSL_new(ctx); + GPR_ASSERT(ssl); + SSL_set_fd(ssl, sock); + if (SSL_connect(ssl) <= 0) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Handshake failed."); + success = false; + } else { + gpr_log(GPR_INFO, "Handshake successful."); + // Validate ALPN preferred by server matches alpn_expected. + const unsigned char *alpn_selected; + unsigned int alpn_selected_len; + SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); + if (strlen(alpn_expected) != alpn_selected_len || + strncmp((const char *)alpn_selected, alpn_expected, + alpn_selected_len) != 0) { + gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); + success = false; + } + } + gpr_event_set(&client_handshake_complete, &client_handshake_complete); + + SSL_free(ssl); + gpr_free(alpn_protos); + SSL_CTX_free(ctx); + EVP_cleanup(); + close(sock); + + gpr_thd_join(thdid); + + grpc_shutdown(); + + return success; +} + +int main(int argc, char *argv[]) { + // Handshake succeeeds when the client supplies the standard ALPN list. + const char *full_alpn_list[] = {"grpc-exp", "h2"}; + GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); + // Handshake succeeeds when the client supplies only h2 as the ALPN list. This + // covers legacy gRPC clients which don't support grpc-exp. + const char *h2_only_alpn_list[] = {"h2"}; + GPR_ASSERT(server_ssl_test(h2_only_alpn_list, 1, "h2")); + // Handshake succeeds when the client supplies superfluous ALPN entries and + // also when h2 precedes gprc-exp. + const char *extra_alpn_list[] = {"foo", "h2", "bar", "grpc-exp"}; + GPR_ASSERT(server_ssl_test(extra_alpn_list, 4, "h2")); + // Handshake fails when the client uses a fake protocol as its only ALPN + // preference. This validates the server is correctly validating ALPN + // and sanity checks the server_ssl_test. + const char *fake_alpn_list[] = {"foo"}; + GPR_ASSERT(!server_ssl_test(fake_alpn_list, 1, "foo")); + return 0; +} diff --git a/test/core/http/format_request_test.c b/test/core/http/format_request_test.c deleted file mode 100644 index 0279a1b5e3..0000000000 --- a/test/core/http/format_request_test.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/http/format_request.h" - -#include - -#include -#include "test/core/util/test_config.h" - -static void test_format_get_request(void) { - grpc_http_header hdr = {"x-yz", "abc"}; - grpc_httpcli_request req; - grpc_slice slice; - - memset(&req, 0, sizeof(req)); - req.host = "example.com"; - req.http.path = "/index.html"; - req.http.hdr_count = 1; - req.http.hdrs = &hdr; - - slice = grpc_httpcli_format_get_request(&req); - - GPR_ASSERT(0 == grpc_slice_str_cmp(slice, - "GET /index.html HTTP/1.0\r\n" - "Host: example.com\r\n" - "Connection: close\r\n" - "User-Agent: " GRPC_HTTPCLI_USER_AGENT - "\r\n" - "x-yz: abc\r\n" - "\r\n")); - - grpc_slice_unref(slice); -} - -static void test_format_post_request(void) { - grpc_http_header hdr = {"x-yz", "abc"}; - grpc_httpcli_request req; - grpc_slice slice; - char body_bytes[] = "fake body"; - size_t body_len = 9; - - memset(&req, 0, sizeof(req)); - req.host = "example.com"; - req.http.path = "/index.html"; - req.http.hdr_count = 1; - req.http.hdrs = &hdr; - - slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len); - - GPR_ASSERT(0 == grpc_slice_str_cmp(slice, - "POST /index.html HTTP/1.0\r\n" - "Host: example.com\r\n" - "Connection: close\r\n" - "User-Agent: " GRPC_HTTPCLI_USER_AGENT - "\r\n" - "x-yz: abc\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 9\r\n" - "\r\n" - "fake body")); - - grpc_slice_unref(slice); -} - -static void test_format_post_request_no_body(void) { - grpc_http_header hdr = {"x-yz", "abc"}; - grpc_httpcli_request req; - grpc_slice slice; - - memset(&req, 0, sizeof(req)); - req.host = "example.com"; - req.http.path = "/index.html"; - req.http.hdr_count = 1; - req.http.hdrs = &hdr; - - slice = grpc_httpcli_format_post_request(&req, NULL, 0); - - GPR_ASSERT(0 == grpc_slice_str_cmp(slice, - "POST /index.html HTTP/1.0\r\n" - "Host: example.com\r\n" - "Connection: close\r\n" - "User-Agent: " GRPC_HTTPCLI_USER_AGENT - "\r\n" - "x-yz: abc\r\n" - "\r\n")); - - grpc_slice_unref(slice); -} - -static void test_format_post_request_content_type_override(void) { - grpc_http_header hdrs[2]; - grpc_httpcli_request req; - grpc_slice slice; - char body_bytes[] = "fake%20body"; - size_t body_len = 11; - - hdrs[0].key = "x-yz"; - hdrs[0].value = "abc"; - hdrs[1].key = "Content-Type"; - hdrs[1].value = "application/x-www-form-urlencoded"; - memset(&req, 0, sizeof(req)); - req.host = "example.com"; - req.http.path = "/index.html"; - req.http.hdr_count = 2; - req.http.hdrs = hdrs; - - slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len); - - GPR_ASSERT(0 == grpc_slice_str_cmp( - slice, - "POST /index.html HTTP/1.0\r\n" - "Host: example.com\r\n" - "Connection: close\r\n" - "User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n" - "x-yz: abc\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 11\r\n" - "\r\n" - "fake%20body")); - - grpc_slice_unref(slice); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - test_format_get_request(); - test_format_post_request(); - test_format_post_request_no_body(); - test_format_post_request_content_type_override(); - - return 0; -} diff --git a/test/core/http/format_request_test.cc b/test/core/http/format_request_test.cc new file mode 100644 index 0000000000..b2d903458d --- /dev/null +++ b/test/core/http/format_request_test.cc @@ -0,0 +1,152 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/http/format_request.h" + +#include + +#include +#include "test/core/util/test_config.h" + +static void test_format_get_request(void) { + grpc_http_header hdr = {const_cast("x-yz"), + const_cast("abc")}; + grpc_httpcli_request req; + grpc_slice slice; + + memset(&req, 0, sizeof(req)); + req.host = const_cast("example.com"); + req.http.path = const_cast("/index.html"); + req.http.hdr_count = 1; + req.http.hdrs = &hdr; + + slice = grpc_httpcli_format_get_request(&req); + + GPR_ASSERT(0 == grpc_slice_str_cmp(slice, + "GET /index.html HTTP/1.0\r\n" + "Host: example.com\r\n" + "Connection: close\r\n" + "User-Agent: " GRPC_HTTPCLI_USER_AGENT + "\r\n" + "x-yz: abc\r\n" + "\r\n")); + + grpc_slice_unref(slice); +} + +static void test_format_post_request(void) { + grpc_http_header hdr = {const_cast("x-yz"), + const_cast("abc")}; + grpc_httpcli_request req; + grpc_slice slice; + char body_bytes[] = "fake body"; + size_t body_len = 9; + + memset(&req, 0, sizeof(req)); + req.host = const_cast("example.com"); + req.http.path = const_cast("/index.html"); + req.http.hdr_count = 1; + req.http.hdrs = &hdr; + + slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len); + + GPR_ASSERT(0 == grpc_slice_str_cmp(slice, + "POST /index.html HTTP/1.0\r\n" + "Host: example.com\r\n" + "Connection: close\r\n" + "User-Agent: " GRPC_HTTPCLI_USER_AGENT + "\r\n" + "x-yz: abc\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 9\r\n" + "\r\n" + "fake body")); + + grpc_slice_unref(slice); +} + +static void test_format_post_request_no_body(void) { + grpc_http_header hdr = {const_cast("x-yz"), + const_cast("abc")}; + grpc_httpcli_request req; + grpc_slice slice; + + memset(&req, 0, sizeof(req)); + req.host = const_cast("example.com"); + req.http.path = const_cast("/index.html"); + req.http.hdr_count = 1; + req.http.hdrs = &hdr; + + slice = grpc_httpcli_format_post_request(&req, NULL, 0); + + GPR_ASSERT(0 == grpc_slice_str_cmp(slice, + "POST /index.html HTTP/1.0\r\n" + "Host: example.com\r\n" + "Connection: close\r\n" + "User-Agent: " GRPC_HTTPCLI_USER_AGENT + "\r\n" + "x-yz: abc\r\n" + "\r\n")); + + grpc_slice_unref(slice); +} + +static void test_format_post_request_content_type_override(void) { + grpc_http_header hdrs[2]; + grpc_httpcli_request req; + grpc_slice slice; + char body_bytes[] = "fake%20body"; + size_t body_len = 11; + + hdrs[0].key = const_cast("x-yz"); + hdrs[0].value = const_cast("abc"); + hdrs[1].key = const_cast("Content-Type"); + hdrs[1].value = const_cast("application/x-www-form-urlencoded"); + memset(&req, 0, sizeof(req)); + req.host = const_cast("example.com"); + req.http.path = const_cast("/index.html"); + req.http.hdr_count = 2; + req.http.hdrs = hdrs; + + slice = grpc_httpcli_format_post_request(&req, body_bytes, body_len); + + GPR_ASSERT(0 == grpc_slice_str_cmp( + slice, + "POST /index.html HTTP/1.0\r\n" + "Host: example.com\r\n" + "Connection: close\r\n" + "User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n" + "x-yz: abc\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: 11\r\n" + "\r\n" + "fake%20body")); + + grpc_slice_unref(slice); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + test_format_get_request(); + test_format_post_request(); + test_format_post_request_no_body(); + test_format_post_request_content_type_override(); + + return 0; +} diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c deleted file mode 100644 index cc1c16d695..0000000000 --- a/test/core/http/httpcli_test.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/http/httpcli.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/iomgr.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 gpr_mu *g_mu; -static grpc_polling_entity g_pops; - -static grpc_millis n_seconds_time(int seconds) { - return grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(seconds)); -} - -static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - const char *expect = - "Hello world!" - "

This is a test

"; - grpc_http_response *response = arg; - 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(g_mu); - g_done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&g_pops), NULL))); - gpr_mu_unlock(g_mu); -} - -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.http.path = "/get"; - req.handshaker = &grpc_httpcli_plaintext; - - grpc_http_response response; - memset(&response, 0, sizeof(response)); - grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_get"); - grpc_httpcli_get( - &exec_ctx, &g_context, &g_pops, resource_quota, &req, n_seconds_time(15), - GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), - &response); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - gpr_mu_lock(g_mu); - while (!g_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &worker, n_seconds_time(1)))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); - gpr_free(host); - grpc_http_response_destroy(&response); -} - -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.http.path = "/post"; - req.handshaker = &grpc_httpcli_plaintext; - - grpc_http_response response; - memset(&response, 0, sizeof(response)); - grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_post"); - grpc_httpcli_post( - &exec_ctx, &g_context, &g_pops, resource_quota, &req, "hello", 5, - n_seconds_time(15), - GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), - &response); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - gpr_mu_lock(g_mu); - while (!g_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &worker, n_seconds_time(1)))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); - gpr_free(host); - grpc_http_response_destroy(&response); -} - -static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset(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[4]; - int port = grpc_pick_unused_port_or_die(); - int arg_shift = 0; - /* 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_ASSERT(argc <= 2); - if (argc == 2) { - args[0] = gpr_strdup(argv[1]); - } else { - arg_shift = 1; - gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root); - gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root); - } - - /* start the server */ - args[1 + arg_shift] = "--port"; - gpr_asprintf(&args[2 + arg_shift], "%d", port); - server = gpr_subprocess_create(3 + arg_shift, (const char **)args); - GPR_ASSERT(server); - gpr_free(args[0]); - if (arg_shift) gpr_free(args[1]); - gpr_free(args[2 + arg_shift]); - gpr_free(root); - - 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 *pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &g_mu); - g_pops = grpc_polling_entity_create_from_pollset(pollset); - - test_get(port); - test_post(port); - - grpc_httpcli_context_destroy(&exec_ctx, &g_context); - GRPC_CLOSURE_INIT(&destroyed, destroy_pops, &g_pops, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - - gpr_free(grpc_polling_entity_pollset(&g_pops)); - - gpr_subprocess_destroy(server); - - return 0; -} diff --git a/test/core/http/httpcli_test.cc b/test/core/http/httpcli_test.cc new file mode 100644 index 0000000000..925f63decc --- /dev/null +++ b/test/core/http/httpcli_test.cc @@ -0,0 +1,211 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/http/httpcli.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/iomgr.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 gpr_mu *g_mu; +static grpc_polling_entity g_pops; + +static grpc_millis n_seconds_time(int seconds) { + return grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(seconds)); +} + +static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + const char *expect = + "Hello world!" + "

This is a test

"; + grpc_http_response *response = static_cast(arg); + 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(g_mu); + g_done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&g_pops), NULL))); + gpr_mu_unlock(g_mu); +} + +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.http.path = const_cast("/get"); + req.handshaker = &grpc_httpcli_plaintext; + + grpc_http_response response; + memset(&response, 0, sizeof(response)); + grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_get"); + grpc_httpcli_get( + &exec_ctx, &g_context, &g_pops, resource_quota, &req, n_seconds_time(15), + GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), + &response); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + gpr_mu_lock(g_mu); + while (!g_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &worker, n_seconds_time(1)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); + gpr_free(host); + grpc_http_response_destroy(&response); +} + +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.http.path = const_cast("/post"); + req.handshaker = &grpc_httpcli_plaintext; + + grpc_http_response response; + memset(&response, 0, sizeof(response)); + grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_post"); + grpc_httpcli_post( + &exec_ctx, &g_context, &g_pops, resource_quota, &req, "hello", 5, + n_seconds_time(15), + GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), + &response); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + gpr_mu_lock(g_mu); + while (!g_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &worker, n_seconds_time(1)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); + gpr_free(host); + grpc_http_response_destroy(&response); +} + +static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { + grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset( + static_cast(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[4]; + int port = grpc_pick_unused_port_or_die(); + int arg_shift = 0; + /* figure out where we are */ + char *root; + if (lslash) { + root = static_cast(gpr_malloc((size_t)(lslash - me + 1))); + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + root = gpr_strdup("."); + } + + GPR_ASSERT(argc <= 2); + if (argc == 2) { + args[0] = gpr_strdup(argv[1]); + } else { + arg_shift = 1; + gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root); + gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root); + } + + /* start the server */ + args[1 + arg_shift] = const_cast("--port"); + gpr_asprintf(&args[2 + arg_shift], "%d", port); + server = gpr_subprocess_create(3 + arg_shift, (const char **)args); + GPR_ASSERT(server); + gpr_free(args[0]); + if (arg_shift) gpr_free(args[1]); + gpr_free(args[2 + arg_shift]); + gpr_free(root); + + 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 *pollset = + static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(pollset, &g_mu); + g_pops = grpc_polling_entity_create_from_pollset(pollset); + + test_get(port); + test_post(port); + + grpc_httpcli_context_destroy(&exec_ctx, &g_context); + GRPC_CLOSURE_INIT(&destroyed, destroy_pops, &g_pops, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_free(grpc_polling_entity_pollset(&g_pops)); + + gpr_subprocess_destroy(server); + + return 0; +} diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c deleted file mode 100644 index f8a3cfdd76..0000000000 --- a/test/core/http/httpscli_test.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/http/httpcli.h" - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/iomgr.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 gpr_mu *g_mu; -static grpc_polling_entity g_pops; - -static grpc_millis n_seconds_time(int seconds) { - return grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(seconds)); -} - -static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - const char *expect = - "Hello world!" - "

This is a test

"; - grpc_http_response *response = arg; - 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(g_mu); - g_done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&g_pops), NULL))); - gpr_mu_unlock(g_mu); -} - -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.http.path = "/get"; - req.handshaker = &grpc_httpcli_ssl; - - grpc_http_response response; - memset(&response, 0, sizeof(response)); - grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_get"); - grpc_httpcli_get( - &exec_ctx, &g_context, &g_pops, resource_quota, &req, n_seconds_time(15), - GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), - &response); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - gpr_mu_lock(g_mu); - while (!g_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &worker, n_seconds_time(1)))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); - gpr_free(host); - grpc_http_response_destroy(&response); -} - -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.http.path = "/post"; - req.handshaker = &grpc_httpcli_ssl; - - grpc_http_response response; - memset(&response, 0, sizeof(response)); - grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_post"); - grpc_httpcli_post( - &exec_ctx, &g_context, &g_pops, resource_quota, &req, "hello", 5, - n_seconds_time(15), - GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), - &response); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - gpr_mu_lock(g_mu); - while (!g_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &worker, n_seconds_time(1)))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); - gpr_free(host); - grpc_http_response_destroy(&response); -} - -static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset(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(); - int arg_shift = 0; - /* 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_ASSERT(argc <= 2); - if (argc == 2) { - args[0] = gpr_strdup(argv[1]); - } else { - arg_shift = 1; - gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root); - gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root); - } - - /* start the server */ - args[1 + arg_shift] = "--port"; - gpr_asprintf(&args[2 + arg_shift], "%d", port); - args[3 + arg_shift] = "--ssl"; - server = gpr_subprocess_create(4 + arg_shift, (const char **)args); - GPR_ASSERT(server); - gpr_free(args[0]); - if (arg_shift) gpr_free(args[1]); - gpr_free(args[2 + arg_shift]); - gpr_free(root); - - 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 *pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &g_mu); - g_pops = grpc_polling_entity_create_from_pollset(pollset); - - test_get(port); - test_post(port); - - grpc_httpcli_context_destroy(&exec_ctx, &g_context); - GRPC_CLOSURE_INIT(&destroyed, destroy_pops, &g_pops, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops), - &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - - gpr_free(grpc_polling_entity_pollset(&g_pops)); - - gpr_subprocess_destroy(server); - - return 0; -} diff --git a/test/core/http/httpscli_test.cc b/test/core/http/httpscli_test.cc new file mode 100644 index 0000000000..179b3a720b --- /dev/null +++ b/test/core/http/httpscli_test.cc @@ -0,0 +1,214 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/http/httpcli.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/iomgr.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 gpr_mu *g_mu; +static grpc_polling_entity g_pops; + +static grpc_millis n_seconds_time(int seconds) { + return grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(seconds)); +} + +static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + const char *expect = + "Hello world!" + "

This is a test

"; + grpc_http_response *response = static_cast(arg); + 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(g_mu); + g_done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&g_pops), NULL))); + gpr_mu_unlock(g_mu); +} + +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 = const_cast("foo.test.google.fr"); + req.http.path = const_cast("/get"); + req.handshaker = &grpc_httpcli_ssl; + + grpc_http_response response; + memset(&response, 0, sizeof(response)); + grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_get"); + grpc_httpcli_get( + &exec_ctx, &g_context, &g_pops, resource_quota, &req, n_seconds_time(15), + GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), + &response); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + gpr_mu_lock(g_mu); + while (!g_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &worker, n_seconds_time(1)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); + gpr_free(host); + grpc_http_response_destroy(&response); +} + +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 = const_cast("foo.test.google.fr"); + req.http.path = const_cast("/post"); + req.handshaker = &grpc_httpcli_ssl; + + grpc_http_response response; + memset(&response, 0, sizeof(response)); + grpc_resource_quota *resource_quota = grpc_resource_quota_create("test_post"); + grpc_httpcli_post( + &exec_ctx, &g_context, &g_pops, resource_quota, &req, "hello", 5, + n_seconds_time(15), + GRPC_CLOSURE_CREATE(on_finish, &response, grpc_schedule_on_exec_ctx), + &response); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + gpr_mu_lock(g_mu); + while (!g_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &worker, n_seconds_time(1)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); + gpr_free(host); + grpc_http_response_destroy(&response); +} + +static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { + grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset( + static_cast(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(); + int arg_shift = 0; + /* figure out where we are */ + char *root; + if (lslash) { + root = static_cast(gpr_malloc((size_t)(lslash - me + 1))); + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + root = gpr_strdup("."); + } + + GPR_ASSERT(argc <= 2); + if (argc == 2) { + args[0] = gpr_strdup(argv[1]); + } else { + arg_shift = 1; + gpr_asprintf(&args[0], "%s/../../tools/distrib/python_wrapper.sh", root); + gpr_asprintf(&args[1], "%s/../../test/core/http/test_server.py", root); + } + + /* start the server */ + args[1 + arg_shift] = const_cast("--port"); + gpr_asprintf(&args[2 + arg_shift], "%d", port); + args[3 + arg_shift] = const_cast("--ssl"); + server = gpr_subprocess_create(4 + arg_shift, (const char **)args); + GPR_ASSERT(server); + gpr_free(args[0]); + if (arg_shift) gpr_free(args[1]); + gpr_free(args[2 + arg_shift]); + gpr_free(root); + + 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 *pollset = + static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(pollset, &g_mu); + g_pops = grpc_polling_entity_create_from_pollset(pollset); + + test_get(port); + test_post(port); + + grpc_httpcli_context_destroy(&exec_ctx, &g_context); + GRPC_CLOSURE_INIT(&destroyed, destroy_pops, &g_pops, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops), + &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_free(grpc_polling_entity_pollset(&g_pops)); + + gpr_subprocess_destroy(server); + + return 0; +} diff --git a/test/core/http/parser_test.c b/test/core/http/parser_test.c deleted file mode 100644 index a7044c03bc..0000000000 --- a/test/core/http/parser_test.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/http/parser.h" - -#include -#include - -#include -#include -#include -#include -#include "test/core/util/slice_splitter.h" -#include "test/core/util/test_config.h" - -static void test_request_succeeds(grpc_slice_split_mode split_mode, - char *request_text, char *expect_method, - grpc_http_version expect_version, - char *expect_path, char *expect_body, ...) { - grpc_http_parser parser; - grpc_slice input_slice = grpc_slice_from_copied_string(request_text); - size_t num_slices; - size_t i; - grpc_slice *slices; - va_list args; - grpc_http_request request; - memset(&request, 0, sizeof(request)); - - grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); - grpc_slice_unref(input_slice); - - grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); - - for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == - GRPC_ERROR_NONE); - grpc_slice_unref(slices[i]); - } - GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); - - GPR_ASSERT(GRPC_HTTP_REQUEST == parser.type); - GPR_ASSERT(0 == strcmp(expect_method, request.method)); - GPR_ASSERT(0 == strcmp(expect_path, request.path)); - GPR_ASSERT(expect_version == request.version); - - if (expect_body != NULL) { - GPR_ASSERT(strlen(expect_body) == request.body_length); - GPR_ASSERT(0 == memcmp(expect_body, request.body, request.body_length)); - } else { - GPR_ASSERT(request.body_length == 0); - } - - va_start(args, expect_body); - i = 0; - for (;;) { - char *expect_key; - char *expect_value; - expect_key = va_arg(args, char *); - if (!expect_key) break; - GPR_ASSERT(i < request.hdr_count); - expect_value = va_arg(args, char *); - GPR_ASSERT(expect_value); - GPR_ASSERT(0 == strcmp(expect_key, request.hdrs[i].key)); - GPR_ASSERT(0 == strcmp(expect_value, request.hdrs[i].value)); - i++; - } - va_end(args); - GPR_ASSERT(i == request.hdr_count); - - grpc_http_request_destroy(&request); - grpc_http_parser_destroy(&parser); - gpr_free(slices); -} - -static void test_succeeds(grpc_slice_split_mode split_mode, char *response_text, - int expect_status, char *expect_body, ...) { - grpc_http_parser parser; - grpc_slice input_slice = grpc_slice_from_copied_string(response_text); - size_t num_slices; - size_t i; - grpc_slice *slices; - va_list args; - grpc_http_response response; - memset(&response, 0, sizeof(response)); - - grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); - grpc_slice_unref(input_slice); - - grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); - - for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == - GRPC_ERROR_NONE); - grpc_slice_unref(slices[i]); - } - GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); - - GPR_ASSERT(GRPC_HTTP_RESPONSE == parser.type); - GPR_ASSERT(expect_status == response.status); - if (expect_body != NULL) { - GPR_ASSERT(strlen(expect_body) == response.body_length); - GPR_ASSERT(0 == memcmp(expect_body, response.body, response.body_length)); - } else { - GPR_ASSERT(response.body_length == 0); - } - - va_start(args, expect_body); - i = 0; - for (;;) { - char *expect_key; - char *expect_value; - expect_key = va_arg(args, char *); - if (!expect_key) break; - GPR_ASSERT(i < response.hdr_count); - expect_value = va_arg(args, char *); - GPR_ASSERT(expect_value); - GPR_ASSERT(0 == strcmp(expect_key, response.hdrs[i].key)); - GPR_ASSERT(0 == strcmp(expect_value, response.hdrs[i].value)); - i++; - } - va_end(args); - GPR_ASSERT(i == response.hdr_count); - - grpc_http_response_destroy(&response); - grpc_http_parser_destroy(&parser); - gpr_free(slices); -} - -static void test_fails(grpc_slice_split_mode split_mode, char *response_text) { - grpc_http_parser parser; - grpc_slice input_slice = grpc_slice_from_copied_string(response_text); - size_t num_slices; - size_t i; - grpc_slice *slices; - grpc_error *error = GRPC_ERROR_NONE; - grpc_http_response response; - memset(&response, 0, sizeof(response)); - - grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); - grpc_slice_unref(input_slice); - - grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); - - for (i = 0; i < num_slices; i++) { - if (GRPC_ERROR_NONE == error) { - error = grpc_http_parser_parse(&parser, slices[i], NULL); - } - grpc_slice_unref(slices[i]); - } - if (GRPC_ERROR_NONE == error) { - error = grpc_http_parser_eof(&parser); - } - GPR_ASSERT(error != GRPC_ERROR_NONE); - GRPC_ERROR_UNREF(error); - - grpc_http_response_destroy(&response); - grpc_http_parser_destroy(&parser); - gpr_free(slices); -} - -static void test_request_fails(grpc_slice_split_mode split_mode, - char *request_text) { - grpc_http_parser parser; - grpc_slice input_slice = grpc_slice_from_copied_string(request_text); - size_t num_slices; - size_t i; - grpc_slice *slices; - grpc_error *error = GRPC_ERROR_NONE; - grpc_http_request request; - memset(&request, 0, sizeof(request)); - - grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); - grpc_slice_unref(input_slice); - - grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); - - for (i = 0; i < num_slices; i++) { - if (error == GRPC_ERROR_NONE) { - error = grpc_http_parser_parse(&parser, slices[i], NULL); - } - grpc_slice_unref(slices[i]); - } - if (error == GRPC_ERROR_NONE) { - error = grpc_http_parser_eof(&parser); - } - GPR_ASSERT(error != GRPC_ERROR_NONE); - GRPC_ERROR_UNREF(error); - - grpc_http_request_destroy(&request); - grpc_http_parser_destroy(&parser); - gpr_free(slices); -} - -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); - - for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) { - test_succeeds(split_modes[i], - "HTTP/1.0 200 OK\r\n" - "xyz: abc\r\n" - "\r\n" - "hello world!", - 200, "hello world!", "xyz", "abc", NULL); - test_succeeds(split_modes[i], - "HTTP/1.0 404 Not Found\r\n" - "\r\n", - 404, NULL, NULL); - test_succeeds(split_modes[i], - "HTTP/1.1 200 OK\r\n" - "xyz: abc\r\n" - "\r\n" - "hello world!", - 200, "hello world!", "xyz", "abc", NULL); - test_succeeds(split_modes[i], - "HTTP/1.1 200 OK\n" - "\n" - "abc", - 200, "abc", NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/1.0\r\n" - "\r\n", - "GET", GRPC_HTTP_HTTP10, "/", NULL, NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/1.0\r\n" - "\r\n" - "xyz", - "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/1.1\r\n" - "\r\n" - "xyz", - "GET", GRPC_HTTP_HTTP11, "/", "xyz", NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/2.0\r\n" - "\r\n" - "xyz", - "GET", GRPC_HTTP_HTTP20, "/", "xyz", NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/1.0\r\n" - "xyz: abc\r\n" - "\r\n" - "xyz", - "GET", GRPC_HTTP_HTTP10, "/", "xyz", "xyz", "abc", - NULL); - test_request_succeeds(split_modes[i], - "GET / HTTP/1.0\n" - "\n" - "xyz", - "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL); - test_fails(split_modes[i], "HTTP/1.0\r\n"); - test_fails(split_modes[i], "HTTP/1.2\r\n"); - test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n"); - 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!"); - test_request_fails(split_modes[i], "GET\r\n"); - test_request_fails(split_modes[i], "GET /\r\n"); - test_request_fails(split_modes[i], "GET / HTTP/0.0\r\n"); - test_request_fails(split_modes[i], "GET / ____/1.0\r\n"); - test_request_fails(split_modes[i], "GET / HTTP/1.2\r\n"); - test_request_fails(split_modes[i], "GET / HTTP/1.0\n"); - - tmp1 = gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); - memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1); - tmp1[2 * GRPC_HTTP_PARSER_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/http/parser_test.cc b/test/core/http/parser_test.cc new file mode 100644 index 0000000000..9eff49122c --- /dev/null +++ b/test/core/http/parser_test.cc @@ -0,0 +1,304 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/http/parser.h" + +#include +#include + +#include +#include +#include +#include +#include "test/core/util/slice_splitter.h" +#include "test/core/util/test_config.h" + +static void test_request_succeeds(grpc_slice_split_mode split_mode, + const char *request_text, + const char *expect_method, + grpc_http_version expect_version, + const char *expect_path, + const char *expect_body, ...) { + grpc_http_parser parser; + grpc_slice input_slice = grpc_slice_from_copied_string(request_text); + size_t num_slices; + size_t i; + grpc_slice *slices; + va_list args; + grpc_http_request request; + memset(&request, 0, sizeof(request)); + + grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); + grpc_slice_unref(input_slice); + + grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); + + for (i = 0; i < num_slices; i++) { + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == + GRPC_ERROR_NONE); + grpc_slice_unref(slices[i]); + } + GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); + + GPR_ASSERT(GRPC_HTTP_REQUEST == parser.type); + GPR_ASSERT(0 == strcmp(expect_method, request.method)); + GPR_ASSERT(0 == strcmp(expect_path, request.path)); + GPR_ASSERT(expect_version == request.version); + + if (expect_body != NULL) { + GPR_ASSERT(strlen(expect_body) == request.body_length); + GPR_ASSERT(0 == memcmp(expect_body, request.body, request.body_length)); + } else { + GPR_ASSERT(request.body_length == 0); + } + + va_start(args, expect_body); + i = 0; + for (;;) { + char *expect_key; + char *expect_value; + expect_key = va_arg(args, char *); + if (!expect_key) break; + GPR_ASSERT(i < request.hdr_count); + expect_value = va_arg(args, char *); + GPR_ASSERT(expect_value); + GPR_ASSERT(0 == strcmp(expect_key, request.hdrs[i].key)); + GPR_ASSERT(0 == strcmp(expect_value, request.hdrs[i].value)); + i++; + } + va_end(args); + GPR_ASSERT(i == request.hdr_count); + + grpc_http_request_destroy(&request); + grpc_http_parser_destroy(&parser); + gpr_free(slices); +} + +static void test_succeeds(grpc_slice_split_mode split_mode, + const char *response_text, int expect_status, + const char *expect_body, ...) { + grpc_http_parser parser; + grpc_slice input_slice = grpc_slice_from_copied_string(response_text); + size_t num_slices; + size_t i; + grpc_slice *slices; + va_list args; + grpc_http_response response; + memset(&response, 0, sizeof(response)); + + grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); + grpc_slice_unref(input_slice); + + grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); + + for (i = 0; i < num_slices; i++) { + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == + GRPC_ERROR_NONE); + grpc_slice_unref(slices[i]); + } + GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); + + GPR_ASSERT(GRPC_HTTP_RESPONSE == parser.type); + GPR_ASSERT(expect_status == response.status); + if (expect_body != NULL) { + GPR_ASSERT(strlen(expect_body) == response.body_length); + GPR_ASSERT(0 == memcmp(expect_body, response.body, response.body_length)); + } else { + GPR_ASSERT(response.body_length == 0); + } + + va_start(args, expect_body); + i = 0; + for (;;) { + char *expect_key; + char *expect_value; + expect_key = va_arg(args, char *); + if (!expect_key) break; + GPR_ASSERT(i < response.hdr_count); + expect_value = va_arg(args, char *); + GPR_ASSERT(expect_value); + GPR_ASSERT(0 == strcmp(expect_key, response.hdrs[i].key)); + GPR_ASSERT(0 == strcmp(expect_value, response.hdrs[i].value)); + i++; + } + va_end(args); + GPR_ASSERT(i == response.hdr_count); + + grpc_http_response_destroy(&response); + grpc_http_parser_destroy(&parser); + gpr_free(slices); +} + +static void test_fails(grpc_slice_split_mode split_mode, + const char *response_text) { + grpc_http_parser parser; + grpc_slice input_slice = grpc_slice_from_copied_string(response_text); + size_t num_slices; + size_t i; + grpc_slice *slices; + grpc_error *error = GRPC_ERROR_NONE; + grpc_http_response response; + memset(&response, 0, sizeof(response)); + + grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); + grpc_slice_unref(input_slice); + + grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); + + for (i = 0; i < num_slices; i++) { + if (GRPC_ERROR_NONE == error) { + error = grpc_http_parser_parse(&parser, slices[i], NULL); + } + grpc_slice_unref(slices[i]); + } + if (GRPC_ERROR_NONE == error) { + error = grpc_http_parser_eof(&parser); + } + GPR_ASSERT(error != GRPC_ERROR_NONE); + GRPC_ERROR_UNREF(error); + + grpc_http_response_destroy(&response); + grpc_http_parser_destroy(&parser); + gpr_free(slices); +} + +static void test_request_fails(grpc_slice_split_mode split_mode, + const char *request_text) { + grpc_http_parser parser; + grpc_slice input_slice = grpc_slice_from_copied_string(request_text); + size_t num_slices; + size_t i; + grpc_slice *slices; + grpc_error *error = GRPC_ERROR_NONE; + grpc_http_request request; + memset(&request, 0, sizeof(request)); + + grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); + grpc_slice_unref(input_slice); + + grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); + + for (i = 0; i < num_slices; i++) { + if (error == GRPC_ERROR_NONE) { + error = grpc_http_parser_parse(&parser, slices[i], NULL); + } + grpc_slice_unref(slices[i]); + } + if (error == GRPC_ERROR_NONE) { + error = grpc_http_parser_eof(&parser); + } + GPR_ASSERT(error != GRPC_ERROR_NONE); + GRPC_ERROR_UNREF(error); + + grpc_http_request_destroy(&request); + grpc_http_parser_destroy(&parser); + gpr_free(slices); +} + +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); + + for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) { + test_succeeds(split_modes[i], + "HTTP/1.0 200 OK\r\n" + "xyz: abc\r\n" + "\r\n" + "hello world!", + 200, "hello world!", "xyz", "abc", NULL); + test_succeeds(split_modes[i], + "HTTP/1.0 404 Not Found\r\n" + "\r\n", + 404, NULL, NULL); + test_succeeds(split_modes[i], + "HTTP/1.1 200 OK\r\n" + "xyz: abc\r\n" + "\r\n" + "hello world!", + 200, "hello world!", "xyz", "abc", NULL); + test_succeeds(split_modes[i], + "HTTP/1.1 200 OK\n" + "\n" + "abc", + 200, "abc", NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/1.0\r\n" + "\r\n", + "GET", GRPC_HTTP_HTTP10, "/", NULL, NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/1.0\r\n" + "\r\n" + "xyz", + "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/1.1\r\n" + "\r\n" + "xyz", + "GET", GRPC_HTTP_HTTP11, "/", "xyz", NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/2.0\r\n" + "\r\n" + "xyz", + "GET", GRPC_HTTP_HTTP20, "/", "xyz", NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/1.0\r\n" + "xyz: abc\r\n" + "\r\n" + "xyz", + "GET", GRPC_HTTP_HTTP10, "/", "xyz", "xyz", "abc", + NULL); + test_request_succeeds(split_modes[i], + "GET / HTTP/1.0\n" + "\n" + "xyz", + "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL); + test_fails(split_modes[i], "HTTP/1.0\r\n"); + test_fails(split_modes[i], "HTTP/1.2\r\n"); + test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n"); + 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!"); + test_request_fails(split_modes[i], "GET\r\n"); + test_request_fails(split_modes[i], "GET /\r\n"); + test_request_fails(split_modes[i], "GET / HTTP/0.0\r\n"); + test_request_fails(split_modes[i], "GET / ____/1.0\r\n"); + test_request_fails(split_modes[i], "GET / HTTP/1.2\r\n"); + test_request_fails(split_modes[i], "GET / HTTP/1.0\n"); + + tmp1 = + static_cast(gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH)); + memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1); + tmp1[2 * GRPC_HTTP_PARSER_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/http/request_fuzzer.c b/test/core/http/request_fuzzer.c deleted file mode 100644 index aefe9eb0f9..0000000000 --- a/test/core/http/request_fuzzer.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include - -#include "src/core/lib/http/parser.h" - -bool squelch = true; -bool leak_check = true; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_http_parser parser; - grpc_http_request request; - memset(&request, 0, sizeof(request)); - grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); - grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); - GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); - GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); - grpc_slice_unref(slice); - grpc_http_parser_destroy(&parser); - grpc_http_request_destroy(&request); - return 0; -} diff --git a/test/core/http/request_fuzzer.cc b/test/core/http/request_fuzzer.cc new file mode 100644 index 0000000000..aefe9eb0f9 --- /dev/null +++ b/test/core/http/request_fuzzer.cc @@ -0,0 +1,42 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include + +#include "src/core/lib/http/parser.h" + +bool squelch = true; +bool leak_check = true; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_http_parser parser; + grpc_http_request request; + memset(&request, 0, sizeof(request)); + grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); + grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); + GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); + GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); + grpc_slice_unref(slice); + grpc_http_parser_destroy(&parser); + grpc_http_request_destroy(&request); + return 0; +} diff --git a/test/core/http/response_fuzzer.c b/test/core/http/response_fuzzer.c deleted file mode 100644 index d5bb67500d..0000000000 --- a/test/core/http/response_fuzzer.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include - -#include "src/core/lib/http/parser.h" - -bool squelch = true; -bool leak_check = true; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_http_parser parser; - grpc_http_response response; - memset(&response, 0, sizeof(response)); - grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); - grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); - GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); - GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); - grpc_slice_unref(slice); - grpc_http_parser_destroy(&parser); - grpc_http_response_destroy(&response); - return 0; -} diff --git a/test/core/http/response_fuzzer.cc b/test/core/http/response_fuzzer.cc new file mode 100644 index 0000000000..d5bb67500d --- /dev/null +++ b/test/core/http/response_fuzzer.cc @@ -0,0 +1,41 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include + +#include "src/core/lib/http/parser.h" + +bool squelch = true; +bool leak_check = true; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_http_parser parser; + grpc_http_response response; + memset(&response, 0, sizeof(response)); + grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); + grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); + GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); + GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); + grpc_slice_unref(slice); + grpc_http_parser_destroy(&parser); + grpc_http_response_destroy(&response); + return 0; +} diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c deleted file mode 100644 index 38f512de0e..0000000000 --- a/test/core/iomgr/combiner_test.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/combiner.h" - -#include -#include -#include -#include -#include - -#include "test/core/util/test_config.h" - -static void test_no_op(void) { - gpr_log(GPR_DEBUG, "test_no_op"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_COMBINER_UNREF(&exec_ctx, grpc_combiner_create(), "test_no_op"); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void set_event_to_true(grpc_exec_ctx *exec_ctx, void *value, - grpc_error *error) { - gpr_event_set(value, (void *)1); -} - -static void test_execute_one(void) { - gpr_log(GPR_DEBUG, "test_execute_one"); - - grpc_combiner *lock = grpc_combiner_create(); - gpr_event done; - gpr_event_init(&done); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_CLOSURE_SCHED(&exec_ctx, - GRPC_CLOSURE_CREATE(set_event_to_true, &done, - grpc_combiner_scheduler(lock)), - GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&done, grpc_timeout_seconds_to_deadline(5)) != - NULL); - GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_one"); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - size_t ctr; - grpc_combiner *lock; - gpr_event done; -} thd_args; - -typedef struct { - size_t *ctr; - size_t value; -} ex_args; - -static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { - ex_args *args = a; - GPR_ASSERT(*args->ctr == args->value - 1); - *args->ctr = args->value; - gpr_free(a); -} - -static void execute_many_loop(void *a) { - thd_args *args = a; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - size_t n = 1; - for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 10000; j++) { - ex_args *c = gpr_malloc(sizeof(*c)); - c->ctr = &args->ctr; - c->value = n++; - GRPC_CLOSURE_SCHED(&exec_ctx, - GRPC_CLOSURE_CREATE( - check_one, c, grpc_combiner_scheduler(args->lock)), - GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - } - // sleep for a little bit, to test a combiner draining and another thread - // picking it up - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); - } - GRPC_CLOSURE_SCHED(&exec_ctx, - GRPC_CLOSURE_CREATE(set_event_to_true, &args->done, - grpc_combiner_scheduler(args->lock)), - GRPC_ERROR_NONE); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_execute_many(void) { - gpr_log(GPR_DEBUG, "test_execute_many"); - - grpc_combiner *lock = grpc_combiner_create(); - gpr_thd_id thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].lock = lock; - gpr_event_init(&ta[i].done); - GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); - } - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - GPR_ASSERT(gpr_event_wait(&ta[i].done, - gpr_inf_future(GPR_CLOCK_REALTIME)) != NULL); - gpr_thd_join(thds[i]); - } - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_many"); - grpc_exec_ctx_finish(&exec_ctx); -} - -static gpr_event got_in_finally; - -static void in_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - gpr_event_set(&got_in_finally, (void *)1); -} - -static void add_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GRPC_CLOSURE_SCHED(exec_ctx, - GRPC_CLOSURE_CREATE(in_finally, arg, - grpc_combiner_finally_scheduler(arg)), - GRPC_ERROR_NONE); -} - -static void test_execute_finally(void) { - gpr_log(GPR_DEBUG, "test_execute_finally"); - - grpc_combiner *lock = grpc_combiner_create(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_event_init(&got_in_finally); - GRPC_CLOSURE_SCHED( - &exec_ctx, - GRPC_CLOSURE_CREATE(add_finally, lock, grpc_combiner_scheduler(lock)), - GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&got_in_finally, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_finally"); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_no_op(); - test_execute_one(); - test_execute_finally(); - test_execute_many(); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/iomgr/combiner_test.cc b/test/core/iomgr/combiner_test.cc new file mode 100644 index 0000000000..7d2d098d2b --- /dev/null +++ b/test/core/iomgr/combiner_test.cc @@ -0,0 +1,168 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/combiner.h" + +#include +#include +#include +#include +#include + +#include "test/core/util/test_config.h" + +static void test_no_op(void) { + gpr_log(GPR_DEBUG, "test_no_op"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_COMBINER_UNREF(&exec_ctx, grpc_combiner_create(), "test_no_op"); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void set_event_to_true(grpc_exec_ctx *exec_ctx, void *value, + grpc_error *error) { + gpr_event_set(static_cast(value), (void *)1); +} + +static void test_execute_one(void) { + gpr_log(GPR_DEBUG, "test_execute_one"); + + grpc_combiner *lock = grpc_combiner_create(); + gpr_event done; + gpr_event_init(&done); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_CLOSURE_SCHED(&exec_ctx, + GRPC_CLOSURE_CREATE(set_event_to_true, &done, + grpc_combiner_scheduler(lock)), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&done, grpc_timeout_seconds_to_deadline(5)) != + NULL); + GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_one"); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + size_t ctr; + grpc_combiner *lock; + gpr_event done; +} thd_args; + +typedef struct { + size_t *ctr; + size_t value; +} ex_args; + +static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { + ex_args *args = static_cast(a); + GPR_ASSERT(*args->ctr == args->value - 1); + *args->ctr = args->value; + gpr_free(a); +} + +static void execute_many_loop(void *a) { + thd_args *args = static_cast(a); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + size_t n = 1; + for (size_t i = 0; i < 10; i++) { + for (size_t j = 0; j < 10000; j++) { + ex_args *c = static_cast(gpr_malloc(sizeof(*c))); + c->ctr = &args->ctr; + c->value = n++; + GRPC_CLOSURE_SCHED(&exec_ctx, + GRPC_CLOSURE_CREATE( + check_one, c, grpc_combiner_scheduler(args->lock)), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + } + // sleep for a little bit, to test a combiner draining and another thread + // picking it up + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); + } + GRPC_CLOSURE_SCHED(&exec_ctx, + GRPC_CLOSURE_CREATE(set_event_to_true, &args->done, + grpc_combiner_scheduler(args->lock)), + GRPC_ERROR_NONE); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_execute_many(void) { + gpr_log(GPR_DEBUG, "test_execute_many"); + + grpc_combiner *lock = grpc_combiner_create(); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].lock = lock; + gpr_event_init(&ta[i].done); + GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); + } + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + GPR_ASSERT(gpr_event_wait(&ta[i].done, + gpr_inf_future(GPR_CLOCK_REALTIME)) != NULL); + gpr_thd_join(thds[i]); + } + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_many"); + grpc_exec_ctx_finish(&exec_ctx); +} + +static gpr_event got_in_finally; + +static void in_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + gpr_event_set(&got_in_finally, (void *)1); +} + +static void add_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GRPC_CLOSURE_SCHED( + exec_ctx, GRPC_CLOSURE_CREATE(in_finally, arg, + grpc_combiner_finally_scheduler( + static_cast(arg))), + GRPC_ERROR_NONE); +} + +static void test_execute_finally(void) { + gpr_log(GPR_DEBUG, "test_execute_finally"); + + grpc_combiner *lock = grpc_combiner_create(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_event_init(&got_in_finally); + GRPC_CLOSURE_SCHED( + &exec_ctx, + GRPC_CLOSURE_CREATE(add_finally, lock, grpc_combiner_scheduler(lock)), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&got_in_finally, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_finally"); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_no_op(); + test_execute_one(); + test_execute_finally(); + test_execute_many(); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c deleted file mode 100644 index f2ce3d0d12..0000000000 --- a/test/core/iomgr/endpoint_pair_test.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/endpoint_pair.h" -#include -#include -#include -#include -#include -#include "test/core/iomgr/endpoint_tests.h" -#include "test/core/util/test_config.h" - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; - -static void clean_up(void) {} - -static grpc_endpoint_test_fixture create_fixture_endpoint_pair( - size_t slice_size) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_test_fixture f; - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - grpc_endpoint_pair p = grpc_iomgr_create_endpoint_pair("test", &args); - - f.client_ep = p.client; - f.server_ep = p.server; - grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); - grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset); - grpc_exec_ctx_finish(&exec_ctx); - - return f; -} - -static grpc_endpoint_test_config configs[] = { - {"tcp/tcp_socketpair", create_fixture_endpoint_pair, clean_up}, -}; - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - grpc_endpoint_tests(configs[0], g_pollset, g_mu); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(g_pollset); - - return 0; -} diff --git a/test/core/iomgr/endpoint_pair_test.cc b/test/core/iomgr/endpoint_pair_test.cc new file mode 100644 index 0000000000..c7ce6c0419 --- /dev/null +++ b/test/core/iomgr/endpoint_pair_test.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/endpoint_pair.h" +#include +#include +#include +#include +#include +#include "test/core/iomgr/endpoint_tests.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; + +static void clean_up(void) {} + +static grpc_endpoint_test_fixture create_fixture_endpoint_pair( + size_t slice_size) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_test_fixture f; + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + grpc_endpoint_pair p = grpc_iomgr_create_endpoint_pair("test", &args); + + f.client_ep = p.client; + f.server_ep = p.server; + grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); + grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset); + grpc_exec_ctx_finish(&exec_ctx); + + return f; +} + +static grpc_endpoint_test_config configs[] = { + {"tcp/tcp_socketpair", create_fixture_endpoint_pair, clean_up}, +}; + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(g_pollset, &g_mu); + grpc_endpoint_tests(configs[0], g_pollset, g_mu); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + + return 0; +} diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c deleted file mode 100644 index 61e901f645..0000000000 --- a/test/core/iomgr/endpoint_tests.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/iomgr/endpoint_tests.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -/* - General test notes: - - All tests which write data into an endpoint write i%256 into byte i, which - is verified by readers. - - In general there are a few interesting things to vary which may lead to - exercising different codepaths in an implementation: - 1. Total amount of data written to the endpoint - 2. Size of slice allocations - 3. Amount of data we read from or write to the endpoint at once - - The tests here tend to parameterize these where applicable. - -*/ - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; - -size_t count_slices(grpc_slice *slices, size_t nslices, int *current_data) { - size_t num_bytes = 0; - size_t i; - size_t j; - unsigned char *buf; - for (i = 0; i < nslices; ++i) { - buf = GRPC_SLICE_START_PTR(slices[i]); - for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { - GPR_ASSERT(buf[j] == *current_data); - *current_data = (*current_data + 1) % 256; - } - num_bytes += GRPC_SLICE_LENGTH(slices[i]); - } - return num_bytes; -} - -static grpc_endpoint_test_fixture begin_test(grpc_endpoint_test_config config, - const char *test_name, - size_t slice_size) { - gpr_log(GPR_INFO, "%s/%s", test_name, config.name); - return config.create_fixture(slice_size); -} - -static void end_test(grpc_endpoint_test_config config) { config.clean_up(); } - -static grpc_slice *allocate_blocks(size_t num_bytes, size_t slice_size, - size_t *num_blocks, uint8_t *current_data) { - size_t nslices = num_bytes / slice_size + (num_bytes % slice_size ? 1 : 0); - grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices); - size_t num_bytes_left = num_bytes; - size_t i; - size_t j; - unsigned char *buf; - *num_blocks = nslices; - - for (i = 0; i < nslices; ++i) { - slices[i] = grpc_slice_malloc(slice_size > num_bytes_left ? num_bytes_left - : slice_size); - num_bytes_left -= GRPC_SLICE_LENGTH(slices[i]); - buf = GRPC_SLICE_START_PTR(slices[i]); - for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { - buf[j] = *current_data; - (*current_data)++; - } - } - GPR_ASSERT(num_bytes_left == 0); - return slices; -} - -struct read_and_write_test_state { - grpc_endpoint *read_ep; - grpc_endpoint *write_ep; - size_t target_bytes; - size_t bytes_read; - size_t current_write_size; - size_t bytes_written; - int current_read_data; - uint8_t current_write_data; - int read_done; - int write_done; - grpc_slice_buffer incoming; - grpc_slice_buffer outgoing; - grpc_closure done_read; - grpc_closure done_write; -}; - -static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx, - void *data, grpc_error *error) { - struct read_and_write_test_state *state = - (struct read_and_write_test_state *)data; - - state->bytes_read += count_slices( - state->incoming.slices, state->incoming.count, &state->current_read_data); - if (state->bytes_read == state->target_bytes || error != GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Read handler done"); - gpr_mu_lock(g_mu); - state->read_done = 1 + (error == GRPC_ERROR_NONE); - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL)); - gpr_mu_unlock(g_mu); - } else if (error == GRPC_ERROR_NONE) { - grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming, - &state->done_read); - } -} - -static void read_and_write_test_write_handler(grpc_exec_ctx *exec_ctx, - void *data, grpc_error *error) { - struct read_and_write_test_state *state = - (struct read_and_write_test_state *)data; - grpc_slice *slices = NULL; - size_t nslices; - - if (error == GRPC_ERROR_NONE) { - state->bytes_written += state->current_write_size; - if (state->target_bytes - state->bytes_written < - state->current_write_size) { - state->current_write_size = state->target_bytes - state->bytes_written; - } - if (state->current_write_size != 0) { - slices = allocate_blocks(state->current_write_size, 8192, &nslices, - &state->current_write_data); - grpc_slice_buffer_reset_and_unref(&state->outgoing); - grpc_slice_buffer_addn(&state->outgoing, slices, nslices); - grpc_endpoint_write(exec_ctx, state->write_ep, &state->outgoing, - &state->done_write); - gpr_free(slices); - return; - } - } - - gpr_log(GPR_INFO, "Write handler done"); - gpr_mu_lock(g_mu); - state->write_done = 1 + (error == GRPC_ERROR_NONE); - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL)); - gpr_mu_unlock(g_mu); -} - -/* Do both reading and writing using the grpc_endpoint API. - - This also includes a test of the shutdown behavior. - */ -static void read_and_write_test(grpc_endpoint_test_config config, - size_t num_bytes, size_t write_size, - size_t slice_size, bool shutdown) { - struct read_and_write_test_state state; - grpc_endpoint_test_fixture f = - begin_test(config, "read_and_write_test", slice_size); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); - gpr_log(GPR_DEBUG, "num_bytes=%" PRIuPTR " write_size=%" PRIuPTR - " slice_size=%" PRIuPTR " shutdown=%d", - num_bytes, write_size, slice_size, shutdown); - - if (shutdown) { - gpr_log(GPR_INFO, "Start read and write shutdown test"); - } else { - gpr_log(GPR_INFO, "Start read and write test with %" PRIuPTR - " bytes, slice size %" PRIuPTR, - num_bytes, slice_size); - } - - state.read_ep = f.client_ep; - state.write_ep = f.server_ep; - state.target_bytes = num_bytes; - state.bytes_read = 0; - state.current_write_size = write_size; - state.bytes_written = 0; - state.read_done = 0; - state.write_done = 0; - state.current_read_data = 0; - state.current_write_data = 0; - GRPC_CLOSURE_INIT(&state.done_read, read_and_write_test_read_handler, &state, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&state.done_write, read_and_write_test_write_handler, - &state, grpc_schedule_on_exec_ctx); - grpc_slice_buffer_init(&state.outgoing); - grpc_slice_buffer_init(&state.incoming); - - /* Get started by pretending an initial write completed */ - /* NOTE: Sets up initial conditions so we can have the same write handler - for the first iteration as for later iterations. It does the right thing - even when bytes_written is unsigned. */ - state.bytes_written -= state.current_write_size; - read_and_write_test_write_handler(&exec_ctx, &state, GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_endpoint_read(&exec_ctx, state.read_ep, &state.incoming, - &state.done_read); - - if (shutdown) { - gpr_log(GPR_DEBUG, "shutdown read"); - grpc_endpoint_shutdown( - &exec_ctx, state.read_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - gpr_log(GPR_DEBUG, "shutdown write"); - grpc_endpoint_shutdown( - &exec_ctx, state.write_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - } - grpc_exec_ctx_flush(&exec_ctx); - - gpr_mu_lock(g_mu); - while (!state.read_done || !state.write_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(grpc_exec_ctx_now(&exec_ctx) < deadline); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - } - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - - end_test(config); - grpc_slice_buffer_destroy_internal(&exec_ctx, &state.outgoing); - grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); - grpc_endpoint_destroy(&exec_ctx, state.read_ep); - grpc_endpoint_destroy(&exec_ctx, state.write_ep); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void inc_on_failure(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - gpr_mu_lock(g_mu); - *(int *)arg += (error != GRPC_ERROR_NONE); - GPR_ASSERT( - GRPC_LOG_IF_ERROR("kick", grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void wait_for_fail_count(grpc_exec_ctx *exec_ctx, int *fail_count, - int want_fail_count) { - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(g_mu); - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); - while (grpc_exec_ctx_now(exec_ctx) < deadline && - *fail_count < want_fail_count) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(exec_ctx, g_pollset, &worker, deadline))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(*fail_count == want_fail_count); - gpr_mu_unlock(g_mu); -} - -static void multiple_shutdown_test(grpc_endpoint_test_config config) { - grpc_endpoint_test_fixture f = - begin_test(config, "multiple_shutdown_test", 128); - int fail_count = 0; - - grpc_slice_buffer slice_buffer; - grpc_slice_buffer_init(&slice_buffer); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); - grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, - GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, - grpc_schedule_on_exec_ctx)); - wait_for_fail_count(&exec_ctx, &fail_count, 0); - grpc_endpoint_shutdown(&exec_ctx, f.client_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - wait_for_fail_count(&exec_ctx, &fail_count, 1); - grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, - GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, - grpc_schedule_on_exec_ctx)); - wait_for_fail_count(&exec_ctx, &fail_count, 2); - grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a")); - grpc_endpoint_write(&exec_ctx, f.client_ep, &slice_buffer, - GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, - grpc_schedule_on_exec_ctx)); - wait_for_fail_count(&exec_ctx, &fail_count, 3); - grpc_endpoint_shutdown(&exec_ctx, f.client_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); - wait_for_fail_count(&exec_ctx, &fail_count, 3); - - grpc_slice_buffer_destroy_internal(&exec_ctx, &slice_buffer); - - grpc_endpoint_destroy(&exec_ctx, f.client_ep); - grpc_endpoint_destroy(&exec_ctx, f.server_ep); - grpc_exec_ctx_finish(&exec_ctx); -} - -void grpc_endpoint_tests(grpc_endpoint_test_config config, - grpc_pollset *pollset, gpr_mu *mu) { - size_t i; - g_pollset = pollset; - g_mu = mu; - multiple_shutdown_test(config); - read_and_write_test(config, 10000000, 100000, 8192, false); - read_and_write_test(config, 1000000, 100000, 1, false); - read_and_write_test(config, 100000000, 100000, 1, true); - for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { - read_and_write_test(config, 40320, i, i, false); - } - g_pollset = NULL; - g_mu = NULL; -} diff --git a/test/core/iomgr/endpoint_tests.cc b/test/core/iomgr/endpoint_tests.cc new file mode 100644 index 0000000000..61e901f645 --- /dev/null +++ b/test/core/iomgr/endpoint_tests.cc @@ -0,0 +1,335 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/iomgr/endpoint_tests.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +/* + General test notes: + + All tests which write data into an endpoint write i%256 into byte i, which + is verified by readers. + + In general there are a few interesting things to vary which may lead to + exercising different codepaths in an implementation: + 1. Total amount of data written to the endpoint + 2. Size of slice allocations + 3. Amount of data we read from or write to the endpoint at once + + The tests here tend to parameterize these where applicable. + +*/ + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; + +size_t count_slices(grpc_slice *slices, size_t nslices, int *current_data) { + size_t num_bytes = 0; + size_t i; + size_t j; + unsigned char *buf; + for (i = 0; i < nslices; ++i) { + buf = GRPC_SLICE_START_PTR(slices[i]); + for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { + GPR_ASSERT(buf[j] == *current_data); + *current_data = (*current_data + 1) % 256; + } + num_bytes += GRPC_SLICE_LENGTH(slices[i]); + } + return num_bytes; +} + +static grpc_endpoint_test_fixture begin_test(grpc_endpoint_test_config config, + const char *test_name, + size_t slice_size) { + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + return config.create_fixture(slice_size); +} + +static void end_test(grpc_endpoint_test_config config) { config.clean_up(); } + +static grpc_slice *allocate_blocks(size_t num_bytes, size_t slice_size, + size_t *num_blocks, uint8_t *current_data) { + size_t nslices = num_bytes / slice_size + (num_bytes % slice_size ? 1 : 0); + grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices); + size_t num_bytes_left = num_bytes; + size_t i; + size_t j; + unsigned char *buf; + *num_blocks = nslices; + + for (i = 0; i < nslices; ++i) { + slices[i] = grpc_slice_malloc(slice_size > num_bytes_left ? num_bytes_left + : slice_size); + num_bytes_left -= GRPC_SLICE_LENGTH(slices[i]); + buf = GRPC_SLICE_START_PTR(slices[i]); + for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { + buf[j] = *current_data; + (*current_data)++; + } + } + GPR_ASSERT(num_bytes_left == 0); + return slices; +} + +struct read_and_write_test_state { + grpc_endpoint *read_ep; + grpc_endpoint *write_ep; + size_t target_bytes; + size_t bytes_read; + size_t current_write_size; + size_t bytes_written; + int current_read_data; + uint8_t current_write_data; + int read_done; + int write_done; + grpc_slice_buffer incoming; + grpc_slice_buffer outgoing; + grpc_closure done_read; + grpc_closure done_write; +}; + +static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx, + void *data, grpc_error *error) { + struct read_and_write_test_state *state = + (struct read_and_write_test_state *)data; + + state->bytes_read += count_slices( + state->incoming.slices, state->incoming.count, &state->current_read_data); + if (state->bytes_read == state->target_bytes || error != GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Read handler done"); + gpr_mu_lock(g_mu); + state->read_done = 1 + (error == GRPC_ERROR_NONE); + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL)); + gpr_mu_unlock(g_mu); + } else if (error == GRPC_ERROR_NONE) { + grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming, + &state->done_read); + } +} + +static void read_and_write_test_write_handler(grpc_exec_ctx *exec_ctx, + void *data, grpc_error *error) { + struct read_and_write_test_state *state = + (struct read_and_write_test_state *)data; + grpc_slice *slices = NULL; + size_t nslices; + + if (error == GRPC_ERROR_NONE) { + state->bytes_written += state->current_write_size; + if (state->target_bytes - state->bytes_written < + state->current_write_size) { + state->current_write_size = state->target_bytes - state->bytes_written; + } + if (state->current_write_size != 0) { + slices = allocate_blocks(state->current_write_size, 8192, &nslices, + &state->current_write_data); + grpc_slice_buffer_reset_and_unref(&state->outgoing); + grpc_slice_buffer_addn(&state->outgoing, slices, nslices); + grpc_endpoint_write(exec_ctx, state->write_ep, &state->outgoing, + &state->done_write); + gpr_free(slices); + return; + } + } + + gpr_log(GPR_INFO, "Write handler done"); + gpr_mu_lock(g_mu); + state->write_done = 1 + (error == GRPC_ERROR_NONE); + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL)); + gpr_mu_unlock(g_mu); +} + +/* Do both reading and writing using the grpc_endpoint API. + + This also includes a test of the shutdown behavior. + */ +static void read_and_write_test(grpc_endpoint_test_config config, + size_t num_bytes, size_t write_size, + size_t slice_size, bool shutdown) { + struct read_and_write_test_state state; + grpc_endpoint_test_fixture f = + begin_test(config, "read_and_write_test", slice_size); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); + gpr_log(GPR_DEBUG, "num_bytes=%" PRIuPTR " write_size=%" PRIuPTR + " slice_size=%" PRIuPTR " shutdown=%d", + num_bytes, write_size, slice_size, shutdown); + + if (shutdown) { + gpr_log(GPR_INFO, "Start read and write shutdown test"); + } else { + gpr_log(GPR_INFO, "Start read and write test with %" PRIuPTR + " bytes, slice size %" PRIuPTR, + num_bytes, slice_size); + } + + state.read_ep = f.client_ep; + state.write_ep = f.server_ep; + state.target_bytes = num_bytes; + state.bytes_read = 0; + state.current_write_size = write_size; + state.bytes_written = 0; + state.read_done = 0; + state.write_done = 0; + state.current_read_data = 0; + state.current_write_data = 0; + GRPC_CLOSURE_INIT(&state.done_read, read_and_write_test_read_handler, &state, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&state.done_write, read_and_write_test_write_handler, + &state, grpc_schedule_on_exec_ctx); + grpc_slice_buffer_init(&state.outgoing); + grpc_slice_buffer_init(&state.incoming); + + /* Get started by pretending an initial write completed */ + /* NOTE: Sets up initial conditions so we can have the same write handler + for the first iteration as for later iterations. It does the right thing + even when bytes_written is unsigned. */ + state.bytes_written -= state.current_write_size; + read_and_write_test_write_handler(&exec_ctx, &state, GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_endpoint_read(&exec_ctx, state.read_ep, &state.incoming, + &state.done_read); + + if (shutdown) { + gpr_log(GPR_DEBUG, "shutdown read"); + grpc_endpoint_shutdown( + &exec_ctx, state.read_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + gpr_log(GPR_DEBUG, "shutdown write"); + grpc_endpoint_shutdown( + &exec_ctx, state.write_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + } + grpc_exec_ctx_flush(&exec_ctx); + + gpr_mu_lock(g_mu); + while (!state.read_done || !state.write_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(grpc_exec_ctx_now(&exec_ctx) < deadline); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + } + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + + end_test(config); + grpc_slice_buffer_destroy_internal(&exec_ctx, &state.outgoing); + grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); + grpc_endpoint_destroy(&exec_ctx, state.read_ep); + grpc_endpoint_destroy(&exec_ctx, state.write_ep); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void inc_on_failure(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + gpr_mu_lock(g_mu); + *(int *)arg += (error != GRPC_ERROR_NONE); + GPR_ASSERT( + GRPC_LOG_IF_ERROR("kick", grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void wait_for_fail_count(grpc_exec_ctx *exec_ctx, int *fail_count, + int want_fail_count) { + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(g_mu); + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); + while (grpc_exec_ctx_now(exec_ctx) < deadline && + *fail_count < want_fail_count) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(exec_ctx, g_pollset, &worker, deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(*fail_count == want_fail_count); + gpr_mu_unlock(g_mu); +} + +static void multiple_shutdown_test(grpc_endpoint_test_config config) { + grpc_endpoint_test_fixture f = + begin_test(config, "multiple_shutdown_test", 128); + int fail_count = 0; + + grpc_slice_buffer slice_buffer; + grpc_slice_buffer_init(&slice_buffer); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); + grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, + GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, + grpc_schedule_on_exec_ctx)); + wait_for_fail_count(&exec_ctx, &fail_count, 0); + grpc_endpoint_shutdown(&exec_ctx, f.client_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + wait_for_fail_count(&exec_ctx, &fail_count, 1); + grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, + GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, + grpc_schedule_on_exec_ctx)); + wait_for_fail_count(&exec_ctx, &fail_count, 2); + grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a")); + grpc_endpoint_write(&exec_ctx, f.client_ep, &slice_buffer, + GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, + grpc_schedule_on_exec_ctx)); + wait_for_fail_count(&exec_ctx, &fail_count, 3); + grpc_endpoint_shutdown(&exec_ctx, f.client_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); + wait_for_fail_count(&exec_ctx, &fail_count, 3); + + grpc_slice_buffer_destroy_internal(&exec_ctx, &slice_buffer); + + grpc_endpoint_destroy(&exec_ctx, f.client_ep); + grpc_endpoint_destroy(&exec_ctx, f.server_ep); + grpc_exec_ctx_finish(&exec_ctx); +} + +void grpc_endpoint_tests(grpc_endpoint_test_config config, + grpc_pollset *pollset, gpr_mu *mu) { + size_t i; + g_pollset = pollset; + g_mu = mu; + multiple_shutdown_test(config); + read_and_write_test(config, 10000000, 100000, 8192, false); + read_and_write_test(config, 1000000, 100000, 1, false); + read_and_write_test(config, 100000000, 100000, 1, true); + for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { + read_and_write_test(config, 40320, i, i, false); + } + g_pollset = NULL; + g_mu = NULL; +} diff --git a/test/core/iomgr/error_test.c b/test/core/iomgr/error_test.c deleted file mode 100644 index 51f8af1957..0000000000 --- a/test/core/iomgr/error_test.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/error.h" - -#include -#include -#include -#include -#include - -#include - -#include "test/core/util/test_config.h" - -static void test_set_get_int() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); - GPR_ASSERT(error); - intptr_t i = 0; - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i)); - GPR_ASSERT(i); // line set will never be 0 - GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); - GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i)); - - intptr_t errnumber = 314; - error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errnumber); - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); - GPR_ASSERT(i == errnumber); - - intptr_t http = 2; - error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, http); - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); - GPR_ASSERT(i == http); - - GRPC_ERROR_UNREF(error); -} - -static void test_set_get_str() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); - - grpc_slice str; - GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str)); - GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str)); - - GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str)); - GPR_ASSERT(strstr((char*)GRPC_SLICE_START_PTR(str), - "error_test.c")); // __FILE__ expands differently on - // Windows. All should at least - // contain error_test.c - - GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "Test", - GRPC_SLICE_LENGTH(str))); - - error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("longer message")); - GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "longer message", - GRPC_SLICE_LENGTH(str))); - - GRPC_ERROR_UNREF(error); -} - -static void test_copy_and_unref() { - // error1 has one ref - grpc_error* error1 = grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("message")); - grpc_slice str; - GPR_ASSERT(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message", - GRPC_SLICE_LENGTH(str))); - - // error 1 has two refs - GRPC_ERROR_REF(error1); - // this gives error3 a ref to the new error, and decrements error1 to one ref - grpc_error* error3 = grpc_error_set_str( - error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall")); - GPR_ASSERT(error3 != error1); // should not be the same because of extra ref - GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message", - GRPC_SLICE_LENGTH(str))); - - // error 1 should not have a syscall but 3 should - GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str)); - GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "syscall", - GRPC_SLICE_LENGTH(str))); - - GRPC_ERROR_UNREF(error1); - GRPC_ERROR_UNREF(error3); -} - -static void test_create_referencing() { - grpc_error* child = grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"), - GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); - grpc_error* parent = - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1); - GPR_ASSERT(parent); - - GRPC_ERROR_UNREF(child); - GRPC_ERROR_UNREF(parent); -} - -static void test_create_referencing_many() { - grpc_error* children[3]; - children[0] = grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"), - GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); - children[1] = - grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child2"), - GRPC_ERROR_INT_HTTP2_ERROR, 5); - children[2] = grpc_error_set_str( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"), - GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3")); - - grpc_error* parent = - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3); - GPR_ASSERT(parent); - - for (size_t i = 0; i < 3; ++i) { - GRPC_ERROR_UNREF(children[i]); - } - GRPC_ERROR_UNREF(parent); -} - -static void print_error_string() { - grpc_error* error = - grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED); - error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666); - error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("message")); - // gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); - GRPC_ERROR_UNREF(error); -} - -static void print_error_string_reference() { - grpc_error* children[2]; - children[0] = grpc_error_set_str( - grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED), - GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("message for child 1")); - children[1] = grpc_error_set_str( - grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("2sd"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL), - GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("message for child 2")); - - grpc_error* parent = - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2); - - for (size_t i = 0; i < 2; ++i) { - GRPC_ERROR_UNREF(children[i]); - } - GRPC_ERROR_UNREF(parent); -} - -static void test_os_error() { - int fake_errno = 5; - const char* syscall = "syscall name"; - grpc_error* error = GRPC_OS_ERROR(fake_errno, syscall); - - intptr_t i = 0; - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); - GPR_ASSERT(i == fake_errno); - - grpc_slice str; - GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str)); - GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), syscall, - GRPC_SLICE_LENGTH(str))); - GRPC_ERROR_UNREF(error); -} - -static void test_special() { - grpc_error* error = GRPC_ERROR_NONE; - error = grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("test child")); - intptr_t i; - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i)); - GPR_ASSERT(i == GRPC_STATUS_OK); - GRPC_ERROR_UNREF(error); -} - -static void test_overflow() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow"); - - for (size_t i = 0; i < 150; ++i) { - error = grpc_error_add_child(error, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child")); - } - - error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 5); - error = - grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_static_string("message for child 2")); - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 5); - - intptr_t i; - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); - GPR_ASSERT(i == 5); - GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i)); - - error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 10); - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); - GPR_ASSERT(i == 10); - - GRPC_ERROR_UNREF(error); - ; -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_set_get_int(); - test_set_get_str(); - test_copy_and_unref(); - print_error_string(); - print_error_string_reference(); - test_os_error(); - test_create_referencing(); - test_create_referencing_many(); - test_special(); - test_overflow(); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/iomgr/error_test.cc b/test/core/iomgr/error_test.cc new file mode 100644 index 0000000000..51f8af1957 --- /dev/null +++ b/test/core/iomgr/error_test.cc @@ -0,0 +1,245 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/error.h" + +#include +#include +#include +#include +#include + +#include + +#include "test/core/util/test_config.h" + +static void test_set_get_int() { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); + GPR_ASSERT(error); + intptr_t i = 0; + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i)); + GPR_ASSERT(i); // line set will never be 0 + GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); + GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i)); + + intptr_t errnumber = 314; + error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errnumber); + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); + GPR_ASSERT(i == errnumber); + + intptr_t http = 2; + error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, http); + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); + GPR_ASSERT(i == http); + + GRPC_ERROR_UNREF(error); +} + +static void test_set_get_str() { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); + + grpc_slice str; + GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str)); + GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR, &str)); + + GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_FILE, &str)); + GPR_ASSERT(strstr((char*)GRPC_SLICE_START_PTR(str), + "error_test.c")); // __FILE__ expands differently on + // Windows. All should at least + // contain error_test.c + + GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "Test", + GRPC_SLICE_LENGTH(str))); + + error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("longer message")); + GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "longer message", + GRPC_SLICE_LENGTH(str))); + + GRPC_ERROR_UNREF(error); +} + +static void test_copy_and_unref() { + // error1 has one ref + grpc_error* error1 = grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("message")); + grpc_slice str; + GPR_ASSERT(grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message", + GRPC_SLICE_LENGTH(str))); + + // error 1 has two refs + GRPC_ERROR_REF(error1); + // this gives error3 a ref to the new error, and decrements error1 to one ref + grpc_error* error3 = grpc_error_set_str( + error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall")); + GPR_ASSERT(error3 != error1); // should not be the same because of extra ref + GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "message", + GRPC_SLICE_LENGTH(str))); + + // error 1 should not have a syscall but 3 should + GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL, &str)); + GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), "syscall", + GRPC_SLICE_LENGTH(str))); + + GRPC_ERROR_UNREF(error1); + GRPC_ERROR_UNREF(error3); +} + +static void test_create_referencing() { + grpc_error* child = grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"), + GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); + grpc_error* parent = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1); + GPR_ASSERT(parent); + + GRPC_ERROR_UNREF(child); + GRPC_ERROR_UNREF(parent); +} + +static void test_create_referencing_many() { + grpc_error* children[3]; + children[0] = grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"), + GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); + children[1] = + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child2"), + GRPC_ERROR_INT_HTTP2_ERROR, 5); + children[2] = grpc_error_set_str( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"), + GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3")); + + grpc_error* parent = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3); + GPR_ASSERT(parent); + + for (size_t i = 0; i < 3; ++i) { + GRPC_ERROR_UNREF(children[i]); + } + GRPC_ERROR_UNREF(parent); +} + +static void print_error_string() { + grpc_error* error = + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED); + error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666); + error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("message")); + // gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); + GRPC_ERROR_UNREF(error); +} + +static void print_error_string_reference() { + grpc_error* children[2]; + children[0] = grpc_error_set_str( + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED), + GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("message for child 1")); + children[1] = grpc_error_set_str( + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("2sd"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL), + GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("message for child 2")); + + grpc_error* parent = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2); + + for (size_t i = 0; i < 2; ++i) { + GRPC_ERROR_UNREF(children[i]); + } + GRPC_ERROR_UNREF(parent); +} + +static void test_os_error() { + int fake_errno = 5; + const char* syscall = "syscall name"; + grpc_error* error = GRPC_OS_ERROR(fake_errno, syscall); + + intptr_t i = 0; + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); + GPR_ASSERT(i == fake_errno); + + grpc_slice str; + GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str)); + GPR_ASSERT(!strncmp((char*)GRPC_SLICE_START_PTR(str), syscall, + GRPC_SLICE_LENGTH(str))); + GRPC_ERROR_UNREF(error); +} + +static void test_special() { + grpc_error* error = GRPC_ERROR_NONE; + error = grpc_error_add_child( + error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("test child")); + intptr_t i; + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i)); + GPR_ASSERT(i == GRPC_STATUS_OK); + GRPC_ERROR_UNREF(error); +} + +static void test_overflow() { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow"); + + for (size_t i = 0; i < 150; ++i) { + error = grpc_error_add_child(error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child")); + } + + error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 5); + error = + grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_static_string("message for child 2")); + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 5); + + intptr_t i; + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); + GPR_ASSERT(i == 5); + GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i)); + + error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, 10); + GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i)); + GPR_ASSERT(i == 10); + + GRPC_ERROR_UNREF(error); + ; +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_set_get_int(); + test_set_get_str(); + test_copy_and_unref(); + print_error_string(); + print_error_string_reference(); + test_os_error(); + test_create_referencing(); + test_create_referencing_many(); + test_special(); + test_overflow(); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/iomgr/ev_epollsig_linux_test.c b/test/core/iomgr/ev_epollsig_linux_test.c deleted file mode 100644 index 37aadacd49..0000000000 --- a/test/core/iomgr/ev_epollsig_linux_test.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "src/core/lib/iomgr/port.h" - -/* This test only relevant on linux systems where epoll() is available */ -#ifdef GRPC_LINUX_EPOLL -#include "src/core/lib/iomgr/ev_epollsig_linux.h" -#include "src/core/lib/iomgr/ev_posix.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -typedef struct test_pollset { - grpc_pollset *pollset; - gpr_mu *mu; -} test_pollset; - -typedef struct test_fd { - int inner_fd; - grpc_fd *fd; -} test_fd; - -/* num_fds should be an even number */ -static void test_fd_init(test_fd *tfds, int *fds, int num_fds) { - int i; - int r; - - /* Create some dummy file descriptors. Currently using pipe file descriptors - * for this test but we could use any other type of file descriptors. Also, - * since pipe() used in this test creates two fds in each call, num_fds should - * be an even number */ - GPR_ASSERT((num_fds % 2) == 0); - for (i = 0; i < num_fds; i = i + 2) { - r = pipe(fds + i); - if (r != 0) { - gpr_log(GPR_ERROR, "Error in creating pipe. %d (%s)", errno, - strerror(errno)); - return; - } - } - - for (i = 0; i < num_fds; i++) { - tfds[i].inner_fd = fds[i]; - tfds[i].fd = grpc_fd_create(fds[i], "test_fd"); - } -} - -static void test_fd_cleanup(grpc_exec_ctx *exec_ctx, test_fd *tfds, - int num_fds) { - int release_fd; - int i; - - for (i = 0; i < num_fds; i++) { - grpc_fd_shutdown(exec_ctx, tfds[i].fd, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_fd_cleanup")); - grpc_exec_ctx_flush(exec_ctx); - - grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, - false /* already_closed */, "test_fd_cleanup"); - grpc_exec_ctx_flush(exec_ctx); - - GPR_ASSERT(release_fd == tfds[i].inner_fd); - close(tfds[i].inner_fd); - } -} - -static void test_pollset_init(test_pollset *pollsets, int num_pollsets) { - int i; - for (i = 0; i < num_pollsets; i++) { - pollsets[i].pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu); - } -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -static void test_pollset_cleanup(grpc_exec_ctx *exec_ctx, - test_pollset *pollsets, int num_pollsets) { - grpc_closure destroyed; - int i; - - for (i = 0; i < num_pollsets; i++) { - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(exec_ctx, pollsets[i].pollset, &destroyed); - - grpc_exec_ctx_flush(exec_ctx); - gpr_free(pollsets[i].pollset); - } -} - -/* - * Cases to test: - * case 1) Polling islands of both fd and pollset are NULL - * case 2) Polling island of fd is NULL but that of pollset is not-NULL - * case 3) Polling island of fd is not-NULL but that of pollset is NULL - * case 4) Polling islands of both fd and pollset are not-NULL and: - * case 4.1) Polling islands of fd and pollset are equal - * case 4.2) Polling islands of fd and pollset are NOT-equal (This results - * in a merge) - * */ - -#define NUM_FDS 8 -#define NUM_POLLSETS 4 - -static void test_add_fd_to_pollset() { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - test_fd tfds[NUM_FDS]; - int fds[NUM_FDS]; - test_pollset pollsets[NUM_POLLSETS]; - void *expected_pi = NULL; - int i; - - test_fd_init(tfds, fds, NUM_FDS); - test_pollset_init(pollsets, NUM_POLLSETS); - - /*Step 1. - * Create three polling islands (This will exercise test case 1 and 2) with - * the following configuration: - * polling island 0 = { fds:0,1,2, pollsets:0} - * polling island 1 = { fds:3,4, pollsets:1} - * polling island 2 = { fds:5,6,7 pollsets:2} - * - *Step 2. - * Add pollset 3 to polling island 0 (by adding fds 0 and 1 to pollset 3) - * (This will exercise test cases 3 and 4.1). The configuration becomes: - * polling island 0 = { fds:0,1,2, pollsets:0,3} <<< pollset 3 added here - * polling island 1 = { fds:3,4, pollsets:1} - * polling island 2 = { fds:5,6,7 pollsets:2} - * - *Step 3. - * Merge polling islands 0 and 1 by adding fd 0 to pollset 1 (This will - * exercise test case 4.2). The configuration becomes: - * polling island (merged) = {fds: 0,1,2,3,4, pollsets: 0,1,3} - * polling island 2 = {fds: 5,6,7 pollsets: 2} - * - *Step 4. - * Finally do one more merge by adding fd 3 to pollset 2. - * polling island (merged) = {fds: 0,1,2,3,4,5,6,7, pollsets: 0,1,2,3} - */ - - /* == Step 1 == */ - for (i = 0; i <= 2; i++) { - grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[i].fd); - grpc_exec_ctx_flush(&exec_ctx); - } - - for (i = 3; i <= 4; i++) { - grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[i].fd); - grpc_exec_ctx_flush(&exec_ctx); - } - - for (i = 5; i <= 7; i++) { - grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[i].fd); - grpc_exec_ctx_flush(&exec_ctx); - } - - /* == Step 2 == */ - for (i = 0; i <= 1; i++) { - grpc_pollset_add_fd(&exec_ctx, pollsets[3].pollset, tfds[i].fd); - grpc_exec_ctx_flush(&exec_ctx); - } - - /* == Step 3 == */ - grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[0].fd); - grpc_exec_ctx_flush(&exec_ctx); - - /* == Step 4 == */ - grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[3].fd); - grpc_exec_ctx_flush(&exec_ctx); - - /* All polling islands are merged at this point */ - - /* Compare Fd:0's polling island with that of all other Fds */ - expected_pi = grpc_fd_get_polling_island(tfds[0].fd); - for (i = 1; i < NUM_FDS; i++) { - GPR_ASSERT(grpc_are_polling_islands_equal( - expected_pi, grpc_fd_get_polling_island(tfds[i].fd))); - } - - /* Compare Fd:0's polling island with that of all other pollsets */ - for (i = 0; i < NUM_POLLSETS; i++) { - GPR_ASSERT(grpc_are_polling_islands_equal( - expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset))); - } - - test_fd_cleanup(&exec_ctx, tfds, NUM_FDS); - test_pollset_cleanup(&exec_ctx, pollsets, NUM_POLLSETS); - grpc_exec_ctx_finish(&exec_ctx); -} - -#undef NUM_FDS -#undef NUM_POLLSETS - -typedef struct threading_shared { - gpr_mu *mu; - grpc_pollset *pollset; - grpc_wakeup_fd *wakeup_fd; - grpc_fd *wakeup_desc; - grpc_closure on_wakeup; - int wakeups; -} threading_shared; - -static __thread int thread_wakeups = 0; - -static void test_threading_loop(void *arg) { - threading_shared *shared = arg; - while (thread_wakeups < 1000000) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_worker *worker; - gpr_mu_lock(shared->mu); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, shared->pollset, &worker, - GRPC_MILLIS_INF_FUTURE))); - gpr_mu_unlock(shared->mu); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_threading_wakeup(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - threading_shared *shared = arg; - ++shared->wakeups; - ++thread_wakeups; - if (error == GRPC_ERROR_NONE) { - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "consume_wakeup", grpc_wakeup_fd_consume_wakeup(shared->wakeup_fd))); - grpc_fd_notify_on_read(exec_ctx, shared->wakeup_desc, &shared->on_wakeup); - GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_next", - grpc_wakeup_fd_wakeup(shared->wakeup_fd))); - } -} - -static void test_threading(void) { - threading_shared shared; - shared.pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(shared.pollset, &shared.mu); - - gpr_thd_id thds[10]; - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt); - } - grpc_wakeup_fd fd; - GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd))); - shared.wakeup_fd = &fd; - shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup"); - shared.wakeups = 0; - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_add_fd(&exec_ctx, shared.pollset, shared.wakeup_desc); - grpc_fd_notify_on_read( - &exec_ctx, shared.wakeup_desc, - GRPC_CLOSURE_INIT(&shared.on_wakeup, test_threading_wakeup, &shared, - grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_finish(&exec_ctx); - } - GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first", - grpc_wakeup_fd_wakeup(shared.wakeup_fd))); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - fd.read_fd = 0; - grpc_wakeup_fd_destroy(&fd); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_fd_shutdown(&exec_ctx, shared.wakeup_desc, GRPC_ERROR_CANCELLED); - grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL, - false /* already_closed */, "done"); - grpc_pollset_shutdown(&exec_ctx, shared.pollset, - GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset, - grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_finish(&exec_ctx); - } - gpr_free(shared.pollset); -} - -int main(int argc, char **argv) { - const char *poll_strategy = NULL; - grpc_test_init(argc, argv); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - poll_strategy = grpc_get_poll_strategy_name(); - if (poll_strategy != NULL && strcmp(poll_strategy, "epollsig") == 0) { - test_add_fd_to_pollset(); - test_threading(); - } else { - gpr_log(GPR_INFO, - "Skipping the test. The test is only relevant for 'epollsig' " - "strategy. and the current strategy is: '%s'", - poll_strategy); - } - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} -#else /* defined(GRPC_LINUX_EPOLL) */ -int main(int argc, char **argv) { return 0; } -#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/test/core/iomgr/ev_epollsig_linux_test.cc b/test/core/iomgr/ev_epollsig_linux_test.cc new file mode 100644 index 0000000000..23079c12c6 --- /dev/null +++ b/test/core/iomgr/ev_epollsig_linux_test.cc @@ -0,0 +1,331 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "src/core/lib/iomgr/port.h" + +/* This test only relevant on linux systems where epoll() is available */ +#ifdef GRPC_LINUX_EPOLL +#include "src/core/lib/iomgr/ev_epollsig_linux.h" +#include "src/core/lib/iomgr/ev_posix.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +typedef struct test_pollset { + grpc_pollset *pollset; + gpr_mu *mu; +} test_pollset; + +typedef struct test_fd { + int inner_fd; + grpc_fd *fd; +} test_fd; + +/* num_fds should be an even number */ +static void test_fd_init(test_fd *tfds, int *fds, int num_fds) { + int i; + int r; + + /* Create some dummy file descriptors. Currently using pipe file descriptors + * for this test but we could use any other type of file descriptors. Also, + * since pipe() used in this test creates two fds in each call, num_fds should + * be an even number */ + GPR_ASSERT((num_fds % 2) == 0); + for (i = 0; i < num_fds; i = i + 2) { + r = pipe(fds + i); + if (r != 0) { + gpr_log(GPR_ERROR, "Error in creating pipe. %d (%s)", errno, + strerror(errno)); + return; + } + } + + for (i = 0; i < num_fds; i++) { + tfds[i].inner_fd = fds[i]; + tfds[i].fd = grpc_fd_create(fds[i], "test_fd"); + } +} + +static void test_fd_cleanup(grpc_exec_ctx *exec_ctx, test_fd *tfds, + int num_fds) { + int release_fd; + int i; + + for (i = 0; i < num_fds; i++) { + grpc_fd_shutdown(exec_ctx, tfds[i].fd, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_fd_cleanup")); + grpc_exec_ctx_flush(exec_ctx); + + grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, + false /* already_closed */, "test_fd_cleanup"); + grpc_exec_ctx_flush(exec_ctx); + + GPR_ASSERT(release_fd == tfds[i].inner_fd); + close(tfds[i].inner_fd); + } +} + +static void test_pollset_init(test_pollset *pollsets, int num_pollsets) { + int i; + for (i = 0; i < num_pollsets; i++) { + pollsets[i].pollset = + static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu); + } +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p); +} + +static void test_pollset_cleanup(grpc_exec_ctx *exec_ctx, + test_pollset *pollsets, int num_pollsets) { + grpc_closure destroyed; + int i; + + for (i = 0; i < num_pollsets; i++) { + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(exec_ctx, pollsets[i].pollset, &destroyed); + + grpc_exec_ctx_flush(exec_ctx); + gpr_free(pollsets[i].pollset); + } +} + +/* + * Cases to test: + * case 1) Polling islands of both fd and pollset are NULL + * case 2) Polling island of fd is NULL but that of pollset is not-NULL + * case 3) Polling island of fd is not-NULL but that of pollset is NULL + * case 4) Polling islands of both fd and pollset are not-NULL and: + * case 4.1) Polling islands of fd and pollset are equal + * case 4.2) Polling islands of fd and pollset are NOT-equal (This results + * in a merge) + * */ + +#define NUM_FDS 8 +#define NUM_POLLSETS 4 + +static void test_add_fd_to_pollset() { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + test_fd tfds[NUM_FDS]; + int fds[NUM_FDS]; + test_pollset pollsets[NUM_POLLSETS]; + void *expected_pi = NULL; + int i; + + test_fd_init(tfds, fds, NUM_FDS); + test_pollset_init(pollsets, NUM_POLLSETS); + + /*Step 1. + * Create three polling islands (This will exercise test case 1 and 2) with + * the following configuration: + * polling island 0 = { fds:0,1,2, pollsets:0} + * polling island 1 = { fds:3,4, pollsets:1} + * polling island 2 = { fds:5,6,7 pollsets:2} + * + *Step 2. + * Add pollset 3 to polling island 0 (by adding fds 0 and 1 to pollset 3) + * (This will exercise test cases 3 and 4.1). The configuration becomes: + * polling island 0 = { fds:0,1,2, pollsets:0,3} <<< pollset 3 added here + * polling island 1 = { fds:3,4, pollsets:1} + * polling island 2 = { fds:5,6,7 pollsets:2} + * + *Step 3. + * Merge polling islands 0 and 1 by adding fd 0 to pollset 1 (This will + * exercise test case 4.2). The configuration becomes: + * polling island (merged) = {fds: 0,1,2,3,4, pollsets: 0,1,3} + * polling island 2 = {fds: 5,6,7 pollsets: 2} + * + *Step 4. + * Finally do one more merge by adding fd 3 to pollset 2. + * polling island (merged) = {fds: 0,1,2,3,4,5,6,7, pollsets: 0,1,2,3} + */ + + /* == Step 1 == */ + for (i = 0; i <= 2; i++) { + grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[i].fd); + grpc_exec_ctx_flush(&exec_ctx); + } + + for (i = 3; i <= 4; i++) { + grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[i].fd); + grpc_exec_ctx_flush(&exec_ctx); + } + + for (i = 5; i <= 7; i++) { + grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[i].fd); + grpc_exec_ctx_flush(&exec_ctx); + } + + /* == Step 2 == */ + for (i = 0; i <= 1; i++) { + grpc_pollset_add_fd(&exec_ctx, pollsets[3].pollset, tfds[i].fd); + grpc_exec_ctx_flush(&exec_ctx); + } + + /* == Step 3 == */ + grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[0].fd); + grpc_exec_ctx_flush(&exec_ctx); + + /* == Step 4 == */ + grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[3].fd); + grpc_exec_ctx_flush(&exec_ctx); + + /* All polling islands are merged at this point */ + + /* Compare Fd:0's polling island with that of all other Fds */ + expected_pi = grpc_fd_get_polling_island(tfds[0].fd); + for (i = 1; i < NUM_FDS; i++) { + GPR_ASSERT(grpc_are_polling_islands_equal( + expected_pi, grpc_fd_get_polling_island(tfds[i].fd))); + } + + /* Compare Fd:0's polling island with that of all other pollsets */ + for (i = 0; i < NUM_POLLSETS; i++) { + GPR_ASSERT(grpc_are_polling_islands_equal( + expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset))); + } + + test_fd_cleanup(&exec_ctx, tfds, NUM_FDS); + test_pollset_cleanup(&exec_ctx, pollsets, NUM_POLLSETS); + grpc_exec_ctx_finish(&exec_ctx); +} + +#undef NUM_FDS +#undef NUM_POLLSETS + +typedef struct threading_shared { + gpr_mu *mu; + grpc_pollset *pollset; + grpc_wakeup_fd *wakeup_fd; + grpc_fd *wakeup_desc; + grpc_closure on_wakeup; + int wakeups; +} threading_shared; + +static __thread int thread_wakeups = 0; + +static void test_threading_loop(void *arg) { + threading_shared *shared = static_cast(arg); + while (thread_wakeups < 1000000) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker; + gpr_mu_lock(shared->mu); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, shared->pollset, &worker, + GRPC_MILLIS_INF_FUTURE))); + gpr_mu_unlock(shared->mu); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_threading_wakeup(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + threading_shared *shared = static_cast(arg); + ++shared->wakeups; + ++thread_wakeups; + if (error == GRPC_ERROR_NONE) { + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "consume_wakeup", grpc_wakeup_fd_consume_wakeup(shared->wakeup_fd))); + grpc_fd_notify_on_read(exec_ctx, shared->wakeup_desc, &shared->on_wakeup); + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_next", + grpc_wakeup_fd_wakeup(shared->wakeup_fd))); + } +} + +static void test_threading(void) { + threading_shared shared; + shared.pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(shared.pollset, &shared.mu); + + gpr_thd_id thds[10]; + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt); + } + grpc_wakeup_fd fd; + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd))); + shared.wakeup_fd = &fd; + shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup"); + shared.wakeups = 0; + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_add_fd(&exec_ctx, shared.pollset, shared.wakeup_desc); + grpc_fd_notify_on_read( + &exec_ctx, shared.wakeup_desc, + GRPC_CLOSURE_INIT(&shared.on_wakeup, test_threading_wakeup, &shared, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + } + GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first", + grpc_wakeup_fd_wakeup(shared.wakeup_fd))); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + fd.read_fd = 0; + grpc_wakeup_fd_destroy(&fd); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_fd_shutdown(&exec_ctx, shared.wakeup_desc, GRPC_ERROR_CANCELLED); + grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL, + false /* already_closed */, "done"); + grpc_pollset_shutdown(&exec_ctx, shared.pollset, + GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + } + gpr_free(shared.pollset); +} + +int main(int argc, char **argv) { + const char *poll_strategy = NULL; + grpc_test_init(argc, argv); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + poll_strategy = grpc_get_poll_strategy_name(); + if (poll_strategy != NULL && strcmp(poll_strategy, "epollsig") == 0) { + test_add_fd_to_pollset(); + test_threading(); + } else { + gpr_log(GPR_INFO, + "Skipping the test. The test is only relevant for 'epollsig' " + "strategy. and the current strategy is: '%s'", + poll_strategy); + } + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} +#else /* defined(GRPC_LINUX_EPOLL) */ +int main(int argc, char **argv) { return 0; } +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c deleted file mode 100644 index d29b1e8e41..0000000000 --- a/test/core/iomgr/fd_conservation_posix_test.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - int i; - struct rlimit rlim; - grpc_endpoint_pair p; - - grpc_test_init(argc, argv); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - /* set max # of file descriptors to a low value, and - verify we can create and destroy many more than this number - of descriptors */ - rlim.rlim_cur = rlim.rlim_max = 10; - GPR_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim)); - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("fd_conservation_posix_test"); - - for (i = 0; i < 100; i++) { - p = grpc_iomgr_create_endpoint_pair("test", NULL); - grpc_endpoint_destroy(&exec_ctx, p.client); - grpc_endpoint_destroy(&exec_ctx, p.server); - grpc_exec_ctx_flush(&exec_ctx); - } - - grpc_resource_quota_unref(resource_quota); - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} diff --git a/test/core/iomgr/fd_conservation_posix_test.cc b/test/core/iomgr/fd_conservation_posix_test.cc new file mode 100644 index 0000000000..d29b1e8e41 --- /dev/null +++ b/test/core/iomgr/fd_conservation_posix_test.cc @@ -0,0 +1,56 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + int i; + struct rlimit rlim; + grpc_endpoint_pair p; + + grpc_test_init(argc, argv); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + /* set max # of file descriptors to a low value, and + verify we can create and destroy many more than this number + of descriptors */ + rlim.rlim_cur = rlim.rlim_max = 10; + GPR_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim)); + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("fd_conservation_posix_test"); + + for (i = 0; i < 100; i++) { + p = grpc_iomgr_create_endpoint_pair("test", NULL); + grpc_endpoint_destroy(&exec_ctx, p.client); + grpc_endpoint_destroy(&exec_ctx, p.server); + grpc_exec_ctx_flush(&exec_ctx); + } + + grpc_resource_quota_unref(resource_quota); + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c deleted file mode 100644 index 1c62f34d3e..0000000000 --- a/test/core/iomgr/fd_posix_test.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/ev_posix.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" -#include "test/core/util/test_config.h" - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; - -/* buffer size used to send and receive data. - 1024 is the minimal value to set TCP send and receive buffer. */ -#define BUF_SIZE 1024 - -/* Create a test socket with the right properties for testing. - port is the TCP port to listen or connect to. - Return a socket FD and sockaddr_in. */ -static void create_test_socket(int port, int *socket_fd, - struct sockaddr_in *sin) { - int fd; - int one = 1; - int buffer_size_bytes = BUF_SIZE; - int flags; - - fd = socket(AF_INET, SOCK_STREAM, 0); - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - /* Reset the size of socket send buffer to the minimal value to facilitate - buffer filling up and triggering notify_on_write */ - GPR_ASSERT(grpc_set_socket_sndbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_set_socket_rcvbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); - /* Make fd non-blocking */ - flags = fcntl(fd, F_GETFL, 0); - GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); - *socket_fd = fd; - - /* Use local address for test */ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = htonl(0x7f000001); - GPR_ASSERT(port >= 0 && port < 65536); - sin->sin_port = htons((uint16_t)port); -} - -/* Dummy gRPC callback */ -void no_op_cb(void *arg, int success) {} - -/* =======An upload server to test notify_on_read=========== - The server simply reads and counts a stream of bytes. */ - -/* An upload server. */ -typedef struct { - grpc_fd *em_fd; /* listening fd */ - ssize_t read_bytes_total; /* total number of received bytes */ - int done; /* set to 1 when a server finishes serving */ - grpc_closure listen_closure; -} server; - -static void server_init(server *sv) { - sv->read_bytes_total = 0; - sv->done = 0; -} - -/* An upload session. - Created when a new upload request arrives in the server. */ -typedef struct { - server *sv; /* not owned by a single session */ - grpc_fd *em_fd; /* fd to read upload bytes */ - char read_buf[BUF_SIZE]; /* buffer to store upload bytes */ - grpc_closure session_read_closure; -} session; - -/* Called when an upload session can be safely shutdown. - Close session FD and start to shutdown listen FD. */ -static void session_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */ - bool success) { - session *se = arg; - server *sv = se->sv; - grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, false /* already_closed */, - "a"); - gpr_free(se); - /* Start to shutdown listen fd. */ - grpc_fd_shutdown(exec_ctx, sv->em_fd, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("session_shutdown_cb")); -} - -/* Called when data become readable in a session. */ -static void session_read_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */ - grpc_error *error) { - session *se = arg; - int fd = grpc_fd_wrapped_fd(se->em_fd); - - ssize_t read_once = 0; - ssize_t read_total = 0; - - if (error != GRPC_ERROR_NONE) { - session_shutdown_cb(exec_ctx, arg, 1); - return; - } - - do { - read_once = read(fd, se->read_buf, BUF_SIZE); - if (read_once > 0) read_total += read_once; - } while (read_once > 0); - se->sv->read_bytes_total += read_total; - - /* read() returns 0 to indicate the TCP connection was closed by the client. - read(fd, read_buf, 0) also returns 0 which should never be called as such. - It is possible to read nothing due to spurious edge event or data has - been drained, In such a case, read() returns -1 and set errno to EAGAIN. */ - if (read_once == 0) { - session_shutdown_cb(exec_ctx, arg, 1); - } else if (read_once == -1) { - if (errno == EAGAIN) { - /* An edge triggered event is cached in the kernel until next poll. - In the current single thread implementation, session_read_cb is called - in the polling thread, such that polling only happens after this - callback, and will catch read edge event if data is available again - before notify_on_read. - TODO(chenw): in multi-threaded version, callback and polling can be - run in different threads. polling may catch a persist read edge event - before notify_on_read is called. */ - grpc_fd_notify_on_read(exec_ctx, se->em_fd, &se->session_read_closure); - } else { - gpr_log(GPR_ERROR, "Unhandled read error %s", strerror(errno)); - abort(); - } - } -} - -/* Called when the listen FD can be safely shutdown. - Close listen FD and signal that server can be shutdown. */ -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, NULL, false /* already_closed */, - "b"); - - gpr_mu_lock(g_mu); - sv->done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -/* Called when a new TCP connection request arrives in the listening port. */ -static void listen_cb(grpc_exec_ctx *exec_ctx, void *arg, /*=sv_arg*/ - grpc_error *error) { - server *sv = arg; - int fd; - int flags; - session *se; - struct sockaddr_storage ss; - socklen_t slen = sizeof(ss); - grpc_fd *listen_em_fd = sv->em_fd; - - if (error != GRPC_ERROR_NONE) { - listen_shutdown_cb(exec_ctx, arg, 1); - return; - } - - fd = accept(grpc_fd_wrapped_fd(listen_em_fd), (struct sockaddr *)&ss, &slen); - GPR_ASSERT(fd >= 0); - GPR_ASSERT(fd < FD_SETSIZE); - flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - se = gpr_malloc(sizeof(*se)); - se->sv = sv; - se->em_fd = grpc_fd_create(fd, "listener"); - grpc_pollset_add_fd(exec_ctx, g_pollset, se->em_fd); - GRPC_CLOSURE_INIT(&se->session_read_closure, session_read_cb, se, - grpc_schedule_on_exec_ctx); - grpc_fd_notify_on_read(exec_ctx, se->em_fd, &se->session_read_closure); - - grpc_fd_notify_on_read(exec_ctx, listen_em_fd, &sv->listen_closure); -} - -/* Max number of connections pending to be accepted by listen(). */ -#define MAX_NUM_FD 1024 - -/* Start a test server, return the TCP listening port bound to listen_fd. - listen_cb() is registered to be interested in reading from listen_fd. - When connection request arrives, listen_cb() is called to accept the - connection request. */ -static int server_start(grpc_exec_ctx *exec_ctx, server *sv) { - int port = 0; - int fd; - struct sockaddr_in sin; - socklen_t addr_len; - - create_test_socket(port, &fd, &sin); - addr_len = sizeof(sin); - GPR_ASSERT(bind(fd, (struct sockaddr *)&sin, addr_len) == 0); - GPR_ASSERT(getsockname(fd, (struct sockaddr *)&sin, &addr_len) == 0); - port = ntohs(sin.sin_port); - GPR_ASSERT(listen(fd, MAX_NUM_FD) == 0); - - sv->em_fd = grpc_fd_create(fd, "server"); - grpc_pollset_add_fd(exec_ctx, g_pollset, sv->em_fd); - /* Register to be interested in reading from listen_fd. */ - GRPC_CLOSURE_INIT(&sv->listen_closure, listen_cb, sv, - grpc_schedule_on_exec_ctx); - grpc_fd_notify_on_read(exec_ctx, sv->em_fd, &sv->listen_closure); - - return port; -} - -/* Wait and shutdown a sever. */ -static void server_wait_and_shutdown(server *sv) { - gpr_mu_lock(g_mu); - while (!sv->done) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - GRPC_MILLIS_INF_FUTURE))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); -} - -/* ===An upload client to test notify_on_write=== */ - -/* Client write buffer size */ -#define CLIENT_WRITE_BUF_SIZE 10 -/* Total number of times that the client fills up the write buffer */ -#define CLIENT_TOTAL_WRITE_CNT 3 - -/* An upload client. */ -typedef struct { - grpc_fd *em_fd; - char write_buf[CLIENT_WRITE_BUF_SIZE]; - ssize_t write_bytes_total; - /* Number of times that the client fills up the write buffer and calls - notify_on_write to schedule another write. */ - int client_write_cnt; - - int done; /* set to 1 when a client finishes sending */ - grpc_closure write_closure; -} client; - -static void client_init(client *cl) { - memset(cl->write_buf, 0, sizeof(cl->write_buf)); - cl->write_bytes_total = 0; - cl->client_write_cnt = 0; - cl->done = 0; -} - -/* Called when a client upload session is ready to shutdown. */ -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, NULL, false /* already_closed */, - "c"); - cl->done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); -} - -/* Write as much as possible, then register notify_on_write. */ -static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */ - grpc_error *error) { - client *cl = arg; - int fd = grpc_fd_wrapped_fd(cl->em_fd); - ssize_t write_once = 0; - - if (error != GRPC_ERROR_NONE) { - gpr_mu_lock(g_mu); - client_session_shutdown_cb(exec_ctx, arg, 1); - gpr_mu_unlock(g_mu); - return; - } - - do { - write_once = write(fd, cl->write_buf, CLIENT_WRITE_BUF_SIZE); - if (write_once > 0) cl->write_bytes_total += write_once; - } while (write_once > 0); - - if (errno == EAGAIN) { - gpr_mu_lock(g_mu); - if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) { - GRPC_CLOSURE_INIT(&cl->write_closure, client_session_write, cl, - grpc_schedule_on_exec_ctx); - grpc_fd_notify_on_write(exec_ctx, cl->em_fd, &cl->write_closure); - cl->client_write_cnt++; - } else { - client_session_shutdown_cb(exec_ctx, arg, 1); - } - gpr_mu_unlock(g_mu); - } else { - gpr_log(GPR_ERROR, "unknown errno %s", strerror(errno)); - abort(); - } -} - -/* Start a client to send a stream of bytes. */ -static void client_start(grpc_exec_ctx *exec_ctx, client *cl, int port) { - int fd; - struct sockaddr_in sin; - create_test_socket(port, &fd, &sin); - if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { - if (errno == EINPROGRESS) { - struct pollfd pfd; - pfd.fd = fd; - pfd.events = POLLOUT; - pfd.revents = 0; - if (poll(&pfd, 1, -1) == -1) { - gpr_log(GPR_ERROR, "poll() failed during connect; errno=%d", errno); - abort(); - } - } else { - gpr_log(GPR_ERROR, "Failed to connect to the server (errno=%d)", errno); - abort(); - } - } - - cl->em_fd = grpc_fd_create(fd, "client"); - grpc_pollset_add_fd(exec_ctx, g_pollset, cl->em_fd); - - client_session_write(exec_ctx, cl, GRPC_ERROR_NONE); -} - -/* Wait for the signal to shutdown a client. */ -static void client_wait_and_shutdown(client *cl) { - gpr_mu_lock(g_mu); - while (!cl->done) { - grpc_pollset_worker *worker = NULL; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - GRPC_MILLIS_INF_FUTURE))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); -} - -/* Test grpc_fd. Start an upload server and client, upload a stream of - bytes from the client to the server, and verify that the total number of - sent bytes is equal to the total number of received bytes. */ -static void test_grpc_fd(void) { - server sv; - client cl; - int port; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - server_init(&sv); - port = server_start(&exec_ctx, &sv); - client_init(&cl); - client_start(&exec_ctx, &cl, port); - grpc_exec_ctx_finish(&exec_ctx); - client_wait_and_shutdown(&cl); - server_wait_and_shutdown(&sv); - GPR_ASSERT(sv.read_bytes_total == cl.write_bytes_total); - gpr_log(GPR_INFO, "Total read bytes %" PRIdPTR, sv.read_bytes_total); -} - -typedef struct fd_change_data { - grpc_iomgr_cb_func cb_that_ran; -} fd_change_data; - -void init_change_data(fd_change_data *fdc) { fdc->cb_that_ran = NULL; } - -void destroy_change_data(fd_change_data *fdc) {} - -static void first_read_callback(grpc_exec_ctx *exec_ctx, - void *arg /* fd_change_data */, - grpc_error *error) { - fd_change_data *fdc = arg; - - gpr_mu_lock(g_mu); - fdc->cb_that_ran = first_read_callback; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void second_read_callback(grpc_exec_ctx *exec_ctx, - void *arg /* fd_change_data */, - grpc_error *error) { - fd_change_data *fdc = arg; - - gpr_mu_lock(g_mu); - fdc->cb_that_ran = second_read_callback; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -/* Test that changing the callback we use for notify_on_read actually works. - Note that we have two different but almost identical callbacks above -- the - point is to have two different function pointers and two different data - pointers and make sure that changing both really works. */ -static void test_grpc_fd_change(void) { - grpc_fd *em_fd; - fd_change_data a, b; - int flags; - int sv[2]; - char data; - ssize_t result; - grpc_closure first_closure; - grpc_closure second_closure; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - GRPC_CLOSURE_INIT(&first_closure, first_read_callback, &a, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&second_closure, second_read_callback, &b, - grpc_schedule_on_exec_ctx); - - init_change_data(&a); - init_change_data(&b); - - GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - - em_fd = grpc_fd_create(sv[0], "test_grpc_fd_change"); - grpc_pollset_add_fd(&exec_ctx, g_pollset, em_fd); - - /* Register the first callback, then make its FD readable */ - grpc_fd_notify_on_read(&exec_ctx, em_fd, &first_closure); - data = 0; - result = write(sv[1], &data, 1); - GPR_ASSERT(result == 1); - - /* And now wait for it to run. */ - gpr_mu_lock(g_mu); - while (a.cb_that_ran == NULL) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - GRPC_MILLIS_INF_FUTURE))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(a.cb_that_ran == first_read_callback); - gpr_mu_unlock(g_mu); - - /* And drain the socket so we can generate a new read edge */ - result = read(sv[0], &data, 1); - GPR_ASSERT(result == 1); - - /* Now register a second callback with distinct change data, and do the same - thing again. */ - grpc_fd_notify_on_read(&exec_ctx, em_fd, &second_closure); - data = 0; - result = write(sv[1], &data, 1); - GPR_ASSERT(result == 1); - - gpr_mu_lock(g_mu); - while (b.cb_that_ran == NULL) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - GRPC_MILLIS_INF_FUTURE))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - /* Except now we verify that second_read_callback ran instead */ - GPR_ASSERT(b.cb_that_ran == second_read_callback); - gpr_mu_unlock(g_mu); - - grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, false /* already_closed */, "d"); - grpc_exec_ctx_finish(&exec_ctx); - destroy_change_data(&a); - destroy_change_data(&b); - close(sv[1]); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - test_grpc_fd(); - test_grpc_fd_change(); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_flush(&exec_ctx); - gpr_free(g_pollset); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/fd_posix_test.cc b/test/core/iomgr/fd_posix_test.cc new file mode 100644 index 0000000000..63363a43a5 --- /dev/null +++ b/test/core/iomgr/fd_posix_test.cc @@ -0,0 +1,545 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/ev_posix.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; + +/* buffer size used to send and receive data. + 1024 is the minimal value to set TCP send and receive buffer. */ +#define BUF_SIZE 1024 + +/* Create a test socket with the right properties for testing. + port is the TCP port to listen or connect to. + Return a socket FD and sockaddr_in. */ +static void create_test_socket(int port, int *socket_fd, + struct sockaddr_in *sin) { + int fd; + int one = 1; + int buffer_size_bytes = BUF_SIZE; + int flags; + + fd = socket(AF_INET, SOCK_STREAM, 0); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + /* Reset the size of socket send buffer to the minimal value to facilitate + buffer filling up and triggering notify_on_write */ + GPR_ASSERT(grpc_set_socket_sndbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_set_socket_rcvbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE); + /* Make fd non-blocking */ + flags = fcntl(fd, F_GETFL, 0); + GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); + *socket_fd = fd; + + /* Use local address for test */ + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(0x7f000001); + GPR_ASSERT(port >= 0 && port < 65536); + sin->sin_port = htons((uint16_t)port); +} + +/* Dummy gRPC callback */ +void no_op_cb(void *arg, int success) {} + +/* =======An upload server to test notify_on_read=========== + The server simply reads and counts a stream of bytes. */ + +/* An upload server. */ +typedef struct { + grpc_fd *em_fd; /* listening fd */ + ssize_t read_bytes_total; /* total number of received bytes */ + int done; /* set to 1 when a server finishes serving */ + grpc_closure listen_closure; +} server; + +static void server_init(server *sv) { + sv->read_bytes_total = 0; + sv->done = 0; +} + +/* An upload session. + Created when a new upload request arrives in the server. */ +typedef struct { + server *sv; /* not owned by a single session */ + grpc_fd *em_fd; /* fd to read upload bytes */ + char read_buf[BUF_SIZE]; /* buffer to store upload bytes */ + grpc_closure session_read_closure; +} session; + +/* Called when an upload session can be safely shutdown. + Close session FD and start to shutdown listen FD. */ +static void session_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */ + bool success) { + session *se = static_cast(arg); + server *sv = se->sv; + grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, false /* already_closed */, + "a"); + gpr_free(se); + /* Start to shutdown listen fd. */ + grpc_fd_shutdown(exec_ctx, sv->em_fd, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("session_shutdown_cb")); +} + +/* Called when data become readable in a session. */ +static void session_read_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */ + grpc_error *error) { + session *se = static_cast(arg); + int fd = grpc_fd_wrapped_fd(se->em_fd); + + ssize_t read_once = 0; + ssize_t read_total = 0; + + if (error != GRPC_ERROR_NONE) { + session_shutdown_cb(exec_ctx, arg, 1); + return; + } + + do { + read_once = read(fd, se->read_buf, BUF_SIZE); + if (read_once > 0) read_total += read_once; + } while (read_once > 0); + se->sv->read_bytes_total += read_total; + + /* read() returns 0 to indicate the TCP connection was closed by the client. + read(fd, read_buf, 0) also returns 0 which should never be called as such. + It is possible to read nothing due to spurious edge event or data has + been drained, In such a case, read() returns -1 and set errno to EAGAIN. */ + if (read_once == 0) { + session_shutdown_cb(exec_ctx, arg, 1); + } else if (read_once == -1) { + if (errno == EAGAIN) { + /* An edge triggered event is cached in the kernel until next poll. + In the current single thread implementation, session_read_cb is called + in the polling thread, such that polling only happens after this + callback, and will catch read edge event if data is available again + before notify_on_read. + TODO(chenw): in multi-threaded version, callback and polling can be + run in different threads. polling may catch a persist read edge event + before notify_on_read is called. */ + grpc_fd_notify_on_read(exec_ctx, se->em_fd, &se->session_read_closure); + } else { + gpr_log(GPR_ERROR, "Unhandled read error %s", strerror(errno)); + abort(); + } + } +} + +/* Called when the listen FD can be safely shutdown. + Close listen FD and signal that server can be shutdown. */ +static void listen_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg /*server */, + int success) { + server *sv = static_cast(arg); + + grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, false /* already_closed */, + "b"); + + gpr_mu_lock(g_mu); + sv->done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +/* Called when a new TCP connection request arrives in the listening port. */ +static void listen_cb(grpc_exec_ctx *exec_ctx, void *arg, /*=sv_arg*/ + grpc_error *error) { + server *sv = static_cast(arg); + int fd; + int flags; + session *se; + struct sockaddr_storage ss; + socklen_t slen = sizeof(ss); + grpc_fd *listen_em_fd = sv->em_fd; + + if (error != GRPC_ERROR_NONE) { + listen_shutdown_cb(exec_ctx, arg, 1); + return; + } + + fd = accept(grpc_fd_wrapped_fd(listen_em_fd), (struct sockaddr *)&ss, &slen); + GPR_ASSERT(fd >= 0); + GPR_ASSERT(fd < FD_SETSIZE); + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + se = static_cast(gpr_malloc(sizeof(*se))); + se->sv = sv; + se->em_fd = grpc_fd_create(fd, "listener"); + grpc_pollset_add_fd(exec_ctx, g_pollset, se->em_fd); + GRPC_CLOSURE_INIT(&se->session_read_closure, session_read_cb, se, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_read(exec_ctx, se->em_fd, &se->session_read_closure); + + grpc_fd_notify_on_read(exec_ctx, listen_em_fd, &sv->listen_closure); +} + +/* Max number of connections pending to be accepted by listen(). */ +#define MAX_NUM_FD 1024 + +/* Start a test server, return the TCP listening port bound to listen_fd. + listen_cb() is registered to be interested in reading from listen_fd. + When connection request arrives, listen_cb() is called to accept the + connection request. */ +static int server_start(grpc_exec_ctx *exec_ctx, server *sv) { + int port = 0; + int fd; + struct sockaddr_in sin; + socklen_t addr_len; + + create_test_socket(port, &fd, &sin); + addr_len = sizeof(sin); + GPR_ASSERT(bind(fd, (struct sockaddr *)&sin, addr_len) == 0); + GPR_ASSERT(getsockname(fd, (struct sockaddr *)&sin, &addr_len) == 0); + port = ntohs(sin.sin_port); + GPR_ASSERT(listen(fd, MAX_NUM_FD) == 0); + + sv->em_fd = grpc_fd_create(fd, "server"); + grpc_pollset_add_fd(exec_ctx, g_pollset, sv->em_fd); + /* Register to be interested in reading from listen_fd. */ + GRPC_CLOSURE_INIT(&sv->listen_closure, listen_cb, sv, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_read(exec_ctx, sv->em_fd, &sv->listen_closure); + + return port; +} + +/* Wait and shutdown a sever. */ +static void server_wait_and_shutdown(server *sv) { + gpr_mu_lock(g_mu); + while (!sv->done) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + GRPC_MILLIS_INF_FUTURE))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); +} + +/* ===An upload client to test notify_on_write=== */ + +/* Client write buffer size */ +#define CLIENT_WRITE_BUF_SIZE 10 +/* Total number of times that the client fills up the write buffer */ +#define CLIENT_TOTAL_WRITE_CNT 3 + +/* An upload client. */ +typedef struct { + grpc_fd *em_fd; + char write_buf[CLIENT_WRITE_BUF_SIZE]; + ssize_t write_bytes_total; + /* Number of times that the client fills up the write buffer and calls + notify_on_write to schedule another write. */ + int client_write_cnt; + + int done; /* set to 1 when a client finishes sending */ + grpc_closure write_closure; +} client; + +static void client_init(client *cl) { + memset(cl->write_buf, 0, sizeof(cl->write_buf)); + cl->write_bytes_total = 0; + cl->client_write_cnt = 0; + cl->done = 0; +} + +/* Called when a client upload session is ready to shutdown. */ +static void client_session_shutdown_cb(grpc_exec_ctx *exec_ctx, + void *arg /*client */, int success) { + client *cl = static_cast(arg); + grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, false /* already_closed */, + "c"); + cl->done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); +} + +/* Write as much as possible, then register notify_on_write. */ +static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */ + grpc_error *error) { + client *cl = static_cast(arg); + int fd = grpc_fd_wrapped_fd(cl->em_fd); + ssize_t write_once = 0; + + if (error != GRPC_ERROR_NONE) { + gpr_mu_lock(g_mu); + client_session_shutdown_cb(exec_ctx, arg, 1); + gpr_mu_unlock(g_mu); + return; + } + + do { + write_once = write(fd, cl->write_buf, CLIENT_WRITE_BUF_SIZE); + if (write_once > 0) cl->write_bytes_total += write_once; + } while (write_once > 0); + + if (errno == EAGAIN) { + gpr_mu_lock(g_mu); + if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) { + GRPC_CLOSURE_INIT(&cl->write_closure, client_session_write, cl, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_write(exec_ctx, cl->em_fd, &cl->write_closure); + cl->client_write_cnt++; + } else { + client_session_shutdown_cb(exec_ctx, arg, 1); + } + gpr_mu_unlock(g_mu); + } else { + gpr_log(GPR_ERROR, "unknown errno %s", strerror(errno)); + abort(); + } +} + +/* Start a client to send a stream of bytes. */ +static void client_start(grpc_exec_ctx *exec_ctx, client *cl, int port) { + int fd; + struct sockaddr_in sin; + create_test_socket(port, &fd, &sin); + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { + if (errno == EINPROGRESS) { + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLOUT; + pfd.revents = 0; + if (poll(&pfd, 1, -1) == -1) { + gpr_log(GPR_ERROR, "poll() failed during connect; errno=%d", errno); + abort(); + } + } else { + gpr_log(GPR_ERROR, "Failed to connect to the server (errno=%d)", errno); + abort(); + } + } + + cl->em_fd = grpc_fd_create(fd, "client"); + grpc_pollset_add_fd(exec_ctx, g_pollset, cl->em_fd); + + client_session_write(exec_ctx, cl, GRPC_ERROR_NONE); +} + +/* Wait for the signal to shutdown a client. */ +static void client_wait_and_shutdown(client *cl) { + gpr_mu_lock(g_mu); + while (!cl->done) { + grpc_pollset_worker *worker = NULL; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + GRPC_MILLIS_INF_FUTURE))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); +} + +/* Test grpc_fd. Start an upload server and client, upload a stream of + bytes from the client to the server, and verify that the total number of + sent bytes is equal to the total number of received bytes. */ +static void test_grpc_fd(void) { + server sv; + client cl; + int port; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + server_init(&sv); + port = server_start(&exec_ctx, &sv); + client_init(&cl); + client_start(&exec_ctx, &cl, port); + grpc_exec_ctx_finish(&exec_ctx); + client_wait_and_shutdown(&cl); + server_wait_and_shutdown(&sv); + GPR_ASSERT(sv.read_bytes_total == cl.write_bytes_total); + gpr_log(GPR_INFO, "Total read bytes %" PRIdPTR, sv.read_bytes_total); +} + +typedef struct fd_change_data { + grpc_iomgr_cb_func cb_that_ran; +} fd_change_data; + +void init_change_data(fd_change_data *fdc) { fdc->cb_that_ran = NULL; } + +void destroy_change_data(fd_change_data *fdc) {} + +static void first_read_callback(grpc_exec_ctx *exec_ctx, + void *arg /* fd_change_data */, + grpc_error *error) { + fd_change_data *fdc = static_cast(arg); + + gpr_mu_lock(g_mu); + fdc->cb_that_ran = first_read_callback; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void second_read_callback(grpc_exec_ctx *exec_ctx, + void *arg /* fd_change_data */, + grpc_error *error) { + fd_change_data *fdc = static_cast(arg); + + gpr_mu_lock(g_mu); + fdc->cb_that_ran = second_read_callback; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +/* Test that changing the callback we use for notify_on_read actually works. + Note that we have two different but almost identical callbacks above -- the + point is to have two different function pointers and two different data + pointers and make sure that changing both really works. */ +static void test_grpc_fd_change(void) { + grpc_fd *em_fd; + fd_change_data a, b; + int flags; + int sv[2]; + char data; + ssize_t result; + grpc_closure first_closure; + grpc_closure second_closure; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + GRPC_CLOSURE_INIT(&first_closure, first_read_callback, &a, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&second_closure, second_read_callback, &b, + grpc_schedule_on_exec_ctx); + + init_change_data(&a); + init_change_data(&b); + + GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); + flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); + + em_fd = grpc_fd_create(sv[0], "test_grpc_fd_change"); + grpc_pollset_add_fd(&exec_ctx, g_pollset, em_fd); + + /* Register the first callback, then make its FD readable */ + grpc_fd_notify_on_read(&exec_ctx, em_fd, &first_closure); + data = 0; + result = write(sv[1], &data, 1); + GPR_ASSERT(result == 1); + + /* And now wait for it to run. */ + gpr_mu_lock(g_mu); + while (a.cb_that_ran == NULL) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + GRPC_MILLIS_INF_FUTURE))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(a.cb_that_ran == first_read_callback); + gpr_mu_unlock(g_mu); + + /* And drain the socket so we can generate a new read edge */ + result = read(sv[0], &data, 1); + GPR_ASSERT(result == 1); + + /* Now register a second callback with distinct change data, and do the same + thing again. */ + grpc_fd_notify_on_read(&exec_ctx, em_fd, &second_closure); + data = 0; + result = write(sv[1], &data, 1); + GPR_ASSERT(result == 1); + + gpr_mu_lock(g_mu); + while (b.cb_that_ran == NULL) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + GRPC_MILLIS_INF_FUTURE))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + /* Except now we verify that second_read_callback ran instead */ + GPR_ASSERT(b.cb_that_ran == second_read_callback); + gpr_mu_unlock(g_mu); + + grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, false /* already_closed */, "d"); + grpc_exec_ctx_finish(&exec_ctx); + destroy_change_data(&a); + destroy_change_data(&b); + close(sv[1]); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(g_pollset, &g_mu); + test_grpc_fd(); + test_grpc_fd_change(); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_flush(&exec_ctx); + gpr_free(g_pollset); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/load_file_test.c b/test/core/iomgr/load_file_test.c deleted file mode 100644 index 537c3430b1..0000000000 --- a/test/core/iomgr/load_file_test.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include - -#include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/support/tmpfile.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) - -static const char prefix[] = "file_test"; - -static void test_load_empty_file(void) { - FILE *tmp = NULL; - grpc_slice slice; - grpc_slice slice_with_null_term; - grpc_error *error; - char *tmp_name; - - LOG_TEST_NAME("test_load_empty_file"); - - tmp = gpr_tmpfile(prefix, &tmp_name); - GPR_ASSERT(tmp_name != NULL); - GPR_ASSERT(tmp != NULL); - fclose(tmp); - - error = grpc_load_file(tmp_name, 0, &slice); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 0); - - error = grpc_load_file(tmp_name, 1, &slice_with_null_term); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice_with_null_term) == 1); - GPR_ASSERT(GRPC_SLICE_START_PTR(slice_with_null_term)[0] == 0); - - remove(tmp_name); - gpr_free(tmp_name); - grpc_slice_unref(slice); - grpc_slice_unref(slice_with_null_term); -} - -static void test_load_failure(void) { - FILE *tmp = NULL; - grpc_slice slice; - grpc_error *error; - char *tmp_name; - - LOG_TEST_NAME("test_load_failure"); - - tmp = gpr_tmpfile(prefix, &tmp_name); - GPR_ASSERT(tmp_name != NULL); - GPR_ASSERT(tmp != NULL); - fclose(tmp); - remove(tmp_name); - - error = grpc_load_file(tmp_name, 0, &slice); - GPR_ASSERT(error != GRPC_ERROR_NONE); - GRPC_ERROR_UNREF(error); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 0); - gpr_free(tmp_name); - grpc_slice_unref(slice); -} - -static void test_load_small_file(void) { - FILE *tmp = NULL; - grpc_slice slice; - grpc_slice slice_with_null_term; - grpc_error *error; - char *tmp_name; - const char *blah = "blah"; - - LOG_TEST_NAME("test_load_small_file"); - - tmp = gpr_tmpfile(prefix, &tmp_name); - GPR_ASSERT(tmp_name != NULL); - GPR_ASSERT(tmp != NULL); - GPR_ASSERT(fwrite(blah, 1, strlen(blah), tmp) == strlen(blah)); - fclose(tmp); - - error = grpc_load_file(tmp_name, 0, &slice); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == strlen(blah)); - GPR_ASSERT(!memcmp(GRPC_SLICE_START_PTR(slice), blah, strlen(blah))); - - error = grpc_load_file(tmp_name, 1, &slice_with_null_term); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice_with_null_term) == (strlen(blah) + 1)); - GPR_ASSERT(strcmp((const char *)GRPC_SLICE_START_PTR(slice_with_null_term), - blah) == 0); - - remove(tmp_name); - gpr_free(tmp_name); - grpc_slice_unref(slice); - grpc_slice_unref(slice_with_null_term); -} - -static void test_load_big_file(void) { - FILE *tmp = NULL; - grpc_slice slice; - grpc_error *error; - char *tmp_name; - static const size_t buffer_size = 124631; - unsigned char *buffer = gpr_malloc(buffer_size); - unsigned char *current; - size_t i; - - LOG_TEST_NAME("test_load_big_file"); - - memset(buffer, 42, buffer_size); - - tmp = gpr_tmpfile(prefix, &tmp_name); - GPR_ASSERT(tmp != NULL); - GPR_ASSERT(tmp_name != NULL); - GPR_ASSERT(fwrite(buffer, 1, buffer_size, tmp) == buffer_size); - fclose(tmp); - - error = grpc_load_file(tmp_name, 0, &slice); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == buffer_size); - current = GRPC_SLICE_START_PTR(slice); - for (i = 0; i < buffer_size; i++) { - GPR_ASSERT(current[i] == 42); - } - - remove(tmp_name); - gpr_free(tmp_name); - grpc_slice_unref(slice); - gpr_free(buffer); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_load_empty_file(); - test_load_failure(); - test_load_small_file(); - test_load_big_file(); - return 0; -} diff --git a/test/core/iomgr/load_file_test.cc b/test/core/iomgr/load_file_test.cc new file mode 100644 index 0000000000..5fb8266b10 --- /dev/null +++ b/test/core/iomgr/load_file_test.cc @@ -0,0 +1,160 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) + +static const char prefix[] = "file_test"; + +static void test_load_empty_file(void) { + FILE *tmp = NULL; + grpc_slice slice; + grpc_slice slice_with_null_term; + grpc_error *error; + char *tmp_name; + + LOG_TEST_NAME("test_load_empty_file"); + + tmp = gpr_tmpfile(prefix, &tmp_name); + GPR_ASSERT(tmp_name != NULL); + GPR_ASSERT(tmp != NULL); + fclose(tmp); + + error = grpc_load_file(tmp_name, 0, &slice); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 0); + + error = grpc_load_file(tmp_name, 1, &slice_with_null_term); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_with_null_term) == 1); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice_with_null_term)[0] == 0); + + remove(tmp_name); + gpr_free(tmp_name); + grpc_slice_unref(slice); + grpc_slice_unref(slice_with_null_term); +} + +static void test_load_failure(void) { + FILE *tmp = NULL; + grpc_slice slice; + grpc_error *error; + char *tmp_name; + + LOG_TEST_NAME("test_load_failure"); + + tmp = gpr_tmpfile(prefix, &tmp_name); + GPR_ASSERT(tmp_name != NULL); + GPR_ASSERT(tmp != NULL); + fclose(tmp); + remove(tmp_name); + + error = grpc_load_file(tmp_name, 0, &slice); + GPR_ASSERT(error != GRPC_ERROR_NONE); + GRPC_ERROR_UNREF(error); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 0); + gpr_free(tmp_name); + grpc_slice_unref(slice); +} + +static void test_load_small_file(void) { + FILE *tmp = NULL; + grpc_slice slice; + grpc_slice slice_with_null_term; + grpc_error *error; + char *tmp_name; + const char *blah = "blah"; + + LOG_TEST_NAME("test_load_small_file"); + + tmp = gpr_tmpfile(prefix, &tmp_name); + GPR_ASSERT(tmp_name != NULL); + GPR_ASSERT(tmp != NULL); + GPR_ASSERT(fwrite(blah, 1, strlen(blah), tmp) == strlen(blah)); + fclose(tmp); + + error = grpc_load_file(tmp_name, 0, &slice); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == strlen(blah)); + GPR_ASSERT(!memcmp(GRPC_SLICE_START_PTR(slice), blah, strlen(blah))); + + error = grpc_load_file(tmp_name, 1, &slice_with_null_term); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_with_null_term) == (strlen(blah) + 1)); + GPR_ASSERT(strcmp((const char *)GRPC_SLICE_START_PTR(slice_with_null_term), + blah) == 0); + + remove(tmp_name); + gpr_free(tmp_name); + grpc_slice_unref(slice); + grpc_slice_unref(slice_with_null_term); +} + +static void test_load_big_file(void) { + FILE *tmp = NULL; + grpc_slice slice; + grpc_error *error; + char *tmp_name; + static const size_t buffer_size = 124631; + unsigned char *buffer = static_cast(gpr_malloc(buffer_size)); + unsigned char *current; + size_t i; + + LOG_TEST_NAME("test_load_big_file"); + + memset(buffer, 42, buffer_size); + + tmp = gpr_tmpfile(prefix, &tmp_name); + GPR_ASSERT(tmp != NULL); + GPR_ASSERT(tmp_name != NULL); + GPR_ASSERT(fwrite(buffer, 1, buffer_size, tmp) == buffer_size); + fclose(tmp); + + error = grpc_load_file(tmp_name, 0, &slice); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == buffer_size); + current = GRPC_SLICE_START_PTR(slice); + for (i = 0; i < buffer_size; i++) { + GPR_ASSERT(current[i] == 42); + } + + remove(tmp_name); + gpr_free(tmp_name); + grpc_slice_unref(slice); + gpr_free(buffer); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_load_empty_file(); + test_load_failure(); + test_load_small_file(); + test_load_big_file(); + return 0; +} diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c deleted file mode 100644 index cddc146ce0..0000000000 --- a/test/core/iomgr/pollset_set_test.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "src/core/lib/iomgr/port.h" - -/* This test only relevant on linux systems where epoll is available */ -#ifdef GRPC_LINUX_EPOLL - -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -/******************************************************************************* - * test_pollset_set - */ - -typedef struct test_pollset_set { grpc_pollset_set *pss; } test_pollset_set; - -void init_test_pollset_sets(test_pollset_set *pollset_sets, const int num_pss) { - for (int i = 0; i < num_pss; i++) { - pollset_sets[i].pss = grpc_pollset_set_create(); - } -} - -void cleanup_test_pollset_sets(grpc_exec_ctx *exec_ctx, - test_pollset_set *pollset_sets, - const int num_pss) { - for (int i = 0; i < num_pss; i++) { - grpc_pollset_set_destroy(exec_ctx, pollset_sets[i].pss); - pollset_sets[i].pss = NULL; - } -} - -/******************************************************************************* - * test_pollset - */ - -typedef struct test_pollset { - grpc_pollset *ps; - gpr_mu *mu; -} test_pollset; - -static void init_test_pollsets(test_pollset *pollsets, const int num_pollsets) { - for (int i = 0; i < num_pollsets; i++) { - pollsets[i].ps = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollsets[i].ps, &pollsets[i].mu); - } -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -static void cleanup_test_pollsets(grpc_exec_ctx *exec_ctx, - test_pollset *pollsets, - const int num_pollsets) { - grpc_closure destroyed; - for (int i = 0; i < num_pollsets; i++) { - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].ps, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(exec_ctx, pollsets[i].ps, &destroyed); - - grpc_exec_ctx_flush(exec_ctx); - gpr_free(pollsets[i].ps); - pollsets[i].ps = NULL; - } -} - -/******************************************************************************* - * test_fd - */ - -typedef struct test_fd { - grpc_fd *fd; - grpc_wakeup_fd wakeup_fd; - - bool is_on_readable_called; /* Is on_readable closure is called ? */ - grpc_closure on_readable; /* Closure to call when this fd is readable */ -} test_fd; - -void on_readable(grpc_exec_ctx *exec_ctx, void *tfd, grpc_error *error) { - ((test_fd *)tfd)->is_on_readable_called = true; -} - -static void reset_test_fd(grpc_exec_ctx *exec_ctx, test_fd *tfd) { - tfd->is_on_readable_called = false; - - GRPC_CLOSURE_INIT(&tfd->on_readable, on_readable, tfd, - grpc_schedule_on_exec_ctx); - grpc_fd_notify_on_read(exec_ctx, tfd->fd, &tfd->on_readable); -} - -static void init_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds, - const int num_fds) { - for (int i = 0; i < num_fds; i++) { - GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_init(&tfds[i].wakeup_fd)); - tfds[i].fd = grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&tfds[i].wakeup_fd), - "test_fd"); - reset_test_fd(exec_ctx, &tfds[i]); - } -} - -static void cleanup_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds, - const int num_fds) { - int release_fd; - - for (int i = 0; i < num_fds; i++) { - grpc_fd_shutdown(exec_ctx, tfds[i].fd, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd cleanup")); - grpc_exec_ctx_flush(exec_ctx); - - /* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also - * calls close() on the underlying fd. In our case, we are using - * grpc_wakeup_fd and we would like to destroy it ourselves (by calling - * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the - * underlying fd, call it with a non-NULL 'release_fd' parameter */ - grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, - false /* already_closed */, "test_fd_cleanup"); - grpc_exec_ctx_flush(exec_ctx); - - grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd); - } -} - -static void make_test_fds_readable(test_fd *tfds, const int num_fds) { - for (int i = 0; i < num_fds; i++) { - GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd)); - } -} - -static void verify_readable_and_reset(grpc_exec_ctx *exec_ctx, test_fd *tfds, - const int num_fds) { - for (int i = 0; i < num_fds; i++) { - /* Verify that the on_readable callback was called */ - GPR_ASSERT(tfds[i].is_on_readable_called); - - /* Reset the tfd[i] structure */ - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_wakeup_fd_consume_wakeup(&tfds[i].wakeup_fd)); - reset_test_fd(exec_ctx, &tfds[i]); - } -} - -/******************************************************************************* - * Main tests - */ - -/* Test some typical scenarios in pollset_set */ -static void pollset_set_test_basic() { - /* We construct the following structure for this test: - * - * +---> FD0 (Added before PSS1, PS1 and PS2 are added to PSS0) - * | - * +---> FD5 (Added after PSS1, PS1 and PS2 are added to PSS0) - * | - * | - * | +---> FD1 (Added before PSS1 is added to PSS0) - * | | - * | +---> FD6 (Added after PSS1 is added to PSS0) - * | | - * +---> PSS1--+ +--> FD2 (Added before PS0 is added to PSS1) - * | | | - * | +---> PS0---+ - * | | - * PSS0---+ +--> FD7 (Added after PS0 is added to PSS1) - * | - * | - * | +---> FD3 (Added before PS1 is added to PSS0) - * | | - * +---> PS1---+ - * | | - * | +---> FD8 (Added after PS1 added to PSS0) - * | - * | - * | +---> FD4 (Added before PS2 is added to PSS0) - * | | - * +---> PS2---+ - * | - * +---> FD9 (Added after PS2 is added to PSS0) - */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_worker *worker; - grpc_millis deadline; - - test_fd tfds[10]; - test_pollset pollsets[3]; - test_pollset_set pollset_sets[2]; - const int num_fds = GPR_ARRAY_SIZE(tfds); - const int num_ps = GPR_ARRAY_SIZE(pollsets); - const int num_pss = GPR_ARRAY_SIZE(pollset_sets); - - init_test_fds(&exec_ctx, tfds, num_fds); - init_test_pollsets(pollsets, num_ps); - init_test_pollset_sets(pollset_sets, num_pss); - - /* Construct the pollset_set/pollset/fd tree (see diagram above) */ - - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); - - grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[2].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[3].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[4].fd); - - grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss, - pollset_sets[1].pss); - - grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps); - grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps); - grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps); - - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd); - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd); - - grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[7].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[8].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[9].fd); - - grpc_exec_ctx_flush(&exec_ctx); - - /* Test that if any FD in the above structure is readable, it is observable by - * doing grpc_pollset_work on any pollset - * - * For every pollset, do the following: - * - (Ensure that all FDs are in reset state) - * - Make all FDs readable - * - Call grpc_pollset_work() on the pollset - * - Flush the exec_ctx - * - Verify that on_readable call back was called for all FDs (and - * reset the FDs) - * */ - for (int i = 0; i < num_ps; i++) { - make_test_fds_readable(tfds, num_fds); - - gpr_mu_lock(pollsets[i].mu); - deadline = grpc_timespec_to_millis_round_up( - grpc_timeout_milliseconds_to_deadline(2)); - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_pollset_work(&exec_ctx, pollsets[i].ps, &worker, deadline)); - gpr_mu_unlock(pollsets[i].mu); - - grpc_exec_ctx_flush(&exec_ctx); - - verify_readable_and_reset(&exec_ctx, tfds, num_fds); - grpc_exec_ctx_flush(&exec_ctx); - } - - /* Test tear down */ - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd); - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps); - grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps); - grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps); - - grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss, - pollset_sets[1].pss); - grpc_exec_ctx_flush(&exec_ctx); - - cleanup_test_fds(&exec_ctx, tfds, num_fds); - cleanup_test_pollsets(&exec_ctx, pollsets, num_ps); - cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss); - grpc_exec_ctx_finish(&exec_ctx); -} - -/* Same FD added multiple times to the pollset_set tree */ -void pollset_set_test_dup_fds() { - /* We construct the following structure for this test: - * - * +---> FD0 - * | - * | - * PSS0---+ - * | +---> FD0 (also under PSS0) - * | | - * +---> PSS1--+ +--> FD1 (also under PSS1) - * | | - * +---> PS ---+ - * | | - * | +--> FD2 - * +---> FD1 - */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_worker *worker; - grpc_millis deadline; - - test_fd tfds[3]; - test_pollset pollset; - test_pollset_set pollset_sets[2]; - const int num_fds = GPR_ARRAY_SIZE(tfds); - const int num_ps = 1; - const int num_pss = GPR_ARRAY_SIZE(pollset_sets); - - init_test_fds(&exec_ctx, tfds, num_fds); - init_test_pollsets(&pollset, num_ps); - init_test_pollset_sets(pollset_sets, num_pss); - - /* Construct the structure */ - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd); - grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); - - grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[1].fd); - grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[2].fd); - - grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps); - grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss, - pollset_sets[1].pss); - - /* Test. Make all FDs readable and make sure that can be observed by doing a - * grpc_pollset_work on the pollset 'PS' */ - make_test_fds_readable(tfds, num_fds); - - gpr_mu_lock(pollset.mu); - deadline = grpc_timespec_to_millis_round_up( - grpc_timeout_milliseconds_to_deadline(2)); - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_pollset_work(&exec_ctx, pollset.ps, &worker, deadline)); - gpr_mu_unlock(pollset.mu); - grpc_exec_ctx_flush(&exec_ctx); - - verify_readable_and_reset(&exec_ctx, tfds, num_fds); - grpc_exec_ctx_flush(&exec_ctx); - - /* Tear down */ - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd); - grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); - - grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps); - grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss, - pollset_sets[1].pss); - grpc_exec_ctx_flush(&exec_ctx); - - cleanup_test_fds(&exec_ctx, tfds, num_fds); - cleanup_test_pollsets(&exec_ctx, &pollset, num_ps); - cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss); - grpc_exec_ctx_finish(&exec_ctx); -} - -/* Pollset_set with an empty pollset */ -void pollset_set_test_empty_pollset() { - /* We construct the following structure for this test: - * - * +---> PS0 (EMPTY) - * | - * +---> FD0 - * | - * PSS0---+ - * | +---> FD1 - * | | - * +---> PS1--+ - * | - * +---> FD2 - */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_worker *worker; - grpc_millis deadline; - - test_fd tfds[3]; - test_pollset pollsets[2]; - test_pollset_set pollset_set; - const int num_fds = GPR_ARRAY_SIZE(tfds); - const int num_ps = GPR_ARRAY_SIZE(pollsets); - const int num_pss = 1; - - init_test_fds(&exec_ctx, tfds, num_fds); - init_test_pollsets(pollsets, num_ps); - init_test_pollset_sets(&pollset_set, num_pss); - - /* Construct the structure */ - grpc_pollset_set_add_fd(&exec_ctx, pollset_set.pss, tfds[0].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[1].fd); - grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[2].fd); - - grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps); - grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps); - - /* Test. Make all FDs readable and make sure that can be observed by doing - * grpc_pollset_work on the empty pollset 'PS0' */ - make_test_fds_readable(tfds, num_fds); - - gpr_mu_lock(pollsets[0].mu); - deadline = grpc_timespec_to_millis_round_up( - grpc_timeout_milliseconds_to_deadline(2)); - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_pollset_work(&exec_ctx, pollsets[0].ps, &worker, deadline)); - gpr_mu_unlock(pollsets[0].mu); - grpc_exec_ctx_flush(&exec_ctx); - - verify_readable_and_reset(&exec_ctx, tfds, num_fds); - grpc_exec_ctx_flush(&exec_ctx); - - /* Tear down */ - grpc_pollset_set_del_fd(&exec_ctx, pollset_set.pss, tfds[0].fd); - grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps); - grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps); - grpc_exec_ctx_flush(&exec_ctx); - - cleanup_test_fds(&exec_ctx, tfds, num_fds); - cleanup_test_pollsets(&exec_ctx, pollsets, num_ps); - cleanup_test_pollset_sets(&exec_ctx, &pollset_set, num_pss); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - const char *poll_strategy = grpc_get_poll_strategy_name(); - - if (poll_strategy != NULL && - (strcmp(poll_strategy, "epollsig") == 0 || - strcmp(poll_strategy, "epoll-threadpool") == 0)) { - pollset_set_test_basic(); - pollset_set_test_dup_fds(); - pollset_set_test_empty_pollset(); - } else { - gpr_log(GPR_INFO, - "Skipping the test. The test is only relevant for 'epoll' " - "strategy. and the current strategy is: '%s'", - poll_strategy); - } - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} -#else /* defined(GRPC_LINUX_EPOLL) */ -int main(int argc, char **argv) { return 0; } -#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/test/core/iomgr/pollset_set_test.cc b/test/core/iomgr/pollset_set_test.cc new file mode 100644 index 0000000000..ae19c81d6d --- /dev/null +++ b/test/core/iomgr/pollset_set_test.cc @@ -0,0 +1,459 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "src/core/lib/iomgr/port.h" + +/* This test only relevant on linux systems where epoll is available */ +#ifdef GRPC_LINUX_EPOLL + +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +/******************************************************************************* + * test_pollset_set + */ + +typedef struct test_pollset_set { grpc_pollset_set *pss; } test_pollset_set; + +void init_test_pollset_sets(test_pollset_set *pollset_sets, const int num_pss) { + for (int i = 0; i < num_pss; i++) { + pollset_sets[i].pss = grpc_pollset_set_create(); + } +} + +void cleanup_test_pollset_sets(grpc_exec_ctx *exec_ctx, + test_pollset_set *pollset_sets, + const int num_pss) { + for (int i = 0; i < num_pss; i++) { + grpc_pollset_set_destroy(exec_ctx, pollset_sets[i].pss); + pollset_sets[i].pss = NULL; + } +} + +/******************************************************************************* + * test_pollset + */ + +typedef struct test_pollset { + grpc_pollset *ps; + gpr_mu *mu; +} test_pollset; + +static void init_test_pollsets(test_pollset *pollsets, const int num_pollsets) { + for (int i = 0; i < num_pollsets; i++) { + pollsets[i].ps = + static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(pollsets[i].ps, &pollsets[i].mu); + } +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +static void cleanup_test_pollsets(grpc_exec_ctx *exec_ctx, + test_pollset *pollsets, + const int num_pollsets) { + grpc_closure destroyed; + for (int i = 0; i < num_pollsets; i++) { + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, pollsets[i].ps, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(exec_ctx, pollsets[i].ps, &destroyed); + + grpc_exec_ctx_flush(exec_ctx); + gpr_free(pollsets[i].ps); + pollsets[i].ps = NULL; + } +} + +/******************************************************************************* + * test_fd + */ + +typedef struct test_fd { + grpc_fd *fd; + grpc_wakeup_fd wakeup_fd; + + bool is_on_readable_called; /* Is on_readable closure is called ? */ + grpc_closure on_readable; /* Closure to call when this fd is readable */ +} test_fd; + +void on_readable(grpc_exec_ctx *exec_ctx, void *tfd, grpc_error *error) { + ((test_fd *)tfd)->is_on_readable_called = true; +} + +static void reset_test_fd(grpc_exec_ctx *exec_ctx, test_fd *tfd) { + tfd->is_on_readable_called = false; + + GRPC_CLOSURE_INIT(&tfd->on_readable, on_readable, tfd, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_read(exec_ctx, tfd->fd, &tfd->on_readable); +} + +static void init_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds, + const int num_fds) { + for (int i = 0; i < num_fds; i++) { + GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_init(&tfds[i].wakeup_fd)); + tfds[i].fd = grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&tfds[i].wakeup_fd), + "test_fd"); + reset_test_fd(exec_ctx, &tfds[i]); + } +} + +static void cleanup_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds, + const int num_fds) { + int release_fd; + + for (int i = 0; i < num_fds; i++) { + grpc_fd_shutdown(exec_ctx, tfds[i].fd, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd cleanup")); + grpc_exec_ctx_flush(exec_ctx); + + /* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also + * calls close() on the underlying fd. In our case, we are using + * grpc_wakeup_fd and we would like to destroy it ourselves (by calling + * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the + * underlying fd, call it with a non-NULL 'release_fd' parameter */ + grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, + false /* already_closed */, "test_fd_cleanup"); + grpc_exec_ctx_flush(exec_ctx); + + grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd); + } +} + +static void make_test_fds_readable(test_fd *tfds, const int num_fds) { + for (int i = 0; i < num_fds; i++) { + GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd)); + } +} + +static void verify_readable_and_reset(grpc_exec_ctx *exec_ctx, test_fd *tfds, + const int num_fds) { + for (int i = 0; i < num_fds; i++) { + /* Verify that the on_readable callback was called */ + GPR_ASSERT(tfds[i].is_on_readable_called); + + /* Reset the tfd[i] structure */ + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_wakeup_fd_consume_wakeup(&tfds[i].wakeup_fd)); + reset_test_fd(exec_ctx, &tfds[i]); + } +} + +/******************************************************************************* + * Main tests + */ + +/* Test some typical scenarios in pollset_set */ +static void pollset_set_test_basic() { + /* We construct the following structure for this test: + * + * +---> FD0 (Added before PSS1, PS1 and PS2 are added to PSS0) + * | + * +---> FD5 (Added after PSS1, PS1 and PS2 are added to PSS0) + * | + * | + * | +---> FD1 (Added before PSS1 is added to PSS0) + * | | + * | +---> FD6 (Added after PSS1 is added to PSS0) + * | | + * +---> PSS1--+ +--> FD2 (Added before PS0 is added to PSS1) + * | | | + * | +---> PS0---+ + * | | + * PSS0---+ +--> FD7 (Added after PS0 is added to PSS1) + * | + * | + * | +---> FD3 (Added before PS1 is added to PSS0) + * | | + * +---> PS1---+ + * | | + * | +---> FD8 (Added after PS1 added to PSS0) + * | + * | + * | +---> FD4 (Added before PS2 is added to PSS0) + * | | + * +---> PS2---+ + * | + * +---> FD9 (Added after PS2 is added to PSS0) + */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker; + grpc_millis deadline; + + test_fd tfds[10]; + test_pollset pollsets[3]; + test_pollset_set pollset_sets[2]; + const int num_fds = GPR_ARRAY_SIZE(tfds); + const int num_ps = GPR_ARRAY_SIZE(pollsets); + const int num_pss = GPR_ARRAY_SIZE(pollset_sets); + + init_test_fds(&exec_ctx, tfds, num_fds); + init_test_pollsets(pollsets, num_ps); + init_test_pollset_sets(pollset_sets, num_pss); + + /* Construct the pollset_set/pollset/fd tree (see diagram above) */ + + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); + + grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[2].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[3].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[4].fd); + + grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss, + pollset_sets[1].pss); + + grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps); + grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps); + grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps); + + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd); + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd); + + grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[7].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[8].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[9].fd); + + grpc_exec_ctx_flush(&exec_ctx); + + /* Test that if any FD in the above structure is readable, it is observable by + * doing grpc_pollset_work on any pollset + * + * For every pollset, do the following: + * - (Ensure that all FDs are in reset state) + * - Make all FDs readable + * - Call grpc_pollset_work() on the pollset + * - Flush the exec_ctx + * - Verify that on_readable call back was called for all FDs (and + * reset the FDs) + * */ + for (int i = 0; i < num_ps; i++) { + make_test_fds_readable(tfds, num_fds); + + gpr_mu_lock(pollsets[i].mu); + deadline = grpc_timespec_to_millis_round_up( + grpc_timeout_milliseconds_to_deadline(2)); + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_pollset_work(&exec_ctx, pollsets[i].ps, &worker, deadline)); + gpr_mu_unlock(pollsets[i].mu); + + grpc_exec_ctx_flush(&exec_ctx); + + verify_readable_and_reset(&exec_ctx, tfds, num_fds); + grpc_exec_ctx_flush(&exec_ctx); + } + + /* Test tear down */ + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd); + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps); + grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps); + grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps); + + grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss, + pollset_sets[1].pss); + grpc_exec_ctx_flush(&exec_ctx); + + cleanup_test_fds(&exec_ctx, tfds, num_fds); + cleanup_test_pollsets(&exec_ctx, pollsets, num_ps); + cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss); + grpc_exec_ctx_finish(&exec_ctx); +} + +/* Same FD added multiple times to the pollset_set tree */ +void pollset_set_test_dup_fds() { + /* We construct the following structure for this test: + * + * +---> FD0 + * | + * | + * PSS0---+ + * | +---> FD0 (also under PSS0) + * | | + * +---> PSS1--+ +--> FD1 (also under PSS1) + * | | + * +---> PS ---+ + * | | + * | +--> FD2 + * +---> FD1 + */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker; + grpc_millis deadline; + + test_fd tfds[3]; + test_pollset pollset; + test_pollset_set pollset_sets[2]; + const int num_fds = GPR_ARRAY_SIZE(tfds); + const int num_ps = 1; + const int num_pss = GPR_ARRAY_SIZE(pollset_sets); + + init_test_fds(&exec_ctx, tfds, num_fds); + init_test_pollsets(&pollset, num_ps); + init_test_pollset_sets(pollset_sets, num_pss); + + /* Construct the structure */ + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd); + grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); + + grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[1].fd); + grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[2].fd); + + grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps); + grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss, + pollset_sets[1].pss); + + /* Test. Make all FDs readable and make sure that can be observed by doing a + * grpc_pollset_work on the pollset 'PS' */ + make_test_fds_readable(tfds, num_fds); + + gpr_mu_lock(pollset.mu); + deadline = grpc_timespec_to_millis_round_up( + grpc_timeout_milliseconds_to_deadline(2)); + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_pollset_work(&exec_ctx, pollset.ps, &worker, deadline)); + gpr_mu_unlock(pollset.mu); + grpc_exec_ctx_flush(&exec_ctx); + + verify_readable_and_reset(&exec_ctx, tfds, num_fds); + grpc_exec_ctx_flush(&exec_ctx); + + /* Tear down */ + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd); + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd); + grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd); + + grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps); + grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss, + pollset_sets[1].pss); + grpc_exec_ctx_flush(&exec_ctx); + + cleanup_test_fds(&exec_ctx, tfds, num_fds); + cleanup_test_pollsets(&exec_ctx, &pollset, num_ps); + cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss); + grpc_exec_ctx_finish(&exec_ctx); +} + +/* Pollset_set with an empty pollset */ +void pollset_set_test_empty_pollset() { + /* We construct the following structure for this test: + * + * +---> PS0 (EMPTY) + * | + * +---> FD0 + * | + * PSS0---+ + * | +---> FD1 + * | | + * +---> PS1--+ + * | + * +---> FD2 + */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_worker *worker; + grpc_millis deadline; + + test_fd tfds[3]; + test_pollset pollsets[2]; + test_pollset_set pollset_set; + const int num_fds = GPR_ARRAY_SIZE(tfds); + const int num_ps = GPR_ARRAY_SIZE(pollsets); + const int num_pss = 1; + + init_test_fds(&exec_ctx, tfds, num_fds); + init_test_pollsets(pollsets, num_ps); + init_test_pollset_sets(&pollset_set, num_pss); + + /* Construct the structure */ + grpc_pollset_set_add_fd(&exec_ctx, pollset_set.pss, tfds[0].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[1].fd); + grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[2].fd); + + grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps); + grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps); + + /* Test. Make all FDs readable and make sure that can be observed by doing + * grpc_pollset_work on the empty pollset 'PS0' */ + make_test_fds_readable(tfds, num_fds); + + gpr_mu_lock(pollsets[0].mu); + deadline = grpc_timespec_to_millis_round_up( + grpc_timeout_milliseconds_to_deadline(2)); + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_pollset_work(&exec_ctx, pollsets[0].ps, &worker, deadline)); + gpr_mu_unlock(pollsets[0].mu); + grpc_exec_ctx_flush(&exec_ctx); + + verify_readable_and_reset(&exec_ctx, tfds, num_fds); + grpc_exec_ctx_flush(&exec_ctx); + + /* Tear down */ + grpc_pollset_set_del_fd(&exec_ctx, pollset_set.pss, tfds[0].fd); + grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps); + grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps); + grpc_exec_ctx_flush(&exec_ctx); + + cleanup_test_fds(&exec_ctx, tfds, num_fds); + cleanup_test_pollsets(&exec_ctx, pollsets, num_ps); + cleanup_test_pollset_sets(&exec_ctx, &pollset_set, num_pss); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + const char *poll_strategy = grpc_get_poll_strategy_name(); + + if (poll_strategy != NULL && + (strcmp(poll_strategy, "epollsig") == 0 || + strcmp(poll_strategy, "epoll-threadpool") == 0)) { + pollset_set_test_basic(); + pollset_set_test_dup_fds(); + pollset_set_test_empty_pollset(); + } else { + gpr_log(GPR_INFO, + "Skipping the test. The test is only relevant for 'epoll' " + "strategy. and the current strategy is: '%s'", + poll_strategy); + } + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} +#else /* defined(GRPC_LINUX_EPOLL) */ +int main(int argc, char **argv) { return 0; } +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/test/core/iomgr/resolve_address_posix_test.c b/test/core/iomgr/resolve_address_posix_test.c deleted file mode 100644 index cb9d6080fb..0000000000 --- a/test/core/iomgr/resolve_address_posix_test.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/resolve_address.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -static gpr_timespec test_deadline(void) { - return grpc_timeout_seconds_to_deadline(100); -} - -typedef struct args_struct { - gpr_event ev; - grpc_resolved_addresses *addrs; - gpr_atm done_atm; - gpr_mu *mu; - grpc_pollset *pollset; - grpc_pollset_set *pollset_set; -} args_struct; - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} - -void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { - gpr_event_init(&args->ev); - args->pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(args->pollset, &args->mu); - args->pollset_set = grpc_pollset_set_create(); - grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); - args->addrs = NULL; -} - -void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { - GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline())); - grpc_resolved_addresses_destroy(args->addrs); - grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset); - grpc_pollset_set_destroy(exec_ctx, args->pollset_set); - grpc_closure do_nothing_cb; - GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); - // exec_ctx needs to be flushed before calling grpc_pollset_destroy() - grpc_exec_ctx_flush(exec_ctx); - grpc_pollset_destroy(exec_ctx, args->pollset); - gpr_free(args->pollset); -} - -static grpc_millis n_sec_deadline(int seconds) { - return grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(seconds)); -} - -static void actually_poll(void *argsp) { - args_struct *args = argsp; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis deadline = n_sec_deadline(10); - while (true) { - bool done = gpr_atm_acq_load(&args->done_atm) != 0; - if (done) { - break; - } - grpc_millis time_left = deadline - grpc_exec_ctx_now(&exec_ctx); - gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRIdPTR, done, time_left); - GPR_ASSERT(time_left >= 0); - grpc_pollset_worker *worker = NULL; - gpr_mu_lock(args->mu); - GRPC_LOG_IF_ERROR("pollset_work", - grpc_pollset_work(&exec_ctx, args->pollset, &worker, - n_sec_deadline(1))); - gpr_mu_unlock(args->mu); - grpc_exec_ctx_flush(&exec_ctx); - } - gpr_event_set(&args->ev, (void *)1); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void poll_pollset_until_request_done(args_struct *args) { - gpr_atm_rel_store(&args->done_atm, 0); - gpr_thd_id id; - gpr_thd_new(&id, actually_poll, args, NULL); -} - -static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, - grpc_error *err) { - args_struct *args = argsp; - GPR_ASSERT(err == GRPC_ERROR_NONE); - GPR_ASSERT(args->addrs != NULL); - GPR_ASSERT(args->addrs->naddrs > 0); - gpr_atm_rel_store(&args->done_atm, 1); -} - -static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { - args_struct *args = argsp; - GPR_ASSERT(err != GRPC_ERROR_NONE); - gpr_atm_rel_store(&args->done_atm, 1); -} - -static void test_unix_socket(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - poll_pollset_until_request_done(&args); - grpc_resolve_address( - &exec_ctx, "unix:/path/name", NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_unix_socket_path_name_too_long(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - const char prefix[] = "unix:/path/name"; - size_t path_name_length = - GPR_ARRAY_SIZE(((struct sockaddr_un *)0)->sun_path) + 6; - char *path_name = gpr_malloc(sizeof(char) * path_name_length); - memset(path_name, 'a', path_name_length); - memcpy(path_name, prefix, strlen(prefix) - 1); - path_name[path_name_length - 1] = '\0'; - - poll_pollset_until_request_done(&args); - grpc_resolve_address( - &exec_ctx, path_name, NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - gpr_free(path_name); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - test_unix_socket(); - test_unix_socket_path_name_too_long(); - grpc_executor_shutdown(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc new file mode 100644 index 0000000000..572b4222b5 --- /dev/null +++ b/test/core/iomgr/resolve_address_posix_test.cc @@ -0,0 +1,171 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/resolve_address.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +static gpr_timespec test_deadline(void) { + return grpc_timeout_seconds_to_deadline(100); +} + +typedef struct args_struct { + gpr_event ev; + grpc_resolved_addresses *addrs; + gpr_atm done_atm; + gpr_mu *mu; + grpc_pollset *pollset; + grpc_pollset_set *pollset_set; +} args_struct; + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} + +void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { + gpr_event_init(&args->ev); + args->pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(args->pollset, &args->mu); + args->pollset_set = grpc_pollset_set_create(); + grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); + args->addrs = NULL; +} + +void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { + GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline())); + grpc_resolved_addresses_destroy(args->addrs); + grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset); + grpc_pollset_set_destroy(exec_ctx, args->pollset_set); + grpc_closure do_nothing_cb; + GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); + // exec_ctx needs to be flushed before calling grpc_pollset_destroy() + grpc_exec_ctx_flush(exec_ctx); + grpc_pollset_destroy(exec_ctx, args->pollset); + gpr_free(args->pollset); +} + +static grpc_millis n_sec_deadline(int seconds) { + return grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(seconds)); +} + +static void actually_poll(void *argsp) { + args_struct *args = static_cast(argsp); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis deadline = n_sec_deadline(10); + while (true) { + bool done = gpr_atm_acq_load(&args->done_atm) != 0; + if (done) { + break; + } + grpc_millis time_left = deadline - grpc_exec_ctx_now(&exec_ctx); + gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRIdPTR, done, time_left); + GPR_ASSERT(time_left >= 0); + grpc_pollset_worker *worker = NULL; + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_work", + grpc_pollset_work(&exec_ctx, args->pollset, &worker, + n_sec_deadline(1))); + gpr_mu_unlock(args->mu); + grpc_exec_ctx_flush(&exec_ctx); + } + gpr_event_set(&args->ev, (void *)1); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void poll_pollset_until_request_done(args_struct *args) { + gpr_atm_rel_store(&args->done_atm, 0); + gpr_thd_id id; + gpr_thd_new(&id, actually_poll, args, NULL); +} + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, + grpc_error *err) { + args_struct *args = static_cast(argsp); + GPR_ASSERT(err == GRPC_ERROR_NONE); + GPR_ASSERT(args->addrs != NULL); + GPR_ASSERT(args->addrs->naddrs > 0); + gpr_atm_rel_store(&args->done_atm, 1); +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { + args_struct *args = static_cast(argsp); + GPR_ASSERT(err != GRPC_ERROR_NONE); + gpr_atm_rel_store(&args->done_atm, 1); +} + +static void test_unix_socket(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + poll_pollset_until_request_done(&args); + grpc_resolve_address( + &exec_ctx, "unix:/path/name", NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_unix_socket_path_name_too_long(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + const char prefix[] = "unix:/path/name"; + size_t path_name_length = + GPR_ARRAY_SIZE(((struct sockaddr_un *)0)->sun_path) + 6; + char *path_name = + static_cast(gpr_malloc(sizeof(char) * path_name_length)); + memset(path_name, 'a', path_name_length); + memcpy(path_name, prefix, strlen(prefix) - 1); + path_name[path_name_length - 1] = '\0'; + + poll_pollset_until_request_done(&args); + grpc_resolve_address( + &exec_ctx, path_name, NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + gpr_free(path_name); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + test_unix_socket(); + test_unix_socket_path_name_too_long(); + grpc_executor_shutdown(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c deleted file mode 100644 index 178bbbb95f..0000000000 --- a/test/core/iomgr/resolve_address_test.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/resolve_address.h" -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -static gpr_timespec test_deadline(void) { - return grpc_timeout_seconds_to_deadline(100); -} - -typedef struct args_struct { - gpr_event ev; - grpc_resolved_addresses *addrs; - gpr_atm done_atm; - gpr_mu *mu; - grpc_pollset *pollset; - grpc_pollset_set *pollset_set; -} args_struct; - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} - -void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { - gpr_event_init(&args->ev); - args->pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(args->pollset, &args->mu); - args->pollset_set = grpc_pollset_set_create(); - grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); - args->addrs = NULL; - gpr_atm_rel_store(&args->done_atm, 0); -} - -void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { - GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline())); - grpc_resolved_addresses_destroy(args->addrs); - grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset); - grpc_pollset_set_destroy(exec_ctx, args->pollset_set); - grpc_closure do_nothing_cb; - GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, - grpc_schedule_on_exec_ctx); - gpr_mu_lock(args->mu); - grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); - gpr_mu_unlock(args->mu); - // exec_ctx needs to be flushed before calling grpc_pollset_destroy() - grpc_exec_ctx_flush(exec_ctx); - grpc_pollset_destroy(exec_ctx, args->pollset); - gpr_free(args->pollset); -} - -static grpc_millis n_sec_deadline(int seconds) { - return grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(seconds)); -} - -static void poll_pollset_until_request_done(args_struct *args) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis deadline = n_sec_deadline(10); - while (true) { - bool done = gpr_atm_acq_load(&args->done_atm) != 0; - if (done) { - break; - } - grpc_millis time_left = deadline - grpc_exec_ctx_now(&exec_ctx); - gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRIdPTR, done, time_left); - GPR_ASSERT(time_left >= 0); - grpc_pollset_worker *worker = NULL; - gpr_mu_lock(args->mu); - GRPC_LOG_IF_ERROR("pollset_work", - grpc_pollset_work(&exec_ctx, args->pollset, &worker, - n_sec_deadline(1))); - gpr_mu_unlock(args->mu); - grpc_exec_ctx_flush(&exec_ctx); - } - gpr_event_set(&args->ev, (void *)1); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, - grpc_error *err) { - args_struct *args = argsp; - GPR_ASSERT(err == GRPC_ERROR_NONE); - GPR_ASSERT(args->addrs != NULL); - GPR_ASSERT(args->addrs->naddrs > 0); - gpr_atm_rel_store(&args->done_atm, 1); - gpr_mu_lock(args->mu); - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, args->pollset, NULL)); - gpr_mu_unlock(args->mu); -} - -static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { - args_struct *args = argsp; - GPR_ASSERT(err != GRPC_ERROR_NONE); - gpr_atm_rel_store(&args->done_atm, 1); - gpr_mu_lock(args->mu); - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, args->pollset, NULL)); - gpr_mu_unlock(args->mu); -} - -static void test_localhost(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, "localhost:1", NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_default_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, "localhost", "1", args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_non_numeric_default_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, "localhost", "https", args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_missing_default_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, "localhost", NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_ipv6_with_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, "[2001:db8::1]:1", NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_ipv6_without_port(void) { - const char *const kCases[] = { - "2001:db8::1", "2001:db8::1.2.3.4", "[2001:db8::1]", - }; - unsigned i; - for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, kCases[i], "80", args.pollset_set, - GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_invalid_ip_addresses(void) { - const char *const kCases[] = { - "293.283.1238.3:1", "[2001:db8::11111]:1", - }; - unsigned i; - for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, kCases[i], NULL, args.pollset_set, - GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_unparseable_hostports(void) { - const char *const kCases[] = { - "[", "[::1", "[::1]bad", "[1.2.3.4]", "[localhost]", "[localhost]:1", - }; - unsigned i; - for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - args_struct args; - args_init(&exec_ctx, &args); - grpc_resolve_address( - &exec_ctx, kCases[i], "1", args.pollset_set, - GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), - &args.addrs); - grpc_exec_ctx_flush(&exec_ctx); - poll_pollset_until_request_done(&args); - args_finish(&exec_ctx, &args); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - test_localhost(); - test_default_port(); - test_non_numeric_default_port(); - test_missing_default_port(); - test_ipv6_with_port(); - test_ipv6_without_port(); - test_invalid_ip_addresses(); - test_unparseable_hostports(); - grpc_executor_shutdown(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc new file mode 100644 index 0000000000..da6aab3518 --- /dev/null +++ b/test/core/iomgr/resolve_address_test.cc @@ -0,0 +1,268 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/resolve_address.h" +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +static gpr_timespec test_deadline(void) { + return grpc_timeout_seconds_to_deadline(100); +} + +typedef struct args_struct { + gpr_event ev; + grpc_resolved_addresses *addrs; + gpr_atm done_atm; + gpr_mu *mu; + grpc_pollset *pollset; + grpc_pollset_set *pollset_set; +} args_struct; + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} + +void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { + gpr_event_init(&args->ev); + args->pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(args->pollset, &args->mu); + args->pollset_set = grpc_pollset_set_create(); + grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); + args->addrs = NULL; + gpr_atm_rel_store(&args->done_atm, 0); +} + +void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { + GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline())); + grpc_resolved_addresses_destroy(args->addrs); + grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset); + grpc_pollset_set_destroy(exec_ctx, args->pollset_set); + grpc_closure do_nothing_cb; + GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, + grpc_schedule_on_exec_ctx); + gpr_mu_lock(args->mu); + grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); + gpr_mu_unlock(args->mu); + // exec_ctx needs to be flushed before calling grpc_pollset_destroy() + grpc_exec_ctx_flush(exec_ctx); + grpc_pollset_destroy(exec_ctx, args->pollset); + gpr_free(args->pollset); +} + +static grpc_millis n_sec_deadline(int seconds) { + return grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(seconds)); +} + +static void poll_pollset_until_request_done(args_struct *args) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis deadline = n_sec_deadline(10); + while (true) { + bool done = gpr_atm_acq_load(&args->done_atm) != 0; + if (done) { + break; + } + grpc_millis time_left = deadline - grpc_exec_ctx_now(&exec_ctx); + gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRIdPTR, done, time_left); + GPR_ASSERT(time_left >= 0); + grpc_pollset_worker *worker = NULL; + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_work", + grpc_pollset_work(&exec_ctx, args->pollset, &worker, + n_sec_deadline(1))); + gpr_mu_unlock(args->mu); + grpc_exec_ctx_flush(&exec_ctx); + } + gpr_event_set(&args->ev, (void *)1); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp, + grpc_error *err) { + args_struct *args = static_cast(argsp); + GPR_ASSERT(err == GRPC_ERROR_NONE); + GPR_ASSERT(args->addrs != NULL); + GPR_ASSERT(args->addrs->naddrs > 0); + gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, args->pollset, NULL)); + gpr_mu_unlock(args->mu); +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) { + args_struct *args = static_cast(argsp); + GPR_ASSERT(err != GRPC_ERROR_NONE); + gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, args->pollset, NULL)); + gpr_mu_unlock(args->mu); +} + +static void test_localhost(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "localhost:1", NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_default_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "localhost", "1", args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_non_numeric_default_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "localhost", "https", args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_missing_default_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "localhost", NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_ipv6_with_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, "[2001:db8::1]:1", NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_ipv6_without_port(void) { + const char *const kCases[] = { + "2001:db8::1", "2001:db8::1.2.3.4", "[2001:db8::1]", + }; + unsigned i; + for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, kCases[i], "80", args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_invalid_ip_addresses(void) { + const char *const kCases[] = { + "293.283.1238.3:1", "[2001:db8::11111]:1", + }; + unsigned i; + for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, kCases[i], NULL, args.pollset_set, + GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_unparseable_hostports(void) { + const char *const kCases[] = { + "[", "[::1", "[::1]bad", "[1.2.3.4]", "[localhost]", "[localhost]:1", + }; + unsigned i; + for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + args_struct args; + args_init(&exec_ctx, &args); + grpc_resolve_address( + &exec_ctx, kCases[i], "1", args.pollset_set, + GRPC_CLOSURE_CREATE(must_fail, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_exec_ctx_flush(&exec_ctx); + poll_pollset_until_request_done(&args); + args_finish(&exec_ctx, &args); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + test_localhost(); + test_default_port(); + test_non_numeric_default_port(); + test_missing_default_port(); + test_ipv6_with_port(); + test_ipv6_without_port(); + test_invalid_ip_addresses(); + test_unparseable_hostports(); + grpc_executor_shutdown(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} diff --git a/test/core/iomgr/resource_quota_test.c b/test/core/iomgr/resource_quota_test.c deleted file mode 100644 index b588f3d120..0000000000 --- a/test/core/iomgr/resource_quota_test.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/resource_quota.h" - -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -gpr_mu g_mu; -gpr_cv g_cv; - -static void inc_int_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { - gpr_mu_lock(&g_mu); - ++*(int *)a; - gpr_cv_signal(&g_cv); - gpr_mu_unlock(&g_mu); -} - -static void assert_counter_becomes(int *ctr, int value) { - gpr_mu_lock(&g_mu); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - while (*ctr != value) { - GPR_ASSERT(!gpr_cv_wait(&g_cv, &g_mu, deadline)); - } - gpr_mu_unlock(&g_mu); -} - -static void set_event_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { - gpr_event_set((gpr_event *)a, (void *)1); -} -grpc_closure *set_event(gpr_event *ev) { - return GRPC_CLOSURE_CREATE(set_event_cb, ev, grpc_schedule_on_exec_ctx); -} - -typedef struct { - size_t size; - grpc_resource_user *resource_user; - grpc_closure *then; -} reclaimer_args; -static void reclaimer_cb(grpc_exec_ctx *exec_ctx, void *args, - grpc_error *error) { - GPR_ASSERT(error == GRPC_ERROR_NONE); - reclaimer_args *a = args; - grpc_resource_user_free(exec_ctx, a->resource_user, a->size); - grpc_resource_user_finish_reclamation(exec_ctx, a->resource_user); - GRPC_CLOSURE_RUN(exec_ctx, a->then, GRPC_ERROR_NONE); - gpr_free(a); -} -grpc_closure *make_reclaimer(grpc_resource_user *resource_user, size_t size, - grpc_closure *then) { - reclaimer_args *a = gpr_malloc(sizeof(*a)); - a->size = size; - a->resource_user = resource_user; - a->then = then; - return GRPC_CLOSURE_CREATE(reclaimer_cb, a, grpc_schedule_on_exec_ctx); -} - -static void unused_reclaimer_cb(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_ASSERT(error == GRPC_ERROR_CANCELLED); - GRPC_CLOSURE_RUN(exec_ctx, arg, GRPC_ERROR_NONE); -} -grpc_closure *make_unused_reclaimer(grpc_closure *then) { - return GRPC_CLOSURE_CREATE(unused_reclaimer_cb, then, - grpc_schedule_on_exec_ctx); -} - -static void destroy_user(grpc_resource_user *usr) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_unref(&exec_ctx, usr); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op(void) { - gpr_log(GPR_INFO, "** test_no_op **"); - grpc_resource_quota_unref(grpc_resource_quota_create("test_no_op")); -} - -static void test_resize_then_destroy(void) { - gpr_log(GPR_INFO, "** test_resize_then_destroy **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_resize_then_destroy"); - grpc_resource_quota_resize(q, 1024 * 1024); - grpc_resource_quota_unref(q); -} - -static void test_resource_user_no_op(void) { - gpr_log(GPR_INFO, "** test_resource_user_no_op **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_resource_user_no_op"); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_instant_alloc_then_free(void) { - gpr_log(GPR_INFO, "** test_instant_alloc_then_free **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_instant_alloc_then_free"); - grpc_resource_quota_resize(q, 1024 * 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); - grpc_exec_ctx_finish(&exec_ctx); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_instant_alloc_free_pair(void) { - gpr_log(GPR_INFO, "** test_instant_alloc_free_pair **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_instant_alloc_free_pair"); - grpc_resource_quota_resize(q, 1024 * 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_simple_async_alloc(void) { - gpr_log(GPR_INFO, "** test_simple_async_alloc **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_simple_async_alloc"); - grpc_resource_quota_resize(q, 1024 * 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_async_alloc_blocked_by_size(void) { - gpr_log(GPR_INFO, "** test_async_alloc_blocked_by_size **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_async_alloc_blocked_by_size"); - grpc_resource_quota_resize(q, 1); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - gpr_event ev; - gpr_event_init(&ev); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait( - &ev, grpc_timeout_milliseconds_to_deadline(100)) == NULL); - } - grpc_resource_quota_resize(q, 1024); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != NULL); - ; - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_scavenge(void) { - gpr_log(GPR_INFO, "** test_scavenge **"); - grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); - grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr1, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr2, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr1); - destroy_user(usr2); -} - -static void test_scavenge_blocked(void) { - gpr_log(GPR_INFO, "** test_scavenge_blocked **"); - grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge_blocked"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); - grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); - gpr_event ev; - { - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait( - &ev, grpc_timeout_milliseconds_to_deadline(100)) == NULL); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr1, 1024); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr2, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr1); - destroy_user(usr2); -} - -static void test_blocked_until_scheduled_reclaim(void) { - gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_blocked_until_scheduled_reclaim"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - gpr_event reclaim_done; - gpr_event_init(&reclaim_done); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, - make_reclaimer(usr, 1024, set_event(&reclaim_done))); - grpc_exec_ctx_finish(&exec_ctx); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaim_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_blocked_until_scheduled_reclaim_and_scavenge(void) { - gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim_and_scavenge **"); - grpc_resource_quota *q = grpc_resource_quota_create( - "test_blocked_until_scheduled_reclaim_and_scavenge"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); - grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - gpr_event reclaim_done; - gpr_event_init(&reclaim_done); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr1, false, - make_reclaimer(usr1, 1024, set_event(&reclaim_done))); - grpc_exec_ctx_finish(&exec_ctx); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaim_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr2, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr1); - destroy_user(usr2); -} - -static void test_blocked_until_scheduled_destructive_reclaim(void) { - gpr_log(GPR_INFO, "** test_blocked_until_scheduled_destructive_reclaim **"); - grpc_resource_quota *q = grpc_resource_quota_create( - "test_blocked_until_scheduled_destructive_reclaim"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - gpr_event reclaim_done; - gpr_event_init(&reclaim_done); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, true, - make_reclaimer(usr, 1024, set_event(&reclaim_done))); - grpc_exec_ctx_finish(&exec_ctx); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaim_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); -} - -static void test_unused_reclaim_is_cancelled(void) { - gpr_log(GPR_INFO, "** test_unused_reclaim_is_cancelled **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_unused_reclaim_is_cancelled"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - gpr_event benign_done; - gpr_event_init(&benign_done); - gpr_event destructive_done; - gpr_event_init(&destructive_done); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, make_unused_reclaimer(set_event(&benign_done))); - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, true, - make_unused_reclaimer(set_event(&destructive_done))); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - grpc_resource_quota_unref(q); - destroy_user(usr); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); -} - -static void test_benign_reclaim_is_preferred(void) { - gpr_log(GPR_INFO, "** test_benign_reclaim_is_preferred **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_benign_reclaim_is_preferred"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - gpr_event benign_done; - gpr_event_init(&benign_done); - gpr_event destructive_done; - gpr_event_init(&destructive_done); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, - make_reclaimer(usr, 1024, set_event(&benign_done))); - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, true, - make_unused_reclaimer(set_event(&destructive_done))); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); -} - -static void test_multiple_reclaims_can_be_triggered(void) { - gpr_log(GPR_INFO, "** test_multiple_reclaims_can_be_triggered **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_multiple_reclaims_can_be_triggered"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - gpr_event benign_done; - gpr_event_init(&benign_done); - gpr_event destructive_done; - gpr_event_init(&destructive_done); - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, - make_reclaimer(usr, 512, set_event(&benign_done))); - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, true, - make_reclaimer(usr, 512, set_event(&destructive_done))); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - gpr_event ev; - gpr_event_init(&ev); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != - NULL); - ; - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_resource_quota_unref(q); - destroy_user(usr); - GPR_ASSERT(gpr_event_wait(&benign_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&destructive_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); -} - -static void test_resource_user_stays_allocated_until_memory_released(void) { - gpr_log(GPR_INFO, - "** test_resource_user_stays_allocated_until_memory_released **"); - grpc_resource_quota *q = grpc_resource_quota_create( - "test_resource_user_stays_allocated_until_memory_released"); - grpc_resource_quota_resize(q, 1024 * 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); - grpc_exec_ctx_finish(&exec_ctx); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_quota_unref(q); - grpc_resource_user_unref(&exec_ctx, usr); - grpc_exec_ctx_finish(&exec_ctx); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void -test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released( - void) { - gpr_log(GPR_INFO, - "** " - "test_resource_user_stays_allocated_and_reclaimers_unrun_until_" - "memory_released **"); - grpc_resource_quota *q = grpc_resource_quota_create( - "test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_" - "released"); - grpc_resource_quota_resize(q, 1024); - for (int i = 0; i < 10; i++) { - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - gpr_event reclaimer_cancelled; - gpr_event_init(&reclaimer_cancelled); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, - make_unused_reclaimer(set_event(&reclaimer_cancelled))); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - gpr_event allocated; - gpr_event_init(&allocated); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&allocated, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_unref(&exec_ctx, usr); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, - grpc_timeout_seconds_to_deadline(5)) != NULL); - } - } - grpc_resource_quota_unref(q); -} - -static void test_reclaimers_can_be_posted_repeatedly(void) { - gpr_log(GPR_INFO, "** test_reclaimers_can_be_posted_repeatedly **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_reclaimers_can_be_posted_repeatedly"); - grpc_resource_quota_resize(q, 1024); - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - { - gpr_event allocated; - gpr_event_init(&allocated); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&allocated, - grpc_timeout_seconds_to_deadline(5)) != NULL); - } - for (int i = 0; i < 10; i++) { - gpr_event reclaimer_done; - gpr_event_init(&reclaimer_done); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_post_reclaimer( - &exec_ctx, usr, false, - make_reclaimer(usr, 1024, set_event(&reclaimer_done))); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&reclaimer_done, - grpc_timeout_milliseconds_to_deadline(100)) == - NULL); - } - { - gpr_event allocated; - gpr_event_init(&allocated); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(gpr_event_wait(&allocated, - grpc_timeout_seconds_to_deadline(5)) != NULL); - GPR_ASSERT(gpr_event_wait(&reclaimer_done, - grpc_timeout_seconds_to_deadline(5)) != NULL); - } - } - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_free(&exec_ctx, usr, 1024); - grpc_exec_ctx_finish(&exec_ctx); - } - destroy_user(usr); - grpc_resource_quota_unref(q); -} - -static void test_one_slice(void) { - gpr_log(GPR_INFO, "** test_one_slice **"); - - grpc_resource_quota *q = grpc_resource_quota_create("test_one_slice"); - grpc_resource_quota_resize(q, 1024); - - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - - grpc_resource_user_slice_allocator alloc; - int num_allocs = 0; - grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); - - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - - { - const int start_allocs = num_allocs; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - assert_counter_becomes(&num_allocs, start_allocs + 1); - } - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - } - destroy_user(usr); - grpc_resource_quota_unref(q); -} - -static void test_one_slice_deleted_late(void) { - gpr_log(GPR_INFO, "** test_one_slice_deleted_late **"); - - grpc_resource_quota *q = - grpc_resource_quota_create("test_one_slice_deleted_late"); - grpc_resource_quota_resize(q, 1024); - - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - - grpc_resource_user_slice_allocator alloc; - int num_allocs = 0; - grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); - - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - - { - const int start_allocs = num_allocs; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - assert_counter_becomes(&num_allocs, start_allocs + 1); - } - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_unref(&exec_ctx, usr); - grpc_exec_ctx_finish(&exec_ctx); - } - - grpc_resource_quota_unref(q); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_resize_to_zero(void) { - gpr_log(GPR_INFO, "** test_resize_to_zero **"); - grpc_resource_quota *q = grpc_resource_quota_create("test_resize_to_zero"); - grpc_resource_quota_resize(q, 0); - grpc_resource_quota_unref(q); -} - -static void test_negative_rq_free_pool(void) { - gpr_log(GPR_INFO, "** test_negative_rq_free_pool **"); - grpc_resource_quota *q = - grpc_resource_quota_create("test_negative_rq_free_pool"); - grpc_resource_quota_resize(q, 1024); - - grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); - - grpc_resource_user_slice_allocator alloc; - int num_allocs = 0; - grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); - - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - - { - const int start_allocs = num_allocs; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - assert_counter_becomes(&num_allocs, start_allocs + 1); - } - - grpc_resource_quota_resize(q, 512); - - double eps = 0.0001; - GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) < 1 + eps); - GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) > 1 - eps); - - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resource_user_unref(&exec_ctx, usr); - grpc_exec_ctx_finish(&exec_ctx); - } - - grpc_resource_quota_unref(q); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - gpr_mu_init(&g_mu); - gpr_cv_init(&g_cv); - test_no_op(); - test_resize_then_destroy(); - test_resource_user_no_op(); - test_instant_alloc_then_free(); - test_instant_alloc_free_pair(); - test_simple_async_alloc(); - test_async_alloc_blocked_by_size(); - test_scavenge(); - test_scavenge_blocked(); - test_blocked_until_scheduled_reclaim(); - test_blocked_until_scheduled_reclaim_and_scavenge(); - test_blocked_until_scheduled_destructive_reclaim(); - test_unused_reclaim_is_cancelled(); - test_benign_reclaim_is_preferred(); - test_multiple_reclaims_can_be_triggered(); - test_resource_user_stays_allocated_until_memory_released(); - test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released(); - test_reclaimers_can_be_posted_repeatedly(); - test_one_slice(); - test_one_slice_deleted_late(); - test_resize_to_zero(); - test_negative_rq_free_pool(); - gpr_mu_destroy(&g_mu); - gpr_cv_destroy(&g_cv); - grpc_shutdown(); - return 0; -} diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc new file mode 100644 index 0000000000..f0002e0947 --- /dev/null +++ b/test/core/iomgr/resource_quota_test.cc @@ -0,0 +1,864 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/resource_quota.h" + +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +gpr_mu g_mu; +gpr_cv g_cv; + +static void inc_int_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { + gpr_mu_lock(&g_mu); + ++*(int *)a; + gpr_cv_signal(&g_cv); + gpr_mu_unlock(&g_mu); +} + +static void assert_counter_becomes(int *ctr, int value) { + gpr_mu_lock(&g_mu); + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); + while (*ctr != value) { + GPR_ASSERT(!gpr_cv_wait(&g_cv, &g_mu, deadline)); + } + gpr_mu_unlock(&g_mu); +} + +static void set_event_cb(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { + gpr_event_set((gpr_event *)a, (void *)1); +} +grpc_closure *set_event(gpr_event *ev) { + return GRPC_CLOSURE_CREATE(set_event_cb, ev, grpc_schedule_on_exec_ctx); +} + +typedef struct { + size_t size; + grpc_resource_user *resource_user; + grpc_closure *then; +} reclaimer_args; +static void reclaimer_cb(grpc_exec_ctx *exec_ctx, void *args, + grpc_error *error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + reclaimer_args *a = static_cast(args); + grpc_resource_user_free(exec_ctx, a->resource_user, a->size); + grpc_resource_user_finish_reclamation(exec_ctx, a->resource_user); + GRPC_CLOSURE_RUN(exec_ctx, a->then, GRPC_ERROR_NONE); + gpr_free(a); +} +grpc_closure *make_reclaimer(grpc_resource_user *resource_user, size_t size, + grpc_closure *then) { + reclaimer_args *a = static_cast(gpr_malloc(sizeof(*a))); + a->size = size; + a->resource_user = resource_user; + a->then = then; + return GRPC_CLOSURE_CREATE(reclaimer_cb, a, grpc_schedule_on_exec_ctx); +} + +static void unused_reclaimer_cb(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(error == GRPC_ERROR_CANCELLED); + GRPC_CLOSURE_RUN(exec_ctx, static_cast(arg), GRPC_ERROR_NONE); +} +grpc_closure *make_unused_reclaimer(grpc_closure *then) { + return GRPC_CLOSURE_CREATE(unused_reclaimer_cb, then, + grpc_schedule_on_exec_ctx); +} + +static void destroy_user(grpc_resource_user *usr) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op(void) { + gpr_log(GPR_INFO, "** test_no_op **"); + grpc_resource_quota_unref(grpc_resource_quota_create("test_no_op")); +} + +static void test_resize_then_destroy(void) { + gpr_log(GPR_INFO, "** test_resize_then_destroy **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_resize_then_destroy"); + grpc_resource_quota_resize(q, 1024 * 1024); + grpc_resource_quota_unref(q); +} + +static void test_resource_user_no_op(void) { + gpr_log(GPR_INFO, "** test_resource_user_no_op **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_resource_user_no_op"); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_instant_alloc_then_free(void) { + gpr_log(GPR_INFO, "** test_instant_alloc_then_free **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_instant_alloc_then_free"); + grpc_resource_quota_resize(q, 1024 * 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); + grpc_exec_ctx_finish(&exec_ctx); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_instant_alloc_free_pair(void) { + gpr_log(GPR_INFO, "** test_instant_alloc_free_pair **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_instant_alloc_free_pair"); + grpc_resource_quota_resize(q, 1024 * 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_simple_async_alloc(void) { + gpr_log(GPR_INFO, "** test_simple_async_alloc **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_simple_async_alloc"); + grpc_resource_quota_resize(q, 1024 * 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_async_alloc_blocked_by_size(void) { + gpr_log(GPR_INFO, "** test_async_alloc_blocked_by_size **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_async_alloc_blocked_by_size"); + grpc_resource_quota_resize(q, 1); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + gpr_event ev; + gpr_event_init(&ev); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait( + &ev, grpc_timeout_milliseconds_to_deadline(100)) == NULL); + } + grpc_resource_quota_resize(q, 1024); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != NULL); + ; + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_scavenge(void) { + gpr_log(GPR_INFO, "** test_scavenge **"); + grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); + grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr1, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr2, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr1); + destroy_user(usr2); +} + +static void test_scavenge_blocked(void) { + gpr_log(GPR_INFO, "** test_scavenge_blocked **"); + grpc_resource_quota *q = grpc_resource_quota_create("test_scavenge_blocked"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); + grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); + gpr_event ev; + { + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait( + &ev, grpc_timeout_milliseconds_to_deadline(100)) == NULL); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr1, 1024); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr2, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr1); + destroy_user(usr2); +} + +static void test_blocked_until_scheduled_reclaim(void) { + gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_blocked_until_scheduled_reclaim"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + gpr_event reclaim_done; + gpr_event_init(&reclaim_done); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, + make_reclaimer(usr, 1024, set_event(&reclaim_done))); + grpc_exec_ctx_finish(&exec_ctx); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaim_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_blocked_until_scheduled_reclaim_and_scavenge(void) { + gpr_log(GPR_INFO, "** test_blocked_until_scheduled_reclaim_and_scavenge **"); + grpc_resource_quota *q = grpc_resource_quota_create( + "test_blocked_until_scheduled_reclaim_and_scavenge"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr1 = grpc_resource_user_create(q, "usr1"); + grpc_resource_user *usr2 = grpc_resource_user_create(q, "usr2"); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr1, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + gpr_event reclaim_done; + gpr_event_init(&reclaim_done); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr1, false, + make_reclaimer(usr1, 1024, set_event(&reclaim_done))); + grpc_exec_ctx_finish(&exec_ctx); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr2, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaim_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr2, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr1); + destroy_user(usr2); +} + +static void test_blocked_until_scheduled_destructive_reclaim(void) { + gpr_log(GPR_INFO, "** test_blocked_until_scheduled_destructive_reclaim **"); + grpc_resource_quota *q = grpc_resource_quota_create( + "test_blocked_until_scheduled_destructive_reclaim"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + gpr_event reclaim_done; + gpr_event_init(&reclaim_done); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, true, + make_reclaimer(usr, 1024, set_event(&reclaim_done))); + grpc_exec_ctx_finish(&exec_ctx); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaim_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); +} + +static void test_unused_reclaim_is_cancelled(void) { + gpr_log(GPR_INFO, "** test_unused_reclaim_is_cancelled **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_unused_reclaim_is_cancelled"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + gpr_event benign_done; + gpr_event_init(&benign_done); + gpr_event destructive_done; + gpr_event_init(&destructive_done); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, make_unused_reclaimer(set_event(&benign_done))); + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, true, + make_unused_reclaimer(set_event(&destructive_done))); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + grpc_resource_quota_unref(q); + destroy_user(usr); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); +} + +static void test_benign_reclaim_is_preferred(void) { + gpr_log(GPR_INFO, "** test_benign_reclaim_is_preferred **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_benign_reclaim_is_preferred"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + gpr_event benign_done; + gpr_event_init(&benign_done); + gpr_event destructive_done; + gpr_event_init(&destructive_done); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, + make_reclaimer(usr, 1024, set_event(&benign_done))); + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, true, + make_unused_reclaimer(set_event(&destructive_done))); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); +} + +static void test_multiple_reclaims_can_be_triggered(void) { + gpr_log(GPR_INFO, "** test_multiple_reclaims_can_be_triggered **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_multiple_reclaims_can_be_triggered"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + gpr_event benign_done; + gpr_event_init(&benign_done); + gpr_event destructive_done; + gpr_event_init(&destructive_done); + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, + make_reclaimer(usr, 512, set_event(&benign_done))); + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, true, + make_reclaimer(usr, 512, set_event(&destructive_done))); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + gpr_event ev; + gpr_event_init(&ev); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&ev)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&ev, grpc_timeout_seconds_to_deadline(5)) != + NULL); + ; + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_resource_quota_unref(q); + destroy_user(usr); + GPR_ASSERT(gpr_event_wait(&benign_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&destructive_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); +} + +static void test_resource_user_stays_allocated_until_memory_released(void) { + gpr_log(GPR_INFO, + "** test_resource_user_stays_allocated_until_memory_released **"); + grpc_resource_quota *q = grpc_resource_quota_create( + "test_resource_user_stays_allocated_until_memory_released"); + grpc_resource_quota_resize(q, 1024 * 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, NULL); + grpc_exec_ctx_finish(&exec_ctx); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_quota_unref(q); + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void +test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released( + void) { + gpr_log(GPR_INFO, + "** " + "test_resource_user_stays_allocated_and_reclaimers_unrun_until_" + "memory_released **"); + grpc_resource_quota *q = grpc_resource_quota_create( + "test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_" + "released"); + grpc_resource_quota_resize(q, 1024); + for (int i = 0; i < 10; i++) { + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + gpr_event reclaimer_cancelled; + gpr_event_init(&reclaimer_cancelled); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, + make_unused_reclaimer(set_event(&reclaimer_cancelled))); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + gpr_event allocated; + gpr_event_init(&allocated); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&allocated, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaimer_cancelled, + grpc_timeout_seconds_to_deadline(5)) != NULL); + } + } + grpc_resource_quota_unref(q); +} + +static void test_reclaimers_can_be_posted_repeatedly(void) { + gpr_log(GPR_INFO, "** test_reclaimers_can_be_posted_repeatedly **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_reclaimers_can_be_posted_repeatedly"); + grpc_resource_quota_resize(q, 1024); + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + { + gpr_event allocated; + gpr_event_init(&allocated); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&allocated, + grpc_timeout_seconds_to_deadline(5)) != NULL); + } + for (int i = 0; i < 10; i++) { + gpr_event reclaimer_done; + gpr_event_init(&reclaimer_done); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_post_reclaimer( + &exec_ctx, usr, false, + make_reclaimer(usr, 1024, set_event(&reclaimer_done))); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&reclaimer_done, + grpc_timeout_milliseconds_to_deadline(100)) == + NULL); + } + { + gpr_event allocated; + gpr_event_init(&allocated); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc(&exec_ctx, usr, 1024, set_event(&allocated)); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(gpr_event_wait(&allocated, + grpc_timeout_seconds_to_deadline(5)) != NULL); + GPR_ASSERT(gpr_event_wait(&reclaimer_done, + grpc_timeout_seconds_to_deadline(5)) != NULL); + } + } + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_free(&exec_ctx, usr, 1024); + grpc_exec_ctx_finish(&exec_ctx); + } + destroy_user(usr); + grpc_resource_quota_unref(q); +} + +static void test_one_slice(void) { + gpr_log(GPR_INFO, "** test_one_slice **"); + + grpc_resource_quota *q = grpc_resource_quota_create("test_one_slice"); + grpc_resource_quota_resize(q, 1024); + + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + + grpc_resource_user_slice_allocator alloc; + int num_allocs = 0; + grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); + + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + + { + const int start_allocs = num_allocs; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + assert_counter_becomes(&num_allocs, start_allocs + 1); + } + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + } + destroy_user(usr); + grpc_resource_quota_unref(q); +} + +static void test_one_slice_deleted_late(void) { + gpr_log(GPR_INFO, "** test_one_slice_deleted_late **"); + + grpc_resource_quota *q = + grpc_resource_quota_create("test_one_slice_deleted_late"); + grpc_resource_quota_resize(q, 1024); + + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + + grpc_resource_user_slice_allocator alloc; + int num_allocs = 0; + grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); + + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + + { + const int start_allocs = num_allocs; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + assert_counter_becomes(&num_allocs, start_allocs + 1); + } + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); + } + + grpc_resource_quota_unref(q); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_resize_to_zero(void) { + gpr_log(GPR_INFO, "** test_resize_to_zero **"); + grpc_resource_quota *q = grpc_resource_quota_create("test_resize_to_zero"); + grpc_resource_quota_resize(q, 0); + grpc_resource_quota_unref(q); +} + +static void test_negative_rq_free_pool(void) { + gpr_log(GPR_INFO, "** test_negative_rq_free_pool **"); + grpc_resource_quota *q = + grpc_resource_quota_create("test_negative_rq_free_pool"); + grpc_resource_quota_resize(q, 1024); + + grpc_resource_user *usr = grpc_resource_user_create(q, "usr"); + + grpc_resource_user_slice_allocator alloc; + int num_allocs = 0; + grpc_resource_user_slice_allocator_init(&alloc, usr, inc_int_cb, &num_allocs); + + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + + { + const int start_allocs = num_allocs; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_alloc_slices(&exec_ctx, &alloc, 1024, 1, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + assert_counter_becomes(&num_allocs, start_allocs + 1); + } + + grpc_resource_quota_resize(q, 512); + + double eps = 0.0001; + GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) < 1 + eps); + GPR_ASSERT(grpc_resource_quota_get_memory_pressure(q) > 1 - eps); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resource_user_unref(&exec_ctx, usr); + grpc_exec_ctx_finish(&exec_ctx); + } + + grpc_resource_quota_unref(q); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + gpr_mu_init(&g_mu); + gpr_cv_init(&g_cv); + test_no_op(); + test_resize_then_destroy(); + test_resource_user_no_op(); + test_instant_alloc_then_free(); + test_instant_alloc_free_pair(); + test_simple_async_alloc(); + test_async_alloc_blocked_by_size(); + test_scavenge(); + test_scavenge_blocked(); + test_blocked_until_scheduled_reclaim(); + test_blocked_until_scheduled_reclaim_and_scavenge(); + test_blocked_until_scheduled_destructive_reclaim(); + test_unused_reclaim_is_cancelled(); + test_benign_reclaim_is_preferred(); + test_multiple_reclaims_can_be_triggered(); + test_resource_user_stays_allocated_until_memory_released(); + test_resource_user_stays_allocated_and_reclaimers_unrun_until_memory_released(); + test_reclaimers_can_be_posted_repeatedly(); + test_one_slice(); + test_one_slice_deleted_late(); + test_resize_to_zero(); + test_negative_rq_free_pool(); + gpr_mu_destroy(&g_mu); + gpr_cv_destroy(&g_cv); + grpc_shutdown(); + return 0; +} diff --git a/test/core/iomgr/sockaddr_utils_test.c b/test/core/iomgr/sockaddr_utils_test.c deleted file mode 100644 index e4a4ddaa99..0000000000 --- a/test/core/iomgr/sockaddr_utils_test.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" - -#include -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -static grpc_resolved_address make_addr4(const uint8_t *data, size_t data_len) { - grpc_resolved_address resolved_addr4; - struct sockaddr_in *addr4 = (struct sockaddr_in *)resolved_addr4.addr; - memset(&resolved_addr4, 0, sizeof(resolved_addr4)); - addr4->sin_family = AF_INET; - GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr)); - memcpy(&addr4->sin_addr.s_addr, data, data_len); - addr4->sin_port = htons(12345); - resolved_addr4.len = sizeof(struct sockaddr_in); - return resolved_addr4; -} - -static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) { - grpc_resolved_address resolved_addr6; - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)resolved_addr6.addr; - memset(&resolved_addr6, 0, sizeof(resolved_addr6)); - addr6->sin6_family = AF_INET6; - GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr)); - memcpy(&addr6->sin6_addr.s6_addr, data, data_len); - addr6->sin6_port = htons(12345); - resolved_addr6.len = sizeof(struct sockaddr_in6); - return resolved_addr6; -} - -static void set_addr6_scope_id(grpc_resolved_address *addr, uint32_t scope_id) { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr->addr; - GPR_ASSERT(addr6->sin6_family == AF_INET6); - addr6->sin6_scope_id = scope_id; -} - -static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xff, 0xff, 192, 0, 2, 1}; - -static const uint8_t kNotQuiteMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xff, 0xfe, 192, 0, 2, 99}; -static const uint8_t kIPv4[] = {192, 0, 2, 1}; - -static const uint8_t kIPv6[] = {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1}; - -static void test_sockaddr_is_v4mapped(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address output4; - grpc_resolved_address expect4; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_is_v4mapped"); - - /* v4mapped input should succeed. */ - input6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, NULL)); - GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, &output4)); - expect4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); - - /* Non-v4mapped input should fail. */ - input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, NULL)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, &output4)); - /* Output is unchanged. */ - GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); - - /* Plain IPv4 input should also fail. */ - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input4, NULL)); -} - -static void test_sockaddr_to_v4mapped(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address output6; - grpc_resolved_address expect6; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_to_v4mapped"); - - /* IPv4 input should succeed. */ - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(grpc_sockaddr_to_v4mapped(&input4, &output6)); - expect6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); - - /* IPv6 input should fail. */ - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); - /* Output is unchanged. */ - GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); - - /* Already-v4mapped input should also fail. */ - input6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); -} - -static void test_sockaddr_is_wildcard(void) { - grpc_resolved_address wild4; - grpc_resolved_address wild6; - grpc_resolved_address wild_mapped; - grpc_resolved_address dummy; - struct sockaddr_in *wild4_addr; - struct sockaddr_in6 *wild6_addr; - struct sockaddr_in6 *wild_mapped_addr; - int port; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_is_wildcard"); - - /* Generate wildcards. */ - grpc_sockaddr_make_wildcards(555, &wild4, &wild6); - GPR_ASSERT(grpc_sockaddr_to_v4mapped(&wild4, &wild_mapped)); - - /* Test 0.0.0.0:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild4, &port)); - GPR_ASSERT(port == 555); - wild4_addr = (struct sockaddr_in *)&wild4.addr; - memset(&wild4_addr->sin_addr.s_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild4, &port)); - - /* Test [::]:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild6, &port)); - GPR_ASSERT(port == 555); - wild6_addr = (struct sockaddr_in6 *)&wild6.addr; - memset(&wild6_addr->sin6_addr.s6_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild6, &port)); - - /* Test [::ffff:0.0.0.0]:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild_mapped, &port)); - GPR_ASSERT(port == 555); - wild_mapped_addr = (struct sockaddr_in6 *)&wild_mapped.addr; - memset(&wild_mapped_addr->sin6_addr.s6_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild_mapped, &port)); - - /* Test AF_UNSPEC. */ - port = -1; - memset(&dummy, 0, sizeof(dummy)); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&dummy, &port)); - GPR_ASSERT(port == -1); -} - -static void expect_sockaddr_str(const char *expected, - grpc_resolved_address *addr, int normalize) { - int result; - char *str; - gpr_log(GPR_INFO, " expect_sockaddr_str(%s)", expected); - result = grpc_sockaddr_to_string(&str, addr, normalize); - GPR_ASSERT(str != NULL); - GPR_ASSERT(result >= 0); - GPR_ASSERT((size_t)result == strlen(str)); - GPR_ASSERT(strcmp(expected, str) == 0); - gpr_free(str); -} - -static void expect_sockaddr_uri(const char *expected, - grpc_resolved_address *addr) { - char *str; - gpr_log(GPR_INFO, " expect_sockaddr_uri(%s)", expected); - str = grpc_sockaddr_to_uri(addr); - GPR_ASSERT(str != NULL); - GPR_ASSERT(strcmp(expected, str) == 0); - gpr_free(str); -} - -static void test_sockaddr_to_string(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address dummy; - struct sockaddr *dummy_addr; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_to_string"); - - errno = 0x7EADBEEF; - - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - expect_sockaddr_str("192.0.2.1:12345", &input4, 0); - expect_sockaddr_str("192.0.2.1:12345", &input4, 1); - expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input4); - - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - expect_sockaddr_str("[2001:db8::1]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6); - - set_addr6_scope_id(&input6, 2); - expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6); - - set_addr6_scope_id(&input6, 101); - expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6); - - input6 = make_addr6(kMapped, sizeof(kMapped)); - expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0); - expect_sockaddr_str("192.0.2.1:12345", &input6, 1); - expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input6); - - input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); - expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 0); - expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[::fffe:c000:263]:12345", &input6); - - memset(&dummy, 0, sizeof(dummy)); - dummy_addr = (struct sockaddr *)dummy.addr; - dummy_addr->sa_family = 123; - expect_sockaddr_str("(sockaddr family=123)", &dummy, 0); - expect_sockaddr_str("(sockaddr family=123)", &dummy, 1); - GPR_ASSERT(grpc_sockaddr_to_uri(&dummy) == NULL); -} - -static void test_sockaddr_set_get_port(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address dummy; - struct sockaddr *dummy_addr; - - gpr_log(GPR_DEBUG, "test_sockaddr_set_get_port"); - - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 12345); - GPR_ASSERT(grpc_sockaddr_set_port(&input4, 54321)); - GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 54321); - - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 12345); - GPR_ASSERT(grpc_sockaddr_set_port(&input6, 54321)); - GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 54321); - - memset(&dummy, 0, sizeof(dummy)); - dummy_addr = (struct sockaddr *)dummy.addr; - dummy_addr->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); - - test_sockaddr_is_v4mapped(); - 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/sockaddr_utils_test.cc b/test/core/iomgr/sockaddr_utils_test.cc new file mode 100644 index 0000000000..e4a4ddaa99 --- /dev/null +++ b/test/core/iomgr/sockaddr_utils_test.cc @@ -0,0 +1,279 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" + +#include +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +static grpc_resolved_address make_addr4(const uint8_t *data, size_t data_len) { + grpc_resolved_address resolved_addr4; + struct sockaddr_in *addr4 = (struct sockaddr_in *)resolved_addr4.addr; + memset(&resolved_addr4, 0, sizeof(resolved_addr4)); + addr4->sin_family = AF_INET; + GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr)); + memcpy(&addr4->sin_addr.s_addr, data, data_len); + addr4->sin_port = htons(12345); + resolved_addr4.len = sizeof(struct sockaddr_in); + return resolved_addr4; +} + +static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) { + grpc_resolved_address resolved_addr6; + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)resolved_addr6.addr; + memset(&resolved_addr6, 0, sizeof(resolved_addr6)); + addr6->sin6_family = AF_INET6; + GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr)); + memcpy(&addr6->sin6_addr.s6_addr, data, data_len); + addr6->sin6_port = htons(12345); + resolved_addr6.len = sizeof(struct sockaddr_in6); + return resolved_addr6; +} + +static void set_addr6_scope_id(grpc_resolved_address *addr, uint32_t scope_id) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr->addr; + GPR_ASSERT(addr6->sin6_family == AF_INET6); + addr6->sin6_scope_id = scope_id; +} + +static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0xff, 0xff, 192, 0, 2, 1}; + +static const uint8_t kNotQuiteMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0xff, 0xfe, 192, 0, 2, 99}; +static const uint8_t kIPv4[] = {192, 0, 2, 1}; + +static const uint8_t kIPv6[] = {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1}; + +static void test_sockaddr_is_v4mapped(void) { + grpc_resolved_address input4; + grpc_resolved_address input6; + grpc_resolved_address output4; + grpc_resolved_address expect4; + + gpr_log(GPR_INFO, "%s", "test_sockaddr_is_v4mapped"); + + /* v4mapped input should succeed. */ + input6 = make_addr6(kMapped, sizeof(kMapped)); + GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, NULL)); + GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, &output4)); + expect4 = make_addr4(kIPv4, sizeof(kIPv4)); + GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); + + /* Non-v4mapped input should fail. */ + input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); + GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, NULL)); + GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, &output4)); + /* Output is unchanged. */ + GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); + + /* Plain IPv4 input should also fail. */ + input4 = make_addr4(kIPv4, sizeof(kIPv4)); + GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input4, NULL)); +} + +static void test_sockaddr_to_v4mapped(void) { + grpc_resolved_address input4; + grpc_resolved_address input6; + grpc_resolved_address output6; + grpc_resolved_address expect6; + + gpr_log(GPR_INFO, "%s", "test_sockaddr_to_v4mapped"); + + /* IPv4 input should succeed. */ + input4 = make_addr4(kIPv4, sizeof(kIPv4)); + GPR_ASSERT(grpc_sockaddr_to_v4mapped(&input4, &output6)); + expect6 = make_addr6(kMapped, sizeof(kMapped)); + GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); + + /* IPv6 input should fail. */ + input6 = make_addr6(kIPv6, sizeof(kIPv6)); + GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); + /* Output is unchanged. */ + GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); + + /* Already-v4mapped input should also fail. */ + input6 = make_addr6(kMapped, sizeof(kMapped)); + GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); +} + +static void test_sockaddr_is_wildcard(void) { + grpc_resolved_address wild4; + grpc_resolved_address wild6; + grpc_resolved_address wild_mapped; + grpc_resolved_address dummy; + struct sockaddr_in *wild4_addr; + struct sockaddr_in6 *wild6_addr; + struct sockaddr_in6 *wild_mapped_addr; + int port; + + gpr_log(GPR_INFO, "%s", "test_sockaddr_is_wildcard"); + + /* Generate wildcards. */ + grpc_sockaddr_make_wildcards(555, &wild4, &wild6); + GPR_ASSERT(grpc_sockaddr_to_v4mapped(&wild4, &wild_mapped)); + + /* Test 0.0.0.0:555 */ + port = -1; + GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild4, &port)); + GPR_ASSERT(port == 555); + wild4_addr = (struct sockaddr_in *)&wild4.addr; + memset(&wild4_addr->sin_addr.s_addr, 0xbd, 1); + GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild4, &port)); + + /* Test [::]:555 */ + port = -1; + GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild6, &port)); + GPR_ASSERT(port == 555); + wild6_addr = (struct sockaddr_in6 *)&wild6.addr; + memset(&wild6_addr->sin6_addr.s6_addr, 0xbd, 1); + GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild6, &port)); + + /* Test [::ffff:0.0.0.0]:555 */ + port = -1; + GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild_mapped, &port)); + GPR_ASSERT(port == 555); + wild_mapped_addr = (struct sockaddr_in6 *)&wild_mapped.addr; + memset(&wild_mapped_addr->sin6_addr.s6_addr, 0xbd, 1); + GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild_mapped, &port)); + + /* Test AF_UNSPEC. */ + port = -1; + memset(&dummy, 0, sizeof(dummy)); + GPR_ASSERT(!grpc_sockaddr_is_wildcard(&dummy, &port)); + GPR_ASSERT(port == -1); +} + +static void expect_sockaddr_str(const char *expected, + grpc_resolved_address *addr, int normalize) { + int result; + char *str; + gpr_log(GPR_INFO, " expect_sockaddr_str(%s)", expected); + result = grpc_sockaddr_to_string(&str, addr, normalize); + GPR_ASSERT(str != NULL); + GPR_ASSERT(result >= 0); + GPR_ASSERT((size_t)result == strlen(str)); + GPR_ASSERT(strcmp(expected, str) == 0); + gpr_free(str); +} + +static void expect_sockaddr_uri(const char *expected, + grpc_resolved_address *addr) { + char *str; + gpr_log(GPR_INFO, " expect_sockaddr_uri(%s)", expected); + str = grpc_sockaddr_to_uri(addr); + GPR_ASSERT(str != NULL); + GPR_ASSERT(strcmp(expected, str) == 0); + gpr_free(str); +} + +static void test_sockaddr_to_string(void) { + grpc_resolved_address input4; + grpc_resolved_address input6; + grpc_resolved_address dummy; + struct sockaddr *dummy_addr; + + gpr_log(GPR_INFO, "%s", "test_sockaddr_to_string"); + + errno = 0x7EADBEEF; + + input4 = make_addr4(kIPv4, sizeof(kIPv4)); + expect_sockaddr_str("192.0.2.1:12345", &input4, 0); + expect_sockaddr_str("192.0.2.1:12345", &input4, 1); + expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input4); + + input6 = make_addr6(kIPv6, sizeof(kIPv6)); + expect_sockaddr_str("[2001:db8::1]:12345", &input6, 0); + expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1); + expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6); + + set_addr6_scope_id(&input6, 2); + expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0); + expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1); + expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6); + + set_addr6_scope_id(&input6, 101); + expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0); + expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1); + expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6); + + input6 = make_addr6(kMapped, sizeof(kMapped)); + expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0); + expect_sockaddr_str("192.0.2.1:12345", &input6, 1); + expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input6); + + input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); + expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 0); + expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 1); + expect_sockaddr_uri("ipv6:[::fffe:c000:263]:12345", &input6); + + memset(&dummy, 0, sizeof(dummy)); + dummy_addr = (struct sockaddr *)dummy.addr; + dummy_addr->sa_family = 123; + expect_sockaddr_str("(sockaddr family=123)", &dummy, 0); + expect_sockaddr_str("(sockaddr family=123)", &dummy, 1); + GPR_ASSERT(grpc_sockaddr_to_uri(&dummy) == NULL); +} + +static void test_sockaddr_set_get_port(void) { + grpc_resolved_address input4; + grpc_resolved_address input6; + grpc_resolved_address dummy; + struct sockaddr *dummy_addr; + + gpr_log(GPR_DEBUG, "test_sockaddr_set_get_port"); + + input4 = make_addr4(kIPv4, sizeof(kIPv4)); + GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 12345); + GPR_ASSERT(grpc_sockaddr_set_port(&input4, 54321)); + GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 54321); + + input6 = make_addr6(kIPv6, sizeof(kIPv6)); + GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 12345); + GPR_ASSERT(grpc_sockaddr_set_port(&input6, 54321)); + GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 54321); + + memset(&dummy, 0, sizeof(dummy)); + dummy_addr = (struct sockaddr *)dummy.addr; + dummy_addr->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); + + test_sockaddr_is_v4mapped(); + 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 deleted file mode 100644 index 30f0c943dc..0000000000 --- a/test/core/iomgr/socket_utils_test.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/socket_utils_posix.h" - -#include -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/iomgr/socket_mutator.h" -#include "test/core/util/test_config.h" - -struct test_socket_mutator { - grpc_socket_mutator base; - int option_value; -}; - -static bool mutate_fd(int fd, grpc_socket_mutator *mutator) { - int newval; - socklen_t intlen = sizeof(newval); - struct test_socket_mutator *m = (struct test_socket_mutator *)mutator; - - if (0 != setsockopt(fd, IPPROTO_IP, IP_TOS, &m->option_value, - sizeof(m->option_value))) { - return false; - } - if (0 != getsockopt(fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) { - return false; - } - if (newval != m->option_value) { - return false; - } - return true; -} - -static void destroy_test_mutator(grpc_socket_mutator *mutator) { - struct test_socket_mutator *m = (struct test_socket_mutator *)mutator; - gpr_free(m); -} - -static int compare_test_mutator(grpc_socket_mutator *a, - grpc_socket_mutator *b) { - struct test_socket_mutator *ma = (struct test_socket_mutator *)a; - struct test_socket_mutator *mb = (struct test_socket_mutator *)b; - return GPR_ICMP(ma->option_value, mb->option_value); -} - -static const grpc_socket_mutator_vtable mutator_vtable = { - mutate_fd, compare_test_mutator, destroy_test_mutator}; - -int main(int argc, char **argv) { - int sock; - grpc_error *err; - grpc_test_init(argc, argv); - - sock = socket(PF_INET, SOCK_STREAM, 0); - GPR_ASSERT(sock > 0); - - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking", - grpc_set_socket_nonblocking(sock, 1))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking", - grpc_set_socket_nonblocking(sock, 0))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec", - grpc_set_socket_cloexec(sock, 1))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec", - grpc_set_socket_cloexec(sock, 0))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr", - grpc_set_socket_reuse_addr(sock, 1))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr", - grpc_set_socket_reuse_addr(sock, 0))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency", - grpc_set_socket_low_latency(sock, 1))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency", - grpc_set_socket_low_latency(sock, 0))); - - struct test_socket_mutator mutator; - grpc_socket_mutator_init(&mutator.base, &mutator_vtable); - - mutator.option_value = IPTOS_LOWDELAY; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "set_socket_with_mutator", - grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); - - mutator.option_value = IPTOS_THROUGHPUT; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "set_socket_with_mutator", - grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); - - mutator.option_value = IPTOS_RELIABILITY; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "set_socket_with_mutator", - grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); - - mutator.option_value = -1; - err = grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator); - GPR_ASSERT(err != GRPC_ERROR_NONE); - GRPC_ERROR_UNREF(err); - - close(sock); - - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc new file mode 100644 index 0000000000..30f0c943dc --- /dev/null +++ b/test/core/iomgr/socket_utils_test.cc @@ -0,0 +1,132 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/socket_utils_posix.h" + +#include +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/iomgr/socket_mutator.h" +#include "test/core/util/test_config.h" + +struct test_socket_mutator { + grpc_socket_mutator base; + int option_value; +}; + +static bool mutate_fd(int fd, grpc_socket_mutator *mutator) { + int newval; + socklen_t intlen = sizeof(newval); + struct test_socket_mutator *m = (struct test_socket_mutator *)mutator; + + if (0 != setsockopt(fd, IPPROTO_IP, IP_TOS, &m->option_value, + sizeof(m->option_value))) { + return false; + } + if (0 != getsockopt(fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) { + return false; + } + if (newval != m->option_value) { + return false; + } + return true; +} + +static void destroy_test_mutator(grpc_socket_mutator *mutator) { + struct test_socket_mutator *m = (struct test_socket_mutator *)mutator; + gpr_free(m); +} + +static int compare_test_mutator(grpc_socket_mutator *a, + grpc_socket_mutator *b) { + struct test_socket_mutator *ma = (struct test_socket_mutator *)a; + struct test_socket_mutator *mb = (struct test_socket_mutator *)b; + return GPR_ICMP(ma->option_value, mb->option_value); +} + +static const grpc_socket_mutator_vtable mutator_vtable = { + mutate_fd, compare_test_mutator, destroy_test_mutator}; + +int main(int argc, char **argv) { + int sock; + grpc_error *err; + grpc_test_init(argc, argv); + + sock = socket(PF_INET, SOCK_STREAM, 0); + GPR_ASSERT(sock > 0); + + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking", + grpc_set_socket_nonblocking(sock, 1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking", + grpc_set_socket_nonblocking(sock, 0))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec", + grpc_set_socket_cloexec(sock, 1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec", + grpc_set_socket_cloexec(sock, 0))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr", + grpc_set_socket_reuse_addr(sock, 1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr", + grpc_set_socket_reuse_addr(sock, 0))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency", + grpc_set_socket_low_latency(sock, 1))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency", + grpc_set_socket_low_latency(sock, 0))); + + struct test_socket_mutator mutator; + grpc_socket_mutator_init(&mutator.base, &mutator_vtable); + + mutator.option_value = IPTOS_LOWDELAY; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "set_socket_with_mutator", + grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); + + mutator.option_value = IPTOS_THROUGHPUT; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "set_socket_with_mutator", + grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); + + mutator.option_value = IPTOS_RELIABILITY; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "set_socket_with_mutator", + grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator))); + + mutator.option_value = -1; + err = grpc_set_socket_with_mutator(sock, (grpc_socket_mutator *)&mutator); + GPR_ASSERT(err != GRPC_ERROR_NONE); + GRPC_ERROR_UNREF(err); + + close(sock); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c deleted file mode 100644 index b8b76d1c42..0000000000 --- a/test/core/iomgr/tcp_client_posix_test.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/tcp_client.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/pollset_set.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" -#include "src/core/lib/iomgr/timer.h" -#include "test/core/util/test_config.h" - -static grpc_pollset_set *g_pollset_set; -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; -static int g_connections_complete = 0; -static grpc_endpoint *g_connecting = NULL; - -static grpc_millis test_deadline(void) { - return grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); -} - -static void finish_connection() { - gpr_mu_lock(g_mu); - g_connections_complete++; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(&exec_ctx, g_pollset, NULL))); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_unlock(g_mu); -} - -static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_ASSERT(g_connecting != NULL); - GPR_ASSERT(error == GRPC_ERROR_NONE); - grpc_endpoint_shutdown( - exec_ctx, g_connecting, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); - grpc_endpoint_destroy(exec_ctx, g_connecting); - g_connecting = NULL; - finish_connection(); -} - -static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_ASSERT(g_connecting == NULL); - GPR_ASSERT(error != GRPC_ERROR_NONE); - finish_connection(); -} - -void test_succeeds(void) { - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - int svr_fd; - int r; - int connections_complete_before; - grpc_closure done; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_DEBUG, "test_succeeds"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - - /* create a dummy server */ - svr_fd = socket(AF_INET, SOCK_STREAM, 0); - GPR_ASSERT(svr_fd >= 0); - GPR_ASSERT( - 0 == bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr.len)); - GPR_ASSERT(0 == listen(svr_fd, 1)); - - gpr_mu_lock(g_mu); - connections_complete_before = g_connections_complete; - gpr_mu_unlock(g_mu); - - /* connect to it */ - GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)addr, - (socklen_t *)&resolved_addr.len) == 0); - GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); - grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set, NULL, - &resolved_addr, GRPC_MILLIS_INF_FUTURE); - - /* await the connection */ - do { - resolved_addr.len = sizeof(addr); - r = accept(svr_fd, (struct sockaddr *)addr, - (socklen_t *)&resolved_addr.len); - } while (r == -1 && errno == EINTR); - GPR_ASSERT(r >= 0); - close(r); - - gpr_mu_lock(g_mu); - - while (g_connections_complete == connections_complete_before) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, - grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(5))))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - - gpr_mu_unlock(g_mu); - - grpc_exec_ctx_finish(&exec_ctx); -} - -void test_fails(void) { - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - int connections_complete_before; - grpc_closure done; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_DEBUG, "test_fails"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - - gpr_mu_lock(g_mu); - connections_complete_before = g_connections_complete; - gpr_mu_unlock(g_mu); - - /* connect to a broken address */ - GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); - grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set, NULL, - &resolved_addr, GRPC_MILLIS_INF_FUTURE); - - gpr_mu_lock(g_mu); - - /* wait for the connection callback to finish */ - while (g_connections_complete == connections_complete_before) { - grpc_pollset_worker *worker = NULL; - grpc_millis polling_deadline = test_deadline(); - switch (grpc_timer_check(&exec_ctx, &polling_deadline)) { - case GRPC_TIMERS_FIRED: - break; - case GRPC_TIMERS_NOT_CHECKED: - polling_deadline = 0; - /* fall through */ - case GRPC_TIMERS_CHECKED_AND_EMPTY: - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - polling_deadline))); - break; - } - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset_set = grpc_pollset_set_create(); - g_pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - grpc_pollset_set_add_pollset(&exec_ctx, g_pollset_set, g_pollset); - grpc_exec_ctx_finish(&exec_ctx); - test_succeeds(); - gpr_log(GPR_ERROR, "End of first test"); - test_fails(); - grpc_pollset_set_destroy(&exec_ctx, g_pollset_set); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(g_pollset); - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_client_posix_test.cc b/test/core/iomgr/tcp_client_posix_test.cc new file mode 100644 index 0000000000..b2dcb1d04f --- /dev/null +++ b/test/core/iomgr/tcp_client_posix_test.cc @@ -0,0 +1,223 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/tcp_client.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/iomgr/timer.h" +#include "test/core/util/test_config.h" + +static grpc_pollset_set *g_pollset_set; +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_connections_complete = 0; +static grpc_endpoint *g_connecting = NULL; + +static grpc_millis test_deadline(void) { + return grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); +} + +static void finish_connection() { + gpr_mu_lock(g_mu); + g_connections_complete++; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(&exec_ctx, g_pollset, NULL))); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_unlock(g_mu); +} + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(g_connecting != NULL); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_endpoint_shutdown( + exec_ctx, g_connecting, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); + grpc_endpoint_destroy(exec_ctx, g_connecting); + g_connecting = NULL; + finish_connection(); +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(g_connecting == NULL); + GPR_ASSERT(error != GRPC_ERROR_NONE); + finish_connection(); +} + +void test_succeeds(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + int svr_fd; + int r; + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_succeeds"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + /* create a dummy server */ + svr_fd = socket(AF_INET, SOCK_STREAM, 0); + GPR_ASSERT(svr_fd >= 0); + GPR_ASSERT( + 0 == bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr.len)); + GPR_ASSERT(0 == listen(svr_fd, 1)); + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to it */ + GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)addr, + (socklen_t *)&resolved_addr.len) == 0); + GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set, NULL, + &resolved_addr, GRPC_MILLIS_INF_FUTURE); + + /* await the connection */ + do { + resolved_addr.len = sizeof(addr); + r = accept(svr_fd, (struct sockaddr *)addr, + (socklen_t *)&resolved_addr.len); + } while (r == -1 && errno == EINTR); + GPR_ASSERT(r >= 0); + close(r); + + gpr_mu_lock(g_mu); + + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, + grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(5))))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + gpr_mu_unlock(g_mu); + + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_fails(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_fails"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to a broken address */ + GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set, NULL, + &resolved_addr, GRPC_MILLIS_INF_FUTURE); + + gpr_mu_lock(g_mu); + + /* wait for the connection callback to finish */ + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + grpc_millis polling_deadline = test_deadline(); + switch (grpc_timer_check(&exec_ctx, &polling_deadline)) { + case GRPC_TIMERS_FIRED: + break; + case GRPC_TIMERS_NOT_CHECKED: + polling_deadline = 0; + /* fall through */ + case GRPC_TIMERS_CHECKED_AND_EMPTY: + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + polling_deadline))); + break; + } + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset_set = grpc_pollset_set_create(); + g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(g_pollset, &g_mu); + grpc_pollset_set_add_pollset(&exec_ctx, g_pollset_set, g_pollset); + grpc_exec_ctx_finish(&exec_ctx); + test_succeeds(); + gpr_log(GPR_ERROR, "End of first test"); + test_fails(); + grpc_pollset_set_destroy(&exec_ctx, g_pollset_set); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c deleted file mode 100644 index edfccbe867..0000000000 --- a/test/core/iomgr/tcp_client_uv_test.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with libuv -#ifdef GRPC_UV - -#include - -#include - -#include "src/core/lib/iomgr/tcp_client.h" - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/pollset.h" -#include "src/core/lib/iomgr/timer.h" -#include "test/core/util/test_config.h" - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; -static int g_connections_complete = 0; -static grpc_endpoint *g_connecting = NULL; - -static grpc_millis test_deadline(void) { - return grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); -} - -static void finish_connection(grpc_exec_ctx *exec_ctx) { - gpr_mu_lock(g_mu); - g_connections_complete++; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_ASSERT(g_connecting != NULL); - GPR_ASSERT(error == GRPC_ERROR_NONE); - grpc_endpoint_shutdown( - exec_ctx, g_connecting, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); - grpc_endpoint_destroy(exec_ctx, g_connecting); - g_connecting = NULL; - finish_connection(exec_ctx); -} - -static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_ASSERT(g_connecting == NULL); - GPR_ASSERT(error != GRPC_ERROR_NONE); - finish_connection(exec_ctx); -} - -static void close_cb(uv_handle_t *handle) { gpr_free(handle); } - -static void connection_cb(uv_stream_t *server, int status) { - uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); - GPR_ASSERT(0 == status); - GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), client_handle)); - GPR_ASSERT(0 == uv_accept(server, (uv_stream_t *)client_handle)); - uv_close((uv_handle_t *)client_handle, close_cb); -} - -void test_succeeds(void) { - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - uv_tcp_t *svr_handle = gpr_malloc(sizeof(uv_tcp_t)); - int connections_complete_before; - grpc_closure done; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_DEBUG, "test_succeeds"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - - /* create a dummy server */ - GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), svr_handle)); - GPR_ASSERT(0 == uv_tcp_bind(svr_handle, (struct sockaddr *)addr, 0)); - GPR_ASSERT(0 == uv_listen((uv_stream_t *)svr_handle, 1, connection_cb)); - - gpr_mu_lock(g_mu); - connections_complete_before = g_connections_complete; - gpr_mu_unlock(g_mu); - - /* connect to it */ - GPR_ASSERT(uv_tcp_getsockname(svr_handle, (struct sockaddr *)addr, - (int *)&resolved_addr.len) == 0); - GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); - grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, - &resolved_addr, GRPC_MILLIS_INF_FUTURE); - - gpr_mu_lock(g_mu); - - while (g_connections_complete == connections_complete_before) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, - grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(5))))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - - // This will get cleaned up when the pollset runs again or gets shutdown - uv_close((uv_handle_t *)svr_handle, close_cb); - - gpr_mu_unlock(g_mu); - - grpc_exec_ctx_finish(&exec_ctx); -} - -void test_fails(void) { - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - int connections_complete_before; - grpc_closure done; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_DEBUG, "test_fails"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - - gpr_mu_lock(g_mu); - connections_complete_before = g_connections_complete; - gpr_mu_unlock(g_mu); - - /* connect to a broken address */ - GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); - grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, - &resolved_addr, GRPC_MILLIS_INF_FUTURE); - - gpr_mu_lock(g_mu); - - /* wait for the connection callback to finish */ - while (g_connections_complete == connections_complete_before) { - grpc_pollset_worker *worker = NULL; - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - grpc_millis polling_deadline = test_deadline(); - switch (grpc_timer_check(&exec_ctx, &polling_deadline)) { - case GRPC_TIMERS_FIRED: - break; - case GRPC_TIMERS_NOT_CHECKED: - polling_deadline = grpc_timespec_to_millis_round_up(now); - /* fall through */ - case GRPC_TIMERS_CHECKED_AND_EMPTY: - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, - polling_deadline))); - break; - } - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_malloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - grpc_exec_ctx_finish(&exec_ctx); - test_succeeds(); - gpr_log(GPR_ERROR, "End of first test"); - test_fails(); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(g_pollset); - return 0; -} - -#else /* GRPC_UV */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_UV */ diff --git a/test/core/iomgr/tcp_client_uv_test.cc b/test/core/iomgr/tcp_client_uv_test.cc new file mode 100644 index 0000000000..edfccbe867 --- /dev/null +++ b/test/core/iomgr/tcp_client_uv_test.cc @@ -0,0 +1,216 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with libuv +#ifdef GRPC_UV + +#include + +#include + +#include "src/core/lib/iomgr/tcp_client.h" + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/timer.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_connections_complete = 0; +static grpc_endpoint *g_connecting = NULL; + +static grpc_millis test_deadline(void) { + return grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); +} + +static void finish_connection(grpc_exec_ctx *exec_ctx) { + gpr_mu_lock(g_mu); + g_connections_complete++; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(g_connecting != NULL); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_endpoint_shutdown( + exec_ctx, g_connecting, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); + grpc_endpoint_destroy(exec_ctx, g_connecting); + g_connecting = NULL; + finish_connection(exec_ctx); +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(g_connecting == NULL); + GPR_ASSERT(error != GRPC_ERROR_NONE); + finish_connection(exec_ctx); +} + +static void close_cb(uv_handle_t *handle) { gpr_free(handle); } + +static void connection_cb(uv_stream_t *server, int status) { + uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); + GPR_ASSERT(0 == status); + GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), client_handle)); + GPR_ASSERT(0 == uv_accept(server, (uv_stream_t *)client_handle)); + uv_close((uv_handle_t *)client_handle, close_cb); +} + +void test_succeeds(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + uv_tcp_t *svr_handle = gpr_malloc(sizeof(uv_tcp_t)); + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_succeeds"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + /* create a dummy server */ + GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), svr_handle)); + GPR_ASSERT(0 == uv_tcp_bind(svr_handle, (struct sockaddr *)addr, 0)); + GPR_ASSERT(0 == uv_listen((uv_stream_t *)svr_handle, 1, connection_cb)); + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to it */ + GPR_ASSERT(uv_tcp_getsockname(svr_handle, (struct sockaddr *)addr, + (int *)&resolved_addr.len) == 0); + GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, + &resolved_addr, GRPC_MILLIS_INF_FUTURE); + + gpr_mu_lock(g_mu); + + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, + grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(5))))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + // This will get cleaned up when the pollset runs again or gets shutdown + uv_close((uv_handle_t *)svr_handle, close_cb); + + gpr_mu_unlock(g_mu); + + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_fails(void) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + int connections_complete_before; + grpc_closure done; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_DEBUG, "test_fails"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + + gpr_mu_lock(g_mu); + connections_complete_before = g_connections_complete; + gpr_mu_unlock(g_mu); + + /* connect to a broken address */ + GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); + grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, + &resolved_addr, GRPC_MILLIS_INF_FUTURE); + + gpr_mu_lock(g_mu); + + /* wait for the connection callback to finish */ + while (g_connections_complete == connections_complete_before) { + grpc_pollset_worker *worker = NULL; + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + grpc_millis polling_deadline = test_deadline(); + switch (grpc_timer_check(&exec_ctx, &polling_deadline)) { + case GRPC_TIMERS_FIRED: + break; + case GRPC_TIMERS_NOT_CHECKED: + polling_deadline = grpc_timespec_to_millis_round_up(now); + /* fall through */ + case GRPC_TIMERS_CHECKED_AND_EMPTY: + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, + polling_deadline))); + break; + } + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + grpc_exec_ctx_finish(&exec_ctx); + test_succeeds(); + gpr_log(GPR_ERROR, "End of first test"); + test_fails(); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + return 0; +} + +#else /* GRPC_UV */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_UV */ diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c deleted file mode 100644 index 6501160c6f..0000000000 --- a/test/core/iomgr/tcp_posix_test.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/tcp_posix.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/iomgr/endpoint_tests.h" -#include "test/core/util/test_config.h" - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; - -/* - General test notes: - - All tests which write data into a socket write i%256 into byte i, which is - verified by readers. - - In general there are a few interesting things to vary which may lead to - exercising different codepaths in an implementation: - 1. Total amount of data written to the socket - 2. Size of slice allocations - 3. Amount of data we read from or write to the socket at once - - The tests here tend to parameterize these where applicable. - - */ - -static void create_sockets(int sv[2]) { - int flags; - GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); -} - -static ssize_t fill_socket(int fd) { - ssize_t write_bytes; - ssize_t total_bytes = 0; - int i; - unsigned char buf[256]; - for (i = 0; i < 256; ++i) { - buf[i] = (uint8_t)i; - } - do { - write_bytes = write(fd, buf, 256); - if (write_bytes > 0) { - total_bytes += write_bytes; - } - } while (write_bytes >= 0 || errno == EINTR); - GPR_ASSERT(errno == EAGAIN); - return total_bytes; -} - -static size_t fill_socket_partial(int fd, size_t bytes) { - ssize_t write_bytes; - size_t total_bytes = 0; - unsigned char *buf = (unsigned char *)gpr_malloc(bytes); - unsigned i; - for (i = 0; i < bytes; ++i) { - buf[i] = (uint8_t)(i % 256); - } - - do { - write_bytes = write(fd, buf, bytes - total_bytes); - if (write_bytes > 0) { - total_bytes += (size_t)write_bytes; - } - } while ((write_bytes >= 0 || errno == EINTR) && bytes > total_bytes); - - gpr_free(buf); - - return total_bytes; -} - -struct read_socket_state { - grpc_endpoint *ep; - size_t read_bytes; - size_t target_read_bytes; - grpc_slice_buffer incoming; - grpc_closure read_cb; -}; - -static size_t count_slices(grpc_slice *slices, size_t nslices, - int *current_data) { - size_t num_bytes = 0; - unsigned i, j; - unsigned char *buf; - for (i = 0; i < nslices; ++i) { - buf = GRPC_SLICE_START_PTR(slices[i]); - for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { - GPR_ASSERT(buf[j] == *current_data); - *current_data = (*current_data + 1) % 256; - } - num_bytes += GRPC_SLICE_LENGTH(slices[i]); - } - return num_bytes; -} - -static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_error *error) { - struct read_socket_state *state = (struct read_socket_state *)user_data; - size_t read_bytes; - int current_data; - - GPR_ASSERT(error == GRPC_ERROR_NONE); - - gpr_mu_lock(g_mu); - current_data = state->read_bytes % 256; - read_bytes = count_slices(state->incoming.slices, state->incoming.count, - ¤t_data); - state->read_bytes += read_bytes; - gpr_log(GPR_INFO, "Read %" PRIuPTR " bytes of %" PRIuPTR, read_bytes, - state->target_read_bytes); - if (state->read_bytes >= state->target_read_bytes) { - GPR_ASSERT(GRPC_LOG_IF_ERROR("kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); - } else { - grpc_endpoint_read(exec_ctx, state->ep, &state->incoming, &state->read_cb); - gpr_mu_unlock(g_mu); - } -} - -/* Write to a socket, then read from it using the grpc_tcp API. */ -static void read_test(size_t num_bytes, size_t slice_size) { - int sv[2]; - grpc_endpoint *ep; - struct read_socket_state state; - size_t written_bytes; - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "Read test of size %" PRIuPTR ", slice size %" PRIuPTR, - num_bytes, slice_size); - - create_sockets(sv); - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args, - "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 %" PRIuPTR " bytes", written_bytes); - - state.ep = ep; - state.read_bytes = 0; - state.target_read_bytes = written_bytes; - grpc_slice_buffer_init(&state.incoming); - GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); - - grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); - - gpr_mu_lock(g_mu); - while (state.read_bytes < state.target_read_bytes) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(state.read_bytes == state.target_read_bytes); - gpr_mu_unlock(g_mu); - - grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); - grpc_endpoint_destroy(&exec_ctx, ep); - grpc_exec_ctx_finish(&exec_ctx); -} - -/* Write to a socket until it fills up, then read from it using the grpc_tcp - API. */ -static void large_read_test(size_t slice_size) { - int sv[2]; - grpc_endpoint *ep; - struct read_socket_state state; - ssize_t written_bytes; - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "Start large read test, slice size %" PRIuPTR, slice_size); - - create_sockets(sv); - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "large_read_test"), - &args, "test"); - grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); - - written_bytes = fill_socket(sv[0]); - gpr_log(GPR_INFO, "Wrote %" PRIuPTR " bytes", written_bytes); - - state.ep = ep; - state.read_bytes = 0; - state.target_read_bytes = (size_t)written_bytes; - grpc_slice_buffer_init(&state.incoming); - GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); - - grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); - - gpr_mu_lock(g_mu); - while (state.read_bytes < state.target_read_bytes) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(state.read_bytes == state.target_read_bytes); - gpr_mu_unlock(g_mu); - - grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); - grpc_endpoint_destroy(&exec_ctx, ep); - grpc_exec_ctx_finish(&exec_ctx); -} - -struct write_socket_state { - grpc_endpoint *ep; - int write_done; -}; - -static grpc_slice *allocate_blocks(size_t num_bytes, size_t slice_size, - size_t *num_blocks, uint8_t *current_data) { - size_t nslices = num_bytes / slice_size + (num_bytes % slice_size ? 1u : 0u); - grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices); - size_t num_bytes_left = num_bytes; - unsigned i, j; - unsigned char *buf; - *num_blocks = nslices; - - for (i = 0; i < nslices; ++i) { - slices[i] = grpc_slice_malloc(slice_size > num_bytes_left ? num_bytes_left - : slice_size); - num_bytes_left -= GRPC_SLICE_LENGTH(slices[i]); - buf = GRPC_SLICE_START_PTR(slices[i]); - for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { - buf[j] = *current_data; - (*current_data)++; - } - } - GPR_ASSERT(num_bytes_left == 0); - return slices; -} - -static void write_done(grpc_exec_ctx *exec_ctx, - void *user_data /* write_socket_state */, - grpc_error *error) { - struct write_socket_state *state = (struct write_socket_state *)user_data; - gpr_log(GPR_INFO, "Write done callback called"); - gpr_mu_lock(g_mu); - gpr_log(GPR_INFO, "Signalling write done"); - state->write_done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) { - unsigned char *buf = (unsigned char *)gpr_malloc(read_size); - ssize_t bytes_read; - size_t bytes_left = num_bytes; - int flags; - int current = 0; - int i; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - flags = fcntl(fd, F_GETFL, 0); - GPR_ASSERT(fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == 0); - - for (;;) { - grpc_pollset_worker *worker = NULL; - gpr_mu_lock(g_mu); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, - grpc_timespec_to_millis_round_up( - grpc_timeout_milliseconds_to_deadline(10))))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - do { - bytes_read = - read(fd, buf, bytes_left > read_size ? read_size : bytes_left); - } while (bytes_read < 0 && errno == EINTR); - GPR_ASSERT(bytes_read >= 0); - for (i = 0; i < bytes_read; ++i) { - GPR_ASSERT(buf[i] == current); - current = (current + 1) % 256; - } - bytes_left -= (size_t)bytes_read; - if (bytes_left == 0) break; - } - flags = fcntl(fd, F_GETFL, 0); - GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); - - gpr_free(buf); -} - -/* Write to a socket using the grpc_tcp API, then drain it directly. - Note that if the write does not complete immediately we need to drain the - socket in parallel with the read. */ -static void write_test(size_t num_bytes, size_t slice_size) { - int sv[2]; - grpc_endpoint *ep; - struct write_socket_state state; - size_t num_blocks; - grpc_slice *slices; - uint8_t current_data = 0; - grpc_slice_buffer outgoing; - grpc_closure write_done_closure; - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, - "Start write test with %" PRIuPTR " bytes, slice size %" PRIuPTR, - num_bytes, slice_size); - - create_sockets(sv); - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "write_test"), &args, - "test"); - grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); - - state.ep = ep; - state.write_done = 0; - - slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - - grpc_slice_buffer_init(&outgoing); - grpc_slice_buffer_addn(&outgoing, slices, num_blocks); - GRPC_CLOSURE_INIT(&write_done_closure, write_done, &state, - grpc_schedule_on_exec_ctx); - - grpc_endpoint_write(&exec_ctx, ep, &outgoing, &write_done_closure); - drain_socket_blocking(sv[0], num_bytes, num_bytes); - gpr_mu_lock(g_mu); - for (;;) { - grpc_pollset_worker *worker = NULL; - if (state.write_done) { - break; - } - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_mu_unlock(g_mu); - - grpc_slice_buffer_destroy_internal(&exec_ctx, &outgoing); - grpc_endpoint_destroy(&exec_ctx, ep); - gpr_free(slices); - grpc_exec_ctx_finish(&exec_ctx); -} - -void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *errors) { - int *done = (int *)arg; - *done = 1; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); -} - -/* Do a read_test, then release fd and try to read/write again. Verify that - grpc_tcp_fd() is available before the fd is released. */ -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; - grpc_millis deadline = - grpc_timespec_to_millis_round_up(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, - grpc_schedule_on_exec_ctx); - - gpr_log(GPR_INFO, - "Release fd read_test of size %" PRIuPTR ", slice size %" PRIuPTR, - num_bytes, slice_size); - - create_sockets(sv); - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args, - "test"); - GPR_ASSERT(grpc_tcp_fd(ep) == sv[1] && sv[1] >= 0); - grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); - - written_bytes = fill_socket_partial(sv[0], num_bytes); - gpr_log(GPR_INFO, "Wrote %" PRIuPTR " bytes", written_bytes); - - state.ep = ep; - state.read_bytes = 0; - state.target_read_bytes = written_bytes; - grpc_slice_buffer_init(&state.incoming); - GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); - - grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); - - gpr_mu_lock(g_mu); - while (state.read_bytes < state.target_read_bytes) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_log(GPR_DEBUG, "wakeup: read=%" PRIdPTR " target=%" PRIdPTR, - state.read_bytes, state.target_read_bytes); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(state.read_bytes == state.target_read_bytes); - gpr_mu_unlock(g_mu); - - grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); - grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - while (!fd_released_done) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_log(GPR_DEBUG, "wakeup: fd_released_done=%d", fd_released_done); - } - gpr_mu_unlock(g_mu); - 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; - - read_test(100, 8192); - read_test(10000, 8192); - read_test(10000, 137); - read_test(10000, 1); - large_read_test(8192); - large_read_test(1); - - write_test(100, 8192); - write_test(100, 1); - write_test(100000, 8192); - write_test(100000, 1); - write_test(100000, 137); - - 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) {} - -static grpc_endpoint_test_fixture create_fixture_tcp_socketpair( - size_t slice_size) { - int sv[2]; - grpc_endpoint_test_fixture f; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - create_sockets(sv); - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("tcp_posix_test_socketpair"); - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - f.client_ep = grpc_tcp_create( - &exec_ctx, grpc_fd_create(sv[0], "fixture:client"), &args, "test"); - f.server_ep = grpc_tcp_create( - &exec_ctx, grpc_fd_create(sv[1], "fixture:server"), &args, "test"); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); - grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset); - - grpc_exec_ctx_finish(&exec_ctx); - - return f; -} - -static grpc_endpoint_test_config configs[] = { - {"tcp/tcp_socketpair", create_fixture_tcp_socketpair, clean_up}, -}; - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - grpc_endpoint_tests(configs[0], g_pollset, g_mu); - run_tests(); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(g_pollset); - - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_posix_test.cc b/test/core/iomgr/tcp_posix_test.cc new file mode 100644 index 0000000000..8a4433b55c --- /dev/null +++ b/test/core/iomgr/tcp_posix_test.cc @@ -0,0 +1,580 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/tcp_posix.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/iomgr/endpoint_tests.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; + +/* + General test notes: + + All tests which write data into a socket write i%256 into byte i, which is + verified by readers. + + In general there are a few interesting things to vary which may lead to + exercising different codepaths in an implementation: + 1. Total amount of data written to the socket + 2. Size of slice allocations + 3. Amount of data we read from or write to the socket at once + + The tests here tend to parameterize these where applicable. + + */ + +static void create_sockets(int sv[2]) { + int flags; + GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); + flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); +} + +static ssize_t fill_socket(int fd) { + ssize_t write_bytes; + ssize_t total_bytes = 0; + int i; + unsigned char buf[256]; + for (i = 0; i < 256; ++i) { + buf[i] = (uint8_t)i; + } + do { + write_bytes = write(fd, buf, 256); + if (write_bytes > 0) { + total_bytes += write_bytes; + } + } while (write_bytes >= 0 || errno == EINTR); + GPR_ASSERT(errno == EAGAIN); + return total_bytes; +} + +static size_t fill_socket_partial(int fd, size_t bytes) { + ssize_t write_bytes; + size_t total_bytes = 0; + unsigned char *buf = (unsigned char *)gpr_malloc(bytes); + unsigned i; + for (i = 0; i < bytes; ++i) { + buf[i] = (uint8_t)(i % 256); + } + + do { + write_bytes = write(fd, buf, bytes - total_bytes); + if (write_bytes > 0) { + total_bytes += (size_t)write_bytes; + } + } while ((write_bytes >= 0 || errno == EINTR) && bytes > total_bytes); + + gpr_free(buf); + + return total_bytes; +} + +struct read_socket_state { + grpc_endpoint *ep; + size_t read_bytes; + size_t target_read_bytes; + grpc_slice_buffer incoming; + grpc_closure read_cb; +}; + +static size_t count_slices(grpc_slice *slices, size_t nslices, + int *current_data) { + size_t num_bytes = 0; + unsigned i, j; + unsigned char *buf; + for (i = 0; i < nslices; ++i) { + buf = GRPC_SLICE_START_PTR(slices[i]); + for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { + GPR_ASSERT(buf[j] == *current_data); + *current_data = (*current_data + 1) % 256; + } + num_bytes += GRPC_SLICE_LENGTH(slices[i]); + } + return num_bytes; +} + +static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_error *error) { + struct read_socket_state *state = (struct read_socket_state *)user_data; + size_t read_bytes; + int current_data; + + GPR_ASSERT(error == GRPC_ERROR_NONE); + + gpr_mu_lock(g_mu); + current_data = state->read_bytes % 256; + read_bytes = count_slices(state->incoming.slices, state->incoming.count, + ¤t_data); + state->read_bytes += read_bytes; + gpr_log(GPR_INFO, "Read %" PRIuPTR " bytes of %" PRIuPTR, read_bytes, + state->target_read_bytes); + if (state->read_bytes >= state->target_read_bytes) { + GPR_ASSERT(GRPC_LOG_IF_ERROR("kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); + } else { + grpc_endpoint_read(exec_ctx, state->ep, &state->incoming, &state->read_cb); + gpr_mu_unlock(g_mu); + } +} + +/* Write to a socket, then read from it using the grpc_tcp API. */ +static void read_test(size_t num_bytes, size_t slice_size) { + int sv[2]; + grpc_endpoint *ep; + struct read_socket_state state; + size_t written_bytes; + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "Read test of size %" PRIuPTR ", slice size %" PRIuPTR, + num_bytes, slice_size); + + create_sockets(sv); + + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER, a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args, + "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 %" PRIuPTR " bytes", written_bytes); + + state.ep = ep; + state.read_bytes = 0; + state.target_read_bytes = written_bytes; + grpc_slice_buffer_init(&state.incoming); + GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); + + grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); + + gpr_mu_lock(g_mu); + while (state.read_bytes < state.target_read_bytes) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(state.read_bytes == state.target_read_bytes); + gpr_mu_unlock(g_mu); + + grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); + grpc_endpoint_destroy(&exec_ctx, ep); + grpc_exec_ctx_finish(&exec_ctx); +} + +/* Write to a socket until it fills up, then read from it using the grpc_tcp + API. */ +static void large_read_test(size_t slice_size) { + int sv[2]; + grpc_endpoint *ep; + struct read_socket_state state; + ssize_t written_bytes; + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "Start large read test, slice size %" PRIuPTR, slice_size); + + create_sockets(sv); + + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "large_read_test"), + &args, "test"); + grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); + + written_bytes = fill_socket(sv[0]); + gpr_log(GPR_INFO, "Wrote %" PRIuPTR " bytes", written_bytes); + + state.ep = ep; + state.read_bytes = 0; + state.target_read_bytes = (size_t)written_bytes; + grpc_slice_buffer_init(&state.incoming); + GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); + + grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); + + gpr_mu_lock(g_mu); + while (state.read_bytes < state.target_read_bytes) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(state.read_bytes == state.target_read_bytes); + gpr_mu_unlock(g_mu); + + grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); + grpc_endpoint_destroy(&exec_ctx, ep); + grpc_exec_ctx_finish(&exec_ctx); +} + +struct write_socket_state { + grpc_endpoint *ep; + int write_done; +}; + +static grpc_slice *allocate_blocks(size_t num_bytes, size_t slice_size, + size_t *num_blocks, uint8_t *current_data) { + size_t nslices = num_bytes / slice_size + (num_bytes % slice_size ? 1u : 0u); + grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices); + size_t num_bytes_left = num_bytes; + unsigned i, j; + unsigned char *buf; + *num_blocks = nslices; + + for (i = 0; i < nslices; ++i) { + slices[i] = grpc_slice_malloc(slice_size > num_bytes_left ? num_bytes_left + : slice_size); + num_bytes_left -= GRPC_SLICE_LENGTH(slices[i]); + buf = GRPC_SLICE_START_PTR(slices[i]); + for (j = 0; j < GRPC_SLICE_LENGTH(slices[i]); ++j) { + buf[j] = *current_data; + (*current_data)++; + } + } + GPR_ASSERT(num_bytes_left == 0); + return slices; +} + +static void write_done(grpc_exec_ctx *exec_ctx, + void *user_data /* write_socket_state */, + grpc_error *error) { + struct write_socket_state *state = (struct write_socket_state *)user_data; + gpr_log(GPR_INFO, "Write done callback called"); + gpr_mu_lock(g_mu); + gpr_log(GPR_INFO, "Signalling write done"); + state->write_done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) { + unsigned char *buf = (unsigned char *)gpr_malloc(read_size); + ssize_t bytes_read; + size_t bytes_left = num_bytes; + int flags; + int current = 0; + int i; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + flags = fcntl(fd, F_GETFL, 0); + GPR_ASSERT(fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == 0); + + for (;;) { + grpc_pollset_worker *worker = NULL; + gpr_mu_lock(g_mu); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, + grpc_timespec_to_millis_round_up( + grpc_timeout_milliseconds_to_deadline(10))))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + do { + bytes_read = + read(fd, buf, bytes_left > read_size ? read_size : bytes_left); + } while (bytes_read < 0 && errno == EINTR); + GPR_ASSERT(bytes_read >= 0); + for (i = 0; i < bytes_read; ++i) { + GPR_ASSERT(buf[i] == current); + current = (current + 1) % 256; + } + bytes_left -= (size_t)bytes_read; + if (bytes_left == 0) break; + } + flags = fcntl(fd, F_GETFL, 0); + GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); + + gpr_free(buf); +} + +/* Write to a socket using the grpc_tcp API, then drain it directly. + Note that if the write does not complete immediately we need to drain the + socket in parallel with the read. */ +static void write_test(size_t num_bytes, size_t slice_size) { + int sv[2]; + grpc_endpoint *ep; + struct write_socket_state state; + size_t num_blocks; + grpc_slice *slices; + uint8_t current_data = 0; + grpc_slice_buffer outgoing; + grpc_closure write_done_closure; + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, + "Start write test with %" PRIuPTR " bytes, slice size %" PRIuPTR, + num_bytes, slice_size); + + create_sockets(sv); + + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER, a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "write_test"), &args, + "test"); + grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); + + state.ep = ep; + state.write_done = 0; + + slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); + + grpc_slice_buffer_init(&outgoing); + grpc_slice_buffer_addn(&outgoing, slices, num_blocks); + GRPC_CLOSURE_INIT(&write_done_closure, write_done, &state, + grpc_schedule_on_exec_ctx); + + grpc_endpoint_write(&exec_ctx, ep, &outgoing, &write_done_closure); + drain_socket_blocking(sv[0], num_bytes, num_bytes); + gpr_mu_lock(g_mu); + for (;;) { + grpc_pollset_worker *worker = NULL; + if (state.write_done) { + break; + } + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_mu_unlock(g_mu); + + grpc_slice_buffer_destroy_internal(&exec_ctx, &outgoing); + grpc_endpoint_destroy(&exec_ctx, ep); + gpr_free(slices); + grpc_exec_ctx_finish(&exec_ctx); +} + +void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *errors) { + int *done = (int *)arg; + *done = 1; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); +} + +/* Do a read_test, then release fd and try to read/write again. Verify that + grpc_tcp_fd() is available before the fd is released. */ +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; + grpc_millis deadline = + grpc_timespec_to_millis_round_up(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, + grpc_schedule_on_exec_ctx); + + gpr_log(GPR_INFO, + "Release fd read_test of size %" PRIuPTR ", slice size %" PRIuPTR, + num_bytes, slice_size); + + create_sockets(sv); + + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + ep = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], "read_test"), &args, + "test"); + GPR_ASSERT(grpc_tcp_fd(ep) == sv[1] && sv[1] >= 0); + grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset); + + written_bytes = fill_socket_partial(sv[0], num_bytes); + gpr_log(GPR_INFO, "Wrote %" PRIuPTR " bytes", written_bytes); + + state.ep = ep; + state.read_bytes = 0; + state.target_read_bytes = written_bytes; + grpc_slice_buffer_init(&state.incoming); + GRPC_CLOSURE_INIT(&state.read_cb, read_cb, &state, grpc_schedule_on_exec_ctx); + + grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb); + + gpr_mu_lock(g_mu); + while (state.read_bytes < state.target_read_bytes) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_log(GPR_DEBUG, "wakeup: read=%" PRIdPTR " target=%" PRIdPTR, + state.read_bytes, state.target_read_bytes); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(state.read_bytes == state.target_read_bytes); + gpr_mu_unlock(g_mu); + + grpc_slice_buffer_destroy_internal(&exec_ctx, &state.incoming); + grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + while (!fd_released_done) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_log(GPR_DEBUG, "wakeup: fd_released_done=%d", fd_released_done); + } + gpr_mu_unlock(g_mu); + 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; + + read_test(100, 8192); + read_test(10000, 8192); + read_test(10000, 137); + read_test(10000, 1); + large_read_test(8192); + large_read_test(1); + + write_test(100, 8192); + write_test(100, 1); + write_test(100000, 8192); + write_test(100000, 1); + write_test(100000, 137); + + 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) {} + +static grpc_endpoint_test_fixture create_fixture_tcp_socketpair( + size_t slice_size) { + int sv[2]; + grpc_endpoint_test_fixture f; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + create_sockets(sv); + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("tcp_posix_test_socketpair"); + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = (int)slice_size; + grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; + f.client_ep = grpc_tcp_create( + &exec_ctx, grpc_fd_create(sv[0], "fixture:client"), &args, "test"); + f.server_ep = grpc_tcp_create( + &exec_ctx, grpc_fd_create(sv[1], "fixture:server"), &args, "test"); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); + grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset); + + grpc_exec_ctx_finish(&exec_ctx); + + return f; +} + +static grpc_endpoint_test_config configs[] = { + {"tcp/tcp_socketpair", create_fixture_tcp_socketpair, clean_up}, +}; + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + grpc_endpoint_tests(configs[0], g_pollset, g_mu); + run_tests(); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c deleted file mode 100644 index 782dfb413a..0000000000 --- a/test/core/iomgr/tcp_server_posix_test.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/tcp_server.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; -static int g_nconnects = 0; - -typedef struct { - /* Owns a ref to server. */ - grpc_tcp_server *server; - unsigned port_index; - unsigned fd_index; - int server_fd; -} on_connect_result; - -typedef struct { - grpc_tcp_server *server; - - /* arg is this server_weak_ref. */ - grpc_closure server_shutdown; -} server_weak_ref; - -#define MAX_URI 1024 -typedef struct { - grpc_resolved_address addr; - char str[MAX_URI]; -} test_addr; - -#define MAX_ADDRS 100 -typedef struct { - size_t naddrs; - test_addr addrs[MAX_ADDRS]; -} test_addrs; - -static on_connect_result g_result = {NULL, 0, 0, -1}; - -static char family_name_buf[1024]; -static const char *sock_family_name(int family) { - if (family == AF_INET) { - return "AF_INET"; - } else if (family == AF_INET6) { - return "AF_INET6"; - } else if (family == AF_UNSPEC) { - return "AF_UNSPEC"; - } else { - sprintf(family_name_buf, "%d", family); - return family_name_buf; - } -} - -static void on_connect_result_init(on_connect_result *result) { - result->server = NULL; - result->port_index = 0; - result->fd_index = 0; - result->server_fd = -1; -} - -static void on_connect_result_set(on_connect_result *result, - const grpc_tcp_server_acceptor *acceptor) { - result->server = grpc_tcp_server_ref(acceptor->from_server); - result->port_index = acceptor->port_index; - result->fd_index = acceptor->fd_index; - result->server_fd = grpc_tcp_server_port_fd( - result->server, acceptor->port_index, acceptor->fd_index); -} - -static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - server_weak_ref *weak_ref = arg; - weak_ref->server = NULL; -} - -static void server_weak_ref_init(server_weak_ref *weak_ref) { - weak_ref->server = NULL; - GRPC_CLOSURE_INIT(&weak_ref->server_shutdown, server_weak_ref_shutdown, - weak_ref, grpc_schedule_on_exec_ctx); -} - -/* Make weak_ref->server_shutdown a shutdown_starting cb on server. - grpc_tcp_server promises that the server object will live until - weak_ref->server_shutdown has returned. A strong ref on grpc_tcp_server - should be held until server_weak_ref_set() returns to avoid a race where the - server is deleted before the shutdown_starting cb is added. */ -static void server_weak_ref_set(server_weak_ref *weak_ref, - grpc_tcp_server *server) { - grpc_tcp_server_shutdown_starting_add(server, &weak_ref->server_shutdown); - weak_ref->server = server; -} - -static void test_addr_init_str(test_addr *addr) { - char *str = NULL; - if (grpc_sockaddr_to_string(&str, &addr->addr, 0) != -1) { - size_t str_len; - memcpy(addr->str, str, (str_len = strnlen(str, sizeof(addr->str) - 1))); - addr->str[str_len] = '\0'; - gpr_free(str); - } else { - addr->str[0] = '\0'; - } -} - -static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, - grpc_pollset *pollset, - grpc_tcp_server_acceptor *acceptor) { - grpc_endpoint_shutdown(exec_ctx, tcp, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); - grpc_endpoint_destroy(exec_ctx, tcp); - - on_connect_result temp_result; - on_connect_result_set(&temp_result, acceptor); - gpr_free(acceptor); - - gpr_mu_lock(g_mu); - g_result = temp_result; - g_nconnects++; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void test_no_op(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_start(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_start"); - grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_port"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - int port = -1; - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == - GRPC_ERROR_NONE && - port > 0); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_port_and_start(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_port_and_start"); - int port = -1; - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == - GRPC_ERROR_NONE && - port > 0); - - grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static grpc_error *tcp_connect(grpc_exec_ctx *exec_ctx, const test_addr *remote, - on_connect_result *result) { - grpc_millis deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); - int clifd; - int nconnects_before; - const struct sockaddr *remote_addr = - (const struct sockaddr *)remote->addr.addr; - - gpr_log(GPR_INFO, "Connecting to %s", remote->str); - gpr_mu_lock(g_mu); - nconnects_before = g_nconnects; - on_connect_result_init(&g_result); - clifd = socket(remote_addr->sa_family, SOCK_STREAM, 0); - if (clifd < 0) { - gpr_mu_unlock(g_mu); - return GRPC_OS_ERROR(errno, "Failed to create socket"); - } - gpr_log(GPR_DEBUG, "start connect to %s", remote->str); - if (connect(clifd, remote_addr, (socklen_t)remote->addr.len) != 0) { - gpr_mu_unlock(g_mu); - close(clifd); - return GRPC_OS_ERROR(errno, "connect"); - } - gpr_log(GPR_DEBUG, "wait"); - while (g_nconnects == nconnects_before && - deadline > grpc_exec_ctx_now(exec_ctx)) { - grpc_pollset_worker *worker = NULL; - grpc_error *err; - if ((err = grpc_pollset_work(exec_ctx, g_pollset, &worker, deadline)) != - GRPC_ERROR_NONE) { - gpr_mu_unlock(g_mu); - close(clifd); - return err; - } - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_log(GPR_DEBUG, "wait done"); - if (g_nconnects != nconnects_before + 1) { - gpr_mu_unlock(g_mu); - close(clifd); - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Didn't connect"); - } - close(clifd); - *result = g_result; - - gpr_mu_unlock(g_mu); - gpr_log(GPR_INFO, "Result (%d, %d) fd %d", result->port_index, - result->fd_index, result->server_fd); - grpc_tcp_server_unref(exec_ctx, result->server); - return GRPC_ERROR_NONE; -} - -/* Tests a tcp server on "::" listeners with multiple ports. If channel_args is - non-NULL, pass them to the server. If dst_addrs is non-NULL, use valid addrs - as destination addrs (port is not set). If dst_addrs is NULL, use listener - addrs as destination addrs. If test_dst_addrs is true, test connectivity with - each destination address, set grpc_resolved_address::len=0 for failures, but - don't fail the overall unitest. */ -static void test_connect(size_t num_connects, - const grpc_channel_args *channel_args, - test_addrs *dst_addrs, bool test_dst_addrs) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - grpc_resolved_address resolved_addr1; - struct sockaddr_storage *const addr = - (struct sockaddr_storage *)resolved_addr.addr; - struct sockaddr_storage *const addr1 = - (struct sockaddr_storage *)resolved_addr1.addr; - unsigned svr_fd_count; - int port; - int svr_port; - unsigned svr1_fd_count; - int svr1_port; - grpc_tcp_server *s; - const unsigned num_ports = 2; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, channel_args, &s)); - unsigned port_num; - server_weak_ref weak_ref; - server_weak_ref_init(&weak_ref); - server_weak_ref_set(&weak_ref, s); - LOG_TEST("test_connect"); - gpr_log(GPR_INFO, - "clients=%lu, num chan args=%lu, remote IP=%s, test_dst_addrs=%d", - (unsigned long)num_connects, - (unsigned long)(channel_args != NULL ? channel_args->num_args : 0), - dst_addrs != NULL ? "" : "::", test_dst_addrs); - memset(&resolved_addr, 0, sizeof(resolved_addr)); - memset(&resolved_addr1, 0, sizeof(resolved_addr1)); - resolved_addr.len = sizeof(struct sockaddr_storage); - resolved_addr1.len = sizeof(struct sockaddr_storage); - addr->ss_family = addr1->ss_family = AF_INET; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "grpc_tcp_server_add_port", - grpc_tcp_server_add_port(s, &resolved_addr, &svr_port))); - gpr_log(GPR_INFO, "Allocated port %d", svr_port); - GPR_ASSERT(svr_port > 0); - /* Cannot use wildcard (port==0), because add_port() will try to reuse the - same port as a previous add_port(). */ - svr1_port = grpc_pick_unused_port_or_die(); - GPR_ASSERT(svr1_port > 0); - gpr_log(GPR_INFO, "Picked unused port %d", svr1_port); - grpc_sockaddr_set_port(&resolved_addr1, svr1_port); - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &port) == - GRPC_ERROR_NONE && - port == svr1_port); - - /* Bad port_index. */ - GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0); - GPR_ASSERT(grpc_tcp_server_port_fd(s, 2, 0) < 0); - - /* Bad fd_index. */ - GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 100) < 0); - GPR_ASSERT(grpc_tcp_server_port_fd(s, 1, 100) < 0); - - /* Got at least one fd per port. */ - svr_fd_count = grpc_tcp_server_port_fd_count(s, 0); - GPR_ASSERT(svr_fd_count >= 1); - svr1_fd_count = grpc_tcp_server_port_fd_count(s, 1); - GPR_ASSERT(svr1_fd_count >= 1); - - grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); - - if (dst_addrs != NULL) { - int ports[] = {svr_port, svr1_port}; - for (port_num = 0; port_num < num_ports; ++port_num) { - size_t dst_idx; - size_t num_tested = 0; - for (dst_idx = 0; dst_idx < dst_addrs->naddrs; ++dst_idx) { - test_addr dst = dst_addrs->addrs[dst_idx]; - on_connect_result result; - grpc_error *err; - if (dst.addr.len == 0) { - gpr_log(GPR_DEBUG, "Skipping test of non-functional local IP %s", - dst.str); - continue; - } - GPR_ASSERT(grpc_sockaddr_set_port(&dst.addr, ports[port_num])); - test_addr_init_str(&dst); - ++num_tested; - on_connect_result_init(&result); - if ((err = tcp_connect(&exec_ctx, &dst, &result)) == GRPC_ERROR_NONE && - result.server_fd >= 0 && result.server == s) { - continue; - } - gpr_log(GPR_ERROR, "Failed to connect to %s: %s", dst.str, - grpc_error_string(err)); - GPR_ASSERT(test_dst_addrs); - dst_addrs->addrs[dst_idx].addr.len = 0; - GRPC_ERROR_UNREF(err); - } - GPR_ASSERT(num_tested > 0); - } - } else { - for (port_num = 0; port_num < num_ports; ++port_num) { - const unsigned num_fds = grpc_tcp_server_port_fd_count(s, port_num); - unsigned fd_num; - for (fd_num = 0; fd_num < num_fds; ++fd_num) { - int fd = grpc_tcp_server_port_fd(s, port_num, fd_num); - size_t connect_num; - test_addr dst; - GPR_ASSERT(fd >= 0); - dst.addr.len = sizeof(dst.addr.addr); - GPR_ASSERT(getsockname(fd, (struct sockaddr *)dst.addr.addr, - (socklen_t *)&dst.addr.len) == 0); - GPR_ASSERT(dst.addr.len <= sizeof(dst.addr.addr)); - test_addr_init_str(&dst); - gpr_log(GPR_INFO, "(%d, %d) fd %d family %s listening on %s", port_num, - fd_num, fd, sock_family_name(addr->ss_family), dst.str); - for (connect_num = 0; connect_num < num_connects; ++connect_num) { - on_connect_result result; - on_connect_result_init(&result); - GPR_ASSERT(GRPC_LOG_IF_ERROR("tcp_connect", - tcp_connect(&exec_ctx, &dst, &result))); - GPR_ASSERT(result.server_fd == fd); - GPR_ASSERT(result.port_index == port_num); - GPR_ASSERT(result.fd_index == fd_num); - GPR_ASSERT(result.server == s); - GPR_ASSERT( - grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) == - result.server_fd); - } - } - } - } - /* Weak ref to server valid until final unref. */ - GPR_ASSERT(weak_ref.server != NULL); - GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); - - /* Weak ref lost. */ - GPR_ASSERT(weak_ref.server == NULL); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_arg chan_args[] = { - {GRPC_ARG_INTEGER, GRPC_ARG_EXPAND_WILDCARD_ADDRS, {.integer = 1}}}; - const grpc_channel_args channel_args = {1, chan_args}; - struct ifaddrs *ifa = NULL; - struct ifaddrs *ifa_it; - // Zalloc dst_addrs to avoid oversized frames. - test_addrs *dst_addrs = gpr_zalloc(sizeof(*dst_addrs)); - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - - test_no_op(); - test_no_op_with_start(); - test_no_op_with_port(); - test_no_op_with_port_and_start(); - - if (getifaddrs(&ifa) != 0 || ifa == NULL) { - gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno)); - return EXIT_FAILURE; - } - dst_addrs->naddrs = 0; - for (ifa_it = ifa; ifa_it != NULL && dst_addrs->naddrs < MAX_ADDRS; - ifa_it = ifa_it->ifa_next) { - if (ifa_it->ifa_addr == NULL) { - continue; - } else if (ifa_it->ifa_addr->sa_family == AF_INET) { - dst_addrs->addrs[dst_addrs->naddrs].addr.len = sizeof(struct sockaddr_in); - } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { - dst_addrs->addrs[dst_addrs->naddrs].addr.len = - sizeof(struct sockaddr_in6); - } else { - continue; - } - memcpy(dst_addrs->addrs[dst_addrs->naddrs].addr.addr, ifa_it->ifa_addr, - dst_addrs->addrs[dst_addrs->naddrs].addr.len); - GPR_ASSERT( - grpc_sockaddr_set_port(&dst_addrs->addrs[dst_addrs->naddrs].addr, 0)); - test_addr_init_str(&dst_addrs->addrs[dst_addrs->naddrs]); - ++dst_addrs->naddrs; - } - freeifaddrs(ifa); - ifa = NULL; - - /* Connect to same addresses as listeners. */ - test_connect(1, NULL, NULL, false); - test_connect(10, NULL, NULL, false); - - /* Set dst_addrs->addrs[i].len=0 for dst_addrs that are unreachable with a - "::" listener. */ - test_connect(1, NULL, dst_addrs, true); - - /* Test connect(2) with dst_addrs. */ - test_connect(1, &channel_args, dst_addrs, false); - /* Test connect(2) with dst_addrs. */ - test_connect(10, &channel_args, dst_addrs, false); - - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(dst_addrs); - gpr_free(g_pollset); - return EXIT_SUCCESS; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc new file mode 100644 index 0000000000..a44e3954f2 --- /dev/null +++ b/test/core/iomgr/tcp_server_posix_test.cc @@ -0,0 +1,512 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/tcp_server.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_nconnects = 0; + +typedef struct { + /* Owns a ref to server. */ + grpc_tcp_server *server; + unsigned port_index; + unsigned fd_index; + int server_fd; +} on_connect_result; + +typedef struct { + grpc_tcp_server *server; + + /* arg is this server_weak_ref. */ + grpc_closure server_shutdown; +} server_weak_ref; + +#define MAX_URI 1024 +typedef struct { + grpc_resolved_address addr; + char str[MAX_URI]; +} test_addr; + +#define MAX_ADDRS 100 +typedef struct { + size_t naddrs; + test_addr addrs[MAX_ADDRS]; +} test_addrs; + +static on_connect_result g_result = {NULL, 0, 0, -1}; + +static char family_name_buf[1024]; +static const char *sock_family_name(int family) { + if (family == AF_INET) { + return "AF_INET"; + } else if (family == AF_INET6) { + return "AF_INET6"; + } else if (family == AF_UNSPEC) { + return "AF_UNSPEC"; + } else { + sprintf(family_name_buf, "%d", family); + return family_name_buf; + } +} + +static void on_connect_result_init(on_connect_result *result) { + result->server = NULL; + result->port_index = 0; + result->fd_index = 0; + result->server_fd = -1; +} + +static void on_connect_result_set(on_connect_result *result, + const grpc_tcp_server_acceptor *acceptor) { + result->server = grpc_tcp_server_ref(acceptor->from_server); + result->port_index = acceptor->port_index; + result->fd_index = acceptor->fd_index; + result->server_fd = grpc_tcp_server_port_fd( + result->server, acceptor->port_index, acceptor->fd_index); +} + +static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + server_weak_ref *weak_ref = static_cast(arg); + weak_ref->server = NULL; +} + +static void server_weak_ref_init(server_weak_ref *weak_ref) { + weak_ref->server = NULL; + GRPC_CLOSURE_INIT(&weak_ref->server_shutdown, server_weak_ref_shutdown, + weak_ref, grpc_schedule_on_exec_ctx); +} + +/* Make weak_ref->server_shutdown a shutdown_starting cb on server. + grpc_tcp_server promises that the server object will live until + weak_ref->server_shutdown has returned. A strong ref on grpc_tcp_server + should be held until server_weak_ref_set() returns to avoid a race where the + server is deleted before the shutdown_starting cb is added. */ +static void server_weak_ref_set(server_weak_ref *weak_ref, + grpc_tcp_server *server) { + grpc_tcp_server_shutdown_starting_add(server, &weak_ref->server_shutdown); + weak_ref->server = server; +} + +static void test_addr_init_str(test_addr *addr) { + char *str = NULL; + if (grpc_sockaddr_to_string(&str, &addr->addr, 0) != -1) { + size_t str_len; + memcpy(addr->str, str, (str_len = strnlen(str, sizeof(addr->str) - 1))); + addr->str[str_len] = '\0'; + gpr_free(str); + } else { + addr->str[0] = '\0'; + } +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, + grpc_pollset *pollset, + grpc_tcp_server_acceptor *acceptor) { + grpc_endpoint_shutdown(exec_ctx, tcp, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); + grpc_endpoint_destroy(exec_ctx, tcp); + + on_connect_result temp_result; + on_connect_result_set(&temp_result, acceptor); + gpr_free(acceptor); + + gpr_mu_lock(g_mu); + g_result = temp_result; + g_nconnects++; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void test_no_op(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_start"); + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + int port = -1; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port_and_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port_and_start"); + int port = -1; + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static grpc_error *tcp_connect(grpc_exec_ctx *exec_ctx, const test_addr *remote, + on_connect_result *result) { + grpc_millis deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); + int clifd; + int nconnects_before; + const struct sockaddr *remote_addr = + (const struct sockaddr *)remote->addr.addr; + + gpr_log(GPR_INFO, "Connecting to %s", remote->str); + gpr_mu_lock(g_mu); + nconnects_before = g_nconnects; + on_connect_result_init(&g_result); + clifd = socket(remote_addr->sa_family, SOCK_STREAM, 0); + if (clifd < 0) { + gpr_mu_unlock(g_mu); + return GRPC_OS_ERROR(errno, "Failed to create socket"); + } + gpr_log(GPR_DEBUG, "start connect to %s", remote->str); + if (connect(clifd, remote_addr, (socklen_t)remote->addr.len) != 0) { + gpr_mu_unlock(g_mu); + close(clifd); + return GRPC_OS_ERROR(errno, "connect"); + } + gpr_log(GPR_DEBUG, "wait"); + while (g_nconnects == nconnects_before && + deadline > grpc_exec_ctx_now(exec_ctx)) { + grpc_pollset_worker *worker = NULL; + grpc_error *err; + if ((err = grpc_pollset_work(exec_ctx, g_pollset, &worker, deadline)) != + GRPC_ERROR_NONE) { + gpr_mu_unlock(g_mu); + close(clifd); + return err; + } + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_log(GPR_DEBUG, "wait done"); + if (g_nconnects != nconnects_before + 1) { + gpr_mu_unlock(g_mu); + close(clifd); + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Didn't connect"); + } + close(clifd); + *result = g_result; + + gpr_mu_unlock(g_mu); + gpr_log(GPR_INFO, "Result (%d, %d) fd %d", result->port_index, + result->fd_index, result->server_fd); + grpc_tcp_server_unref(exec_ctx, result->server); + return GRPC_ERROR_NONE; +} + +/* Tests a tcp server on "::" listeners with multiple ports. If channel_args is + non-NULL, pass them to the server. If dst_addrs is non-NULL, use valid addrs + as destination addrs (port is not set). If dst_addrs is NULL, use listener + addrs as destination addrs. If test_dst_addrs is true, test connectivity with + each destination address, set grpc_resolved_address::len=0 for failures, but + don't fail the overall unitest. */ +static void test_connect(size_t num_connects, + const grpc_channel_args *channel_args, + test_addrs *dst_addrs, bool test_dst_addrs) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + grpc_resolved_address resolved_addr1; + struct sockaddr_storage *const addr = + (struct sockaddr_storage *)resolved_addr.addr; + struct sockaddr_storage *const addr1 = + (struct sockaddr_storage *)resolved_addr1.addr; + unsigned svr_fd_count; + int port; + int svr_port; + unsigned svr1_fd_count; + int svr1_port; + grpc_tcp_server *s; + const unsigned num_ports = 2; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, channel_args, &s)); + unsigned port_num; + server_weak_ref weak_ref; + server_weak_ref_init(&weak_ref); + server_weak_ref_set(&weak_ref, s); + LOG_TEST("test_connect"); + gpr_log(GPR_INFO, + "clients=%lu, num chan args=%lu, remote IP=%s, test_dst_addrs=%d", + (unsigned long)num_connects, + (unsigned long)(channel_args != NULL ? channel_args->num_args : 0), + dst_addrs != NULL ? "" : "::", test_dst_addrs); + memset(&resolved_addr, 0, sizeof(resolved_addr)); + memset(&resolved_addr1, 0, sizeof(resolved_addr1)); + resolved_addr.len = sizeof(struct sockaddr_storage); + resolved_addr1.len = sizeof(struct sockaddr_storage); + addr->ss_family = addr1->ss_family = AF_INET; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "grpc_tcp_server_add_port", + grpc_tcp_server_add_port(s, &resolved_addr, &svr_port))); + gpr_log(GPR_INFO, "Allocated port %d", svr_port); + GPR_ASSERT(svr_port > 0); + /* Cannot use wildcard (port==0), because add_port() will try to reuse the + same port as a previous add_port(). */ + svr1_port = grpc_pick_unused_port_or_die(); + GPR_ASSERT(svr1_port > 0); + gpr_log(GPR_INFO, "Picked unused port %d", svr1_port); + grpc_sockaddr_set_port(&resolved_addr1, svr1_port); + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &port) == + GRPC_ERROR_NONE && + port == svr1_port); + + /* Bad port_index. */ + GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0); + GPR_ASSERT(grpc_tcp_server_port_fd(s, 2, 0) < 0); + + /* Bad fd_index. */ + GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 100) < 0); + GPR_ASSERT(grpc_tcp_server_port_fd(s, 1, 100) < 0); + + /* Got at least one fd per port. */ + svr_fd_count = grpc_tcp_server_port_fd_count(s, 0); + GPR_ASSERT(svr_fd_count >= 1); + svr1_fd_count = grpc_tcp_server_port_fd_count(s, 1); + GPR_ASSERT(svr1_fd_count >= 1); + + grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); + + if (dst_addrs != NULL) { + int ports[] = {svr_port, svr1_port}; + for (port_num = 0; port_num < num_ports; ++port_num) { + size_t dst_idx; + size_t num_tested = 0; + for (dst_idx = 0; dst_idx < dst_addrs->naddrs; ++dst_idx) { + test_addr dst = dst_addrs->addrs[dst_idx]; + on_connect_result result; + grpc_error *err; + if (dst.addr.len == 0) { + gpr_log(GPR_DEBUG, "Skipping test of non-functional local IP %s", + dst.str); + continue; + } + GPR_ASSERT(grpc_sockaddr_set_port(&dst.addr, ports[port_num])); + test_addr_init_str(&dst); + ++num_tested; + on_connect_result_init(&result); + if ((err = tcp_connect(&exec_ctx, &dst, &result)) == GRPC_ERROR_NONE && + result.server_fd >= 0 && result.server == s) { + continue; + } + gpr_log(GPR_ERROR, "Failed to connect to %s: %s", dst.str, + grpc_error_string(err)); + GPR_ASSERT(test_dst_addrs); + dst_addrs->addrs[dst_idx].addr.len = 0; + GRPC_ERROR_UNREF(err); + } + GPR_ASSERT(num_tested > 0); + } + } else { + for (port_num = 0; port_num < num_ports; ++port_num) { + const unsigned num_fds = grpc_tcp_server_port_fd_count(s, port_num); + unsigned fd_num; + for (fd_num = 0; fd_num < num_fds; ++fd_num) { + int fd = grpc_tcp_server_port_fd(s, port_num, fd_num); + size_t connect_num; + test_addr dst; + GPR_ASSERT(fd >= 0); + dst.addr.len = sizeof(dst.addr.addr); + GPR_ASSERT(getsockname(fd, (struct sockaddr *)dst.addr.addr, + (socklen_t *)&dst.addr.len) == 0); + GPR_ASSERT(dst.addr.len <= sizeof(dst.addr.addr)); + test_addr_init_str(&dst); + gpr_log(GPR_INFO, "(%d, %d) fd %d family %s listening on %s", port_num, + fd_num, fd, sock_family_name(addr->ss_family), dst.str); + for (connect_num = 0; connect_num < num_connects; ++connect_num) { + on_connect_result result; + on_connect_result_init(&result); + GPR_ASSERT(GRPC_LOG_IF_ERROR("tcp_connect", + tcp_connect(&exec_ctx, &dst, &result))); + GPR_ASSERT(result.server_fd == fd); + GPR_ASSERT(result.port_index == port_num); + GPR_ASSERT(result.fd_index == fd_num); + GPR_ASSERT(result.server == s); + GPR_ASSERT( + grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) == + result.server_fd); + } + } + } + } + /* Weak ref to server valid until final unref. */ + GPR_ASSERT(weak_ref.server != NULL); + GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); + + /* Weak ref lost. */ + GPR_ASSERT(weak_ref.server == NULL); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_arg chan_args[1]; + chan_args[0].type = GRPC_ARG_INTEGER; + chan_args[0].key = const_cast(GRPC_ARG_EXPAND_WILDCARD_ADDRS); + chan_args[0].value.integer = 1; + const grpc_channel_args channel_args = {1, chan_args}; + struct ifaddrs *ifa = NULL; + struct ifaddrs *ifa_it; + // Zalloc dst_addrs to avoid oversized frames. + test_addrs *dst_addrs = + static_cast(gpr_zalloc(sizeof(*dst_addrs))); + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(g_pollset, &g_mu); + + test_no_op(); + test_no_op_with_start(); + test_no_op_with_port(); + test_no_op_with_port_and_start(); + + if (getifaddrs(&ifa) != 0 || ifa == NULL) { + gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno)); + return EXIT_FAILURE; + } + dst_addrs->naddrs = 0; + for (ifa_it = ifa; ifa_it != NULL && dst_addrs->naddrs < MAX_ADDRS; + ifa_it = ifa_it->ifa_next) { + if (ifa_it->ifa_addr == NULL) { + continue; + } else if (ifa_it->ifa_addr->sa_family == AF_INET) { + dst_addrs->addrs[dst_addrs->naddrs].addr.len = sizeof(struct sockaddr_in); + } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { + dst_addrs->addrs[dst_addrs->naddrs].addr.len = + sizeof(struct sockaddr_in6); + } else { + continue; + } + memcpy(dst_addrs->addrs[dst_addrs->naddrs].addr.addr, ifa_it->ifa_addr, + dst_addrs->addrs[dst_addrs->naddrs].addr.len); + GPR_ASSERT( + grpc_sockaddr_set_port(&dst_addrs->addrs[dst_addrs->naddrs].addr, 0)); + test_addr_init_str(&dst_addrs->addrs[dst_addrs->naddrs]); + ++dst_addrs->naddrs; + } + freeifaddrs(ifa); + ifa = NULL; + + /* Connect to same addresses as listeners. */ + test_connect(1, NULL, NULL, false); + test_connect(10, NULL, NULL, false); + + /* Set dst_addrs->addrs[i].len=0 for dst_addrs that are unreachable with a + "::" listener. */ + test_connect(1, NULL, dst_addrs, true); + + /* Test connect(2) with dst_addrs. */ + test_connect(1, &channel_args, dst_addrs, false); + /* Test connect(2) with dst_addrs. */ + test_connect(10, &channel_args, dst_addrs, false); + + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(dst_addrs); + gpr_free(g_pollset); + return EXIT_SUCCESS; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c deleted file mode 100644 index 9fafd3177a..0000000000 --- a/test/core/iomgr/tcp_server_uv_test.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with libuv -#ifdef GRPC_UV - -#include - -#include "src/core/lib/iomgr/tcp_server.h" - -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; -static int g_nconnects = 0; - -typedef struct on_connect_result { - /* Owns a ref to server. */ - grpc_tcp_server *server; - unsigned port_index; - unsigned fd_index; -} on_connect_result; - -typedef struct server_weak_ref { - grpc_tcp_server *server; - - /* arg is this server_weak_ref. */ - grpc_closure server_shutdown; -} server_weak_ref; - -static on_connect_result g_result = {NULL, 0, 0}; - -static void on_connect_result_init(on_connect_result *result) { - result->server = NULL; - result->port_index = 0; - result->fd_index = 0; -} - -static void on_connect_result_set(on_connect_result *result, - const grpc_tcp_server_acceptor *acceptor) { - result->server = grpc_tcp_server_ref(acceptor->from_server); - result->port_index = acceptor->port_index; - result->fd_index = acceptor->fd_index; -} - -static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - server_weak_ref *weak_ref = arg; - weak_ref->server = NULL; -} - -static void server_weak_ref_init(server_weak_ref *weak_ref) { - weak_ref->server = NULL; - GRPC_CLOSURE_INIT(&weak_ref->server_shutdown, server_weak_ref_shutdown, - weak_ref, grpc_schedule_on_exec_ctx); -} - -/* Make weak_ref->server_shutdown a shutdown_starting cb on server. - grpc_tcp_server promises that the server object will live until - weak_ref->server_shutdown has returned. A strong ref on grpc_tcp_server - should be held until server_weak_ref_set() returns to avoid a race where the - server is deleted before the shutdown_starting cb is added. */ -static void server_weak_ref_set(server_weak_ref *weak_ref, - grpc_tcp_server *server) { - grpc_tcp_server_shutdown_starting_add(server, &weak_ref->server_shutdown); - weak_ref->server = server; -} - -static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, - grpc_pollset *pollset, - grpc_tcp_server_acceptor *acceptor) { - grpc_endpoint_shutdown(exec_ctx, tcp, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); - grpc_endpoint_destroy(exec_ctx, tcp); - - on_connect_result temp_result; - on_connect_result_set(&temp_result, acceptor); - gpr_free(acceptor); - - gpr_mu_lock(g_mu); - g_result = temp_result; - g_nconnects++; - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void test_no_op(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_start(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_start"); - grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_port(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_port"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - int port; - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == - GRPC_ERROR_NONE && - port > 0); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_port_and_start(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - LOG_TEST("test_no_op_with_port_and_start"); - int port; - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == - GRPC_ERROR_NONE && - port > 0); - - grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void connect_cb(uv_connect_t *req, int status) { - GPR_ASSERT(status == 0); - gpr_free(req); -} - -static void close_cb(uv_handle_t *handle) { gpr_free(handle); } - -static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote, - socklen_t remote_len, on_connect_result *result) { - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); - uv_connect_t *req = gpr_malloc(sizeof(uv_connect_t)); - int nconnects_before; - - gpr_mu_lock(g_mu); - nconnects_before = g_nconnects; - on_connect_result_init(&g_result); - GPR_ASSERT(uv_tcp_init(uv_default_loop(), client_handle) == 0); - gpr_log(GPR_DEBUG, "start connect"); - GPR_ASSERT(uv_tcp_connect(req, client_handle, remote, connect_cb) == 0); - gpr_log(GPR_DEBUG, "wait"); - while (g_nconnects == nconnects_before && - gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(exec_ctx, g_pollset, &worker, - grpc_timespec_to_millis_round_up(deadline)))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_finish(exec_ctx); - gpr_mu_lock(g_mu); - } - gpr_log(GPR_DEBUG, "wait done"); - GPR_ASSERT(g_nconnects == nconnects_before + 1); - uv_close((uv_handle_t *)client_handle, close_cb); - *result = g_result; - - gpr_mu_unlock(g_mu); -} - -/* Tests a tcp server with multiple ports. */ -static void test_connect(unsigned n) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - grpc_resolved_address resolved_addr1; - struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; - struct sockaddr_storage *addr1 = - (struct sockaddr_storage *)resolved_addr1.addr; - int svr_port; - int svr1_port; - grpc_tcp_server *s; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); - unsigned i; - server_weak_ref weak_ref; - server_weak_ref_init(&weak_ref); - LOG_TEST("test_connect"); - gpr_log(GPR_INFO, "clients=%d", n); - memset(&resolved_addr, 0, sizeof(resolved_addr)); - memset(&resolved_addr1, 0, sizeof(resolved_addr1)); - resolved_addr.len = sizeof(struct sockaddr_storage); - resolved_addr1.len = sizeof(struct sockaddr_storage); - addr->ss_family = addr1->ss_family = AF_INET; - GPR_ASSERT(GRPC_ERROR_NONE == - grpc_tcp_server_add_port(s, &resolved_addr, &svr_port)); - GPR_ASSERT(svr_port > 0); - GPR_ASSERT((uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr)) == 0); - /* Cannot use wildcard (port==0), because add_port() will try to reuse the - same port as a previous add_port(). */ - svr1_port = grpc_pick_unused_port_or_die(); - grpc_sockaddr_set_port(&resolved_addr1, svr1_port); - GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &svr_port) == - GRPC_ERROR_NONE && - svr_port == svr1_port); - - grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); - - GPR_ASSERT(uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr1) == 0); - - for (i = 0; i < n; i++) { - on_connect_result result; - on_connect_result_init(&result); - tcp_connect(&exec_ctx, (struct sockaddr *)addr, - (socklen_t)resolved_addr.len, &result); - GPR_ASSERT(result.port_index == 0); - GPR_ASSERT(result.server == s); - if (weak_ref.server == NULL) { - server_weak_ref_set(&weak_ref, result.server); - } - grpc_tcp_server_unref(&exec_ctx, result.server); - - on_connect_result_init(&result); - tcp_connect(&exec_ctx, (struct sockaddr *)addr1, - (socklen_t)resolved_addr1.len, &result); - GPR_ASSERT(result.port_index == 1); - GPR_ASSERT(result.server == s); - grpc_tcp_server_unref(&exec_ctx, result.server); - } - - /* Weak ref to server valid until final unref. */ - GPR_ASSERT(weak_ref.server != NULL); - - grpc_tcp_server_unref(&exec_ctx, s); - grpc_exec_ctx_finish(&exec_ctx); - - /* Weak ref lost. */ - GPR_ASSERT(weak_ref.server == NULL); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_malloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - - test_no_op(); - test_no_op_with_start(); - test_no_op_with_port(); - test_no_op_with_port_and_start(); - test_connect(1); - test_connect(10); - - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(g_pollset); - return 0; -} - -#else /* GRPC_UV */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_UV */ diff --git a/test/core/iomgr/tcp_server_uv_test.cc b/test/core/iomgr/tcp_server_uv_test.cc new file mode 100644 index 0000000000..9fafd3177a --- /dev/null +++ b/test/core/iomgr/tcp_server_uv_test.cc @@ -0,0 +1,325 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with libuv +#ifdef GRPC_UV + +#include + +#include "src/core/lib/iomgr/tcp_server.h" + +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; +static int g_nconnects = 0; + +typedef struct on_connect_result { + /* Owns a ref to server. */ + grpc_tcp_server *server; + unsigned port_index; + unsigned fd_index; +} on_connect_result; + +typedef struct server_weak_ref { + grpc_tcp_server *server; + + /* arg is this server_weak_ref. */ + grpc_closure server_shutdown; +} server_weak_ref; + +static on_connect_result g_result = {NULL, 0, 0}; + +static void on_connect_result_init(on_connect_result *result) { + result->server = NULL; + result->port_index = 0; + result->fd_index = 0; +} + +static void on_connect_result_set(on_connect_result *result, + const grpc_tcp_server_acceptor *acceptor) { + result->server = grpc_tcp_server_ref(acceptor->from_server); + result->port_index = acceptor->port_index; + result->fd_index = acceptor->fd_index; +} + +static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + server_weak_ref *weak_ref = arg; + weak_ref->server = NULL; +} + +static void server_weak_ref_init(server_weak_ref *weak_ref) { + weak_ref->server = NULL; + GRPC_CLOSURE_INIT(&weak_ref->server_shutdown, server_weak_ref_shutdown, + weak_ref, grpc_schedule_on_exec_ctx); +} + +/* Make weak_ref->server_shutdown a shutdown_starting cb on server. + grpc_tcp_server promises that the server object will live until + weak_ref->server_shutdown has returned. A strong ref on grpc_tcp_server + should be held until server_weak_ref_set() returns to avoid a race where the + server is deleted before the shutdown_starting cb is added. */ +static void server_weak_ref_set(server_weak_ref *weak_ref, + grpc_tcp_server *server) { + grpc_tcp_server_shutdown_starting_add(server, &weak_ref->server_shutdown); + weak_ref->server = server; +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, + grpc_pollset *pollset, + grpc_tcp_server_acceptor *acceptor) { + grpc_endpoint_shutdown(exec_ctx, tcp, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); + grpc_endpoint_destroy(exec_ctx, tcp); + + on_connect_result temp_result; + on_connect_result_set(&temp_result, acceptor); + gpr_free(acceptor); + + gpr_mu_lock(g_mu); + g_result = temp_result; + g_nconnects++; + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void test_no_op(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_start"); + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + int port; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port_and_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + LOG_TEST("test_no_op_with_port_and_start"); + int port; + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == + GRPC_ERROR_NONE && + port > 0); + + grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void connect_cb(uv_connect_t *req, int status) { + GPR_ASSERT(status == 0); + gpr_free(req); +} + +static void close_cb(uv_handle_t *handle) { gpr_free(handle); } + +static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote, + socklen_t remote_len, on_connect_result *result) { + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); + uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t)); + uv_connect_t *req = gpr_malloc(sizeof(uv_connect_t)); + int nconnects_before; + + gpr_mu_lock(g_mu); + nconnects_before = g_nconnects; + on_connect_result_init(&g_result); + GPR_ASSERT(uv_tcp_init(uv_default_loop(), client_handle) == 0); + gpr_log(GPR_DEBUG, "start connect"); + GPR_ASSERT(uv_tcp_connect(req, client_handle, remote, connect_cb) == 0); + gpr_log(GPR_DEBUG, "wait"); + while (g_nconnects == nconnects_before && + gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(exec_ctx, g_pollset, &worker, + grpc_timespec_to_millis_round_up(deadline)))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_finish(exec_ctx); + gpr_mu_lock(g_mu); + } + gpr_log(GPR_DEBUG, "wait done"); + GPR_ASSERT(g_nconnects == nconnects_before + 1); + uv_close((uv_handle_t *)client_handle, close_cb); + *result = g_result; + + gpr_mu_unlock(g_mu); +} + +/* Tests a tcp server with multiple ports. */ +static void test_connect(unsigned n) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + grpc_resolved_address resolved_addr1; + struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; + struct sockaddr_storage *addr1 = + (struct sockaddr_storage *)resolved_addr1.addr; + int svr_port; + int svr1_port; + grpc_tcp_server *s; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); + unsigned i; + server_weak_ref weak_ref; + server_weak_ref_init(&weak_ref); + LOG_TEST("test_connect"); + gpr_log(GPR_INFO, "clients=%d", n); + memset(&resolved_addr, 0, sizeof(resolved_addr)); + memset(&resolved_addr1, 0, sizeof(resolved_addr1)); + resolved_addr.len = sizeof(struct sockaddr_storage); + resolved_addr1.len = sizeof(struct sockaddr_storage); + addr->ss_family = addr1->ss_family = AF_INET; + GPR_ASSERT(GRPC_ERROR_NONE == + grpc_tcp_server_add_port(s, &resolved_addr, &svr_port)); + GPR_ASSERT(svr_port > 0); + GPR_ASSERT((uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr)) == 0); + /* Cannot use wildcard (port==0), because add_port() will try to reuse the + same port as a previous add_port(). */ + svr1_port = grpc_pick_unused_port_or_die(); + grpc_sockaddr_set_port(&resolved_addr1, svr1_port); + GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &svr_port) == + GRPC_ERROR_NONE && + svr_port == svr1_port); + + grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); + + GPR_ASSERT(uv_ip6_addr("::", svr_port, (struct sockaddr_in6 *)addr1) == 0); + + for (i = 0; i < n; i++) { + on_connect_result result; + on_connect_result_init(&result); + tcp_connect(&exec_ctx, (struct sockaddr *)addr, + (socklen_t)resolved_addr.len, &result); + GPR_ASSERT(result.port_index == 0); + GPR_ASSERT(result.server == s); + if (weak_ref.server == NULL) { + server_weak_ref_set(&weak_ref, result.server); + } + grpc_tcp_server_unref(&exec_ctx, result.server); + + on_connect_result_init(&result); + tcp_connect(&exec_ctx, (struct sockaddr *)addr1, + (socklen_t)resolved_addr1.len, &result); + GPR_ASSERT(result.port_index == 1); + GPR_ASSERT(result.server == s); + grpc_tcp_server_unref(&exec_ctx, result.server); + } + + /* Weak ref to server valid until final unref. */ + GPR_ASSERT(weak_ref.server != NULL); + + grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); + + /* Weak ref lost. */ + GPR_ASSERT(weak_ref.server == NULL); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + + test_no_op(); + test_no_op_with_start(); + test_no_op_with_port(); + test_no_op_with_port_and_start(); + test_connect(1); + test_connect(10); + + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(g_pollset); + return 0; +} + +#else /* GRPC_UV */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_UV */ diff --git a/test/core/iomgr/time_averaged_stats_test.c b/test/core/iomgr/time_averaged_stats_test.c deleted file mode 100644 index 508e3c5bf8..0000000000 --- a/test/core/iomgr/time_averaged_stats_test.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/time_averaged_stats.h" - -#include - -#include -#include "test/core/util/test_config.h" - -#define EXPECT_EQ(a, b) GPR_ASSERT((a) == (b)) -#define EXPECT_DOUBLE_EQ(a, b) GPR_ASSERT(fabs((a) - (b)) < 1e-9) - -static void no_regress_no_persist_test_1(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); - - /* Should have no effect */ - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); - - /* Should replace old average */ - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); -} - -static void no_regress_no_persist_test_2(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - /* Should replace init value */ - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 3000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); -} - -static void no_regress_no_persist_test_3(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - /* Should replace init value */ - grpc_time_averaged_stats_add_sample(&tas, 2500); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(2500, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 3500); - grpc_time_averaged_stats_add_sample(&tas, 4500); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(4000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); -} - -static void some_regress_no_persist_test(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0.5, 0.0); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - /* (2 * 2000 + 0.5 * 1000) / 2.5 */ - EXPECT_DOUBLE_EQ(1800, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2.5, tas.aggregate_total_weight); -} - -static void some_decay_test(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 1, 0.0); - EXPECT_EQ(1000, tas.aggregate_weighted_avg); - /* Should avg with init value */ - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); -} - -static void no_regress_full_persist_test(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0, 1.0); - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); - - /* Should replace init value */ - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_EQ(2000, tas.aggregate_weighted_avg); - EXPECT_EQ(1, tas.aggregate_total_weight); - - /* Will result in average of the 3 samples. */ - grpc_time_averaged_stats_add_sample(&tas, 2300); - grpc_time_averaged_stats_add_sample(&tas, 2300); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(2200, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(3, tas.aggregate_total_weight); -} - -static void no_regress_some_persist_test(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0, 0.5); - /* Should replace init value */ - grpc_time_averaged_stats_add_sample(&tas, 2000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 2500); - grpc_time_averaged_stats_add_sample(&tas, 4000); - grpc_time_averaged_stats_update_average(&tas); - EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2.5, tas.aggregate_total_weight); -} - -static void some_regress_some_persist_test(void) { - grpc_time_averaged_stats tas; - grpc_time_averaged_stats_init(&tas, 1000, 0.4, 0.6); - /* Sample weight = 0 */ - EXPECT_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_EQ(0, tas.aggregate_total_weight); - - grpc_time_averaged_stats_update_average(&tas); - /* (0.6 * 0 * 1000 + 0.4 * 1000 / 0.4) */ - EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(0.4, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 2640); - grpc_time_averaged_stats_update_average(&tas); - /* (1 * 2640 + 0.6 * 0.4 * 1000 + 0.4 * 1000 / (1 + 0.6 * 0.4 + 0.4) */ - EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(1.64, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 2876.8); - grpc_time_averaged_stats_update_average(&tas); - /* (1 * 2876.8 + 0.6 * 1.64 * 2000 + 0.4 * 1000 / (1 + 0.6 * 1.64 + 0.4) */ - EXPECT_DOUBLE_EQ(2200, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2.384, tas.aggregate_total_weight); - - grpc_time_averaged_stats_add_sample(&tas, 4944.32); - grpc_time_averaged_stats_update_average(&tas); - /* (1 * 4944.32 + 0.6 * 2.384 * 2200 + 0.4 * 1000) / - (1 + 0.6 * 2.384 + 0.4) */ - EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); - EXPECT_DOUBLE_EQ(2.8304, tas.aggregate_total_weight); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - no_regress_no_persist_test_1(); - no_regress_no_persist_test_2(); - no_regress_no_persist_test_3(); - some_regress_no_persist_test(); - some_decay_test(); - no_regress_full_persist_test(); - no_regress_some_persist_test(); - some_regress_some_persist_test(); - return 0; -} diff --git a/test/core/iomgr/time_averaged_stats_test.cc b/test/core/iomgr/time_averaged_stats_test.cc new file mode 100644 index 0000000000..508e3c5bf8 --- /dev/null +++ b/test/core/iomgr/time_averaged_stats_test.cc @@ -0,0 +1,193 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/time_averaged_stats.h" + +#include + +#include +#include "test/core/util/test_config.h" + +#define EXPECT_EQ(a, b) GPR_ASSERT((a) == (b)) +#define EXPECT_DOUBLE_EQ(a, b) GPR_ASSERT(fabs((a) - (b)) < 1e-9) + +static void no_regress_no_persist_test_1(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); + + /* Should have no effect */ + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); + + /* Should replace old average */ + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); +} + +static void no_regress_no_persist_test_2(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + /* Should replace init value */ + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 3000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); +} + +static void no_regress_no_persist_test_3(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0, 0.0); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + /* Should replace init value */ + grpc_time_averaged_stats_add_sample(&tas, 2500); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(2500, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 3500); + grpc_time_averaged_stats_add_sample(&tas, 4500); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(4000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); +} + +static void some_regress_no_persist_test(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0.5, 0.0); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + /* (2 * 2000 + 0.5 * 1000) / 2.5 */ + EXPECT_DOUBLE_EQ(1800, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2.5, tas.aggregate_total_weight); +} + +static void some_decay_test(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 1, 0.0); + EXPECT_EQ(1000, tas.aggregate_weighted_avg); + /* Should avg with init value */ + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(1500, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2, tas.aggregate_total_weight); +} + +static void no_regress_full_persist_test(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0, 1.0); + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(0, tas.aggregate_total_weight); + + /* Should replace init value */ + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_EQ(2000, tas.aggregate_weighted_avg); + EXPECT_EQ(1, tas.aggregate_total_weight); + + /* Will result in average of the 3 samples. */ + grpc_time_averaged_stats_add_sample(&tas, 2300); + grpc_time_averaged_stats_add_sample(&tas, 2300); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(2200, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(3, tas.aggregate_total_weight); +} + +static void no_regress_some_persist_test(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0, 0.5); + /* Should replace init value */ + grpc_time_averaged_stats_add_sample(&tas, 2000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 2500); + grpc_time_averaged_stats_add_sample(&tas, 4000); + grpc_time_averaged_stats_update_average(&tas); + EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2.5, tas.aggregate_total_weight); +} + +static void some_regress_some_persist_test(void) { + grpc_time_averaged_stats tas; + grpc_time_averaged_stats_init(&tas, 1000, 0.4, 0.6); + /* Sample weight = 0 */ + EXPECT_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_EQ(0, tas.aggregate_total_weight); + + grpc_time_averaged_stats_update_average(&tas); + /* (0.6 * 0 * 1000 + 0.4 * 1000 / 0.4) */ + EXPECT_DOUBLE_EQ(1000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(0.4, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 2640); + grpc_time_averaged_stats_update_average(&tas); + /* (1 * 2640 + 0.6 * 0.4 * 1000 + 0.4 * 1000 / (1 + 0.6 * 0.4 + 0.4) */ + EXPECT_DOUBLE_EQ(2000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(1.64, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 2876.8); + grpc_time_averaged_stats_update_average(&tas); + /* (1 * 2876.8 + 0.6 * 1.64 * 2000 + 0.4 * 1000 / (1 + 0.6 * 1.64 + 0.4) */ + EXPECT_DOUBLE_EQ(2200, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2.384, tas.aggregate_total_weight); + + grpc_time_averaged_stats_add_sample(&tas, 4944.32); + grpc_time_averaged_stats_update_average(&tas); + /* (1 * 4944.32 + 0.6 * 2.384 * 2200 + 0.4 * 1000) / + (1 + 0.6 * 2.384 + 0.4) */ + EXPECT_DOUBLE_EQ(3000, tas.aggregate_weighted_avg); + EXPECT_DOUBLE_EQ(2.8304, tas.aggregate_total_weight); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + no_regress_no_persist_test_1(); + no_regress_no_persist_test_2(); + no_regress_no_persist_test_3(); + some_regress_no_persist_test(); + some_decay_test(); + no_regress_full_persist_test(); + no_regress_some_persist_test(); + some_regress_some_persist_test(); + return 0; +} diff --git a/test/core/iomgr/timer_heap_test.c b/test/core/iomgr/timer_heap_test.c deleted file mode 100644 index ee5a474fd1..0000000000 --- a/test/core/iomgr/timer_heap_test.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test only works with the generic timer implementation -#ifdef GRPC_TIMER_USE_GENERIC - -#include "src/core/lib/iomgr/timer_heap.h" - -#include -#include - -#include -#include -#include - -#include "test/core/util/test_config.h" - -static gpr_atm random_deadline(void) { return rand(); } - -static grpc_timer *create_test_elements(size_t num_elements) { - grpc_timer *elems = gpr_malloc(num_elements * sizeof(grpc_timer)); - size_t i; - for (i = 0; i < num_elements; i++) { - elems[i].deadline = random_deadline(); - } - return elems; -} - -static int contains(grpc_timer_heap *pq, grpc_timer *el) { - size_t i; - for (i = 0; i < pq->timer_count; i++) { - if (pq->timers[i] == el) return 1; - } - return 0; -} - -static void check_valid(grpc_timer_heap *pq) { - size_t i; - for (i = 0; i < pq->timer_count; ++i) { - size_t left_child = 1u + 2u * i; - size_t right_child = left_child + 1u; - if (left_child < pq->timer_count) { - GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[left_child]->deadline); - } - if (right_child < pq->timer_count) { - GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[right_child]->deadline); - } - } -} - -/******************************************************************************* - * test1 - */ - -static void test1(void) { - grpc_timer_heap pq; - const size_t num_test_elements = 200; - const size_t num_test_operations = 10000; - size_t i; - grpc_timer *test_elements = create_test_elements(num_test_elements); - uint8_t *inpq = gpr_malloc(num_test_elements); - - gpr_log(GPR_INFO, "test1"); - - grpc_timer_heap_init(&pq); - memset(inpq, 0, num_test_elements); - GPR_ASSERT(grpc_timer_heap_is_empty(&pq)); - check_valid(&pq); - for (i = 0; i < num_test_elements; ++i) { - GPR_ASSERT(!contains(&pq, &test_elements[i])); - grpc_timer_heap_add(&pq, &test_elements[i]); - check_valid(&pq); - GPR_ASSERT(contains(&pq, &test_elements[i])); - inpq[i] = 1; - } - for (i = 0; i < num_test_elements; ++i) { - /* Test that check still succeeds even for element that wasn't just - inserted. */ - GPR_ASSERT(contains(&pq, &test_elements[i])); - } - - GPR_ASSERT(pq.timer_count == num_test_elements); - - check_valid(&pq); - - for (i = 0; i < num_test_operations; ++i) { - size_t elem_num = (size_t)rand() % num_test_elements; - grpc_timer *el = &test_elements[elem_num]; - if (!inpq[elem_num]) { /* not in pq */ - GPR_ASSERT(!contains(&pq, el)); - el->deadline = random_deadline(); - grpc_timer_heap_add(&pq, el); - GPR_ASSERT(contains(&pq, el)); - inpq[elem_num] = 1; - check_valid(&pq); - } else { - GPR_ASSERT(contains(&pq, el)); - grpc_timer_heap_remove(&pq, el); - GPR_ASSERT(!contains(&pq, el)); - inpq[elem_num] = 0; - check_valid(&pq); - } - } - - grpc_timer_heap_destroy(&pq); - gpr_free(test_elements); - gpr_free(inpq); -} - -/******************************************************************************* - * test2 - */ - -typedef struct { - grpc_timer elem; - bool inserted; -} elem_struct; - -static elem_struct *search_elems(elem_struct *elems, size_t count, - bool inserted) { - size_t *search_order = gpr_malloc(count * sizeof(*search_order)); - for (size_t i = 0; i < count; i++) { - search_order[i] = i; - } - for (size_t i = 0; i < count * 2; i++) { - size_t a = (size_t)rand() % count; - size_t b = (size_t)rand() % count; - GPR_SWAP(size_t, search_order[a], search_order[b]); - } - elem_struct *out = NULL; - for (size_t i = 0; out == NULL && i < count; i++) { - if (elems[search_order[i]].inserted == inserted) { - out = &elems[search_order[i]]; - } - } - gpr_free(search_order); - return out; -} - -static void test2(void) { - gpr_log(GPR_INFO, "test2"); - - grpc_timer_heap pq; - - static const size_t elems_size = 1000; - elem_struct *elems = gpr_malloc(elems_size * sizeof(elem_struct)); - size_t num_inserted = 0; - - grpc_timer_heap_init(&pq); - memset(elems, 0, elems_size); - - for (size_t round = 0; round < 10000; round++) { - int r = rand() % 1000; - if (r <= 550) { - /* 55% of the time we try to add something */ - elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), false); - if (el != NULL) { - el->elem.deadline = random_deadline(); - grpc_timer_heap_add(&pq, &el->elem); - el->inserted = true; - num_inserted++; - check_valid(&pq); - } - } else if (r <= 650) { - /* 10% of the time we try to remove something */ - elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), true); - if (el != NULL) { - grpc_timer_heap_remove(&pq, &el->elem); - el->inserted = false; - num_inserted--; - check_valid(&pq); - } - } else { - /* the remaining times we pop */ - if (num_inserted > 0) { - grpc_timer *top = grpc_timer_heap_top(&pq); - grpc_timer_heap_pop(&pq); - for (size_t i = 0; i < elems_size; i++) { - if (top == &elems[i].elem) { - GPR_ASSERT(elems[i].inserted); - elems[i].inserted = false; - } - } - num_inserted--; - check_valid(&pq); - } - } - - if (num_inserted) { - gpr_atm *min_deadline = NULL; - for (size_t i = 0; i < elems_size; i++) { - if (elems[i].inserted) { - if (min_deadline == NULL) { - min_deadline = &elems[i].elem.deadline; - } else { - if (elems[i].elem.deadline < *min_deadline) { - min_deadline = &elems[i].elem.deadline; - } - } - } - } - GPR_ASSERT(grpc_timer_heap_top(&pq)->deadline == *min_deadline); - } - } - - grpc_timer_heap_destroy(&pq); - gpr_free(elems); -} - -static void shrink_test(void) { - gpr_log(GPR_INFO, "shrink_test"); - - grpc_timer_heap pq; - size_t i; - size_t expected_size; - - /* A large random number to allow for multiple shrinkages, at least 512. */ - const size_t num_elements = (size_t)rand() % 2000 + 512; - - grpc_timer_heap_init(&pq); - - /* Create a priority queue with many elements. Make sure the Size() is - correct. */ - for (i = 0; i < num_elements; ++i) { - GPR_ASSERT(i == pq.timer_count); - grpc_timer_heap_add(&pq, create_test_elements(1)); - } - GPR_ASSERT(num_elements == pq.timer_count); - - /* Remove elements until the Size is 1/4 the original size. */ - while (pq.timer_count > num_elements / 4) { - grpc_timer *const te = pq.timers[pq.timer_count - 1]; - grpc_timer_heap_remove(&pq, te); - gpr_free(te); - } - GPR_ASSERT(num_elements / 4 == pq.timer_count); - - /* Expect that Capacity is in the right range: - Size * 2 <= Capacity <= Size * 4 */ - GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); - GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); - check_valid(&pq); - - /* Remove the rest of the elements. Check that the Capacity is not more than - 4 times the Size and not less than 2 times, but never goes below 16. */ - expected_size = pq.timer_count; - while (pq.timer_count > 0) { - const size_t which = (size_t)rand() % pq.timer_count; - grpc_timer *te = pq.timers[which]; - grpc_timer_heap_remove(&pq, te); - gpr_free(te); - expected_size--; - GPR_ASSERT(expected_size == pq.timer_count); - GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); - if (pq.timer_count >= 8) { - GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); - } else { - GPR_ASSERT(16 <= pq.timer_capacity); - } - check_valid(&pq); - } - - GPR_ASSERT(0 == pq.timer_count); - GPR_ASSERT(pq.timer_capacity >= 16 && pq.timer_capacity < 32); - - grpc_timer_heap_destroy(&pq); -} - -int main(int argc, char **argv) { - int i; - - grpc_test_init(argc, argv); - - for (i = 0; i < 5; i++) { - test1(); - test2(); - shrink_test(); - } - - return 0; -} - -#else /* GRPC_TIMER_USE_GENERIC */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_TIMER_USE_GENERIC */ diff --git a/test/core/iomgr/timer_heap_test.cc b/test/core/iomgr/timer_heap_test.cc new file mode 100644 index 0000000000..3eb25dd0be --- /dev/null +++ b/test/core/iomgr/timer_heap_test.cc @@ -0,0 +1,307 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test only works with the generic timer implementation +#ifdef GRPC_TIMER_USE_GENERIC + +#include "src/core/lib/iomgr/timer_heap.h" + +#include +#include + +#include +#include +#include + +#include "test/core/util/test_config.h" + +static gpr_atm random_deadline(void) { return rand(); } + +static grpc_timer *create_test_elements(size_t num_elements) { + grpc_timer *elems = + static_cast(gpr_malloc(num_elements * sizeof(grpc_timer))); + size_t i; + for (i = 0; i < num_elements; i++) { + elems[i].deadline = random_deadline(); + } + return elems; +} + +static int contains(grpc_timer_heap *pq, grpc_timer *el) { + size_t i; + for (i = 0; i < pq->timer_count; i++) { + if (pq->timers[i] == el) return 1; + } + return 0; +} + +static void check_valid(grpc_timer_heap *pq) { + size_t i; + for (i = 0; i < pq->timer_count; ++i) { + size_t left_child = 1u + 2u * i; + size_t right_child = left_child + 1u; + if (left_child < pq->timer_count) { + GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[left_child]->deadline); + } + if (right_child < pq->timer_count) { + GPR_ASSERT(pq->timers[i]->deadline <= pq->timers[right_child]->deadline); + } + } +} + +/******************************************************************************* + * test1 + */ + +static void test1(void) { + grpc_timer_heap pq; + const size_t num_test_elements = 200; + const size_t num_test_operations = 10000; + size_t i; + grpc_timer *test_elements = create_test_elements(num_test_elements); + uint8_t *inpq = static_cast(gpr_malloc(num_test_elements)); + + gpr_log(GPR_INFO, "test1"); + + grpc_timer_heap_init(&pq); + memset(inpq, 0, num_test_elements); + GPR_ASSERT(grpc_timer_heap_is_empty(&pq)); + check_valid(&pq); + for (i = 0; i < num_test_elements; ++i) { + GPR_ASSERT(!contains(&pq, &test_elements[i])); + grpc_timer_heap_add(&pq, &test_elements[i]); + check_valid(&pq); + GPR_ASSERT(contains(&pq, &test_elements[i])); + inpq[i] = 1; + } + for (i = 0; i < num_test_elements; ++i) { + /* Test that check still succeeds even for element that wasn't just + inserted. */ + GPR_ASSERT(contains(&pq, &test_elements[i])); + } + + GPR_ASSERT(pq.timer_count == num_test_elements); + + check_valid(&pq); + + for (i = 0; i < num_test_operations; ++i) { + size_t elem_num = (size_t)rand() % num_test_elements; + grpc_timer *el = &test_elements[elem_num]; + if (!inpq[elem_num]) { /* not in pq */ + GPR_ASSERT(!contains(&pq, el)); + el->deadline = random_deadline(); + grpc_timer_heap_add(&pq, el); + GPR_ASSERT(contains(&pq, el)); + inpq[elem_num] = 1; + check_valid(&pq); + } else { + GPR_ASSERT(contains(&pq, el)); + grpc_timer_heap_remove(&pq, el); + GPR_ASSERT(!contains(&pq, el)); + inpq[elem_num] = 0; + check_valid(&pq); + } + } + + grpc_timer_heap_destroy(&pq); + gpr_free(test_elements); + gpr_free(inpq); +} + +/******************************************************************************* + * test2 + */ + +typedef struct { + grpc_timer elem; + bool inserted; +} elem_struct; + +static elem_struct *search_elems(elem_struct *elems, size_t count, + bool inserted) { + size_t *search_order = + static_cast(gpr_malloc(count * sizeof(*search_order))); + for (size_t i = 0; i < count; i++) { + search_order[i] = i; + } + for (size_t i = 0; i < count * 2; i++) { + size_t a = (size_t)rand() % count; + size_t b = (size_t)rand() % count; + GPR_SWAP(size_t, search_order[a], search_order[b]); + } + elem_struct *out = NULL; + for (size_t i = 0; out == NULL && i < count; i++) { + if (elems[search_order[i]].inserted == inserted) { + out = &elems[search_order[i]]; + } + } + gpr_free(search_order); + return out; +} + +static void test2(void) { + gpr_log(GPR_INFO, "test2"); + + grpc_timer_heap pq; + + static const size_t elems_size = 1000; + elem_struct *elems = + static_cast(gpr_malloc(elems_size * sizeof(elem_struct))); + size_t num_inserted = 0; + + grpc_timer_heap_init(&pq); + memset(elems, 0, elems_size); + + for (size_t round = 0; round < 10000; round++) { + int r = rand() % 1000; + if (r <= 550) { + /* 55% of the time we try to add something */ + elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), false); + if (el != NULL) { + el->elem.deadline = random_deadline(); + grpc_timer_heap_add(&pq, &el->elem); + el->inserted = true; + num_inserted++; + check_valid(&pq); + } + } else if (r <= 650) { + /* 10% of the time we try to remove something */ + elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), true); + if (el != NULL) { + grpc_timer_heap_remove(&pq, &el->elem); + el->inserted = false; + num_inserted--; + check_valid(&pq); + } + } else { + /* the remaining times we pop */ + if (num_inserted > 0) { + grpc_timer *top = grpc_timer_heap_top(&pq); + grpc_timer_heap_pop(&pq); + for (size_t i = 0; i < elems_size; i++) { + if (top == &elems[i].elem) { + GPR_ASSERT(elems[i].inserted); + elems[i].inserted = false; + } + } + num_inserted--; + check_valid(&pq); + } + } + + if (num_inserted) { + gpr_atm *min_deadline = NULL; + for (size_t i = 0; i < elems_size; i++) { + if (elems[i].inserted) { + if (min_deadline == NULL) { + min_deadline = &elems[i].elem.deadline; + } else { + if (elems[i].elem.deadline < *min_deadline) { + min_deadline = &elems[i].elem.deadline; + } + } + } + } + GPR_ASSERT(grpc_timer_heap_top(&pq)->deadline == *min_deadline); + } + } + + grpc_timer_heap_destroy(&pq); + gpr_free(elems); +} + +static void shrink_test(void) { + gpr_log(GPR_INFO, "shrink_test"); + + grpc_timer_heap pq; + size_t i; + size_t expected_size; + + /* A large random number to allow for multiple shrinkages, at least 512. */ + const size_t num_elements = (size_t)rand() % 2000 + 512; + + grpc_timer_heap_init(&pq); + + /* Create a priority queue with many elements. Make sure the Size() is + correct. */ + for (i = 0; i < num_elements; ++i) { + GPR_ASSERT(i == pq.timer_count); + grpc_timer_heap_add(&pq, create_test_elements(1)); + } + GPR_ASSERT(num_elements == pq.timer_count); + + /* Remove elements until the Size is 1/4 the original size. */ + while (pq.timer_count > num_elements / 4) { + grpc_timer *const te = pq.timers[pq.timer_count - 1]; + grpc_timer_heap_remove(&pq, te); + gpr_free(te); + } + GPR_ASSERT(num_elements / 4 == pq.timer_count); + + /* Expect that Capacity is in the right range: + Size * 2 <= Capacity <= Size * 4 */ + GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); + GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); + check_valid(&pq); + + /* Remove the rest of the elements. Check that the Capacity is not more than + 4 times the Size and not less than 2 times, but never goes below 16. */ + expected_size = pq.timer_count; + while (pq.timer_count > 0) { + const size_t which = (size_t)rand() % pq.timer_count; + grpc_timer *te = pq.timers[which]; + grpc_timer_heap_remove(&pq, te); + gpr_free(te); + expected_size--; + GPR_ASSERT(expected_size == pq.timer_count); + GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); + if (pq.timer_count >= 8) { + GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); + } else { + GPR_ASSERT(16 <= pq.timer_capacity); + } + check_valid(&pq); + } + + GPR_ASSERT(0 == pq.timer_count); + GPR_ASSERT(pq.timer_capacity >= 16 && pq.timer_capacity < 32); + + grpc_timer_heap_destroy(&pq); +} + +int main(int argc, char **argv) { + int i; + + grpc_test_init(argc, argv); + + for (i = 0; i < 5; i++) { + test1(); + test2(); + shrink_test(); + } + + return 0; +} + +#else /* GRPC_TIMER_USE_GENERIC */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_TIMER_USE_GENERIC */ diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c deleted file mode 100644 index c3d9f9d88d..0000000000 --- a/test/core/iomgr/timer_list_test.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test only works with the generic timer implementation -#ifdef GRPC_TIMER_USE_GENERIC - -#include "src/core/lib/iomgr/timer.h" - -#include - -#include -#include "src/core/lib/debug/trace.h" -#include "test/core/util/test_config.h" - -#define MAX_CB 30 - -extern grpc_tracer_flag grpc_timer_trace; -extern grpc_tracer_flag grpc_timer_check_trace; - -static int cb_called[MAX_CB][2]; - -static void cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - cb_called[(intptr_t)arg][error == GRPC_ERROR_NONE]++; -} - -static void add_test(void) { - int i; - grpc_timer timers[20]; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "add_test"); - - grpc_timer_list_init(&exec_ctx); - grpc_timer_trace.value = 1; - grpc_timer_check_trace.value = 1; - memset(cb_called, 0, sizeof(cb_called)); - - grpc_millis start = grpc_exec_ctx_now(&exec_ctx); - - /* 10 ms timers. will expire in the current epoch */ - for (i = 0; i < 10; i++) { - grpc_timer_init(&exec_ctx, &timers[i], start + 10, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)i, - grpc_schedule_on_exec_ctx)); - } - - /* 1010 ms timers. will expire in the next epoch */ - for (i = 10; i < 20; i++) { - grpc_timer_init(&exec_ctx, &timers[i], start + 1010, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)i, - grpc_schedule_on_exec_ctx)); - } - - /* collect timers. Only the first batch should be ready. */ - exec_ctx.now = start + 500; - GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); - grpc_exec_ctx_finish(&exec_ctx); - for (i = 0; i < 20; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 10)); - GPR_ASSERT(cb_called[i][0] == 0); - } - - exec_ctx.now = start + 600; - GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == - GRPC_TIMERS_CHECKED_AND_EMPTY); - grpc_exec_ctx_finish(&exec_ctx); - for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 10)); - GPR_ASSERT(cb_called[i][0] == 0); - } - - /* collect the rest of the timers */ - exec_ctx.now = start + 1500; - GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); - grpc_exec_ctx_finish(&exec_ctx); - for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 20)); - GPR_ASSERT(cb_called[i][0] == 0); - } - - exec_ctx.now = start + 1600; - GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == - GRPC_TIMERS_CHECKED_AND_EMPTY); - for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 20)); - GPR_ASSERT(cb_called[i][0] == 0); - } - - grpc_timer_list_shutdown(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); -} - -/* Cleaning up a list with pending timers. */ -void destruction_test(void) { - grpc_timer timers[5]; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "destruction_test"); - - exec_ctx.now_is_valid = true; - exec_ctx.now = 0; - grpc_timer_list_init(&exec_ctx); - grpc_timer_trace.value = 1; - grpc_timer_check_trace.value = 1; - memset(cb_called, 0, sizeof(cb_called)); - - grpc_timer_init( - &exec_ctx, &timers[0], 100, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)0, grpc_schedule_on_exec_ctx)); - grpc_timer_init( - &exec_ctx, &timers[1], 3, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)1, grpc_schedule_on_exec_ctx)); - grpc_timer_init( - &exec_ctx, &timers[2], 100, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)2, grpc_schedule_on_exec_ctx)); - grpc_timer_init( - &exec_ctx, &timers[3], 3, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)3, grpc_schedule_on_exec_ctx)); - grpc_timer_init( - &exec_ctx, &timers[4], 1, - GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)4, grpc_schedule_on_exec_ctx)); - exec_ctx.now = 2; - GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(1 == cb_called[4][1]); - grpc_timer_cancel(&exec_ctx, &timers[0]); - grpc_timer_cancel(&exec_ctx, &timers[3]); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(1 == cb_called[0][0]); - GPR_ASSERT(1 == cb_called[3][0]); - - grpc_timer_list_shutdown(&exec_ctx); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(1 == cb_called[1][0]); - GPR_ASSERT(1 == cb_called[2][0]); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); - add_test(); - destruction_test(); - return 0; -} - -#else /* GRPC_TIMER_USE_GENERIC */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_TIMER_USE_GENERIC */ diff --git a/test/core/iomgr/timer_list_test.cc b/test/core/iomgr/timer_list_test.cc new file mode 100644 index 0000000000..c3d9f9d88d --- /dev/null +++ b/test/core/iomgr/timer_list_test.cc @@ -0,0 +1,167 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test only works with the generic timer implementation +#ifdef GRPC_TIMER_USE_GENERIC + +#include "src/core/lib/iomgr/timer.h" + +#include + +#include +#include "src/core/lib/debug/trace.h" +#include "test/core/util/test_config.h" + +#define MAX_CB 30 + +extern grpc_tracer_flag grpc_timer_trace; +extern grpc_tracer_flag grpc_timer_check_trace; + +static int cb_called[MAX_CB][2]; + +static void cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + cb_called[(intptr_t)arg][error == GRPC_ERROR_NONE]++; +} + +static void add_test(void) { + int i; + grpc_timer timers[20]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "add_test"); + + grpc_timer_list_init(&exec_ctx); + grpc_timer_trace.value = 1; + grpc_timer_check_trace.value = 1; + memset(cb_called, 0, sizeof(cb_called)); + + grpc_millis start = grpc_exec_ctx_now(&exec_ctx); + + /* 10 ms timers. will expire in the current epoch */ + for (i = 0; i < 10; i++) { + grpc_timer_init(&exec_ctx, &timers[i], start + 10, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)i, + grpc_schedule_on_exec_ctx)); + } + + /* 1010 ms timers. will expire in the next epoch */ + for (i = 10; i < 20; i++) { + grpc_timer_init(&exec_ctx, &timers[i], start + 1010, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)i, + grpc_schedule_on_exec_ctx)); + } + + /* collect timers. Only the first batch should be ready. */ + exec_ctx.now = start + 500; + GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); + grpc_exec_ctx_finish(&exec_ctx); + for (i = 0; i < 20; i++) { + GPR_ASSERT(cb_called[i][1] == (i < 10)); + GPR_ASSERT(cb_called[i][0] == 0); + } + + exec_ctx.now = start + 600; + GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == + GRPC_TIMERS_CHECKED_AND_EMPTY); + grpc_exec_ctx_finish(&exec_ctx); + for (i = 0; i < 30; i++) { + GPR_ASSERT(cb_called[i][1] == (i < 10)); + GPR_ASSERT(cb_called[i][0] == 0); + } + + /* collect the rest of the timers */ + exec_ctx.now = start + 1500; + GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); + grpc_exec_ctx_finish(&exec_ctx); + for (i = 0; i < 30; i++) { + GPR_ASSERT(cb_called[i][1] == (i < 20)); + GPR_ASSERT(cb_called[i][0] == 0); + } + + exec_ctx.now = start + 1600; + GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == + GRPC_TIMERS_CHECKED_AND_EMPTY); + for (i = 0; i < 30; i++) { + GPR_ASSERT(cb_called[i][1] == (i < 20)); + GPR_ASSERT(cb_called[i][0] == 0); + } + + grpc_timer_list_shutdown(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); +} + +/* Cleaning up a list with pending timers. */ +void destruction_test(void) { + grpc_timer timers[5]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "destruction_test"); + + exec_ctx.now_is_valid = true; + exec_ctx.now = 0; + grpc_timer_list_init(&exec_ctx); + grpc_timer_trace.value = 1; + grpc_timer_check_trace.value = 1; + memset(cb_called, 0, sizeof(cb_called)); + + grpc_timer_init( + &exec_ctx, &timers[0], 100, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)0, grpc_schedule_on_exec_ctx)); + grpc_timer_init( + &exec_ctx, &timers[1], 3, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)1, grpc_schedule_on_exec_ctx)); + grpc_timer_init( + &exec_ctx, &timers[2], 100, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)2, grpc_schedule_on_exec_ctx)); + grpc_timer_init( + &exec_ctx, &timers[3], 3, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)3, grpc_schedule_on_exec_ctx)); + grpc_timer_init( + &exec_ctx, &timers[4], 1, + GRPC_CLOSURE_CREATE(cb, (void *)(intptr_t)4, grpc_schedule_on_exec_ctx)); + exec_ctx.now = 2; + GPR_ASSERT(grpc_timer_check(&exec_ctx, NULL) == GRPC_TIMERS_FIRED); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(1 == cb_called[4][1]); + grpc_timer_cancel(&exec_ctx, &timers[0]); + grpc_timer_cancel(&exec_ctx, &timers[3]); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(1 == cb_called[0][0]); + GPR_ASSERT(1 == cb_called[3][0]); + + grpc_timer_list_shutdown(&exec_ctx); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(1 == cb_called[1][0]); + GPR_ASSERT(1 == cb_called[2][0]); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); + add_test(); + destruction_test(); + return 0; +} + +#else /* GRPC_TIMER_USE_GENERIC */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_TIMER_USE_GENERIC */ diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c deleted file mode 100644 index 2e44d0abc8..0000000000 --- a/test/core/iomgr/udp_server_test.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include "src/core/lib/iomgr/udp_server.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/socket_factory_posix.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) - -static grpc_pollset *g_pollset; -static gpr_mu *g_mu; -static int g_number_of_reads = 0; -static int g_number_of_writes = 0; -static int g_number_of_bytes_read = 0; -static int g_number_of_orphan_calls = 0; - -static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) { - char read_buffer[512]; - ssize_t byte_count; - - gpr_mu_lock(g_mu); - byte_count = - recv(grpc_fd_wrapped_fd(emfd), read_buffer, sizeof(read_buffer), 0); - - g_number_of_reads++; - g_number_of_bytes_read += (int)byte_count; - - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) { - gpr_mu_lock(g_mu); - g_number_of_writes++; - - GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, g_pollset, NULL))); - gpr_mu_unlock(g_mu); -} - -static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, - grpc_closure *closure, void *user_data) { - gpr_log(GPR_INFO, "gRPC FD about to be orphaned: %d", - grpc_fd_wrapped_fd(emfd)); - g_number_of_orphan_calls++; -} - -struct test_socket_factory { - grpc_socket_factory base; - int number_of_socket_calls; - int number_of_bind_calls; -}; -typedef struct test_socket_factory test_socket_factory; - -static int test_socket_factory_socket(grpc_socket_factory *factory, int domain, - int type, int protocol) { - test_socket_factory *f = (test_socket_factory *)factory; - f->number_of_socket_calls++; - return socket(domain, type, protocol); -} - -static int test_socket_factory_bind(grpc_socket_factory *factory, int sockfd, - const grpc_resolved_address *addr) { - test_socket_factory *f = (test_socket_factory *)factory; - f->number_of_bind_calls++; - return bind(sockfd, (struct sockaddr *)addr->addr, (socklen_t)addr->len); -} - -static int test_socket_factory_compare(grpc_socket_factory *a, - grpc_socket_factory *b) { - return GPR_ICMP(a, b); -} - -static void test_socket_factory_destroy(grpc_socket_factory *factory) { - test_socket_factory *f = (test_socket_factory *)factory; - gpr_free(f); -} - -static const grpc_socket_factory_vtable test_socket_factory_vtable = { - test_socket_factory_socket, test_socket_factory_bind, - test_socket_factory_compare, test_socket_factory_destroy}; - -static test_socket_factory *test_socket_factory_create(void) { - test_socket_factory *factory = gpr_malloc(sizeof(test_socket_factory)); - grpc_socket_factory_init(&factory->base, &test_socket_factory_vtable); - factory->number_of_socket_calls = 0; - factory->number_of_bind_calls = 0; - return factory; -} - -static void test_no_op(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_udp_server *s = grpc_udp_server_create(NULL); - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_start(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_udp_server *s = grpc_udp_server_create(NULL); - LOG_TEST("test_no_op_with_start"); - grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL); - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_no_op_with_port(void) { - g_number_of_orphan_calls = 0; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_udp_server *s = grpc_udp_server_create(NULL); - LOG_TEST("test_no_op_with_port"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, - on_fd_orphaned)); - - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); - - /* The server had a single FD, which should have been orphaned. */ - GPR_ASSERT(g_number_of_orphan_calls == 1); -} - -static void test_no_op_with_port_and_socket_factory(void) { - g_number_of_orphan_calls = 0; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - - test_socket_factory *socket_factory = test_socket_factory_create(); - grpc_arg socket_factory_arg = - grpc_socket_factory_to_arg(&socket_factory->base); - grpc_channel_args *channel_args = - grpc_channel_args_copy_and_add(NULL, &socket_factory_arg, 1); - grpc_udp_server *s = grpc_udp_server_create(channel_args); - grpc_channel_args_destroy(&exec_ctx, channel_args); - - LOG_TEST("test_no_op_with_port_and_socket_factory"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, - on_fd_orphaned)); - GPR_ASSERT(socket_factory->number_of_socket_calls == 1); - GPR_ASSERT(socket_factory->number_of_bind_calls == 1); - - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); - grpc_socket_factory_unref(&socket_factory->base); - - /* The server had a single FD, which should have been orphaned. */ - GPR_ASSERT(g_number_of_orphan_calls == 1); -} - -static void test_no_op_with_port_and_start(void) { - g_number_of_orphan_calls = 0; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - grpc_udp_server *s = grpc_udp_server_create(NULL); - LOG_TEST("test_no_op_with_port_and_start"); - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, - on_fd_orphaned)); - - grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL); - - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); - - /* The server had a single FD, which is orphaned exactly once in * - * grpc_udp_server_destroy. */ - GPR_ASSERT(g_number_of_orphan_calls == 1); -} - -static void test_receive(int number_of_clients) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; - int clifd, svrfd; - grpc_udp_server *s = grpc_udp_server_create(NULL); - int i; - int number_of_reads_before; - grpc_millis deadline; - grpc_pollset *pollsets[1]; - LOG_TEST("test_receive"); - gpr_log(GPR_INFO, "clients=%d", number_of_clients); - - g_number_of_bytes_read = 0; - g_number_of_orphan_calls = 0; - - memset(&resolved_addr, 0, sizeof(resolved_addr)); - resolved_addr.len = sizeof(struct sockaddr_storage); - addr->ss_family = AF_INET; - GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, - on_fd_orphaned)); - - svrfd = grpc_udp_server_get_fd(s, 0); - GPR_ASSERT(svrfd >= 0); - GPR_ASSERT(getsockname(svrfd, (struct sockaddr *)addr, - (socklen_t *)&resolved_addr.len) == 0); - GPR_ASSERT(resolved_addr.len <= sizeof(struct sockaddr_storage)); - - pollsets[0] = g_pollset; - grpc_udp_server_start(&exec_ctx, s, pollsets, 1, NULL); - - gpr_mu_lock(g_mu); - - for (i = 0; i < number_of_clients; i++) { - deadline = - grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); - - number_of_reads_before = g_number_of_reads; - /* Create a socket, send a packet to the UDP server. */ - clifd = socket(addr->ss_family, SOCK_DGRAM, 0); - GPR_ASSERT(clifd >= 0); - GPR_ASSERT(connect(clifd, (struct sockaddr *)addr, - (socklen_t)resolved_addr.len) == 0); - GPR_ASSERT(5 == write(clifd, "hello", 5)); - while (g_number_of_reads == number_of_reads_before && - deadline > grpc_exec_ctx_now(&exec_ctx)) { - grpc_pollset_worker *worker = NULL; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); - gpr_mu_unlock(g_mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(g_mu); - } - GPR_ASSERT(g_number_of_reads == number_of_reads_before + 1); - close(clifd); - } - GPR_ASSERT(g_number_of_bytes_read == 5 * number_of_clients); - - gpr_mu_unlock(g_mu); - - grpc_udp_server_destroy(&exec_ctx, s, NULL); - grpc_exec_ctx_finish(&exec_ctx); - - /* The server had a single FD, which is orphaned exactly once in * - * grpc_udp_server_destroy. */ - GPR_ASSERT(g_number_of_orphan_calls == 1); - - /* The write callback should have fired a few times. */ - GPR_ASSERT(g_number_of_writes > 0); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - grpc_init(); - g_pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - - test_no_op(); - test_no_op_with_start(); - test_no_op_with_port(); - test_no_op_with_port_and_socket_factory(); - test_no_op_with_port_and_start(); - test_receive(1); - test_receive(10); - - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(g_pollset); - grpc_shutdown(); - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc new file mode 100644 index 0000000000..51c7ab8c29 --- /dev/null +++ b/test/core/iomgr/udp_server_test.cc @@ -0,0 +1,328 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/udp_server.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/socket_factory_posix.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) + +static grpc_pollset *g_pollset; +static gpr_mu *g_mu; +static int g_number_of_reads = 0; +static int g_number_of_writes = 0; +static int g_number_of_bytes_read = 0; +static int g_number_of_orphan_calls = 0; + +static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) { + char read_buffer[512]; + ssize_t byte_count; + + gpr_mu_lock(g_mu); + byte_count = + recv(grpc_fd_wrapped_fd(emfd), read_buffer, sizeof(read_buffer), 0); + + g_number_of_reads++; + g_number_of_bytes_read += (int)byte_count; + + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) { + gpr_mu_lock(g_mu); + g_number_of_writes++; + + GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, g_pollset, NULL))); + gpr_mu_unlock(g_mu); +} + +static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, + grpc_closure *closure, void *user_data) { + gpr_log(GPR_INFO, "gRPC FD about to be orphaned: %d", + grpc_fd_wrapped_fd(emfd)); + g_number_of_orphan_calls++; +} + +struct test_socket_factory { + grpc_socket_factory base; + int number_of_socket_calls; + int number_of_bind_calls; +}; +typedef struct test_socket_factory test_socket_factory; + +static int test_socket_factory_socket(grpc_socket_factory *factory, int domain, + int type, int protocol) { + test_socket_factory *f = (test_socket_factory *)factory; + f->number_of_socket_calls++; + return socket(domain, type, protocol); +} + +static int test_socket_factory_bind(grpc_socket_factory *factory, int sockfd, + const grpc_resolved_address *addr) { + test_socket_factory *f = (test_socket_factory *)factory; + f->number_of_bind_calls++; + return bind(sockfd, (struct sockaddr *)addr->addr, (socklen_t)addr->len); +} + +static int test_socket_factory_compare(grpc_socket_factory *a, + grpc_socket_factory *b) { + return GPR_ICMP(a, b); +} + +static void test_socket_factory_destroy(grpc_socket_factory *factory) { + test_socket_factory *f = (test_socket_factory *)factory; + gpr_free(f); +} + +static const grpc_socket_factory_vtable test_socket_factory_vtable = { + test_socket_factory_socket, test_socket_factory_bind, + test_socket_factory_compare, test_socket_factory_destroy}; + +static test_socket_factory *test_socket_factory_create(void) { + test_socket_factory *factory = static_cast( + gpr_malloc(sizeof(test_socket_factory))); + grpc_socket_factory_init(&factory->base, &test_socket_factory_vtable); + factory->number_of_socket_calls = 0; + factory->number_of_bind_calls = 0; + return factory; +} + +static void test_no_op(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_udp_server *s = grpc_udp_server_create(NULL); + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_start(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_udp_server *s = grpc_udp_server_create(NULL); + LOG_TEST("test_no_op_with_start"); + grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL); + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_no_op_with_port(void) { + g_number_of_orphan_calls = 0; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_udp_server *s = grpc_udp_server_create(NULL); + LOG_TEST("test_no_op_with_port"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, + on_fd_orphaned)); + + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); + + /* The server had a single FD, which should have been orphaned. */ + GPR_ASSERT(g_number_of_orphan_calls == 1); +} + +static void test_no_op_with_port_and_socket_factory(void) { + g_number_of_orphan_calls = 0; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + + test_socket_factory *socket_factory = test_socket_factory_create(); + grpc_arg socket_factory_arg = + grpc_socket_factory_to_arg(&socket_factory->base); + grpc_channel_args *channel_args = + grpc_channel_args_copy_and_add(NULL, &socket_factory_arg, 1); + grpc_udp_server *s = grpc_udp_server_create(channel_args); + grpc_channel_args_destroy(&exec_ctx, channel_args); + + LOG_TEST("test_no_op_with_port_and_socket_factory"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, + on_fd_orphaned)); + GPR_ASSERT(socket_factory->number_of_socket_calls == 1); + GPR_ASSERT(socket_factory->number_of_bind_calls == 1); + + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); + grpc_socket_factory_unref(&socket_factory->base); + + /* The server had a single FD, which should have been orphaned. */ + GPR_ASSERT(g_number_of_orphan_calls == 1); +} + +static void test_no_op_with_port_and_start(void) { + g_number_of_orphan_calls = 0; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + grpc_udp_server *s = grpc_udp_server_create(NULL); + LOG_TEST("test_no_op_with_port_and_start"); + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, + on_fd_orphaned)); + + grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL); + + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); + + /* The server had a single FD, which is orphaned exactly once in * + * grpc_udp_server_destroy. */ + GPR_ASSERT(g_number_of_orphan_calls == 1); +} + +static void test_receive(int number_of_clients) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; + int clifd, svrfd; + grpc_udp_server *s = grpc_udp_server_create(NULL); + int i; + int number_of_reads_before; + grpc_millis deadline; + grpc_pollset *pollsets[1]; + LOG_TEST("test_receive"); + gpr_log(GPR_INFO, "clients=%d", number_of_clients); + + g_number_of_bytes_read = 0; + g_number_of_orphan_calls = 0; + + memset(&resolved_addr, 0, sizeof(resolved_addr)); + resolved_addr.len = sizeof(struct sockaddr_storage); + addr->ss_family = AF_INET; + GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write, + on_fd_orphaned)); + + svrfd = grpc_udp_server_get_fd(s, 0); + GPR_ASSERT(svrfd >= 0); + GPR_ASSERT(getsockname(svrfd, (struct sockaddr *)addr, + (socklen_t *)&resolved_addr.len) == 0); + GPR_ASSERT(resolved_addr.len <= sizeof(struct sockaddr_storage)); + + pollsets[0] = g_pollset; + grpc_udp_server_start(&exec_ctx, s, pollsets, 1, NULL); + + gpr_mu_lock(g_mu); + + for (i = 0; i < number_of_clients; i++) { + deadline = + grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); + + number_of_reads_before = g_number_of_reads; + /* Create a socket, send a packet to the UDP server. */ + clifd = socket(addr->ss_family, SOCK_DGRAM, 0); + GPR_ASSERT(clifd >= 0); + GPR_ASSERT(connect(clifd, (struct sockaddr *)addr, + (socklen_t)resolved_addr.len) == 0); + GPR_ASSERT(5 == write(clifd, "hello", 5)); + while (g_number_of_reads == number_of_reads_before && + deadline > grpc_exec_ctx_now(&exec_ctx)) { + grpc_pollset_worker *worker = NULL; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, g_pollset, &worker, deadline))); + gpr_mu_unlock(g_mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(g_mu); + } + GPR_ASSERT(g_number_of_reads == number_of_reads_before + 1); + close(clifd); + } + GPR_ASSERT(g_number_of_bytes_read == 5 * number_of_clients); + + gpr_mu_unlock(g_mu); + + grpc_udp_server_destroy(&exec_ctx, s, NULL); + grpc_exec_ctx_finish(&exec_ctx); + + /* The server had a single FD, which is orphaned exactly once in * + * grpc_udp_server_destroy. */ + GPR_ASSERT(g_number_of_orphan_calls == 1); + + /* The write callback should have fired a few times. */ + GPR_ASSERT(g_number_of_writes > 0); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(p)); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + grpc_init(); + g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(g_pollset, &g_mu); + + test_no_op(); + test_no_op_with_start(); + test_no_op_with_port(); + test_no_op_with_port_and_socket_factory(); + test_no_op_with_port_and_start(); + test_receive(1); + test_receive(10); + + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(g_pollset); + grpc_shutdown(); + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/wakeup_fd_cv_test.c b/test/core/iomgr/wakeup_fd_cv_test.c deleted file mode 100644 index 0b211274f2..0000000000 --- a/test/core/iomgr/wakeup_fd_cv_test.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -#ifdef GRPC_POSIX_SOCKET - -#include - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/iomgr_posix.h" -#include "src/core/lib/support/env.h" - -typedef struct poll_args { - struct pollfd *fds; - nfds_t nfds; - int timeout; - int result; -} poll_args; - -gpr_cv poll_cv; -gpr_mu poll_mu; -static int socket_event = 0; - -// Trigger a "socket" POLLIN in mock_poll() -void trigger_socket_event() { - gpr_mu_lock(&poll_mu); - socket_event = 1; - gpr_cv_broadcast(&poll_cv); - gpr_mu_unlock(&poll_mu); -} - -void reset_socket_event() { - gpr_mu_lock(&poll_mu); - socket_event = 0; - gpr_mu_unlock(&poll_mu); -} - -// Mocks posix poll() function -int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) { - int res = 0; - gpr_timespec poll_time; - gpr_mu_lock(&poll_mu); - GPR_ASSERT(nfds == 3); - GPR_ASSERT(fds[0].fd == 20); - GPR_ASSERT(fds[1].fd == 30); - GPR_ASSERT(fds[2].fd == 50); - GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP)); - GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP)); - GPR_ASSERT(fds[2].events == POLLIN); - - if (timeout < 0) { - poll_time = gpr_inf_future(GPR_CLOCK_REALTIME); - } else { - poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis(timeout, GPR_TIMESPAN)); - } - - if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) { - fds[0].revents = POLLIN; - res = 1; - } - gpr_mu_unlock(&poll_mu); - return res; -} - -void background_poll(void *args) { - poll_args *pargs = (poll_args *)args; - pargs->result = grpc_poll_function(pargs->fds, pargs->nfds, pargs->timeout); -} - -void test_many_fds(void) { - int i; - grpc_wakeup_fd fd[1000]; - for (i = 0; i < 1000; i++) { - GPR_ASSERT(grpc_wakeup_fd_init(&fd[i]) == GRPC_ERROR_NONE); - } - for (i = 0; i < 1000; i++) { - grpc_wakeup_fd_destroy(&fd[i]); - } -} - -void test_poll_cv_trigger(void) { - grpc_wakeup_fd cvfd1, cvfd2, cvfd3; - struct pollfd pfds[6]; - poll_args pargs; - gpr_thd_id t_id; - gpr_thd_options opt; - - GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE); - GPR_ASSERT(cvfd1.read_fd < 0); - GPR_ASSERT(cvfd2.read_fd < 0); - GPR_ASSERT(cvfd3.read_fd < 0); - GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd); - GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd); - GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd); - - pfds[0].fd = cvfd1.read_fd; - pfds[1].fd = cvfd2.read_fd; - pfds[2].fd = 20; - pfds[3].fd = 30; - pfds[4].fd = cvfd3.read_fd; - pfds[5].fd = 50; - - pfds[0].events = 0; - pfds[1].events = POLLIN; - pfds[2].events = POLLIN | POLLHUP; - pfds[3].events = POLLIN | POLLHUP; - pfds[4].events = POLLIN; - pfds[5].events = POLLIN; - - pargs.fds = pfds; - pargs.nfds = 6; - pargs.timeout = 1000; - pargs.result = -2; - - opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - gpr_thd_new(&t_id, &background_poll, &pargs, &opt); - - // Wakeup wakeup_fd not listening for events - GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE); - gpr_thd_join(t_id); - GPR_ASSERT(pargs.result == 0); - GPR_ASSERT(pfds[0].revents == 0); - GPR_ASSERT(pfds[1].revents == 0); - GPR_ASSERT(pfds[2].revents == 0); - GPR_ASSERT(pfds[3].revents == 0); - GPR_ASSERT(pfds[4].revents == 0); - GPR_ASSERT(pfds[5].revents == 0); - - // Pollin on socket fd - pargs.timeout = -1; - pargs.result = -2; - gpr_thd_new(&t_id, &background_poll, &pargs, &opt); - trigger_socket_event(); - gpr_thd_join(t_id); - GPR_ASSERT(pargs.result == 1); - GPR_ASSERT(pfds[0].revents == 0); - GPR_ASSERT(pfds[1].revents == 0); - GPR_ASSERT(pfds[2].revents == POLLIN); - GPR_ASSERT(pfds[3].revents == 0); - GPR_ASSERT(pfds[4].revents == 0); - GPR_ASSERT(pfds[5].revents == 0); - - // Pollin on wakeup fd - reset_socket_event(); - pargs.result = -2; - gpr_thd_new(&t_id, &background_poll, &pargs, &opt); - GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE); - gpr_thd_join(t_id); - - GPR_ASSERT(pargs.result == 1); - GPR_ASSERT(pfds[0].revents == 0); - GPR_ASSERT(pfds[1].revents == POLLIN); - GPR_ASSERT(pfds[2].revents == 0); - GPR_ASSERT(pfds[3].revents == 0); - GPR_ASSERT(pfds[4].revents == 0); - GPR_ASSERT(pfds[5].revents == 0); - - // Pollin on wakeupfd before poll() - pargs.result = -2; - gpr_thd_new(&t_id, &background_poll, &pargs, &opt); - gpr_thd_join(t_id); - - GPR_ASSERT(pargs.result == 1); - GPR_ASSERT(pfds[0].revents == 0); - GPR_ASSERT(pfds[1].revents == POLLIN); - GPR_ASSERT(pfds[2].revents == 0); - GPR_ASSERT(pfds[3].revents == 0); - GPR_ASSERT(pfds[4].revents == 0); - GPR_ASSERT(pfds[5].revents == 0); - - // No Events - pargs.result = -2; - pargs.timeout = 1000; - reset_socket_event(); - GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE); - gpr_thd_new(&t_id, &background_poll, &pargs, &opt); - gpr_thd_join(t_id); - - GPR_ASSERT(pargs.result == 0); - GPR_ASSERT(pfds[0].revents == 0); - GPR_ASSERT(pfds[1].revents == 0); - GPR_ASSERT(pfds[2].revents == 0); - GPR_ASSERT(pfds[3].revents == 0); - GPR_ASSERT(pfds[4].revents == 0); - GPR_ASSERT(pfds[5].revents == 0); -} - -int main(int argc, char **argv) { - gpr_setenv("GRPC_POLL_STRATEGY", "poll-cv"); - grpc_poll_function = &mock_poll; - gpr_mu_init(&poll_mu); - gpr_cv_init(&poll_cv); - - grpc_iomgr_platform_init(); - test_many_fds(); - grpc_iomgr_platform_shutdown(); - - grpc_iomgr_platform_init(); - test_poll_cv_trigger(); - grpc_iomgr_platform_shutdown(); - return 0; -} - -#else /* GRPC_POSIX_SOCKET */ - -int main(int argc, char **argv) { return 1; } - -#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/iomgr/wakeup_fd_cv_test.cc b/test/core/iomgr/wakeup_fd_cv_test.cc new file mode 100644 index 0000000000..0b211274f2 --- /dev/null +++ b/test/core/iomgr/wakeup_fd_cv_test.cc @@ -0,0 +1,234 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_POSIX_SOCKET + +#include + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_posix.h" +#include "src/core/lib/support/env.h" + +typedef struct poll_args { + struct pollfd *fds; + nfds_t nfds; + int timeout; + int result; +} poll_args; + +gpr_cv poll_cv; +gpr_mu poll_mu; +static int socket_event = 0; + +// Trigger a "socket" POLLIN in mock_poll() +void trigger_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 1; + gpr_cv_broadcast(&poll_cv); + gpr_mu_unlock(&poll_mu); +} + +void reset_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 0; + gpr_mu_unlock(&poll_mu); +} + +// Mocks posix poll() function +int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) { + int res = 0; + gpr_timespec poll_time; + gpr_mu_lock(&poll_mu); + GPR_ASSERT(nfds == 3); + GPR_ASSERT(fds[0].fd == 20); + GPR_ASSERT(fds[1].fd == 30); + GPR_ASSERT(fds[2].fd == 50); + GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[2].events == POLLIN); + + if (timeout < 0) { + poll_time = gpr_inf_future(GPR_CLOCK_REALTIME); + } else { + poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(timeout, GPR_TIMESPAN)); + } + + if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) { + fds[0].revents = POLLIN; + res = 1; + } + gpr_mu_unlock(&poll_mu); + return res; +} + +void background_poll(void *args) { + poll_args *pargs = (poll_args *)args; + pargs->result = grpc_poll_function(pargs->fds, pargs->nfds, pargs->timeout); +} + +void test_many_fds(void) { + int i; + grpc_wakeup_fd fd[1000]; + for (i = 0; i < 1000; i++) { + GPR_ASSERT(grpc_wakeup_fd_init(&fd[i]) == GRPC_ERROR_NONE); + } + for (i = 0; i < 1000; i++) { + grpc_wakeup_fd_destroy(&fd[i]); + } +} + +void test_poll_cv_trigger(void) { + grpc_wakeup_fd cvfd1, cvfd2, cvfd3; + struct pollfd pfds[6]; + poll_args pargs; + gpr_thd_id t_id; + gpr_thd_options opt; + + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE); + GPR_ASSERT(cvfd1.read_fd < 0); + GPR_ASSERT(cvfd2.read_fd < 0); + GPR_ASSERT(cvfd3.read_fd < 0); + GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd); + GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd); + GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd); + + pfds[0].fd = cvfd1.read_fd; + pfds[1].fd = cvfd2.read_fd; + pfds[2].fd = 20; + pfds[3].fd = 30; + pfds[4].fd = cvfd3.read_fd; + pfds[5].fd = 50; + + pfds[0].events = 0; + pfds[1].events = POLLIN; + pfds[2].events = POLLIN | POLLHUP; + pfds[3].events = POLLIN | POLLHUP; + pfds[4].events = POLLIN; + pfds[5].events = POLLIN; + + pargs.fds = pfds; + pargs.nfds = 6; + pargs.timeout = 1000; + pargs.result = -2; + + opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + + // Wakeup wakeup_fd not listening for events + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on socket fd + pargs.timeout = -1; + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + trigger_socket_event(); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == POLLIN); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeup fd + reset_socket_event(); + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeupfd before poll() + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // No Events + pargs.result = -2; + pargs.timeout = 1000; + reset_socket_event(); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); +} + +int main(int argc, char **argv) { + gpr_setenv("GRPC_POLL_STRATEGY", "poll-cv"); + grpc_poll_function = &mock_poll; + gpr_mu_init(&poll_mu); + gpr_cv_init(&poll_cv); + + grpc_iomgr_platform_init(); + test_many_fds(); + grpc_iomgr_platform_shutdown(); + + grpc_iomgr_platform_init(); + test_poll_cv_trigger(); + grpc_iomgr_platform_shutdown(); + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char **argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/test/core/json/fuzzer.c b/test/core/json/fuzzer.c deleted file mode 100644 index b825904d41..0000000000 --- a/test/core/json/fuzzer.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include - -#include "src/core/lib/json/json.h" -#include "test/core/util/memory_counters.h" - -bool squelch = true; -bool leak_check = true; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - char *s; - struct grpc_memory_counters counters; - grpc_memory_counters_init(); - s = gpr_malloc(size); - memcpy(s, data, size); - grpc_json *x; - if ((x = grpc_json_parse_string_with_len(s, size))) { - grpc_json_destroy(x); - } - gpr_free(s); - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); - return 0; -} diff --git a/test/core/json/fuzzer.cc b/test/core/json/fuzzer.cc new file mode 100644 index 0000000000..a8b75f72a2 --- /dev/null +++ b/test/core/json/fuzzer.cc @@ -0,0 +1,47 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include + +#include "src/core/lib/json/json.h" +#include "test/core/util/memory_counters.h" + +bool squelch = true; +bool leak_check = true; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + char *s; + struct grpc_memory_counters counters; + grpc_memory_counters_init(); + s = static_cast(gpr_malloc(size)); + memcpy(s, data, size); + grpc_json *x; + if ((x = grpc_json_parse_string_with_len(s, size))) { + grpc_json_destroy(x); + } + gpr_free(s); + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); + return 0; +} diff --git a/test/core/json/json_rewrite.c b/test/core/json/json_rewrite.c deleted file mode 100644 index dfe32f5adf..0000000000 --- a/test/core/json/json_rewrite.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include - -#include "src/core/lib/json/json_reader.h" -#include "src/core/lib/json/json_writer.h" - -typedef struct json_writer_userdata { FILE *out; } json_writer_userdata; - -typedef struct stacked_container { - grpc_json_type type; - struct stacked_container *next; -} stacked_container; - -typedef struct json_reader_userdata { - FILE *in; - grpc_json_writer *writer; - char *scratchpad; - char *ptr; - size_t free_space; - size_t allocated; - size_t string_len; - stacked_container *top; -} json_reader_userdata; - -static void json_writer_output_char(void *userdata, char c) { - json_writer_userdata *state = userdata; - fputc(c, state->out); -} - -static void json_writer_output_string(void *userdata, const char *str) { - json_writer_userdata *state = userdata; - fputs(str, state->out); -} - -static void json_writer_output_string_with_len(void *userdata, const char *str, - size_t len) { - json_writer_userdata *state = userdata; - fwrite(str, len, 1, state->out); -} - -grpc_json_writer_vtable writer_vtable = {json_writer_output_char, - json_writer_output_string, - json_writer_output_string_with_len}; - -static void check_string(json_reader_userdata *state, size_t needed) { - if (state->free_space >= needed) return; - needed -= state->free_space; - needed = (needed + 0xffu) & ~0xffu; - state->scratchpad = gpr_realloc(state->scratchpad, state->allocated + needed); - state->free_space += needed; - state->allocated += needed; -} - -static void json_reader_string_clear(void *userdata) { - json_reader_userdata *state = userdata; - state->free_space = state->allocated; - state->string_len = 0; -} - -static void json_reader_string_add_char(void *userdata, uint32_t c) { - json_reader_userdata *state = userdata; - check_string(state, 1); - GPR_ASSERT(c < 256); - state->scratchpad[state->string_len++] = (char)c; -} - -static void json_reader_string_add_utf32(void *userdata, uint32_t c) { - if (c <= 0x7f) { - json_reader_string_add_char(userdata, c); - } else if (c <= 0x7ff) { - uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu); - uint32_t b2 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - } else if (c <= 0xffffu) { - uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu); - uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu); - uint32_t b3 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - json_reader_string_add_char(userdata, b3); - } else if (c <= 0x1fffffu) { - uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u); - uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu); - uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu); - uint32_t b4 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - json_reader_string_add_char(userdata, b3); - json_reader_string_add_char(userdata, b4); - } -} - -static uint32_t json_reader_read_char(void *userdata) { - int r; - json_reader_userdata *state = userdata; - - r = fgetc(state->in); - if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF; - return (uint32_t)r; -} - -static void json_reader_container_begins(void *userdata, grpc_json_type type) { - json_reader_userdata *state = userdata; - stacked_container *container = gpr_malloc(sizeof(stacked_container)); - - container->type = type; - container->next = state->top; - state->top = container; - - grpc_json_writer_container_begins(state->writer, type); -} - -static grpc_json_type json_reader_container_ends(void *userdata) { - json_reader_userdata *state = userdata; - stacked_container *container = state->top; - - grpc_json_writer_container_ends(state->writer, container->type); - state->top = container->next; - gpr_free(container); - return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL; -} - -static void json_reader_set_key(void *userdata) { - json_reader_userdata *state = userdata; - json_reader_string_add_char(userdata, 0); - - grpc_json_writer_object_key(state->writer, state->scratchpad); -} - -static void json_reader_set_string(void *userdata) { - json_reader_userdata *state = userdata; - json_reader_string_add_char(userdata, 0); - - grpc_json_writer_value_string(state->writer, state->scratchpad); -} - -static int json_reader_set_number(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad, - state->string_len); - - return 1; -} - -static void json_reader_set_true(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "true", 4); -} - -static void json_reader_set_false(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "false", 5); -} - -static void json_reader_set_null(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "null", 4); -} - -static grpc_json_reader_vtable reader_vtable = { - json_reader_string_clear, json_reader_string_add_char, - json_reader_string_add_utf32, json_reader_read_char, - json_reader_container_begins, json_reader_container_ends, - json_reader_set_key, json_reader_set_string, - json_reader_set_number, json_reader_set_true, - json_reader_set_false, json_reader_set_null}; - -int rewrite(FILE *in, FILE *out, int indent) { - grpc_json_writer writer; - grpc_json_reader reader; - grpc_json_reader_status status; - json_writer_userdata writer_user; - json_reader_userdata reader_user; - - reader_user.writer = &writer; - reader_user.in = in; - reader_user.top = NULL; - reader_user.scratchpad = NULL; - reader_user.string_len = 0; - reader_user.free_space = 0; - reader_user.allocated = 0; - - writer_user.out = out; - - grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user); - grpc_json_reader_init(&reader, &reader_vtable, &reader_user); - - status = grpc_json_reader_run(&reader); - - free(reader_user.scratchpad); - while (reader_user.top) { - stacked_container *container = reader_user.top; - reader_user.top = container->next; - free(container); - } - - return status == GRPC_JSON_DONE; -} - -int main(int argc, char **argv) { - int indent = 2; - gpr_cmdline *cl; - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_int(cl, "indent", NULL, &indent); - gpr_cmdline_parse(cl, argc, argv); - gpr_cmdline_destroy(cl); - - return rewrite(stdin, stdout, indent) ? 0 : 1; -} diff --git a/test/core/json/json_rewrite.cc b/test/core/json/json_rewrite.cc new file mode 100644 index 0000000000..27443e3c49 --- /dev/null +++ b/test/core/json/json_rewrite.cc @@ -0,0 +1,239 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +#include "src/core/lib/json/json_reader.h" +#include "src/core/lib/json/json_writer.h" + +typedef struct json_writer_userdata { FILE *out; } json_writer_userdata; + +typedef struct stacked_container { + grpc_json_type type; + struct stacked_container *next; +} stacked_container; + +typedef struct json_reader_userdata { + FILE *in; + grpc_json_writer *writer; + char *scratchpad; + char *ptr; + size_t free_space; + size_t allocated; + size_t string_len; + stacked_container *top; +} json_reader_userdata; + +static void json_writer_output_char(void *userdata, char c) { + json_writer_userdata *state = static_cast(userdata); + fputc(c, state->out); +} + +static void json_writer_output_string(void *userdata, const char *str) { + json_writer_userdata *state = static_cast(userdata); + fputs(str, state->out); +} + +static void json_writer_output_string_with_len(void *userdata, const char *str, + size_t len) { + json_writer_userdata *state = static_cast(userdata); + fwrite(str, len, 1, state->out); +} + +grpc_json_writer_vtable writer_vtable = {json_writer_output_char, + json_writer_output_string, + json_writer_output_string_with_len}; + +static void check_string(json_reader_userdata *state, size_t needed) { + if (state->free_space >= needed) return; + needed -= state->free_space; + needed = (needed + 0xffu) & ~0xffu; + state->scratchpad = static_cast( + gpr_realloc(state->scratchpad, state->allocated + needed)); + state->free_space += needed; + state->allocated += needed; +} + +static void json_reader_string_clear(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + state->free_space = state->allocated; + state->string_len = 0; +} + +static void json_reader_string_add_char(void *userdata, uint32_t c) { + json_reader_userdata *state = static_cast(userdata); + check_string(state, 1); + GPR_ASSERT(c < 256); + state->scratchpad[state->string_len++] = (char)c; +} + +static void json_reader_string_add_utf32(void *userdata, uint32_t c) { + if (c <= 0x7f) { + json_reader_string_add_char(userdata, c); + } else if (c <= 0x7ff) { + uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu); + uint32_t b2 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + } else if (c <= 0xffffu) { + uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu); + uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu); + uint32_t b3 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + json_reader_string_add_char(userdata, b3); + } else if (c <= 0x1fffffu) { + uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u); + uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu); + uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu); + uint32_t b4 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + json_reader_string_add_char(userdata, b3); + json_reader_string_add_char(userdata, b4); + } +} + +static uint32_t json_reader_read_char(void *userdata) { + int r; + json_reader_userdata *state = static_cast(userdata); + + r = fgetc(state->in); + if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF; + return (uint32_t)r; +} + +static void json_reader_container_begins(void *userdata, grpc_json_type type) { + json_reader_userdata *state = static_cast(userdata); + stacked_container *container = + static_cast(gpr_malloc(sizeof(stacked_container))); + + container->type = type; + container->next = state->top; + state->top = container; + + grpc_json_writer_container_begins(state->writer, type); +} + +static grpc_json_type json_reader_container_ends(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + stacked_container *container = state->top; + + grpc_json_writer_container_ends(state->writer, container->type); + state->top = container->next; + gpr_free(container); + return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL; +} + +static void json_reader_set_key(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + json_reader_string_add_char(userdata, 0); + + grpc_json_writer_object_key(state->writer, state->scratchpad); +} + +static void json_reader_set_string(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + json_reader_string_add_char(userdata, 0); + + grpc_json_writer_value_string(state->writer, state->scratchpad); +} + +static int json_reader_set_number(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad, + state->string_len); + + return 1; +} + +static void json_reader_set_true(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "true", 4); +} + +static void json_reader_set_false(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "false", 5); +} + +static void json_reader_set_null(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "null", 4); +} + +static grpc_json_reader_vtable reader_vtable = { + json_reader_string_clear, json_reader_string_add_char, + json_reader_string_add_utf32, json_reader_read_char, + json_reader_container_begins, json_reader_container_ends, + json_reader_set_key, json_reader_set_string, + json_reader_set_number, json_reader_set_true, + json_reader_set_false, json_reader_set_null}; + +int rewrite(FILE *in, FILE *out, int indent) { + grpc_json_writer writer; + grpc_json_reader reader; + grpc_json_reader_status status; + json_writer_userdata writer_user; + json_reader_userdata reader_user; + + reader_user.writer = &writer; + reader_user.in = in; + reader_user.top = NULL; + reader_user.scratchpad = NULL; + reader_user.string_len = 0; + reader_user.free_space = 0; + reader_user.allocated = 0; + + writer_user.out = out; + + grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user); + grpc_json_reader_init(&reader, &reader_vtable, &reader_user); + + status = grpc_json_reader_run(&reader); + + free(reader_user.scratchpad); + while (reader_user.top) { + stacked_container *container = reader_user.top; + reader_user.top = container->next; + free(container); + } + + return status == GRPC_JSON_DONE; +} + +int main(int argc, char **argv) { + int indent = 2; + gpr_cmdline *cl; + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_int(cl, "indent", NULL, &indent); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + return rewrite(stdin, stdout, indent) ? 0 : 1; +} diff --git a/test/core/json/json_rewrite_test.c b/test/core/json/json_rewrite_test.c deleted file mode 100644 index a654971b34..0000000000 --- a/test/core/json/json_rewrite_test.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -#include "src/core/lib/json/json_reader.h" -#include "src/core/lib/json/json_writer.h" - -typedef struct json_writer_userdata { FILE *cmp; } json_writer_userdata; - -typedef struct stacked_container { - grpc_json_type type; - struct stacked_container *next; -} stacked_container; - -typedef struct json_reader_userdata { - FILE *in; - grpc_json_writer *writer; - char *scratchpad; - char *ptr; - size_t free_space; - size_t allocated; - size_t string_len; - stacked_container *top; - int did_eagain; -} json_reader_userdata; - -static void json_writer_output_char(void *userdata, char c) { - json_writer_userdata *state = userdata; - int cmp = fgetc(state->cmp); - - /* treat CRLF as LF */ - if (cmp == '\r' && c == '\n') { - cmp = fgetc(state->cmp); - } - GPR_ASSERT(cmp == c); -} - -static void json_writer_output_string(void *userdata, const char *str) { - while (*str) { - json_writer_output_char(userdata, *str++); - } -} - -static void json_writer_output_string_with_len(void *userdata, const char *str, - size_t len) { - size_t i; - for (i = 0; i < len; i++) { - json_writer_output_char(userdata, str[i]); - } -} - -grpc_json_writer_vtable writer_vtable = {json_writer_output_char, - json_writer_output_string, - json_writer_output_string_with_len}; - -static void check_string(json_reader_userdata *state, size_t needed) { - if (state->free_space >= needed) return; - needed -= state->free_space; - needed = (needed + 0xffu) & ~0xffu; - state->scratchpad = gpr_realloc(state->scratchpad, state->allocated + needed); - state->free_space += needed; - state->allocated += needed; -} - -static void json_reader_string_clear(void *userdata) { - json_reader_userdata *state = userdata; - state->free_space = state->allocated; - state->string_len = 0; -} - -static void json_reader_string_add_char(void *userdata, uint32_t c) { - json_reader_userdata *state = userdata; - check_string(state, 1); - GPR_ASSERT(c <= 256); - state->scratchpad[state->string_len++] = (char)c; -} - -static void json_reader_string_add_utf32(void *userdata, uint32_t c) { - if (c <= 0x7f) { - json_reader_string_add_char(userdata, c); - } else if (c <= 0x7ffu) { - uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu); - uint32_t b2 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - } else if (c <= 0xffffu) { - uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu); - uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu); - uint32_t b3 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - json_reader_string_add_char(userdata, b3); - } else if (c <= 0x1fffffu) { - uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u); - uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu); - uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu); - uint32_t b4 = 0x80u | (c & 0x3fu); - json_reader_string_add_char(userdata, b1); - json_reader_string_add_char(userdata, b2); - json_reader_string_add_char(userdata, b3); - json_reader_string_add_char(userdata, b4); - } -} - -static uint32_t json_reader_read_char(void *userdata) { - int r; - json_reader_userdata *state = userdata; - - if (!state->did_eagain) { - state->did_eagain = 1; - return GRPC_JSON_READ_CHAR_EAGAIN; - } - - state->did_eagain = 0; - - r = fgetc(state->in); - if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF; - return (uint32_t)r; -} - -static void json_reader_container_begins(void *userdata, grpc_json_type type) { - json_reader_userdata *state = userdata; - stacked_container *container = gpr_malloc(sizeof(stacked_container)); - - container->type = type; - container->next = state->top; - state->top = container; - - grpc_json_writer_container_begins(state->writer, type); -} - -static grpc_json_type json_reader_container_ends(void *userdata) { - json_reader_userdata *state = userdata; - stacked_container *container = state->top; - - grpc_json_writer_container_ends(state->writer, container->type); - state->top = container->next; - gpr_free(container); - return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL; -} - -static void json_reader_set_key(void *userdata) { - json_reader_userdata *state = userdata; - json_reader_string_add_char(userdata, 0); - - grpc_json_writer_object_key(state->writer, state->scratchpad); -} - -static void json_reader_set_string(void *userdata) { - json_reader_userdata *state = userdata; - json_reader_string_add_char(userdata, 0); - - grpc_json_writer_value_string(state->writer, state->scratchpad); -} - -static int json_reader_set_number(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad, - state->string_len); - - return 1; -} - -static void json_reader_set_true(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "true", 4); -} - -static void json_reader_set_false(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "false", 5); -} - -static void json_reader_set_null(void *userdata) { - json_reader_userdata *state = userdata; - - grpc_json_writer_value_raw_with_len(state->writer, "null", 4); -} - -static grpc_json_reader_vtable reader_vtable = { - json_reader_string_clear, json_reader_string_add_char, - json_reader_string_add_utf32, json_reader_read_char, - json_reader_container_begins, json_reader_container_ends, - json_reader_set_key, json_reader_set_string, - json_reader_set_number, json_reader_set_true, - json_reader_set_false, json_reader_set_null}; - -int rewrite_and_compare(FILE *in, FILE *cmp, int indent) { - grpc_json_writer writer; - grpc_json_reader reader; - grpc_json_reader_status status; - json_writer_userdata writer_user; - json_reader_userdata reader_user; - - GPR_ASSERT(in); - GPR_ASSERT(cmp); - - reader_user.writer = &writer; - reader_user.in = in; - reader_user.top = NULL; - reader_user.scratchpad = NULL; - reader_user.string_len = 0; - reader_user.free_space = 0; - reader_user.allocated = 0; - reader_user.did_eagain = 0; - - writer_user.cmp = cmp; - - grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user); - grpc_json_reader_init(&reader, &reader_vtable, &reader_user); - - do { - status = grpc_json_reader_run(&reader); - } while (status == GRPC_JSON_EAGAIN); - - free(reader_user.scratchpad); - while (reader_user.top) { - stacked_container *container = reader_user.top; - reader_user.top = container->next; - free(container); - } - - return status == GRPC_JSON_DONE; -} - -typedef struct test_file { - const char *input; - const char *cmp; - int indent; -} test_file; - -static test_file test_files[] = { - {"test/core/json/rewrite_test_input.json", - "test/core/json/rewrite_test_output_condensed.json", 0}, - {"test/core/json/rewrite_test_input.json", - "test/core/json/rewrite_test_output_indented.json", 2}, - {"test/core/json/rewrite_test_output_indented.json", - "test/core/json/rewrite_test_output_condensed.json", 0}, - {"test/core/json/rewrite_test_output_condensed.json", - "test/core/json/rewrite_test_output_indented.json", 2}, -}; - -void test_rewrites() { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(test_files); i++) { - test_file *test = test_files + i; - FILE *input = fopen(test->input, "rb"); - FILE *cmp = fopen(test->cmp, "rb"); - int status; - gpr_log(GPR_INFO, "Testing file %s against %s using indent=%i", test->input, - test->cmp, test->indent); - status = rewrite_and_compare(input, cmp, test->indent); - GPR_ASSERT(status); - fclose(input); - fclose(cmp); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_rewrites(); - gpr_log(GPR_INFO, "json_rewrite_test success"); - return 0; -} diff --git a/test/core/json/json_rewrite_test.cc b/test/core/json/json_rewrite_test.cc new file mode 100644 index 0000000000..ba22709a70 --- /dev/null +++ b/test/core/json/json_rewrite_test.cc @@ -0,0 +1,292 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +#include "src/core/lib/json/json_reader.h" +#include "src/core/lib/json/json_writer.h" + +typedef struct json_writer_userdata { FILE *cmp; } json_writer_userdata; + +typedef struct stacked_container { + grpc_json_type type; + struct stacked_container *next; +} stacked_container; + +typedef struct json_reader_userdata { + FILE *in; + grpc_json_writer *writer; + char *scratchpad; + char *ptr; + size_t free_space; + size_t allocated; + size_t string_len; + stacked_container *top; + int did_eagain; +} json_reader_userdata; + +static void json_writer_output_char(void *userdata, char c) { + json_writer_userdata *state = static_cast(userdata); + int cmp = fgetc(state->cmp); + + /* treat CRLF as LF */ + if (cmp == '\r' && c == '\n') { + cmp = fgetc(state->cmp); + } + GPR_ASSERT(cmp == c); +} + +static void json_writer_output_string(void *userdata, const char *str) { + while (*str) { + json_writer_output_char(userdata, *str++); + } +} + +static void json_writer_output_string_with_len(void *userdata, const char *str, + size_t len) { + size_t i; + for (i = 0; i < len; i++) { + json_writer_output_char(userdata, str[i]); + } +} + +grpc_json_writer_vtable writer_vtable = {json_writer_output_char, + json_writer_output_string, + json_writer_output_string_with_len}; + +static void check_string(json_reader_userdata *state, size_t needed) { + if (state->free_space >= needed) return; + needed -= state->free_space; + needed = (needed + 0xffu) & ~0xffu; + state->scratchpad = static_cast( + gpr_realloc(state->scratchpad, state->allocated + needed)); + state->free_space += needed; + state->allocated += needed; +} + +static void json_reader_string_clear(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + state->free_space = state->allocated; + state->string_len = 0; +} + +static void json_reader_string_add_char(void *userdata, uint32_t c) { + json_reader_userdata *state = static_cast(userdata); + check_string(state, 1); + GPR_ASSERT(c <= 256); + state->scratchpad[state->string_len++] = (char)c; +} + +static void json_reader_string_add_utf32(void *userdata, uint32_t c) { + if (c <= 0x7f) { + json_reader_string_add_char(userdata, c); + } else if (c <= 0x7ffu) { + uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu); + uint32_t b2 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + } else if (c <= 0xffffu) { + uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu); + uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu); + uint32_t b3 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + json_reader_string_add_char(userdata, b3); + } else if (c <= 0x1fffffu) { + uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u); + uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu); + uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu); + uint32_t b4 = 0x80u | (c & 0x3fu); + json_reader_string_add_char(userdata, b1); + json_reader_string_add_char(userdata, b2); + json_reader_string_add_char(userdata, b3); + json_reader_string_add_char(userdata, b4); + } +} + +static uint32_t json_reader_read_char(void *userdata) { + int r; + json_reader_userdata *state = static_cast(userdata); + + if (!state->did_eagain) { + state->did_eagain = 1; + return GRPC_JSON_READ_CHAR_EAGAIN; + } + + state->did_eagain = 0; + + r = fgetc(state->in); + if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF; + return (uint32_t)r; +} + +static void json_reader_container_begins(void *userdata, grpc_json_type type) { + json_reader_userdata *state = static_cast(userdata); + stacked_container *container = + static_cast(gpr_malloc(sizeof(stacked_container))); + + container->type = type; + container->next = state->top; + state->top = container; + + grpc_json_writer_container_begins(state->writer, type); +} + +static grpc_json_type json_reader_container_ends(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + stacked_container *container = state->top; + + grpc_json_writer_container_ends(state->writer, container->type); + state->top = container->next; + gpr_free(container); + return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL; +} + +static void json_reader_set_key(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + json_reader_string_add_char(userdata, 0); + + grpc_json_writer_object_key(state->writer, state->scratchpad); +} + +static void json_reader_set_string(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + json_reader_string_add_char(userdata, 0); + + grpc_json_writer_value_string(state->writer, state->scratchpad); +} + +static int json_reader_set_number(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad, + state->string_len); + + return 1; +} + +static void json_reader_set_true(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "true", 4); +} + +static void json_reader_set_false(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "false", 5); +} + +static void json_reader_set_null(void *userdata) { + json_reader_userdata *state = static_cast(userdata); + + grpc_json_writer_value_raw_with_len(state->writer, "null", 4); +} + +static grpc_json_reader_vtable reader_vtable = { + json_reader_string_clear, json_reader_string_add_char, + json_reader_string_add_utf32, json_reader_read_char, + json_reader_container_begins, json_reader_container_ends, + json_reader_set_key, json_reader_set_string, + json_reader_set_number, json_reader_set_true, + json_reader_set_false, json_reader_set_null}; + +int rewrite_and_compare(FILE *in, FILE *cmp, int indent) { + grpc_json_writer writer; + grpc_json_reader reader; + grpc_json_reader_status status; + json_writer_userdata writer_user; + json_reader_userdata reader_user; + + GPR_ASSERT(in); + GPR_ASSERT(cmp); + + reader_user.writer = &writer; + reader_user.in = in; + reader_user.top = NULL; + reader_user.scratchpad = NULL; + reader_user.string_len = 0; + reader_user.free_space = 0; + reader_user.allocated = 0; + reader_user.did_eagain = 0; + + writer_user.cmp = cmp; + + grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user); + grpc_json_reader_init(&reader, &reader_vtable, &reader_user); + + do { + status = grpc_json_reader_run(&reader); + } while (status == GRPC_JSON_EAGAIN); + + free(reader_user.scratchpad); + while (reader_user.top) { + stacked_container *container = reader_user.top; + reader_user.top = container->next; + free(container); + } + + return status == GRPC_JSON_DONE; +} + +typedef struct test_file { + const char *input; + const char *cmp; + int indent; +} test_file; + +static test_file test_files[] = { + {"test/core/json/rewrite_test_input.json", + "test/core/json/rewrite_test_output_condensed.json", 0}, + {"test/core/json/rewrite_test_input.json", + "test/core/json/rewrite_test_output_indented.json", 2}, + {"test/core/json/rewrite_test_output_indented.json", + "test/core/json/rewrite_test_output_condensed.json", 0}, + {"test/core/json/rewrite_test_output_condensed.json", + "test/core/json/rewrite_test_output_indented.json", 2}, +}; + +void test_rewrites() { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(test_files); i++) { + test_file *test = test_files + i; + FILE *input = fopen(test->input, "rb"); + FILE *cmp = fopen(test->cmp, "rb"); + int status; + gpr_log(GPR_INFO, "Testing file %s against %s using indent=%i", test->input, + test->cmp, test->indent); + status = rewrite_and_compare(input, cmp, test->indent); + GPR_ASSERT(status); + fclose(input); + fclose(cmp); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_rewrites(); + gpr_log(GPR_INFO, "json_rewrite_test success"); + return 0; +} diff --git a/test/core/json/json_stream_error_test.c b/test/core/json/json_stream_error_test.c deleted file mode 100644 index 379cd5d078..0000000000 --- a/test/core/json/json_stream_error_test.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -#include "src/core/lib/json/json_reader.h" -#include "src/core/lib/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 uint32_t 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_stream_error_test.cc b/test/core/json/json_stream_error_test.cc new file mode 100644 index 0000000000..379cd5d078 --- /dev/null +++ b/test/core/json/json_stream_error_test.cc @@ -0,0 +1,57 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +#include "src/core/lib/json/json_reader.h" +#include "src/core/lib/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 uint32_t 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 deleted file mode 100644 index bbc6f7a4e6..0000000000 --- a/test/core/json/json_test.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Copyright 2015-2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include "src/core/lib/json/json.h" -#include "src/core/lib/support/string.h" - -#include "test/core/util/test_config.h" - -typedef struct testing_pair { - const char *input; - const char *output; -} 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. */ - {"\"\\u0020\\\\\\u0010\\u000a\\u000D\"", "\" \\\\\\u0010\\n\\r\""}, - /* Testing various UTF-8 sequences. */ - {"\"ßâñć௵⇒\"", "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""}, - {"\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\"", - "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""}, - /* Testing UTF-8 character "𝄞", U+11D1E. */ - {"\"\xf0\x9d\x84\x9e\"", "\"\\ud834\\udd1e\""}, - {"\"\\ud834\\udd1e\"", "\"\\ud834\\udd1e\""}, - {"{\"\\ud834\\udd1e\":0}", "{\"\\ud834\\udd1e\":0}"}, - /* Testing nested empty containers. */ - { - " [ [ ] , { } , [ ] ] ", "[[],{},[]]", - }, - /* Testing escapes and control chars in key strings. */ - {" { \"\\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\"", "\"\""}, - /* Testing valid number parsing. */ - {"[0, 42 , 0.0123, 123.456]", "[0,42,0.0123,123.456]"}, - {"[1e4,-53.235e-31, 0.3e+3]", "[1e4,-53.235e-31,0.3e+3]"}, - /* Testing keywords parsing. */ - {"[true, false, null]", "[true,false,null]"}, - - /* Testing invalid parsing. */ - - /* Testing plain invalid things, exercising the state machine. */ - {"\\", NULL}, - {"nu ll", NULL}, - {"{\"foo\": bar}", NULL}, - {"{\"foo\": bar\"x\"}", NULL}, - {"fals", NULL}, - {"0,0 ", NULL}, - {"\"foo\",[]", NULL}, - /* Testing unterminated string. */ - {"\"\\x", NULL}, - /* Testing invalid UTF-16 number. */ - {"\"\\u123x", NULL}, - {"{\"\\u123x", NULL}, - /* Testing imbalanced surrogate pairs. */ - {"\"\\ud834f", NULL}, - {"{\"\\ud834f\":0}", NULL}, - {"\"\\ud834\\n", NULL}, - {"{\"\\ud834\\n\":0}", NULL}, - {"\"\\udd1ef", NULL}, - {"{\"\\udd1ef\":0}", NULL}, - {"\"\\ud834\\ud834\"", NULL}, - {"{\"\\ud834\\ud834\"\":0}", NULL}, - {"\"\\ud834\\u1234\"", NULL}, - {"{\"\\ud834\\u1234\"\":0}", NULL}, - {"\"\\ud834]\"", NULL}, - {"{\"\\ud834]\"\":0}", NULL}, - {"\"\\ud834 \"", NULL}, - {"{\"\\ud834 \"\":0}", NULL}, - {"\"\\ud834\\\\\"", NULL}, - {"{\"\\ud834\\\\\"\":0}", NULL}, - /* Testing embedded invalid whitechars. */ - {"\"\n\"", NULL}, - {"\"\t\"", NULL}, - /* Testing empty json data. */ - {"", NULL}, - /* Testing extra characters after end of parsing. */ - {"{},", NULL}, - /* Testing imbalanced containers. */ - {"{}}", NULL}, - {"[]]", NULL}, - {"{{}", NULL}, - {"[[]", NULL}, - {"[}", NULL}, - {"{]", NULL}, - /* 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. */ - {"1.", NULL}, - {"1e", NULL}, - {".12", NULL}, - {"1.x", NULL}, - {"1.12x", NULL}, - {"1ex", NULL}, - {"1e12x", NULL}, - {".12x", NULL}, - {"000", NULL}, -}; - -static void test_pairs() { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(testing_pairs); i++) { - testing_pair *pair = testing_pairs + i; - char *scratchpad = gpr_strdup(pair->input); - grpc_json *json; - - gpr_log(GPR_INFO, "parsing string %i - should %s", i, - pair->output ? "succeed" : "fail"); - json = grpc_json_parse_string(scratchpad); - - if (pair->output) { - char *output; - - GPR_ASSERT(json); - output = grpc_json_dump_to_string(json, 0); - GPR_ASSERT(output); - gpr_log(GPR_INFO, "succeeded with output = %s", output); - GPR_ASSERT(strcmp(output, pair->output) == 0); - - grpc_json_destroy(json); - gpr_free(output); - } else { - gpr_log(GPR_INFO, "failed"); - GPR_ASSERT(!json); - } - - gpr_free(scratchpad); - } -} - -static void test_atypical() { - char *scratchpad = gpr_strdup("[[],[],[]]"); - grpc_json *json = grpc_json_parse_string(scratchpad); - grpc_json *brother; - - GPR_ASSERT(json); - GPR_ASSERT(json->child); - brother = json->child->next; - grpc_json_destroy(json->child); - GPR_ASSERT(json->child == brother); - grpc_json_destroy(json->child->next); - grpc_json_destroy(json); - gpr_free(scratchpad); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_pairs(); - test_atypical(); - gpr_log(GPR_INFO, "json_test success"); - return 0; -} diff --git a/test/core/json/json_test.cc b/test/core/json/json_test.cc new file mode 100644 index 0000000000..bbc6f7a4e6 --- /dev/null +++ b/test/core/json/json_test.cc @@ -0,0 +1,191 @@ +/* + * + * Copyright 2015-2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include "src/core/lib/json/json.h" +#include "src/core/lib/support/string.h" + +#include "test/core/util/test_config.h" + +typedef struct testing_pair { + const char *input; + const char *output; +} 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. */ + {"\"\\u0020\\\\\\u0010\\u000a\\u000D\"", "\" \\\\\\u0010\\n\\r\""}, + /* Testing various UTF-8 sequences. */ + {"\"ßâñć௵⇒\"", "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""}, + {"\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\"", + "\"\\u00df\\u00e2\\u00f1\\u0107\\u0bf5\\u21d2\""}, + /* Testing UTF-8 character "𝄞", U+11D1E. */ + {"\"\xf0\x9d\x84\x9e\"", "\"\\ud834\\udd1e\""}, + {"\"\\ud834\\udd1e\"", "\"\\ud834\\udd1e\""}, + {"{\"\\ud834\\udd1e\":0}", "{\"\\ud834\\udd1e\":0}"}, + /* Testing nested empty containers. */ + { + " [ [ ] , { } , [ ] ] ", "[[],{},[]]", + }, + /* Testing escapes and control chars in key strings. */ + {" { \"\\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\"", "\"\""}, + /* Testing valid number parsing. */ + {"[0, 42 , 0.0123, 123.456]", "[0,42,0.0123,123.456]"}, + {"[1e4,-53.235e-31, 0.3e+3]", "[1e4,-53.235e-31,0.3e+3]"}, + /* Testing keywords parsing. */ + {"[true, false, null]", "[true,false,null]"}, + + /* Testing invalid parsing. */ + + /* Testing plain invalid things, exercising the state machine. */ + {"\\", NULL}, + {"nu ll", NULL}, + {"{\"foo\": bar}", NULL}, + {"{\"foo\": bar\"x\"}", NULL}, + {"fals", NULL}, + {"0,0 ", NULL}, + {"\"foo\",[]", NULL}, + /* Testing unterminated string. */ + {"\"\\x", NULL}, + /* Testing invalid UTF-16 number. */ + {"\"\\u123x", NULL}, + {"{\"\\u123x", NULL}, + /* Testing imbalanced surrogate pairs. */ + {"\"\\ud834f", NULL}, + {"{\"\\ud834f\":0}", NULL}, + {"\"\\ud834\\n", NULL}, + {"{\"\\ud834\\n\":0}", NULL}, + {"\"\\udd1ef", NULL}, + {"{\"\\udd1ef\":0}", NULL}, + {"\"\\ud834\\ud834\"", NULL}, + {"{\"\\ud834\\ud834\"\":0}", NULL}, + {"\"\\ud834\\u1234\"", NULL}, + {"{\"\\ud834\\u1234\"\":0}", NULL}, + {"\"\\ud834]\"", NULL}, + {"{\"\\ud834]\"\":0}", NULL}, + {"\"\\ud834 \"", NULL}, + {"{\"\\ud834 \"\":0}", NULL}, + {"\"\\ud834\\\\\"", NULL}, + {"{\"\\ud834\\\\\"\":0}", NULL}, + /* Testing embedded invalid whitechars. */ + {"\"\n\"", NULL}, + {"\"\t\"", NULL}, + /* Testing empty json data. */ + {"", NULL}, + /* Testing extra characters after end of parsing. */ + {"{},", NULL}, + /* Testing imbalanced containers. */ + {"{}}", NULL}, + {"[]]", NULL}, + {"{{}", NULL}, + {"[[]", NULL}, + {"[}", NULL}, + {"{]", NULL}, + /* 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. */ + {"1.", NULL}, + {"1e", NULL}, + {".12", NULL}, + {"1.x", NULL}, + {"1.12x", NULL}, + {"1ex", NULL}, + {"1e12x", NULL}, + {".12x", NULL}, + {"000", NULL}, +}; + +static void test_pairs() { + unsigned i; + + for (i = 0; i < GPR_ARRAY_SIZE(testing_pairs); i++) { + testing_pair *pair = testing_pairs + i; + char *scratchpad = gpr_strdup(pair->input); + grpc_json *json; + + gpr_log(GPR_INFO, "parsing string %i - should %s", i, + pair->output ? "succeed" : "fail"); + json = grpc_json_parse_string(scratchpad); + + if (pair->output) { + char *output; + + GPR_ASSERT(json); + output = grpc_json_dump_to_string(json, 0); + GPR_ASSERT(output); + gpr_log(GPR_INFO, "succeeded with output = %s", output); + GPR_ASSERT(strcmp(output, pair->output) == 0); + + grpc_json_destroy(json); + gpr_free(output); + } else { + gpr_log(GPR_INFO, "failed"); + GPR_ASSERT(!json); + } + + gpr_free(scratchpad); + } +} + +static void test_atypical() { + char *scratchpad = gpr_strdup("[[],[],[]]"); + grpc_json *json = grpc_json_parse_string(scratchpad); + grpc_json *brother; + + GPR_ASSERT(json); + GPR_ASSERT(json->child); + brother = json->child->next; + grpc_json_destroy(json->child); + GPR_ASSERT(json->child == brother); + grpc_json_destroy(json->child->next); + grpc_json_destroy(json); + gpr_free(scratchpad); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_pairs(); + test_atypical(); + gpr_log(GPR_INFO, "json_test success"); + return 0; +} diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c deleted file mode 100644 index 6392554d85..0000000000 --- a/test/core/memory_usage/client.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/memory_counters.h" -#include "test/core/util/test_config.h" - -static grpc_channel *channel; -static grpc_completion_queue *cq; -static grpc_op metadata_ops[2]; -static grpc_op status_ops[2]; -static grpc_op snapshot_ops[6]; -static grpc_op *op; - -typedef struct { - grpc_call *call; - grpc_metadata_array initial_metadata_recv; - grpc_status_code status; - grpc_slice details; - grpc_metadata_array trailing_metadata_recv; -} fling_call; - -// Statically allocate call data structs. Enough to accomodate 10000 ping-pong -// calls and 1 extra for the snapshot calls. -static fling_call calls[10001]; - -static void *tag(intptr_t t) { return (void *)t; } - -// A call is intentionally divided into two steps. First step is to initiate a -// call (i.e send and recv metadata). A call is outstanding after we initated, -// so we can measure the call memory usage. -static void init_ping_pong_request(int call_idx) { - grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); - - memset(metadata_ops, 0, sizeof(metadata_ops)); - op = metadata_ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &calls[call_idx].initial_metadata_recv; - op++; - - grpc_slice hostname = grpc_slice_from_static_string("localhost"); - calls[call_idx].call = grpc_channel_create_call( - channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/Reflector/reflectUnary"), &hostname, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, - metadata_ops, - (size_t)(op - metadata_ops), - tag(call_idx), NULL)); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); -} - -// Second step is to finish the call (i.e recv status) and destroy the call. -static void finish_ping_pong_request(int call_idx) { - grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); - - memset(status_ops, 0, sizeof(status_ops)); - op = status_ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = - &calls[call_idx].trailing_metadata_recv; - op->data.recv_status_on_client.status = &calls[call_idx].status; - op->data.recv_status_on_client.status_details = &calls[call_idx].details; - op++; - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, - status_ops, - (size_t)(op - status_ops), - tag(call_idx), NULL)); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); - grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); - grpc_slice_unref(calls[call_idx].details); - grpc_call_unref(calls[call_idx].call); - calls[call_idx].call = NULL; -} - -static struct grpc_memory_counters send_snapshot_request(int call_idx, - grpc_slice call_type) { - grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); - grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); - - grpc_byte_buffer *response_payload_recv = NULL; - memset(snapshot_ops, 0, sizeof(snapshot_ops)); - op = snapshot_ops; - - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &calls[call_idx].initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = - &calls[call_idx].trailing_metadata_recv; - op->data.recv_status_on_client.status = &calls[call_idx].status; - op->data.recv_status_on_client.status_details = &calls[call_idx].details; - op++; - - grpc_slice hostname = grpc_slice_from_static_string("localhost"); - calls[call_idx].call = grpc_channel_create_call( - channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, &hostname, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( - calls[call_idx].call, snapshot_ops, - (size_t)(op - snapshot_ops), (void *)0, NULL)); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - grpc_byte_buffer_reader reader; - grpc_byte_buffer_reader_init(&reader, response_payload_recv); - grpc_slice response = grpc_byte_buffer_reader_readall(&reader); - - struct grpc_memory_counters snapshot; - snapshot.total_size_absolute = - ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) - ->total_size_absolute; - snapshot.total_allocs_absolute = - ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) - ->total_allocs_absolute; - snapshot.total_size_relative = - ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) - ->total_size_relative; - snapshot.total_allocs_relative = - ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) - ->total_allocs_relative; - - grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); - grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); - grpc_slice_unref(response); - grpc_byte_buffer_reader_destroy(&reader); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(calls[call_idx].details); - calls[call_idx].details = grpc_empty_slice(); - grpc_call_unref(calls[call_idx].call); - calls[call_idx].call = NULL; - - return snapshot; -} - -int main(int argc, char **argv) { - grpc_memory_counters_init(); - grpc_slice slice = grpc_slice_from_copied_string("x"); - char *fake_argv[1]; - - char *target = "localhost:443"; - gpr_cmdline *cl; - grpc_event event; - - grpc_init(); - - GPR_ASSERT(argc >= 1); - fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); - - int warmup_iterations = 100; - int benchmark_iterations = 1000; - - cl = gpr_cmdline_create("memory profiling client"); - gpr_cmdline_add_string(cl, "target", "Target host:port", &target); - gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations); - gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations", - &benchmark_iterations); - gpr_cmdline_parse(cl, argc, argv); - gpr_cmdline_destroy(cl); - - for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) { - calls[k].details = grpc_empty_slice(); - } - - cq = grpc_completion_queue_create_for_next(NULL); - - struct grpc_memory_counters client_channel_start = - grpc_memory_counters_snapshot(); - channel = grpc_insecure_channel_create(target, NULL, NULL); - - int call_idx = 0; - - struct grpc_memory_counters before_server_create = send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation")); - struct grpc_memory_counters after_server_create = send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation")); - - // warmup period - for (int i = 0; i < warmup_iterations; i++) { - send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); - } - - for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) { - init_ping_pong_request(call_idx + 1); - } - - struct grpc_memory_counters server_benchmark_calls_start = - send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); - - struct grpc_memory_counters client_benchmark_calls_start = - grpc_memory_counters_snapshot(); - - // benchmark period - for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { - init_ping_pong_request(call_idx + 1); - } - - struct grpc_memory_counters client_calls_inflight = - grpc_memory_counters_snapshot(); - - struct grpc_memory_counters server_calls_inflight = send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/DestroyCalls")); - - do { - event = grpc_completion_queue_next( - cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(10000, GPR_TIMESPAN)), - NULL); - } while (event.type != GRPC_QUEUE_TIMEOUT); - - // second step - recv status and destroy call - for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations; - ++call_idx) { - finish_ping_pong_request(call_idx + 1); - } - - struct grpc_memory_counters server_calls_end = send_snapshot_request( - 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); - - struct grpc_memory_counters client_channel_end = - grpc_memory_counters_snapshot(); - - grpc_channel_destroy(channel); - grpc_completion_queue_shutdown(cq); - - do { - event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); - } while (event.type != GRPC_QUEUE_SHUTDOWN); - grpc_slice_unref(slice); - - grpc_completion_queue_destroy(cq); - grpc_shutdown(); - - gpr_log(GPR_INFO, "---------client stats--------"); - gpr_log(GPR_INFO, "client call memory usage: %f bytes per call", - (double)(client_calls_inflight.total_size_relative - - client_benchmark_calls_start.total_size_relative) / - benchmark_iterations); - gpr_log(GPR_INFO, "client channel memory usage %zi bytes", - client_channel_end.total_size_relative - - client_channel_start.total_size_relative); - - gpr_log(GPR_INFO, "---------server stats--------"); - gpr_log(GPR_INFO, "server create: %zi bytes", - after_server_create.total_size_relative - - before_server_create.total_size_relative); - gpr_log(GPR_INFO, "server call memory usage: %f bytes per call", - (double)(server_calls_inflight.total_size_relative - - server_benchmark_calls_start.total_size_relative) / - benchmark_iterations); - gpr_log(GPR_INFO, "server channel memory usage %zi bytes", - server_calls_end.total_size_relative - - after_server_create.total_size_relative); - - const char *csv_file = "memory_usage.csv"; - FILE *csv = fopen(csv_file, "w"); - if (csv) { - char *env_build = gpr_getenv("BUILD_NUMBER"); - char *env_job = gpr_getenv("JOB_NAME"); - fprintf(csv, "%f,%zi,%zi,%f,%zi,%s,%s\n", - (double)(client_calls_inflight.total_size_relative - - client_benchmark_calls_start.total_size_relative) / - benchmark_iterations, - client_channel_end.total_size_relative - - client_channel_start.total_size_relative, - after_server_create.total_size_relative - - before_server_create.total_size_relative, - (double)(server_calls_inflight.total_size_relative - - server_benchmark_calls_start.total_size_relative) / - benchmark_iterations, - server_calls_end.total_size_relative - - after_server_create.total_size_relative, - env_build == NULL ? "" : env_build, env_job == NULL ? "" : env_job); - fclose(csv); - gpr_log(GPR_INFO, "Summary written to %s", csv_file); - } - - grpc_memory_counters_destroy(); - return 0; -} diff --git a/test/core/memory_usage/client.cc b/test/core/memory_usage/client.cc new file mode 100644 index 0000000000..fbf907fe33 --- /dev/null +++ b/test/core/memory_usage/client.cc @@ -0,0 +1,329 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/test_config.h" + +static grpc_channel *channel; +static grpc_completion_queue *cq; +static grpc_op metadata_ops[2]; +static grpc_op status_ops[2]; +static grpc_op snapshot_ops[6]; +static grpc_op *op; + +typedef struct { + grpc_call *call; + grpc_metadata_array initial_metadata_recv; + grpc_status_code status; + grpc_slice details; + grpc_metadata_array trailing_metadata_recv; +} fling_call; + +// Statically allocate call data structs. Enough to accomodate 10000 ping-pong +// calls and 1 extra for the snapshot calls. +static fling_call calls[10001]; + +static void *tag(intptr_t t) { return (void *)t; } + +// A call is intentionally divided into two steps. First step is to initiate a +// call (i.e send and recv metadata). A call is outstanding after we initated, +// so we can measure the call memory usage. +static void init_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + + memset(metadata_ops, 0, sizeof(metadata_ops)); + op = metadata_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &calls[call_idx].initial_metadata_recv; + op++; + + grpc_slice hostname = grpc_slice_from_static_string("localhost"); + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/Reflector/reflectUnary"), &hostname, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + metadata_ops, + (size_t)(op - metadata_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +} + +// Second step is to finish the call (i.e recv status) and destroy the call. +static void finish_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + memset(status_ops, 0, sizeof(status_ops)); + op = status_ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op++; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + status_ops, + (size_t)(op - status_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + grpc_slice_unref(calls[call_idx].details); + grpc_call_unref(calls[call_idx].call); + calls[call_idx].call = NULL; +} + +static struct grpc_memory_counters send_snapshot_request(int call_idx, + grpc_slice call_type) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + grpc_byte_buffer *response_payload_recv = NULL; + memset(snapshot_ops, 0, sizeof(snapshot_ops)); + op = snapshot_ops; + + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = + &calls[call_idx].initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op++; + + grpc_slice hostname = grpc_slice_from_static_string("localhost"); + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, &hostname, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( + calls[call_idx].call, snapshot_ops, + (size_t)(op - snapshot_ops), (void *)0, NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_byte_buffer_reader reader; + grpc_byte_buffer_reader_init(&reader, response_payload_recv); + grpc_slice response = grpc_byte_buffer_reader_readall(&reader); + + struct grpc_memory_counters snapshot; + snapshot.total_size_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_absolute; + snapshot.total_allocs_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_absolute; + snapshot.total_size_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_relative; + snapshot.total_allocs_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_relative; + + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + grpc_slice_unref(response); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(response_payload_recv); + grpc_slice_unref(calls[call_idx].details); + calls[call_idx].details = grpc_empty_slice(); + grpc_call_unref(calls[call_idx].call); + calls[call_idx].call = NULL; + + return snapshot; +} + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_slice slice = grpc_slice_from_copied_string("x"); + char *fake_argv[1]; + + const char *target = "localhost:443"; + gpr_cmdline *cl; + grpc_event event; + + grpc_init(); + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + int warmup_iterations = 100; + int benchmark_iterations = 1000; + + cl = gpr_cmdline_create("memory profiling client"); + gpr_cmdline_add_string(cl, "target", "Target host:port", &target); + gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations); + gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations", + &benchmark_iterations); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) { + calls[k].details = grpc_empty_slice(); + } + + cq = grpc_completion_queue_create_for_next(NULL); + + struct grpc_memory_counters client_channel_start = + grpc_memory_counters_snapshot(); + channel = grpc_insecure_channel_create(target, NULL, NULL); + + int call_idx = 0; + + struct grpc_memory_counters before_server_create = send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation")); + struct grpc_memory_counters after_server_create = send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation")); + + // warmup period + for (int i = 0; i < warmup_iterations; i++) { + send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); + } + + for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_benchmark_calls_start = + send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); + + struct grpc_memory_counters client_benchmark_calls_start = + grpc_memory_counters_snapshot(); + + // benchmark period + for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters client_calls_inflight = + grpc_memory_counters_snapshot(); + + struct grpc_memory_counters server_calls_inflight = send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/DestroyCalls")); + + do { + event = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(10000, GPR_TIMESPAN)), + NULL); + } while (event.type != GRPC_QUEUE_TIMEOUT); + + // second step - recv status and destroy call + for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations; + ++call_idx) { + finish_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_calls_end = send_snapshot_request( + 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); + + struct grpc_memory_counters client_channel_end = + grpc_memory_counters_snapshot(); + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + + do { + event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + } while (event.type != GRPC_QUEUE_SHUTDOWN); + grpc_slice_unref(slice); + + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + + gpr_log(GPR_INFO, "---------client stats--------"); + gpr_log(GPR_INFO, "client call memory usage: %f bytes per call", + (double)(client_calls_inflight.total_size_relative - + client_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "client channel memory usage %zi bytes", + client_channel_end.total_size_relative - + client_channel_start.total_size_relative); + + gpr_log(GPR_INFO, "---------server stats--------"); + gpr_log(GPR_INFO, "server create: %zi bytes", + after_server_create.total_size_relative - + before_server_create.total_size_relative); + gpr_log(GPR_INFO, "server call memory usage: %f bytes per call", + (double)(server_calls_inflight.total_size_relative - + server_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "server channel memory usage %zi bytes", + server_calls_end.total_size_relative - + after_server_create.total_size_relative); + + const char *csv_file = "memory_usage.csv"; + FILE *csv = fopen(csv_file, "w"); + if (csv) { + char *env_build = gpr_getenv("BUILD_NUMBER"); + char *env_job = gpr_getenv("JOB_NAME"); + fprintf(csv, "%f,%zi,%zi,%f,%zi,%s,%s\n", + (double)(client_calls_inflight.total_size_relative - + client_benchmark_calls_start.total_size_relative) / + benchmark_iterations, + client_channel_end.total_size_relative - + client_channel_start.total_size_relative, + after_server_create.total_size_relative - + before_server_create.total_size_relative, + (double)(server_calls_inflight.total_size_relative - + server_benchmark_calls_start.total_size_relative) / + benchmark_iterations, + server_calls_end.total_size_relative - + after_server_create.total_size_relative, + env_build == NULL ? "" : env_build, env_job == NULL ? "" : env_job); + fclose(csv); + gpr_log(GPR_INFO, "Summary written to %s", csv_file); + } + + grpc_memory_counters_destroy(); + return 0; +} diff --git a/test/core/memory_usage/memory_usage_test.c b/test/core/memory_usage/memory_usage_test.c deleted file mode 100644 index f4ee6c65e3..0000000000 --- a/test/core/memory_usage/memory_usage_test.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/support/string.h" -#include "test/core/util/port.h" - -int main(int argc, char **argv) { - char *me = argv[0]; - char *lslash = strrchr(me, '/'); - char root[1024]; - int port = grpc_pick_unused_port_or_die(); - char *args[10]; - int status; - gpr_subprocess *svr, *cli; - /* figure out where we are */ - if (lslash) { - memcpy(root, me, (size_t)(lslash - me)); - root[lslash - me] = 0; - } else { - strcpy(root, "."); - } - /* start the server */ - gpr_asprintf(&args[0], "%s/memory_profile_server%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--bind"; - gpr_join_host_port(&args[2], "::", port); - args[3] = "--no-secure"; - svr = gpr_subprocess_create(4, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* start the client */ - gpr_asprintf(&args[0], "%s/memory_profile_client%s", root, - gpr_subprocess_binary_extension()); - args[1] = "--target"; - gpr_join_host_port(&args[2], "127.0.0.1", port); - args[3] = "--warmup=1000"; - args[4] = "--benchmark=9000"; - cli = gpr_subprocess_create(5, (const char **)args); - gpr_free(args[0]); - gpr_free(args[2]); - - /* wait for completion */ - printf("waiting for client\n"); - if ((status = gpr_subprocess_join(cli))) { - gpr_subprocess_destroy(cli); - gpr_subprocess_destroy(svr); - return status; - } - gpr_subprocess_destroy(cli); - - gpr_subprocess_interrupt(svr); - status = gpr_subprocess_join(svr); - gpr_subprocess_destroy(svr); - return status; -} diff --git a/test/core/memory_usage/memory_usage_test.cc b/test/core/memory_usage/memory_usage_test.cc new file mode 100644 index 0000000000..7bf165719b --- /dev/null +++ b/test/core/memory_usage/memory_usage_test.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + gpr_subprocess *svr, *cli; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + gpr_asprintf(&args[0], "%s/memory_profile_server%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--bind"); + gpr_join_host_port(&args[2], "::", port); + args[3] = const_cast("--no-secure"); + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* start the client */ + gpr_asprintf(&args[0], "%s/memory_profile_client%s", root, + gpr_subprocess_binary_extension()); + args[1] = const_cast("--target"); + gpr_join_host_port(&args[2], "127.0.0.1", port); + args[3] = const_cast("--warmup=1000"); + args[4] = const_cast("--benchmark=9000"); + cli = gpr_subprocess_create(5, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* wait for completion */ + printf("waiting for client\n"); + if ((status = gpr_subprocess_join(cli))) { + gpr_subprocess_destroy(cli); + gpr_subprocess_destroy(svr); + return status; + } + gpr_subprocess_destroy(cli); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c deleted file mode 100644 index b25341ead2..0000000000 --- a/test/core/memory_usage/server.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#ifndef _WIN32 -/* This is for _exit() below, which is temporary. */ -#include -#endif - -#include -#include -#include -#include -#include -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/memory_counters.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static grpc_completion_queue *cq; -static grpc_server *server; -static grpc_op metadata_ops[2]; -static grpc_op snapshot_ops[5]; -static grpc_op status_op; -static int got_sigint = 0; -static grpc_byte_buffer *payload_buffer = NULL; -static grpc_byte_buffer *terminal_buffer = NULL; -static int was_cancelled = 2; - -static void *tag(intptr_t t) { return (void *)t; } - -typedef enum { - FLING_SERVER_NEW_REQUEST = 1, - FLING_SERVER_SEND_INIT_METADATA, - FLING_SERVER_WAIT_FOR_DESTROY, - FLING_SERVER_SEND_STATUS_FLING_CALL, - FLING_SERVER_SEND_STATUS_SNAPSHOT, - FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL -} fling_server_tags; - -typedef struct { - fling_server_tags state; - grpc_call *call; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_send; -} fling_call; - -// hold up to 10000 calls and 6 snaphost calls -static fling_call calls[100006]; - -static void request_call_unary(int call_idx) { - if (call_idx == (int)(sizeof(calls) / sizeof(fling_call))) { - gpr_log(GPR_INFO, "Used all call slots (10000) on server. Server exit."); - _exit(0); - } - grpc_metadata_array_init(&calls[call_idx].request_metadata_recv); - grpc_server_request_call( - server, &calls[call_idx].call, &calls[call_idx].call_details, - &calls[call_idx].request_metadata_recv, cq, cq, &calls[call_idx]); -} - -static void send_initial_metadata_unary(void *tag) { - grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); - metadata_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - metadata_ops[0].data.send_initial_metadata.count = 0; - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, - metadata_ops, 1, tag, NULL)); -} - -static void send_status(void *tag) { - status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; - status_op.data.send_status_from_server.status = GRPC_STATUS_OK; - status_op.data.send_status_from_server.trailing_metadata_count = 0; - grpc_slice details = grpc_slice_from_static_string(""); - status_op.data.send_status_from_server.status_details = &details; - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, - &status_op, 1, tag, NULL)); -} - -static void send_snapshot(void *tag, struct grpc_memory_counters *snapshot) { - grpc_op *op; - - grpc_slice snapshot_slice = - grpc_slice_new(snapshot, sizeof(*snapshot), gpr_free); - payload_buffer = grpc_raw_byte_buffer_create(&snapshot_slice, 1); - grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); - - op = snapshot_ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &terminal_buffer; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - if (payload_buffer == NULL) { - gpr_log(GPR_INFO, "NULL payload buffer !!!"); - } - op->data.send_message.send_message = payload_buffer; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.trailing_metadata_count = 0; - grpc_slice details = grpc_slice_from_static_string(""); - op->data.send_status_from_server.status_details = &details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_batch((*(fling_call *)tag).call, snapshot_ops, - (size_t)(op - snapshot_ops), tag, NULL)); -} -/* We have some sort of deadlock, so let's not exit gracefully for now. - When that is resolved, please remove the #include above. */ -static void sigint_handler(int x) { _exit(0); } - -int main(int argc, char **argv) { - grpc_memory_counters_init(); - grpc_event ev; - char *addr_buf = NULL; - gpr_cmdline *cl; - grpc_completion_queue *shutdown_cq; - int shutdown_started = 0; - int shutdown_finished = 0; - - int secure = 0; - char *addr = NULL; - - char *fake_argv[1]; - - GPR_ASSERT(argc >= 1); - fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); - - grpc_init(); - srand((unsigned)clock()); - - cl = gpr_cmdline_create("fling server"); - gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); - gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); - gpr_cmdline_parse(cl, argc, argv); - gpr_cmdline_destroy(cl); - - if (addr == NULL) { - gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); - addr = addr_buf; - } - gpr_log(GPR_INFO, "creating server on: %s", addr); - - cq = grpc_completion_queue_create_for_next(NULL); - - struct grpc_memory_counters before_server_create = - grpc_memory_counters_snapshot(); - if (secure) { - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *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); - } else { - server = grpc_server_create(NULL, NULL); - GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); - } - - grpc_server_register_completion_queue(server, cq, NULL); - grpc_server_start(server); - - struct grpc_memory_counters after_server_create = - grpc_memory_counters_snapshot(); - - gpr_free(addr_buf); - addr = addr_buf = NULL; - - // initialize call instances - for (int i = 0; i < (int)(sizeof(calls) / sizeof(fling_call)); i++) { - grpc_call_details_init(&calls[i].call_details); - calls[i].state = FLING_SERVER_NEW_REQUEST; - } - - int next_call_idx = 0; - struct grpc_memory_counters current_snapshot; - - request_call_unary(next_call_idx); - - signal(SIGINT, sigint_handler); - - while (!shutdown_finished) { - if (got_sigint && !shutdown_started) { - gpr_log(GPR_INFO, "Shutting down due to SIGINT"); - - shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); - GPR_ASSERT( - grpc_completion_queue_pluck(shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), NULL) - .type == GRPC_OP_COMPLETE); - grpc_completion_queue_destroy(shutdown_cq); - 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); - fling_call *s = ev.tag; - switch (ev.type) { - case GRPC_OP_COMPLETE: - switch (s->state) { - case FLING_SERVER_NEW_REQUEST: - request_call_unary(++next_call_idx); - if (0 == grpc_slice_str_cmp(s->call_details.method, - "/Reflector/reflectUnary")) { - s->state = FLING_SERVER_SEND_INIT_METADATA; - send_initial_metadata_unary(s); - } else if (0 == - grpc_slice_str_cmp(s->call_details.method, - "Reflector/GetBeforeSvrCreation")) { - s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; - send_snapshot(s, &before_server_create); - } else if (0 == - grpc_slice_str_cmp(s->call_details.method, - "Reflector/GetAfterSvrCreation")) { - s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; - send_snapshot(s, &after_server_create); - } else if (0 == grpc_slice_str_cmp(s->call_details.method, - "Reflector/SimpleSnapshot")) { - s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; - current_snapshot = grpc_memory_counters_snapshot(); - send_snapshot(s, ¤t_snapshot); - } else if (0 == grpc_slice_str_cmp(s->call_details.method, - "Reflector/DestroyCalls")) { - s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL; - current_snapshot = grpc_memory_counters_snapshot(); - send_snapshot(s, ¤t_snapshot); - } else { - gpr_log(GPR_ERROR, "Wrong call method"); - } - break; - case FLING_SERVER_SEND_INIT_METADATA: - s->state = FLING_SERVER_WAIT_FOR_DESTROY; - break; - case FLING_SERVER_WAIT_FOR_DESTROY: - break; - case FLING_SERVER_SEND_STATUS_FLING_CALL: - grpc_call_unref(s->call); - grpc_call_details_destroy(&s->call_details); - grpc_metadata_array_destroy(&s->initial_metadata_send); - grpc_metadata_array_destroy(&s->request_metadata_recv); - break; - case FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL: - for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); - ++k) { - if (calls[k].state == FLING_SERVER_WAIT_FOR_DESTROY) { - calls[k].state = FLING_SERVER_SEND_STATUS_FLING_CALL; - send_status(&calls[k]); - } - } - // no break here since we want to continue to case - // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call - case FLING_SERVER_SEND_STATUS_SNAPSHOT: - grpc_byte_buffer_destroy(payload_buffer); - grpc_byte_buffer_destroy(terminal_buffer); - grpc_call_unref(s->call); - grpc_call_details_destroy(&s->call_details); - grpc_metadata_array_destroy(&s->initial_metadata_send); - grpc_metadata_array_destroy(&s->request_metadata_recv); - terminal_buffer = NULL; - payload_buffer = NULL; - break; - } - break; - case GRPC_QUEUE_SHUTDOWN: - GPR_ASSERT(shutdown_started); - shutdown_finished = 1; - break; - case GRPC_QUEUE_TIMEOUT: - break; - } - } - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_shutdown(); - grpc_memory_counters_destroy(); - return 0; -} diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc new file mode 100644 index 0000000000..8dee58e274 --- /dev/null +++ b/test/core/memory_usage/server.cc @@ -0,0 +1,315 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#ifndef _WIN32 +/* This is for _exit() below, which is temporary. */ +#include +#endif + +#include +#include +#include +#include +#include +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static grpc_completion_queue *cq; +static grpc_server *server; +static grpc_op metadata_ops[2]; +static grpc_op snapshot_ops[5]; +static grpc_op status_op; +static int got_sigint = 0; +static grpc_byte_buffer *payload_buffer = NULL; +static grpc_byte_buffer *terminal_buffer = NULL; +static int was_cancelled = 2; + +static void *tag(intptr_t t) { return (void *)t; } + +typedef enum { + FLING_SERVER_NEW_REQUEST = 1, + FLING_SERVER_SEND_INIT_METADATA, + FLING_SERVER_WAIT_FOR_DESTROY, + FLING_SERVER_SEND_STATUS_FLING_CALL, + FLING_SERVER_SEND_STATUS_SNAPSHOT, + FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL +} fling_server_tags; + +typedef struct { + fling_server_tags state; + grpc_call *call; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_send; +} fling_call; + +// hold up to 10000 calls and 6 snaphost calls +static fling_call calls[100006]; + +static void request_call_unary(int call_idx) { + if (call_idx == (int)(sizeof(calls) / sizeof(fling_call))) { + gpr_log(GPR_INFO, "Used all call slots (10000) on server. Server exit."); + _exit(0); + } + grpc_metadata_array_init(&calls[call_idx].request_metadata_recv); + grpc_server_request_call( + server, &calls[call_idx].call, &calls[call_idx].call_details, + &calls[call_idx].request_metadata_recv, cq, cq, &calls[call_idx]); +} + +static void send_initial_metadata_unary(void *tag) { + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + metadata_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; + metadata_ops[0].data.send_initial_metadata.count = 0; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + metadata_ops, 1, tag, NULL)); +} + +static void send_status(void *tag) { + status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; + status_op.data.send_status_from_server.status = GRPC_STATUS_OK; + status_op.data.send_status_from_server.trailing_metadata_count = 0; + grpc_slice details = grpc_slice_from_static_string(""); + status_op.data.send_status_from_server.status_details = &details; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + &status_op, 1, tag, NULL)); +} + +static void send_snapshot(void *tag, struct grpc_memory_counters *snapshot) { + grpc_op *op; + + grpc_slice snapshot_slice = + grpc_slice_new(snapshot, sizeof(*snapshot), gpr_free); + payload_buffer = grpc_raw_byte_buffer_create(&snapshot_slice, 1); + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + + op = snapshot_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &terminal_buffer; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + if (payload_buffer == NULL) { + gpr_log(GPR_INFO, "NULL payload buffer !!!"); + } + op->data.send_message.send_message = payload_buffer; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.trailing_metadata_count = 0; + grpc_slice details = grpc_slice_from_static_string(""); + op->data.send_status_from_server.status_details = &details; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op++; + + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_batch((*(fling_call *)tag).call, snapshot_ops, + (size_t)(op - snapshot_ops), tag, NULL)); +} +/* We have some sort of deadlock, so let's not exit gracefully for now. + When that is resolved, please remove the #include above. */ +static void sigint_handler(int x) { _exit(0); } + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_event ev; + char *addr_buf = NULL; + gpr_cmdline *cl; + grpc_completion_queue *shutdown_cq; + int shutdown_started = 0; + int shutdown_finished = 0; + + int secure = 0; + const char *addr = NULL; + + char *fake_argv[1]; + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + grpc_init(); + srand((unsigned)clock()); + + cl = gpr_cmdline_create("fling server"); + gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); + gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + if (addr == NULL) { + gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); + addr = addr_buf; + } + gpr_log(GPR_INFO, "creating server on: %s", addr); + + cq = grpc_completion_queue_create_for_next(NULL); + + struct grpc_memory_counters before_server_create = + grpc_memory_counters_snapshot(); + if (secure) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *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); + } else { + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); + } + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + struct grpc_memory_counters after_server_create = + grpc_memory_counters_snapshot(); + + gpr_free(addr_buf); + addr = addr_buf = NULL; + + // initialize call instances + for (int i = 0; i < (int)(sizeof(calls) / sizeof(fling_call)); i++) { + grpc_call_details_init(&calls[i].call_details); + calls[i].state = FLING_SERVER_NEW_REQUEST; + } + + int next_call_idx = 0; + struct grpc_memory_counters current_snapshot; + + request_call_unary(next_call_idx); + + signal(SIGINT, sigint_handler); + + while (!shutdown_finished) { + if (got_sigint && !shutdown_started) { + gpr_log(GPR_INFO, "Shutting down due to SIGINT"); + + shutdown_cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000)); + GPR_ASSERT( + grpc_completion_queue_pluck(shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_destroy(shutdown_cq); + 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); + fling_call *s = static_cast(ev.tag); + switch (ev.type) { + case GRPC_OP_COMPLETE: + switch (s->state) { + case FLING_SERVER_NEW_REQUEST: + request_call_unary(++next_call_idx); + if (0 == grpc_slice_str_cmp(s->call_details.method, + "/Reflector/reflectUnary")) { + s->state = FLING_SERVER_SEND_INIT_METADATA; + send_initial_metadata_unary(s); + } else if (0 == + grpc_slice_str_cmp(s->call_details.method, + "Reflector/GetBeforeSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &before_server_create); + } else if (0 == + grpc_slice_str_cmp(s->call_details.method, + "Reflector/GetAfterSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &after_server_create); + } else if (0 == grpc_slice_str_cmp(s->call_details.method, + "Reflector/SimpleSnapshot")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else if (0 == grpc_slice_str_cmp(s->call_details.method, + "Reflector/DestroyCalls")) { + s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else { + gpr_log(GPR_ERROR, "Wrong call method"); + } + break; + case FLING_SERVER_SEND_INIT_METADATA: + s->state = FLING_SERVER_WAIT_FOR_DESTROY; + break; + case FLING_SERVER_WAIT_FOR_DESTROY: + break; + case FLING_SERVER_SEND_STATUS_FLING_CALL: + grpc_call_unref(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + break; + case FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL: + for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); + ++k) { + if (calls[k].state == FLING_SERVER_WAIT_FOR_DESTROY) { + calls[k].state = FLING_SERVER_SEND_STATUS_FLING_CALL; + send_status(&calls[k]); + } + } + // no break here since we want to continue to case + // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call + case FLING_SERVER_SEND_STATUS_SNAPSHOT: + grpc_byte_buffer_destroy(payload_buffer); + grpc_byte_buffer_destroy(terminal_buffer); + grpc_call_unref(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + terminal_buffer = NULL; + payload_buffer = NULL; + break; + } + break; + case GRPC_QUEUE_SHUTDOWN: + GPR_ASSERT(shutdown_started); + shutdown_finished = 1; + break; + case GRPC_QUEUE_TIMEOUT: + break; + } + } + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + grpc_memory_counters_destroy(); + return 0; +} diff --git a/test/core/nanopb/fuzzer_response.c b/test/core/nanopb/fuzzer_response.c deleted file mode 100644 index c9b63979a1..0000000000 --- a/test/core/nanopb/fuzzer_response.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include - -#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" - -bool squelch = true; -bool leak_check = true; - -static void dont_log(gpr_log_func_args *args) {} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (squelch) gpr_set_log_function(dont_log); - grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); - grpc_grpclb_initial_response *response; - if ((response = grpc_grpclb_initial_response_parse(slice))) { - grpc_grpclb_initial_response_destroy(response); - } - grpc_slice_unref(slice); - return 0; -} diff --git a/test/core/nanopb/fuzzer_response.cc b/test/core/nanopb/fuzzer_response.cc new file mode 100644 index 0000000000..c9b63979a1 --- /dev/null +++ b/test/core/nanopb/fuzzer_response.cc @@ -0,0 +1,40 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" + +bool squelch = true; +bool leak_check = true; + +static void dont_log(gpr_log_func_args *args) {} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (squelch) gpr_set_log_function(dont_log); + grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); + grpc_grpclb_initial_response *response; + if ((response = grpc_grpclb_initial_response_parse(slice))) { + grpc_grpclb_initial_response_destroy(response); + } + grpc_slice_unref(slice); + return 0; +} diff --git a/test/core/nanopb/fuzzer_serverlist.c b/test/core/nanopb/fuzzer_serverlist.c deleted file mode 100644 index dd70f0c331..0000000000 --- a/test/core/nanopb/fuzzer_serverlist.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include - -#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" - -bool squelch = true; -bool leak_check = true; - -static void dont_log(gpr_log_func_args *args) {} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (squelch) gpr_set_log_function(dont_log); - grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); - grpc_grpclb_serverlist *serverlist; - if ((serverlist = grpc_grpclb_response_parse_serverlist(slice))) { - grpc_grpclb_destroy_serverlist(serverlist); - } - grpc_slice_unref(slice); - return 0; -} diff --git a/test/core/nanopb/fuzzer_serverlist.cc b/test/core/nanopb/fuzzer_serverlist.cc new file mode 100644 index 0000000000..dd70f0c331 --- /dev/null +++ b/test/core/nanopb/fuzzer_serverlist.cc @@ -0,0 +1,40 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" + +bool squelch = true; +bool leak_check = true; + +static void dont_log(gpr_log_func_args *args) {} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (squelch) gpr_set_log_function(dont_log); + grpc_slice slice = grpc_slice_from_copied_buffer((const char *)data, size); + grpc_grpclb_serverlist *serverlist; + if ((serverlist = grpc_grpclb_response_parse_serverlist(slice))) { + grpc_grpclb_destroy_serverlist(serverlist); + } + grpc_slice_unref(slice); + return 0; +} diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c deleted file mode 100644 index 1550003eb9..0000000000 --- a/test/core/network_benchmarks/low_level_ping_pong.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - Basic I/O ping-pong benchmarks. - - The goal here is to establish lower bounds on how fast the stack could get by - measuring the cost of using various I/O strategies to do a basic - request-response loop. - */ - -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" - -typedef struct fd_pair { - int read_fd; - int write_fd; -} fd_pair; - -typedef struct thread_args { - fd_pair fds; - size_t msg_size; - int (*read_bytes)(struct thread_args *args, char *buf); - int (*write_bytes)(struct thread_args *args, char *buf); - int (*setup)(struct thread_args *args); - int epoll_fd; - char *strategy_name; -} thread_args; - -/* - Read strategies - - There are a number of read strategies, each of which has a blocking and - non-blocking version. - */ - -/* Basic call to read() */ -static int read_bytes(int fd, char *buf, size_t read_size, int spin) { - size_t bytes_read = 0; - ssize_t err; - do { - err = read(fd, buf + bytes_read, read_size - bytes_read); - if (err < 0) { - if (errno == EINTR) { - continue; - } else { - if (errno == EAGAIN && spin == 1) { - continue; - } - gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); - return -1; - } - } else { - bytes_read += (size_t)err; - } - } while (bytes_read < read_size); - return 0; -} - -static int blocking_read_bytes(thread_args *args, char *buf) { - return read_bytes(args->fds.read_fd, buf, args->msg_size, 0); -} - -static int spin_read_bytes(thread_args *args, char *buf) { - return read_bytes(args->fds.read_fd, buf, args->msg_size, 1); -} - -/* Call poll() to monitor a non-blocking fd */ -static int poll_read_bytes(int fd, char *buf, size_t read_size, int spin) { - struct pollfd pfd; - size_t bytes_read = 0; - int err; - ssize_t err2; - - pfd.fd = fd; - pfd.events = POLLIN; - do { - err = poll(&pfd, 1, spin ? 0 : -1); - if (err < 0) { - if (errno == EINTR) { - continue; - } else { - gpr_log(GPR_ERROR, "Poll failed: %s", strerror(errno)); - return -1; - } - } - if (err == 0 && spin) continue; - GPR_ASSERT(err == 1); - GPR_ASSERT(pfd.revents == POLLIN); - do { - err2 = read(fd, buf + bytes_read, read_size - bytes_read); - } while (err2 < 0 && errno == EINTR); - if (err2 < 0 && errno != EAGAIN) { - gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); - return -1; - } - bytes_read += (size_t)err2; - } while (bytes_read < read_size); - return 0; -} - -static int poll_read_bytes_blocking(struct thread_args *args, char *buf) { - return poll_read_bytes(args->fds.read_fd, buf, args->msg_size, 0); -} - -static int poll_read_bytes_spin(struct thread_args *args, char *buf) { - return poll_read_bytes(args->fds.read_fd, buf, args->msg_size, 1); -} - -#ifdef __linux__ -/* Call epoll_wait() to monitor a non-blocking fd */ -static int epoll_read_bytes(struct thread_args *args, char *buf, int spin) { - struct epoll_event ev; - size_t bytes_read = 0; - int err; - ssize_t err2; - size_t read_size = args->msg_size; - - do { - err = epoll_wait(args->epoll_fd, &ev, 1, spin ? 0 : -1); - if (err < 0) { - if (errno == EINTR) continue; - gpr_log(GPR_ERROR, "epoll_wait failed: %s", strerror(errno)); - return -1; - } - if (err == 0 && spin) continue; - GPR_ASSERT(err == 1); - GPR_ASSERT(ev.events & EPOLLIN); - GPR_ASSERT(ev.data.fd == args->fds.read_fd); - do { - do { - err2 = - read(args->fds.read_fd, buf + bytes_read, read_size - bytes_read); - } while (err2 < 0 && errno == EINTR); - if (errno == EAGAIN) break; - bytes_read += (size_t)err2; - /* TODO(klempner): This should really be doing an extra call after we are - done to ensure we see an EAGAIN */ - } while (bytes_read < read_size); - } while (bytes_read < read_size); - GPR_ASSERT(bytes_read == read_size); - return 0; -} - -static int epoll_read_bytes_blocking(struct thread_args *args, char *buf) { - return epoll_read_bytes(args, buf, 0); -} - -static int epoll_read_bytes_spin(struct thread_args *args, char *buf) { - return epoll_read_bytes(args, buf, 1); -} -#endif /* __linux__ */ - -/* Write out bytes. - At this point we only have one strategy, since in the common case these - writes go directly out to the kernel. - */ -static int blocking_write_bytes(struct thread_args *args, char *buf) { - size_t bytes_written = 0; - ssize_t err; - size_t write_size = args->msg_size; - do { - err = write(args->fds.write_fd, buf + bytes_written, - write_size - bytes_written); - if (err < 0) { - if (errno == EINTR) { - continue; - } else { - gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); - return -1; - } - } else { - bytes_written += (size_t)err; - } - } while (bytes_written < write_size); - return 0; -} - -/* - Initialization code - - These are called at the beginning of the client and server thread, depending - on the scenario we're using. - */ -static int set_socket_nonblocking(thread_args *args) { - if (!GRPC_LOG_IF_ERROR("Unable to set read socket nonblocking", - grpc_set_socket_nonblocking(args->fds.read_fd, 1))) { - return -1; - } - if (!GRPC_LOG_IF_ERROR("Unable to set write socket nonblocking", - grpc_set_socket_nonblocking(args->fds.write_fd, 1))) { - return -1; - } - return 0; -} - -static int do_nothing(thread_args *args) { return 0; } - -#ifdef __linux__ -/* Special case for epoll, where we need to create the fd ahead of time. */ -static int epoll_setup(thread_args *args) { - int epoll_fd; - struct epoll_event ev; - set_socket_nonblocking(args); - epoll_fd = epoll_create(1); - if (epoll_fd < 0) { - gpr_log(GPR_ERROR, "epoll_create: %s", strerror(errno)); - return -1; - } - - args->epoll_fd = epoll_fd; - - ev.events = EPOLLIN | EPOLLET; - ev.data.fd = args->fds.read_fd; - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->fds.read_fd, &ev) < 0) { - gpr_log(GPR_ERROR, "epoll_ctl: %s", strerror(errno)); - } - return 0; -} -#endif - -static void server_thread(thread_args *args) { - char *buf = gpr_malloc(args->msg_size); - if (args->setup(args) < 0) { - gpr_log(GPR_ERROR, "Setup failed"); - } - for (;;) { - if (args->read_bytes(args, buf) < 0) { - gpr_log(GPR_ERROR, "Server read failed"); - gpr_free(buf); - return; - } - if (args->write_bytes(args, buf) < 0) { - gpr_log(GPR_ERROR, "Server write failed"); - gpr_free(buf); - return; - } - } -} - -static void server_thread_wrap(void *arg) { - thread_args *args = arg; - server_thread(args); -} - -static void print_histogram(gpr_histogram *histogram) { - /* TODO(klempner): Print more detailed information, such as detailed histogram - buckets */ - gpr_log(GPR_INFO, "latency (50/95/99/99.9): %f/%f/%f/%f", - gpr_histogram_percentile(histogram, 50), - gpr_histogram_percentile(histogram, 95), - gpr_histogram_percentile(histogram, 99), - gpr_histogram_percentile(histogram, 99.9)); -} - -static double now(void) { - gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME); - return 1e9 * (double)tv.tv_sec + (double)tv.tv_nsec; -} - -static void client_thread(thread_args *args) { - char *buf = gpr_malloc(args->msg_size * sizeof(char)); - memset(buf, 0, args->msg_size * sizeof(char)); - gpr_histogram *histogram = gpr_histogram_create(0.01, 60e9); - double start_time; - double end_time; - double interval; - const int kNumIters = 100000; - int i; - - if (args->setup(args) < 0) { - gpr_log(GPR_ERROR, "Setup failed"); - } - for (i = 0; i < kNumIters; ++i) { - start_time = now(); - if (args->write_bytes(args, buf) < 0) { - gpr_log(GPR_ERROR, "Client write failed"); - goto error; - } - if (args->read_bytes(args, buf) < 0) { - gpr_log(GPR_ERROR, "Client read failed"); - goto error; - } - end_time = now(); - if (i > kNumIters / 2) { - interval = end_time - start_time; - gpr_histogram_add(histogram, interval); - } - } - print_histogram(histogram); -error: - gpr_free(buf); - gpr_histogram_destroy(histogram); -} - -/* This roughly matches tcp_server's create_listening_socket */ -static int create_listening_socket(struct sockaddr *port, socklen_t len) { - int fd = socket(port->sa_family, SOCK_STREAM, 0); - if (fd < 0) { - gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); - goto error; - } - - if (!GRPC_LOG_IF_ERROR("Failed to set listening socket cloexec", - grpc_set_socket_cloexec(fd, 1))) { - goto error; - } - if (!GRPC_LOG_IF_ERROR("Failed to set listening socket low latency", - grpc_set_socket_low_latency(fd, 1))) { - goto error; - } - if (!GRPC_LOG_IF_ERROR("Failed to set listening socket reuse addr", - grpc_set_socket_reuse_addr(fd, 1))) { - goto error; - } - - if (bind(fd, port, len) < 0) { - gpr_log(GPR_ERROR, "bind: %s", strerror(errno)); - goto error; - } - - if (listen(fd, 1) < 0) { - gpr_log(GPR_ERROR, "listen: %s", strerror(errno)); - goto error; - } - - if (getsockname(fd, port, &len) < 0) { - gpr_log(GPR_ERROR, "getsockname: %s", strerror(errno)); - goto error; - } - - return fd; - -error: - if (fd >= 0) { - close(fd); - } - return -1; -} - -static int connect_client(struct sockaddr *addr, socklen_t len) { - int fd = socket(addr->sa_family, SOCK_STREAM, 0); - int err; - if (fd < 0) { - gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); - goto error; - } - - if (!GRPC_LOG_IF_ERROR("Failed to set connecting socket cloexec", - grpc_set_socket_cloexec(fd, 1))) { - goto error; - } - if (!GRPC_LOG_IF_ERROR("Failed to set connecting socket low latency", - grpc_set_socket_low_latency(fd, 1))) { - goto error; - } - - do { - err = connect(fd, addr, len); - } while (err < 0 && errno == EINTR); - - if (err < 0) { - gpr_log(GPR_ERROR, "connect error: %s", strerror(errno)); - goto error; - } - return fd; - -error: - if (fd >= 0) { - close(fd); - } - return -1; -} - -static int accept_server(int listen_fd) { - int fd = accept(listen_fd, NULL, NULL); - if (fd < 0) { - gpr_log(GPR_ERROR, "Accept failed: %s", strerror(errno)); - return -1; - } - return fd; -} - -static int create_sockets_tcp(fd_pair *client_fds, fd_pair *server_fds) { - int listen_fd = -1; - int client_fd = -1; - int server_fd = -1; - - struct sockaddr_in port; - struct sockaddr *sa_port = (struct sockaddr *)&port; - - port.sin_family = AF_INET; - port.sin_port = 0; - port.sin_addr.s_addr = INADDR_ANY; - - listen_fd = create_listening_socket(sa_port, sizeof(port)); - if (listen_fd == -1) { - gpr_log(GPR_ERROR, "Listen failed"); - goto error; - } - - client_fd = connect_client(sa_port, sizeof(port)); - if (client_fd == -1) { - gpr_log(GPR_ERROR, "Connect failed"); - goto error; - } - - server_fd = accept_server(listen_fd); - if (server_fd == -1) { - gpr_log(GPR_ERROR, "Accept failed"); - goto error; - } - - client_fds->read_fd = client_fd; - client_fds->write_fd = client_fd; - server_fds->read_fd = server_fd; - server_fds->write_fd = server_fd; - close(listen_fd); - return 0; - -error: - if (listen_fd != -1) { - close(listen_fd); - } - if (client_fd != -1) { - close(client_fd); - } - if (server_fd != -1) { - close(server_fd); - } - return -1; -} - -static int create_sockets_socketpair(fd_pair *client_fds, fd_pair *server_fds) { - int fds[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - gpr_log(GPR_ERROR, "socketpair: %s", strerror(errno)); - return -1; - } - - client_fds->read_fd = fds[0]; - client_fds->write_fd = fds[0]; - server_fds->read_fd = fds[1]; - server_fds->write_fd = fds[1]; - return 0; -} - -static int create_sockets_pipe(fd_pair *client_fds, fd_pair *server_fds) { - int cfds[2]; - int sfds[2]; - if (pipe(cfds) < 0) { - gpr_log(GPR_ERROR, "pipe: %s", strerror(errno)); - return -1; - } - - if (pipe(sfds) < 0) { - gpr_log(GPR_ERROR, "pipe: %s", strerror(errno)); - return -1; - } - - client_fds->read_fd = cfds[0]; - client_fds->write_fd = cfds[1]; - server_fds->read_fd = sfds[0]; - server_fds->write_fd = sfds[1]; - return 0; -} - -static const char *read_strategy_usage = - "Strategy for doing reads, which is one of:\n" - " blocking: blocking read calls\n" - " same_thread_poll: poll() call on same thread \n" -#ifdef __linux__ - " same_thread_epoll: epoll_wait() on same thread \n" -#endif - " spin_read: spinning non-blocking read() calls \n" - " spin_poll: spinning 0 timeout poll() calls \n" -#ifdef __linux__ - " spin_epoll: spinning 0 timeout epoll_wait() calls \n" -#endif - ""; - -static const char *socket_type_usage = - "Type of socket used, one of:\n" - " tcp: fds are endpoints of a TCP connection\n" - " socketpair: fds come from socketpair()\n" - " pipe: fds come from pipe()\n"; - -void print_usage(char *argv0) { - fprintf(stderr, "%s usage:\n\n", argv0); - fprintf(stderr, "%s read_strategy socket_type msg_size\n\n", argv0); - fprintf(stderr, "where read_strategy is one of:\n"); - fprintf(stderr, " blocking: blocking read calls\n"); - fprintf(stderr, " same_thread_poll: poll() call on same thread \n"); -#ifdef __linux__ - fprintf(stderr, " same_thread_epoll: epoll_wait() on same thread \n"); -#endif - fprintf(stderr, " spin_read: spinning non-blocking read() calls \n"); - fprintf(stderr, " spin_poll: spinning 0 timeout poll() calls \n"); -#ifdef __linux__ - fprintf(stderr, " spin_epoll: spinning 0 timeout epoll_wait() calls \n"); -#endif - fprintf(stderr, "and socket_type is one of:\n"); - fprintf(stderr, " tcp: fds are endpoints of a TCP connection\n"); - fprintf(stderr, " socketpair: fds come from socketpair()\n"); - fprintf(stderr, " pipe: fds come from pipe()\n"); -} - -typedef struct test_strategy { - char *name; - int (*read_strategy)(struct thread_args *args, char *buf); - int (*setup)(struct thread_args *args); -} test_strategy; - -static test_strategy test_strategies[] = { - {"blocking", blocking_read_bytes, do_nothing}, - {"same_thread_poll", poll_read_bytes_blocking, set_socket_nonblocking}, -#ifdef __linux__ - {"same_thread_epoll", epoll_read_bytes_blocking, epoll_setup}, - {"spin_epoll", epoll_read_bytes_spin, epoll_setup}, -#endif /* __linux__ */ - {"spin_read", spin_read_bytes, set_socket_nonblocking}, - {"spin_poll", poll_read_bytes_spin, set_socket_nonblocking}}; - -static char *socket_types[] = {"tcp", "socketpair", "pipe"}; - -int create_socket(char *socket_type, fd_pair *client_fds, fd_pair *server_fds) { - if (strcmp(socket_type, "tcp") == 0) { - create_sockets_tcp(client_fds, server_fds); - } else if (strcmp(socket_type, "socketpair") == 0) { - create_sockets_socketpair(client_fds, server_fds); - } else if (strcmp(socket_type, "pipe") == 0) { - create_sockets_pipe(client_fds, server_fds); - } else { - fprintf(stderr, "Invalid socket type %s\n", socket_type); - return -1; - } - return 0; -} - -static int run_benchmark(char *socket_type, thread_args *client_args, - thread_args *server_args) { - gpr_thd_id tid; - int rv = 0; - - rv = create_socket(socket_type, &client_args->fds, &server_args->fds); - if (rv < 0) { - return rv; - } - - gpr_log(GPR_INFO, "Starting test %s %s %zu", client_args->strategy_name, - socket_type, client_args->msg_size); - - gpr_thd_new(&tid, server_thread_wrap, server_args, NULL); - client_thread(client_args); - return 0; -} - -static int run_all_benchmarks(size_t msg_size) { - int error = 0; - size_t i; - for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { - test_strategy *strategy = &test_strategies[i]; - size_t j; - for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) { - thread_args *client_args = gpr_malloc(sizeof(thread_args)); - thread_args *server_args = gpr_malloc(sizeof(thread_args)); - char *socket_type = socket_types[j]; - - client_args->read_bytes = strategy->read_strategy; - client_args->write_bytes = blocking_write_bytes; - client_args->setup = strategy->setup; - client_args->msg_size = msg_size; - client_args->strategy_name = strategy->name; - server_args->read_bytes = strategy->read_strategy; - server_args->write_bytes = blocking_write_bytes; - server_args->setup = strategy->setup; - server_args->msg_size = msg_size; - server_args->strategy_name = strategy->name; - error = run_benchmark(socket_type, client_args, server_args); - if (error < 0) { - return error; - } - } - } - return error; -} - -int main(int argc, char **argv) { - thread_args *client_args = gpr_malloc(sizeof(thread_args)); - thread_args *server_args = gpr_malloc(sizeof(thread_args)); - int msg_size = -1; - char *read_strategy = NULL; - char *socket_type = NULL; - size_t i; - const test_strategy *strategy = NULL; - int error = 0; - - gpr_cmdline *cmdline = - gpr_cmdline_create("low_level_ping_pong network benchmarking tool"); - - gpr_cmdline_add_int(cmdline, "msg_size", "Size of sent messages", &msg_size); - gpr_cmdline_add_string(cmdline, "read_strategy", read_strategy_usage, - &read_strategy); - gpr_cmdline_add_string(cmdline, "socket_type", socket_type_usage, - &socket_type); - - gpr_cmdline_parse(cmdline, argc, argv); - - if (msg_size == -1) { - msg_size = 50; - } - - if (read_strategy == NULL) { - gpr_log(GPR_INFO, "No strategy specified, running all benchmarks"); - return run_all_benchmarks((size_t)msg_size); - } - - if (socket_type == NULL) { - socket_type = "tcp"; - } - if (msg_size <= 0) { - fprintf(stderr, "msg_size must be > 0\n"); - print_usage(argv[0]); - return -1; - } - - for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { - if (strcmp(test_strategies[i].name, read_strategy) == 0) { - strategy = &test_strategies[i]; - } - } - if (strategy == NULL) { - fprintf(stderr, "Invalid read strategy %s\n", read_strategy); - return -1; - } - - client_args->read_bytes = strategy->read_strategy; - client_args->write_bytes = blocking_write_bytes; - client_args->setup = strategy->setup; - client_args->msg_size = (size_t)msg_size; - client_args->strategy_name = read_strategy; - server_args->read_bytes = strategy->read_strategy; - server_args->write_bytes = blocking_write_bytes; - server_args->setup = strategy->setup; - server_args->msg_size = (size_t)msg_size; - server_args->strategy_name = read_strategy; - - error = run_benchmark(socket_type, client_args, server_args); - - gpr_cmdline_destroy(cmdline); - return error; -} diff --git a/test/core/network_benchmarks/low_level_ping_pong.cc b/test/core/network_benchmarks/low_level_ping_pong.cc new file mode 100644 index 0000000000..1550003eb9 --- /dev/null +++ b/test/core/network_benchmarks/low_level_ping_pong.cc @@ -0,0 +1,684 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + Basic I/O ping-pong benchmarks. + + The goal here is to establish lower bounds on how fast the stack could get by + measuring the cost of using various I/O strategies to do a basic + request-response loop. + */ + +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" + +typedef struct fd_pair { + int read_fd; + int write_fd; +} fd_pair; + +typedef struct thread_args { + fd_pair fds; + size_t msg_size; + int (*read_bytes)(struct thread_args *args, char *buf); + int (*write_bytes)(struct thread_args *args, char *buf); + int (*setup)(struct thread_args *args); + int epoll_fd; + char *strategy_name; +} thread_args; + +/* + Read strategies + + There are a number of read strategies, each of which has a blocking and + non-blocking version. + */ + +/* Basic call to read() */ +static int read_bytes(int fd, char *buf, size_t read_size, int spin) { + size_t bytes_read = 0; + ssize_t err; + do { + err = read(fd, buf + bytes_read, read_size - bytes_read); + if (err < 0) { + if (errno == EINTR) { + continue; + } else { + if (errno == EAGAIN && spin == 1) { + continue; + } + gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); + return -1; + } + } else { + bytes_read += (size_t)err; + } + } while (bytes_read < read_size); + return 0; +} + +static int blocking_read_bytes(thread_args *args, char *buf) { + return read_bytes(args->fds.read_fd, buf, args->msg_size, 0); +} + +static int spin_read_bytes(thread_args *args, char *buf) { + return read_bytes(args->fds.read_fd, buf, args->msg_size, 1); +} + +/* Call poll() to monitor a non-blocking fd */ +static int poll_read_bytes(int fd, char *buf, size_t read_size, int spin) { + struct pollfd pfd; + size_t bytes_read = 0; + int err; + ssize_t err2; + + pfd.fd = fd; + pfd.events = POLLIN; + do { + err = poll(&pfd, 1, spin ? 0 : -1); + if (err < 0) { + if (errno == EINTR) { + continue; + } else { + gpr_log(GPR_ERROR, "Poll failed: %s", strerror(errno)); + return -1; + } + } + if (err == 0 && spin) continue; + GPR_ASSERT(err == 1); + GPR_ASSERT(pfd.revents == POLLIN); + do { + err2 = read(fd, buf + bytes_read, read_size - bytes_read); + } while (err2 < 0 && errno == EINTR); + if (err2 < 0 && errno != EAGAIN) { + gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); + return -1; + } + bytes_read += (size_t)err2; + } while (bytes_read < read_size); + return 0; +} + +static int poll_read_bytes_blocking(struct thread_args *args, char *buf) { + return poll_read_bytes(args->fds.read_fd, buf, args->msg_size, 0); +} + +static int poll_read_bytes_spin(struct thread_args *args, char *buf) { + return poll_read_bytes(args->fds.read_fd, buf, args->msg_size, 1); +} + +#ifdef __linux__ +/* Call epoll_wait() to monitor a non-blocking fd */ +static int epoll_read_bytes(struct thread_args *args, char *buf, int spin) { + struct epoll_event ev; + size_t bytes_read = 0; + int err; + ssize_t err2; + size_t read_size = args->msg_size; + + do { + err = epoll_wait(args->epoll_fd, &ev, 1, spin ? 0 : -1); + if (err < 0) { + if (errno == EINTR) continue; + gpr_log(GPR_ERROR, "epoll_wait failed: %s", strerror(errno)); + return -1; + } + if (err == 0 && spin) continue; + GPR_ASSERT(err == 1); + GPR_ASSERT(ev.events & EPOLLIN); + GPR_ASSERT(ev.data.fd == args->fds.read_fd); + do { + do { + err2 = + read(args->fds.read_fd, buf + bytes_read, read_size - bytes_read); + } while (err2 < 0 && errno == EINTR); + if (errno == EAGAIN) break; + bytes_read += (size_t)err2; + /* TODO(klempner): This should really be doing an extra call after we are + done to ensure we see an EAGAIN */ + } while (bytes_read < read_size); + } while (bytes_read < read_size); + GPR_ASSERT(bytes_read == read_size); + return 0; +} + +static int epoll_read_bytes_blocking(struct thread_args *args, char *buf) { + return epoll_read_bytes(args, buf, 0); +} + +static int epoll_read_bytes_spin(struct thread_args *args, char *buf) { + return epoll_read_bytes(args, buf, 1); +} +#endif /* __linux__ */ + +/* Write out bytes. + At this point we only have one strategy, since in the common case these + writes go directly out to the kernel. + */ +static int blocking_write_bytes(struct thread_args *args, char *buf) { + size_t bytes_written = 0; + ssize_t err; + size_t write_size = args->msg_size; + do { + err = write(args->fds.write_fd, buf + bytes_written, + write_size - bytes_written); + if (err < 0) { + if (errno == EINTR) { + continue; + } else { + gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno)); + return -1; + } + } else { + bytes_written += (size_t)err; + } + } while (bytes_written < write_size); + return 0; +} + +/* + Initialization code + + These are called at the beginning of the client and server thread, depending + on the scenario we're using. + */ +static int set_socket_nonblocking(thread_args *args) { + if (!GRPC_LOG_IF_ERROR("Unable to set read socket nonblocking", + grpc_set_socket_nonblocking(args->fds.read_fd, 1))) { + return -1; + } + if (!GRPC_LOG_IF_ERROR("Unable to set write socket nonblocking", + grpc_set_socket_nonblocking(args->fds.write_fd, 1))) { + return -1; + } + return 0; +} + +static int do_nothing(thread_args *args) { return 0; } + +#ifdef __linux__ +/* Special case for epoll, where we need to create the fd ahead of time. */ +static int epoll_setup(thread_args *args) { + int epoll_fd; + struct epoll_event ev; + set_socket_nonblocking(args); + epoll_fd = epoll_create(1); + if (epoll_fd < 0) { + gpr_log(GPR_ERROR, "epoll_create: %s", strerror(errno)); + return -1; + } + + args->epoll_fd = epoll_fd; + + ev.events = EPOLLIN | EPOLLET; + ev.data.fd = args->fds.read_fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->fds.read_fd, &ev) < 0) { + gpr_log(GPR_ERROR, "epoll_ctl: %s", strerror(errno)); + } + return 0; +} +#endif + +static void server_thread(thread_args *args) { + char *buf = gpr_malloc(args->msg_size); + if (args->setup(args) < 0) { + gpr_log(GPR_ERROR, "Setup failed"); + } + for (;;) { + if (args->read_bytes(args, buf) < 0) { + gpr_log(GPR_ERROR, "Server read failed"); + gpr_free(buf); + return; + } + if (args->write_bytes(args, buf) < 0) { + gpr_log(GPR_ERROR, "Server write failed"); + gpr_free(buf); + return; + } + } +} + +static void server_thread_wrap(void *arg) { + thread_args *args = arg; + server_thread(args); +} + +static void print_histogram(gpr_histogram *histogram) { + /* TODO(klempner): Print more detailed information, such as detailed histogram + buckets */ + gpr_log(GPR_INFO, "latency (50/95/99/99.9): %f/%f/%f/%f", + gpr_histogram_percentile(histogram, 50), + gpr_histogram_percentile(histogram, 95), + gpr_histogram_percentile(histogram, 99), + gpr_histogram_percentile(histogram, 99.9)); +} + +static double now(void) { + gpr_timespec tv = gpr_now(GPR_CLOCK_REALTIME); + return 1e9 * (double)tv.tv_sec + (double)tv.tv_nsec; +} + +static void client_thread(thread_args *args) { + char *buf = gpr_malloc(args->msg_size * sizeof(char)); + memset(buf, 0, args->msg_size * sizeof(char)); + gpr_histogram *histogram = gpr_histogram_create(0.01, 60e9); + double start_time; + double end_time; + double interval; + const int kNumIters = 100000; + int i; + + if (args->setup(args) < 0) { + gpr_log(GPR_ERROR, "Setup failed"); + } + for (i = 0; i < kNumIters; ++i) { + start_time = now(); + if (args->write_bytes(args, buf) < 0) { + gpr_log(GPR_ERROR, "Client write failed"); + goto error; + } + if (args->read_bytes(args, buf) < 0) { + gpr_log(GPR_ERROR, "Client read failed"); + goto error; + } + end_time = now(); + if (i > kNumIters / 2) { + interval = end_time - start_time; + gpr_histogram_add(histogram, interval); + } + } + print_histogram(histogram); +error: + gpr_free(buf); + gpr_histogram_destroy(histogram); +} + +/* This roughly matches tcp_server's create_listening_socket */ +static int create_listening_socket(struct sockaddr *port, socklen_t len) { + int fd = socket(port->sa_family, SOCK_STREAM, 0); + if (fd < 0) { + gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); + goto error; + } + + if (!GRPC_LOG_IF_ERROR("Failed to set listening socket cloexec", + grpc_set_socket_cloexec(fd, 1))) { + goto error; + } + if (!GRPC_LOG_IF_ERROR("Failed to set listening socket low latency", + grpc_set_socket_low_latency(fd, 1))) { + goto error; + } + if (!GRPC_LOG_IF_ERROR("Failed to set listening socket reuse addr", + grpc_set_socket_reuse_addr(fd, 1))) { + goto error; + } + + if (bind(fd, port, len) < 0) { + gpr_log(GPR_ERROR, "bind: %s", strerror(errno)); + goto error; + } + + if (listen(fd, 1) < 0) { + gpr_log(GPR_ERROR, "listen: %s", strerror(errno)); + goto error; + } + + if (getsockname(fd, port, &len) < 0) { + gpr_log(GPR_ERROR, "getsockname: %s", strerror(errno)); + goto error; + } + + return fd; + +error: + if (fd >= 0) { + close(fd); + } + return -1; +} + +static int connect_client(struct sockaddr *addr, socklen_t len) { + int fd = socket(addr->sa_family, SOCK_STREAM, 0); + int err; + if (fd < 0) { + gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); + goto error; + } + + if (!GRPC_LOG_IF_ERROR("Failed to set connecting socket cloexec", + grpc_set_socket_cloexec(fd, 1))) { + goto error; + } + if (!GRPC_LOG_IF_ERROR("Failed to set connecting socket low latency", + grpc_set_socket_low_latency(fd, 1))) { + goto error; + } + + do { + err = connect(fd, addr, len); + } while (err < 0 && errno == EINTR); + + if (err < 0) { + gpr_log(GPR_ERROR, "connect error: %s", strerror(errno)); + goto error; + } + return fd; + +error: + if (fd >= 0) { + close(fd); + } + return -1; +} + +static int accept_server(int listen_fd) { + int fd = accept(listen_fd, NULL, NULL); + if (fd < 0) { + gpr_log(GPR_ERROR, "Accept failed: %s", strerror(errno)); + return -1; + } + return fd; +} + +static int create_sockets_tcp(fd_pair *client_fds, fd_pair *server_fds) { + int listen_fd = -1; + int client_fd = -1; + int server_fd = -1; + + struct sockaddr_in port; + struct sockaddr *sa_port = (struct sockaddr *)&port; + + port.sin_family = AF_INET; + port.sin_port = 0; + port.sin_addr.s_addr = INADDR_ANY; + + listen_fd = create_listening_socket(sa_port, sizeof(port)); + if (listen_fd == -1) { + gpr_log(GPR_ERROR, "Listen failed"); + goto error; + } + + client_fd = connect_client(sa_port, sizeof(port)); + if (client_fd == -1) { + gpr_log(GPR_ERROR, "Connect failed"); + goto error; + } + + server_fd = accept_server(listen_fd); + if (server_fd == -1) { + gpr_log(GPR_ERROR, "Accept failed"); + goto error; + } + + client_fds->read_fd = client_fd; + client_fds->write_fd = client_fd; + server_fds->read_fd = server_fd; + server_fds->write_fd = server_fd; + close(listen_fd); + return 0; + +error: + if (listen_fd != -1) { + close(listen_fd); + } + if (client_fd != -1) { + close(client_fd); + } + if (server_fd != -1) { + close(server_fd); + } + return -1; +} + +static int create_sockets_socketpair(fd_pair *client_fds, fd_pair *server_fds) { + int fds[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + gpr_log(GPR_ERROR, "socketpair: %s", strerror(errno)); + return -1; + } + + client_fds->read_fd = fds[0]; + client_fds->write_fd = fds[0]; + server_fds->read_fd = fds[1]; + server_fds->write_fd = fds[1]; + return 0; +} + +static int create_sockets_pipe(fd_pair *client_fds, fd_pair *server_fds) { + int cfds[2]; + int sfds[2]; + if (pipe(cfds) < 0) { + gpr_log(GPR_ERROR, "pipe: %s", strerror(errno)); + return -1; + } + + if (pipe(sfds) < 0) { + gpr_log(GPR_ERROR, "pipe: %s", strerror(errno)); + return -1; + } + + client_fds->read_fd = cfds[0]; + client_fds->write_fd = cfds[1]; + server_fds->read_fd = sfds[0]; + server_fds->write_fd = sfds[1]; + return 0; +} + +static const char *read_strategy_usage = + "Strategy for doing reads, which is one of:\n" + " blocking: blocking read calls\n" + " same_thread_poll: poll() call on same thread \n" +#ifdef __linux__ + " same_thread_epoll: epoll_wait() on same thread \n" +#endif + " spin_read: spinning non-blocking read() calls \n" + " spin_poll: spinning 0 timeout poll() calls \n" +#ifdef __linux__ + " spin_epoll: spinning 0 timeout epoll_wait() calls \n" +#endif + ""; + +static const char *socket_type_usage = + "Type of socket used, one of:\n" + " tcp: fds are endpoints of a TCP connection\n" + " socketpair: fds come from socketpair()\n" + " pipe: fds come from pipe()\n"; + +void print_usage(char *argv0) { + fprintf(stderr, "%s usage:\n\n", argv0); + fprintf(stderr, "%s read_strategy socket_type msg_size\n\n", argv0); + fprintf(stderr, "where read_strategy is one of:\n"); + fprintf(stderr, " blocking: blocking read calls\n"); + fprintf(stderr, " same_thread_poll: poll() call on same thread \n"); +#ifdef __linux__ + fprintf(stderr, " same_thread_epoll: epoll_wait() on same thread \n"); +#endif + fprintf(stderr, " spin_read: spinning non-blocking read() calls \n"); + fprintf(stderr, " spin_poll: spinning 0 timeout poll() calls \n"); +#ifdef __linux__ + fprintf(stderr, " spin_epoll: spinning 0 timeout epoll_wait() calls \n"); +#endif + fprintf(stderr, "and socket_type is one of:\n"); + fprintf(stderr, " tcp: fds are endpoints of a TCP connection\n"); + fprintf(stderr, " socketpair: fds come from socketpair()\n"); + fprintf(stderr, " pipe: fds come from pipe()\n"); +} + +typedef struct test_strategy { + char *name; + int (*read_strategy)(struct thread_args *args, char *buf); + int (*setup)(struct thread_args *args); +} test_strategy; + +static test_strategy test_strategies[] = { + {"blocking", blocking_read_bytes, do_nothing}, + {"same_thread_poll", poll_read_bytes_blocking, set_socket_nonblocking}, +#ifdef __linux__ + {"same_thread_epoll", epoll_read_bytes_blocking, epoll_setup}, + {"spin_epoll", epoll_read_bytes_spin, epoll_setup}, +#endif /* __linux__ */ + {"spin_read", spin_read_bytes, set_socket_nonblocking}, + {"spin_poll", poll_read_bytes_spin, set_socket_nonblocking}}; + +static char *socket_types[] = {"tcp", "socketpair", "pipe"}; + +int create_socket(char *socket_type, fd_pair *client_fds, fd_pair *server_fds) { + if (strcmp(socket_type, "tcp") == 0) { + create_sockets_tcp(client_fds, server_fds); + } else if (strcmp(socket_type, "socketpair") == 0) { + create_sockets_socketpair(client_fds, server_fds); + } else if (strcmp(socket_type, "pipe") == 0) { + create_sockets_pipe(client_fds, server_fds); + } else { + fprintf(stderr, "Invalid socket type %s\n", socket_type); + return -1; + } + return 0; +} + +static int run_benchmark(char *socket_type, thread_args *client_args, + thread_args *server_args) { + gpr_thd_id tid; + int rv = 0; + + rv = create_socket(socket_type, &client_args->fds, &server_args->fds); + if (rv < 0) { + return rv; + } + + gpr_log(GPR_INFO, "Starting test %s %s %zu", client_args->strategy_name, + socket_type, client_args->msg_size); + + gpr_thd_new(&tid, server_thread_wrap, server_args, NULL); + client_thread(client_args); + return 0; +} + +static int run_all_benchmarks(size_t msg_size) { + int error = 0; + size_t i; + for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { + test_strategy *strategy = &test_strategies[i]; + size_t j; + for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) { + thread_args *client_args = gpr_malloc(sizeof(thread_args)); + thread_args *server_args = gpr_malloc(sizeof(thread_args)); + char *socket_type = socket_types[j]; + + client_args->read_bytes = strategy->read_strategy; + client_args->write_bytes = blocking_write_bytes; + client_args->setup = strategy->setup; + client_args->msg_size = msg_size; + client_args->strategy_name = strategy->name; + server_args->read_bytes = strategy->read_strategy; + server_args->write_bytes = blocking_write_bytes; + server_args->setup = strategy->setup; + server_args->msg_size = msg_size; + server_args->strategy_name = strategy->name; + error = run_benchmark(socket_type, client_args, server_args); + if (error < 0) { + return error; + } + } + } + return error; +} + +int main(int argc, char **argv) { + thread_args *client_args = gpr_malloc(sizeof(thread_args)); + thread_args *server_args = gpr_malloc(sizeof(thread_args)); + int msg_size = -1; + char *read_strategy = NULL; + char *socket_type = NULL; + size_t i; + const test_strategy *strategy = NULL; + int error = 0; + + gpr_cmdline *cmdline = + gpr_cmdline_create("low_level_ping_pong network benchmarking tool"); + + gpr_cmdline_add_int(cmdline, "msg_size", "Size of sent messages", &msg_size); + gpr_cmdline_add_string(cmdline, "read_strategy", read_strategy_usage, + &read_strategy); + gpr_cmdline_add_string(cmdline, "socket_type", socket_type_usage, + &socket_type); + + gpr_cmdline_parse(cmdline, argc, argv); + + if (msg_size == -1) { + msg_size = 50; + } + + if (read_strategy == NULL) { + gpr_log(GPR_INFO, "No strategy specified, running all benchmarks"); + return run_all_benchmarks((size_t)msg_size); + } + + if (socket_type == NULL) { + socket_type = "tcp"; + } + if (msg_size <= 0) { + fprintf(stderr, "msg_size must be > 0\n"); + print_usage(argv[0]); + return -1; + } + + for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { + if (strcmp(test_strategies[i].name, read_strategy) == 0) { + strategy = &test_strategies[i]; + } + } + if (strategy == NULL) { + fprintf(stderr, "Invalid read strategy %s\n", read_strategy); + return -1; + } + + client_args->read_bytes = strategy->read_strategy; + client_args->write_bytes = blocking_write_bytes; + client_args->setup = strategy->setup; + client_args->msg_size = (size_t)msg_size; + client_args->strategy_name = read_strategy; + server_args->read_bytes = strategy->read_strategy; + server_args->write_bytes = blocking_write_bytes; + server_args->setup = strategy->setup; + server_args->msg_size = (size_t)msg_size; + server_args->strategy_name = read_strategy; + + error = run_benchmark(socket_type, client_args, server_args); + + gpr_cmdline_destroy(cmdline); + return error; +} diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c deleted file mode 100644 index 88daf28c99..0000000000 --- a/test/core/security/auth_context_test.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/security/context/security_context.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#include - -static void test_empty_context(void) { - grpc_auth_context *ctx = grpc_auth_context_create(NULL); - grpc_auth_property_iterator it; - - gpr_log(GPR_INFO, "test_empty_context"); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL); - it = grpc_auth_context_peer_identity(ctx); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - it = grpc_auth_context_property_iterator(ctx); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - it = grpc_auth_context_find_properties_by_name(ctx, "foo"); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "bar") == - 0); - GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static void test_simple_context(void) { - grpc_auth_context *ctx = grpc_auth_context_create(NULL); - grpc_auth_property_iterator it; - size_t i; - - gpr_log(GPR_INFO, "test_simple_context"); - GPR_ASSERT(ctx != NULL); - grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); - grpc_auth_context_add_cstring_property(ctx, "name", "chapo"); - grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); - GPR_ASSERT(ctx->properties.count == 3); - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") == - 1); - - GPR_ASSERT( - strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0); - it = grpc_auth_context_property_iterator(ctx); - for (i = 0; i < ctx->properties.count; i++) { - const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); - GPR_ASSERT(p == &ctx->properties.array[i]); - } - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - it = grpc_auth_context_find_properties_by_name(ctx, "foo"); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[2]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - it = grpc_auth_context_peer_identity(ctx); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[0]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[1]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static void test_chained_context(void) { - grpc_auth_context *chained = grpc_auth_context_create(NULL); - grpc_auth_context *ctx = grpc_auth_context_create(chained); - grpc_auth_property_iterator it; - size_t i; - - gpr_log(GPR_INFO, "test_chained_context"); - GRPC_AUTH_CONTEXT_UNREF(chained, "chained"); - grpc_auth_context_add_cstring_property(chained, "name", "padapo"); - grpc_auth_context_add_cstring_property(chained, "foo", "baz"); - grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); - grpc_auth_context_add_cstring_property(ctx, "name", "chap0"); - grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") == - 1); - - GPR_ASSERT( - strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0); - it = grpc_auth_context_property_iterator(ctx); - for (i = 0; i < ctx->properties.count; i++) { - const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); - GPR_ASSERT(p == &ctx->properties.array[i]); - } - for (i = 0; i < chained->properties.count; i++) { - const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); - GPR_ASSERT(p == &chained->properties.array[i]); - } - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - it = grpc_auth_context_find_properties_by_name(ctx, "foo"); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[2]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &chained->properties.array[1]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - it = grpc_auth_context_peer_identity(ctx); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[0]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &ctx->properties.array[1]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == - &chained->properties.array[0]); - GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_empty_context(); - test_simple_context(); - test_chained_context(); - return 0; -} diff --git a/test/core/security/auth_context_test.cc b/test/core/security/auth_context_test.cc new file mode 100644 index 0000000000..88daf28c99 --- /dev/null +++ b/test/core/security/auth_context_test.cc @@ -0,0 +1,138 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#include + +static void test_empty_context(void) { + grpc_auth_context *ctx = grpc_auth_context_create(NULL); + grpc_auth_property_iterator it; + + gpr_log(GPR_INFO, "test_empty_context"); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL); + it = grpc_auth_context_peer_identity(ctx); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + it = grpc_auth_context_property_iterator(ctx); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + it = grpc_auth_context_find_properties_by_name(ctx, "foo"); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "bar") == + 0); + GPR_ASSERT(grpc_auth_context_peer_identity_property_name(ctx) == NULL); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static void test_simple_context(void) { + grpc_auth_context *ctx = grpc_auth_context_create(NULL); + grpc_auth_property_iterator it; + size_t i; + + gpr_log(GPR_INFO, "test_simple_context"); + GPR_ASSERT(ctx != NULL); + grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); + grpc_auth_context_add_cstring_property(ctx, "name", "chapo"); + grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); + GPR_ASSERT(ctx->properties.count == 3); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") == + 1); + + GPR_ASSERT( + strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0); + it = grpc_auth_context_property_iterator(ctx); + for (i = 0; i < ctx->properties.count; i++) { + const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); + GPR_ASSERT(p == &ctx->properties.array[i]); + } + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + it = grpc_auth_context_find_properties_by_name(ctx, "foo"); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[2]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + it = grpc_auth_context_peer_identity(ctx); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[0]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[1]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static void test_chained_context(void) { + grpc_auth_context *chained = grpc_auth_context_create(NULL); + grpc_auth_context *ctx = grpc_auth_context_create(chained); + grpc_auth_property_iterator it; + size_t i; + + gpr_log(GPR_INFO, "test_chained_context"); + GRPC_AUTH_CONTEXT_UNREF(chained, "chained"); + grpc_auth_context_add_cstring_property(chained, "name", "padapo"); + grpc_auth_context_add_cstring_property(chained, "foo", "baz"); + grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); + grpc_auth_context_add_cstring_property(ctx, "name", "chap0"); + grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(ctx, "name") == + 1); + + GPR_ASSERT( + strcmp(grpc_auth_context_peer_identity_property_name(ctx), "name") == 0); + it = grpc_auth_context_property_iterator(ctx); + for (i = 0; i < ctx->properties.count; i++) { + const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); + GPR_ASSERT(p == &ctx->properties.array[i]); + } + for (i = 0; i < chained->properties.count; i++) { + const grpc_auth_property *p = grpc_auth_property_iterator_next(&it); + GPR_ASSERT(p == &chained->properties.array[i]); + } + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + it = grpc_auth_context_find_properties_by_name(ctx, "foo"); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[2]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &chained->properties.array[1]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + it = grpc_auth_context_peer_identity(ctx); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[0]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &ctx->properties.array[1]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == + &chained->properties.array[0]); + GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); + + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_empty_context(); + test_simple_context(); + test_chained_context(); + return 0; +} diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c deleted file mode 100644 index 93ea27f425..0000000000 --- a/test/core/security/create_jwt.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" - -#include -#include -#include -#include - -void create_jwt(const char *json_key_file_path, const char *service_url, - const char *scope) { - grpc_auth_json_key key; - char *jwt; - grpc_slice json_key_data; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(json_key_file_path, 1, &json_key_data))); - key = grpc_auth_json_key_create_from_string( - (const char *)GRPC_SLICE_START_PTR(json_key_data)); - grpc_slice_unref(json_key_data); - if (!grpc_auth_json_key_is_valid(&key)) { - fprintf(stderr, "Could not parse json key.\n"); - exit(1); - } - jwt = grpc_jwt_encode_and_sign( - &key, service_url == NULL ? GRPC_JWT_OAUTH2_AUDIENCE : service_url, - grpc_max_auth_token_lifetime(), scope); - grpc_auth_json_key_destruct(&key); - if (jwt == NULL) { - fprintf(stderr, "Could not create JWT.\n"); - exit(1); - } - fprintf(stdout, "%s\n", jwt); - gpr_free(jwt); -} - -int main(int argc, char **argv) { - char *scope = NULL; - char *json_key_file_path = NULL; - char *service_url = NULL; - grpc_init(); - gpr_cmdline *cl = gpr_cmdline_create("create_jwt"); - gpr_cmdline_add_string(cl, "json_key", "File path of the json key.", - &json_key_file_path); - gpr_cmdline_add_string(cl, "scope", - "OPTIONAL Space delimited permissions. Mutually " - "exclusive with service_url", - &scope); - gpr_cmdline_add_string(cl, "service_url", - "OPTIONAL service URL. Mutually exclusive with scope.", - &service_url); - gpr_cmdline_parse(cl, argc, argv); - - if (json_key_file_path == NULL) { - fprintf(stderr, "Missing --json_key option.\n"); - exit(1); - } - if (scope != NULL) { - if (service_url != NULL) { - fprintf(stderr, - "Options --scope and --service_url are mutually exclusive.\n"); - exit(1); - } - } else if (service_url == NULL) { - fprintf(stderr, "Need one of --service_url or --scope options.\n"); - exit(1); - } - - create_jwt(json_key_file_path, service_url, scope); - - gpr_cmdline_destroy(cl); - grpc_shutdown(); - return 0; -} diff --git a/test/core/security/create_jwt.cc b/test/core/security/create_jwt.cc new file mode 100644 index 0000000000..2444dbeae7 --- /dev/null +++ b/test/core/security/create_jwt.cc @@ -0,0 +1,93 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" + +#include +#include +#include +#include + +void create_jwt(const char *json_key_file_path, const char *service_url, + const char *scope) { + grpc_auth_json_key key; + char *jwt; + grpc_slice json_key_data; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(json_key_file_path, 1, &json_key_data))); + key = grpc_auth_json_key_create_from_string( + (const char *)GRPC_SLICE_START_PTR(json_key_data)); + grpc_slice_unref(json_key_data); + if (!grpc_auth_json_key_is_valid(&key)) { + fprintf(stderr, "Could not parse json key.\n"); + exit(1); + } + jwt = grpc_jwt_encode_and_sign( + &key, service_url == NULL ? GRPC_JWT_OAUTH2_AUDIENCE : service_url, + grpc_max_auth_token_lifetime(), scope); + grpc_auth_json_key_destruct(&key); + if (jwt == NULL) { + fprintf(stderr, "Could not create JWT.\n"); + exit(1); + } + fprintf(stdout, "%s\n", jwt); + gpr_free(jwt); +} + +int main(int argc, char **argv) { + const char *scope = NULL; + const char *json_key_file_path = NULL; + const char *service_url = NULL; + grpc_init(); + gpr_cmdline *cl = gpr_cmdline_create("create_jwt"); + gpr_cmdline_add_string(cl, "json_key", "File path of the json key.", + &json_key_file_path); + gpr_cmdline_add_string(cl, "scope", + "OPTIONAL Space delimited permissions. Mutually " + "exclusive with service_url", + &scope); + gpr_cmdline_add_string(cl, "service_url", + "OPTIONAL service URL. Mutually exclusive with scope.", + &service_url); + gpr_cmdline_parse(cl, argc, argv); + + if (json_key_file_path == NULL) { + fprintf(stderr, "Missing --json_key option.\n"); + exit(1); + } + if (scope != NULL) { + if (service_url != NULL) { + fprintf(stderr, + "Options --scope and --service_url are mutually exclusive.\n"); + exit(1); + } + } else if (service_url == NULL) { + fprintf(stderr, "Need one of --service_url or --scope options.\n"); + exit(1); + } + + create_jwt(json_key_file_path, service_url, scope); + + gpr_cmdline_destroy(cl); + grpc_shutdown(); + return 0; +} diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c deleted file mode 100644 index 34f310142c..0000000000 --- a/test/core/security/credentials_test.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/security/credentials/credentials.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/security/credentials/composite/composite_credentials.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/core/lib/security/credentials/google_default/google_default_credentials.h" -#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" -#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/support/tmpfile.h" -#include "test/core/util/test_config.h" - -/* -- Mock channel credentials. -- */ - -static grpc_channel_credentials *grpc_mock_channel_credentials_create( - const grpc_channel_credentials_vtable *vtable) { - grpc_channel_credentials *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - c->type = "mock"; - c->vtable = vtable; - gpr_ref_init(&c->refcount, 1); - return c; -} - -/* -- Constants. -- */ - -static const char test_google_iam_authorization_token[] = "blahblahblhahb"; -static const char test_google_iam_authority_selector[] = "respectmyauthoritah"; -static const char test_oauth2_bearer_token[] = - "Bearer blaaslkdjfaslkdfasdsfasf"; - -/* This JSON key was generated with the GCE console and revoked immediately. - The identifiers have been changed as well. - Maximum size for a string literal is 509 chars in C89, yay! */ -static const char test_json_key_str_part1[] = - "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" - "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" - "qg" - "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" - "rWBQvS4hle4LfijkP3J5BG+" - "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" - "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" - "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" - "8HpCqFYM9V8f34SBWfD4fRFT+n/" - "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; -static const char test_json_key_str_part2[] = - "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" - "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" - "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" - "G" - "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" - "A" - "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" - "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" - "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" - "Y" - "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; -static const char test_json_key_str_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - -/* Test refresh token. */ -static const char test_refresh_token_str[] = - "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," - " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," - " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," - " \"type\": \"authorized_user\"}"; - -static const char valid_oauth2_json_response[] = - "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," - " \"expires_in\":3599, " - " \"token_type\":\"Bearer\"}"; - -static const char test_scope[] = "perm1 perm2"; - -static const char test_signed_jwt[] = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW" - "U0MDcyZTViYTdmZDkwODg2YzcifQ"; - -static const char test_service_url[] = "https://foo.com/foo.v1"; -static const char other_test_service_url[] = "https://bar.com/bar.v1"; - -static const char test_method[] = "ThisIsNotAMethod"; - -/* -- Utils. -- */ - -static char *test_json_key_str(void) { - size_t result_len = strlen(test_json_key_str_part1) + - strlen(test_json_key_str_part2) + - strlen(test_json_key_str_part3); - char *result = gpr_malloc(result_len + 1); - char *current = result; - strcpy(result, test_json_key_str_part1); - current += strlen(test_json_key_str_part1); - strcpy(current, test_json_key_str_part2); - current += strlen(test_json_key_str_part2); - strcpy(current, test_json_key_str_part3); - return result; -} - -static grpc_httpcli_response http_response(int status, const char *body) { - grpc_httpcli_response response; - memset(&response, 0, sizeof(grpc_httpcli_response)); - response.status = status; - response.body = gpr_strdup((char *)body); - response.body_length = strlen(body); - return response; -} - -/* -- Tests. -- */ - -static void test_empty_md_array(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_credentials_mdelem_array md_array; - memset(&md_array, 0, sizeof(md_array)); - GPR_ASSERT(md_array.md == NULL); - GPR_ASSERT(md_array.size == 0); - grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_add_to_empty_md_array(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_credentials_mdelem_array md_array; - memset(&md_array, 0, sizeof(md_array)); - const char *key = "hello"; - const char *value = "there blah blah blah blah blah blah blah"; - grpc_mdelem md = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), - grpc_slice_from_copied_string(value)); - grpc_credentials_mdelem_array_add(&md_array, md); - GPR_ASSERT(md_array.size == 1); - GPR_ASSERT(grpc_mdelem_eq(md, md_array.md[0])); - GRPC_MDELEM_UNREF(&exec_ctx, md); - grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_add_abunch_to_md_array(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_credentials_mdelem_array md_array; - memset(&md_array, 0, sizeof(md_array)); - const char *key = "hello"; - const char *value = "there blah blah blah blah blah blah blah"; - grpc_mdelem md = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), - grpc_slice_from_copied_string(value)); - size_t num_entries = 1000; - for (size_t i = 0; i < num_entries; ++i) { - grpc_credentials_mdelem_array_add(&md_array, md); - } - for (size_t i = 0; i < num_entries; ++i) { - GPR_ASSERT(grpc_mdelem_eq(md_array.md[i], md)); - } - GRPC_MDELEM_UNREF(&exec_ctx, md); - grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_ok(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = - http_response(200, valid_oauth2_json_response); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_OK); - GPR_ASSERT(token_lifetime == 3599 * GPR_MS_PER_SEC); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(token_md), "authorization") == 0); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(token_md), - "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == - 0); - GRPC_MDELEM_UNREF(&exec_ctx, token_md); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = - http_response(401, valid_oauth2_json_response); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = http_response(200, ""); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = - http_response(200, - "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," - " \"expires_in\":3599, " - " \"token_type\":\"Bearer\""); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = http_response(200, - "{" - " \"expires_in\":3599, " - " \"token_type\":\"Bearer\"}"); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = - http_response(200, - "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," - " \"expires_in\":3599, " - "}"); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime( - void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem token_md = GRPC_MDNULL; - grpc_millis token_lifetime; - grpc_httpcli_response response = - http_response(200, - "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," - " \"token_type\":\"Bearer\"}"); - GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( - &exec_ctx, &response, &token_md, &token_lifetime) == - GRPC_CREDENTIALS_ERROR); - grpc_http_response_destroy(&response); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - const char *key; - const char *value; -} expected_md; - -typedef struct { - grpc_error *expected_error; - const expected_md *expected; - size_t expected_size; - grpc_credentials_mdelem_array md_array; - grpc_closure on_request_metadata; - grpc_call_credentials *creds; - grpc_polling_entity pollent; -} request_metadata_state; - -static void check_metadata(const expected_md *expected, - grpc_credentials_mdelem_array *md_array) { - for (size_t i = 0; i < md_array->size; ++i) { - size_t j; - for (j = 0; j < md_array->size; ++j) { - if (0 == - grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) { - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]), - expected[i].value) == 0); - break; - } - } - if (j == md_array->size) { - gpr_log(GPR_ERROR, "key %s not found", expected[i].key); - GPR_ASSERT(0); - } - } -} - -static void check_request_metadata(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - request_metadata_state *state = (request_metadata_state *)arg; - gpr_log(GPR_INFO, "expected_error: %s", - grpc_error_string(state->expected_error)); - gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error)); - if (state->expected_error == GRPC_ERROR_NONE) { - GPR_ASSERT(error == GRPC_ERROR_NONE); - } else { - grpc_slice expected_error; - GPR_ASSERT(grpc_error_get_str(state->expected_error, - GRPC_ERROR_STR_DESCRIPTION, &expected_error)); - grpc_slice actual_error; - GPR_ASSERT( - grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error)); - GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0); - GRPC_ERROR_UNREF(state->expected_error); - } - gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR, - state->expected_size, state->md_array.size); - GPR_ASSERT(state->md_array.size == state->expected_size); - check_metadata(state->expected, &state->md_array); - grpc_credentials_mdelem_array_destroy(exec_ctx, &state->md_array); - grpc_pollset_set_destroy(exec_ctx, - grpc_polling_entity_pollset_set(&state->pollent)); - gpr_free(state); -} - -static request_metadata_state *make_request_metadata_state( - grpc_error *expected_error, const expected_md *expected, - size_t expected_size) { - request_metadata_state *state = gpr_zalloc(sizeof(*state)); - state->expected_error = expected_error; - state->expected = expected; - state->expected_size = expected_size; - state->pollent = - grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()); - GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state, - grpc_schedule_on_exec_ctx); - return state; -} - -static void run_request_metadata_test(grpc_exec_ctx *exec_ctx, - grpc_call_credentials *creds, - grpc_auth_metadata_context auth_md_ctx, - request_metadata_state *state) { - grpc_error *error = GRPC_ERROR_NONE; - if (grpc_call_credentials_get_request_metadata( - exec_ctx, creds, &state->pollent, auth_md_ctx, &state->md_array, - &state->on_request_metadata, &error)) { - // Synchronous result. Invoke the callback directly. - check_request_metadata(exec_ctx, state, error); - GRPC_ERROR_UNREF(error); - } -} - -static void test_google_iam_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - test_google_iam_authorization_token}, - {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - test_google_iam_authority_selector}}; - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_call_credentials *creds = grpc_google_iam_credentials_create( - test_google_iam_authorization_token, test_google_iam_authority_selector, - NULL); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_access_token_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}}; - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_call_credentials *creds = - grpc_access_token_credentials_create("blah", NULL); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static grpc_security_status check_channel_oauth2_create_security_connector( - grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, - grpc_call_credentials *call_creds, const char *target, - const grpc_channel_args *args, grpc_channel_security_connector **sc, - grpc_channel_args **new_args) { - GPR_ASSERT(strcmp(c->type, "mock") == 0); - GPR_ASSERT(call_creds != NULL); - GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); - return GRPC_SECURITY_OK; -} - -static void test_channel_oauth2_composite_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *new_args; - grpc_channel_credentials_vtable vtable = { - NULL, check_channel_oauth2_create_security_connector, NULL}; - grpc_channel_credentials *channel_creds = - grpc_mock_channel_credentials_create(&vtable); - grpc_call_credentials *oauth2_creds = - grpc_access_token_credentials_create("blah", NULL); - grpc_channel_credentials *channel_oauth2_creds = - grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, - NULL); - grpc_channel_credentials_release(channel_creds); - grpc_call_credentials_release(oauth2_creds); - GPR_ASSERT(grpc_channel_credentials_create_security_connector( - &exec_ctx, channel_oauth2_creds, NULL, NULL, NULL, - &new_args) == GRPC_SECURITY_OK); - grpc_channel_credentials_release(channel_oauth2_creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_oauth2_google_iam_composite_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - expected_md emd[] = { - {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}, - {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - test_google_iam_authorization_token}, - {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - test_google_iam_authority_selector}}; - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create( - &exec_ctx, "authorization", test_oauth2_bearer_token, 0); - grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( - test_google_iam_authorization_token, test_google_iam_authority_selector, - NULL); - grpc_call_credentials *composite_creds = - grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds, - NULL); - grpc_call_credentials_unref(&exec_ctx, oauth2_creds); - grpc_call_credentials_unref(&exec_ctx, google_iam_creds); - GPR_ASSERT( - strcmp(composite_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); - const grpc_call_credentials_array *creds_array = - grpc_composite_call_credentials_get_credentials(composite_creds); - GPR_ASSERT(creds_array->num_creds == 2); - GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, - GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); - GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, - GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); - run_request_metadata_test(&exec_ctx, composite_creds, auth_md_ctx, state); - grpc_call_credentials_unref(&exec_ctx, composite_creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static grpc_security_status -check_channel_oauth2_google_iam_create_security_connector( - grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, - grpc_call_credentials *call_creds, const char *target, - const grpc_channel_args *args, grpc_channel_security_connector **sc, - grpc_channel_args **new_args) { - const grpc_call_credentials_array *creds_array; - GPR_ASSERT(strcmp(c->type, "mock") == 0); - GPR_ASSERT(call_creds != NULL); - GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == - 0); - creds_array = grpc_composite_call_credentials_get_credentials(call_creds); - GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, - GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); - GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, - GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); - return GRPC_SECURITY_OK; -} - -static void test_channel_oauth2_google_iam_composite_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *new_args; - grpc_channel_credentials_vtable vtable = { - NULL, check_channel_oauth2_google_iam_create_security_connector, NULL}; - grpc_channel_credentials *channel_creds = - grpc_mock_channel_credentials_create(&vtable); - grpc_call_credentials *oauth2_creds = - grpc_access_token_credentials_create("blah", NULL); - grpc_channel_credentials *channel_oauth2_creds = - grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, - NULL); - grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( - test_google_iam_authorization_token, test_google_iam_authority_selector, - NULL); - grpc_channel_credentials *channel_oauth2_iam_creds = - grpc_composite_channel_credentials_create(channel_oauth2_creds, - google_iam_creds, NULL); - grpc_channel_credentials_release(channel_creds); - grpc_call_credentials_release(oauth2_creds); - grpc_channel_credentials_release(channel_oauth2_creds); - grpc_call_credentials_release(google_iam_creds); - - GPR_ASSERT(grpc_channel_credentials_create_security_connector( - &exec_ctx, channel_oauth2_iam_creds, NULL, NULL, NULL, - &new_args) == GRPC_SECURITY_OK); - - grpc_channel_credentials_release(channel_oauth2_iam_creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void validate_compute_engine_http_request( - const grpc_httpcli_request *request) { - GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); - GPR_ASSERT( - strcmp(request->http.path, - "/computeMetadata/v1/instance/service-accounts/default/token") == - 0); - GPR_ASSERT(request->http.hdr_count == 1); - GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Metadata-Flavor") == 0); - GPR_ASSERT(strcmp(request->http.hdrs[0].value, "Google") == 0); -} - -static int compute_engine_httpcli_get_success_override( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - validate_compute_engine_http_request(request); - *response = http_response(200, valid_oauth2_json_response); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static int compute_engine_httpcli_get_failure_override( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - validate_compute_engine_http_request(request); - *response = http_response(403, "Not Authorized."); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static int httpcli_post_should_not_be_called( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - const char *body_bytes, size_t body_size, grpc_millis deadline, - grpc_closure *on_done, grpc_httpcli_response *response) { - GPR_ASSERT("HTTP POST should not be called" == NULL); - return 1; -} - -static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx, - const grpc_httpcli_request *request, - grpc_millis deadline, - grpc_closure *on_done, - grpc_httpcli_response *response) { - GPR_ASSERT("HTTP GET should not be called" == NULL); - return 1; -} - -static void test_compute_engine_creds_success(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - expected_md emd[] = { - {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; - grpc_call_credentials *creds = - grpc_google_compute_engine_credentials_create(NULL); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - - /* First request: http get should be called. */ - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, - httpcli_post_should_not_be_called); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - /* Second request: the cached token should be served directly. */ - state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - httpcli_post_should_not_be_called); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_httpcli_set_override(NULL, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_compute_engine_creds_failure(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - request_metadata_state *state = make_request_metadata_state( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error occured when fetching oauth2 token."), - NULL, 0); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - grpc_call_credentials *creds = - grpc_google_compute_engine_credentials_create(NULL); - grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, - httpcli_post_should_not_be_called); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_httpcli_set_override(NULL, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void validate_refresh_token_http_request( - const grpc_httpcli_request *request, const char *body, size_t body_size) { - /* The content of the assertion is tested extensively in json_token_test. */ - char *expected_body = NULL; - GPR_ASSERT(body != NULL); - GPR_ASSERT(body_size != 0); - gpr_asprintf(&expected_body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, - "32555999999.apps.googleusercontent.com", - "EmssLNjJy1332hD4KFsecret", - "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42"); - GPR_ASSERT(strlen(expected_body) == body_size); - GPR_ASSERT(memcmp(expected_body, body, body_size) == 0); - gpr_free(expected_body); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0); - GPR_ASSERT( - strcmp(request->http.path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0); - GPR_ASSERT(request->http.hdr_count == 1); - GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0); - GPR_ASSERT(strcmp(request->http.hdrs[0].value, - "application/x-www-form-urlencoded") == 0); -} - -static int refresh_token_httpcli_post_success( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - const char *body, size_t body_size, grpc_millis deadline, - grpc_closure *on_done, grpc_httpcli_response *response) { - validate_refresh_token_http_request(request, body, body_size); - *response = http_response(200, valid_oauth2_json_response); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static int refresh_token_httpcli_post_failure( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - const char *body, size_t body_size, grpc_millis deadline, - grpc_closure *on_done, grpc_httpcli_response *response) { - validate_refresh_token_http_request(request, body, body_size); - *response = http_response(403, "Not Authorized."); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static void test_refresh_token_creds_success(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - expected_md emd[] = { - {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create( - test_refresh_token_str, NULL); - - /* First request: http get should be called. */ - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - refresh_token_httpcli_post_success); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - /* Second request: the cached token should be served directly. */ - state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - httpcli_post_should_not_be_called); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_httpcli_set_override(NULL, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_refresh_token_creds_failure(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - request_metadata_state *state = make_request_metadata_state( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error occured when fetching oauth2 token."), - NULL, 0); - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create( - test_refresh_token_str, NULL); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - refresh_token_httpcli_post_failure); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_httpcli_set_override(NULL, NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void validate_jwt_encode_and_sign_params( - const grpc_auth_json_key *json_key, const char *scope, - gpr_timespec token_lifetime) { - GPR_ASSERT(grpc_auth_json_key_is_valid(json_key)); - GPR_ASSERT(json_key->private_key != NULL); - GPR_ASSERT(RSA_check_key(json_key->private_key)); - GPR_ASSERT(json_key->type != NULL && - strcmp(json_key->type, "service_account") == 0); - GPR_ASSERT(json_key->private_key_id != NULL && - strcmp(json_key->private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); - GPR_ASSERT(json_key->client_id != NULL && - strcmp(json_key->client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com") == 0); - GPR_ASSERT(json_key->client_email != NULL && - strcmp(json_key->client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com") == 0); - if (scope != NULL) GPR_ASSERT(strcmp(scope, test_scope) == 0); - GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime())); -} - -static char *encode_and_sign_jwt_success(const grpc_auth_json_key *json_key, - const char *audience, - gpr_timespec token_lifetime, - const char *scope) { - validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); - return gpr_strdup(test_signed_jwt); -} - -static char *encode_and_sign_jwt_failure(const grpc_auth_json_key *json_key, - const char *audience, - gpr_timespec token_lifetime, - const char *scope) { - validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); - return NULL; -} - -static char *encode_and_sign_jwt_should_not_be_called( - const grpc_auth_json_key *json_key, const char *audience, - gpr_timespec token_lifetime, const char *scope) { - GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == NULL); - return NULL; -} - -static grpc_service_account_jwt_access_credentials *creds_as_jwt( - grpc_call_credentials *creds) { - GPR_ASSERT(creds != NULL); - GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0); - return (grpc_service_account_jwt_access_credentials *)creds; -} - -static void test_jwt_creds_lifetime(void) { - char *json_key_string = test_json_key_str(); - - // Max lifetime. - grpc_call_credentials *jwt_creds = - grpc_service_account_jwt_access_credentials_create( - json_key_string, grpc_max_auth_token_lifetime(), NULL); - GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, - grpc_max_auth_token_lifetime()) == 0); - grpc_call_credentials_release(jwt_creds); - - // Shorter lifetime. - gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN}; - GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0); - jwt_creds = grpc_service_account_jwt_access_credentials_create( - json_key_string, token_lifetime, NULL); - GPR_ASSERT( - gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, token_lifetime) == 0); - grpc_call_credentials_release(jwt_creds); - - // Cropped lifetime. - gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN}; - token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max); - jwt_creds = grpc_service_account_jwt_access_credentials_create( - json_key_string, token_lifetime, NULL); - GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, - grpc_max_auth_token_lifetime()) == 0); - grpc_call_credentials_release(jwt_creds); - - gpr_free(json_key_string); -} - -static void test_jwt_creds_success(void) { - char *json_key_string = test_json_key_str(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - char *expected_md_value; - gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); - expected_md emd[] = {{"authorization", expected_md_value}}; - grpc_call_credentials *creds = - grpc_service_account_jwt_access_credentials_create( - json_key_string, grpc_max_auth_token_lifetime(), NULL); - - /* First request: jwt_encode_and_sign should be called. */ - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - /* Second request: the cached token should be served directly. */ - state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - grpc_jwt_encode_and_sign_set_override( - encode_and_sign_jwt_should_not_be_called); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - /* Third request: Different service url so jwt_encode_and_sign should be - called again (no caching). */ - state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - auth_md_ctx.service_url = other_test_service_url; - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_call_credentials_unref(&exec_ctx, creds); - gpr_free(json_key_string); - gpr_free(expected_md_value); - grpc_jwt_encode_and_sign_set_override(NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_jwt_creds_signing_failure(void) { - char *json_key_string = test_json_key_str(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - request_metadata_state *state = make_request_metadata_state( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), NULL, 0); - grpc_call_credentials *creds = - grpc_service_account_jwt_access_credentials_create( - json_key_string, grpc_max_auth_token_lifetime(), NULL); - - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); - - gpr_free(json_key_string); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_jwt_encode_and_sign_set_override(NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void set_google_default_creds_env_var_with_file_contents( - const char *file_prefix, const char *contents) { - size_t contents_len = strlen(contents); - char *creds_file_name; - FILE *creds_file = gpr_tmpfile(file_prefix, &creds_file_name); - GPR_ASSERT(creds_file_name != NULL); - GPR_ASSERT(creds_file != NULL); - GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len); - fclose(creds_file); - gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name); - gpr_free(creds_file_name); -} - -static void test_google_default_creds_auth_key(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_service_account_jwt_access_credentials *jwt; - grpc_composite_channel_credentials *creds; - char *json_key = test_json_key_str(); - grpc_flush_cached_google_default_credentials(); - set_google_default_creds_env_var_with_file_contents( - "json_key_google_default_creds", json_key); - gpr_free(json_key); - creds = (grpc_composite_channel_credentials *) - grpc_google_default_credentials_create(); - GPR_ASSERT(creds != NULL); - jwt = (grpc_service_account_jwt_access_credentials *)creds->call_creds; - GPR_ASSERT( - strcmp(jwt->key.client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") == - 0); - grpc_channel_credentials_unref(&exec_ctx, &creds->base); - gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_google_default_creds_refresh_token(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_google_refresh_token_credentials *refresh; - grpc_composite_channel_credentials *creds; - grpc_flush_cached_google_default_credentials(); - set_google_default_creds_env_var_with_file_contents( - "refresh_token_google_default_creds", test_refresh_token_str); - creds = (grpc_composite_channel_credentials *) - grpc_google_default_credentials_create(); - GPR_ASSERT(creds != NULL); - refresh = (grpc_google_refresh_token_credentials *)creds->call_creds; - GPR_ASSERT(strcmp(refresh->refresh_token.client_id, - "32555999999.apps.googleusercontent.com") == 0); - grpc_channel_credentials_unref(&exec_ctx, &creds->base); - gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ - grpc_exec_ctx_finish(&exec_ctx); -} - -static int default_creds_gce_detection_httpcli_get_success_override( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, ""); - grpc_http_header *headers = gpr_malloc(sizeof(*headers) * 1); - headers[0].key = gpr_strdup("Metadata-Flavor"); - headers[0].value = gpr_strdup("Google"); - response->hdr_count = 1; - response->hdrs = headers; - GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - 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; - expected_md emd[] = { - {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; - request_metadata_state *state = - make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); - 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); - grpc_composite_channel_credentials *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); - run_request_metadata_test(&exec_ctx, creds->call_creds, auth_md_ctx, state); - grpc_exec_ctx_flush(&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); - grpc_channel_credentials *cached_creds = - grpc_google_default_credentials_create(); - GPR_ASSERT(cached_creds == &creds->base); - - /* Cleanup. */ - grpc_channel_credentials_unref(&exec_ctx, cached_creds); - grpc_channel_credentials_unref(&exec_ctx, &creds->base); - grpc_httpcli_set_override(NULL, NULL); - grpc_override_well_known_credentials_path_getter(NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static int default_creds_gce_detection_httpcli_get_failure_override( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - /* No magic header. */ - GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); - *response = http_response(200, ""); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - 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, - PLUGIN_DESTROY_CALLED_STATE -} plugin_state; - -static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}}; - -static int plugin_get_metadata_success( - void *state, grpc_auth_metadata_context context, - grpc_credentials_plugin_metadata_cb cb, void *user_data, - grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], - size_t *num_creds_md, grpc_status_code *status, - const char **error_details) { - GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); - GPR_ASSERT(strcmp(context.method_name, test_method) == 0); - GPR_ASSERT(context.channel_auth_context == NULL); - GPR_ASSERT(context.reserved == NULL); - GPR_ASSERT(GPR_ARRAY_SIZE(plugin_md) < - GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX); - plugin_state *s = (plugin_state *)state; - *s = PLUGIN_GET_METADATA_CALLED_STATE; - for (size_t i = 0; i < GPR_ARRAY_SIZE(plugin_md); ++i) { - memset(&creds_md[i], 0, sizeof(grpc_metadata)); - creds_md[i].key = grpc_slice_from_copied_string(plugin_md[i].key); - creds_md[i].value = grpc_slice_from_copied_string(plugin_md[i].value); - } - *num_creds_md = GPR_ARRAY_SIZE(plugin_md); - return true; // Synchronous return. -} - -static const char *plugin_error_details = "Could not get metadata for plugin."; - -static int plugin_get_metadata_failure( - void *state, grpc_auth_metadata_context context, - grpc_credentials_plugin_metadata_cb cb, void *user_data, - grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], - size_t *num_creds_md, grpc_status_code *status, - const char **error_details) { - GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); - GPR_ASSERT(strcmp(context.method_name, test_method) == 0); - GPR_ASSERT(context.channel_auth_context == NULL); - GPR_ASSERT(context.reserved == NULL); - plugin_state *s = (plugin_state *)state; - *s = PLUGIN_GET_METADATA_CALLED_STATE; - *status = GRPC_STATUS_UNAUTHENTICATED; - *error_details = gpr_strdup(plugin_error_details); - return true; // Synchronous return. -} - -static void plugin_destroy(void *state) { - plugin_state *s = (plugin_state *)state; - *s = PLUGIN_DESTROY_CALLED_STATE; -} - -static void test_metadata_plugin_success(void) { - plugin_state state = PLUGIN_INITIAL_STATE; - grpc_metadata_credentials_plugin plugin; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - request_metadata_state *md_state = make_request_metadata_state( - GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md)); - - plugin.state = &state; - plugin.get_metadata = plugin_get_metadata_success; - plugin.destroy = plugin_destroy; - - grpc_call_credentials *creds = - grpc_metadata_credentials_create_from_plugin(plugin, NULL); - GPR_ASSERT(state == PLUGIN_INITIAL_STATE); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state); - GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); -} - -static void test_metadata_plugin_failure(void) { - plugin_state state = PLUGIN_INITIAL_STATE; - grpc_metadata_credentials_plugin plugin; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, - NULL}; - char *expected_error; - gpr_asprintf(&expected_error, - "Getting metadata from plugin failed with error: %s", - plugin_error_details); - request_metadata_state *md_state = make_request_metadata_state( - GRPC_ERROR_CREATE_FROM_COPIED_STRING(expected_error), NULL, 0); - gpr_free(expected_error); - - plugin.state = &state; - plugin.get_metadata = plugin_get_metadata_failure; - plugin.destroy = plugin_destroy; - - grpc_call_credentials *creds = - grpc_metadata_credentials_create_from_plugin(plugin, NULL); - GPR_ASSERT(state == PLUGIN_INITIAL_STATE); - run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state); - GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); - grpc_call_credentials_unref(&exec_ctx, creds); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); -} - -static void test_get_well_known_google_credentials_file_path(void) { - char *path; - char *home = gpr_getenv("HOME"); - path = grpc_get_well_known_google_credentials_file_path(); - GPR_ASSERT(path != NULL); - 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); - gpr_setenv("HOME", home); - gpr_free(path); -#endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */ - gpr_free(home); -} - -static void test_channel_creds_duplicate_without_call_creds(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_channel_credentials *channel_creds = - grpc_fake_transport_security_credentials_create(); - - grpc_channel_credentials *dup = - grpc_channel_credentials_duplicate_without_call_credentials( - channel_creds); - GPR_ASSERT(dup == channel_creds); - grpc_channel_credentials_unref(&exec_ctx, dup); - - grpc_call_credentials *call_creds = - grpc_access_token_credentials_create("blah", NULL); - grpc_channel_credentials *composite_creds = - grpc_composite_channel_credentials_create(channel_creds, call_creds, - NULL); - grpc_call_credentials_unref(&exec_ctx, call_creds); - dup = grpc_channel_credentials_duplicate_without_call_credentials( - composite_creds); - GPR_ASSERT(dup == channel_creds); - grpc_channel_credentials_unref(&exec_ctx, dup); - - grpc_channel_credentials_unref(&exec_ctx, channel_creds); - grpc_channel_credentials_unref(&exec_ctx, composite_creds); - - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_empty_md_array(); - test_add_to_empty_md_array(); - test_add_abunch_to_md_array(); - test_oauth2_token_fetcher_creds_parsing_ok(); - test_oauth2_token_fetcher_creds_parsing_bad_http_status(); - test_oauth2_token_fetcher_creds_parsing_empty_http_body(); - test_oauth2_token_fetcher_creds_parsing_invalid_json(); - test_oauth2_token_fetcher_creds_parsing_missing_token(); - test_oauth2_token_fetcher_creds_parsing_missing_token_type(); - test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(); - test_google_iam_creds(); - test_access_token_creds(); - test_channel_oauth2_composite_creds(); - test_oauth2_google_iam_composite_creds(); - test_channel_oauth2_google_iam_composite_creds(); - test_compute_engine_creds_success(); - test_compute_engine_creds_failure(); - test_refresh_token_creds_success(); - test_refresh_token_creds_failure(); - test_jwt_creds_lifetime(); - test_jwt_creds_success(); - test_jwt_creds_signing_failure(); - test_google_default_creds_auth_key(); - 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(); - test_channel_creds_duplicate_without_call_creds(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc new file mode 100644 index 0000000000..dfc071b64a --- /dev/null +++ b/test/core/security/credentials_test.cc @@ -0,0 +1,1219 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/security/credentials/credentials.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/security/credentials/composite/composite_credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/credentials/google_default/google_default_credentials.h" +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "test/core/util/test_config.h" + +/* -- Mock channel credentials. -- */ + +static grpc_channel_credentials *grpc_mock_channel_credentials_create( + const grpc_channel_credentials_vtable *vtable) { + grpc_channel_credentials *c = + static_cast(gpr_malloc(sizeof(*c))); + memset(c, 0, sizeof(*c)); + c->type = "mock"; + c->vtable = vtable; + gpr_ref_init(&c->refcount, 1); + return c; +} + +/* -- Constants. -- */ + +static const char test_google_iam_authorization_token[] = "blahblahblhahb"; +static const char test_google_iam_authority_selector[] = "respectmyauthoritah"; +static const char test_oauth2_bearer_token[] = + "Bearer blaaslkdjfaslkdfasdsfasf"; + +/* This JSON key was generated with the GCE console and revoked immediately. + The identifiers have been changed as well. + Maximum size for a string literal is 509 chars in C89, yay! */ +static const char test_json_key_str_part1[] = + "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" + "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" + "qg" + "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" + "rWBQvS4hle4LfijkP3J5BG+" + "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" + "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" + "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" + "8HpCqFYM9V8f34SBWfD4fRFT+n/" + "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; +static const char test_json_key_str_part2[] = + "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" + "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" + "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" + "G" + "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" + "A" + "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" + "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" + "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" + "Y" + "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; +static const char test_json_key_str_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + +/* Test refresh token. */ +static const char test_refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + +static const char valid_oauth2_json_response[] = + "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," + " \"expires_in\":3599, " + " \"token_type\":\"Bearer\"}"; + +static const char test_scope[] = "perm1 perm2"; + +static const char test_signed_jwt[] = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW" + "U0MDcyZTViYTdmZDkwODg2YzcifQ"; + +static const char test_service_url[] = "https://foo.com/foo.v1"; +static const char other_test_service_url[] = "https://bar.com/bar.v1"; + +static const char test_method[] = "ThisIsNotAMethod"; + +/* -- Utils. -- */ + +static char *test_json_key_str(void) { + size_t result_len = strlen(test_json_key_str_part1) + + strlen(test_json_key_str_part2) + + strlen(test_json_key_str_part3); + char *result = static_cast(gpr_malloc(result_len + 1)); + char *current = result; + strcpy(result, test_json_key_str_part1); + current += strlen(test_json_key_str_part1); + strcpy(current, test_json_key_str_part2); + current += strlen(test_json_key_str_part2); + strcpy(current, test_json_key_str_part3); + return result; +} + +static grpc_httpcli_response http_response(int status, const char *body) { + grpc_httpcli_response response; + memset(&response, 0, sizeof(grpc_httpcli_response)); + response.status = status; + response.body = gpr_strdup((char *)body); + response.body_length = strlen(body); + return response; +} + +/* -- Tests. -- */ + +static void test_empty_md_array(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_credentials_mdelem_array md_array; + memset(&md_array, 0, sizeof(md_array)); + GPR_ASSERT(md_array.md == NULL); + GPR_ASSERT(md_array.size == 0); + grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_add_to_empty_md_array(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_credentials_mdelem_array md_array; + memset(&md_array, 0, sizeof(md_array)); + const char *key = "hello"; + const char *value = "there blah blah blah blah blah blah blah"; + grpc_mdelem md = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), + grpc_slice_from_copied_string(value)); + grpc_credentials_mdelem_array_add(&md_array, md); + GPR_ASSERT(md_array.size == 1); + GPR_ASSERT(grpc_mdelem_eq(md, md_array.md[0])); + GRPC_MDELEM_UNREF(&exec_ctx, md); + grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_add_abunch_to_md_array(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_credentials_mdelem_array md_array; + memset(&md_array, 0, sizeof(md_array)); + const char *key = "hello"; + const char *value = "there blah blah blah blah blah blah blah"; + grpc_mdelem md = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), + grpc_slice_from_copied_string(value)); + size_t num_entries = 1000; + for (size_t i = 0; i < num_entries; ++i) { + grpc_credentials_mdelem_array_add(&md_array, md); + } + for (size_t i = 0; i < num_entries; ++i) { + GPR_ASSERT(grpc_mdelem_eq(md_array.md[i], md)); + } + GRPC_MDELEM_UNREF(&exec_ctx, md); + grpc_credentials_mdelem_array_destroy(&exec_ctx, &md_array); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_ok(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = + http_response(200, valid_oauth2_json_response); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_OK); + GPR_ASSERT(token_lifetime == 3599 * GPR_MS_PER_SEC); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(token_md), "authorization") == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(token_md), + "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == + 0); + GRPC_MDELEM_UNREF(&exec_ctx, token_md); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = + http_response(401, valid_oauth2_json_response); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = http_response(200, ""); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = + http_response(200, + "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," + " \"expires_in\":3599, " + " \"token_type\":\"Bearer\""); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = http_response(200, + "{" + " \"expires_in\":3599, " + " \"token_type\":\"Bearer\"}"); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = + http_response(200, + "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," + " \"expires_in\":3599, " + "}"); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime( + void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem token_md = GRPC_MDNULL; + grpc_millis token_lifetime; + grpc_httpcli_response response = + http_response(200, + "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\"," + " \"token_type\":\"Bearer\"}"); + GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response( + &exec_ctx, &response, &token_md, &token_lifetime) == + GRPC_CREDENTIALS_ERROR); + grpc_http_response_destroy(&response); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + const char *key; + const char *value; +} expected_md; + +typedef struct { + grpc_error *expected_error; + const expected_md *expected; + size_t expected_size; + grpc_credentials_mdelem_array md_array; + grpc_closure on_request_metadata; + grpc_call_credentials *creds; + grpc_polling_entity pollent; +} request_metadata_state; + +static void check_metadata(const expected_md *expected, + grpc_credentials_mdelem_array *md_array) { + for (size_t i = 0; i < md_array->size; ++i) { + size_t j; + for (j = 0; j < md_array->size; ++j) { + if (0 == + grpc_slice_str_cmp(GRPC_MDKEY(md_array->md[j]), expected[i].key)) { + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md_array->md[j]), + expected[i].value) == 0); + break; + } + } + if (j == md_array->size) { + gpr_log(GPR_ERROR, "key %s not found", expected[i].key); + GPR_ASSERT(0); + } + } +} + +static void check_request_metadata(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + request_metadata_state *state = (request_metadata_state *)arg; + gpr_log(GPR_INFO, "expected_error: %s", + grpc_error_string(state->expected_error)); + gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error)); + if (state->expected_error == GRPC_ERROR_NONE) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + } else { + grpc_slice expected_error; + GPR_ASSERT(grpc_error_get_str(state->expected_error, + GRPC_ERROR_STR_DESCRIPTION, &expected_error)); + grpc_slice actual_error; + GPR_ASSERT( + grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &actual_error)); + GPR_ASSERT(grpc_slice_cmp(expected_error, actual_error) == 0); + GRPC_ERROR_UNREF(state->expected_error); + } + gpr_log(GPR_INFO, "expected_size=%" PRIdPTR " actual_size=%" PRIdPTR, + state->expected_size, state->md_array.size); + GPR_ASSERT(state->md_array.size == state->expected_size); + check_metadata(state->expected, &state->md_array); + grpc_credentials_mdelem_array_destroy(exec_ctx, &state->md_array); + grpc_pollset_set_destroy(exec_ctx, + grpc_polling_entity_pollset_set(&state->pollent)); + gpr_free(state); +} + +static request_metadata_state *make_request_metadata_state( + grpc_error *expected_error, const expected_md *expected, + size_t expected_size) { + request_metadata_state *state = + static_cast(gpr_zalloc(sizeof(*state))); + state->expected_error = expected_error; + state->expected = expected; + state->expected_size = expected_size; + state->pollent = + grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()); + GRPC_CLOSURE_INIT(&state->on_request_metadata, check_request_metadata, state, + grpc_schedule_on_exec_ctx); + return state; +} + +static void run_request_metadata_test(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_auth_metadata_context auth_md_ctx, + request_metadata_state *state) { + grpc_error *error = GRPC_ERROR_NONE; + if (grpc_call_credentials_get_request_metadata( + exec_ctx, creds, &state->pollent, auth_md_ctx, &state->md_array, + &state->on_request_metadata, &error)) { + // Synchronous result. Invoke the callback directly. + check_request_metadata(exec_ctx, state, error); + GRPC_ERROR_UNREF(error); + } +} + +static void test_google_iam_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + test_google_iam_authorization_token}, + {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + test_google_iam_authority_selector}}; + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_call_credentials *creds = grpc_google_iam_credentials_create( + test_google_iam_authorization_token, test_google_iam_authority_selector, + NULL); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_access_token_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}}; + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_call_credentials *creds = + grpc_access_token_credentials_create("blah", NULL); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static grpc_security_status check_channel_oauth2_create_security_connector( + grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, + grpc_call_credentials *call_creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args) { + GPR_ASSERT(strcmp(c->type, "mock") == 0); + GPR_ASSERT(call_creds != NULL); + GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); + return GRPC_SECURITY_OK; +} + +static void test_channel_oauth2_composite_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *new_args; + grpc_channel_credentials_vtable vtable = { + NULL, check_channel_oauth2_create_security_connector, NULL}; + grpc_channel_credentials *channel_creds = + grpc_mock_channel_credentials_create(&vtable); + grpc_call_credentials *oauth2_creds = + grpc_access_token_credentials_create("blah", NULL); + grpc_channel_credentials *channel_oauth2_creds = + grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, + NULL); + grpc_channel_credentials_release(channel_creds); + grpc_call_credentials_release(oauth2_creds); + GPR_ASSERT(grpc_channel_credentials_create_security_connector( + &exec_ctx, channel_oauth2_creds, NULL, NULL, NULL, + &new_args) == GRPC_SECURITY_OK); + grpc_channel_credentials_release(channel_oauth2_creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_oauth2_google_iam_composite_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + expected_md emd[] = { + {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}, + {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + test_google_iam_authorization_token}, + {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + test_google_iam_authority_selector}}; + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create( + &exec_ctx, "authorization", test_oauth2_bearer_token, 0); + grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( + test_google_iam_authorization_token, test_google_iam_authority_selector, + NULL); + grpc_call_credentials *composite_creds = + grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds, + NULL); + grpc_call_credentials_unref(&exec_ctx, oauth2_creds); + grpc_call_credentials_unref(&exec_ctx, google_iam_creds); + GPR_ASSERT( + strcmp(composite_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); + const grpc_call_credentials_array *creds_array = + grpc_composite_call_credentials_get_credentials(composite_creds); + GPR_ASSERT(creds_array->num_creds == 2); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); + run_request_metadata_test(&exec_ctx, composite_creds, auth_md_ctx, state); + grpc_call_credentials_unref(&exec_ctx, composite_creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static grpc_security_status +check_channel_oauth2_google_iam_create_security_connector( + grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, + grpc_call_credentials *call_creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args) { + const grpc_call_credentials_array *creds_array; + GPR_ASSERT(strcmp(c->type, "mock") == 0); + GPR_ASSERT(call_creds != NULL); + GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == + 0); + creds_array = grpc_composite_call_credentials_get_credentials(call_creds); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0); + return GRPC_SECURITY_OK; +} + +static void test_channel_oauth2_google_iam_composite_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *new_args; + grpc_channel_credentials_vtable vtable = { + NULL, check_channel_oauth2_google_iam_create_security_connector, NULL}; + grpc_channel_credentials *channel_creds = + grpc_mock_channel_credentials_create(&vtable); + grpc_call_credentials *oauth2_creds = + grpc_access_token_credentials_create("blah", NULL); + grpc_channel_credentials *channel_oauth2_creds = + grpc_composite_channel_credentials_create(channel_creds, oauth2_creds, + NULL); + grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create( + test_google_iam_authorization_token, test_google_iam_authority_selector, + NULL); + grpc_channel_credentials *channel_oauth2_iam_creds = + grpc_composite_channel_credentials_create(channel_oauth2_creds, + google_iam_creds, NULL); + grpc_channel_credentials_release(channel_creds); + grpc_call_credentials_release(oauth2_creds); + grpc_channel_credentials_release(channel_oauth2_creds); + grpc_call_credentials_release(google_iam_creds); + + GPR_ASSERT(grpc_channel_credentials_create_security_connector( + &exec_ctx, channel_oauth2_iam_creds, NULL, NULL, NULL, + &new_args) == GRPC_SECURITY_OK); + + grpc_channel_credentials_release(channel_oauth2_iam_creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void validate_compute_engine_http_request( + const grpc_httpcli_request *request) { + GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT( + strcmp(request->http.path, + "/computeMetadata/v1/instance/service-accounts/default/token") == + 0); + GPR_ASSERT(request->http.hdr_count == 1); + GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Metadata-Flavor") == 0); + GPR_ASSERT(strcmp(request->http.hdrs[0].value, "Google") == 0); +} + +static int compute_engine_httpcli_get_success_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + validate_compute_engine_http_request(request); + *response = http_response(200, valid_oauth2_json_response); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static int compute_engine_httpcli_get_failure_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + validate_compute_engine_http_request(request); + *response = http_response(403, "Not Authorized."); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static int httpcli_post_should_not_be_called( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + const char *body_bytes, size_t body_size, grpc_millis deadline, + grpc_closure *on_done, grpc_httpcli_response *response) { + GPR_ASSERT("HTTP POST should not be called" == NULL); + return 1; +} + +static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx, + const grpc_httpcli_request *request, + grpc_millis deadline, + grpc_closure *on_done, + grpc_httpcli_response *response) { + GPR_ASSERT("HTTP GET should not be called" == NULL); + return 1; +} + +static void test_compute_engine_creds_success(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + expected_md emd[] = { + {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; + grpc_call_credentials *creds = + grpc_google_compute_engine_credentials_create(NULL); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + + /* First request: http get should be called. */ + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(compute_engine_httpcli_get_success_override, + httpcli_post_should_not_be_called); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + /* Second request: the cached token should be served directly. */ + state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + httpcli_post_should_not_be_called); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_httpcli_set_override(NULL, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_compute_engine_creds_failure(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + request_metadata_state *state = make_request_metadata_state( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Error occured when fetching oauth2 token."), + NULL, 0); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_call_credentials *creds = + grpc_google_compute_engine_credentials_create(NULL); + grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, + httpcli_post_should_not_be_called); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_httpcli_set_override(NULL, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void validate_refresh_token_http_request( + const grpc_httpcli_request *request, const char *body, size_t body_size) { + /* The content of the assertion is tested extensively in json_token_test. */ + char *expected_body = NULL; + GPR_ASSERT(body != NULL); + GPR_ASSERT(body_size != 0); + gpr_asprintf(&expected_body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, + "32555999999.apps.googleusercontent.com", + "EmssLNjJy1332hD4KFsecret", + "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42"); + GPR_ASSERT(strlen(expected_body) == body_size); + GPR_ASSERT(memcmp(expected_body, body, body_size) == 0); + gpr_free(expected_body); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0); + GPR_ASSERT( + strcmp(request->http.path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0); + GPR_ASSERT(request->http.hdr_count == 1); + GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0); + GPR_ASSERT(strcmp(request->http.hdrs[0].value, + "application/x-www-form-urlencoded") == 0); +} + +static int refresh_token_httpcli_post_success( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + const char *body, size_t body_size, grpc_millis deadline, + grpc_closure *on_done, grpc_httpcli_response *response) { + validate_refresh_token_http_request(request, body, body_size); + *response = http_response(200, valid_oauth2_json_response); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static int refresh_token_httpcli_post_failure( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + const char *body, size_t body_size, grpc_millis deadline, + grpc_closure *on_done, grpc_httpcli_response *response) { + validate_refresh_token_http_request(request, body, body_size); + *response = http_response(403, "Not Authorized."); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static void test_refresh_token_creds_success(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + expected_md emd[] = { + {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create( + test_refresh_token_str, NULL); + + /* First request: http get should be called. */ + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + refresh_token_httpcli_post_success); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + /* Second request: the cached token should be served directly. */ + state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + httpcli_post_should_not_be_called); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_httpcli_set_override(NULL, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_refresh_token_creds_failure(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + request_metadata_state *state = make_request_metadata_state( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Error occured when fetching oauth2 token."), + NULL, 0); + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + grpc_call_credentials *creds = grpc_google_refresh_token_credentials_create( + test_refresh_token_str, NULL); + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + refresh_token_httpcli_post_failure); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_httpcli_set_override(NULL, NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void validate_jwt_encode_and_sign_params( + const grpc_auth_json_key *json_key, const char *scope, + gpr_timespec token_lifetime) { + GPR_ASSERT(grpc_auth_json_key_is_valid(json_key)); + GPR_ASSERT(json_key->private_key != NULL); + GPR_ASSERT(RSA_check_key(json_key->private_key)); + GPR_ASSERT(json_key->type != NULL && + strcmp(json_key->type, "service_account") == 0); + GPR_ASSERT(json_key->private_key_id != NULL && + strcmp(json_key->private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); + GPR_ASSERT(json_key->client_id != NULL && + strcmp(json_key->client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); + GPR_ASSERT(json_key->client_email != NULL && + strcmp(json_key->client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); + if (scope != NULL) GPR_ASSERT(strcmp(scope, test_scope) == 0); + GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime())); +} + +static char *encode_and_sign_jwt_success(const grpc_auth_json_key *json_key, + const char *audience, + gpr_timespec token_lifetime, + const char *scope) { + validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); + return gpr_strdup(test_signed_jwt); +} + +static char *encode_and_sign_jwt_failure(const grpc_auth_json_key *json_key, + const char *audience, + gpr_timespec token_lifetime, + const char *scope) { + validate_jwt_encode_and_sign_params(json_key, scope, token_lifetime); + return NULL; +} + +static char *encode_and_sign_jwt_should_not_be_called( + const grpc_auth_json_key *json_key, const char *audience, + gpr_timespec token_lifetime, const char *scope) { + GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == NULL); + return NULL; +} + +static grpc_service_account_jwt_access_credentials *creds_as_jwt( + grpc_call_credentials *creds) { + GPR_ASSERT(creds != NULL); + GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0); + return (grpc_service_account_jwt_access_credentials *)creds; +} + +static void test_jwt_creds_lifetime(void) { + char *json_key_string = test_json_key_str(); + + // Max lifetime. + grpc_call_credentials *jwt_creds = + grpc_service_account_jwt_access_credentials_create( + json_key_string, grpc_max_auth_token_lifetime(), NULL); + GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, + grpc_max_auth_token_lifetime()) == 0); + grpc_call_credentials_release(jwt_creds); + + // Shorter lifetime. + gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN}; + GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0); + jwt_creds = grpc_service_account_jwt_access_credentials_create( + json_key_string, token_lifetime, NULL); + GPR_ASSERT( + gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, token_lifetime) == 0); + grpc_call_credentials_release(jwt_creds); + + // Cropped lifetime. + gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN}; + token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max); + jwt_creds = grpc_service_account_jwt_access_credentials_create( + json_key_string, token_lifetime, NULL); + GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, + grpc_max_auth_token_lifetime()) == 0); + grpc_call_credentials_release(jwt_creds); + + gpr_free(json_key_string); +} + +static void test_jwt_creds_success(void) { + char *json_key_string = test_json_key_str(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + char *expected_md_value; + gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); + expected_md emd[] = {{"authorization", expected_md_value}}; + grpc_call_credentials *creds = + grpc_service_account_jwt_access_credentials_create( + json_key_string, grpc_max_auth_token_lifetime(), NULL); + + /* First request: jwt_encode_and_sign should be called. */ + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + /* Second request: the cached token should be served directly. */ + state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_jwt_encode_and_sign_set_override( + encode_and_sign_jwt_should_not_be_called); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + /* Third request: Different service url so jwt_encode_and_sign should be + called again (no caching). */ + state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + auth_md_ctx.service_url = other_test_service_url; + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_call_credentials_unref(&exec_ctx, creds); + gpr_free(json_key_string); + gpr_free(expected_md_value); + grpc_jwt_encode_and_sign_set_override(NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_jwt_creds_signing_failure(void) { + char *json_key_string = test_json_key_str(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + request_metadata_state *state = make_request_metadata_state( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."), NULL, 0); + grpc_call_credentials *creds = + grpc_service_account_jwt_access_credentials_create( + json_key_string, grpc_max_auth_token_lifetime(), NULL); + + grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, state); + + gpr_free(json_key_string); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_jwt_encode_and_sign_set_override(NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void set_google_default_creds_env_var_with_file_contents( + const char *file_prefix, const char *contents) { + size_t contents_len = strlen(contents); + char *creds_file_name; + FILE *creds_file = gpr_tmpfile(file_prefix, &creds_file_name); + GPR_ASSERT(creds_file_name != NULL); + GPR_ASSERT(creds_file != NULL); + GPR_ASSERT(fwrite(contents, 1, contents_len, creds_file) == contents_len); + fclose(creds_file); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, creds_file_name); + gpr_free(creds_file_name); +} + +static void test_google_default_creds_auth_key(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_service_account_jwt_access_credentials *jwt; + grpc_composite_channel_credentials *creds; + char *json_key = test_json_key_str(); + grpc_flush_cached_google_default_credentials(); + set_google_default_creds_env_var_with_file_contents( + "json_key_google_default_creds", json_key); + gpr_free(json_key); + creds = (grpc_composite_channel_credentials *) + grpc_google_default_credentials_create(); + GPR_ASSERT(creds != NULL); + jwt = (grpc_service_account_jwt_access_credentials *)creds->call_creds; + GPR_ASSERT( + strcmp(jwt->key.client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") == + 0); + grpc_channel_credentials_unref(&exec_ctx, &creds->base); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_google_default_creds_refresh_token(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_google_refresh_token_credentials *refresh; + grpc_composite_channel_credentials *creds; + grpc_flush_cached_google_default_credentials(); + set_google_default_creds_env_var_with_file_contents( + "refresh_token_google_default_creds", test_refresh_token_str); + creds = (grpc_composite_channel_credentials *) + grpc_google_default_credentials_create(); + GPR_ASSERT(creds != NULL); + refresh = (grpc_google_refresh_token_credentials *)creds->call_creds; + GPR_ASSERT(strcmp(refresh->refresh_token.client_id, + "32555999999.apps.googleusercontent.com") == 0); + grpc_channel_credentials_unref(&exec_ctx, &creds->base); + gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */ + grpc_exec_ctx_finish(&exec_ctx); +} + +static int default_creds_gce_detection_httpcli_get_success_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, ""); + grpc_http_header *headers = + static_cast(gpr_malloc(sizeof(*headers) * 1)); + headers[0].key = gpr_strdup("Metadata-Flavor"); + headers[0].value = gpr_strdup("Google"); + response->hdr_count = 1; + response->hdrs = headers; + GPR_ASSERT(strcmp(request->http.path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + 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; + expected_md emd[] = { + {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}}; + request_metadata_state *state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + 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); + grpc_composite_channel_credentials *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); + run_request_metadata_test(&exec_ctx, creds->call_creds, auth_md_ctx, state); + grpc_exec_ctx_flush(&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); + grpc_channel_credentials *cached_creds = + grpc_google_default_credentials_create(); + GPR_ASSERT(cached_creds == &creds->base); + + /* Cleanup. */ + grpc_channel_credentials_unref(&exec_ctx, cached_creds); + grpc_channel_credentials_unref(&exec_ctx, &creds->base); + grpc_httpcli_set_override(NULL, NULL); + grpc_override_well_known_credentials_path_getter(NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static int default_creds_gce_detection_httpcli_get_failure_override( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + /* No magic header. */ + GPR_ASSERT(strcmp(request->http.path, "/") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + *response = http_response(200, ""); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + 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, + PLUGIN_DESTROY_CALLED_STATE +} plugin_state; + +static const expected_md plugin_md[] = {{"foo", "bar"}, {"hi", "there"}}; + +static int plugin_get_metadata_success( + void *state, grpc_auth_metadata_context context, + grpc_credentials_plugin_metadata_cb cb, void *user_data, + grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], + size_t *num_creds_md, grpc_status_code *status, + const char **error_details) { + GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); + GPR_ASSERT(strcmp(context.method_name, test_method) == 0); + GPR_ASSERT(context.channel_auth_context == NULL); + GPR_ASSERT(context.reserved == NULL); + GPR_ASSERT(GPR_ARRAY_SIZE(plugin_md) < + GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX); + plugin_state *s = (plugin_state *)state; + *s = PLUGIN_GET_METADATA_CALLED_STATE; + for (size_t i = 0; i < GPR_ARRAY_SIZE(plugin_md); ++i) { + memset(&creds_md[i], 0, sizeof(grpc_metadata)); + creds_md[i].key = grpc_slice_from_copied_string(plugin_md[i].key); + creds_md[i].value = grpc_slice_from_copied_string(plugin_md[i].value); + } + *num_creds_md = GPR_ARRAY_SIZE(plugin_md); + return true; // Synchronous return. +} + +static const char *plugin_error_details = "Could not get metadata for plugin."; + +static int plugin_get_metadata_failure( + void *state, grpc_auth_metadata_context context, + grpc_credentials_plugin_metadata_cb cb, void *user_data, + grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], + size_t *num_creds_md, grpc_status_code *status, + const char **error_details) { + GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0); + GPR_ASSERT(strcmp(context.method_name, test_method) == 0); + GPR_ASSERT(context.channel_auth_context == NULL); + GPR_ASSERT(context.reserved == NULL); + plugin_state *s = (plugin_state *)state; + *s = PLUGIN_GET_METADATA_CALLED_STATE; + *status = GRPC_STATUS_UNAUTHENTICATED; + *error_details = gpr_strdup(plugin_error_details); + return true; // Synchronous return. +} + +static void plugin_destroy(void *state) { + plugin_state *s = (plugin_state *)state; + *s = PLUGIN_DESTROY_CALLED_STATE; +} + +static void test_metadata_plugin_success(void) { + plugin_state state = PLUGIN_INITIAL_STATE; + grpc_metadata_credentials_plugin plugin; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + request_metadata_state *md_state = make_request_metadata_state( + GRPC_ERROR_NONE, plugin_md, GPR_ARRAY_SIZE(plugin_md)); + + plugin.state = &state; + plugin.get_metadata = plugin_get_metadata_success; + plugin.destroy = plugin_destroy; + + grpc_call_credentials *creds = + grpc_metadata_credentials_create_from_plugin(plugin, NULL); + GPR_ASSERT(state == PLUGIN_INITIAL_STATE); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state); + GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); +} + +static void test_metadata_plugin_failure(void) { + plugin_state state = PLUGIN_INITIAL_STATE; + grpc_metadata_credentials_plugin plugin; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL, + NULL}; + char *expected_error; + gpr_asprintf(&expected_error, + "Getting metadata from plugin failed with error: %s", + plugin_error_details); + request_metadata_state *md_state = make_request_metadata_state( + GRPC_ERROR_CREATE_FROM_COPIED_STRING(expected_error), NULL, 0); + gpr_free(expected_error); + + plugin.state = &state; + plugin.get_metadata = plugin_get_metadata_failure; + plugin.destroy = plugin_destroy; + + grpc_call_credentials *creds = + grpc_metadata_credentials_create_from_plugin(plugin, NULL); + GPR_ASSERT(state == PLUGIN_INITIAL_STATE); + run_request_metadata_test(&exec_ctx, creds, auth_md_ctx, md_state); + GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE); + grpc_call_credentials_unref(&exec_ctx, creds); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE); +} + +static void test_get_well_known_google_credentials_file_path(void) { + char *path; + char *home = gpr_getenv("HOME"); + path = grpc_get_well_known_google_credentials_file_path(); + GPR_ASSERT(path != NULL); + 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); + gpr_setenv("HOME", home); + gpr_free(path); +#endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */ + gpr_free(home); +} + +static void test_channel_creds_duplicate_without_call_creds(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_channel_credentials *channel_creds = + grpc_fake_transport_security_credentials_create(); + + grpc_channel_credentials *dup = + grpc_channel_credentials_duplicate_without_call_credentials( + channel_creds); + GPR_ASSERT(dup == channel_creds); + grpc_channel_credentials_unref(&exec_ctx, dup); + + grpc_call_credentials *call_creds = + grpc_access_token_credentials_create("blah", NULL); + grpc_channel_credentials *composite_creds = + grpc_composite_channel_credentials_create(channel_creds, call_creds, + NULL); + grpc_call_credentials_unref(&exec_ctx, call_creds); + dup = grpc_channel_credentials_duplicate_without_call_credentials( + composite_creds); + GPR_ASSERT(dup == channel_creds); + grpc_channel_credentials_unref(&exec_ctx, dup); + + grpc_channel_credentials_unref(&exec_ctx, channel_creds); + grpc_channel_credentials_unref(&exec_ctx, composite_creds); + + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_empty_md_array(); + test_add_to_empty_md_array(); + test_add_abunch_to_md_array(); + test_oauth2_token_fetcher_creds_parsing_ok(); + test_oauth2_token_fetcher_creds_parsing_bad_http_status(); + test_oauth2_token_fetcher_creds_parsing_empty_http_body(); + test_oauth2_token_fetcher_creds_parsing_invalid_json(); + test_oauth2_token_fetcher_creds_parsing_missing_token(); + test_oauth2_token_fetcher_creds_parsing_missing_token_type(); + test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(); + test_google_iam_creds(); + test_access_token_creds(); + test_channel_oauth2_composite_creds(); + test_oauth2_google_iam_composite_creds(); + test_channel_oauth2_google_iam_composite_creds(); + test_compute_engine_creds_success(); + test_compute_engine_creds_failure(); + test_refresh_token_creds_success(); + test_refresh_token_creds_failure(); + test_jwt_creds_lifetime(); + test_jwt_creds_success(); + test_jwt_creds_signing_failure(); + test_google_default_creds_auth_key(); + 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(); + test_channel_creds_duplicate_without_call_creds(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c deleted file mode 100644 index 3998cb51cd..0000000000 --- a/test/core/security/fetch_oauth2.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "test/core/security/oauth2_utils.h" - -static grpc_call_credentials *create_refresh_token_creds( - const char *json_refresh_token_file_path) { - grpc_slice refresh_token; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", - grpc_load_file(json_refresh_token_file_path, 1, &refresh_token))); - return grpc_google_refresh_token_credentials_create( - (const char *)GRPC_SLICE_START_PTR(refresh_token), NULL); -} - -int main(int argc, char **argv) { - grpc_call_credentials *creds = NULL; - char *json_key_file_path = NULL; - char *json_refresh_token_file_path = NULL; - char *token = NULL; - int use_gce = 0; - char *scope = NULL; - gpr_cmdline *cl = gpr_cmdline_create("fetch_oauth2"); - gpr_cmdline_add_string(cl, "json_refresh_token", - "File path of the json refresh token.", - &json_refresh_token_file_path); - gpr_cmdline_add_flag( - cl, "gce", - "Get a token from the GCE metadata server (only works in GCE).", - &use_gce); - gpr_cmdline_parse(cl, argc, argv); - - grpc_init(); - - if (json_key_file_path != NULL && json_refresh_token_file_path != NULL) { - gpr_log(GPR_ERROR, - "--json_key and --json_refresh_token are mutually exclusive."); - exit(1); - } - - if (use_gce) { - if (json_key_file_path != NULL || scope != NULL) { - gpr_log(GPR_INFO, - "Ignoring json key and scope to get a token from the GCE " - "metadata server."); - } - creds = grpc_google_compute_engine_credentials_create(NULL); - if (creds == NULL) { - gpr_log(GPR_ERROR, "Could not create gce credentials."); - exit(1); - } - } else if (json_refresh_token_file_path != NULL) { - creds = create_refresh_token_creds(json_refresh_token_file_path); - if (creds == NULL) { - gpr_log(GPR_ERROR, - "Could not create refresh token creds. %s does probably not " - "contain a valid json refresh token.", - json_refresh_token_file_path); - exit(1); - } - } else { - gpr_log(GPR_ERROR, "Missing --gce or --json_refresh_token option."); - exit(1); - } - GPR_ASSERT(creds != NULL); - - token = grpc_test_fetch_oauth2_token_with_credentials(creds); - if (token != NULL) { - printf("Got token: %s.\n", token); - gpr_free(token); - } - grpc_call_credentials_release(creds); - gpr_cmdline_destroy(cl); - grpc_shutdown(); - return 0; -} diff --git a/test/core/security/fetch_oauth2.cc b/test/core/security/fetch_oauth2.cc new file mode 100644 index 0000000000..1f1cf11545 --- /dev/null +++ b/test/core/security/fetch_oauth2.cc @@ -0,0 +1,104 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "test/core/security/oauth2_utils.h" + +static grpc_call_credentials *create_refresh_token_creds( + const char *json_refresh_token_file_path) { + grpc_slice refresh_token; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", + grpc_load_file(json_refresh_token_file_path, 1, &refresh_token))); + return grpc_google_refresh_token_credentials_create( + (const char *)GRPC_SLICE_START_PTR(refresh_token), NULL); +} + +int main(int argc, char **argv) { + grpc_call_credentials *creds = NULL; + char *json_key_file_path = NULL; + const char *json_refresh_token_file_path = NULL; + char *token = NULL; + int use_gce = 0; + char *scope = NULL; + gpr_cmdline *cl = gpr_cmdline_create("fetch_oauth2"); + gpr_cmdline_add_string(cl, "json_refresh_token", + "File path of the json refresh token.", + &json_refresh_token_file_path); + gpr_cmdline_add_flag( + cl, "gce", + "Get a token from the GCE metadata server (only works in GCE).", + &use_gce); + gpr_cmdline_parse(cl, argc, argv); + + grpc_init(); + + if (json_key_file_path != NULL && json_refresh_token_file_path != NULL) { + gpr_log(GPR_ERROR, + "--json_key and --json_refresh_token are mutually exclusive."); + exit(1); + } + + if (use_gce) { + if (json_key_file_path != NULL || scope != NULL) { + gpr_log(GPR_INFO, + "Ignoring json key and scope to get a token from the GCE " + "metadata server."); + } + creds = grpc_google_compute_engine_credentials_create(NULL); + if (creds == NULL) { + gpr_log(GPR_ERROR, "Could not create gce credentials."); + exit(1); + } + } else if (json_refresh_token_file_path != NULL) { + creds = create_refresh_token_creds(json_refresh_token_file_path); + if (creds == NULL) { + gpr_log(GPR_ERROR, + "Could not create refresh token creds. %s does probably not " + "contain a valid json refresh token.", + json_refresh_token_file_path); + exit(1); + } + } else { + gpr_log(GPR_ERROR, "Missing --gce or --json_refresh_token option."); + exit(1); + } + GPR_ASSERT(creds != NULL); + + token = grpc_test_fetch_oauth2_token_with_credentials(creds); + if (token != NULL) { + printf("Got token: %s.\n", token); + gpr_free(token); + } + grpc_call_credentials_release(creds); + gpr_cmdline_destroy(cl); + grpc_shutdown(); + return 0; +} diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c deleted file mode 100644 index 6573f70e72..0000000000 --- a/test/core/security/json_token_test.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/security/credentials/jwt/json_token.h" - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/json/json.h" -#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" -#include "src/core/lib/slice/b64.h" -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -/* This JSON key was generated with the GCE console and revoked immediately. - The identifiers have been changed as well. - Maximum size for a string literal is 509 chars in C89, yay! */ -static const char test_json_key_str_part1[] = - "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" - "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" - "qg" - "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" - "rWBQvS4hle4LfijkP3J5BG+" - "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" - "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" - "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" - "8HpCqFYM9V8f34SBWfD4fRFT+n/" - "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; -static const char test_json_key_str_part2[] = - "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" - "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" - "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" - "G" - "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" - "A" - "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" - "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" - "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" - "Y" - "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; -static const char test_json_key_str_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - -/* Test refresh token. */ -static const char test_refresh_token_str[] = - "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," - " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," - " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," - " \"type\": \"authorized_user\"}"; - -static const char test_scope[] = "myperm1 myperm2"; - -static const char test_service_url[] = "https://foo.com/foo.v1"; - -static char *test_json_key_str(const char *bad_part3) { - const char *part3 = bad_part3 != NULL ? bad_part3 : test_json_key_str_part3; - size_t result_len = strlen(test_json_key_str_part1) + - strlen(test_json_key_str_part2) + strlen(part3); - char *result = gpr_malloc(result_len + 1); - char *current = result; - strcpy(result, test_json_key_str_part1); - current += strlen(test_json_key_str_part1); - strcpy(current, test_json_key_str_part2); - current += strlen(test_json_key_str_part2); - strcpy(current, part3); - return result; -} - -static void test_parse_json_key_success(void) { - char *json_string = test_json_key_str(NULL); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(grpc_auth_json_key_is_valid(&json_key)); - GPR_ASSERT(json_key.type != NULL && - strcmp(json_key.type, "service_account") == 0); - GPR_ASSERT(json_key.private_key_id != NULL && - strcmp(json_key.private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); - GPR_ASSERT(json_key.client_id != NULL && - strcmp(json_key.client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com") == 0); - GPR_ASSERT(json_key.client_email != NULL && - strcmp(json_key.client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com") == 0); - GPR_ASSERT(json_key.private_key != NULL); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_bad_json(void) { - const char non_closing_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" "; - char *json_string = test_json_key_str(non_closing_part3); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_no_type(void) { - const char no_type_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\" }"; - char *json_string = test_json_key_str(no_type_part3); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_no_client_id(void) { - const char no_client_id_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", " - "\"type\": \"service_account\" }"; - char *json_string = test_json_key_str(no_client_id_part3); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_no_client_email(void) { - const char no_client_email_part3[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - char *json_string = test_json_key_str(no_client_email_part3); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_no_private_key_id(void) { - const char no_private_key_id_part3[] = - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - char *json_string = test_json_key_str(no_private_key_id_part3); - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); -} - -static void test_parse_json_key_failure_no_private_key(void) { - const char no_private_key_json_string[] = - "{ \"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(no_private_key_json_string); - GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); - grpc_auth_json_key_destruct(&json_key); -} - -static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, - char **scratchpad) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - char *b64; - char *decoded; - grpc_json *json; - grpc_slice slice; - b64 = gpr_malloc(len + 1); - strncpy(b64, str, len); - b64[len] = '\0'; - slice = grpc_base64_decode(&exec_ctx, b64, 1); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(slice)); - decoded = gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1); - strncpy(decoded, (const char *)GRPC_SLICE_START_PTR(slice), - GRPC_SLICE_LENGTH(slice)); - decoded[GRPC_SLICE_LENGTH(slice)] = '\0'; - json = grpc_json_parse_string(decoded); - gpr_free(b64); - *scratchpad = decoded; - grpc_slice_unref(slice); - grpc_exec_ctx_finish(&exec_ctx); - return json; -} - -static void check_jwt_header(grpc_json *header) { - grpc_json *ptr; - grpc_json *alg = NULL; - grpc_json *typ = NULL; - grpc_json *kid = NULL; - - for (ptr = header->child; ptr; ptr = ptr->next) { - if (strcmp(ptr->key, "alg") == 0) { - alg = ptr; - } else if (strcmp(ptr->key, "typ") == 0) { - typ = ptr; - } else if (strcmp(ptr->key, "kid") == 0) { - kid = ptr; - } - } - GPR_ASSERT(alg != NULL); - GPR_ASSERT(alg->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(alg->value, "RS256") == 0); - - GPR_ASSERT(typ != NULL); - GPR_ASSERT(typ->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(typ->value, "JWT") == 0); - - GPR_ASSERT(kid != NULL); - GPR_ASSERT(kid->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(kid->value, "e6b5137873db8d2ef81e06a47289e6434ec8a165") == - 0); -} - -static void check_jwt_claim(grpc_json *claim, const char *expected_audience, - const char *expected_scope) { - gpr_timespec expiration = gpr_time_0(GPR_CLOCK_REALTIME); - gpr_timespec issue_time = gpr_time_0(GPR_CLOCK_REALTIME); - gpr_timespec parsed_lifetime; - grpc_json *iss = NULL; - grpc_json *scope = NULL; - grpc_json *aud = NULL; - grpc_json *exp = NULL; - grpc_json *iat = NULL; - grpc_json *sub = NULL; - grpc_json *ptr; - - for (ptr = claim->child; ptr; ptr = ptr->next) { - if (strcmp(ptr->key, "iss") == 0) { - iss = ptr; - } else if (strcmp(ptr->key, "sub") == 0) { - sub = ptr; - } else if (strcmp(ptr->key, "scope") == 0) { - scope = ptr; - } else if (strcmp(ptr->key, "aud") == 0) { - aud = ptr; - } else if (strcmp(ptr->key, "exp") == 0) { - exp = ptr; - } else if (strcmp(ptr->key, "iat") == 0) { - iat = ptr; - } - } - - GPR_ASSERT(iss != NULL); - GPR_ASSERT(iss->type == GRPC_JSON_STRING); - GPR_ASSERT( - strcmp( - iss->value, - "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com") == - 0); - - if (expected_scope != NULL) { - GPR_ASSERT(scope != NULL); - GPR_ASSERT(sub == NULL); - GPR_ASSERT(scope->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(scope->value, expected_scope) == 0); - } else { - /* Claims without scope must have a sub. */ - GPR_ASSERT(scope == NULL); - GPR_ASSERT(sub != NULL); - GPR_ASSERT(sub->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(iss->value, sub->value) == 0); - } - - GPR_ASSERT(aud != NULL); - GPR_ASSERT(aud->type == GRPC_JSON_STRING); - GPR_ASSERT(strcmp(aud->value, expected_audience) == 0); - - GPR_ASSERT(exp != NULL); - GPR_ASSERT(exp->type == GRPC_JSON_NUMBER); - expiration.tv_sec = strtol(exp->value, NULL, 10); - - GPR_ASSERT(iat != NULL); - GPR_ASSERT(iat->type == GRPC_JSON_NUMBER); - issue_time.tv_sec = strtol(iat->value, NULL, 10); - - parsed_lifetime = gpr_time_sub(expiration, issue_time); - GPR_ASSERT(parsed_lifetime.tv_sec == grpc_max_auth_token_lifetime().tv_sec); -} - -static void check_jwt_signature(const char *b64_signature, RSA *rsa_key, - const char *signed_data, - size_t signed_data_size) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); - EVP_PKEY *key = EVP_PKEY_new(); - - grpc_slice sig = grpc_base64_decode(&exec_ctx, b64_signature, 1); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig)); - GPR_ASSERT(GRPC_SLICE_LENGTH(sig) == 128); - - GPR_ASSERT(md_ctx != NULL); - GPR_ASSERT(key != NULL); - EVP_PKEY_set1_RSA(key, rsa_key); - - GPR_ASSERT(EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key) == 1); - GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) == - 1); - GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(sig), - GRPC_SLICE_LENGTH(sig)) == 1); - - grpc_slice_unref_internal(&exec_ctx, sig); - if (key != NULL) EVP_PKEY_free(key); - if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); - - grpc_exec_ctx_finish(&exec_ctx); -} - -static char *service_account_creds_jwt_encode_and_sign( - const grpc_auth_json_key *key) { - return grpc_jwt_encode_and_sign(key, GRPC_JWT_OAUTH2_AUDIENCE, - grpc_max_auth_token_lifetime(), test_scope); -} - -static char *jwt_creds_jwt_encode_and_sign(const grpc_auth_json_key *key) { - return grpc_jwt_encode_and_sign(key, test_service_url, - grpc_max_auth_token_lifetime(), NULL); -} - -static void service_account_creds_check_jwt_claim(grpc_json *claim) { - check_jwt_claim(claim, GRPC_JWT_OAUTH2_AUDIENCE, test_scope); -} - -static void jwt_creds_check_jwt_claim(grpc_json *claim) { - check_jwt_claim(claim, test_service_url, NULL); -} - -static void test_jwt_encode_and_sign( - char *(*jwt_encode_and_sign_func)(const grpc_auth_json_key *), - void (*check_jwt_claim_func)(grpc_json *)) { - char *json_string = test_json_key_str(NULL); - grpc_json *parsed_header = NULL; - grpc_json *parsed_claim = NULL; - char *scratchpad; - grpc_auth_json_key json_key = - grpc_auth_json_key_create_from_string(json_string); - const char *b64_signature; - size_t offset = 0; - char *jwt = jwt_encode_and_sign_func(&json_key); - const char *dot = strchr(jwt, '.'); - GPR_ASSERT(dot != NULL); - parsed_header = - parse_json_part_from_jwt(jwt, (size_t)(dot - jwt), &scratchpad); - GPR_ASSERT(parsed_header != NULL); - check_jwt_header(parsed_header); - offset = (size_t)(dot - jwt) + 1; - grpc_json_destroy(parsed_header); - gpr_free(scratchpad); - - dot = strchr(jwt + offset, '.'); - GPR_ASSERT(dot != NULL); - parsed_claim = parse_json_part_from_jwt( - jwt + offset, (size_t)(dot - (jwt + offset)), &scratchpad); - GPR_ASSERT(parsed_claim != NULL); - check_jwt_claim_func(parsed_claim); - offset = (size_t)(dot - jwt) + 1; - grpc_json_destroy(parsed_claim); - gpr_free(scratchpad); - - dot = strchr(jwt + offset, '.'); - GPR_ASSERT(dot == NULL); /* no more part. */ - b64_signature = jwt + offset; - check_jwt_signature(b64_signature, json_key.private_key, jwt, offset - 1); - - gpr_free(json_string); - grpc_auth_json_key_destruct(&json_key); - gpr_free(jwt); -} - -static void test_service_account_creds_jwt_encode_and_sign(void) { - test_jwt_encode_and_sign(service_account_creds_jwt_encode_and_sign, - service_account_creds_check_jwt_claim); -} - -static void test_jwt_creds_jwt_encode_and_sign(void) { - test_jwt_encode_and_sign(jwt_creds_jwt_encode_and_sign, - jwt_creds_check_jwt_claim); -} - -static void test_parse_refresh_token_success(void) { - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(test_refresh_token_str); - GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token)); - GPR_ASSERT(refresh_token.type != NULL && - (strcmp(refresh_token.type, "authorized_user") == 0)); - GPR_ASSERT(refresh_token.client_id != NULL && - (strcmp(refresh_token.client_id, - "32555999999.apps.googleusercontent.com") == 0)); - GPR_ASSERT( - refresh_token.client_secret != NULL && - (strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret") == 0)); - GPR_ASSERT(refresh_token.refresh_token != NULL && - (strcmp(refresh_token.refresh_token, - "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42") == 0)); - grpc_auth_refresh_token_destruct(&refresh_token); -} - -static void test_parse_refresh_token_failure_no_type(void) { - const char refresh_token_str[] = - "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," - " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," - " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"}"; - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(refresh_token_str); - GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); -} - -static void test_parse_refresh_token_failure_no_client_id(void) { - const char refresh_token_str[] = - "{ \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," - " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," - " \"type\": \"authorized_user\"}"; - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(refresh_token_str); - GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); -} - -static void test_parse_refresh_token_failure_no_client_secret(void) { - const char refresh_token_str[] = - "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," - " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," - " \"type\": \"authorized_user\"}"; - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(refresh_token_str); - GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); -} - -static void test_parse_refresh_token_failure_no_refresh_token(void) { - const char refresh_token_str[] = - "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," - " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," - " \"type\": \"authorized_user\"}"; - grpc_auth_refresh_token refresh_token = - grpc_auth_refresh_token_create_from_string(refresh_token_str); - GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_parse_json_key_success(); - test_parse_json_key_failure_bad_json(); - test_parse_json_key_failure_no_type(); - test_parse_json_key_failure_no_client_id(); - test_parse_json_key_failure_no_client_email(); - test_parse_json_key_failure_no_private_key_id(); - test_parse_json_key_failure_no_private_key(); - test_service_account_creds_jwt_encode_and_sign(); - test_jwt_creds_jwt_encode_and_sign(); - test_parse_refresh_token_success(); - test_parse_refresh_token_failure_no_type(); - test_parse_refresh_token_failure_no_client_id(); - test_parse_refresh_token_failure_no_client_secret(); - test_parse_refresh_token_failure_no_refresh_token(); - return 0; -} diff --git a/test/core/security/json_token_test.cc b/test/core/security/json_token_test.cc new file mode 100644 index 0000000000..70661a111b --- /dev/null +++ b/test/core/security/json_token_test.cc @@ -0,0 +1,501 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/security/credentials/jwt/json_token.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/json/json.h" +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" +#include "src/core/lib/slice/b64.h" +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +/* This JSON key was generated with the GCE console and revoked immediately. + The identifiers have been changed as well. + Maximum size for a string literal is 509 chars in C89, yay! */ +static const char test_json_key_str_part1[] = + "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" + "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" + "qg" + "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" + "rWBQvS4hle4LfijkP3J5BG+" + "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" + "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" + "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" + "8HpCqFYM9V8f34SBWfD4fRFT+n/" + "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; +static const char test_json_key_str_part2[] = + "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" + "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" + "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" + "G" + "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" + "A" + "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" + "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" + "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" + "Y" + "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; +static const char test_json_key_str_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + +/* Test refresh token. */ +static const char test_refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + +static const char test_scope[] = "myperm1 myperm2"; + +static const char test_service_url[] = "https://foo.com/foo.v1"; + +static char *test_json_key_str(const char *bad_part3) { + const char *part3 = bad_part3 != NULL ? bad_part3 : test_json_key_str_part3; + size_t result_len = strlen(test_json_key_str_part1) + + strlen(test_json_key_str_part2) + strlen(part3); + char *result = static_cast(gpr_malloc(result_len + 1)); + char *current = result; + strcpy(result, test_json_key_str_part1); + current += strlen(test_json_key_str_part1); + strcpy(current, test_json_key_str_part2); + current += strlen(test_json_key_str_part2); + strcpy(current, part3); + return result; +} + +static void test_parse_json_key_success(void) { + char *json_string = test_json_key_str(NULL); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(grpc_auth_json_key_is_valid(&json_key)); + GPR_ASSERT(json_key.type != NULL && + strcmp(json_key.type, "service_account") == 0); + GPR_ASSERT(json_key.private_key_id != NULL && + strcmp(json_key.private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); + GPR_ASSERT(json_key.client_id != NULL && + strcmp(json_key.client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); + GPR_ASSERT(json_key.client_email != NULL && + strcmp(json_key.client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); + GPR_ASSERT(json_key.private_key != NULL); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_bad_json(void) { + const char non_closing_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" "; + char *json_string = test_json_key_str(non_closing_part3); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_no_type(void) { + const char no_type_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\" }"; + char *json_string = test_json_key_str(no_type_part3); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_no_client_id(void) { + const char no_client_id_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", " + "\"type\": \"service_account\" }"; + char *json_string = test_json_key_str(no_client_id_part3); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_no_client_email(void) { + const char no_client_email_part3[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + char *json_string = test_json_key_str(no_client_email_part3); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_no_private_key_id(void) { + const char no_private_key_id_part3[] = + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + char *json_string = test_json_key_str(no_private_key_id_part3); + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); +} + +static void test_parse_json_key_failure_no_private_key(void) { + const char no_private_key_json_string[] = + "{ \"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(no_private_key_json_string); + GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key)); + grpc_auth_json_key_destruct(&json_key); +} + +static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, + char **scratchpad) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + char *b64; + char *decoded; + grpc_json *json; + grpc_slice slice; + b64 = static_cast(gpr_malloc(len + 1)); + strncpy(b64, str, len); + b64[len] = '\0'; + slice = grpc_base64_decode(&exec_ctx, b64, 1); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(slice)); + decoded = static_cast(gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1)); + strncpy(decoded, (const char *)GRPC_SLICE_START_PTR(slice), + GRPC_SLICE_LENGTH(slice)); + decoded[GRPC_SLICE_LENGTH(slice)] = '\0'; + json = grpc_json_parse_string(decoded); + gpr_free(b64); + *scratchpad = decoded; + grpc_slice_unref(slice); + grpc_exec_ctx_finish(&exec_ctx); + return json; +} + +static void check_jwt_header(grpc_json *header) { + grpc_json *ptr; + grpc_json *alg = NULL; + grpc_json *typ = NULL; + grpc_json *kid = NULL; + + for (ptr = header->child; ptr; ptr = ptr->next) { + if (strcmp(ptr->key, "alg") == 0) { + alg = ptr; + } else if (strcmp(ptr->key, "typ") == 0) { + typ = ptr; + } else if (strcmp(ptr->key, "kid") == 0) { + kid = ptr; + } + } + GPR_ASSERT(alg != NULL); + GPR_ASSERT(alg->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(alg->value, "RS256") == 0); + + GPR_ASSERT(typ != NULL); + GPR_ASSERT(typ->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(typ->value, "JWT") == 0); + + GPR_ASSERT(kid != NULL); + GPR_ASSERT(kid->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(kid->value, "e6b5137873db8d2ef81e06a47289e6434ec8a165") == + 0); +} + +static void check_jwt_claim(grpc_json *claim, const char *expected_audience, + const char *expected_scope) { + gpr_timespec expiration = gpr_time_0(GPR_CLOCK_REALTIME); + gpr_timespec issue_time = gpr_time_0(GPR_CLOCK_REALTIME); + gpr_timespec parsed_lifetime; + grpc_json *iss = NULL; + grpc_json *scope = NULL; + grpc_json *aud = NULL; + grpc_json *exp = NULL; + grpc_json *iat = NULL; + grpc_json *sub = NULL; + grpc_json *ptr; + + for (ptr = claim->child; ptr; ptr = ptr->next) { + if (strcmp(ptr->key, "iss") == 0) { + iss = ptr; + } else if (strcmp(ptr->key, "sub") == 0) { + sub = ptr; + } else if (strcmp(ptr->key, "scope") == 0) { + scope = ptr; + } else if (strcmp(ptr->key, "aud") == 0) { + aud = ptr; + } else if (strcmp(ptr->key, "exp") == 0) { + exp = ptr; + } else if (strcmp(ptr->key, "iat") == 0) { + iat = ptr; + } + } + + GPR_ASSERT(iss != NULL); + GPR_ASSERT(iss->type == GRPC_JSON_STRING); + GPR_ASSERT( + strcmp( + iss->value, + "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com") == + 0); + + if (expected_scope != NULL) { + GPR_ASSERT(scope != NULL); + GPR_ASSERT(sub == NULL); + GPR_ASSERT(scope->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(scope->value, expected_scope) == 0); + } else { + /* Claims without scope must have a sub. */ + GPR_ASSERT(scope == NULL); + GPR_ASSERT(sub != NULL); + GPR_ASSERT(sub->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(iss->value, sub->value) == 0); + } + + GPR_ASSERT(aud != NULL); + GPR_ASSERT(aud->type == GRPC_JSON_STRING); + GPR_ASSERT(strcmp(aud->value, expected_audience) == 0); + + GPR_ASSERT(exp != NULL); + GPR_ASSERT(exp->type == GRPC_JSON_NUMBER); + expiration.tv_sec = strtol(exp->value, NULL, 10); + + GPR_ASSERT(iat != NULL); + GPR_ASSERT(iat->type == GRPC_JSON_NUMBER); + issue_time.tv_sec = strtol(iat->value, NULL, 10); + + parsed_lifetime = gpr_time_sub(expiration, issue_time); + GPR_ASSERT(parsed_lifetime.tv_sec == grpc_max_auth_token_lifetime().tv_sec); +} + +static void check_jwt_signature(const char *b64_signature, RSA *rsa_key, + const char *signed_data, + size_t signed_data_size) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); + EVP_PKEY *key = EVP_PKEY_new(); + + grpc_slice sig = grpc_base64_decode(&exec_ctx, b64_signature, 1); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig)); + GPR_ASSERT(GRPC_SLICE_LENGTH(sig) == 128); + + GPR_ASSERT(md_ctx != NULL); + GPR_ASSERT(key != NULL); + EVP_PKEY_set1_RSA(key, rsa_key); + + GPR_ASSERT(EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key) == 1); + GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) == + 1); + GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(sig), + GRPC_SLICE_LENGTH(sig)) == 1); + + grpc_slice_unref_internal(&exec_ctx, sig); + if (key != NULL) EVP_PKEY_free(key); + if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); + + grpc_exec_ctx_finish(&exec_ctx); +} + +static char *service_account_creds_jwt_encode_and_sign( + const grpc_auth_json_key *key) { + return grpc_jwt_encode_and_sign(key, GRPC_JWT_OAUTH2_AUDIENCE, + grpc_max_auth_token_lifetime(), test_scope); +} + +static char *jwt_creds_jwt_encode_and_sign(const grpc_auth_json_key *key) { + return grpc_jwt_encode_and_sign(key, test_service_url, + grpc_max_auth_token_lifetime(), NULL); +} + +static void service_account_creds_check_jwt_claim(grpc_json *claim) { + check_jwt_claim(claim, GRPC_JWT_OAUTH2_AUDIENCE, test_scope); +} + +static void jwt_creds_check_jwt_claim(grpc_json *claim) { + check_jwt_claim(claim, test_service_url, NULL); +} + +static void test_jwt_encode_and_sign( + char *(*jwt_encode_and_sign_func)(const grpc_auth_json_key *), + void (*check_jwt_claim_func)(grpc_json *)) { + char *json_string = test_json_key_str(NULL); + grpc_json *parsed_header = NULL; + grpc_json *parsed_claim = NULL; + char *scratchpad; + grpc_auth_json_key json_key = + grpc_auth_json_key_create_from_string(json_string); + const char *b64_signature; + size_t offset = 0; + char *jwt = jwt_encode_and_sign_func(&json_key); + const char *dot = strchr(jwt, '.'); + GPR_ASSERT(dot != NULL); + parsed_header = + parse_json_part_from_jwt(jwt, (size_t)(dot - jwt), &scratchpad); + GPR_ASSERT(parsed_header != NULL); + check_jwt_header(parsed_header); + offset = (size_t)(dot - jwt) + 1; + grpc_json_destroy(parsed_header); + gpr_free(scratchpad); + + dot = strchr(jwt + offset, '.'); + GPR_ASSERT(dot != NULL); + parsed_claim = parse_json_part_from_jwt( + jwt + offset, (size_t)(dot - (jwt + offset)), &scratchpad); + GPR_ASSERT(parsed_claim != NULL); + check_jwt_claim_func(parsed_claim); + offset = (size_t)(dot - jwt) + 1; + grpc_json_destroy(parsed_claim); + gpr_free(scratchpad); + + dot = strchr(jwt + offset, '.'); + GPR_ASSERT(dot == NULL); /* no more part. */ + b64_signature = jwt + offset; + check_jwt_signature(b64_signature, json_key.private_key, jwt, offset - 1); + + gpr_free(json_string); + grpc_auth_json_key_destruct(&json_key); + gpr_free(jwt); +} + +static void test_service_account_creds_jwt_encode_and_sign(void) { + test_jwt_encode_and_sign(service_account_creds_jwt_encode_and_sign, + service_account_creds_check_jwt_claim); +} + +static void test_jwt_creds_jwt_encode_and_sign(void) { + test_jwt_encode_and_sign(jwt_creds_jwt_encode_and_sign, + jwt_creds_check_jwt_claim); +} + +static void test_parse_refresh_token_success(void) { + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(test_refresh_token_str); + GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token)); + GPR_ASSERT(refresh_token.type != NULL && + (strcmp(refresh_token.type, "authorized_user") == 0)); + GPR_ASSERT(refresh_token.client_id != NULL && + (strcmp(refresh_token.client_id, + "32555999999.apps.googleusercontent.com") == 0)); + GPR_ASSERT( + refresh_token.client_secret != NULL && + (strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret") == 0)); + GPR_ASSERT(refresh_token.refresh_token != NULL && + (strcmp(refresh_token.refresh_token, + "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42") == 0)); + grpc_auth_refresh_token_destruct(&refresh_token); +} + +static void test_parse_refresh_token_failure_no_type(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_client_id(void) { + const char refresh_token_str[] = + "{ \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_client_secret(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_refresh_token(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_parse_json_key_success(); + test_parse_json_key_failure_bad_json(); + test_parse_json_key_failure_no_type(); + test_parse_json_key_failure_no_client_id(); + test_parse_json_key_failure_no_client_email(); + test_parse_json_key_failure_no_private_key_id(); + test_parse_json_key_failure_no_private_key(); + test_service_account_creds_jwt_encode_and_sign(); + test_jwt_creds_jwt_encode_and_sign(); + test_parse_refresh_token_success(); + test_parse_refresh_token_failure_no_type(); + test_parse_refresh_token_failure_no_client_id(); + test_parse_refresh_token_failure_no_client_secret(); + test_parse_refresh_token_failure_no_refresh_token(); + return 0; +} diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c deleted file mode 100644 index a4bfe0130e..0000000000 --- a/test/core/security/jwt_verifier_test.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" - -#include - -#include - -#include -#include -#include -#include - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/security/credentials/jwt/json_token.h" -#include "src/core/lib/slice/b64.h" -#include "test/core/util/test_config.h" - -/* This JSON key was generated with the GCE console and revoked immediately. - The identifiers have been changed as well. - Maximum size for a string literal is 509 chars in C89, yay! */ -static const char json_key_str_part1[] = - "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" - "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" - "qg" - "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" - "rWBQvS4hle4LfijkP3J5BG+" - "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" - "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" - "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" - "8HpCqFYM9V8f34SBWfD4fRFT+n/" - "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; -static const char json_key_str_part2[] = - "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" - "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" - "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" - "G" - "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" - "A" - "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" - "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" - "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" - "Y" - "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; -static const char json_key_str_part3_for_google_email_issuer[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." - "com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; -/* Trick our JWT library into issuing a JWT with iss=accounts.google.com. */ -static const char json_key_str_part3_for_url_issuer[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": \"accounts.google.com\", " - "\"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; -static const char json_key_str_part3_for_custom_email_issuer[] = - "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " - "\"client_email\": " - "\"foo@bar.com\", \"client_id\": " - "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." - "com\", \"type\": \"service_account\" }"; - -static grpc_jwt_verifier_email_domain_key_url_mapping custom_mapping = { - "bar.com", "keys.bar.com/jwk"}; - -static const char expected_user_data[] = "user data"; - -static const char good_jwk_set[] = - "{" - " \"keys\": [" - " {" - " \"kty\": \"RSA\"," - " \"alg\": \"RS256\"," - " \"use\": \"sig\"," - " \"kid\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\"," - " \"n\": " - "\"4S8myegefIeRdynuYkSqBYaOLDvU19cHKC56RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ6mxP" - "QutZC1nKNJ6D-tYFC9LiGV7gt-KOQ_cnkEb4hcMw_xF_OI1FCx6cBcM0-" - "RjiQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFU=\"," - " \"e\": \"AQAB\"" - " }" - " ]" - "}"; - -static gpr_timespec expected_lifetime = {3600, 0, GPR_TIMESPAN}; - -static const char good_google_email_keys_part1[] = - "{\"e6b5137873db8d2ef81e06a47289e6434ec8a165\": \"-----BEGIN " - "CERTIFICATE-----" - "\\nMIICATCCAWoCCQDEywLhxvHjnDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB\\nVTET" - "MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\\ncyBQdHkgTHR" - "kMB4XDTE1MDYyOTA4Mzk1MFoXDTI1MDYyNjA4Mzk1MFowRTELMAkG\\nA1UEBhMCQVUxEzARBg" - "NVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\\nIFdpZGdpdHMgUHR5IEx0ZDCBn" - "zANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4S8m\\nyegefIeRdynuYkSqBYaOLDvU19cHKC56" - "RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ\\n6mxPQutZC1nKNJ6D+tYFC9LiGV7gt+KOQ/"; - -static const char good_google_email_keys_part2[] = - "cnkEb4hcMw/xF/OI1FCx6cBcM0+" - "Rji\\nQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFUCAwEAATANBgkqhkiG9w0BAQsF\\nA" - "AOBgQBfu69FkPmBknbKNFgurPz78kbs3VNN+k/" - "PUgO5DHKskJmgK2TbtvX2VMpx\\nkftmHGzgzMzUlOtigCaGMgHWjfqjpP9uuDbahXrZBJzB8c" - "Oq7MrQF8r17qVvo3Ue\\nPjTKQMAsU8uxTEMmeuz9L6yExs0rfd6bPOrQkAoVfFfiYB3/" - "pA==\\n-----END CERTIFICATE-----\\n\"}"; - -static const char expected_audience[] = "https://foo.com"; - -static const char good_openid_config[] = - "{" - " \"issuer\": \"https://accounts.google.com\"," - " \"authorization_endpoint\": " - "\"https://accounts.google.com/o/oauth2/v2/auth\"," - " \"token_endpoint\": \"https://www.googleapis.com/oauth2/v4/token\"," - " \"userinfo_endpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\"," - " \"revocation_endpoint\": \"https://accounts.google.com/o/oauth2/revoke\"," - " \"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\"" - "}"; - -static const char expired_claims[] = - "{ \"aud\": \"https://foo.com\"," - " \"iss\": \"blah.foo.com\"," - " \"sub\": \"juju@blah.foo.com\"," - " \"jti\": \"jwtuniqueid\"," - " \"iat\": 100," /* Way back in the past... */ - " \"exp\": 120," - " \"nbf\": 60," - " \"foo\": \"bar\"}"; - -static const char claims_without_time_constraint[] = - "{ \"aud\": \"https://foo.com\"," - " \"iss\": \"blah.foo.com\"," - " \"sub\": \"juju@blah.foo.com\"," - " \"jti\": \"jwtuniqueid\"," - " \"foo\": \"bar\"}"; - -static const char claims_with_bad_subject[] = - "{ \"aud\": \"https://foo.com\"," - " \"iss\": \"evil@blah.foo.com\"," - " \"sub\": \"juju@blah.foo.com\"," - " \"jti\": \"jwtuniqueid\"," - " \"foo\": \"bar\"}"; - -static const char invalid_claims[] = - "{ \"aud\": \"https://foo.com\"," - " \"iss\": 46," /* Issuer cannot be a number. */ - " \"sub\": \"juju@blah.foo.com\"," - " \"jti\": \"jwtuniqueid\"," - " \"foo\": \"bar\"}"; - -typedef struct { - grpc_jwt_verifier_status expected_status; - const char *expected_issuer; - const char *expected_subject; -} verifier_test_config; - -static void test_jwt_issuer_email_domain(void) { - const char *d = grpc_jwt_issuer_email_domain("https://foo.com"); - GPR_ASSERT(d == NULL); - d = grpc_jwt_issuer_email_domain("foo.com"); - GPR_ASSERT(d == NULL); - d = grpc_jwt_issuer_email_domain(""); - GPR_ASSERT(d == NULL); - d = grpc_jwt_issuer_email_domain("@"); - GPR_ASSERT(d == NULL); - d = grpc_jwt_issuer_email_domain("bar@foo"); - GPR_ASSERT(strcmp(d, "foo") == 0); - d = grpc_jwt_issuer_email_domain("bar@foo.com"); - GPR_ASSERT(strcmp(d, "foo.com") == 0); - d = grpc_jwt_issuer_email_domain("bar@blah.foo.com"); - GPR_ASSERT(strcmp(d, "foo.com") == 0); - d = grpc_jwt_issuer_email_domain("bar.blah@blah.foo.com"); - GPR_ASSERT(strcmp(d, "foo.com") == 0); - d = grpc_jwt_issuer_email_domain("bar.blah@baz.blah.foo.com"); - GPR_ASSERT(strcmp(d, "foo.com") == 0); - - /* This is not a very good parser but make sure we do not crash on these weird - inputs. */ - d = grpc_jwt_issuer_email_domain("@foo"); - GPR_ASSERT(strcmp(d, "foo") == 0); - d = grpc_jwt_issuer_email_domain("bar@."); - GPR_ASSERT(d != NULL); - d = grpc_jwt_issuer_email_domain("bar@.."); - GPR_ASSERT(d != NULL); - d = grpc_jwt_issuer_email_domain("bar@..."); - GPR_ASSERT(d != NULL); -} - -static void test_claims_success(void) { - grpc_jwt_claims *claims; - grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint); - grpc_json *json = grpc_json_parse_string_with_len( - (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); - GPR_ASSERT(json != NULL); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); - GPR_ASSERT(claims != NULL); - GPR_ASSERT(grpc_jwt_claims_json(claims) == json); - GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); - GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == - GRPC_JWT_VERIFIER_OK); - grpc_jwt_claims_destroy(&exec_ctx, claims); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_expired_claims_failure(void) { - grpc_jwt_claims *claims; - grpc_slice s = grpc_slice_from_copied_string(expired_claims); - grpc_json *json = grpc_json_parse_string_with_len( - (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); - gpr_timespec exp_iat = {100, 0, GPR_CLOCK_REALTIME}; - gpr_timespec exp_exp = {120, 0, GPR_CLOCK_REALTIME}; - gpr_timespec exp_nbf = {60, 0, GPR_CLOCK_REALTIME}; - GPR_ASSERT(json != NULL); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); - GPR_ASSERT(claims != NULL); - GPR_ASSERT(grpc_jwt_claims_json(claims) == json); - GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0); - GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); - GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_issued_at(claims), exp_iat) == 0); - GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_expires_at(claims), exp_exp) == 0); - GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_not_before(claims), exp_nbf) == 0); - - GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == - GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE); - grpc_jwt_claims_destroy(&exec_ctx, claims); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_invalid_claims_failure(void) { - grpc_slice s = grpc_slice_from_copied_string(invalid_claims); - grpc_json *json = grpc_json_parse_string_with_len( - (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(grpc_jwt_claims_from_json(&exec_ctx, json, s) == NULL); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_bad_audience_claims_failure(void) { - grpc_jwt_claims *claims; - grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint); - grpc_json *json = grpc_json_parse_string_with_len( - (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); - GPR_ASSERT(json != NULL); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); - GPR_ASSERT(claims != NULL); - GPR_ASSERT(grpc_jwt_claims_check(claims, "https://bar.com") == - GRPC_JWT_VERIFIER_BAD_AUDIENCE); - grpc_jwt_claims_destroy(&exec_ctx, claims); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_bad_subject_claims_failure(void) { - grpc_jwt_claims *claims; - grpc_slice s = grpc_slice_from_copied_string(claims_with_bad_subject); - grpc_json *json = grpc_json_parse_string_with_len( - (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); - GPR_ASSERT(json != NULL); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); - GPR_ASSERT(claims != NULL); - GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == - GRPC_JWT_VERIFIER_BAD_SUBJECT); - grpc_jwt_claims_destroy(&exec_ctx, claims); - grpc_exec_ctx_finish(&exec_ctx); -} - -static char *json_key_str(const char *last_part) { - size_t result_len = strlen(json_key_str_part1) + strlen(json_key_str_part2) + - strlen(last_part); - char *result = gpr_malloc(result_len + 1); - char *current = result; - strcpy(result, json_key_str_part1); - current += strlen(json_key_str_part1); - strcpy(current, json_key_str_part2); - current += strlen(json_key_str_part2); - strcpy(current, last_part); - return result; -} - -static char *good_google_email_keys(void) { - size_t result_len = strlen(good_google_email_keys_part1) + - strlen(good_google_email_keys_part2); - char *result = gpr_malloc(result_len + 1); - char *current = result; - strcpy(result, good_google_email_keys_part1); - current += strlen(good_google_email_keys_part1); - strcpy(current, good_google_email_keys_part2); - return result; -} - -static grpc_httpcli_response http_response(int status, char *body) { - grpc_httpcli_response response; - memset(&response, 0, sizeof(grpc_httpcli_response)); - response.status = status; - response.body = body; - response.body_length = strlen(body); - return response; -} - -static int httpcli_post_should_not_be_called( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - const char *body_bytes, size_t body_size, grpc_millis deadline, - grpc_closure *on_done, grpc_httpcli_response *response) { - GPR_ASSERT("HTTP POST should not be called" == NULL); - return 1; -} - -static int httpcli_get_google_keys_for_email( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, good_google_email_keys()); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); - GPR_ASSERT(strcmp(request->http.path, - "/robot/v1/metadata/x509/" - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com") == 0); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static void on_verification_success(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims) { - GPR_ASSERT(status == GRPC_JWT_VERIFIER_OK); - GPR_ASSERT(claims != NULL); - GPR_ASSERT(user_data == (void *)expected_user_data); - GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), expected_audience) == 0); - grpc_jwt_claims_destroy(exec_ctx, claims); -} - -static void test_jwt_verifier_google_email_issuer_success(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_google_keys_for_email, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_success, (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(jwt); - grpc_httpcli_set_override(NULL, NULL); -} - -static int httpcli_get_custom_keys_for_email( - grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, gpr_strdup(good_jwk_set)); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0); - GPR_ASSERT(strcmp(request->http.path, "/jwk/foo@bar.com") == 0); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static void test_jwt_verifier_custom_email_issuer_success(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(&custom_mapping, 1); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_custom_email_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_custom_keys_for_email, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_success, (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(jwt); - grpc_httpcli_set_override(NULL, NULL); -} - -static int httpcli_get_jwk_set(grpc_exec_ctx *exec_ctx, - const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, gpr_strdup(good_jwk_set)); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); - GPR_ASSERT(strcmp(request->http.path, "/oauth2/v3/certs") == 0); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static int httpcli_get_openid_config(grpc_exec_ctx *exec_ctx, - const grpc_httpcli_request *request, - grpc_millis deadline, - grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, gpr_strdup(good_openid_config)); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0); - GPR_ASSERT(strcmp(request->http.path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0); - grpc_httpcli_set_override(httpcli_get_jwk_set, - httpcli_post_should_not_be_called); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static void test_jwt_verifier_url_issuer_success(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_url_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_openid_config, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_success, (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(jwt); - grpc_httpcli_set_override(NULL, NULL); -} - -static void on_verification_key_retrieval_error(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims) { - GPR_ASSERT(status == GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR); - GPR_ASSERT(claims == NULL); - GPR_ASSERT(user_data == (void *)expected_user_data); -} - -static int httpcli_get_bad_json(grpc_exec_ctx *exec_ctx, - const grpc_httpcli_request *request, - grpc_millis deadline, grpc_closure *on_done, - grpc_httpcli_response *response) { - *response = http_response(200, gpr_strdup("{\"bad\": \"stuff\"}")); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); - return 1; -} - -static void test_jwt_verifier_url_issuer_bad_config(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_url_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_bad_json, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_key_retrieval_error, - (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(jwt); - grpc_httpcli_set_override(NULL, NULL); -} - -static void test_jwt_verifier_bad_json_key(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_bad_json, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_key_retrieval_error, - (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(jwt); - grpc_httpcli_set_override(NULL, NULL); -} - -static void corrupt_jwt_sig(char *jwt) { - grpc_slice sig; - char *bad_b64_sig; - uint8_t *sig_bytes; - char *last_dot = strrchr(jwt, '.'); - GPR_ASSERT(last_dot != NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - sig = grpc_base64_decode(&exec_ctx, last_dot + 1, 1); - grpc_exec_ctx_finish(&exec_ctx); - } - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig)); - sig_bytes = GRPC_SLICE_START_PTR(sig); - (*sig_bytes)++; /* Corrupt first byte. */ - bad_b64_sig = grpc_base64_encode(GRPC_SLICE_START_PTR(sig), - GRPC_SLICE_LENGTH(sig), 1, 0); - memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig)); - gpr_free(bad_b64_sig); - grpc_slice_unref(sig); -} - -static void on_verification_bad_signature(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims) { - GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_SIGNATURE); - GPR_ASSERT(claims == NULL); - GPR_ASSERT(user_data == (void *)expected_user_data); -} - -static void test_jwt_verifier_bad_signature(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - char *jwt = NULL; - char *key_str = json_key_str(json_key_str_part3_for_url_issuer); - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); - gpr_free(key_str); - GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); - grpc_httpcli_set_override(httpcli_get_openid_config, - httpcli_post_should_not_be_called); - jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, - NULL); - grpc_auth_json_key_destruct(&key); - corrupt_jwt_sig(jwt); - GPR_ASSERT(jwt != NULL); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, - on_verification_bad_signature, - (void *)expected_user_data); - gpr_free(jwt); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - grpc_httpcli_set_override(NULL, NULL); -} - -static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx, - const grpc_httpcli_request *request, - grpc_millis deadline, - grpc_closure *on_done, - grpc_httpcli_response *response) { - GPR_ASSERT(0); - return 1; -} - -static void on_verification_bad_format(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims) { - GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_FORMAT); - GPR_ASSERT(claims == NULL); - GPR_ASSERT(user_data == (void *)expected_user_data); -} - -static void test_jwt_verifier_bad_format(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - httpcli_post_should_not_be_called); - grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, "bad jwt", - expected_audience, on_verification_bad_format, - (void *)expected_user_data); - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - grpc_httpcli_set_override(NULL, NULL); -} - -/* find verification key: bad jks, cannot find key in jks */ -/* bad signature custom provided email*/ -/* bad key */ - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_jwt_issuer_email_domain(); - test_claims_success(); - test_expired_claims_failure(); - test_invalid_claims_failure(); - test_bad_audience_claims_failure(); - test_bad_subject_claims_failure(); - test_jwt_verifier_google_email_issuer_success(); - test_jwt_verifier_custom_email_issuer_success(); - test_jwt_verifier_url_issuer_success(); - test_jwt_verifier_url_issuer_bad_config(); - test_jwt_verifier_bad_json_key(); - test_jwt_verifier_bad_signature(); - test_jwt_verifier_bad_format(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/security/jwt_verifier_test.cc b/test/core/security/jwt_verifier_test.cc new file mode 100644 index 0000000000..b0b94ba250 --- /dev/null +++ b/test/core/security/jwt_verifier_test.cc @@ -0,0 +1,634 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" + +#include + +#include + +#include +#include +#include +#include + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/security/credentials/jwt/json_token.h" +#include "src/core/lib/slice/b64.h" +#include "test/core/util/test_config.h" + +/* This JSON key was generated with the GCE console and revoked immediately. + The identifiers have been changed as well. + Maximum size for a string literal is 509 chars in C89, yay! */ +static const char json_key_str_part1[] = + "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----" + "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE" + "qg" + "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/" + "rWBQvS4hle4LfijkP3J5BG+" + "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+" + "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/" + "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/" + "8HpCqFYM9V8f34SBWfD4fRFT+n/" + "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+"; +static const char json_key_str_part2[] = + "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+" + "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/" + "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA" + "G" + "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz" + "A" + "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+" + "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/" + "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ" + "Y" + "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", "; +static const char json_key_str_part3_for_google_email_issuer[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount." + "com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; +/* Trick our JWT library into issuing a JWT with iss=accounts.google.com. */ +static const char json_key_str_part3_for_url_issuer[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": \"accounts.google.com\", " + "\"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; +static const char json_key_str_part3_for_custom_email_issuer[] = + "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", " + "\"client_email\": " + "\"foo@bar.com\", \"client_id\": " + "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." + "com\", \"type\": \"service_account\" }"; + +static grpc_jwt_verifier_email_domain_key_url_mapping custom_mapping = { + "bar.com", "keys.bar.com/jwk"}; + +static const char expected_user_data[] = "user data"; + +static const char good_jwk_set[] = + "{" + " \"keys\": [" + " {" + " \"kty\": \"RSA\"," + " \"alg\": \"RS256\"," + " \"use\": \"sig\"," + " \"kid\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\"," + " \"n\": " + "\"4S8myegefIeRdynuYkSqBYaOLDvU19cHKC56RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ6mxP" + "QutZC1nKNJ6D-tYFC9LiGV7gt-KOQ_cnkEb4hcMw_xF_OI1FCx6cBcM0-" + "RjiQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFU=\"," + " \"e\": \"AQAB\"" + " }" + " ]" + "}"; + +static gpr_timespec expected_lifetime = {3600, 0, GPR_TIMESPAN}; + +static const char good_google_email_keys_part1[] = + "{\"e6b5137873db8d2ef81e06a47289e6434ec8a165\": \"-----BEGIN " + "CERTIFICATE-----" + "\\nMIICATCCAWoCCQDEywLhxvHjnDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB\\nVTET" + "MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\\ncyBQdHkgTHR" + "kMB4XDTE1MDYyOTA4Mzk1MFoXDTI1MDYyNjA4Mzk1MFowRTELMAkG\\nA1UEBhMCQVUxEzARBg" + "NVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\\nIFdpZGdpdHMgUHR5IEx0ZDCBn" + "zANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4S8m\\nyegefIeRdynuYkSqBYaOLDvU19cHKC56" + "RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ\\n6mxPQutZC1nKNJ6D+tYFC9LiGV7gt+KOQ/"; + +static const char good_google_email_keys_part2[] = + "cnkEb4hcMw/xF/OI1FCx6cBcM0+" + "Rji\\nQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFUCAwEAATANBgkqhkiG9w0BAQsF\\nA" + "AOBgQBfu69FkPmBknbKNFgurPz78kbs3VNN+k/" + "PUgO5DHKskJmgK2TbtvX2VMpx\\nkftmHGzgzMzUlOtigCaGMgHWjfqjpP9uuDbahXrZBJzB8c" + "Oq7MrQF8r17qVvo3Ue\\nPjTKQMAsU8uxTEMmeuz9L6yExs0rfd6bPOrQkAoVfFfiYB3/" + "pA==\\n-----END CERTIFICATE-----\\n\"}"; + +static const char expected_audience[] = "https://foo.com"; + +static const char good_openid_config[] = + "{" + " \"issuer\": \"https://accounts.google.com\"," + " \"authorization_endpoint\": " + "\"https://accounts.google.com/o/oauth2/v2/auth\"," + " \"token_endpoint\": \"https://www.googleapis.com/oauth2/v4/token\"," + " \"userinfo_endpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\"," + " \"revocation_endpoint\": \"https://accounts.google.com/o/oauth2/revoke\"," + " \"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\"" + "}"; + +static const char expired_claims[] = + "{ \"aud\": \"https://foo.com\"," + " \"iss\": \"blah.foo.com\"," + " \"sub\": \"juju@blah.foo.com\"," + " \"jti\": \"jwtuniqueid\"," + " \"iat\": 100," /* Way back in the past... */ + " \"exp\": 120," + " \"nbf\": 60," + " \"foo\": \"bar\"}"; + +static const char claims_without_time_constraint[] = + "{ \"aud\": \"https://foo.com\"," + " \"iss\": \"blah.foo.com\"," + " \"sub\": \"juju@blah.foo.com\"," + " \"jti\": \"jwtuniqueid\"," + " \"foo\": \"bar\"}"; + +static const char claims_with_bad_subject[] = + "{ \"aud\": \"https://foo.com\"," + " \"iss\": \"evil@blah.foo.com\"," + " \"sub\": \"juju@blah.foo.com\"," + " \"jti\": \"jwtuniqueid\"," + " \"foo\": \"bar\"}"; + +static const char invalid_claims[] = + "{ \"aud\": \"https://foo.com\"," + " \"iss\": 46," /* Issuer cannot be a number. */ + " \"sub\": \"juju@blah.foo.com\"," + " \"jti\": \"jwtuniqueid\"," + " \"foo\": \"bar\"}"; + +typedef struct { + grpc_jwt_verifier_status expected_status; + const char *expected_issuer; + const char *expected_subject; +} verifier_test_config; + +static void test_jwt_issuer_email_domain(void) { + const char *d = grpc_jwt_issuer_email_domain("https://foo.com"); + GPR_ASSERT(d == NULL); + d = grpc_jwt_issuer_email_domain("foo.com"); + GPR_ASSERT(d == NULL); + d = grpc_jwt_issuer_email_domain(""); + GPR_ASSERT(d == NULL); + d = grpc_jwt_issuer_email_domain("@"); + GPR_ASSERT(d == NULL); + d = grpc_jwt_issuer_email_domain("bar@foo"); + GPR_ASSERT(strcmp(d, "foo") == 0); + d = grpc_jwt_issuer_email_domain("bar@foo.com"); + GPR_ASSERT(strcmp(d, "foo.com") == 0); + d = grpc_jwt_issuer_email_domain("bar@blah.foo.com"); + GPR_ASSERT(strcmp(d, "foo.com") == 0); + d = grpc_jwt_issuer_email_domain("bar.blah@blah.foo.com"); + GPR_ASSERT(strcmp(d, "foo.com") == 0); + d = grpc_jwt_issuer_email_domain("bar.blah@baz.blah.foo.com"); + GPR_ASSERT(strcmp(d, "foo.com") == 0); + + /* This is not a very good parser but make sure we do not crash on these weird + inputs. */ + d = grpc_jwt_issuer_email_domain("@foo"); + GPR_ASSERT(strcmp(d, "foo") == 0); + d = grpc_jwt_issuer_email_domain("bar@."); + GPR_ASSERT(d != NULL); + d = grpc_jwt_issuer_email_domain("bar@.."); + GPR_ASSERT(d != NULL); + d = grpc_jwt_issuer_email_domain("bar@..."); + GPR_ASSERT(d != NULL); +} + +static void test_claims_success(void) { + grpc_jwt_claims *claims; + grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint); + grpc_json *json = grpc_json_parse_string_with_len( + (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); + GPR_ASSERT(json != NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); + GPR_ASSERT(claims != NULL); + GPR_ASSERT(grpc_jwt_claims_json(claims) == json); + GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); + GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == + GRPC_JWT_VERIFIER_OK); + grpc_jwt_claims_destroy(&exec_ctx, claims); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_expired_claims_failure(void) { + grpc_jwt_claims *claims; + grpc_slice s = grpc_slice_from_copied_string(expired_claims); + grpc_json *json = grpc_json_parse_string_with_len( + (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); + gpr_timespec exp_iat = {100, 0, GPR_CLOCK_REALTIME}; + gpr_timespec exp_exp = {120, 0, GPR_CLOCK_REALTIME}; + gpr_timespec exp_nbf = {60, 0, GPR_CLOCK_REALTIME}; + GPR_ASSERT(json != NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); + GPR_ASSERT(claims != NULL); + GPR_ASSERT(grpc_jwt_claims_json(claims) == json); + GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju@blah.foo.com") == 0); + GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); + GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_issued_at(claims), exp_iat) == 0); + GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_expires_at(claims), exp_exp) == 0); + GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_not_before(claims), exp_nbf) == 0); + + GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == + GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE); + grpc_jwt_claims_destroy(&exec_ctx, claims); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_invalid_claims_failure(void) { + grpc_slice s = grpc_slice_from_copied_string(invalid_claims); + grpc_json *json = grpc_json_parse_string_with_len( + (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(grpc_jwt_claims_from_json(&exec_ctx, json, s) == NULL); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_bad_audience_claims_failure(void) { + grpc_jwt_claims *claims; + grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint); + grpc_json *json = grpc_json_parse_string_with_len( + (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); + GPR_ASSERT(json != NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); + GPR_ASSERT(claims != NULL); + GPR_ASSERT(grpc_jwt_claims_check(claims, "https://bar.com") == + GRPC_JWT_VERIFIER_BAD_AUDIENCE); + grpc_jwt_claims_destroy(&exec_ctx, claims); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_bad_subject_claims_failure(void) { + grpc_jwt_claims *claims; + grpc_slice s = grpc_slice_from_copied_string(claims_with_bad_subject); + grpc_json *json = grpc_json_parse_string_with_len( + (char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s)); + GPR_ASSERT(json != NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + claims = grpc_jwt_claims_from_json(&exec_ctx, json, s); + GPR_ASSERT(claims != NULL); + GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == + GRPC_JWT_VERIFIER_BAD_SUBJECT); + grpc_jwt_claims_destroy(&exec_ctx, claims); + grpc_exec_ctx_finish(&exec_ctx); +} + +static char *json_key_str(const char *last_part) { + size_t result_len = strlen(json_key_str_part1) + strlen(json_key_str_part2) + + strlen(last_part); + char *result = static_cast(gpr_malloc(result_len + 1)); + char *current = result; + strcpy(result, json_key_str_part1); + current += strlen(json_key_str_part1); + strcpy(current, json_key_str_part2); + current += strlen(json_key_str_part2); + strcpy(current, last_part); + return result; +} + +static char *good_google_email_keys(void) { + size_t result_len = strlen(good_google_email_keys_part1) + + strlen(good_google_email_keys_part2); + char *result = static_cast(gpr_malloc(result_len + 1)); + char *current = result; + strcpy(result, good_google_email_keys_part1); + current += strlen(good_google_email_keys_part1); + strcpy(current, good_google_email_keys_part2); + return result; +} + +static grpc_httpcli_response http_response(int status, char *body) { + grpc_httpcli_response response; + memset(&response, 0, sizeof(grpc_httpcli_response)); + response.status = status; + response.body = body; + response.body_length = strlen(body); + return response; +} + +static int httpcli_post_should_not_be_called( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + const char *body_bytes, size_t body_size, grpc_millis deadline, + grpc_closure *on_done, grpc_httpcli_response *response) { + GPR_ASSERT("HTTP POST should not be called" == NULL); + return 1; +} + +static int httpcli_get_google_keys_for_email( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, good_google_email_keys()); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); + GPR_ASSERT(strcmp(request->http.path, + "/robot/v1/metadata/x509/" + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static void on_verification_success(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims) { + GPR_ASSERT(status == GRPC_JWT_VERIFIER_OK); + GPR_ASSERT(claims != NULL); + GPR_ASSERT(user_data == (void *)expected_user_data); + GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), expected_audience) == 0); + grpc_jwt_claims_destroy(exec_ctx, claims); +} + +static void test_jwt_verifier_google_email_issuer_success(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_google_keys_for_email, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_success, (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(jwt); + grpc_httpcli_set_override(NULL, NULL); +} + +static int httpcli_get_custom_keys_for_email( + grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, gpr_strdup(good_jwk_set)); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0); + GPR_ASSERT(strcmp(request->http.path, "/jwk/foo@bar.com") == 0); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static void test_jwt_verifier_custom_email_issuer_success(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(&custom_mapping, 1); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_custom_email_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_custom_keys_for_email, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_success, (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(jwt); + grpc_httpcli_set_override(NULL, NULL); +} + +static int httpcli_get_jwk_set(grpc_exec_ctx *exec_ctx, + const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, gpr_strdup(good_jwk_set)); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); + GPR_ASSERT(strcmp(request->http.path, "/oauth2/v3/certs") == 0); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static int httpcli_get_openid_config(grpc_exec_ctx *exec_ctx, + const grpc_httpcli_request *request, + grpc_millis deadline, + grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, gpr_strdup(good_openid_config)); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0); + GPR_ASSERT(strcmp(request->http.path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0); + grpc_httpcli_set_override(httpcli_get_jwk_set, + httpcli_post_should_not_be_called); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static void test_jwt_verifier_url_issuer_success(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_url_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_openid_config, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_success, (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(jwt); + grpc_httpcli_set_override(NULL, NULL); +} + +static void on_verification_key_retrieval_error(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims) { + GPR_ASSERT(status == GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR); + GPR_ASSERT(claims == NULL); + GPR_ASSERT(user_data == (void *)expected_user_data); +} + +static int httpcli_get_bad_json(grpc_exec_ctx *exec_ctx, + const grpc_httpcli_request *request, + grpc_millis deadline, grpc_closure *on_done, + grpc_httpcli_response *response) { + *response = http_response(200, gpr_strdup("{\"bad\": \"stuff\"}")); + GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); + GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_NONE); + return 1; +} + +static void test_jwt_verifier_url_issuer_bad_config(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_url_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_bad_json, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_key_retrieval_error, + (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(jwt); + grpc_httpcli_set_override(NULL, NULL); +} + +static void test_jwt_verifier_bad_json_key(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_bad_json, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_key_retrieval_error, + (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(jwt); + grpc_httpcli_set_override(NULL, NULL); +} + +static void corrupt_jwt_sig(char *jwt) { + grpc_slice sig; + char *bad_b64_sig; + uint8_t *sig_bytes; + char *last_dot = strrchr(jwt, '.'); + GPR_ASSERT(last_dot != NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + sig = grpc_base64_decode(&exec_ctx, last_dot + 1, 1); + grpc_exec_ctx_finish(&exec_ctx); + } + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig)); + sig_bytes = GRPC_SLICE_START_PTR(sig); + (*sig_bytes)++; /* Corrupt first byte. */ + bad_b64_sig = grpc_base64_encode(GRPC_SLICE_START_PTR(sig), + GRPC_SLICE_LENGTH(sig), 1, 0); + memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig)); + gpr_free(bad_b64_sig); + grpc_slice_unref(sig); +} + +static void on_verification_bad_signature(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims) { + GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_SIGNATURE); + GPR_ASSERT(claims == NULL); + GPR_ASSERT(user_data == (void *)expected_user_data); +} + +static void test_jwt_verifier_bad_signature(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + char *jwt = NULL; + char *key_str = json_key_str(json_key_str_part3_for_url_issuer); + grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str); + gpr_free(key_str); + GPR_ASSERT(grpc_auth_json_key_is_valid(&key)); + grpc_httpcli_set_override(httpcli_get_openid_config, + httpcli_post_should_not_be_called); + jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime, + NULL); + grpc_auth_json_key_destruct(&key); + corrupt_jwt_sig(jwt); + GPR_ASSERT(jwt != NULL); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience, + on_verification_bad_signature, + (void *)expected_user_data); + gpr_free(jwt); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + grpc_httpcli_set_override(NULL, NULL); +} + +static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx, + const grpc_httpcli_request *request, + grpc_millis deadline, + grpc_closure *on_done, + grpc_httpcli_response *response) { + GPR_ASSERT(0); + return 1; +} + +static void on_verification_bad_format(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims) { + GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_FORMAT); + GPR_ASSERT(claims == NULL); + GPR_ASSERT(user_data == (void *)expected_user_data); +} + +static void test_jwt_verifier_bad_format(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0); + grpc_httpcli_set_override(httpcli_get_should_not_be_called, + httpcli_post_should_not_be_called); + grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, "bad jwt", + expected_audience, on_verification_bad_format, + (void *)expected_user_data); + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + grpc_httpcli_set_override(NULL, NULL); +} + +/* find verification key: bad jks, cannot find key in jks */ +/* bad signature custom provided email*/ +/* bad key */ + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_jwt_issuer_email_domain(); + test_claims_success(); + test_expired_claims_failure(); + test_invalid_claims_failure(); + test_bad_audience_claims_failure(); + test_bad_subject_claims_failure(); + test_jwt_verifier_google_email_issuer_success(); + test_jwt_verifier_custom_email_issuer_success(); + test_jwt_verifier_url_issuer_success(); + test_jwt_verifier_url_issuer_bad_config(); + test_jwt_verifier_bad_json_key(); + test_jwt_verifier_bad_signature(); + test_jwt_verifier_bad_format(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c deleted file mode 100644 index 73d6c5bc7d..0000000000 --- a/test/core/security/oauth2_utils.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/security/oauth2_utils.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/security/credentials/credentials.h" - -typedef struct { - gpr_mu *mu; - grpc_polling_entity pops; - bool is_done; - char *token; - - grpc_credentials_mdelem_array md_array; - grpc_closure closure; -} oauth2_request; - -static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - oauth2_request *request = (oauth2_request *)arg; - char *token = NULL; - grpc_slice token_slice; - if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Fetching token failed: %s", grpc_error_string(error)); - } else { - GPR_ASSERT(request->md_array.size == 1); - token_slice = GRPC_MDVALUE(request->md_array.md[0]); - token = (char *)gpr_malloc(GRPC_SLICE_LENGTH(token_slice) + 1); - memcpy(token, GRPC_SLICE_START_PTR(token_slice), - GRPC_SLICE_LENGTH(token_slice)); - token[GRPC_SLICE_LENGTH(token_slice)] = '\0'; - } - grpc_credentials_mdelem_array_destroy(exec_ctx, &request->md_array); - gpr_mu_lock(request->mu); - request->is_done = true; - request->token = token; - GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&request->pops), - NULL)); - gpr_mu_unlock(request->mu); -} - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused, - grpc_error *error) {} - -char *grpc_test_fetch_oauth2_token_with_credentials( - grpc_call_credentials *creds) { - oauth2_request request; - memset(&request, 0, sizeof(request)); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure do_nothing_closure; - grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL}; - - grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &request.mu); - request.pops = grpc_polling_entity_create_from_pollset(pollset); - request.is_done = false; - - GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL, - grpc_schedule_on_exec_ctx); - - GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request, - grpc_schedule_on_exec_ctx); - - grpc_error *error = GRPC_ERROR_NONE; - if (grpc_call_credentials_get_request_metadata( - &exec_ctx, creds, &request.pops, null_ctx, &request.md_array, - &request.closure, &error)) { - // Synchronous result; invoke callback directly. - on_oauth2_response(&exec_ctx, &request, error); - GRPC_ERROR_UNREF(error); - } - grpc_exec_ctx_flush(&exec_ctx); - - gpr_mu_lock(request.mu); - while (!request.is_done) { - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, - grpc_polling_entity_pollset(&request.pops), - &worker, GRPC_MILLIS_INF_FUTURE))) { - request.is_done = true; - } - } - gpr_mu_unlock(request.mu); - - grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&request.pops), - &do_nothing_closure); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(grpc_polling_entity_pollset(&request.pops)); - return request.token; -} diff --git a/test/core/security/oauth2_utils.cc b/test/core/security/oauth2_utils.cc new file mode 100644 index 0000000000..73d6c5bc7d --- /dev/null +++ b/test/core/security/oauth2_utils.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/security/oauth2_utils.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/security/credentials/credentials.h" + +typedef struct { + gpr_mu *mu; + grpc_polling_entity pops; + bool is_done; + char *token; + + grpc_credentials_mdelem_array md_array; + grpc_closure closure; +} oauth2_request; + +static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + oauth2_request *request = (oauth2_request *)arg; + char *token = NULL; + grpc_slice token_slice; + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Fetching token failed: %s", grpc_error_string(error)); + } else { + GPR_ASSERT(request->md_array.size == 1); + token_slice = GRPC_MDVALUE(request->md_array.md[0]); + token = (char *)gpr_malloc(GRPC_SLICE_LENGTH(token_slice) + 1); + memcpy(token, GRPC_SLICE_START_PTR(token_slice), + GRPC_SLICE_LENGTH(token_slice)); + token[GRPC_SLICE_LENGTH(token_slice)] = '\0'; + } + grpc_credentials_mdelem_array_destroy(exec_ctx, &request->md_array); + gpr_mu_lock(request->mu); + request->is_done = true; + request->token = token; + GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&request->pops), + NULL)); + gpr_mu_unlock(request->mu); +} + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused, + grpc_error *error) {} + +char *grpc_test_fetch_oauth2_token_with_credentials( + grpc_call_credentials *creds) { + oauth2_request request; + memset(&request, 0, sizeof(request)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_closure do_nothing_closure; + grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL}; + + grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(pollset, &request.mu); + request.pops = grpc_polling_entity_create_from_pollset(pollset); + request.is_done = false; + + GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL, + grpc_schedule_on_exec_ctx); + + GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request, + grpc_schedule_on_exec_ctx); + + grpc_error *error = GRPC_ERROR_NONE; + if (grpc_call_credentials_get_request_metadata( + &exec_ctx, creds, &request.pops, null_ctx, &request.md_array, + &request.closure, &error)) { + // Synchronous result; invoke callback directly. + on_oauth2_response(&exec_ctx, &request, error); + GRPC_ERROR_UNREF(error); + } + grpc_exec_ctx_flush(&exec_ctx); + + gpr_mu_lock(request.mu); + while (!request.is_done) { + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, + grpc_polling_entity_pollset(&request.pops), + &worker, GRPC_MILLIS_INF_FUTURE))) { + request.is_done = true; + } + } + gpr_mu_unlock(request.mu); + + grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&request.pops), + &do_nothing_closure); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(grpc_polling_entity_pollset(&request.pops)); + return request.token; +} diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c deleted file mode 100644 index 29c38dfdf8..0000000000 --- a/test/core/security/print_google_default_creds_token.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/security/credentials/composite/composite_credentials.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" - -typedef struct { - gpr_mu *mu; - grpc_polling_entity pops; - bool is_done; - - grpc_credentials_mdelem_array md_array; - grpc_closure on_request_metadata; -} synchronizer; - -static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - synchronizer *sync = arg; - if (error != GRPC_ERROR_NONE) { - fprintf(stderr, "Fetching token failed: %s\n", grpc_error_string(error)); - } else { - char *token; - GPR_ASSERT(sync->md_array.size == 1); - token = grpc_slice_to_c_string(GRPC_MDVALUE(sync->md_array.md[0])); - printf("\nGot token: %s\n\n", token); - gpr_free(token); - } - gpr_mu_lock(sync->mu); - sync->is_done = true; - GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&sync->pops), - NULL)); - gpr_mu_unlock(sync->mu); -} - -int main(int argc, char **argv) { - int result = 0; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - synchronizer sync; - grpc_channel_credentials *creds = NULL; - char *service_url = "https://test.foo.google.com/Foo"; - grpc_auth_metadata_context context; - gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token"); - gpr_cmdline_add_string(cl, "service_url", - "Service URL for the token request.", &service_url); - gpr_cmdline_parse(cl, argc, argv); - memset(&context, 0, sizeof(context)); - context.service_url = service_url; - - grpc_init(); - - creds = grpc_google_default_credentials_create(); - if (creds == NULL) { - fprintf(stderr, "\nCould not find default credentials.\n\n"); - result = 1; - goto end; - } - - memset(&sync, 0, sizeof(sync)); - grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &sync.mu); - sync.pops = grpc_polling_entity_create_from_pollset(pollset); - sync.is_done = false; - GRPC_CLOSURE_INIT(&sync.on_request_metadata, on_metadata_response, &sync, - grpc_schedule_on_exec_ctx); - - grpc_error *error = GRPC_ERROR_NONE; - if (grpc_call_credentials_get_request_metadata( - &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds, - &sync.pops, context, &sync.md_array, &sync.on_request_metadata, - &error)) { - // Synchronous response. Invoke callback directly. - on_metadata_response(&exec_ctx, &sync, error); - GRPC_ERROR_UNREF(error); - } - - gpr_mu_lock(sync.mu); - while (!sync.is_done) { - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, - grpc_polling_entity_pollset(&sync.pops), &worker, - GRPC_MILLIS_INF_FUTURE))) - sync.is_done = true; - gpr_mu_unlock(sync.mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(sync.mu); - } - gpr_mu_unlock(sync.mu); - - grpc_exec_ctx_finish(&exec_ctx); - - grpc_channel_credentials_release(creds); - gpr_free(grpc_polling_entity_pollset(&sync.pops)); - -end: - gpr_cmdline_destroy(cl); - grpc_shutdown(); - return result; -} diff --git a/test/core/security/print_google_default_creds_token.cc b/test/core/security/print_google_default_creds_token.cc new file mode 100644 index 0000000000..81c992c4d6 --- /dev/null +++ b/test/core/security/print_google_default_creds_token.cc @@ -0,0 +1,132 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/security/credentials/composite/composite_credentials.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" + +typedef struct { + gpr_mu *mu; + grpc_polling_entity pops; + bool is_done; + + grpc_credentials_mdelem_array md_array; + grpc_closure on_request_metadata; +} synchronizer; + +static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + synchronizer *sync = static_cast(arg); + if (error != GRPC_ERROR_NONE) { + fprintf(stderr, "Fetching token failed: %s\n", grpc_error_string(error)); + } else { + char *token; + GPR_ASSERT(sync->md_array.size == 1); + token = grpc_slice_to_c_string(GRPC_MDVALUE(sync->md_array.md[0])); + printf("\nGot token: %s\n\n", token); + gpr_free(token); + } + gpr_mu_lock(sync->mu); + sync->is_done = true; + GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&sync->pops), + NULL)); + gpr_mu_unlock(sync->mu); +} + +int main(int argc, char **argv) { + int result = 0; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + synchronizer sync; + grpc_channel_credentials *creds = NULL; + const char *service_url = "https://test.foo.google.com/Foo"; + grpc_auth_metadata_context context; + gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token"); + grpc_pollset *pollset = nullptr; + grpc_error *error = nullptr; + gpr_cmdline_add_string(cl, "service_url", + "Service URL for the token request.", &service_url); + gpr_cmdline_parse(cl, argc, argv); + memset(&context, 0, sizeof(context)); + context.service_url = service_url; + + grpc_init(); + + creds = grpc_google_default_credentials_create(); + if (creds == NULL) { + fprintf(stderr, "\nCould not find default credentials.\n\n"); + result = 1; + goto end; + } + + memset(&sync, 0, sizeof(sync)); + pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(pollset, &sync.mu); + sync.pops = grpc_polling_entity_create_from_pollset(pollset); + sync.is_done = false; + GRPC_CLOSURE_INIT(&sync.on_request_metadata, on_metadata_response, &sync, + grpc_schedule_on_exec_ctx); + + error = GRPC_ERROR_NONE; + if (grpc_call_credentials_get_request_metadata( + &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds, + &sync.pops, context, &sync.md_array, &sync.on_request_metadata, + &error)) { + // Synchronous response. Invoke callback directly. + on_metadata_response(&exec_ctx, &sync, error); + GRPC_ERROR_UNREF(error); + } + + gpr_mu_lock(sync.mu); + while (!sync.is_done) { + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, + grpc_polling_entity_pollset(&sync.pops), &worker, + GRPC_MILLIS_INF_FUTURE))) + sync.is_done = true; + gpr_mu_unlock(sync.mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(sync.mu); + } + gpr_mu_unlock(sync.mu); + + grpc_exec_ctx_finish(&exec_ctx); + + grpc_channel_credentials_release(creds); + gpr_free(grpc_polling_entity_pollset(&sync.pops)); + +end: + gpr_cmdline_destroy(cl); + grpc_shutdown(); + return result; +} diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c deleted file mode 100644 index 839a05fa9b..0000000000 --- a/test/core/security/secure_endpoint_test.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/iomgr/endpoint_tests.h" - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/iomgr/endpoint_pair.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/security/transport/secure_endpoint.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/tsi/fake_transport_security.h" -#include "test/core/util/test_config.h" - -static gpr_mu *g_mu; -static grpc_pollset *g_pollset; - -static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair( - size_t slice_size, grpc_slice *leftover_slices, size_t leftover_nslices, - bool use_zero_copy_protector) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - tsi_frame_protector *fake_read_protector = - tsi_create_fake_frame_protector(NULL); - tsi_frame_protector *fake_write_protector = - tsi_create_fake_frame_protector(NULL); - tsi_zero_copy_grpc_protector *fake_read_zero_copy_protector = - use_zero_copy_protector ? tsi_create_fake_zero_copy_grpc_protector(NULL) - : NULL; - tsi_zero_copy_grpc_protector *fake_write_zero_copy_protector = - use_zero_copy_protector ? tsi_create_fake_zero_copy_grpc_protector(NULL) - : NULL; - grpc_endpoint_test_fixture f; - grpc_endpoint_pair tcp; - - grpc_arg a[] = {{.key = GRPC_ARG_TCP_READ_CHUNK_SIZE, - .type = GRPC_ARG_INTEGER, - .value.integer = (int)slice_size}}; - grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; - tcp = grpc_iomgr_create_endpoint_pair("fixture", &args); - grpc_endpoint_add_to_pollset(&exec_ctx, tcp.client, g_pollset); - grpc_endpoint_add_to_pollset(&exec_ctx, tcp.server, g_pollset); - - if (leftover_nslices == 0) { - f.client_ep = grpc_secure_endpoint_create(fake_read_protector, - fake_read_zero_copy_protector, - tcp.client, NULL, 0); - } else { - unsigned i; - tsi_result result; - size_t still_pending_size; - size_t total_buffer_size = 8192; - size_t buffer_size = total_buffer_size; - uint8_t *encrypted_buffer = (uint8_t *)gpr_malloc(buffer_size); - uint8_t *cur = encrypted_buffer; - grpc_slice encrypted_leftover; - for (i = 0; i < leftover_nslices; i++) { - grpc_slice plain = leftover_slices[i]; - uint8_t *message_bytes = GRPC_SLICE_START_PTR(plain); - size_t message_size = GRPC_SLICE_LENGTH(plain); - while (message_size > 0) { - size_t protected_buffer_size_to_send = buffer_size; - size_t processed_message_size = message_size; - result = tsi_frame_protector_protect( - fake_write_protector, message_bytes, &processed_message_size, cur, - &protected_buffer_size_to_send); - GPR_ASSERT(result == TSI_OK); - message_bytes += processed_message_size; - message_size -= processed_message_size; - cur += protected_buffer_size_to_send; - GPR_ASSERT(buffer_size >= protected_buffer_size_to_send); - buffer_size -= protected_buffer_size_to_send; - } - grpc_slice_unref(plain); - } - do { - size_t protected_buffer_size_to_send = buffer_size; - result = tsi_frame_protector_protect_flush(fake_write_protector, cur, - &protected_buffer_size_to_send, - &still_pending_size); - GPR_ASSERT(result == TSI_OK); - cur += protected_buffer_size_to_send; - GPR_ASSERT(buffer_size >= protected_buffer_size_to_send); - buffer_size -= protected_buffer_size_to_send; - } while (still_pending_size > 0); - encrypted_leftover = grpc_slice_from_copied_buffer( - (const char *)encrypted_buffer, total_buffer_size - buffer_size); - f.client_ep = grpc_secure_endpoint_create( - fake_read_protector, fake_read_zero_copy_protector, tcp.client, - &encrypted_leftover, 1); - grpc_slice_unref(encrypted_leftover); - gpr_free(encrypted_buffer); - } - - f.server_ep = grpc_secure_endpoint_create(fake_write_protector, - fake_write_zero_copy_protector, - tcp.server, NULL, 0); - grpc_exec_ctx_finish(&exec_ctx); - return f; -} - -static grpc_endpoint_test_fixture -secure_endpoint_create_fixture_tcp_socketpair_noleftover(size_t slice_size) { - return secure_endpoint_create_fixture_tcp_socketpair(slice_size, NULL, 0, - false); -} - -static grpc_endpoint_test_fixture -secure_endpoint_create_fixture_tcp_socketpair_noleftover_zero_copy( - size_t slice_size) { - return secure_endpoint_create_fixture_tcp_socketpair(slice_size, NULL, 0, - true); -} - -static grpc_endpoint_test_fixture -secure_endpoint_create_fixture_tcp_socketpair_leftover(size_t slice_size) { - grpc_slice s = - grpc_slice_from_copied_string("hello world 12345678900987654321"); - return secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1, - false); -} - -static grpc_endpoint_test_fixture -secure_endpoint_create_fixture_tcp_socketpair_leftover_zero_copy( - size_t slice_size) { - grpc_slice s = - grpc_slice_from_copied_string("hello world 12345678900987654321"); - return secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1, true); -} - -static void clean_up(void) {} - -static grpc_endpoint_test_config configs[] = { - {"secure_ep/tcp_socketpair", - secure_endpoint_create_fixture_tcp_socketpair_noleftover, clean_up}, - {"secure_ep/tcp_socketpair_zero_copy", - secure_endpoint_create_fixture_tcp_socketpair_noleftover_zero_copy, - clean_up}, - {"secure_ep/tcp_socketpair_leftover", - secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up}, - {"secure_ep/tcp_socketpair_leftover_zero_copy", - secure_endpoint_create_fixture_tcp_socketpair_leftover_zero_copy, - clean_up}, -}; - -static void inc_call_ctr(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - ++*(int *)arg; -} - -static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { - grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - grpc_slice_buffer incoming; - grpc_slice s = - grpc_slice_from_copied_string("hello world 12345678900987654321"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - int n = 0; - grpc_closure done_closure; - gpr_log(GPR_INFO, "Start test left over"); - - grpc_slice_buffer_init(&incoming); - GRPC_CLOSURE_INIT(&done_closure, inc_call_ctr, &n, grpc_schedule_on_exec_ctx); - grpc_endpoint_read(&exec_ctx, f.client_ep, &incoming, &done_closure); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(n == 1); - GPR_ASSERT(incoming.count == 1); - GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0])); - - grpc_endpoint_shutdown( - &exec_ctx, f.client_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end")); - grpc_endpoint_shutdown( - &exec_ctx, f.server_ep, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end")); - grpc_endpoint_destroy(&exec_ctx, f.client_ep); - grpc_endpoint_destroy(&exec_ctx, f.server_ep); - grpc_exec_ctx_finish(&exec_ctx); - grpc_slice_unref_internal(&exec_ctx, s); - grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); - - clean_up(); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p); -} - -int main(int argc, char **argv) { - grpc_closure destroyed; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_test_init(argc, argv); - - grpc_init(); - g_pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(g_pollset, &g_mu); - grpc_endpoint_tests(configs[0], g_pollset, g_mu); - grpc_endpoint_tests(configs[1], g_pollset, g_mu); - test_leftover(configs[2], 1); - test_leftover(configs[3], 1); - GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, - grpc_schedule_on_exec_ctx); - grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - - gpr_free(g_pollset); - - return 0; -} diff --git a/test/core/security/secure_endpoint_test.cc b/test/core/security/secure_endpoint_test.cc new file mode 100644 index 0000000000..fe7961d1d9 --- /dev/null +++ b/test/core/security/secure_endpoint_test.cc @@ -0,0 +1,230 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/iomgr/endpoint_tests.h" + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/tsi/fake_transport_security.h" +#include "test/core/util/test_config.h" + +static gpr_mu *g_mu; +static grpc_pollset *g_pollset; + +static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair( + size_t slice_size, grpc_slice *leftover_slices, size_t leftover_nslices, + bool use_zero_copy_protector) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + tsi_frame_protector *fake_read_protector = + tsi_create_fake_frame_protector(NULL); + tsi_frame_protector *fake_write_protector = + tsi_create_fake_frame_protector(NULL); + tsi_zero_copy_grpc_protector *fake_read_zero_copy_protector = + use_zero_copy_protector ? tsi_create_fake_zero_copy_grpc_protector(NULL) + : NULL; + tsi_zero_copy_grpc_protector *fake_write_zero_copy_protector = + use_zero_copy_protector ? tsi_create_fake_zero_copy_grpc_protector(NULL) + : NULL; + grpc_endpoint_test_fixture f; + grpc_endpoint_pair tcp; + + grpc_arg a[1]; + a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); + a[0].type = GRPC_ARG_INTEGER; + a[0].value.integer = (int)slice_size; + grpc_channel_args args = {.num_args = GPR_ARRAY_SIZE(a), .args = a}; + tcp = grpc_iomgr_create_endpoint_pair("fixture", &args); + grpc_endpoint_add_to_pollset(&exec_ctx, tcp.client, g_pollset); + grpc_endpoint_add_to_pollset(&exec_ctx, tcp.server, g_pollset); + + if (leftover_nslices == 0) { + f.client_ep = grpc_secure_endpoint_create(fake_read_protector, + fake_read_zero_copy_protector, + tcp.client, NULL, 0); + } else { + unsigned i; + tsi_result result; + size_t still_pending_size; + size_t total_buffer_size = 8192; + size_t buffer_size = total_buffer_size; + uint8_t *encrypted_buffer = (uint8_t *)gpr_malloc(buffer_size); + uint8_t *cur = encrypted_buffer; + grpc_slice encrypted_leftover; + for (i = 0; i < leftover_nslices; i++) { + grpc_slice plain = leftover_slices[i]; + uint8_t *message_bytes = GRPC_SLICE_START_PTR(plain); + size_t message_size = GRPC_SLICE_LENGTH(plain); + while (message_size > 0) { + size_t protected_buffer_size_to_send = buffer_size; + size_t processed_message_size = message_size; + result = tsi_frame_protector_protect( + fake_write_protector, message_bytes, &processed_message_size, cur, + &protected_buffer_size_to_send); + GPR_ASSERT(result == TSI_OK); + message_bytes += processed_message_size; + message_size -= processed_message_size; + cur += protected_buffer_size_to_send; + GPR_ASSERT(buffer_size >= protected_buffer_size_to_send); + buffer_size -= protected_buffer_size_to_send; + } + grpc_slice_unref(plain); + } + do { + size_t protected_buffer_size_to_send = buffer_size; + result = tsi_frame_protector_protect_flush(fake_write_protector, cur, + &protected_buffer_size_to_send, + &still_pending_size); + GPR_ASSERT(result == TSI_OK); + cur += protected_buffer_size_to_send; + GPR_ASSERT(buffer_size >= protected_buffer_size_to_send); + buffer_size -= protected_buffer_size_to_send; + } while (still_pending_size > 0); + encrypted_leftover = grpc_slice_from_copied_buffer( + (const char *)encrypted_buffer, total_buffer_size - buffer_size); + f.client_ep = grpc_secure_endpoint_create( + fake_read_protector, fake_read_zero_copy_protector, tcp.client, + &encrypted_leftover, 1); + grpc_slice_unref(encrypted_leftover); + gpr_free(encrypted_buffer); + } + + f.server_ep = grpc_secure_endpoint_create(fake_write_protector, + fake_write_zero_copy_protector, + tcp.server, NULL, 0); + grpc_exec_ctx_finish(&exec_ctx); + return f; +} + +static grpc_endpoint_test_fixture +secure_endpoint_create_fixture_tcp_socketpair_noleftover(size_t slice_size) { + return secure_endpoint_create_fixture_tcp_socketpair(slice_size, NULL, 0, + false); +} + +static grpc_endpoint_test_fixture +secure_endpoint_create_fixture_tcp_socketpair_noleftover_zero_copy( + size_t slice_size) { + return secure_endpoint_create_fixture_tcp_socketpair(slice_size, NULL, 0, + true); +} + +static grpc_endpoint_test_fixture +secure_endpoint_create_fixture_tcp_socketpair_leftover(size_t slice_size) { + grpc_slice s = + grpc_slice_from_copied_string("hello world 12345678900987654321"); + return secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1, + false); +} + +static grpc_endpoint_test_fixture +secure_endpoint_create_fixture_tcp_socketpair_leftover_zero_copy( + size_t slice_size) { + grpc_slice s = + grpc_slice_from_copied_string("hello world 12345678900987654321"); + return secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1, true); +} + +static void clean_up(void) {} + +static grpc_endpoint_test_config configs[] = { + {"secure_ep/tcp_socketpair", + secure_endpoint_create_fixture_tcp_socketpair_noleftover, clean_up}, + {"secure_ep/tcp_socketpair_zero_copy", + secure_endpoint_create_fixture_tcp_socketpair_noleftover_zero_copy, + clean_up}, + {"secure_ep/tcp_socketpair_leftover", + secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up}, + {"secure_ep/tcp_socketpair_leftover_zero_copy", + secure_endpoint_create_fixture_tcp_socketpair_leftover_zero_copy, + clean_up}, +}; + +static void inc_call_ctr(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + ++*(int *)arg; +} + +static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { + grpc_endpoint_test_fixture f = config.create_fixture(slice_size); + grpc_slice_buffer incoming; + grpc_slice s = + grpc_slice_from_copied_string("hello world 12345678900987654321"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + int n = 0; + grpc_closure done_closure; + gpr_log(GPR_INFO, "Start test left over"); + + grpc_slice_buffer_init(&incoming); + GRPC_CLOSURE_INIT(&done_closure, inc_call_ctr, &n, grpc_schedule_on_exec_ctx); + grpc_endpoint_read(&exec_ctx, f.client_ep, &incoming, &done_closure); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(n == 1); + GPR_ASSERT(incoming.count == 1); + GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0])); + + grpc_endpoint_shutdown( + &exec_ctx, f.client_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end")); + grpc_endpoint_shutdown( + &exec_ctx, f.server_ep, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("test_leftover end")); + grpc_endpoint_destroy(&exec_ctx, f.client_ep); + grpc_endpoint_destroy(&exec_ctx, f.server_ep); + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref_internal(&exec_ctx, s); + grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); + + clean_up(); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_test_init(argc, argv); + + grpc_init(); + g_pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(g_pollset, &g_mu); + grpc_endpoint_tests(configs[0], g_pollset, g_mu); + grpc_endpoint_tests(configs[1], g_pollset, g_mu); + test_leftover(configs[2], 1); + test_leftover(configs[3], 1); + GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset, + grpc_schedule_on_exec_ctx); + grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_free(g_pollset); + + return 0; +} diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c deleted file mode 100644 index eecf0f462b..0000000000 --- a/test/core/security/security_connector_test.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/security/context/security_context.h" -#include "src/core/lib/security/transport/security_connector.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/support/tmpfile.h" -#include "src/core/tsi/ssl_transport_security.h" -#include "src/core/tsi/transport_security.h" -#include "test/core/util/test_config.h" - -static int check_transport_security_type(const grpc_auth_context *ctx) { - grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( - ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); - const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); - if (prop == NULL) return 0; - if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE, - prop->value_length) != 0) { - return 0; - } - /* Check that we have only one property with this name. */ - if (grpc_auth_property_iterator_next(&it) != NULL) return 0; - return 1; -} - -static int check_peer_property(const tsi_peer *peer, - const tsi_peer_property *expected) { - size_t i; - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property *prop = &peer->properties[i]; - if ((strcmp(prop->name, expected->name) == 0) && - (prop->value.length == expected->value.length) && - (memcmp(prop->value.data, expected->value.data, - expected->value.length) == 0)) { - return 1; - } - } - return 0; /* Not found... */ -} - -static int check_ssl_peer_equivalence(const tsi_peer *original, - const tsi_peer *reconstructed) { - /* The reconstructed peer only has CN, SAN and pem cert properties. */ - size_t i; - for (i = 0; i < original->property_count; i++) { - const tsi_peer_property *prop = &original->properties[i]; - if ((strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) || - (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == - 0) || - (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0)) { - if (!check_peer_property(reconstructed, prop)) return 0; - } - } - return 1; -} - -static void test_unauthenticated_ssl_peer(void) { - tsi_peer peer; - tsi_peer rpeer; - grpc_auth_context *ctx; - GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, - &peer.properties[0]) == TSI_OK); - ctx = tsi_ssl_peer_to_auth_context(&peer); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx)); - GPR_ASSERT(check_transport_security_type(ctx)); - - rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); - GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); - - tsi_shallow_peer_destruct(&rpeer); - tsi_peer_destruct(&peer); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static int check_identity(const grpc_auth_context *ctx, - const char *expected_property_name, - const char **expected_identities, - size_t num_identities) { - grpc_auth_property_iterator it; - const grpc_auth_property *prop; - size_t i; - GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); - it = grpc_auth_context_peer_identity(ctx); - for (i = 0; i < num_identities; i++) { - prop = grpc_auth_property_iterator_next(&it); - if (prop == NULL) { - gpr_log(GPR_ERROR, "Expected identity value %s not found.", - expected_identities[i]); - return 0; - } - if (strcmp(prop->name, expected_property_name) != 0) { - gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.", - expected_property_name, prop->name); - return 0; - } - if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) { - gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.", - expected_identities[i], prop->value); - return 0; - } - } - return 1; -} - -static int check_x509_cn(const grpc_auth_context *ctx, - const char *expected_cn) { - grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( - ctx, GRPC_X509_CN_PROPERTY_NAME); - const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); - if (prop == NULL) { - gpr_log(GPR_ERROR, "CN property not found."); - return 0; - } - if (strncmp(prop->value, expected_cn, prop->value_length) != 0) { - gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value); - return 0; - } - if (grpc_auth_property_iterator_next(&it) != NULL) { - gpr_log(GPR_ERROR, "Expected only one property for CN."); - return 0; - } - return 1; -} - -static int check_x509_pem_cert(const grpc_auth_context *ctx, - const char *expected_pem_cert) { - grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( - ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME); - const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); - if (prop == NULL) { - gpr_log(GPR_ERROR, "Pem certificate property not found."); - return 0; - } - if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) { - gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert, - prop->value); - return 0; - } - if (grpc_auth_property_iterator_next(&it) != NULL) { - gpr_log(GPR_ERROR, "Expected only one property for pem cert."); - return 0; - } - return 1; -} - -static void test_cn_only_ssl_peer_to_auth_context(void) { - tsi_peer peer; - tsi_peer rpeer; - grpc_auth_context *ctx; - const char *expected_cn = "cn1"; - const char *expected_pem_cert = "pem_cert1"; - GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, - &peer.properties[0]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, - &peer.properties[1]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, - &peer.properties[2]) == TSI_OK); - ctx = tsi_ssl_peer_to_auth_context(&peer); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); - GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1)); - GPR_ASSERT(check_transport_security_type(ctx)); - GPR_ASSERT(check_x509_cn(ctx, expected_cn)); - GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); - - rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); - GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); - - tsi_shallow_peer_destruct(&rpeer); - tsi_peer_destruct(&peer); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { - tsi_peer peer; - tsi_peer rpeer; - grpc_auth_context *ctx; - const char *expected_cn = "cn1"; - const char *expected_san = "san1"; - const char *expected_pem_cert = "pem_cert1"; - GPR_ASSERT(tsi_construct_peer(4, &peer) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, - &peer.properties[0]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, - &peer.properties[1]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san, - &peer.properties[2]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, - &peer.properties[3]) == TSI_OK); - ctx = tsi_ssl_peer_to_auth_context(&peer); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); - GPR_ASSERT( - check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1)); - GPR_ASSERT(check_transport_security_type(ctx)); - GPR_ASSERT(check_x509_cn(ctx, expected_cn)); - GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); - - rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); - GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); - - tsi_shallow_peer_destruct(&rpeer); - tsi_peer_destruct(&peer); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) { - tsi_peer peer; - tsi_peer rpeer; - grpc_auth_context *ctx; - const char *expected_cn = "cn1"; - const char *expected_sans[] = {"san1", "san2", "san3"}; - const char *expected_pem_cert = "pem_cert1"; - size_t i; - GPR_ASSERT(tsi_construct_peer(3 + GPR_ARRAY_SIZE(expected_sans), &peer) == - TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, - &peer.properties[0]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, - &peer.properties[1]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, - &peer.properties[2]) == TSI_OK); - for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) { - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, - expected_sans[i], &peer.properties[3 + i]) == TSI_OK); - } - ctx = tsi_ssl_peer_to_auth_context(&peer); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); - GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans, - GPR_ARRAY_SIZE(expected_sans))); - GPR_ASSERT(check_transport_security_type(ctx)); - GPR_ASSERT(check_x509_cn(ctx, expected_cn)); - GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); - - rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); - GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); - - tsi_shallow_peer_destruct(&rpeer); - tsi_peer_destruct(&peer); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( - void) { - tsi_peer peer; - tsi_peer rpeer; - grpc_auth_context *ctx; - const char *expected_cn = "cn1"; - const char *expected_pem_cert = "pem_cert1"; - const char *expected_sans[] = {"san1", "san2", "san3"}; - size_t i; - GPR_ASSERT(tsi_construct_peer(5 + GPR_ARRAY_SIZE(expected_sans), &peer) == - TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, - &peer.properties[0]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - "foo", "bar", &peer.properties[1]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, - &peer.properties[2]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - "chapi", "chapo", &peer.properties[3]) == TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, - &peer.properties[4]) == TSI_OK); - for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) { - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, - expected_sans[i], &peer.properties[5 + i]) == TSI_OK); - } - ctx = tsi_ssl_peer_to_auth_context(&peer); - GPR_ASSERT(ctx != NULL); - GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); - GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans, - GPR_ARRAY_SIZE(expected_sans))); - GPR_ASSERT(check_transport_security_type(ctx)); - GPR_ASSERT(check_x509_cn(ctx, expected_cn)); - GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); - - rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); - GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); - - tsi_shallow_peer_destruct(&rpeer); - tsi_peer_destruct(&peer); - GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); -} - -static const char *roots_for_override_api = "roots for override api"; - -static grpc_ssl_roots_override_result override_roots_success( - char **pem_root_certs) { - *pem_root_certs = gpr_strdup(roots_for_override_api); - return GRPC_SSL_ROOTS_OVERRIDE_OK; -} - -static grpc_ssl_roots_override_result override_roots_permanent_failure( - char **pem_root_certs) { - return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; -} - -static void test_default_ssl_roots(void) { - const char *roots_for_env_var = "roots for env var"; - - char *roots_env_var_file_path; - FILE *roots_env_var_file = - gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path); - fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file); - fclose(roots_env_var_file); - - /* First let's get the root through the override: set the env to an invalid - value. */ - gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); - grpc_set_ssl_roots_override_callback(override_roots_success); - grpc_slice roots = grpc_get_default_ssl_roots_for_testing(); - char *roots_contents = grpc_slice_to_c_string(roots); - grpc_slice_unref(roots); - GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); - gpr_free(roots_contents); - - /* Now let's set the env var: We should get the contents pointed value - instead. */ - gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path); - roots = grpc_get_default_ssl_roots_for_testing(); - roots_contents = grpc_slice_to_c_string(roots); - grpc_slice_unref(roots); - GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0); - gpr_free(roots_contents); - - /* Now reset the env var. We should fall back to the value overridden using - the api. */ - gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); - roots = grpc_get_default_ssl_roots_for_testing(); - roots_contents = grpc_slice_to_c_string(roots); - grpc_slice_unref(roots); - GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); - gpr_free(roots_contents); - - /* Now setup a permanent failure for the overridden roots and we should get - an empty slice. */ - grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); - roots = grpc_get_default_ssl_roots_for_testing(); - GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots)); - - /* Cleanup. */ - remove(roots_env_var_file_path); - gpr_free(roots_env_var_file_path); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - - test_unauthenticated_ssl_peer(); - test_cn_only_ssl_peer_to_auth_context(); - test_cn_and_one_san_ssl_peer_to_auth_context(); - test_cn_and_multiple_sans_ssl_peer_to_auth_context(); - test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); - test_default_ssl_roots(); - - grpc_shutdown(); - return 0; -} diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc new file mode 100644 index 0000000000..eecf0f462b --- /dev/null +++ b/test/core/security/security_connector_test.cc @@ -0,0 +1,405 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" +#include "test/core/util/test_config.h" + +static int check_transport_security_type(const grpc_auth_context *ctx) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) return 0; + if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE, + prop->value_length) != 0) { + return 0; + } + /* Check that we have only one property with this name. */ + if (grpc_auth_property_iterator_next(&it) != NULL) return 0; + return 1; +} + +static int check_peer_property(const tsi_peer *peer, + const tsi_peer_property *expected) { + size_t i; + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property *prop = &peer->properties[i]; + if ((strcmp(prop->name, expected->name) == 0) && + (prop->value.length == expected->value.length) && + (memcmp(prop->value.data, expected->value.data, + expected->value.length) == 0)) { + return 1; + } + } + return 0; /* Not found... */ +} + +static int check_ssl_peer_equivalence(const tsi_peer *original, + const tsi_peer *reconstructed) { + /* The reconstructed peer only has CN, SAN and pem cert properties. */ + size_t i; + for (i = 0; i < original->property_count; i++) { + const tsi_peer_property *prop = &original->properties[i]; + if ((strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) || + (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == + 0) || + (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0)) { + if (!check_peer_property(reconstructed, prop)) return 0; + } + } + return 1; +} + +static void test_unauthenticated_ssl_peer(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, + &peer.properties[0]) == TSI_OK); + ctx = tsi_ssl_peer_to_auth_context(&peer); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx)); + GPR_ASSERT(check_transport_security_type(ctx)); + + rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); + GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); + + tsi_shallow_peer_destruct(&rpeer); + tsi_peer_destruct(&peer); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static int check_identity(const grpc_auth_context *ctx, + const char *expected_property_name, + const char **expected_identities, + size_t num_identities) { + grpc_auth_property_iterator it; + const grpc_auth_property *prop; + size_t i; + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + it = grpc_auth_context_peer_identity(ctx); + for (i = 0; i < num_identities; i++) { + prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "Expected identity value %s not found.", + expected_identities[i]); + return 0; + } + if (strcmp(prop->name, expected_property_name) != 0) { + gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.", + expected_property_name, prop->name); + return 0; + } + if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.", + expected_identities[i], prop->value); + return 0; + } + } + return 1; +} + +static int check_x509_cn(const grpc_auth_context *ctx, + const char *expected_cn) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_X509_CN_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "CN property not found."); + return 0; + } + if (strncmp(prop->value, expected_cn, prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value); + return 0; + } + if (grpc_auth_property_iterator_next(&it) != NULL) { + gpr_log(GPR_ERROR, "Expected only one property for CN."); + return 0; + } + return 1; +} + +static int check_x509_pem_cert(const grpc_auth_context *ctx, + const char *expected_pem_cert) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "Pem certificate property not found."); + return 0; + } + if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert, + prop->value); + return 0; + } + if (grpc_auth_property_iterator_next(&it) != NULL) { + gpr_log(GPR_ERROR, "Expected only one property for pem cert."); + return 0; + } + return 1; +} + +static void test_cn_only_ssl_peer_to_auth_context(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_pem_cert = "pem_cert1"; + GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, + &peer.properties[1]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[2]) == TSI_OK); + ctx = tsi_ssl_peer_to_auth_context(&peer); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1)); + GPR_ASSERT(check_transport_security_type(ctx)); + GPR_ASSERT(check_x509_cn(ctx, expected_cn)); + GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); + + rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); + GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); + + tsi_shallow_peer_destruct(&rpeer); + tsi_peer_destruct(&peer); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_san = "san1"; + const char *expected_pem_cert = "pem_cert1"; + GPR_ASSERT(tsi_construct_peer(4, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, + &peer.properties[1]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san, + &peer.properties[2]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[3]) == TSI_OK); + ctx = tsi_ssl_peer_to_auth_context(&peer); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + GPR_ASSERT( + check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1)); + GPR_ASSERT(check_transport_security_type(ctx)); + GPR_ASSERT(check_x509_cn(ctx, expected_cn)); + GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); + + rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); + GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); + + tsi_shallow_peer_destruct(&rpeer); + tsi_peer_destruct(&peer); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_sans[] = {"san1", "san2", "san3"}; + const char *expected_pem_cert = "pem_cert1"; + size_t i; + GPR_ASSERT(tsi_construct_peer(3 + GPR_ARRAY_SIZE(expected_sans), &peer) == + TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, + &peer.properties[1]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[2]) == TSI_OK); + for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, + expected_sans[i], &peer.properties[3 + i]) == TSI_OK); + } + ctx = tsi_ssl_peer_to_auth_context(&peer); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans, + GPR_ARRAY_SIZE(expected_sans))); + GPR_ASSERT(check_transport_security_type(ctx)); + GPR_ASSERT(check_x509_cn(ctx, expected_cn)); + GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); + + rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); + GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); + + tsi_shallow_peer_destruct(&rpeer); + tsi_peer_destruct(&peer); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( + void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_pem_cert = "pem_cert1"; + const char *expected_sans[] = {"san1", "san2", "san3"}; + size_t i; + GPR_ASSERT(tsi_construct_peer(5 + GPR_ARRAY_SIZE(expected_sans), &peer) == + TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + "foo", "bar", &peer.properties[1]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, + &peer.properties[2]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + "chapi", "chapo", &peer.properties[3]) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[4]) == TSI_OK); + for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, + expected_sans[i], &peer.properties[5 + i]) == TSI_OK); + } + ctx = tsi_ssl_peer_to_auth_context(&peer); + GPR_ASSERT(ctx != NULL); + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans, + GPR_ARRAY_SIZE(expected_sans))); + GPR_ASSERT(check_transport_security_type(ctx)); + GPR_ASSERT(check_x509_cn(ctx, expected_cn)); + GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); + + rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); + GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); + + tsi_shallow_peer_destruct(&rpeer); + tsi_peer_destruct(&peer); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); +} + +static const char *roots_for_override_api = "roots for override api"; + +static grpc_ssl_roots_override_result override_roots_success( + char **pem_root_certs) { + *pem_root_certs = gpr_strdup(roots_for_override_api); + return GRPC_SSL_ROOTS_OVERRIDE_OK; +} + +static grpc_ssl_roots_override_result override_roots_permanent_failure( + char **pem_root_certs) { + return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; +} + +static void test_default_ssl_roots(void) { + const char *roots_for_env_var = "roots for env var"; + + char *roots_env_var_file_path; + FILE *roots_env_var_file = + gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path); + fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file); + fclose(roots_env_var_file); + + /* First let's get the root through the override: set the env to an invalid + value. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); + grpc_set_ssl_roots_override_callback(override_roots_success); + grpc_slice roots = grpc_get_default_ssl_roots_for_testing(); + char *roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); + gpr_free(roots_contents); + + /* Now let's set the env var: We should get the contents pointed value + instead. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path); + roots = grpc_get_default_ssl_roots_for_testing(); + roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0); + gpr_free(roots_contents); + + /* Now reset the env var. We should fall back to the value overridden using + the api. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); + roots = grpc_get_default_ssl_roots_for_testing(); + roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); + gpr_free(roots_contents); + + /* Now setup a permanent failure for the overridden roots and we should get + an empty slice. */ + grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); + roots = grpc_get_default_ssl_roots_for_testing(); + GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots)); + + /* Cleanup. */ + remove(roots_env_var_file_path); + gpr_free(roots_env_var_file_path); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_unauthenticated_ssl_peer(); + test_cn_only_ssl_peer_to_auth_context(); + test_cn_and_one_san_ssl_peer_to_auth_context(); + test_cn_and_multiple_sans_ssl_peer_to_auth_context(); + test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); + test_default_ssl_roots(); + + grpc_shutdown(); + return 0; +} diff --git a/test/core/security/ssl_server_fuzzer.c b/test/core/security/ssl_server_fuzzer.c deleted file mode 100644 index f9b754b8f2..0000000000 --- a/test/core/security/ssl_server_fuzzer.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/transport/security_connector.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/memory_counters.h" -#include "test/core/util/mock_endpoint.h" - -bool squelch = true; -// ssl has an array of global gpr_mu's that are never released. -// Turning this on will fail the leak check. -bool leak_check = false; - -static void discard_write(grpc_slice slice) {} - -static void dont_log(gpr_log_func_args *args) {} - -struct handshake_state { - bool done_callback_called; -}; - -static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_handshaker_args *args = arg; - struct handshake_state *state = args->user_data; - GPR_ASSERT(state->done_callback_called == false); - state->done_callback_called = true; - // The fuzzer should not pass the handshake. - GPR_ASSERT(error != GRPC_ERROR_NONE); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - struct grpc_memory_counters counters; - if (squelch) gpr_set_log_function(dont_log); - if (leak_check) grpc_memory_counters_init(); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("ssl_server_fuzzer"); - grpc_endpoint *mock_endpoint = - grpc_mock_endpoint_create(discard_write, resource_quota); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - - grpc_mock_endpoint_put_read( - &exec_ctx, mock_endpoint, - grpc_slice_from_copied_buffer((const char *)data, size)); - - // Load key pair and establish server SSL credentials. - grpc_ssl_pem_key_cert_pair pem_key_cert_pair; - grpc_slice ca_slice, cert_slice, key_slice; - ca_slice = grpc_slice_from_static_string(test_root_cert); - cert_slice = grpc_slice_from_static_string(test_server1_cert); - key_slice = grpc_slice_from_static_string(test_server1_key); - const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); - pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); - grpc_server_credentials *creds = grpc_ssl_server_credentials_create( - ca_cert, &pem_key_cert_pair, 1, 0, NULL); - - // Create security connector - grpc_server_security_connector *sc = NULL; - grpc_security_status status = - grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc); - GPR_ASSERT(status == GRPC_SECURITY_OK); - grpc_millis deadline = GPR_MS_PER_SEC + grpc_exec_ctx_now(&exec_ctx); - - struct handshake_state state; - state.done_callback_called = false; - grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); - grpc_server_security_connector_add_handshakers(&exec_ctx, sc, handshake_mgr); - grpc_handshake_manager_do_handshake( - &exec_ctx, handshake_mgr, mock_endpoint, NULL /* channel_args */, - deadline, NULL /* acceptor */, on_handshake_done, &state); - grpc_exec_ctx_flush(&exec_ctx); - - // If the given string happens to be part of the correct client hello, the - // server will wait for more data. Explicitly fail the server by shutting down - // the endpoint. - if (!state.done_callback_called) { - grpc_endpoint_shutdown( - &exec_ctx, mock_endpoint, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Explicit close")); - grpc_exec_ctx_flush(&exec_ctx); - } - - GPR_ASSERT(state.done_callback_called); - - grpc_handshake_manager_destroy(&exec_ctx, handshake_mgr); - GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "test"); - grpc_server_credentials_release(creds); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); - grpc_exec_ctx_flush(&exec_ctx); - - grpc_shutdown(); - if (leak_check) { - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); - } - return 0; -} diff --git a/test/core/security/ssl_server_fuzzer.cc b/test/core/security/ssl_server_fuzzer.cc new file mode 100644 index 0000000000..9d43a416c3 --- /dev/null +++ b/test/core/security/ssl_server_fuzzer.cc @@ -0,0 +1,126 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/mock_endpoint.h" + +bool squelch = true; +// ssl has an array of global gpr_mu's that are never released. +// Turning this on will fail the leak check. +bool leak_check = false; + +static void discard_write(grpc_slice slice) {} + +static void dont_log(gpr_log_func_args *args) {} + +struct handshake_state { + bool done_callback_called; +}; + +static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_handshaker_args *args = static_cast(arg); + struct handshake_state *state = + static_cast(args->user_data); + GPR_ASSERT(state->done_callback_called == false); + state->done_callback_called = true; + // The fuzzer should not pass the handshake. + GPR_ASSERT(error != GRPC_ERROR_NONE); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct grpc_memory_counters counters; + if (squelch) gpr_set_log_function(dont_log); + if (leak_check) grpc_memory_counters_init(); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("ssl_server_fuzzer"); + grpc_endpoint *mock_endpoint = + grpc_mock_endpoint_create(discard_write, resource_quota); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + + grpc_mock_endpoint_put_read( + &exec_ctx, mock_endpoint, + grpc_slice_from_copied_buffer((const char *)data, size)); + + // Load key pair and establish server SSL credentials. + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_slice ca_slice, cert_slice, key_slice; + ca_slice = grpc_slice_from_static_string(test_root_cert); + cert_slice = grpc_slice_from_static_string(test_server1_cert); + key_slice = grpc_slice_from_static_string(test_server1_key); + const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); + pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); + grpc_server_credentials *creds = grpc_ssl_server_credentials_create( + ca_cert, &pem_key_cert_pair, 1, 0, NULL); + + // Create security connector + grpc_server_security_connector *sc = NULL; + grpc_security_status status = + grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc); + GPR_ASSERT(status == GRPC_SECURITY_OK); + grpc_millis deadline = GPR_MS_PER_SEC + grpc_exec_ctx_now(&exec_ctx); + + struct handshake_state state; + state.done_callback_called = false; + grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); + grpc_server_security_connector_add_handshakers(&exec_ctx, sc, handshake_mgr); + grpc_handshake_manager_do_handshake( + &exec_ctx, handshake_mgr, mock_endpoint, NULL /* channel_args */, + deadline, NULL /* acceptor */, on_handshake_done, &state); + grpc_exec_ctx_flush(&exec_ctx); + + // If the given string happens to be part of the correct client hello, the + // server will wait for more data. Explicitly fail the server by shutting down + // the endpoint. + if (!state.done_callback_called) { + grpc_endpoint_shutdown( + &exec_ctx, mock_endpoint, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Explicit close")); + grpc_exec_ctx_flush(&exec_ctx); + } + + GPR_ASSERT(state.done_callback_called); + + grpc_handshake_manager_destroy(&exec_ctx, handshake_mgr); + GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "test"); + grpc_server_credentials_release(creds); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + grpc_slice_unref(ca_slice); + grpc_exec_ctx_flush(&exec_ctx); + + grpc_shutdown(); + if (leak_check) { + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); + } + return 0; +} diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c deleted file mode 100644 index cec6fb94b4..0000000000 --- a/test/core/security/verify_jwt.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" - -typedef struct { - grpc_pollset *pollset; - gpr_mu *mu; - int is_done; - int success; -} synchronizer; - -static void print_usage_and_exit(gpr_cmdline *cl, const char *argv0) { - char *usage = gpr_cmdline_usage_string(cl, argv0); - fprintf(stderr, "%s", usage); - gpr_free(usage); - gpr_cmdline_destroy(cl); - exit(1); -} - -static void on_jwt_verification_done(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims) { - synchronizer *sync = user_data; - - sync->success = (status == GRPC_JWT_VERIFIER_OK); - if (sync->success) { - char *claims_str; - GPR_ASSERT(claims != NULL); - claims_str = - grpc_json_dump_to_string((grpc_json *)grpc_jwt_claims_json(claims), 2); - printf("Claims: \n\n%s\n", claims_str); - gpr_free(claims_str); - grpc_jwt_claims_destroy(exec_ctx, claims); - } else { - GPR_ASSERT(claims == NULL); - fprintf(stderr, "Verification failed with error %s\n", - grpc_jwt_verifier_status_to_string(status)); - } - - gpr_mu_lock(sync->mu); - sync->is_done = 1; - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, sync->pollset, NULL)); - gpr_mu_unlock(sync->mu); -} - -int main(int argc, char **argv) { - synchronizer sync; - grpc_jwt_verifier *verifier; - gpr_cmdline *cl; - char *jwt = NULL; - char *aud = NULL; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_init(); - cl = gpr_cmdline_create("JWT verifier tool"); - gpr_cmdline_add_string(cl, "jwt", "JSON web token to verify", &jwt); - gpr_cmdline_add_string(cl, "aud", "Audience for the JWT", &aud); - gpr_cmdline_parse(cl, argc, argv); - if (jwt == NULL || aud == NULL) { - print_usage_and_exit(cl, argv[0]); - } - - verifier = grpc_jwt_verifier_create(NULL, 0); - - grpc_init(); - - sync.pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(sync.pollset, &sync.mu); - sync.is_done = 0; - - grpc_jwt_verifier_verify(&exec_ctx, verifier, sync.pollset, jwt, aud, - on_jwt_verification_done, &sync); - - gpr_mu_lock(sync.mu); - while (!sync.is_done) { - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR("pollset_work", - grpc_pollset_work(&exec_ctx, sync.pollset, &worker, - GRPC_MILLIS_INF_FUTURE))) - sync.is_done = true; - gpr_mu_unlock(sync.mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(sync.mu); - } - gpr_mu_unlock(sync.mu); - - gpr_free(sync.pollset); - - grpc_jwt_verifier_destroy(&exec_ctx, verifier); - grpc_exec_ctx_finish(&exec_ctx); - gpr_cmdline_destroy(cl); - grpc_shutdown(); - return !sync.success; -} diff --git a/test/core/security/verify_jwt.cc b/test/core/security/verify_jwt.cc new file mode 100644 index 0000000000..c6591cf546 --- /dev/null +++ b/test/core/security/verify_jwt.cc @@ -0,0 +1,122 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" + +typedef struct { + grpc_pollset *pollset; + gpr_mu *mu; + int is_done; + int success; +} synchronizer; + +static void print_usage_and_exit(gpr_cmdline *cl, const char *argv0) { + char *usage = gpr_cmdline_usage_string(cl, argv0); + fprintf(stderr, "%s", usage); + gpr_free(usage); + gpr_cmdline_destroy(cl); + exit(1); +} + +static void on_jwt_verification_done(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims) { + synchronizer *sync = static_cast(user_data); + + sync->success = (status == GRPC_JWT_VERIFIER_OK); + if (sync->success) { + char *claims_str; + GPR_ASSERT(claims != NULL); + claims_str = + grpc_json_dump_to_string((grpc_json *)grpc_jwt_claims_json(claims), 2); + printf("Claims: \n\n%s\n", claims_str); + gpr_free(claims_str); + grpc_jwt_claims_destroy(exec_ctx, claims); + } else { + GPR_ASSERT(claims == NULL); + fprintf(stderr, "Verification failed with error %s\n", + grpc_jwt_verifier_status_to_string(status)); + } + + gpr_mu_lock(sync->mu); + sync->is_done = 1; + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, sync->pollset, NULL)); + gpr_mu_unlock(sync->mu); +} + +int main(int argc, char **argv) { + synchronizer sync; + grpc_jwt_verifier *verifier; + gpr_cmdline *cl; + const char *jwt = NULL; + const char *aud = NULL; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_init(); + cl = gpr_cmdline_create("JWT verifier tool"); + gpr_cmdline_add_string(cl, "jwt", "JSON web token to verify", &jwt); + gpr_cmdline_add_string(cl, "aud", "Audience for the JWT", &aud); + gpr_cmdline_parse(cl, argc, argv); + if (jwt == NULL || aud == NULL) { + print_usage_and_exit(cl, argv[0]); + } + + verifier = grpc_jwt_verifier_create(NULL, 0); + + grpc_init(); + + sync.pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(sync.pollset, &sync.mu); + sync.is_done = 0; + + grpc_jwt_verifier_verify(&exec_ctx, verifier, sync.pollset, jwt, aud, + on_jwt_verification_done, &sync); + + gpr_mu_lock(sync.mu); + while (!sync.is_done) { + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR("pollset_work", + grpc_pollset_work(&exec_ctx, sync.pollset, &worker, + GRPC_MILLIS_INF_FUTURE))) + sync.is_done = true; + gpr_mu_unlock(sync.mu); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(sync.mu); + } + gpr_mu_unlock(sync.mu); + + gpr_free(sync.pollset); + + grpc_jwt_verifier_destroy(&exec_ctx, verifier); + grpc_exec_ctx_finish(&exec_ctx); + gpr_cmdline_destroy(cl); + grpc_shutdown(); + return !sync.success; +} diff --git a/test/core/slice/b64_test.c b/test/core/slice/b64_test.c deleted file mode 100644 index bd375aa6a7..0000000000 --- a/test/core/slice/b64_test.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/slice/b64.h" - -#include - -#include -#include -#include -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -static int buffers_are_equal(const unsigned char *buf1, - const unsigned char *buf2, size_t size) { - size_t i; - for (i = 0; i < size; i++) { - if (buf1[i] != buf2[i]) { - gpr_log(GPR_ERROR, "buf1 and buf2 differ: buf1[%d] = %x vs buf2[%d] = %x", - (int)i, buf1[i], (int)i, buf2[i]); - return 0; - } - } - return 1; -} - -static void test_simple_encode_decode_b64(int url_safe, int multiline) { - const char *hello = "hello"; - char *hello_b64 = - grpc_base64_encode(hello, strlen(hello), url_safe, multiline); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice hello_slice = grpc_base64_decode(&exec_ctx, hello_b64, url_safe); - GPR_ASSERT(GRPC_SLICE_LENGTH(hello_slice) == strlen(hello)); - GPR_ASSERT(strncmp((const char *)GRPC_SLICE_START_PTR(hello_slice), hello, - GRPC_SLICE_LENGTH(hello_slice)) == 0); - - grpc_slice_unref_internal(&exec_ctx, hello_slice); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(hello_b64); -} - -static void test_full_range_encode_decode_b64(int url_safe, int multiline) { - unsigned char orig[256]; - size_t i; - char *b64; - grpc_slice orig_decoded; - for (i = 0; i < sizeof(orig); i++) orig[i] = (uint8_t)i; - - /* Try all the different paddings. */ - for (i = 0; i < 3; i++) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline); - orig_decoded = grpc_base64_decode(&exec_ctx, b64, url_safe); - GPR_ASSERT(GRPC_SLICE_LENGTH(orig_decoded) == (sizeof(orig) - i)); - GPR_ASSERT(buffers_are_equal(orig, GRPC_SLICE_START_PTR(orig_decoded), - sizeof(orig) - i)); - grpc_slice_unref_internal(&exec_ctx, orig_decoded); - gpr_free(b64); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_simple_encode_decode_b64_no_multiline(void) { - test_simple_encode_decode_b64(0, 0); -} - -static void test_simple_encode_decode_b64_multiline(void) { - test_simple_encode_decode_b64(0, 1); -} - -static void test_simple_encode_decode_b64_urlsafe_no_multiline(void) { - test_simple_encode_decode_b64(1, 0); -} - -static void test_simple_encode_decode_b64_urlsafe_multiline(void) { - test_simple_encode_decode_b64(1, 1); -} - -static void test_full_range_encode_decode_b64_no_multiline(void) { - test_full_range_encode_decode_b64(0, 0); -} - -static void test_full_range_encode_decode_b64_multiline(void) { - test_full_range_encode_decode_b64(0, 1); -} - -static void test_full_range_encode_decode_b64_urlsafe_no_multiline(void) { - test_full_range_encode_decode_b64(1, 0); -} - -static void test_full_range_encode_decode_b64_urlsafe_multiline(void) { - test_full_range_encode_decode_b64(1, 1); -} - -static void test_url_safe_unsafe_mismatch_failure(void) { - unsigned char orig[256]; - size_t i; - char *b64; - grpc_slice orig_decoded; - int url_safe = 1; - for (i = 0; i < sizeof(orig); i++) orig[i] = (uint8_t)i; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0); - orig_decoded = grpc_base64_decode(&exec_ctx, b64, !url_safe); - GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded)); - gpr_free(b64); - grpc_slice_unref_internal(&exec_ctx, orig_decoded); - - b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0); - orig_decoded = grpc_base64_decode(&exec_ctx, b64, url_safe); - GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded)); - gpr_free(b64); - grpc_slice_unref_internal(&exec_ctx, orig_decoded); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_rfc4648_test_vectors(void) { - char *b64; - - b64 = grpc_base64_encode("", 0, 0, 0); - GPR_ASSERT(strcmp("", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("f", 1, 0, 0); - GPR_ASSERT(strcmp("Zg==", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("fo", 2, 0, 0); - GPR_ASSERT(strcmp("Zm8=", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("foo", 3, 0, 0); - GPR_ASSERT(strcmp("Zm9v", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("foob", 4, 0, 0); - GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("fooba", 5, 0, 0); - GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0); - gpr_free(b64); - - b64 = grpc_base64_encode("foobar", 6, 0, 0); - GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0); - gpr_free(b64); -} - -static void test_unpadded_decode(void) { - grpc_slice decoded; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - decoded = grpc_base64_decode(&exec_ctx, "Zm9vYmFy", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "foobar") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "Zm9vYmE", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "fooba") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "Zm9vYg", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "foob") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "Zm9v", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "foo") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "Zm8", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "fo") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "Zg", 0); - GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); - GPR_ASSERT(grpc_slice_str_cmp(decoded, "f") == 0); - grpc_slice_unref(decoded); - - decoded = grpc_base64_decode(&exec_ctx, "", 0); - GPR_ASSERT(GRPC_SLICE_IS_EMPTY(decoded)); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_simple_encode_decode_b64_no_multiline(); - test_simple_encode_decode_b64_multiline(); - test_simple_encode_decode_b64_urlsafe_no_multiline(); - test_simple_encode_decode_b64_urlsafe_multiline(); - test_full_range_encode_decode_b64_no_multiline(); - test_full_range_encode_decode_b64_multiline(); - test_full_range_encode_decode_b64_urlsafe_no_multiline(); - test_full_range_encode_decode_b64_urlsafe_multiline(); - test_url_safe_unsafe_mismatch_failure(); - test_rfc4648_test_vectors(); - test_unpadded_decode(); - return 0; -} diff --git a/test/core/slice/b64_test.cc b/test/core/slice/b64_test.cc new file mode 100644 index 0000000000..bd375aa6a7 --- /dev/null +++ b/test/core/slice/b64_test.cc @@ -0,0 +1,219 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/slice/b64.h" + +#include + +#include +#include +#include +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +static int buffers_are_equal(const unsigned char *buf1, + const unsigned char *buf2, size_t size) { + size_t i; + for (i = 0; i < size; i++) { + if (buf1[i] != buf2[i]) { + gpr_log(GPR_ERROR, "buf1 and buf2 differ: buf1[%d] = %x vs buf2[%d] = %x", + (int)i, buf1[i], (int)i, buf2[i]); + return 0; + } + } + return 1; +} + +static void test_simple_encode_decode_b64(int url_safe, int multiline) { + const char *hello = "hello"; + char *hello_b64 = + grpc_base64_encode(hello, strlen(hello), url_safe, multiline); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice hello_slice = grpc_base64_decode(&exec_ctx, hello_b64, url_safe); + GPR_ASSERT(GRPC_SLICE_LENGTH(hello_slice) == strlen(hello)); + GPR_ASSERT(strncmp((const char *)GRPC_SLICE_START_PTR(hello_slice), hello, + GRPC_SLICE_LENGTH(hello_slice)) == 0); + + grpc_slice_unref_internal(&exec_ctx, hello_slice); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(hello_b64); +} + +static void test_full_range_encode_decode_b64(int url_safe, int multiline) { + unsigned char orig[256]; + size_t i; + char *b64; + grpc_slice orig_decoded; + for (i = 0; i < sizeof(orig); i++) orig[i] = (uint8_t)i; + + /* Try all the different paddings. */ + for (i = 0; i < 3; i++) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline); + orig_decoded = grpc_base64_decode(&exec_ctx, b64, url_safe); + GPR_ASSERT(GRPC_SLICE_LENGTH(orig_decoded) == (sizeof(orig) - i)); + GPR_ASSERT(buffers_are_equal(orig, GRPC_SLICE_START_PTR(orig_decoded), + sizeof(orig) - i)); + grpc_slice_unref_internal(&exec_ctx, orig_decoded); + gpr_free(b64); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_simple_encode_decode_b64_no_multiline(void) { + test_simple_encode_decode_b64(0, 0); +} + +static void test_simple_encode_decode_b64_multiline(void) { + test_simple_encode_decode_b64(0, 1); +} + +static void test_simple_encode_decode_b64_urlsafe_no_multiline(void) { + test_simple_encode_decode_b64(1, 0); +} + +static void test_simple_encode_decode_b64_urlsafe_multiline(void) { + test_simple_encode_decode_b64(1, 1); +} + +static void test_full_range_encode_decode_b64_no_multiline(void) { + test_full_range_encode_decode_b64(0, 0); +} + +static void test_full_range_encode_decode_b64_multiline(void) { + test_full_range_encode_decode_b64(0, 1); +} + +static void test_full_range_encode_decode_b64_urlsafe_no_multiline(void) { + test_full_range_encode_decode_b64(1, 0); +} + +static void test_full_range_encode_decode_b64_urlsafe_multiline(void) { + test_full_range_encode_decode_b64(1, 1); +} + +static void test_url_safe_unsafe_mismatch_failure(void) { + unsigned char orig[256]; + size_t i; + char *b64; + grpc_slice orig_decoded; + int url_safe = 1; + for (i = 0; i < sizeof(orig); i++) orig[i] = (uint8_t)i; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0); + orig_decoded = grpc_base64_decode(&exec_ctx, b64, !url_safe); + GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded)); + gpr_free(b64); + grpc_slice_unref_internal(&exec_ctx, orig_decoded); + + b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0); + orig_decoded = grpc_base64_decode(&exec_ctx, b64, url_safe); + GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded)); + gpr_free(b64); + grpc_slice_unref_internal(&exec_ctx, orig_decoded); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_rfc4648_test_vectors(void) { + char *b64; + + b64 = grpc_base64_encode("", 0, 0, 0); + GPR_ASSERT(strcmp("", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("f", 1, 0, 0); + GPR_ASSERT(strcmp("Zg==", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("fo", 2, 0, 0); + GPR_ASSERT(strcmp("Zm8=", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("foo", 3, 0, 0); + GPR_ASSERT(strcmp("Zm9v", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("foob", 4, 0, 0); + GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("fooba", 5, 0, 0); + GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0); + gpr_free(b64); + + b64 = grpc_base64_encode("foobar", 6, 0, 0); + GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0); + gpr_free(b64); +} + +static void test_unpadded_decode(void) { + grpc_slice decoded; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + decoded = grpc_base64_decode(&exec_ctx, "Zm9vYmFy", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "foobar") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "Zm9vYmE", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "fooba") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "Zm9vYg", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "foob") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "Zm9v", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "foo") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "Zm8", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "fo") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "Zg", 0); + GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded)); + GPR_ASSERT(grpc_slice_str_cmp(decoded, "f") == 0); + grpc_slice_unref(decoded); + + decoded = grpc_base64_decode(&exec_ctx, "", 0); + GPR_ASSERT(GRPC_SLICE_IS_EMPTY(decoded)); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_simple_encode_decode_b64_no_multiline(); + test_simple_encode_decode_b64_multiline(); + test_simple_encode_decode_b64_urlsafe_no_multiline(); + test_simple_encode_decode_b64_urlsafe_multiline(); + test_full_range_encode_decode_b64_no_multiline(); + test_full_range_encode_decode_b64_multiline(); + test_full_range_encode_decode_b64_urlsafe_no_multiline(); + test_full_range_encode_decode_b64_urlsafe_multiline(); + test_url_safe_unsafe_mismatch_failure(); + test_rfc4648_test_vectors(); + test_unpadded_decode(); + return 0; +} diff --git a/test/core/slice/percent_decode_fuzzer.c b/test/core/slice/percent_decode_fuzzer.c deleted file mode 100644 index ad4e3fed7a..0000000000 --- a/test/core/slice/percent_decode_fuzzer.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include - -#include "src/core/lib/slice/percent_encoding.h" -#include "test/core/util/memory_counters.h" - -bool squelch = true; -bool leak_check = true; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - struct grpc_memory_counters counters; - grpc_memory_counters_init(); - grpc_slice input = grpc_slice_from_copied_buffer((const char *)data, size); - grpc_slice output; - if (grpc_strict_percent_decode_slice( - input, grpc_url_percent_encoding_unreserved_bytes, &output)) { - grpc_slice_unref(output); - } - if (grpc_strict_percent_decode_slice( - input, grpc_compatible_percent_encoding_unreserved_bytes, &output)) { - grpc_slice_unref(output); - } - grpc_slice_unref(grpc_permissive_percent_decode_slice(input)); - grpc_slice_unref(input); - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); - return 0; -} diff --git a/test/core/slice/percent_decode_fuzzer.cc b/test/core/slice/percent_decode_fuzzer.cc new file mode 100644 index 0000000000..ad4e3fed7a --- /dev/null +++ b/test/core/slice/percent_decode_fuzzer.cc @@ -0,0 +1,51 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include + +#include "src/core/lib/slice/percent_encoding.h" +#include "test/core/util/memory_counters.h" + +bool squelch = true; +bool leak_check = true; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct grpc_memory_counters counters; + grpc_memory_counters_init(); + grpc_slice input = grpc_slice_from_copied_buffer((const char *)data, size); + grpc_slice output; + if (grpc_strict_percent_decode_slice( + input, grpc_url_percent_encoding_unreserved_bytes, &output)) { + grpc_slice_unref(output); + } + if (grpc_strict_percent_decode_slice( + input, grpc_compatible_percent_encoding_unreserved_bytes, &output)) { + grpc_slice_unref(output); + } + grpc_slice_unref(grpc_permissive_percent_decode_slice(input)); + grpc_slice_unref(input); + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); + return 0; +} diff --git a/test/core/slice/percent_encode_fuzzer.c b/test/core/slice/percent_encode_fuzzer.c deleted file mode 100644 index db3dc3bb3f..0000000000 --- a/test/core/slice/percent_encode_fuzzer.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include - -#include "src/core/lib/slice/percent_encoding.h" -#include "test/core/util/memory_counters.h" - -bool squelch = true; -bool leak_check = true; - -static void test(const uint8_t *data, size_t size, const uint8_t *dict) { - struct grpc_memory_counters counters; - grpc_memory_counters_init(); - grpc_slice input = grpc_slice_from_copied_buffer((const char *)data, size); - grpc_slice output = grpc_percent_encode_slice(input, dict); - grpc_slice decoded_output; - // encoder must always produce decodable output - GPR_ASSERT(grpc_strict_percent_decode_slice(output, dict, &decoded_output)); - grpc_slice permissive_decoded_output = - grpc_permissive_percent_decode_slice(output); - // and decoded output must always match the input - GPR_ASSERT(grpc_slice_eq(input, decoded_output)); - GPR_ASSERT(grpc_slice_eq(input, permissive_decoded_output)); - grpc_slice_unref(input); - grpc_slice_unref(output); - grpc_slice_unref(decoded_output); - grpc_slice_unref(permissive_decoded_output); - counters = grpc_memory_counters_snapshot(); - grpc_memory_counters_destroy(); - GPR_ASSERT(counters.total_size_relative == 0); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - test(data, size, grpc_url_percent_encoding_unreserved_bytes); - test(data, size, grpc_compatible_percent_encoding_unreserved_bytes); - return 0; -} diff --git a/test/core/slice/percent_encode_fuzzer.cc b/test/core/slice/percent_encode_fuzzer.cc new file mode 100644 index 0000000000..db3dc3bb3f --- /dev/null +++ b/test/core/slice/percent_encode_fuzzer.cc @@ -0,0 +1,58 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include + +#include "src/core/lib/slice/percent_encoding.h" +#include "test/core/util/memory_counters.h" + +bool squelch = true; +bool leak_check = true; + +static void test(const uint8_t *data, size_t size, const uint8_t *dict) { + struct grpc_memory_counters counters; + grpc_memory_counters_init(); + grpc_slice input = grpc_slice_from_copied_buffer((const char *)data, size); + grpc_slice output = grpc_percent_encode_slice(input, dict); + grpc_slice decoded_output; + // encoder must always produce decodable output + GPR_ASSERT(grpc_strict_percent_decode_slice(output, dict, &decoded_output)); + grpc_slice permissive_decoded_output = + grpc_permissive_percent_decode_slice(output); + // and decoded output must always match the input + GPR_ASSERT(grpc_slice_eq(input, decoded_output)); + GPR_ASSERT(grpc_slice_eq(input, permissive_decoded_output)); + grpc_slice_unref(input); + grpc_slice_unref(output); + grpc_slice_unref(decoded_output); + grpc_slice_unref(permissive_decoded_output); + counters = grpc_memory_counters_snapshot(); + grpc_memory_counters_destroy(); + GPR_ASSERT(counters.total_size_relative == 0); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + test(data, size, grpc_url_percent_encoding_unreserved_bytes); + test(data, size, grpc_compatible_percent_encoding_unreserved_bytes); + return 0; +} diff --git a/test/core/slice/percent_encoding_test.c b/test/core/slice/percent_encoding_test.c deleted file mode 100644 index fcc8d33db3..0000000000 --- a/test/core/slice/percent_encoding_test.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/slice/percent_encoding.h" - -#include -#include - -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#define TEST_VECTOR(raw, encoded, dict) \ - test_vector(raw, sizeof(raw) - 1, encoded, sizeof(encoded) - 1, dict) - -#define TEST_NONCONFORMANT_VECTOR(encoded, permissive_unencoded, dict) \ - test_nonconformant_vector(encoded, sizeof(encoded) - 1, \ - permissive_unencoded, \ - sizeof(permissive_unencoded) - 1, dict) - -static void test_vector(const char *raw, size_t raw_length, const char *encoded, - size_t encoded_length, const uint8_t *dict) { - char *raw_msg = gpr_dump(raw, raw_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *encoded_msg = - gpr_dump(encoded, encoded_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "Trial:\nraw = %s\nencoded = %s", raw_msg, encoded_msg); - gpr_free(raw_msg); - gpr_free(encoded_msg); - - grpc_slice raw_slice = grpc_slice_from_copied_buffer(raw, raw_length); - grpc_slice encoded_slice = - grpc_slice_from_copied_buffer(encoded, encoded_length); - grpc_slice raw2encoded_slice = grpc_percent_encode_slice(raw_slice, dict); - grpc_slice encoded2raw_slice; - GPR_ASSERT(grpc_strict_percent_decode_slice(encoded_slice, dict, - &encoded2raw_slice)); - grpc_slice encoded2raw_permissive_slice = - grpc_permissive_percent_decode_slice(encoded_slice); - - char *raw2encoded_msg = - grpc_dump_slice(raw2encoded_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *encoded2raw_msg = - grpc_dump_slice(encoded2raw_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *encoded2raw_permissive_msg = grpc_dump_slice( - encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, - "Result:\nraw2encoded = %s\nencoded2raw = %s\nencoded2raw_permissive " - "= %s", - raw2encoded_msg, encoded2raw_msg, encoded2raw_permissive_msg); - gpr_free(raw2encoded_msg); - gpr_free(encoded2raw_msg); - gpr_free(encoded2raw_permissive_msg); - - GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_slice)); - GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_permissive_slice)); - GPR_ASSERT(grpc_slice_eq(encoded_slice, raw2encoded_slice)); - - grpc_slice_unref(encoded2raw_slice); - grpc_slice_unref(encoded2raw_permissive_slice); - grpc_slice_unref(raw2encoded_slice); - grpc_slice_unref(raw_slice); - grpc_slice_unref(encoded_slice); -} - -static void test_nonconformant_vector(const char *encoded, - size_t encoded_length, - const char *permissive_unencoded, - size_t permissive_unencoded_length, - const uint8_t *dict) { - char *permissive_unencoded_msg = - gpr_dump(permissive_unencoded, permissive_unencoded_length, - GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *encoded_msg = - gpr_dump(encoded, encoded_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "Trial:\nraw = %s\nencoded = %s", permissive_unencoded_msg, - encoded_msg); - gpr_free(permissive_unencoded_msg); - gpr_free(encoded_msg); - - grpc_slice permissive_unencoded_slice = grpc_slice_from_copied_buffer( - permissive_unencoded, permissive_unencoded_length); - grpc_slice encoded_slice = - grpc_slice_from_copied_buffer(encoded, encoded_length); - grpc_slice encoded2raw_slice; - GPR_ASSERT(!grpc_strict_percent_decode_slice(encoded_slice, dict, - &encoded2raw_slice)); - grpc_slice encoded2raw_permissive_slice = - grpc_permissive_percent_decode_slice(encoded_slice); - - char *encoded2raw_permissive_msg = grpc_dump_slice( - encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "Result:\nencoded2raw_permissive = %s", - encoded2raw_permissive_msg); - gpr_free(encoded2raw_permissive_msg); - - GPR_ASSERT( - grpc_slice_eq(permissive_unencoded_slice, encoded2raw_permissive_slice)); - - grpc_slice_unref(permissive_unencoded_slice); - grpc_slice_unref(encoded2raw_permissive_slice); - grpc_slice_unref(encoded_slice); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - TEST_VECTOR( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", - grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("\x00", "%00", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("\x01", "%01", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("a b", "a%20b", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR(" b", "%20b", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("a b", "a b", grpc_compatible_percent_encoding_unreserved_bytes); - TEST_VECTOR(" b", " b", grpc_compatible_percent_encoding_unreserved_bytes); - TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes); - TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes); - TEST_NONCONFORMANT_VECTOR("%", "%", - grpc_url_percent_encoding_unreserved_bytes); - TEST_NONCONFORMANT_VECTOR("%A", "%A", - grpc_url_percent_encoding_unreserved_bytes); - TEST_NONCONFORMANT_VECTOR("%AG", "%AG", - grpc_url_percent_encoding_unreserved_bytes); - TEST_NONCONFORMANT_VECTOR("\0", "\0", - grpc_url_percent_encoding_unreserved_bytes); - return 0; -} diff --git a/test/core/slice/percent_encoding_test.cc b/test/core/slice/percent_encoding_test.cc new file mode 100644 index 0000000000..fcc8d33db3 --- /dev/null +++ b/test/core/slice/percent_encoding_test.cc @@ -0,0 +1,144 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/slice/percent_encoding.h" + +#include +#include + +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#define TEST_VECTOR(raw, encoded, dict) \ + test_vector(raw, sizeof(raw) - 1, encoded, sizeof(encoded) - 1, dict) + +#define TEST_NONCONFORMANT_VECTOR(encoded, permissive_unencoded, dict) \ + test_nonconformant_vector(encoded, sizeof(encoded) - 1, \ + permissive_unencoded, \ + sizeof(permissive_unencoded) - 1, dict) + +static void test_vector(const char *raw, size_t raw_length, const char *encoded, + size_t encoded_length, const uint8_t *dict) { + char *raw_msg = gpr_dump(raw, raw_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *encoded_msg = + gpr_dump(encoded, encoded_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "Trial:\nraw = %s\nencoded = %s", raw_msg, encoded_msg); + gpr_free(raw_msg); + gpr_free(encoded_msg); + + grpc_slice raw_slice = grpc_slice_from_copied_buffer(raw, raw_length); + grpc_slice encoded_slice = + grpc_slice_from_copied_buffer(encoded, encoded_length); + grpc_slice raw2encoded_slice = grpc_percent_encode_slice(raw_slice, dict); + grpc_slice encoded2raw_slice; + GPR_ASSERT(grpc_strict_percent_decode_slice(encoded_slice, dict, + &encoded2raw_slice)); + grpc_slice encoded2raw_permissive_slice = + grpc_permissive_percent_decode_slice(encoded_slice); + + char *raw2encoded_msg = + grpc_dump_slice(raw2encoded_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *encoded2raw_msg = + grpc_dump_slice(encoded2raw_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *encoded2raw_permissive_msg = grpc_dump_slice( + encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, + "Result:\nraw2encoded = %s\nencoded2raw = %s\nencoded2raw_permissive " + "= %s", + raw2encoded_msg, encoded2raw_msg, encoded2raw_permissive_msg); + gpr_free(raw2encoded_msg); + gpr_free(encoded2raw_msg); + gpr_free(encoded2raw_permissive_msg); + + GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_slice)); + GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_permissive_slice)); + GPR_ASSERT(grpc_slice_eq(encoded_slice, raw2encoded_slice)); + + grpc_slice_unref(encoded2raw_slice); + grpc_slice_unref(encoded2raw_permissive_slice); + grpc_slice_unref(raw2encoded_slice); + grpc_slice_unref(raw_slice); + grpc_slice_unref(encoded_slice); +} + +static void test_nonconformant_vector(const char *encoded, + size_t encoded_length, + const char *permissive_unencoded, + size_t permissive_unencoded_length, + const uint8_t *dict) { + char *permissive_unencoded_msg = + gpr_dump(permissive_unencoded, permissive_unencoded_length, + GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *encoded_msg = + gpr_dump(encoded, encoded_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "Trial:\nraw = %s\nencoded = %s", permissive_unencoded_msg, + encoded_msg); + gpr_free(permissive_unencoded_msg); + gpr_free(encoded_msg); + + grpc_slice permissive_unencoded_slice = grpc_slice_from_copied_buffer( + permissive_unencoded, permissive_unencoded_length); + grpc_slice encoded_slice = + grpc_slice_from_copied_buffer(encoded, encoded_length); + grpc_slice encoded2raw_slice; + GPR_ASSERT(!grpc_strict_percent_decode_slice(encoded_slice, dict, + &encoded2raw_slice)); + grpc_slice encoded2raw_permissive_slice = + grpc_permissive_percent_decode_slice(encoded_slice); + + char *encoded2raw_permissive_msg = grpc_dump_slice( + encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "Result:\nencoded2raw_permissive = %s", + encoded2raw_permissive_msg); + gpr_free(encoded2raw_permissive_msg); + + GPR_ASSERT( + grpc_slice_eq(permissive_unencoded_slice, encoded2raw_permissive_slice)); + + grpc_slice_unref(permissive_unencoded_slice); + grpc_slice_unref(encoded2raw_permissive_slice); + grpc_slice_unref(encoded_slice); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + TEST_VECTOR( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", + grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("\x00", "%00", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("\x01", "%01", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("a b", "a%20b", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR(" b", "%20b", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("a b", "a b", grpc_compatible_percent_encoding_unreserved_bytes); + TEST_VECTOR(" b", " b", grpc_compatible_percent_encoding_unreserved_bytes); + TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes); + TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes); + TEST_NONCONFORMANT_VECTOR("%", "%", + grpc_url_percent_encoding_unreserved_bytes); + TEST_NONCONFORMANT_VECTOR("%A", "%A", + grpc_url_percent_encoding_unreserved_bytes); + TEST_NONCONFORMANT_VECTOR("%AG", "%AG", + grpc_url_percent_encoding_unreserved_bytes); + TEST_NONCONFORMANT_VECTOR("\0", "\0", + grpc_url_percent_encoding_unreserved_bytes); + return 0; +} diff --git a/test/core/slice/slice_buffer_test.c b/test/core/slice/slice_buffer_test.c deleted file mode 100644 index 2fba496bd0..0000000000 --- a/test/core/slice/slice_buffer_test.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include "test/core/util/test_config.h" - -void test_slice_buffer_add() { - grpc_slice_buffer buf; - grpc_slice aaa = grpc_slice_from_copied_string("aaa"); - grpc_slice bb = grpc_slice_from_copied_string("bb"); - size_t i; - - grpc_slice_buffer_init(&buf); - for (i = 0; i < 10; i++) { - grpc_slice_ref(aaa); - grpc_slice_ref(bb); - grpc_slice_buffer_add(&buf, aaa); - grpc_slice_buffer_add(&buf, bb); - } - GPR_ASSERT(buf.count > 0); - GPR_ASSERT(buf.length == 50); - grpc_slice_buffer_reset_and_unref(&buf); - GPR_ASSERT(buf.count == 0); - GPR_ASSERT(buf.length == 0); - for (i = 0; i < 10; i++) { - grpc_slice_ref(aaa); - grpc_slice_ref(bb); - grpc_slice_buffer_add(&buf, aaa); - grpc_slice_buffer_add(&buf, bb); - } - GPR_ASSERT(buf.count > 0); - GPR_ASSERT(buf.length == 50); - for (i = 0; i < 10; i++) { - grpc_slice_buffer_pop(&buf); - grpc_slice_unref(aaa); - grpc_slice_unref(bb); - } - GPR_ASSERT(buf.count == 0); - GPR_ASSERT(buf.length == 0); - grpc_slice_buffer_destroy(&buf); -} - -void test_slice_buffer_move_first() { - grpc_slice slices[3]; - grpc_slice_buffer src; - grpc_slice_buffer dst; - int idx = 0; - size_t src_len = 0; - size_t dst_len = 0; - - slices[0] = grpc_slice_from_copied_string("aaa"); - slices[1] = grpc_slice_from_copied_string("bbbb"); - slices[2] = grpc_slice_from_copied_string("ccc"); - - grpc_slice_buffer_init(&src); - grpc_slice_buffer_init(&dst); - for (idx = 0; idx < 3; idx++) { - grpc_slice_ref(slices[idx]); - /* For this test, it is important that we add each slice at a new - slice index */ - grpc_slice_buffer_add_indexed(&src, slices[idx]); - grpc_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; - grpc_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 */ - grpc_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*/ - grpc_slice_buffer_move_first(&src, 2, &dst); - src_len -= 2; - dst_len += 2; - GPR_ASSERT(src.length == src_len); - GPR_ASSERT(dst.length == dst_len); -} - -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/slice/slice_buffer_test.cc b/test/core/slice/slice_buffer_test.cc new file mode 100644 index 0000000000..2fba496bd0 --- /dev/null +++ b/test/core/slice/slice_buffer_test.cc @@ -0,0 +1,114 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include "test/core/util/test_config.h" + +void test_slice_buffer_add() { + grpc_slice_buffer buf; + grpc_slice aaa = grpc_slice_from_copied_string("aaa"); + grpc_slice bb = grpc_slice_from_copied_string("bb"); + size_t i; + + grpc_slice_buffer_init(&buf); + for (i = 0; i < 10; i++) { + grpc_slice_ref(aaa); + grpc_slice_ref(bb); + grpc_slice_buffer_add(&buf, aaa); + grpc_slice_buffer_add(&buf, bb); + } + GPR_ASSERT(buf.count > 0); + GPR_ASSERT(buf.length == 50); + grpc_slice_buffer_reset_and_unref(&buf); + GPR_ASSERT(buf.count == 0); + GPR_ASSERT(buf.length == 0); + for (i = 0; i < 10; i++) { + grpc_slice_ref(aaa); + grpc_slice_ref(bb); + grpc_slice_buffer_add(&buf, aaa); + grpc_slice_buffer_add(&buf, bb); + } + GPR_ASSERT(buf.count > 0); + GPR_ASSERT(buf.length == 50); + for (i = 0; i < 10; i++) { + grpc_slice_buffer_pop(&buf); + grpc_slice_unref(aaa); + grpc_slice_unref(bb); + } + GPR_ASSERT(buf.count == 0); + GPR_ASSERT(buf.length == 0); + grpc_slice_buffer_destroy(&buf); +} + +void test_slice_buffer_move_first() { + grpc_slice slices[3]; + grpc_slice_buffer src; + grpc_slice_buffer dst; + int idx = 0; + size_t src_len = 0; + size_t dst_len = 0; + + slices[0] = grpc_slice_from_copied_string("aaa"); + slices[1] = grpc_slice_from_copied_string("bbbb"); + slices[2] = grpc_slice_from_copied_string("ccc"); + + grpc_slice_buffer_init(&src); + grpc_slice_buffer_init(&dst); + for (idx = 0; idx < 3; idx++) { + grpc_slice_ref(slices[idx]); + /* For this test, it is important that we add each slice at a new + slice index */ + grpc_slice_buffer_add_indexed(&src, slices[idx]); + grpc_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; + grpc_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 */ + grpc_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*/ + grpc_slice_buffer_move_first(&src, 2, &dst); + src_len -= 2; + dst_len += 2; + GPR_ASSERT(src.length == src_len); + GPR_ASSERT(dst.length == dst_len); +} + +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/slice/slice_hash_table_test.c b/test/core/slice/slice_hash_table_test.c deleted file mode 100644 index f3689aac64..0000000000 --- a/test/core/slice/slice_hash_table_test.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/slice/slice_hash_table.h" - -#include - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/util/test_config.h" - -typedef struct { - char* key; - char* value; -} test_entry; - -static void populate_entries(const test_entry* input, size_t num_entries, - grpc_slice_hash_table_entry* output) { - for (size_t i = 0; i < num_entries; ++i) { - output[i].key = grpc_slice_from_copied_string(input[i].key); - output[i].value = gpr_strdup(input[i].value); - } -} - -static void check_values(const test_entry* input, size_t num_entries, - grpc_slice_hash_table* table) { - for (size_t i = 0; i < num_entries; ++i) { - grpc_slice key = grpc_slice_from_static_string(input[i].key); - char* actual = grpc_slice_hash_table_get(table, key); - GPR_ASSERT(actual != NULL); - GPR_ASSERT(strcmp(actual, input[i].value) == 0); - grpc_slice_unref(key); - } -} - -static void check_non_existent_value(const char* key_string, - grpc_slice_hash_table* table) { - grpc_slice key = grpc_slice_from_static_string(key_string); - GPR_ASSERT(grpc_slice_hash_table_get(table, key) == NULL); - grpc_slice_unref(key); -} - -static void destroy_string(grpc_exec_ctx* exec_ctx, void* value) { - gpr_free(value); -} - -static grpc_slice_hash_table* create_table_from_entries( - const test_entry* test_entries, size_t num_test_entries, - int (*value_cmp_fn)(void*, void*)) { - // Construct table. - grpc_slice_hash_table_entry* entries = - gpr_zalloc(sizeof(*entries) * num_test_entries); - populate_entries(test_entries, num_test_entries, entries); - grpc_slice_hash_table* table = grpc_slice_hash_table_create( - num_test_entries, entries, destroy_string, value_cmp_fn); - gpr_free(entries); - return table; -} - -static void test_slice_hash_table() { - const test_entry test_entries[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}, - {"key_3", "value_3"}, {"key_4", "value_4"}, {"key_5", "value_5"}, - {"key_6", "value_6"}, {"key_7", "value_7"}, {"key_8", "value_8"}, - {"key_9", "value_9"}, {"key_10", "value_10"}, {"key_11", "value_11"}, - {"key_12", "value_12"}, {"key_13", "value_13"}, {"key_14", "value_14"}, - {"key_15", "value_15"}, {"key_16", "value_16"}, {"key_17", "value_17"}, - {"key_18", "value_18"}, {"key_19", "value_19"}, {"key_20", "value_20"}, - {"key_21", "value_21"}, {"key_22", "value_22"}, {"key_23", "value_23"}, - {"key_24", "value_24"}, {"key_25", "value_25"}, {"key_26", "value_26"}, - {"key_27", "value_27"}, {"key_28", "value_28"}, {"key_29", "value_29"}, - {"key_30", "value_30"}, {"key_31", "value_31"}, {"key_32", "value_32"}, - {"key_33", "value_33"}, {"key_34", "value_34"}, {"key_35", "value_35"}, - {"key_36", "value_36"}, {"key_37", "value_37"}, {"key_38", "value_38"}, - {"key_39", "value_39"}, {"key_40", "value_40"}, {"key_41", "value_41"}, - {"key_42", "value_42"}, {"key_43", "value_43"}, {"key_44", "value_44"}, - {"key_45", "value_45"}, {"key_46", "value_46"}, {"key_47", "value_47"}, - {"key_48", "value_48"}, {"key_49", "value_49"}, {"key_50", "value_50"}, - {"key_51", "value_51"}, {"key_52", "value_52"}, {"key_53", "value_53"}, - {"key_54", "value_54"}, {"key_55", "value_55"}, {"key_56", "value_56"}, - {"key_57", "value_57"}, {"key_58", "value_58"}, {"key_59", "value_59"}, - {"key_60", "value_60"}, {"key_61", "value_61"}, {"key_62", "value_62"}, - {"key_63", "value_63"}, {"key_64", "value_64"}, {"key_65", "value_65"}, - {"key_66", "value_66"}, {"key_67", "value_67"}, {"key_68", "value_68"}, - {"key_69", "value_69"}, {"key_70", "value_70"}, {"key_71", "value_71"}, - {"key_72", "value_72"}, {"key_73", "value_73"}, {"key_74", "value_74"}, - {"key_75", "value_75"}, {"key_76", "value_76"}, {"key_77", "value_77"}, - {"key_78", "value_78"}, {"key_79", "value_79"}, {"key_80", "value_80"}, - {"key_81", "value_81"}, {"key_82", "value_82"}, {"key_83", "value_83"}, - {"key_84", "value_84"}, {"key_85", "value_85"}, {"key_86", "value_86"}, - {"key_87", "value_87"}, {"key_88", "value_88"}, {"key_89", "value_89"}, - {"key_90", "value_90"}, {"key_91", "value_91"}, {"key_92", "value_92"}, - {"key_93", "value_93"}, {"key_94", "value_94"}, {"key_95", "value_95"}, - {"key_96", "value_96"}, {"key_97", "value_97"}, {"key_98", "value_98"}, - {"key_99", "value_99"}, - }; - const size_t num_entries = GPR_ARRAY_SIZE(test_entries); - grpc_slice_hash_table* table = - create_table_from_entries(test_entries, num_entries, NULL); - // Check contents of table. - check_values(test_entries, num_entries, table); - check_non_existent_value("XX", table); - // Clean up. - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_hash_table_unref(&exec_ctx, table); - grpc_exec_ctx_finish(&exec_ctx); -} - -static int value_cmp_fn(void* a, void* b) { - const char* a_str = a; - const char* b_str = b; - return strcmp(a_str, b_str); -} - -static int pointer_cmp_fn(void* a, void* b) { return GPR_ICMP(a, b); } - -static void test_slice_hash_table_eq() { - const test_entry test_entries_a[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_a = GPR_ARRAY_SIZE(test_entries_a); - grpc_slice_hash_table* table_a = - create_table_from_entries(test_entries_a, num_entries_a, value_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_a) == 0); - - const test_entry test_entries_b[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_b = GPR_ARRAY_SIZE(test_entries_b); - grpc_slice_hash_table* table_b = - create_table_from_entries(test_entries_b, num_entries_b, value_cmp_fn); - - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b) == 0); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_hash_table_unref(&exec_ctx, table_a); - grpc_slice_hash_table_unref(&exec_ctx, table_b); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_slice_hash_table_not_eq() { - const test_entry test_entries_a[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_a = GPR_ARRAY_SIZE(test_entries_a); - grpc_slice_hash_table* table_a = - create_table_from_entries(test_entries_a, num_entries_a, value_cmp_fn); - - // Different sizes. - const test_entry test_entries_b_smaller[] = {{"key_0", "value_0"}, - {"key_1", "value_1"}}; - const size_t num_entries_b_smaller = GPR_ARRAY_SIZE(test_entries_b_smaller); - grpc_slice_hash_table* table_b_smaller = create_table_from_entries( - test_entries_b_smaller, num_entries_b_smaller, value_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b_smaller) > 0); - - const test_entry test_entries_b_larger[] = {{"key_0", "value_0"}, - {"key_1", "value_1"}, - {"key_2", "value_2"}, - {"key_3", "value_3"}}; - const size_t num_entries_b_larger = GPR_ARRAY_SIZE(test_entries_b_larger); - grpc_slice_hash_table* table_b_larger = create_table_from_entries( - test_entries_b_larger, num_entries_b_larger, value_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b_larger) < 0); - - // One key doesn't match and is lexicographically "smaller". - const test_entry test_entries_c[] = { - {"key_zz", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_c = GPR_ARRAY_SIZE(test_entries_c); - grpc_slice_hash_table* table_c = - create_table_from_entries(test_entries_c, num_entries_c, value_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_c) > 0); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_c, table_a) < 0); - - // One value doesn't match. - const test_entry test_entries_d[] = { - {"key_0", "value_z"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_d = GPR_ARRAY_SIZE(test_entries_d); - grpc_slice_hash_table* table_d = - create_table_from_entries(test_entries_d, num_entries_d, value_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_d) < 0); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_d, table_a) > 0); - - // Same values but different "equals" functions. - const test_entry test_entries_e[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_e = GPR_ARRAY_SIZE(test_entries_e); - grpc_slice_hash_table* table_e = - create_table_from_entries(test_entries_e, num_entries_e, value_cmp_fn); - const test_entry test_entries_f[] = { - {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; - const size_t num_entries_f = GPR_ARRAY_SIZE(test_entries_f); - grpc_slice_hash_table* table_f = - create_table_from_entries(test_entries_f, num_entries_f, pointer_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_e, table_f) != 0); - - // Same (empty) key, different values. - const test_entry test_entries_g[] = {{"", "value_0"}}; - const size_t num_entries_g = GPR_ARRAY_SIZE(test_entries_g); - grpc_slice_hash_table* table_g = - create_table_from_entries(test_entries_g, num_entries_g, value_cmp_fn); - const test_entry test_entries_h[] = {{"", "value_1"}}; - const size_t num_entries_h = GPR_ARRAY_SIZE(test_entries_h); - grpc_slice_hash_table* table_h = - create_table_from_entries(test_entries_h, num_entries_h, pointer_cmp_fn); - GPR_ASSERT(grpc_slice_hash_table_cmp(table_g, table_h) != 0); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_slice_hash_table_unref(&exec_ctx, table_a); - grpc_slice_hash_table_unref(&exec_ctx, table_b_larger); - grpc_slice_hash_table_unref(&exec_ctx, table_b_smaller); - grpc_slice_hash_table_unref(&exec_ctx, table_c); - grpc_slice_hash_table_unref(&exec_ctx, table_d); - grpc_slice_hash_table_unref(&exec_ctx, table_e); - grpc_slice_hash_table_unref(&exec_ctx, table_f); - grpc_slice_hash_table_unref(&exec_ctx, table_g); - grpc_slice_hash_table_unref(&exec_ctx, table_h); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - test_slice_hash_table(); - test_slice_hash_table_eq(); - test_slice_hash_table_not_eq(); - return 0; -} diff --git a/test/core/slice/slice_hash_table_test.cc b/test/core/slice/slice_hash_table_test.cc new file mode 100644 index 0000000000..a2006b3c10 --- /dev/null +++ b/test/core/slice/slice_hash_table_test.cc @@ -0,0 +1,243 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/slice/slice_hash_table.h" + +#include + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +typedef struct { + const char* key; + const char* value; +} test_entry; + +static void populate_entries(const test_entry* input, size_t num_entries, + grpc_slice_hash_table_entry* output) { + for (size_t i = 0; i < num_entries; ++i) { + output[i].key = grpc_slice_from_copied_string(input[i].key); + output[i].value = gpr_strdup(input[i].value); + } +} + +static void check_values(const test_entry* input, size_t num_entries, + grpc_slice_hash_table* table) { + for (size_t i = 0; i < num_entries; ++i) { + grpc_slice key = grpc_slice_from_static_string(input[i].key); + const char* actual = + static_cast(grpc_slice_hash_table_get(table, key)); + GPR_ASSERT(actual != NULL); + GPR_ASSERT(strcmp(actual, input[i].value) == 0); + grpc_slice_unref(key); + } +} + +static void check_non_existent_value(const char* key_string, + grpc_slice_hash_table* table) { + grpc_slice key = grpc_slice_from_static_string(key_string); + GPR_ASSERT(grpc_slice_hash_table_get(table, key) == NULL); + grpc_slice_unref(key); +} + +static void destroy_string(grpc_exec_ctx* exec_ctx, void* value) { + gpr_free(value); +} + +static grpc_slice_hash_table* create_table_from_entries( + const test_entry* test_entries, size_t num_test_entries, + int (*value_cmp_fn)(void*, void*)) { + // Construct table. + grpc_slice_hash_table_entry* entries = + static_cast( + gpr_zalloc(sizeof(*entries) * num_test_entries)); + populate_entries(test_entries, num_test_entries, entries); + grpc_slice_hash_table* table = grpc_slice_hash_table_create( + num_test_entries, entries, destroy_string, value_cmp_fn); + gpr_free(entries); + return table; +} + +static void test_slice_hash_table() { + const test_entry test_entries[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}, + {"key_3", "value_3"}, {"key_4", "value_4"}, {"key_5", "value_5"}, + {"key_6", "value_6"}, {"key_7", "value_7"}, {"key_8", "value_8"}, + {"key_9", "value_9"}, {"key_10", "value_10"}, {"key_11", "value_11"}, + {"key_12", "value_12"}, {"key_13", "value_13"}, {"key_14", "value_14"}, + {"key_15", "value_15"}, {"key_16", "value_16"}, {"key_17", "value_17"}, + {"key_18", "value_18"}, {"key_19", "value_19"}, {"key_20", "value_20"}, + {"key_21", "value_21"}, {"key_22", "value_22"}, {"key_23", "value_23"}, + {"key_24", "value_24"}, {"key_25", "value_25"}, {"key_26", "value_26"}, + {"key_27", "value_27"}, {"key_28", "value_28"}, {"key_29", "value_29"}, + {"key_30", "value_30"}, {"key_31", "value_31"}, {"key_32", "value_32"}, + {"key_33", "value_33"}, {"key_34", "value_34"}, {"key_35", "value_35"}, + {"key_36", "value_36"}, {"key_37", "value_37"}, {"key_38", "value_38"}, + {"key_39", "value_39"}, {"key_40", "value_40"}, {"key_41", "value_41"}, + {"key_42", "value_42"}, {"key_43", "value_43"}, {"key_44", "value_44"}, + {"key_45", "value_45"}, {"key_46", "value_46"}, {"key_47", "value_47"}, + {"key_48", "value_48"}, {"key_49", "value_49"}, {"key_50", "value_50"}, + {"key_51", "value_51"}, {"key_52", "value_52"}, {"key_53", "value_53"}, + {"key_54", "value_54"}, {"key_55", "value_55"}, {"key_56", "value_56"}, + {"key_57", "value_57"}, {"key_58", "value_58"}, {"key_59", "value_59"}, + {"key_60", "value_60"}, {"key_61", "value_61"}, {"key_62", "value_62"}, + {"key_63", "value_63"}, {"key_64", "value_64"}, {"key_65", "value_65"}, + {"key_66", "value_66"}, {"key_67", "value_67"}, {"key_68", "value_68"}, + {"key_69", "value_69"}, {"key_70", "value_70"}, {"key_71", "value_71"}, + {"key_72", "value_72"}, {"key_73", "value_73"}, {"key_74", "value_74"}, + {"key_75", "value_75"}, {"key_76", "value_76"}, {"key_77", "value_77"}, + {"key_78", "value_78"}, {"key_79", "value_79"}, {"key_80", "value_80"}, + {"key_81", "value_81"}, {"key_82", "value_82"}, {"key_83", "value_83"}, + {"key_84", "value_84"}, {"key_85", "value_85"}, {"key_86", "value_86"}, + {"key_87", "value_87"}, {"key_88", "value_88"}, {"key_89", "value_89"}, + {"key_90", "value_90"}, {"key_91", "value_91"}, {"key_92", "value_92"}, + {"key_93", "value_93"}, {"key_94", "value_94"}, {"key_95", "value_95"}, + {"key_96", "value_96"}, {"key_97", "value_97"}, {"key_98", "value_98"}, + {"key_99", "value_99"}, + }; + const size_t num_entries = GPR_ARRAY_SIZE(test_entries); + grpc_slice_hash_table* table = + create_table_from_entries(test_entries, num_entries, NULL); + // Check contents of table. + check_values(test_entries, num_entries, table); + check_non_existent_value("XX", table); + // Clean up. + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_hash_table_unref(&exec_ctx, table); + grpc_exec_ctx_finish(&exec_ctx); +} + +static int value_cmp_fn(void* a, void* b) { + const char* a_str = static_cast(a); + const char* b_str = static_cast(b); + return strcmp(a_str, b_str); +} + +static int pointer_cmp_fn(void* a, void* b) { return GPR_ICMP(a, b); } + +static void test_slice_hash_table_eq() { + const test_entry test_entries_a[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_a = GPR_ARRAY_SIZE(test_entries_a); + grpc_slice_hash_table* table_a = + create_table_from_entries(test_entries_a, num_entries_a, value_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_a) == 0); + + const test_entry test_entries_b[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_b = GPR_ARRAY_SIZE(test_entries_b); + grpc_slice_hash_table* table_b = + create_table_from_entries(test_entries_b, num_entries_b, value_cmp_fn); + + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b) == 0); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_hash_table_unref(&exec_ctx, table_a); + grpc_slice_hash_table_unref(&exec_ctx, table_b); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_slice_hash_table_not_eq() { + const test_entry test_entries_a[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_a = GPR_ARRAY_SIZE(test_entries_a); + grpc_slice_hash_table* table_a = + create_table_from_entries(test_entries_a, num_entries_a, value_cmp_fn); + + // Different sizes. + const test_entry test_entries_b_smaller[] = {{"key_0", "value_0"}, + {"key_1", "value_1"}}; + const size_t num_entries_b_smaller = GPR_ARRAY_SIZE(test_entries_b_smaller); + grpc_slice_hash_table* table_b_smaller = create_table_from_entries( + test_entries_b_smaller, num_entries_b_smaller, value_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b_smaller) > 0); + + const test_entry test_entries_b_larger[] = {{"key_0", "value_0"}, + {"key_1", "value_1"}, + {"key_2", "value_2"}, + {"key_3", "value_3"}}; + const size_t num_entries_b_larger = GPR_ARRAY_SIZE(test_entries_b_larger); + grpc_slice_hash_table* table_b_larger = create_table_from_entries( + test_entries_b_larger, num_entries_b_larger, value_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_b_larger) < 0); + + // One key doesn't match and is lexicographically "smaller". + const test_entry test_entries_c[] = { + {"key_zz", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_c = GPR_ARRAY_SIZE(test_entries_c); + grpc_slice_hash_table* table_c = + create_table_from_entries(test_entries_c, num_entries_c, value_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_c) > 0); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_c, table_a) < 0); + + // One value doesn't match. + const test_entry test_entries_d[] = { + {"key_0", "value_z"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_d = GPR_ARRAY_SIZE(test_entries_d); + grpc_slice_hash_table* table_d = + create_table_from_entries(test_entries_d, num_entries_d, value_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_a, table_d) < 0); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_d, table_a) > 0); + + // Same values but different "equals" functions. + const test_entry test_entries_e[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_e = GPR_ARRAY_SIZE(test_entries_e); + grpc_slice_hash_table* table_e = + create_table_from_entries(test_entries_e, num_entries_e, value_cmp_fn); + const test_entry test_entries_f[] = { + {"key_0", "value_0"}, {"key_1", "value_1"}, {"key_2", "value_2"}}; + const size_t num_entries_f = GPR_ARRAY_SIZE(test_entries_f); + grpc_slice_hash_table* table_f = + create_table_from_entries(test_entries_f, num_entries_f, pointer_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_e, table_f) != 0); + + // Same (empty) key, different values. + const test_entry test_entries_g[] = {{"", "value_0"}}; + const size_t num_entries_g = GPR_ARRAY_SIZE(test_entries_g); + grpc_slice_hash_table* table_g = + create_table_from_entries(test_entries_g, num_entries_g, value_cmp_fn); + const test_entry test_entries_h[] = {{"", "value_1"}}; + const size_t num_entries_h = GPR_ARRAY_SIZE(test_entries_h); + grpc_slice_hash_table* table_h = + create_table_from_entries(test_entries_h, num_entries_h, pointer_cmp_fn); + GPR_ASSERT(grpc_slice_hash_table_cmp(table_g, table_h) != 0); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_hash_table_unref(&exec_ctx, table_a); + grpc_slice_hash_table_unref(&exec_ctx, table_b_larger); + grpc_slice_hash_table_unref(&exec_ctx, table_b_smaller); + grpc_slice_hash_table_unref(&exec_ctx, table_c); + grpc_slice_hash_table_unref(&exec_ctx, table_d); + grpc_slice_hash_table_unref(&exec_ctx, table_e); + grpc_slice_hash_table_unref(&exec_ctx, table_f); + grpc_slice_hash_table_unref(&exec_ctx, table_g); + grpc_slice_hash_table_unref(&exec_ctx, table_h); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + test_slice_hash_table(); + test_slice_hash_table_eq(); + test_slice_hash_table_not_eq(); + return 0; +} diff --git a/test/core/slice/slice_string_helpers_test.c b/test/core/slice/slice_string_helpers_test.c deleted file mode 100644 index 504acf8f84..0000000000 --- a/test/core/slice/slice_string_helpers_test.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/slice/slice_string_helpers.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) - -static void expect_slice_dump(grpc_slice slice, uint32_t flags, - const char *result) { - char *got = grpc_dump_slice(slice, flags); - GPR_ASSERT(0 == strcmp(got, result)); - gpr_free(got); - grpc_slice_unref(slice); -} - -static void test_dump_slice(void) { - static const char *text = "HELLO WORLD!"; - static const char *long_text = - "It was a bright cold day in April, and the clocks were striking " - "thirteen. Winston Smith, his chin nuzzled into his breast in an effort " - "to escape the vile wind, slipped quickly through the glass doors of " - "Victory Mansions, though not quickly enough to prevent a swirl of " - "gritty dust from entering along with him."; - - LOG_TEST_NAME("test_dump_slice"); - - expect_slice_dump(grpc_slice_from_copied_string(text), GPR_DUMP_ASCII, text); - expect_slice_dump(grpc_slice_from_copied_string(long_text), GPR_DUMP_ASCII, - long_text); - expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX, - "01"); - expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), - GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); -} - -static void test_strsplit(void) { - grpc_slice_buffer *parts; - grpc_slice str; - - LOG_TEST_NAME("test_strsplit"); - - parts = gpr_malloc(sizeof(grpc_slice_buffer)); - grpc_slice_buffer_init(parts); - - str = grpc_slice_from_copied_string("one, two, three, four"); - grpc_slice_split(str, ", ", parts); - GPR_ASSERT(4 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - /* separator not present in string */ - str = grpc_slice_from_copied_string("one two three four"); - grpc_slice_split(str, ", ", parts); - GPR_ASSERT(1 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - /* separator at the end */ - str = grpc_slice_from_copied_string("foo,"); - grpc_slice_split(str, ",", parts); - GPR_ASSERT(2 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - /* separator at the beginning */ - str = grpc_slice_from_copied_string(",foo"); - grpc_slice_split(str, ",", parts); - GPR_ASSERT(2 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - /* standalone separator */ - str = grpc_slice_from_copied_string(","); - grpc_slice_split(str, ",", parts); - GPR_ASSERT(2 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - /* empty input */ - str = grpc_slice_from_copied_string(""); - grpc_slice_split(str, ", ", parts); - GPR_ASSERT(1 == parts->count); - GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); - grpc_slice_buffer_reset_and_unref(parts); - grpc_slice_unref(str); - - grpc_slice_buffer_destroy(parts); - gpr_free(parts); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_dump_slice(); - test_strsplit(); - return 0; -} diff --git a/test/core/slice/slice_string_helpers_test.cc b/test/core/slice/slice_string_helpers_test.cc new file mode 100644 index 0000000000..8877da73f5 --- /dev/null +++ b/test/core/slice/slice_string_helpers_test.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/slice/slice_string_helpers.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) + +static void expect_slice_dump(grpc_slice slice, uint32_t flags, + const char *result) { + char *got = grpc_dump_slice(slice, flags); + GPR_ASSERT(0 == strcmp(got, result)); + gpr_free(got); + grpc_slice_unref(slice); +} + +static void test_dump_slice(void) { + static const char *text = "HELLO WORLD!"; + static const char *long_text = + "It was a bright cold day in April, and the clocks were striking " + "thirteen. Winston Smith, his chin nuzzled into his breast in an effort " + "to escape the vile wind, slipped quickly through the glass doors of " + "Victory Mansions, though not quickly enough to prevent a swirl of " + "gritty dust from entering along with him."; + + LOG_TEST_NAME("test_dump_slice"); + + expect_slice_dump(grpc_slice_from_copied_string(text), GPR_DUMP_ASCII, text); + expect_slice_dump(grpc_slice_from_copied_string(long_text), GPR_DUMP_ASCII, + long_text); + expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX, + "01"); + expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), + GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); +} + +static void test_strsplit(void) { + grpc_slice_buffer *parts; + grpc_slice str; + + LOG_TEST_NAME("test_strsplit"); + + parts = + static_cast(gpr_malloc(sizeof(grpc_slice_buffer))); + grpc_slice_buffer_init(parts); + + str = grpc_slice_from_copied_string("one, two, three, four"); + grpc_slice_split(str, ", ", parts); + GPR_ASSERT(4 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator not present in string */ + str = grpc_slice_from_copied_string("one two three four"); + grpc_slice_split(str, ", ", parts); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator at the end */ + str = grpc_slice_from_copied_string("foo,"); + grpc_slice_split(str, ",", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator at the beginning */ + str = grpc_slice_from_copied_string(",foo"); + grpc_slice_split(str, ",", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* standalone separator */ + str = grpc_slice_from_copied_string(","); + grpc_slice_split(str, ",", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* empty input */ + str = grpc_slice_from_copied_string(""); + grpc_slice_split(str, ", ", parts); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + grpc_slice_buffer_destroy(parts); + gpr_free(parts); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_dump_slice(); + test_strsplit(); + return 0; +} diff --git a/test/core/slice/slice_test.c b/test/core/slice/slice_test.c deleted file mode 100644 index cda37fb8d9..0000000000 --- a/test/core/slice/slice_test.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/transport/static_metadata.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x); - -static void test_slice_malloc_returns_something_sensible(void) { - /* Calls grpc_slice_create for various lengths and verifies the internals for - consistency. */ - size_t length; - size_t i; - grpc_slice slice; - - LOG_TEST_NAME("test_slice_malloc_returns_something_sensible"); - - for (length = 0; length <= 1024; length++) { - slice = grpc_slice_malloc(length); - /* If there is a length, slice.data must be non-NULL. If length is zero - we don't care. */ - if (length) { - GPR_ASSERT(GRPC_SLICE_START_PTR(slice)); - } - /* Returned slice length must be what was requested. */ - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == length); - /* If the slice has a refcount, it must be destroyable. */ - if (slice.refcount) { - GPR_ASSERT(slice.refcount->vtable != NULL); - GPR_ASSERT(slice.refcount->vtable->ref != NULL); - GPR_ASSERT(slice.refcount->vtable->unref != NULL); - GPR_ASSERT(slice.refcount->vtable->hash != NULL); - } - /* We must be able to write to every byte of the data */ - for (i = 0; i < length; i++) { - GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; - } - /* And finally we must succeed in destroying the slice */ - grpc_slice_unref(slice); - } -} - -static void do_nothing(void *ignored) {} - -static void test_slice_new_returns_something_sensible(void) { - uint8_t x; - - grpc_slice slice = grpc_slice_new(&x, 1, do_nothing); - GPR_ASSERT(slice.refcount); - GPR_ASSERT(slice.data.refcounted.bytes == &x); - GPR_ASSERT(slice.data.refcounted.length == 1); - grpc_slice_unref(slice); -} - -/* destroy function that sets a mark to indicate it was called. */ -static void set_mark(void *p) { *((int *)p) = 1; } - -static void test_slice_new_with_user_data(void) { - int marker = 0; - uint8_t buf[2]; - grpc_slice slice; - - buf[0] = 0; - buf[1] = 1; - slice = grpc_slice_new_with_user_data(buf, 2, set_mark, &marker); - GPR_ASSERT(marker == 0); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 2); - GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[0] == 0); - GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[1] == 1); - - /* unref should cause destroy function to run. */ - grpc_slice_unref(slice); - GPR_ASSERT(marker == 1); -} - -static int do_nothing_with_len_1_calls = 0; - -static void do_nothing_with_len_1(void *ignored, size_t len) { - GPR_ASSERT(len == 1); - do_nothing_with_len_1_calls++; -} - -static void test_slice_new_with_len_returns_something_sensible(void) { - uint8_t x; - int num_refs = 5; /* To test adding/removing an arbitrary number of refs */ - int i; - - grpc_slice slice = grpc_slice_new_with_len(&x, 1, do_nothing_with_len_1); - 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++) { - grpc_slice_ref(slice); - } - for (i = 0; i < num_refs; i++) { - grpc_slice_unref(slice); - } - GPR_ASSERT(do_nothing_with_len_1_calls == 0); /* Shouldn't be called yet */ - - /* last unref */ - grpc_slice_unref(slice); - GPR_ASSERT(do_nothing_with_len_1_calls == 1); -} - -static void test_slice_sub_works(unsigned length) { - grpc_slice slice; - grpc_slice sub; - unsigned i, j, k; - - LOG_TEST_NAME("test_slice_sub_works"); - gpr_log(GPR_INFO, "length=%d", length); - - /* Create a slice in which each byte is equal to the distance from it to the - beginning of the slice. */ - slice = grpc_slice_malloc(length); - for (i = 0; i < length; i++) { - GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; - } - - /* Ensure that for all subsets length is correct and that we start on the - correct byte. Additionally check that no copies were made. */ - for (i = 0; i < length; i++) { - for (j = i; j < length; j++) { - sub = grpc_slice_sub(slice, i, j); - GPR_ASSERT(GRPC_SLICE_LENGTH(sub) == j - i); - for (k = 0; k < j - i; k++) { - GPR_ASSERT(GRPC_SLICE_START_PTR(sub)[k] == (uint8_t)(i + k)); - } - grpc_slice_unref(sub); - } - } - grpc_slice_unref(slice); -} - -static void check_head_tail(grpc_slice slice, grpc_slice head, - grpc_slice tail) { - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == - GRPC_SLICE_LENGTH(head) + GRPC_SLICE_LENGTH(tail)); - GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice), - GRPC_SLICE_START_PTR(head), GRPC_SLICE_LENGTH(head))); - GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(head), - GRPC_SLICE_START_PTR(tail), GRPC_SLICE_LENGTH(tail))); -} - -static void test_slice_split_head_works(size_t length) { - grpc_slice slice; - grpc_slice head, tail; - size_t i; - - LOG_TEST_NAME("test_slice_split_head_works"); - gpr_log(GPR_INFO, "length=%" PRIuPTR, length); - - /* Create a slice in which each byte is equal to the distance from it to the - beginning of the slice. */ - slice = grpc_slice_malloc(length); - for (i = 0; i < length; i++) { - GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; - } - - /* Ensure that for all subsets length is correct and that we start on the - correct byte. Additionally check that no copies were made. */ - for (i = 0; i < length; i++) { - tail = grpc_slice_ref(slice); - head = grpc_slice_split_head(&tail, i); - check_head_tail(slice, head, tail); - grpc_slice_unref(tail); - grpc_slice_unref(head); - } - - grpc_slice_unref(slice); -} - -static void test_slice_split_tail_works(size_t length) { - grpc_slice slice; - grpc_slice head, tail; - size_t i; - - LOG_TEST_NAME("test_slice_split_tail_works"); - gpr_log(GPR_INFO, "length=%" PRIuPTR, length); - - /* Create a slice in which each byte is equal to the distance from it to the - beginning of the slice. */ - slice = grpc_slice_malloc(length); - for (i = 0; i < length; i++) { - GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; - } - - /* Ensure that for all subsets length is correct and that we start on the - correct byte. Additionally check that no copies were made. */ - for (i = 0; i < length; i++) { - head = grpc_slice_ref(slice); - tail = grpc_slice_split_tail(&head, i); - check_head_tail(slice, head, tail); - grpc_slice_unref(tail); - grpc_slice_unref(head); - } - - grpc_slice_unref(slice); -} - -static void test_slice_from_copied_string_works(void) { - static const char *text = "HELLO WORLD!"; - grpc_slice slice; - - LOG_TEST_NAME("test_slice_from_copied_string_works"); - - slice = grpc_slice_from_copied_string(text); - GPR_ASSERT(strlen(text) == GRPC_SLICE_LENGTH(slice)); - GPR_ASSERT( - 0 == memcmp(text, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))); - grpc_slice_unref(slice); -} - -static void test_slice_interning(void) { - LOG_TEST_NAME("test_slice_interning"); - - grpc_init(); - grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789"); - grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789"); - GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2)); - grpc_slice interned1 = grpc_slice_intern(src1); - grpc_slice interned2 = grpc_slice_intern(src2); - GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) == - GRPC_SLICE_START_PTR(interned2)); - GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1)); - GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2)); - grpc_slice_unref(src1); - grpc_slice_unref(src2); - grpc_slice_unref(interned1); - grpc_slice_unref(interned2); - grpc_shutdown(); -} - -static void test_static_slice_interning(void) { - LOG_TEST_NAME("test_static_slice_interning"); - - // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary - // to intern a static slice - - for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { - GPR_ASSERT(grpc_slice_is_equivalent( - grpc_static_slice_table[i], - grpc_slice_intern(grpc_static_slice_table[i]))); - } -} - -static void test_static_slice_copy_interning(void) { - LOG_TEST_NAME("test_static_slice_copy_interning"); - - grpc_init(); - - for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { - grpc_slice copy = grpc_slice_dup(grpc_static_slice_table[i]); - GPR_ASSERT(grpc_static_slice_table[i].refcount != copy.refcount); - GPR_ASSERT(grpc_static_slice_table[i].refcount == - grpc_slice_intern(copy).refcount); - grpc_slice_unref(copy); - } - - grpc_shutdown(); -} - -int main(int argc, char **argv) { - unsigned length; - grpc_test_init(argc, argv); - test_slice_malloc_returns_something_sensible(); - test_slice_new_returns_something_sensible(); - test_slice_new_with_user_data(); - test_slice_new_with_len_returns_something_sensible(); - for (length = 0; length < 128; length++) { - test_slice_sub_works(length); - test_slice_split_head_works(length); - test_slice_split_tail_works(length); - } - test_slice_from_copied_string_works(); - test_slice_interning(); - test_static_slice_interning(); - test_static_slice_copy_interning(); - return 0; -} diff --git a/test/core/slice/slice_test.cc b/test/core/slice/slice_test.cc new file mode 100644 index 0000000000..cda37fb8d9 --- /dev/null +++ b/test/core/slice/slice_test.cc @@ -0,0 +1,309 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x); + +static void test_slice_malloc_returns_something_sensible(void) { + /* Calls grpc_slice_create for various lengths and verifies the internals for + consistency. */ + size_t length; + size_t i; + grpc_slice slice; + + LOG_TEST_NAME("test_slice_malloc_returns_something_sensible"); + + for (length = 0; length <= 1024; length++) { + slice = grpc_slice_malloc(length); + /* If there is a length, slice.data must be non-NULL. If length is zero + we don't care. */ + if (length) { + GPR_ASSERT(GRPC_SLICE_START_PTR(slice)); + } + /* Returned slice length must be what was requested. */ + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == length); + /* If the slice has a refcount, it must be destroyable. */ + if (slice.refcount) { + GPR_ASSERT(slice.refcount->vtable != NULL); + GPR_ASSERT(slice.refcount->vtable->ref != NULL); + GPR_ASSERT(slice.refcount->vtable->unref != NULL); + GPR_ASSERT(slice.refcount->vtable->hash != NULL); + } + /* We must be able to write to every byte of the data */ + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + /* And finally we must succeed in destroying the slice */ + grpc_slice_unref(slice); + } +} + +static void do_nothing(void *ignored) {} + +static void test_slice_new_returns_something_sensible(void) { + uint8_t x; + + grpc_slice slice = grpc_slice_new(&x, 1, do_nothing); + GPR_ASSERT(slice.refcount); + GPR_ASSERT(slice.data.refcounted.bytes == &x); + GPR_ASSERT(slice.data.refcounted.length == 1); + grpc_slice_unref(slice); +} + +/* destroy function that sets a mark to indicate it was called. */ +static void set_mark(void *p) { *((int *)p) = 1; } + +static void test_slice_new_with_user_data(void) { + int marker = 0; + uint8_t buf[2]; + grpc_slice slice; + + buf[0] = 0; + buf[1] = 1; + slice = grpc_slice_new_with_user_data(buf, 2, set_mark, &marker); + GPR_ASSERT(marker == 0); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == 2); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[0] == 0); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice)[1] == 1); + + /* unref should cause destroy function to run. */ + grpc_slice_unref(slice); + GPR_ASSERT(marker == 1); +} + +static int do_nothing_with_len_1_calls = 0; + +static void do_nothing_with_len_1(void *ignored, size_t len) { + GPR_ASSERT(len == 1); + do_nothing_with_len_1_calls++; +} + +static void test_slice_new_with_len_returns_something_sensible(void) { + uint8_t x; + int num_refs = 5; /* To test adding/removing an arbitrary number of refs */ + int i; + + grpc_slice slice = grpc_slice_new_with_len(&x, 1, do_nothing_with_len_1); + 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++) { + grpc_slice_ref(slice); + } + for (i = 0; i < num_refs; i++) { + grpc_slice_unref(slice); + } + GPR_ASSERT(do_nothing_with_len_1_calls == 0); /* Shouldn't be called yet */ + + /* last unref */ + grpc_slice_unref(slice); + GPR_ASSERT(do_nothing_with_len_1_calls == 1); +} + +static void test_slice_sub_works(unsigned length) { + grpc_slice slice; + grpc_slice sub; + unsigned i, j, k; + + LOG_TEST_NAME("test_slice_sub_works"); + gpr_log(GPR_INFO, "length=%d", length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + for (j = i; j < length; j++) { + sub = grpc_slice_sub(slice, i, j); + GPR_ASSERT(GRPC_SLICE_LENGTH(sub) == j - i); + for (k = 0; k < j - i; k++) { + GPR_ASSERT(GRPC_SLICE_START_PTR(sub)[k] == (uint8_t)(i + k)); + } + grpc_slice_unref(sub); + } + } + grpc_slice_unref(slice); +} + +static void check_head_tail(grpc_slice slice, grpc_slice head, + grpc_slice tail) { + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == + GRPC_SLICE_LENGTH(head) + GRPC_SLICE_LENGTH(tail)); + GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice), + GRPC_SLICE_START_PTR(head), GRPC_SLICE_LENGTH(head))); + GPR_ASSERT(0 == memcmp(GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(head), + GRPC_SLICE_START_PTR(tail), GRPC_SLICE_LENGTH(tail))); +} + +static void test_slice_split_head_works(size_t length) { + grpc_slice slice; + grpc_slice head, tail; + size_t i; + + LOG_TEST_NAME("test_slice_split_head_works"); + gpr_log(GPR_INFO, "length=%" PRIuPTR, length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + tail = grpc_slice_ref(slice); + head = grpc_slice_split_head(&tail, i); + check_head_tail(slice, head, tail); + grpc_slice_unref(tail); + grpc_slice_unref(head); + } + + grpc_slice_unref(slice); +} + +static void test_slice_split_tail_works(size_t length) { + grpc_slice slice; + grpc_slice head, tail; + size_t i; + + LOG_TEST_NAME("test_slice_split_tail_works"); + gpr_log(GPR_INFO, "length=%" PRIuPTR, length); + + /* Create a slice in which each byte is equal to the distance from it to the + beginning of the slice. */ + slice = grpc_slice_malloc(length); + for (i = 0; i < length; i++) { + GRPC_SLICE_START_PTR(slice)[i] = (uint8_t)i; + } + + /* Ensure that for all subsets length is correct and that we start on the + correct byte. Additionally check that no copies were made. */ + for (i = 0; i < length; i++) { + head = grpc_slice_ref(slice); + tail = grpc_slice_split_tail(&head, i); + check_head_tail(slice, head, tail); + grpc_slice_unref(tail); + grpc_slice_unref(head); + } + + grpc_slice_unref(slice); +} + +static void test_slice_from_copied_string_works(void) { + static const char *text = "HELLO WORLD!"; + grpc_slice slice; + + LOG_TEST_NAME("test_slice_from_copied_string_works"); + + slice = grpc_slice_from_copied_string(text); + GPR_ASSERT(strlen(text) == GRPC_SLICE_LENGTH(slice)); + GPR_ASSERT( + 0 == memcmp(text, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))); + grpc_slice_unref(slice); +} + +static void test_slice_interning(void) { + LOG_TEST_NAME("test_slice_interning"); + + grpc_init(); + grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789"); + grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789"); + GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2)); + grpc_slice interned1 = grpc_slice_intern(src1); + grpc_slice interned2 = grpc_slice_intern(src2); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) == + GRPC_SLICE_START_PTR(interned2)); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1)); + GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2)); + grpc_slice_unref(src1); + grpc_slice_unref(src2); + grpc_slice_unref(interned1); + grpc_slice_unref(interned2); + grpc_shutdown(); +} + +static void test_static_slice_interning(void) { + LOG_TEST_NAME("test_static_slice_interning"); + + // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary + // to intern a static slice + + for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { + GPR_ASSERT(grpc_slice_is_equivalent( + grpc_static_slice_table[i], + grpc_slice_intern(grpc_static_slice_table[i]))); + } +} + +static void test_static_slice_copy_interning(void) { + LOG_TEST_NAME("test_static_slice_copy_interning"); + + grpc_init(); + + for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { + grpc_slice copy = grpc_slice_dup(grpc_static_slice_table[i]); + GPR_ASSERT(grpc_static_slice_table[i].refcount != copy.refcount); + GPR_ASSERT(grpc_static_slice_table[i].refcount == + grpc_slice_intern(copy).refcount); + grpc_slice_unref(copy); + } + + grpc_shutdown(); +} + +int main(int argc, char **argv) { + unsigned length; + grpc_test_init(argc, argv); + test_slice_malloc_returns_something_sensible(); + test_slice_new_returns_something_sensible(); + test_slice_new_with_user_data(); + test_slice_new_with_len_returns_something_sensible(); + for (length = 0; length < 128; length++) { + test_slice_sub_works(length); + test_slice_split_head_works(length); + test_slice_split_tail_works(length); + } + test_slice_from_copied_string_works(); + test_slice_interning(); + test_static_slice_interning(); + test_static_slice_copy_interning(); + return 0; +} diff --git a/test/core/statistics/census_log_tests.c b/test/core/statistics/census_log_tests.c deleted file mode 100644 index 229a5e55f9..0000000000 --- a/test/core/statistics/census_log_tests.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/census_log.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -/* Fills in 'record' of size 'size'. Each byte in record is filled in with the - same value. The value is extracted from 'record' pointer. */ -static void write_record(char *record, size_t size) { - char data = (uintptr_t)record % 255; - memset(record, data, size); -} - -/* Reads fixed size records. Returns the number of records read in - 'num_records'. */ -static void read_records(size_t record_size, const char *buffer, - size_t buffer_size, int32_t *num_records) { - int32_t ix; - GPR_ASSERT(buffer_size >= record_size); - GPR_ASSERT(buffer_size % record_size == 0); - *num_records = buffer_size / record_size; - for (ix = 0; ix < *num_records; ++ix) { - size_t jx; - const char *record = buffer + (record_size * ix); - char data = (uintptr_t)record % 255; - for (jx = 0; jx < record_size; ++jx) { - GPR_ASSERT(data == record[jx]); - } - } -} - -/* Tries to write the specified number of records. Stops when the log gets - full. Returns the number of records written. Spins for random - number of times, up to 'max_spin_count', between writes. */ -static size_t write_records_to_log(int writer_id, int32_t record_size, - int32_t num_records, - int32_t max_spin_count) { - int32_t ix; - int counter = 0; - for (ix = 0; ix < num_records; ++ix) { - int32_t jx; - int32_t spin_count = max_spin_count ? rand() % max_spin_count : 0; - char *record; - if (counter++ == num_records / 10) { - printf(" Writer %d: %d out of %d written\n", writer_id, ix, - num_records); - counter = 0; - } - record = (char *)(census_log_start_write(record_size)); - if (record == NULL) { - return ix; - } - write_record(record, record_size); - census_log_end_write(record, record_size); - for (jx = 0; jx < spin_count; ++jx) { - GPR_ASSERT(jx >= 0); - } - } - return num_records; -} - -/* Performs a single read iteration. Returns the number of records read. */ -static size_t perform_read_iteration(size_t record_size) { - const void *read_buffer = NULL; - size_t bytes_available; - size_t records_read = 0; - census_log_init_reader(); - while ((read_buffer = census_log_read_next(&bytes_available))) { - int32_t num_records = 0; - read_records(record_size, (const char *)read_buffer, bytes_available, - &num_records); - records_read += num_records; - } - return records_read; -} - -/* Asserts that the log is empty. */ -static void assert_log_empty(void) { - size_t bytes_available; - census_log_init_reader(); - GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); -} - -/* Given log size and record size, computes the minimum usable space. */ -static int32_t min_usable_space(size_t log_size, size_t record_size) { - int32_t usable_space; - int32_t num_blocks = - GPR_MAX(log_size / CENSUS_LOG_MAX_RECORD_SIZE, gpr_cpu_num_cores()); - int32_t waste_per_block = CENSUS_LOG_MAX_RECORD_SIZE % record_size; - /* In the worst case, all except one core-local block is full. */ - int32_t num_full_blocks = num_blocks - 1; - usable_space = (int32_t)log_size - - (num_full_blocks * CENSUS_LOG_MAX_RECORD_SIZE) - - ((num_blocks - num_full_blocks) * waste_per_block); - GPR_ASSERT(usable_space > 0); - return usable_space; -} - -/* Fills the log and verifies data. If 'no fragmentation' is true, records - are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record - size. If not a circular log, verifies that the number of records written - match the number of records read. */ -static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { - int size; - int32_t records_written; - int32_t usable_space; - int32_t records_read; - if (no_fragmentation) { - int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); - size = (1 << log2size); - } else { - while (1) { - size = 1 + (rand() % CENSUS_LOG_MAX_RECORD_SIZE); - if (CENSUS_LOG_MAX_RECORD_SIZE % size) { - break; - } - } - } - printf(" Fill record size: %d\n", size); - records_written = write_records_to_log( - 0 /* writer id */, size, (log_size / size) * 2, 0 /* spin count */); - usable_space = min_usable_space(log_size, size); - GPR_ASSERT(records_written * size >= usable_space); - records_read = perform_read_iteration(size); - if (!circular_log) { - GPR_ASSERT(records_written == records_read); - } - assert_log_empty(); -} - -/* Structure to pass args to writer_thread */ -typedef struct writer_thread_args { - /* Index of this thread in the writers vector. */ - int index; - /* Record size. */ - size_t record_size; - /* Number of records to write. */ - int32_t num_records; - /* Used to signal when writer is complete */ - gpr_cv *done; - gpr_mu *mu; - int *count; -} writer_thread_args; - -/* Writes the given number of records of random size (up to kMaxRecordSize) and - random data to the specified log. */ -static void writer_thread(void *arg) { - writer_thread_args *args = (writer_thread_args *)arg; - /* Maximum number of times to spin between writes. */ - static const int32_t MAX_SPIN_COUNT = 50; - int records_written = 0; - printf(" Writer: %d\n", args->index); - while (records_written < args->num_records) { - records_written += write_records_to_log(args->index, args->record_size, - args->num_records - records_written, - MAX_SPIN_COUNT); - if (records_written < args->num_records) { - /* Ran out of log space. Sleep for a bit and let the reader catch up. - This should never happen for circular logs. */ - printf(" Writer stalled due to out-of-space: %d out of %d written\n", - records_written, args->num_records); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); - } - } - /* Done. Decrement count and signal. */ - gpr_mu_lock(args->mu); - (*args->count)--; - gpr_cv_broadcast(args->done); - printf(" Writer done: %d\n", args->index); - gpr_mu_unlock(args->mu); -} - -/* struct to pass args to reader_thread */ -typedef struct reader_thread_args { - /* Record size. */ - size_t record_size; - /* Interval between read iterations. */ - int32_t read_iteration_interval_in_msec; - /* Total number of records. */ - int32_t total_records; - /* Signalled when reader should stop. */ - gpr_cv stop; - int stop_flag; - /* Used to signal when reader has finished */ - gpr_cv *done; - gpr_mu *mu; - int running; -} reader_thread_args; - -/* Reads and verifies the specified number of records. Reader can also be - stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' - between read iterations. */ -static void reader_thread(void *arg) { - int32_t records_read = 0; - reader_thread_args *args = (reader_thread_args *)arg; - int32_t num_iterations = 0; - gpr_timespec interval; - int counter = 0; - printf(" Reader starting\n"); - interval = gpr_time_from_micros( - (int64_t)args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); - gpr_mu_lock(args->mu); - while (!args->stop_flag && records_read < args->total_records) { - gpr_cv_wait(&args->stop, args->mu, interval); - if (!args->stop_flag) { - records_read += perform_read_iteration(args->record_size); - GPR_ASSERT(records_read <= args->total_records); - if (counter++ == 100000) { - printf(" Reader: %d out of %d read\n", records_read, - args->total_records); - counter = 0; - } - ++num_iterations; - } - } - /* Done */ - args->running = 0; - gpr_cv_broadcast(args->done); - printf(" Reader: records: %d, iterations: %d\n", records_read, - num_iterations); - gpr_mu_unlock(args->mu); -} - -/* Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER - records. Also, starts a reader that iterates over and reads blocks every - READ_ITERATION_INTERVAL_IN_MSEC. */ -/* Number of writers. */ -#define NUM_WRITERS 5 -static void multiple_writers_single_reader(int circular_log) { - /* Sleep interval between read iterations. */ - static const int32_t READ_ITERATION_INTERVAL_IN_MSEC = 10; - /* Number of records written by each writer. */ - static const int32_t NUM_RECORDS_PER_WRITER = 10 * 1024 * 1024; - /* Maximum record size. */ - static const size_t MAX_RECORD_SIZE = 10; - int ix; - gpr_thd_id id; - gpr_cv writers_done; - int writers_count = NUM_WRITERS; - gpr_mu writers_mu; /* protects writers_done and writers_count */ - writer_thread_args writers[NUM_WRITERS]; - gpr_cv reader_done; - gpr_mu reader_mu; /* protects reader_done and reader.running */ - reader_thread_args reader; - int32_t record_size = 1 + rand() % MAX_RECORD_SIZE; - printf(" Record size: %d\n", record_size); - /* Create and start writers. */ - gpr_cv_init(&writers_done); - gpr_mu_init(&writers_mu); - for (ix = 0; ix < NUM_WRITERS; ++ix) { - writers[ix].index = ix; - writers[ix].record_size = record_size; - writers[ix].num_records = NUM_RECORDS_PER_WRITER; - writers[ix].done = &writers_done; - writers[ix].count = &writers_count; - writers[ix].mu = &writers_mu; - gpr_thd_new(&id, &writer_thread, &writers[ix], NULL); - } - /* Start reader. */ - reader.record_size = record_size; - reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; - reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; - reader.stop_flag = 0; - gpr_cv_init(&reader.stop); - gpr_cv_init(&reader_done); - reader.done = &reader_done; - gpr_mu_init(&reader_mu); - reader.mu = &reader_mu; - reader.running = 1; - gpr_thd_new(&id, &reader_thread, &reader, NULL); - /* Wait for writers to finish. */ - gpr_mu_lock(&writers_mu); - while (writers_count != 0) { - gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&writers_mu); - gpr_mu_destroy(&writers_mu); - gpr_cv_destroy(&writers_done); - gpr_mu_lock(&reader_mu); - if (circular_log) { - /* Stop reader. */ - reader.stop_flag = 1; - gpr_cv_signal(&reader.stop); - } - /* wait for reader to finish */ - while (reader.running) { - gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - if (circular_log) { - /* Assert that there were no out-of-space errors. */ - GPR_ASSERT(0 == census_log_out_of_space_count()); - } - gpr_mu_unlock(&reader_mu); - gpr_mu_destroy(&reader_mu); - gpr_cv_destroy(&reader_done); - printf(" Reader: finished\n"); -} - -/* Log sizes to use for all tests. */ -#define LOG_SIZE_IN_MB 1 -#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) - -static void setup_test(int circular_log) { - census_log_initialize(LOG_SIZE_IN_MB, circular_log); - GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); -} - -/* Attempts to create a record of invalid size (size > - CENSUS_LOG_MAX_RECORD_SIZE). */ -void test_invalid_record_size(void) { - static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; - static const size_t VALID_SIZE = 1; - void *record; - printf("Starting test: invalid record size\n"); - setup_test(0); - record = census_log_start_write(INVALID_SIZE); - GPR_ASSERT(record == NULL); - /* Now try writing a valid record. */ - record = census_log_start_write(VALID_SIZE); - GPR_ASSERT(record != NULL); - census_log_end_write(record, VALID_SIZE); - /* Verifies that available space went down by one block. In theory, this - check can fail if the thread is context switched to a new CPU during the - start_write execution (multiple blocks get allocated), but this has not - been observed in practice. */ - GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == - census_log_remaining_space()); - census_log_shutdown(); -} - -/* Tests end_write() with a different size than what was specified in - start_write(). */ -void test_end_write_with_different_size(void) { - static const size_t START_WRITE_SIZE = 10; - static const size_t END_WRITE_SIZE = 7; - void *record_written; - const void *record_read; - size_t bytes_available; - printf("Starting test: end write with different size\n"); - setup_test(0); - record_written = census_log_start_write(START_WRITE_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, END_WRITE_SIZE); - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(END_WRITE_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -/* Verifies that pending records are not available via read_next(). */ -void test_read_pending_record(void) { - static const size_t PR_RECORD_SIZE = 1024; - size_t bytes_available; - const void *record_read; - void *record_written; - printf("Starting test: read pending record\n"); - setup_test(0); - /* Start a write. */ - record_written = census_log_start_write(PR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - /* As write is pending, read should fail. */ - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - /* A read followed by end_write() should succeed. */ - census_log_end_write(record_written, PR_RECORD_SIZE); - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_written == record_read); - GPR_ASSERT(PR_RECORD_SIZE == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -/* Tries reading beyond pending write. */ -void test_read_beyond_pending_record(void) { - /* Start a write. */ - uint32_t incomplete_record_size = 10; - uint32_t complete_record_size = 20; - size_t bytes_available; - void *complete_record; - const void *record_read; - void *incomplete_record; - printf("Starting test: read beyond pending record\n"); - setup_test(0); - incomplete_record = census_log_start_write(incomplete_record_size); - GPR_ASSERT(incomplete_record != NULL); - complete_record = census_log_start_write(complete_record_size); - GPR_ASSERT(complete_record != NULL); - GPR_ASSERT(complete_record != incomplete_record); - census_log_end_write(complete_record, complete_record_size); - /* Now iterate over blocks to read completed records. */ - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(complete_record == record_read); - GPR_ASSERT(complete_record_size == bytes_available); - /* Complete first record. */ - census_log_end_write(incomplete_record, incomplete_record_size); - /* Have read past the incomplete record, so read_next() should return NULL. */ - /* NB: this test also assumes our thread did not get switched to a different - CPU between the two start_write calls */ - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read == NULL); - /* Reset reader to get the newly completed record. */ - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(incomplete_record == record_read); - GPR_ASSERT(incomplete_record_size == bytes_available); - assert_log_empty(); - census_log_shutdown(); -} - -/* Tests scenario where block being read is detached from a core and put on the - dirty list. */ -void test_detached_while_reading(void) { - static const size_t DWR_RECORD_SIZE = 10; - size_t bytes_available; - const void *record_read; - void *record_written; - uint32_t block_read = 0; - printf("Starting test: detached while reading\n"); - setup_test(0); - /* Start a write. */ - record_written = census_log_start_write(DWR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, DWR_RECORD_SIZE); - /* Read this record. */ - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read != NULL); - GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); - /* Now fill the log. This will move the block being read from core-local - array to the dirty list. */ - while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { - census_log_end_write(record_written, DWR_RECORD_SIZE); - } - - /* In this iteration, read_next() should only traverse blocks in the - core-local array. Therefore, we expect at most gpr_cpu_num_cores() more - blocks. As log is full, if read_next() is traversing the dirty list, we - will get more than gpr_cpu_num_cores() blocks. */ - while ((record_read = census_log_read_next(&bytes_available))) { - ++block_read; - GPR_ASSERT(block_read <= gpr_cpu_num_cores()); - } - census_log_shutdown(); -} - -/* Fills non-circular log with records sized such that size is a multiple of - CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ -void test_fill_log_no_fragmentation(void) { - const int circular = 0; - printf("Starting test: fill log no fragmentation\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -/* Fills circular log with records sized such that size is a multiple of - CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ -void test_fill_circular_log_no_fragmentation(void) { - const int circular = 1; - printf("Starting test: fill circular log no fragmentation\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -/* Fills non-circular log with records that may straddle end of a block. */ -void test_fill_log_with_straddling_records(void) { - const int circular = 0; - printf("Starting test: fill log with straddling records\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -/* Fills circular log with records that may straddle end of a block. */ -void test_fill_circular_log_with_straddling_records(void) { - const int circular = 1; - printf("Starting test: fill circular log with straddling records\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -/* Tests scenario where multiple writers and a single reader are using a log - that is configured to discard old records. */ -void test_multiple_writers_circular_log(void) { - const int circular = 1; - printf("Starting test: multiple writers circular log\n"); - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -/* Tests scenario where multiple writers and a single reader are using a log - that is configured to discard old records. */ -void test_multiple_writers(void) { - const int circular = 0; - printf("Starting test: multiple writers\n"); - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -/* Repeat the straddling records and multiple writers tests with a small log. */ -void test_small_log(void) { - size_t log_size; - const int circular = 0; - printf("Starting test: small log\n"); - census_log_initialize(0, circular); - log_size = census_log_remaining_space(); - GPR_ASSERT(log_size > 0); - fill_log(log_size, 0, circular); - census_log_shutdown(); - census_log_initialize(0, circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -void test_performance(void) { - int write_size = 1; - for (; write_size < CENSUS_LOG_MAX_RECORD_SIZE; write_size *= 2) { - gpr_timespec write_time; - gpr_timespec start_time; - double write_time_micro = 0.0; - int nrecords = 0; - setup_test(0); - start_time = gpr_now(GPR_CLOCK_REALTIME); - while (1) { - void *record = census_log_start_write(write_size); - if (record == NULL) { - break; - } - census_log_end_write(record, write_size); - nrecords++; - } - write_time = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); - write_time_micro = write_time.tv_sec * 1000000 + write_time.tv_nsec / 1000; - census_log_shutdown(); - printf( - "Wrote %d %d byte records in %.3g microseconds: %g records/us " - "(%g ns/record), %g gigabytes/s\n", - nrecords, write_size, write_time_micro, nrecords / write_time_micro, - 1000 * write_time_micro / nrecords, - (write_size * nrecords) / write_time_micro / 1000); - } -} diff --git a/test/core/statistics/census_log_tests.cc b/test/core/statistics/census_log_tests.cc new file mode 100644 index 0000000000..229a5e55f9 --- /dev/null +++ b/test/core/statistics/census_log_tests.cc @@ -0,0 +1,576 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/census/census_log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* Fills in 'record' of size 'size'. Each byte in record is filled in with the + same value. The value is extracted from 'record' pointer. */ +static void write_record(char *record, size_t size) { + char data = (uintptr_t)record % 255; + memset(record, data, size); +} + +/* Reads fixed size records. Returns the number of records read in + 'num_records'. */ +static void read_records(size_t record_size, const char *buffer, + size_t buffer_size, int32_t *num_records) { + int32_t ix; + GPR_ASSERT(buffer_size >= record_size); + GPR_ASSERT(buffer_size % record_size == 0); + *num_records = buffer_size / record_size; + for (ix = 0; ix < *num_records; ++ix) { + size_t jx; + const char *record = buffer + (record_size * ix); + char data = (uintptr_t)record % 255; + for (jx = 0; jx < record_size; ++jx) { + GPR_ASSERT(data == record[jx]); + } + } +} + +/* Tries to write the specified number of records. Stops when the log gets + full. Returns the number of records written. Spins for random + number of times, up to 'max_spin_count', between writes. */ +static size_t write_records_to_log(int writer_id, int32_t record_size, + int32_t num_records, + int32_t max_spin_count) { + int32_t ix; + int counter = 0; + for (ix = 0; ix < num_records; ++ix) { + int32_t jx; + int32_t spin_count = max_spin_count ? rand() % max_spin_count : 0; + char *record; + if (counter++ == num_records / 10) { + printf(" Writer %d: %d out of %d written\n", writer_id, ix, + num_records); + counter = 0; + } + record = (char *)(census_log_start_write(record_size)); + if (record == NULL) { + return ix; + } + write_record(record, record_size); + census_log_end_write(record, record_size); + for (jx = 0; jx < spin_count; ++jx) { + GPR_ASSERT(jx >= 0); + } + } + return num_records; +} + +/* Performs a single read iteration. Returns the number of records read. */ +static size_t perform_read_iteration(size_t record_size) { + const void *read_buffer = NULL; + size_t bytes_available; + size_t records_read = 0; + census_log_init_reader(); + while ((read_buffer = census_log_read_next(&bytes_available))) { + int32_t num_records = 0; + read_records(record_size, (const char *)read_buffer, bytes_available, + &num_records); + records_read += num_records; + } + return records_read; +} + +/* Asserts that the log is empty. */ +static void assert_log_empty(void) { + size_t bytes_available; + census_log_init_reader(); + GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); +} + +/* Given log size and record size, computes the minimum usable space. */ +static int32_t min_usable_space(size_t log_size, size_t record_size) { + int32_t usable_space; + int32_t num_blocks = + GPR_MAX(log_size / CENSUS_LOG_MAX_RECORD_SIZE, gpr_cpu_num_cores()); + int32_t waste_per_block = CENSUS_LOG_MAX_RECORD_SIZE % record_size; + /* In the worst case, all except one core-local block is full. */ + int32_t num_full_blocks = num_blocks - 1; + usable_space = (int32_t)log_size - + (num_full_blocks * CENSUS_LOG_MAX_RECORD_SIZE) - + ((num_blocks - num_full_blocks) * waste_per_block); + GPR_ASSERT(usable_space > 0); + return usable_space; +} + +/* Fills the log and verifies data. If 'no fragmentation' is true, records + are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record + size. If not a circular log, verifies that the number of records written + match the number of records read. */ +static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { + int size; + int32_t records_written; + int32_t usable_space; + int32_t records_read; + if (no_fragmentation) { + int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); + size = (1 << log2size); + } else { + while (1) { + size = 1 + (rand() % CENSUS_LOG_MAX_RECORD_SIZE); + if (CENSUS_LOG_MAX_RECORD_SIZE % size) { + break; + } + } + } + printf(" Fill record size: %d\n", size); + records_written = write_records_to_log( + 0 /* writer id */, size, (log_size / size) * 2, 0 /* spin count */); + usable_space = min_usable_space(log_size, size); + GPR_ASSERT(records_written * size >= usable_space); + records_read = perform_read_iteration(size); + if (!circular_log) { + GPR_ASSERT(records_written == records_read); + } + assert_log_empty(); +} + +/* Structure to pass args to writer_thread */ +typedef struct writer_thread_args { + /* Index of this thread in the writers vector. */ + int index; + /* Record size. */ + size_t record_size; + /* Number of records to write. */ + int32_t num_records; + /* Used to signal when writer is complete */ + gpr_cv *done; + gpr_mu *mu; + int *count; +} writer_thread_args; + +/* Writes the given number of records of random size (up to kMaxRecordSize) and + random data to the specified log. */ +static void writer_thread(void *arg) { + writer_thread_args *args = (writer_thread_args *)arg; + /* Maximum number of times to spin between writes. */ + static const int32_t MAX_SPIN_COUNT = 50; + int records_written = 0; + printf(" Writer: %d\n", args->index); + while (records_written < args->num_records) { + records_written += write_records_to_log(args->index, args->record_size, + args->num_records - records_written, + MAX_SPIN_COUNT); + if (records_written < args->num_records) { + /* Ran out of log space. Sleep for a bit and let the reader catch up. + This should never happen for circular logs. */ + printf(" Writer stalled due to out-of-space: %d out of %d written\n", + records_written, args->num_records); + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); + } + } + /* Done. Decrement count and signal. */ + gpr_mu_lock(args->mu); + (*args->count)--; + gpr_cv_broadcast(args->done); + printf(" Writer done: %d\n", args->index); + gpr_mu_unlock(args->mu); +} + +/* struct to pass args to reader_thread */ +typedef struct reader_thread_args { + /* Record size. */ + size_t record_size; + /* Interval between read iterations. */ + int32_t read_iteration_interval_in_msec; + /* Total number of records. */ + int32_t total_records; + /* Signalled when reader should stop. */ + gpr_cv stop; + int stop_flag; + /* Used to signal when reader has finished */ + gpr_cv *done; + gpr_mu *mu; + int running; +} reader_thread_args; + +/* Reads and verifies the specified number of records. Reader can also be + stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' + between read iterations. */ +static void reader_thread(void *arg) { + int32_t records_read = 0; + reader_thread_args *args = (reader_thread_args *)arg; + int32_t num_iterations = 0; + gpr_timespec interval; + int counter = 0; + printf(" Reader starting\n"); + interval = gpr_time_from_micros( + (int64_t)args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); + gpr_mu_lock(args->mu); + while (!args->stop_flag && records_read < args->total_records) { + gpr_cv_wait(&args->stop, args->mu, interval); + if (!args->stop_flag) { + records_read += perform_read_iteration(args->record_size); + GPR_ASSERT(records_read <= args->total_records); + if (counter++ == 100000) { + printf(" Reader: %d out of %d read\n", records_read, + args->total_records); + counter = 0; + } + ++num_iterations; + } + } + /* Done */ + args->running = 0; + gpr_cv_broadcast(args->done); + printf(" Reader: records: %d, iterations: %d\n", records_read, + num_iterations); + gpr_mu_unlock(args->mu); +} + +/* Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER + records. Also, starts a reader that iterates over and reads blocks every + READ_ITERATION_INTERVAL_IN_MSEC. */ +/* Number of writers. */ +#define NUM_WRITERS 5 +static void multiple_writers_single_reader(int circular_log) { + /* Sleep interval between read iterations. */ + static const int32_t READ_ITERATION_INTERVAL_IN_MSEC = 10; + /* Number of records written by each writer. */ + static const int32_t NUM_RECORDS_PER_WRITER = 10 * 1024 * 1024; + /* Maximum record size. */ + static const size_t MAX_RECORD_SIZE = 10; + int ix; + gpr_thd_id id; + gpr_cv writers_done; + int writers_count = NUM_WRITERS; + gpr_mu writers_mu; /* protects writers_done and writers_count */ + writer_thread_args writers[NUM_WRITERS]; + gpr_cv reader_done; + gpr_mu reader_mu; /* protects reader_done and reader.running */ + reader_thread_args reader; + int32_t record_size = 1 + rand() % MAX_RECORD_SIZE; + printf(" Record size: %d\n", record_size); + /* Create and start writers. */ + gpr_cv_init(&writers_done); + gpr_mu_init(&writers_mu); + for (ix = 0; ix < NUM_WRITERS; ++ix) { + writers[ix].index = ix; + writers[ix].record_size = record_size; + writers[ix].num_records = NUM_RECORDS_PER_WRITER; + writers[ix].done = &writers_done; + writers[ix].count = &writers_count; + writers[ix].mu = &writers_mu; + gpr_thd_new(&id, &writer_thread, &writers[ix], NULL); + } + /* Start reader. */ + reader.record_size = record_size; + reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; + reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; + reader.stop_flag = 0; + gpr_cv_init(&reader.stop); + gpr_cv_init(&reader_done); + reader.done = &reader_done; + gpr_mu_init(&reader_mu); + reader.mu = &reader_mu; + reader.running = 1; + gpr_thd_new(&id, &reader_thread, &reader, NULL); + /* Wait for writers to finish. */ + gpr_mu_lock(&writers_mu); + while (writers_count != 0) { + gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&writers_mu); + gpr_mu_destroy(&writers_mu); + gpr_cv_destroy(&writers_done); + gpr_mu_lock(&reader_mu); + if (circular_log) { + /* Stop reader. */ + reader.stop_flag = 1; + gpr_cv_signal(&reader.stop); + } + /* wait for reader to finish */ + while (reader.running) { + gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + if (circular_log) { + /* Assert that there were no out-of-space errors. */ + GPR_ASSERT(0 == census_log_out_of_space_count()); + } + gpr_mu_unlock(&reader_mu); + gpr_mu_destroy(&reader_mu); + gpr_cv_destroy(&reader_done); + printf(" Reader: finished\n"); +} + +/* Log sizes to use for all tests. */ +#define LOG_SIZE_IN_MB 1 +#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) + +static void setup_test(int circular_log) { + census_log_initialize(LOG_SIZE_IN_MB, circular_log); + GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); +} + +/* Attempts to create a record of invalid size (size > + CENSUS_LOG_MAX_RECORD_SIZE). */ +void test_invalid_record_size(void) { + static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; + static const size_t VALID_SIZE = 1; + void *record; + printf("Starting test: invalid record size\n"); + setup_test(0); + record = census_log_start_write(INVALID_SIZE); + GPR_ASSERT(record == NULL); + /* Now try writing a valid record. */ + record = census_log_start_write(VALID_SIZE); + GPR_ASSERT(record != NULL); + census_log_end_write(record, VALID_SIZE); + /* Verifies that available space went down by one block. In theory, this + check can fail if the thread is context switched to a new CPU during the + start_write execution (multiple blocks get allocated), but this has not + been observed in practice. */ + GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == + census_log_remaining_space()); + census_log_shutdown(); +} + +/* Tests end_write() with a different size than what was specified in + start_write(). */ +void test_end_write_with_different_size(void) { + static const size_t START_WRITE_SIZE = 10; + static const size_t END_WRITE_SIZE = 7; + void *record_written; + const void *record_read; + size_t bytes_available; + printf("Starting test: end write with different size\n"); + setup_test(0); + record_written = census_log_start_write(START_WRITE_SIZE); + GPR_ASSERT(record_written != NULL); + census_log_end_write(record_written, END_WRITE_SIZE); + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_written == record_read); + GPR_ASSERT(END_WRITE_SIZE == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +/* Verifies that pending records are not available via read_next(). */ +void test_read_pending_record(void) { + static const size_t PR_RECORD_SIZE = 1024; + size_t bytes_available; + const void *record_read; + void *record_written; + printf("Starting test: read pending record\n"); + setup_test(0); + /* Start a write. */ + record_written = census_log_start_write(PR_RECORD_SIZE); + GPR_ASSERT(record_written != NULL); + /* As write is pending, read should fail. */ + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read == NULL); + /* A read followed by end_write() should succeed. */ + census_log_end_write(record_written, PR_RECORD_SIZE); + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_written == record_read); + GPR_ASSERT(PR_RECORD_SIZE == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +/* Tries reading beyond pending write. */ +void test_read_beyond_pending_record(void) { + /* Start a write. */ + uint32_t incomplete_record_size = 10; + uint32_t complete_record_size = 20; + size_t bytes_available; + void *complete_record; + const void *record_read; + void *incomplete_record; + printf("Starting test: read beyond pending record\n"); + setup_test(0); + incomplete_record = census_log_start_write(incomplete_record_size); + GPR_ASSERT(incomplete_record != NULL); + complete_record = census_log_start_write(complete_record_size); + GPR_ASSERT(complete_record != NULL); + GPR_ASSERT(complete_record != incomplete_record); + census_log_end_write(complete_record, complete_record_size); + /* Now iterate over blocks to read completed records. */ + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(complete_record == record_read); + GPR_ASSERT(complete_record_size == bytes_available); + /* Complete first record. */ + census_log_end_write(incomplete_record, incomplete_record_size); + /* Have read past the incomplete record, so read_next() should return NULL. */ + /* NB: this test also assumes our thread did not get switched to a different + CPU between the two start_write calls */ + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read == NULL); + /* Reset reader to get the newly completed record. */ + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(incomplete_record == record_read); + GPR_ASSERT(incomplete_record_size == bytes_available); + assert_log_empty(); + census_log_shutdown(); +} + +/* Tests scenario where block being read is detached from a core and put on the + dirty list. */ +void test_detached_while_reading(void) { + static const size_t DWR_RECORD_SIZE = 10; + size_t bytes_available; + const void *record_read; + void *record_written; + uint32_t block_read = 0; + printf("Starting test: detached while reading\n"); + setup_test(0); + /* Start a write. */ + record_written = census_log_start_write(DWR_RECORD_SIZE); + GPR_ASSERT(record_written != NULL); + census_log_end_write(record_written, DWR_RECORD_SIZE); + /* Read this record. */ + census_log_init_reader(); + record_read = census_log_read_next(&bytes_available); + GPR_ASSERT(record_read != NULL); + GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); + /* Now fill the log. This will move the block being read from core-local + array to the dirty list. */ + while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { + census_log_end_write(record_written, DWR_RECORD_SIZE); + } + + /* In this iteration, read_next() should only traverse blocks in the + core-local array. Therefore, we expect at most gpr_cpu_num_cores() more + blocks. As log is full, if read_next() is traversing the dirty list, we + will get more than gpr_cpu_num_cores() blocks. */ + while ((record_read = census_log_read_next(&bytes_available))) { + ++block_read; + GPR_ASSERT(block_read <= gpr_cpu_num_cores()); + } + census_log_shutdown(); +} + +/* Fills non-circular log with records sized such that size is a multiple of + CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ +void test_fill_log_no_fragmentation(void) { + const int circular = 0; + printf("Starting test: fill log no fragmentation\n"); + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); + census_log_shutdown(); +} + +/* Fills circular log with records sized such that size is a multiple of + CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ +void test_fill_circular_log_no_fragmentation(void) { + const int circular = 1; + printf("Starting test: fill circular log no fragmentation\n"); + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); + census_log_shutdown(); +} + +/* Fills non-circular log with records that may straddle end of a block. */ +void test_fill_log_with_straddling_records(void) { + const int circular = 0; + printf("Starting test: fill log with straddling records\n"); + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); + census_log_shutdown(); +} + +/* Fills circular log with records that may straddle end of a block. */ +void test_fill_circular_log_with_straddling_records(void) { + const int circular = 1; + printf("Starting test: fill circular log with straddling records\n"); + setup_test(circular); + fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); + census_log_shutdown(); +} + +/* Tests scenario where multiple writers and a single reader are using a log + that is configured to discard old records. */ +void test_multiple_writers_circular_log(void) { + const int circular = 1; + printf("Starting test: multiple writers circular log\n"); + setup_test(circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +/* Tests scenario where multiple writers and a single reader are using a log + that is configured to discard old records. */ +void test_multiple_writers(void) { + const int circular = 0; + printf("Starting test: multiple writers\n"); + setup_test(circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +/* Repeat the straddling records and multiple writers tests with a small log. */ +void test_small_log(void) { + size_t log_size; + const int circular = 0; + printf("Starting test: small log\n"); + census_log_initialize(0, circular); + log_size = census_log_remaining_space(); + GPR_ASSERT(log_size > 0); + fill_log(log_size, 0, circular); + census_log_shutdown(); + census_log_initialize(0, circular); + multiple_writers_single_reader(circular); + census_log_shutdown(); +} + +void test_performance(void) { + int write_size = 1; + for (; write_size < CENSUS_LOG_MAX_RECORD_SIZE; write_size *= 2) { + gpr_timespec write_time; + gpr_timespec start_time; + double write_time_micro = 0.0; + int nrecords = 0; + setup_test(0); + start_time = gpr_now(GPR_CLOCK_REALTIME); + while (1) { + void *record = census_log_start_write(write_size); + if (record == NULL) { + break; + } + census_log_end_write(record, write_size); + nrecords++; + } + write_time = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); + write_time_micro = write_time.tv_sec * 1000000 + write_time.tv_nsec / 1000; + census_log_shutdown(); + printf( + "Wrote %d %d byte records in %.3g microseconds: %g records/us " + "(%g ns/record), %g gigabytes/s\n", + nrecords, write_size, write_time_micro, nrecords / write_time_micro, + 1000 * write_time_micro / nrecords, + (write_size * nrecords) / write_time_micro / 1000); + } +} diff --git a/test/core/statistics/census_stub_test.c b/test/core/statistics/census_stub_test.c deleted file mode 100644 index f38d571abd..0000000000 --- a/test/core/statistics/census_stub_test.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include "src/core/ext/census/census_interface.h" -#include "src/core/ext/census/census_rpc_stats.h" -#include "test/core/util/test_config.h" - -/* Tests census noop stubs in a simulated rpc flow */ -void test_census_stubs(void) { - census_op_id op_id; - census_rpc_stats *stats = census_rpc_stats_create_empty(); - census_aggregated_rpc_stats data_map = {0, NULL}; - - /* Initializes census library at server start up time. */ - census_init(); - /* Starts tracing at the beginning of a rpc. */ - op_id = census_tracing_start_op(); - /* Appends custom annotations on a trace object. */ - census_tracing_print(op_id, "annotation foo"); - census_tracing_print(op_id, "annotation bar"); - /* Appends method tag on the trace object. */ - census_add_method_tag(op_id, "service_foo/method.bar"); - /* Either record client side stats or server side stats associated with the - op_id. Here for testing purpose, we record both. */ - census_record_rpc_client_stats(op_id, stats); - census_record_rpc_server_stats(op_id, stats); - /* Ends a tracing. */ - census_tracing_end_op(op_id); - /* In process stats queries. */ - census_get_server_stats(&data_map); - census_aggregated_rpc_stats_set_empty(&data_map); - census_get_client_stats(&data_map); - census_aggregated_rpc_stats_set_empty(&data_map); - gpr_free(stats); - census_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_census_stubs(); - return 0; -} diff --git a/test/core/statistics/census_stub_test.cc b/test/core/statistics/census_stub_test.cc new file mode 100644 index 0000000000..f38d571abd --- /dev/null +++ b/test/core/statistics/census_stub_test.cc @@ -0,0 +1,62 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include "src/core/ext/census/census_interface.h" +#include "src/core/ext/census/census_rpc_stats.h" +#include "test/core/util/test_config.h" + +/* Tests census noop stubs in a simulated rpc flow */ +void test_census_stubs(void) { + census_op_id op_id; + census_rpc_stats *stats = census_rpc_stats_create_empty(); + census_aggregated_rpc_stats data_map = {0, NULL}; + + /* Initializes census library at server start up time. */ + census_init(); + /* Starts tracing at the beginning of a rpc. */ + op_id = census_tracing_start_op(); + /* Appends custom annotations on a trace object. */ + census_tracing_print(op_id, "annotation foo"); + census_tracing_print(op_id, "annotation bar"); + /* Appends method tag on the trace object. */ + census_add_method_tag(op_id, "service_foo/method.bar"); + /* Either record client side stats or server side stats associated with the + op_id. Here for testing purpose, we record both. */ + census_record_rpc_client_stats(op_id, stats); + census_record_rpc_server_stats(op_id, stats); + /* Ends a tracing. */ + census_tracing_end_op(op_id); + /* In process stats queries. */ + census_get_server_stats(&data_map); + census_aggregated_rpc_stats_set_empty(&data_map); + census_get_client_stats(&data_map); + census_aggregated_rpc_stats_set_empty(&data_map); + gpr_free(stats); + census_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_census_stubs(); + return 0; +} diff --git a/test/core/statistics/hash_table_test.c b/test/core/statistics/hash_table_test.c deleted file mode 100644 index d714e15091..0000000000 --- a/test/core/statistics/hash_table_test.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include "src/core/ext/census/hash_table.h" - -#include -#include -#include -#include "src/core/lib/support/murmur_hash.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -static uint64_t hash64(const void *k) { - size_t len = strlen(k); - uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0); - return higher << 32 | - gpr_murmur_hash3((const char *)(k) + len / 2, len - len / 2, 0); -} - -static int cmp_str_keys(const void *k1, const void *k2) { - return strcmp((const char *)k1, (const char *)k2); -} - -static uint64_t force_collision(const void *k) { - return (1997 + hash64(k) % 3); -} - -static void free_data(void *data) { gpr_free(data); } - -/* Basic tests that empty hash table can be created and destroyed. */ -static void test_create_table(void) { - /* Create table with uint64 key type */ - census_ht *ht = NULL; - census_ht_option ht_options = { - CENSUS_HT_UINT64, 1999, NULL, NULL, NULL, NULL}; - ht = census_ht_create(&ht_options); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_destroy(ht); - /* Create table with pointer key type */ - ht = NULL; - ht_options.key_type = CENSUS_HT_POINTER; - ht_options.hash = &hash64; - ht_options.compare_keys = &cmp_str_keys; - ht = census_ht_create(&ht_options); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_destroy(ht); -} - -static void test_table_with_int_key(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; - census_ht *ht = census_ht_create(&opt); - uint64_t i = 0; - uint64_t sum_of_keys = 0; - size_t num_elements; - census_ht_kv *elements = NULL; - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - elements = census_ht_get_all_elements(ht, &num_elements); - GPR_ASSERT(num_elements == 0); - GPR_ASSERT(elements == NULL); - for (i = 0; i < 20; ++i) { - census_ht_key key; - key.val = i; - census_ht_insert(ht, key, (void *)(intptr_t)i); - GPR_ASSERT(census_ht_get_size(ht) == i + 1); - } - for (i = 0; i < 20; i++) { - uint64_t *val = NULL; - census_ht_key key; - key.val = i; - val = census_ht_find(ht, key); - GPR_ASSERT(val == (void *)(intptr_t)i); - } - elements = census_ht_get_all_elements(ht, &num_elements); - GPR_ASSERT(elements != NULL); - GPR_ASSERT(num_elements == 20); - for (i = 0; i < num_elements; i++) { - sum_of_keys += elements[i].k.val; - } - GPR_ASSERT(sum_of_keys == 190); - gpr_free(elements); - census_ht_destroy(ht); -} - -/* Test that there is no memory leak when keys and values are owned by table. */ -static void test_value_and_key_deleter(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, - &cmp_str_keys, &free_data, &free_data}; - census_ht *ht = census_ht_create(&opt); - census_ht_key key; - char *val = NULL; - char *val2 = NULL; - key.ptr = gpr_malloc(100); - val = gpr_malloc(10); - strcpy(val, "value"); - strcpy(key.ptr, "some string as a key"); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_insert(ht, key, val); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val = census_ht_find(ht, key); - GPR_ASSERT(val != NULL); - GPR_ASSERT(strcmp(val, "value") == 0); - /* Insert same key different value, old value is overwritten. */ - val2 = gpr_malloc(10); - strcpy(val2, "v2"); - census_ht_insert(ht, key, val2); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val2 = census_ht_find(ht, key); - GPR_ASSERT(val2 != NULL); - GPR_ASSERT(strcmp(val2, "v2") == 0); - census_ht_destroy(ht); -} - -/* Test simple insert and erase operations. */ -static void test_simple_add_and_erase(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; - census_ht *ht = census_ht_create(&opt); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - { - census_ht_key key; - int val = 3; - key.val = 2; - census_ht_insert(ht, key, (void *)&val); - GPR_ASSERT(census_ht_get_size(ht) == 1); - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 0); - /* Erasing a key from an empty table should be noop. */ - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 0); - /* Erasing a non-existant key from a table should be noop. */ - census_ht_insert(ht, key, (void *)&val); - key.val = 3; - census_ht_insert(ht, key, (void *)&val); - key.val = 9; - census_ht_insert(ht, key, (void *)&val); - GPR_ASSERT(census_ht_get_size(ht) == 3); - key.val = 1; - census_ht_erase(ht, key); - /* size unchanged after deleting non-existant key. */ - GPR_ASSERT(census_ht_get_size(ht) == 3); - /* size decrease by 1 after deleting an existant key. */ - key.val = 2; - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 2); - } - census_ht_destroy(ht); -} - -static void test_insertion_and_deletion_with_high_collision_rate(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 13, &force_collision, - &cmp_str_keys, NULL, NULL}; - census_ht *ht = census_ht_create(&opt); - char key_str[1000][GPR_LTOA_MIN_BUFSIZE]; - uint64_t val = 0; - unsigned i = 0; - for (i = 0; i < 1000; i++) { - census_ht_key key; - key.ptr = key_str[i]; - gpr_ltoa(i, key_str[i]); - census_ht_insert(ht, key, (void *)(&val)); - gpr_log(GPR_INFO, "%d\n", i); - GPR_ASSERT(census_ht_get_size(ht) == (i + 1)); - } - for (i = 0; i < 1000; i++) { - census_ht_key key; - key.ptr = key_str[i]; - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == (999 - i)); - } - census_ht_destroy(ht); -} - -static void test_table_with_string_key(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, - &cmp_str_keys, NULL, NULL}; - census_ht *ht = census_ht_create(&opt); - const char *keys[] = { - "k1", "a", "000", "apple", "banana_a_long_long_long_banana", - "%$", "111", "foo", "b"}; - const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - int i = 0; - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - for (i = 0; i < 9; i++) { - census_ht_key key; - key.ptr = (void *)(keys[i]); - census_ht_insert(ht, key, (void *)(vals + i)); - } - GPR_ASSERT(census_ht_get_size(ht) == 9); - for (i = 0; i < 9; i++) { - census_ht_key key; - int *val_ptr; - key.ptr = (void *)(keys[i]); - val_ptr = census_ht_find(ht, key); - GPR_ASSERT(*val_ptr == vals[i]); - } - { - /* inserts duplicate keys */ - census_ht_key key; - int *val_ptr = NULL; - key.ptr = (void *)(keys[2]); - census_ht_insert(ht, key, (void *)(vals + 8)); - /* expect value to be over written by new insertion */ - GPR_ASSERT(census_ht_get_size(ht) == 9); - val_ptr = census_ht_find(ht, key); - GPR_ASSERT(*val_ptr == vals[8]); - } - for (i = 0; i < 9; i++) { - census_ht_key key; - int *val_ptr; - uint32_t expected_tbl_sz = 9 - i; - GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz); - key.ptr = (void *)(keys[i]); - val_ptr = census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz - 1); - val_ptr = census_ht_find(ht, key); - GPR_ASSERT(val_ptr == NULL); - } - census_ht_destroy(ht); -} - -static void test_insertion_with_same_key(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 11, NULL, NULL, NULL, NULL}; - census_ht *ht = census_ht_create(&opt); - census_ht_key key; - const char vals[] = {'a', 'b', 'c'}; - char *val_ptr; - key.val = 3; - census_ht_insert(ht, key, (void *)&(vals[0])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char *)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'a'); - key.val = 4; - val_ptr = (char *)census_ht_find(ht, key); - GPR_ASSERT(val_ptr == NULL); - key.val = 3; - census_ht_insert(ht, key, (void *)&(vals[1])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char *)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'b'); - census_ht_insert(ht, key, (void *)&(vals[2])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char *)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'c'); - census_ht_destroy(ht); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_create_table(); - test_simple_add_and_erase(); - test_table_with_int_key(); - test_table_with_string_key(); - test_value_and_key_deleter(); - test_insertion_with_same_key(); - test_insertion_and_deletion_with_high_collision_rate(); - return 0; -} diff --git a/test/core/statistics/hash_table_test.cc b/test/core/statistics/hash_table_test.cc new file mode 100644 index 0000000000..d714e15091 --- /dev/null +++ b/test/core/statistics/hash_table_test.cc @@ -0,0 +1,286 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "src/core/ext/census/hash_table.h" + +#include +#include +#include +#include "src/core/lib/support/murmur_hash.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +static uint64_t hash64(const void *k) { + size_t len = strlen(k); + uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0); + return higher << 32 | + gpr_murmur_hash3((const char *)(k) + len / 2, len - len / 2, 0); +} + +static int cmp_str_keys(const void *k1, const void *k2) { + return strcmp((const char *)k1, (const char *)k2); +} + +static uint64_t force_collision(const void *k) { + return (1997 + hash64(k) % 3); +} + +static void free_data(void *data) { gpr_free(data); } + +/* Basic tests that empty hash table can be created and destroyed. */ +static void test_create_table(void) { + /* Create table with uint64 key type */ + census_ht *ht = NULL; + census_ht_option ht_options = { + CENSUS_HT_UINT64, 1999, NULL, NULL, NULL, NULL}; + ht = census_ht_create(&ht_options); + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + census_ht_destroy(ht); + /* Create table with pointer key type */ + ht = NULL; + ht_options.key_type = CENSUS_HT_POINTER; + ht_options.hash = &hash64; + ht_options.compare_keys = &cmp_str_keys; + ht = census_ht_create(&ht_options); + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + census_ht_destroy(ht); +} + +static void test_table_with_int_key(void) { + census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; + census_ht *ht = census_ht_create(&opt); + uint64_t i = 0; + uint64_t sum_of_keys = 0; + size_t num_elements; + census_ht_kv *elements = NULL; + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + elements = census_ht_get_all_elements(ht, &num_elements); + GPR_ASSERT(num_elements == 0); + GPR_ASSERT(elements == NULL); + for (i = 0; i < 20; ++i) { + census_ht_key key; + key.val = i; + census_ht_insert(ht, key, (void *)(intptr_t)i); + GPR_ASSERT(census_ht_get_size(ht) == i + 1); + } + for (i = 0; i < 20; i++) { + uint64_t *val = NULL; + census_ht_key key; + key.val = i; + val = census_ht_find(ht, key); + GPR_ASSERT(val == (void *)(intptr_t)i); + } + elements = census_ht_get_all_elements(ht, &num_elements); + GPR_ASSERT(elements != NULL); + GPR_ASSERT(num_elements == 20); + for (i = 0; i < num_elements; i++) { + sum_of_keys += elements[i].k.val; + } + GPR_ASSERT(sum_of_keys == 190); + gpr_free(elements); + census_ht_destroy(ht); +} + +/* Test that there is no memory leak when keys and values are owned by table. */ +static void test_value_and_key_deleter(void) { + census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, + &cmp_str_keys, &free_data, &free_data}; + census_ht *ht = census_ht_create(&opt); + census_ht_key key; + char *val = NULL; + char *val2 = NULL; + key.ptr = gpr_malloc(100); + val = gpr_malloc(10); + strcpy(val, "value"); + strcpy(key.ptr, "some string as a key"); + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + census_ht_insert(ht, key, val); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val = census_ht_find(ht, key); + GPR_ASSERT(val != NULL); + GPR_ASSERT(strcmp(val, "value") == 0); + /* Insert same key different value, old value is overwritten. */ + val2 = gpr_malloc(10); + strcpy(val2, "v2"); + census_ht_insert(ht, key, val2); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val2 = census_ht_find(ht, key); + GPR_ASSERT(val2 != NULL); + GPR_ASSERT(strcmp(val2, "v2") == 0); + census_ht_destroy(ht); +} + +/* Test simple insert and erase operations. */ +static void test_simple_add_and_erase(void) { + census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; + census_ht *ht = census_ht_create(&opt); + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + { + census_ht_key key; + int val = 3; + key.val = 2; + census_ht_insert(ht, key, (void *)&val); + GPR_ASSERT(census_ht_get_size(ht) == 1); + census_ht_erase(ht, key); + GPR_ASSERT(census_ht_get_size(ht) == 0); + /* Erasing a key from an empty table should be noop. */ + census_ht_erase(ht, key); + GPR_ASSERT(census_ht_get_size(ht) == 0); + /* Erasing a non-existant key from a table should be noop. */ + census_ht_insert(ht, key, (void *)&val); + key.val = 3; + census_ht_insert(ht, key, (void *)&val); + key.val = 9; + census_ht_insert(ht, key, (void *)&val); + GPR_ASSERT(census_ht_get_size(ht) == 3); + key.val = 1; + census_ht_erase(ht, key); + /* size unchanged after deleting non-existant key. */ + GPR_ASSERT(census_ht_get_size(ht) == 3); + /* size decrease by 1 after deleting an existant key. */ + key.val = 2; + census_ht_erase(ht, key); + GPR_ASSERT(census_ht_get_size(ht) == 2); + } + census_ht_destroy(ht); +} + +static void test_insertion_and_deletion_with_high_collision_rate(void) { + census_ht_option opt = {CENSUS_HT_POINTER, 13, &force_collision, + &cmp_str_keys, NULL, NULL}; + census_ht *ht = census_ht_create(&opt); + char key_str[1000][GPR_LTOA_MIN_BUFSIZE]; + uint64_t val = 0; + unsigned i = 0; + for (i = 0; i < 1000; i++) { + census_ht_key key; + key.ptr = key_str[i]; + gpr_ltoa(i, key_str[i]); + census_ht_insert(ht, key, (void *)(&val)); + gpr_log(GPR_INFO, "%d\n", i); + GPR_ASSERT(census_ht_get_size(ht) == (i + 1)); + } + for (i = 0; i < 1000; i++) { + census_ht_key key; + key.ptr = key_str[i]; + census_ht_erase(ht, key); + GPR_ASSERT(census_ht_get_size(ht) == (999 - i)); + } + census_ht_destroy(ht); +} + +static void test_table_with_string_key(void) { + census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, + &cmp_str_keys, NULL, NULL}; + census_ht *ht = census_ht_create(&opt); + const char *keys[] = { + "k1", "a", "000", "apple", "banana_a_long_long_long_banana", + "%$", "111", "foo", "b"}; + const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + int i = 0; + GPR_ASSERT(ht != NULL); + GPR_ASSERT(census_ht_get_size(ht) == 0); + for (i = 0; i < 9; i++) { + census_ht_key key; + key.ptr = (void *)(keys[i]); + census_ht_insert(ht, key, (void *)(vals + i)); + } + GPR_ASSERT(census_ht_get_size(ht) == 9); + for (i = 0; i < 9; i++) { + census_ht_key key; + int *val_ptr; + key.ptr = (void *)(keys[i]); + val_ptr = census_ht_find(ht, key); + GPR_ASSERT(*val_ptr == vals[i]); + } + { + /* inserts duplicate keys */ + census_ht_key key; + int *val_ptr = NULL; + key.ptr = (void *)(keys[2]); + census_ht_insert(ht, key, (void *)(vals + 8)); + /* expect value to be over written by new insertion */ + GPR_ASSERT(census_ht_get_size(ht) == 9); + val_ptr = census_ht_find(ht, key); + GPR_ASSERT(*val_ptr == vals[8]); + } + for (i = 0; i < 9; i++) { + census_ht_key key; + int *val_ptr; + uint32_t expected_tbl_sz = 9 - i; + GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz); + key.ptr = (void *)(keys[i]); + val_ptr = census_ht_find(ht, key); + GPR_ASSERT(val_ptr != NULL); + census_ht_erase(ht, key); + GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz - 1); + val_ptr = census_ht_find(ht, key); + GPR_ASSERT(val_ptr == NULL); + } + census_ht_destroy(ht); +} + +static void test_insertion_with_same_key(void) { + census_ht_option opt = {CENSUS_HT_UINT64, 11, NULL, NULL, NULL, NULL}; + census_ht *ht = census_ht_create(&opt); + census_ht_key key; + const char vals[] = {'a', 'b', 'c'}; + char *val_ptr; + key.val = 3; + census_ht_insert(ht, key, (void *)&(vals[0])); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val_ptr = (char *)census_ht_find(ht, key); + GPR_ASSERT(val_ptr != NULL); + GPR_ASSERT(*val_ptr == 'a'); + key.val = 4; + val_ptr = (char *)census_ht_find(ht, key); + GPR_ASSERT(val_ptr == NULL); + key.val = 3; + census_ht_insert(ht, key, (void *)&(vals[1])); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val_ptr = (char *)census_ht_find(ht, key); + GPR_ASSERT(val_ptr != NULL); + GPR_ASSERT(*val_ptr == 'b'); + census_ht_insert(ht, key, (void *)&(vals[2])); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val_ptr = (char *)census_ht_find(ht, key); + GPR_ASSERT(val_ptr != NULL); + GPR_ASSERT(*val_ptr == 'c'); + census_ht_destroy(ht); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_create_table(); + test_simple_add_and_erase(); + test_table_with_int_key(); + test_table_with_string_key(); + test_value_and_key_deleter(); + test_insertion_with_same_key(); + test_insertion_and_deletion_with_high_collision_rate(); + return 0; +} diff --git a/test/core/statistics/multiple_writers_circular_buffer_test.c b/test/core/statistics/multiple_writers_circular_buffer_test.c deleted file mode 100644 index 8abd76c3d1..0000000000 --- a/test/core/statistics/multiple_writers_circular_buffer_test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/statistics/census_log_tests.h" - -#include - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_multiple_writers_circular_log(); - return 0; -} diff --git a/test/core/statistics/multiple_writers_circular_buffer_test.cc b/test/core/statistics/multiple_writers_circular_buffer_test.cc new file mode 100644 index 0000000000..8abd76c3d1 --- /dev/null +++ b/test/core/statistics/multiple_writers_circular_buffer_test.cc @@ -0,0 +1,31 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/statistics/census_log_tests.h" + +#include + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_multiple_writers_circular_log(); + return 0; +} diff --git a/test/core/statistics/multiple_writers_test.c b/test/core/statistics/multiple_writers_test.c deleted file mode 100644 index de800e0d8a..0000000000 --- a/test/core/statistics/multiple_writers_test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/statistics/census_log_tests.h" - -#include - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_multiple_writers(); - return 0; -} diff --git a/test/core/statistics/multiple_writers_test.cc b/test/core/statistics/multiple_writers_test.cc new file mode 100644 index 0000000000..de800e0d8a --- /dev/null +++ b/test/core/statistics/multiple_writers_test.cc @@ -0,0 +1,31 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/statistics/census_log_tests.h" + +#include + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_multiple_writers(); + return 0; +} diff --git a/test/core/statistics/performance_test.c b/test/core/statistics/performance_test.c deleted file mode 100644 index 6104acb612..0000000000 --- a/test/core/statistics/performance_test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/statistics/census_log_tests.h" - -#include - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_performance(); - return 0; -} diff --git a/test/core/statistics/performance_test.cc b/test/core/statistics/performance_test.cc new file mode 100644 index 0000000000..6104acb612 --- /dev/null +++ b/test/core/statistics/performance_test.cc @@ -0,0 +1,31 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/statistics/census_log_tests.h" + +#include + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_performance(); + return 0; +} diff --git a/test/core/statistics/quick_test.c b/test/core/statistics/quick_test.c deleted file mode 100644 index 1e044b6b59..0000000000 --- a/test/core/statistics/quick_test.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/statistics/census_log_tests.h" - -#include - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_invalid_record_size(); - test_end_write_with_different_size(); - test_read_pending_record(); - test_read_beyond_pending_record(); - test_detached_while_reading(); - test_fill_log_no_fragmentation(); - test_fill_circular_log_no_fragmentation(); - test_fill_log_with_straddling_records(); - test_fill_circular_log_with_straddling_records(); - return 0; -} diff --git a/test/core/statistics/quick_test.cc b/test/core/statistics/quick_test.cc new file mode 100644 index 0000000000..1e044b6b59 --- /dev/null +++ b/test/core/statistics/quick_test.cc @@ -0,0 +1,39 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/statistics/census_log_tests.h" + +#include + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_invalid_record_size(); + test_end_write_with_different_size(); + test_read_pending_record(); + test_read_beyond_pending_record(); + test_detached_while_reading(); + test_fill_log_no_fragmentation(); + test_fill_circular_log_no_fragmentation(); + test_fill_log_with_straddling_records(); + test_fill_circular_log_with_straddling_records(); + return 0; +} diff --git a/test/core/statistics/rpc_stats_test.c b/test/core/statistics/rpc_stats_test.c deleted file mode 100644 index 01ac5a19ab..0000000000 --- a/test/core/statistics/rpc_stats_test.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include "src/core/ext/census/census_interface.h" -#include "src/core/ext/census/census_rpc_stats.h" -#include "src/core/ext/census/census_tracing.h" -#include "test/core/util/test_config.h" - -/* Ensure all possible state transitions are called without causing problem */ -static void test_init_shutdown(void) { - census_stats_store_init(); - census_stats_store_init(); - census_stats_store_shutdown(); - census_stats_store_shutdown(); - census_stats_store_init(); -} - -static void test_create_and_destroy(void) { - census_rpc_stats *stats = NULL; - census_aggregated_rpc_stats agg_stats = {0, NULL}; - - stats = census_rpc_stats_create_empty(); - GPR_ASSERT(stats != NULL); - GPR_ASSERT(stats->cnt == 0 && stats->rpc_error_cnt == 0 && - stats->app_error_cnt == 0 && stats->elapsed_time_ms == 0.0 && - stats->api_request_bytes == 0 && stats->wire_request_bytes == 0 && - stats->api_response_bytes == 0 && stats->wire_response_bytes == 0); - gpr_free(stats); - - census_aggregated_rpc_stats_set_empty(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - GPR_ASSERT(agg_stats.stats == NULL); - agg_stats.num_entries = 1; - agg_stats.stats = (census_per_method_rpc_stats *)gpr_malloc( - sizeof(census_per_method_rpc_stats)); - agg_stats.stats[0].method = gpr_strdup("foo"); - census_aggregated_rpc_stats_set_empty(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - GPR_ASSERT(agg_stats.stats == NULL); -} - -#define ASSERT_NEAR(a, b) \ - GPR_ASSERT((a - b) * (a - b) < 1e-24 * (a + b) * (a + b)) - -static void test_record_and_get_stats(void) { - census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; - census_op_id id; - census_aggregated_rpc_stats agg_stats = {0, NULL}; - - /* Record client stats twice with the same op_id. */ - census_init(); - id = census_tracing_start_op(); - census_add_method_tag(id, "m1"); - census_record_rpc_client_stats(id, &stats); - census_record_rpc_client_stats(id, &stats); - census_tracing_end_op(id); - /* Server stats expect to be empty */ - census_get_server_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - GPR_ASSERT(agg_stats.stats == NULL); - /* Client stats expect to have one entry */ - census_get_client_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 1); - GPR_ASSERT(agg_stats.stats != NULL); - GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m1") == 0); - GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 2 && - agg_stats.stats[0].hour_stats.cnt == 2 && - agg_stats.stats[0].total_stats.cnt == 2); - ASSERT_NEAR(agg_stats.stats[0].minute_stats.wire_response_bytes, 16.8); - ASSERT_NEAR(agg_stats.stats[0].hour_stats.wire_response_bytes, 16.8); - ASSERT_NEAR(agg_stats.stats[0].total_stats.wire_response_bytes, 16.8); - /* Get stats again, results should be the same. */ - census_get_client_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 1); - census_aggregated_rpc_stats_set_empty(&agg_stats); - census_shutdown(); - - /* Record both server (once) and client (twice) stats with different op_ids. - */ - census_init(); - id = census_tracing_start_op(); - census_add_method_tag(id, "m2"); - census_record_rpc_client_stats(id, &stats); - census_tracing_end_op(id); - id = census_tracing_start_op(); - census_add_method_tag(id, "m3"); - census_record_rpc_server_stats(id, &stats); - census_tracing_end_op(id); - id = census_tracing_start_op(); - census_add_method_tag(id, "m4"); - census_record_rpc_client_stats(id, &stats); - census_tracing_end_op(id); - /* Check server stats */ - census_get_server_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 1); - GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m3") == 0); - GPR_ASSERT(agg_stats.stats[0].minute_stats.app_error_cnt == 3 && - agg_stats.stats[0].hour_stats.app_error_cnt == 3 && - agg_stats.stats[0].total_stats.app_error_cnt == 3); - census_aggregated_rpc_stats_set_empty(&agg_stats); - /* Check client stats */ - census_get_client_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 2); - GPR_ASSERT(agg_stats.stats != NULL); - GPR_ASSERT((strcmp(agg_stats.stats[0].method, "m2") == 0 && - strcmp(agg_stats.stats[1].method, "m4") == 0) || - (strcmp(agg_stats.stats[0].method, "m4") == 0 && - strcmp(agg_stats.stats[1].method, "m2") == 0)); - GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 1 && - agg_stats.stats[1].minute_stats.cnt == 1); - census_aggregated_rpc_stats_set_empty(&agg_stats); - census_shutdown(); -} - -static void test_record_stats_on_unknown_op_id(void) { - census_op_id unknown_id = {0xDEAD, 0xBEEF}; - census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; - census_aggregated_rpc_stats agg_stats = {0, NULL}; - - census_init(); - /* Tests that recording stats against unknown id is noop. */ - census_record_rpc_client_stats(unknown_id, &stats); - census_record_rpc_server_stats(unknown_id, &stats); - census_get_server_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - GPR_ASSERT(agg_stats.stats == NULL); - census_get_client_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - GPR_ASSERT(agg_stats.stats == NULL); - census_aggregated_rpc_stats_set_empty(&agg_stats); - census_shutdown(); -} - -/* Test that record stats is noop when trace store is uninitialized. */ -static void test_record_stats_with_trace_store_uninitialized(void) { - census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; - census_op_id id = {0, 0}; - census_aggregated_rpc_stats agg_stats = {0, NULL}; - - census_init(); - id = census_tracing_start_op(); - census_add_method_tag(id, "m"); - census_tracing_end_op(id); - /* shuts down trace store only. */ - census_tracing_shutdown(); - census_record_rpc_client_stats(id, &stats); - census_get_client_stats(&agg_stats); - GPR_ASSERT(agg_stats.num_entries == 0); - census_stats_store_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_init_shutdown(); - test_create_and_destroy(); - test_record_and_get_stats(); - test_record_stats_on_unknown_op_id(); - test_record_stats_with_trace_store_uninitialized(); - return 0; -} diff --git a/test/core/statistics/rpc_stats_test.cc b/test/core/statistics/rpc_stats_test.cc new file mode 100644 index 0000000000..01ac5a19ab --- /dev/null +++ b/test/core/statistics/rpc_stats_test.cc @@ -0,0 +1,183 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/census/census_interface.h" +#include "src/core/ext/census/census_rpc_stats.h" +#include "src/core/ext/census/census_tracing.h" +#include "test/core/util/test_config.h" + +/* Ensure all possible state transitions are called without causing problem */ +static void test_init_shutdown(void) { + census_stats_store_init(); + census_stats_store_init(); + census_stats_store_shutdown(); + census_stats_store_shutdown(); + census_stats_store_init(); +} + +static void test_create_and_destroy(void) { + census_rpc_stats *stats = NULL; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + stats = census_rpc_stats_create_empty(); + GPR_ASSERT(stats != NULL); + GPR_ASSERT(stats->cnt == 0 && stats->rpc_error_cnt == 0 && + stats->app_error_cnt == 0 && stats->elapsed_time_ms == 0.0 && + stats->api_request_bytes == 0 && stats->wire_request_bytes == 0 && + stats->api_response_bytes == 0 && stats->wire_response_bytes == 0); + gpr_free(stats); + + census_aggregated_rpc_stats_set_empty(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + agg_stats.num_entries = 1; + agg_stats.stats = (census_per_method_rpc_stats *)gpr_malloc( + sizeof(census_per_method_rpc_stats)); + agg_stats.stats[0].method = gpr_strdup("foo"); + census_aggregated_rpc_stats_set_empty(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); +} + +#define ASSERT_NEAR(a, b) \ + GPR_ASSERT((a - b) * (a - b) < 1e-24 * (a + b) * (a + b)) + +static void test_record_and_get_stats(void) { + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_op_id id; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + /* Record client stats twice with the same op_id. */ + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m1"); + census_record_rpc_client_stats(id, &stats); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + /* Server stats expect to be empty */ + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + /* Client stats expect to have one entry */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + GPR_ASSERT(agg_stats.stats != NULL); + GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m1") == 0); + GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 2 && + agg_stats.stats[0].hour_stats.cnt == 2 && + agg_stats.stats[0].total_stats.cnt == 2); + ASSERT_NEAR(agg_stats.stats[0].minute_stats.wire_response_bytes, 16.8); + ASSERT_NEAR(agg_stats.stats[0].hour_stats.wire_response_bytes, 16.8); + ASSERT_NEAR(agg_stats.stats[0].total_stats.wire_response_bytes, 16.8); + /* Get stats again, results should be the same. */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); + + /* Record both server (once) and client (twice) stats with different op_ids. + */ + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m2"); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + id = census_tracing_start_op(); + census_add_method_tag(id, "m3"); + census_record_rpc_server_stats(id, &stats); + census_tracing_end_op(id); + id = census_tracing_start_op(); + census_add_method_tag(id, "m4"); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + /* Check server stats */ + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m3") == 0); + GPR_ASSERT(agg_stats.stats[0].minute_stats.app_error_cnt == 3 && + agg_stats.stats[0].hour_stats.app_error_cnt == 3 && + agg_stats.stats[0].total_stats.app_error_cnt == 3); + census_aggregated_rpc_stats_set_empty(&agg_stats); + /* Check client stats */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 2); + GPR_ASSERT(agg_stats.stats != NULL); + GPR_ASSERT((strcmp(agg_stats.stats[0].method, "m2") == 0 && + strcmp(agg_stats.stats[1].method, "m4") == 0) || + (strcmp(agg_stats.stats[0].method, "m4") == 0 && + strcmp(agg_stats.stats[1].method, "m2") == 0)); + GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 1 && + agg_stats.stats[1].minute_stats.cnt == 1); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); +} + +static void test_record_stats_on_unknown_op_id(void) { + census_op_id unknown_id = {0xDEAD, 0xBEEF}; + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + census_init(); + /* Tests that recording stats against unknown id is noop. */ + census_record_rpc_client_stats(unknown_id, &stats); + census_record_rpc_server_stats(unknown_id, &stats); + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); +} + +/* Test that record stats is noop when trace store is uninitialized. */ +static void test_record_stats_with_trace_store_uninitialized(void) { + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_op_id id = {0, 0}; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m"); + census_tracing_end_op(id); + /* shuts down trace store only. */ + census_tracing_shutdown(); + census_record_rpc_client_stats(id, &stats); + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + census_stats_store_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_init_shutdown(); + test_create_and_destroy(); + test_record_and_get_stats(); + test_record_stats_on_unknown_op_id(); + test_record_stats_with_trace_store_uninitialized(); + return 0; +} diff --git a/test/core/statistics/small_log_test.c b/test/core/statistics/small_log_test.c deleted file mode 100644 index 4bcc35c37e..0000000000 --- a/test/core/statistics/small_log_test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/statistics/census_log_tests.h" - -#include - -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - test_small_log(); - return 0; -} diff --git a/test/core/statistics/small_log_test.cc b/test/core/statistics/small_log_test.cc new file mode 100644 index 0000000000..4bcc35c37e --- /dev/null +++ b/test/core/statistics/small_log_test.cc @@ -0,0 +1,31 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/statistics/census_log_tests.h" + +#include + +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + test_small_log(); + return 0; +} diff --git a/test/core/statistics/trace_test.c b/test/core/statistics/trace_test.c deleted file mode 100644 index 63da9f71d3..0000000000 --- a/test/core/statistics/trace_test.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/ext/census/census_interface.h" -#include "src/core/ext/census/census_tracing.h" -#include "src/core/ext/census/census_tracing.h" -#include "test/core/util/test_config.h" - -/* Ensure all possible state transitions are called without causing problem */ -static void test_init_shutdown(void) { - census_tracing_init(); - census_tracing_init(); - census_tracing_shutdown(); - census_tracing_shutdown(); - census_tracing_init(); -} - -static void test_start_op_generates_locally_unique_ids(void) { -/* Check that ids generated within window size of 1000 are unique. - TODO(hongyu): Replace O(n^2) duplicate detection algorithm with O(nlogn) - algorithm. Enhance the test to larger window size (>10^6) */ -#define WINDOW_SIZE 1000 - census_op_id ids[WINDOW_SIZE]; - int i; - census_init(); - for (i = 0; i < WINDOW_SIZE; i++) { - ids[i] = census_tracing_start_op(); - census_tracing_end_op(ids[i]); - } - for (i = 0; i < WINDOW_SIZE - 1; i++) { - int j; - for (j = i + 1; j < WINDOW_SIZE; j++) { - GPR_ASSERT(ids[i].upper != ids[j].upper || ids[i].lower != ids[j].lower); - } - } -#undef WINDOW_SIZE - census_shutdown(); -} - -static void test_get_trace_method_name(void) { - census_op_id id; - const char write_name[] = "service/method"; - census_tracing_init(); - id = census_tracing_start_op(); - census_add_method_tag(id, write_name); - census_internal_lock_trace_store(); - { - const char *read_name = - census_get_trace_method_name(census_get_trace_obj_locked(id)); - GPR_ASSERT(strcmp(read_name, write_name) == 0); - } - census_internal_unlock_trace_store(); - census_tracing_shutdown(); -} - -typedef struct thd_arg { - int num_done; - gpr_cv done; - gpr_mu mu; -} thd_arg; - -static void mimic_trace_op_sequences(void *arg) { - census_op_id id; - const char *method_name = "service_foo/method_bar"; - int i = 0; - const int num_iter = 200; - thd_arg *args = (thd_arg *)arg; - GPR_ASSERT(args != NULL); - gpr_log(GPR_INFO, "Start trace op sequence thread."); - for (i = 0; i < num_iter; i++) { - id = census_tracing_start_op(); - census_add_method_tag(id, method_name); - /* pretend doing 1us work. */ - gpr_sleep_until(GRPC_TIMEOUT_MICROS_TO_DEADLINE(1)); - census_tracing_end_op(id); - } - gpr_log(GPR_INFO, "End trace op sequence thread."); - gpr_mu_lock(&args->mu); - args->num_done += 1; - gpr_cv_broadcast(&args->done); - gpr_mu_unlock(&args->mu); -} - -static void test_concurrency(void) { -#define NUM_THREADS 1000 - gpr_thd_id tid[NUM_THREADS]; - int i = 0; - thd_arg arg; - arg.num_done = 0; - gpr_mu_init(&arg.mu); - gpr_cv_init(&arg.done); - census_tracing_init(); - for (i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); - } - gpr_mu_lock(&arg.mu); - while (arg.num_done < NUM_THREADS) { - gpr_log(GPR_INFO, "num done %d", arg.num_done); - gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&arg.mu); - census_tracing_shutdown(); -#undef NUM_THREADS -} - -static void test_add_method_tag_to_unknown_op_id(void) { - census_op_id unknown_id = {0xDEAD, 0xBEEF}; - int ret = 0; - census_tracing_init(); - ret = census_add_method_tag(unknown_id, "foo"); - GPR_ASSERT(ret != 0); - census_tracing_shutdown(); -} - -static void test_trace_print(void) { - census_op_id id; - int i; - const char *annotation_txt[4] = {"abc", "", "$%^ *()_"}; - char long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 10]; - - memset(long_txt, 'a', GPR_ARRAY_SIZE(long_txt)); - long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 9] = '\0'; - annotation_txt[3] = long_txt; - - census_tracing_init(); - id = census_tracing_start_op(); - /* Adds large number of annotations to each trace */ - for (i = 0; i < 1000; i++) { - census_tracing_print(id, - annotation_txt[i % GPR_ARRAY_SIZE(annotation_txt)]); - } - census_tracing_end_op(id); - - census_tracing_shutdown(); -} - -/* Returns 1 if two ids are equal, otherwise returns 0. */ -static int ids_equal(census_op_id id1, census_op_id id2) { - return (id1.upper == id2.upper) && (id1.lower == id2.lower); -} - -static void test_get_active_ops(void) { - census_op_id id_1, id_2, id_3; - census_trace_obj **active_ops; - const char *annotation_txt[] = {"annotation 1", "a2"}; - int i = 0; - int n = 0; - - gpr_log(GPR_INFO, "test_get_active_ops"); - census_tracing_init(); - /* No active ops before calling start_op(). */ - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops == NULL); - GPR_ASSERT(n == 0); - - /* Starts one op */ - id_1 = census_tracing_start_op(); - census_add_method_tag(id_1, "foo_1"); - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops != NULL); - GPR_ASSERT(n == 1); - GPR_ASSERT(ids_equal(active_ops[0]->id, id_1)); - census_trace_obj_destroy(active_ops[0]); - gpr_free(active_ops); - active_ops = NULL; - - /* Start the second and the third ops */ - id_2 = census_tracing_start_op(); - census_add_method_tag(id_2, "foo_2"); - id_3 = census_tracing_start_op(); - census_add_method_tag(id_3, "foo_3"); - - active_ops = census_get_active_ops(&n); - GPR_ASSERT(n == 3); - for (i = 0; i < 3; i++) { - census_trace_obj_destroy(active_ops[i]); - } - gpr_free(active_ops); - active_ops = NULL; - - /* End the second op and add annotations to the third ops */ - census_tracing_end_op(id_2); - census_tracing_print(id_3, annotation_txt[0]); - census_tracing_print(id_3, annotation_txt[1]); - - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops != NULL); - GPR_ASSERT(n == 2); - for (i = 0; i < 2; i++) { - census_trace_obj_destroy(active_ops[i]); - } - gpr_free(active_ops); - active_ops = NULL; - - /* End all ops. */ - census_tracing_end_op(id_1); - census_tracing_end_op(id_3); - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops == NULL); - GPR_ASSERT(n == 0); - - census_tracing_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_init_shutdown(); - test_start_op_generates_locally_unique_ids(); - test_get_trace_method_name(); - test_concurrency(); - test_add_method_tag_to_unknown_op_id(); - test_trace_print(); - test_get_active_ops(); - return 0; -} diff --git a/test/core/statistics/trace_test.cc b/test/core/statistics/trace_test.cc new file mode 100644 index 0000000000..63da9f71d3 --- /dev/null +++ b/test/core/statistics/trace_test.cc @@ -0,0 +1,240 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/ext/census/census_interface.h" +#include "src/core/ext/census/census_tracing.h" +#include "src/core/ext/census/census_tracing.h" +#include "test/core/util/test_config.h" + +/* Ensure all possible state transitions are called without causing problem */ +static void test_init_shutdown(void) { + census_tracing_init(); + census_tracing_init(); + census_tracing_shutdown(); + census_tracing_shutdown(); + census_tracing_init(); +} + +static void test_start_op_generates_locally_unique_ids(void) { +/* Check that ids generated within window size of 1000 are unique. + TODO(hongyu): Replace O(n^2) duplicate detection algorithm with O(nlogn) + algorithm. Enhance the test to larger window size (>10^6) */ +#define WINDOW_SIZE 1000 + census_op_id ids[WINDOW_SIZE]; + int i; + census_init(); + for (i = 0; i < WINDOW_SIZE; i++) { + ids[i] = census_tracing_start_op(); + census_tracing_end_op(ids[i]); + } + for (i = 0; i < WINDOW_SIZE - 1; i++) { + int j; + for (j = i + 1; j < WINDOW_SIZE; j++) { + GPR_ASSERT(ids[i].upper != ids[j].upper || ids[i].lower != ids[j].lower); + } + } +#undef WINDOW_SIZE + census_shutdown(); +} + +static void test_get_trace_method_name(void) { + census_op_id id; + const char write_name[] = "service/method"; + census_tracing_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, write_name); + census_internal_lock_trace_store(); + { + const char *read_name = + census_get_trace_method_name(census_get_trace_obj_locked(id)); + GPR_ASSERT(strcmp(read_name, write_name) == 0); + } + census_internal_unlock_trace_store(); + census_tracing_shutdown(); +} + +typedef struct thd_arg { + int num_done; + gpr_cv done; + gpr_mu mu; +} thd_arg; + +static void mimic_trace_op_sequences(void *arg) { + census_op_id id; + const char *method_name = "service_foo/method_bar"; + int i = 0; + const int num_iter = 200; + thd_arg *args = (thd_arg *)arg; + GPR_ASSERT(args != NULL); + gpr_log(GPR_INFO, "Start trace op sequence thread."); + for (i = 0; i < num_iter; i++) { + id = census_tracing_start_op(); + census_add_method_tag(id, method_name); + /* pretend doing 1us work. */ + gpr_sleep_until(GRPC_TIMEOUT_MICROS_TO_DEADLINE(1)); + census_tracing_end_op(id); + } + gpr_log(GPR_INFO, "End trace op sequence thread."); + gpr_mu_lock(&args->mu); + args->num_done += 1; + gpr_cv_broadcast(&args->done); + gpr_mu_unlock(&args->mu); +} + +static void test_concurrency(void) { +#define NUM_THREADS 1000 + gpr_thd_id tid[NUM_THREADS]; + int i = 0; + thd_arg arg; + arg.num_done = 0; + gpr_mu_init(&arg.mu); + gpr_cv_init(&arg.done); + census_tracing_init(); + for (i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); + } + gpr_mu_lock(&arg.mu); + while (arg.num_done < NUM_THREADS) { + gpr_log(GPR_INFO, "num done %d", arg.num_done); + gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&arg.mu); + census_tracing_shutdown(); +#undef NUM_THREADS +} + +static void test_add_method_tag_to_unknown_op_id(void) { + census_op_id unknown_id = {0xDEAD, 0xBEEF}; + int ret = 0; + census_tracing_init(); + ret = census_add_method_tag(unknown_id, "foo"); + GPR_ASSERT(ret != 0); + census_tracing_shutdown(); +} + +static void test_trace_print(void) { + census_op_id id; + int i; + const char *annotation_txt[4] = {"abc", "", "$%^ *()_"}; + char long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 10]; + + memset(long_txt, 'a', GPR_ARRAY_SIZE(long_txt)); + long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 9] = '\0'; + annotation_txt[3] = long_txt; + + census_tracing_init(); + id = census_tracing_start_op(); + /* Adds large number of annotations to each trace */ + for (i = 0; i < 1000; i++) { + census_tracing_print(id, + annotation_txt[i % GPR_ARRAY_SIZE(annotation_txt)]); + } + census_tracing_end_op(id); + + census_tracing_shutdown(); +} + +/* Returns 1 if two ids are equal, otherwise returns 0. */ +static int ids_equal(census_op_id id1, census_op_id id2) { + return (id1.upper == id2.upper) && (id1.lower == id2.lower); +} + +static void test_get_active_ops(void) { + census_op_id id_1, id_2, id_3; + census_trace_obj **active_ops; + const char *annotation_txt[] = {"annotation 1", "a2"}; + int i = 0; + int n = 0; + + gpr_log(GPR_INFO, "test_get_active_ops"); + census_tracing_init(); + /* No active ops before calling start_op(). */ + active_ops = census_get_active_ops(&n); + GPR_ASSERT(active_ops == NULL); + GPR_ASSERT(n == 0); + + /* Starts one op */ + id_1 = census_tracing_start_op(); + census_add_method_tag(id_1, "foo_1"); + active_ops = census_get_active_ops(&n); + GPR_ASSERT(active_ops != NULL); + GPR_ASSERT(n == 1); + GPR_ASSERT(ids_equal(active_ops[0]->id, id_1)); + census_trace_obj_destroy(active_ops[0]); + gpr_free(active_ops); + active_ops = NULL; + + /* Start the second and the third ops */ + id_2 = census_tracing_start_op(); + census_add_method_tag(id_2, "foo_2"); + id_3 = census_tracing_start_op(); + census_add_method_tag(id_3, "foo_3"); + + active_ops = census_get_active_ops(&n); + GPR_ASSERT(n == 3); + for (i = 0; i < 3; i++) { + census_trace_obj_destroy(active_ops[i]); + } + gpr_free(active_ops); + active_ops = NULL; + + /* End the second op and add annotations to the third ops */ + census_tracing_end_op(id_2); + census_tracing_print(id_3, annotation_txt[0]); + census_tracing_print(id_3, annotation_txt[1]); + + active_ops = census_get_active_ops(&n); + GPR_ASSERT(active_ops != NULL); + GPR_ASSERT(n == 2); + for (i = 0; i < 2; i++) { + census_trace_obj_destroy(active_ops[i]); + } + gpr_free(active_ops); + active_ops = NULL; + + /* End all ops. */ + census_tracing_end_op(id_1); + census_tracing_end_op(id_3); + active_ops = census_get_active_ops(&n); + GPR_ASSERT(active_ops == NULL); + GPR_ASSERT(n == 0); + + census_tracing_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_init_shutdown(); + test_start_op_generates_locally_unique_ids(); + test_get_trace_method_name(); + test_concurrency(); + test_add_method_tag_to_unknown_op_id(); + test_trace_print(); + test_get_active_ops(); + return 0; +} diff --git a/test/core/statistics/window_stats_test.c b/test/core/statistics/window_stats_test.c deleted file mode 100644 index 254c14a6a8..0000000000 --- a/test/core/statistics/window_stats_test.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/window_stats.h" -#include -#include -#include -#include "test/core/util/test_config.h" - -typedef struct test_stat { - double value1; - int value2; -} test_stat; - -void add_test_stat(void *base, const void *addme) { - test_stat *b = (test_stat *)base; - const test_stat *a = (const test_stat *)addme; - b->value1 += a->value1; - b->value2 += a->value2; -} - -void add_proportion_test_stat(double p, void *base, const void *addme) { - test_stat *b = (test_stat *)base; - const test_stat *a = (const test_stat *)addme; - b->value1 += p * a->value1; - b->value2 += p * a->value2 + 0.5; /* +0.5 is poor mans (no c99) round() */ -} - -const struct census_window_stats_stat_info kMyStatInfo = { - sizeof(test_stat), NULL, add_test_stat, add_proportion_test_stat}; - -const gpr_timespec kMilliSecInterval = {0, 1000000}; -const gpr_timespec kSecInterval = {1, 0}; -const gpr_timespec kMinInterval = {60, 0}; -const gpr_timespec kHourInterval = {3600, 0}; -const gpr_timespec kPrimeInterval = {0, 101}; - -static int compare_double(double a, double b, double epsilon) { - if (a >= b) { - return (a > b + epsilon) ? 1 : 0; - } else { - return (b > a + epsilon) ? -1 : 0; - } -} - -void empty_test(void) { - census_window_stats_sums result; - const gpr_timespec zero = {0, 0}; - test_stat sum; - struct census_window_stats *stats = - census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - result.statistic = ∑ - census_window_stats_get_sums(stats, zero, &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - census_window_stats_destroy(stats); -} - -void one_interval_test(void) { - const test_stat value = {0.1, 4}; - const double epsilon = 1e10 - 11; - gpr_timespec when = {0, 0}; - census_window_stats_sums result; - test_stat sum; - /* granularity == 5 so width of internal windows should be 12s */ - struct census_window_stats *stats = - census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - /* phase 1: insert a single value at t=0s, and check that various measurement - times result in expected output values */ - census_window_stats_add(stats, when, &value); - result.statistic = ∑ - /* when = 0s, values extracted should be everything */ - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when = 6,30,60s, should be all of the data */ - when.tv_sec = 6; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when == 30s,60s, should be all of the data */ - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - when.tv_sec = 60; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when = 66s, should be half (only take half of bottom bucket) */ - when.tv_sec = 66; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && - sum.value2 == value.value2 / 2); - /* when = 72s, should be completely out of window */ - when.tv_sec = 72; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && - compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); - - /* phase 2: tear down and do as before, but inserting two values */ - census_window_stats_destroy(stats); - stats = census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - when.tv_sec = 0; - when.tv_nsec = 17; - census_window_stats_add(stats, when, &value); - when.tv_sec = 1; - census_window_stats_add(stats, when, &value); - when.tv_sec = 0; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && - compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); - /* time = 3s, 30s, should get all data */ - when.tv_sec = 3; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && - sum.value2 == 2 * value.value2); - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && - sum.value2 == 2 * value.value2); - - /* phase 3: insert into "middle" bucket, and force a shift, pushing out - the two values in bottom bucket */ - when.tv_sec = 30; - census_window_stats_add(stats, when, &value); - when.tv_sec = 76; - census_window_stats_add(stats, when, &value); - when.tv_sec = 0; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - /* half of the single value in the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && - sum.value2 == value.value2 / 2); - when.tv_sec = 74; - census_window_stats_get_sums(stats, when, &result); - /* half of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 1.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 1.5, epsilon) == 0 && - sum.value2 == value.value2 / 2 * 3); - when.tv_sec = 76; - census_window_stats_get_sums(stats, when, &result); - /* >=76s, get all of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && - sum.value2 == value.value2 * 2); - when.tv_sec = 78; - census_window_stats_get_sums(stats, when, &result); - /* half of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && - sum.value2 == value.value2 * 2); - census_window_stats_destroy(stats); -} - -void many_interval_test(void) { - gpr_timespec intervals[4]; - const test_stat value = {123.45, 8}; - const double epsilon = 1e10 - 11; - gpr_timespec when = {3600, 0}; /* one hour */ - census_window_stats_sums result[4]; - test_stat sums[4]; - int i; - struct census_window_stats *stats; - intervals[0] = kMilliSecInterval; - intervals[1] = kSecInterval; - intervals[2] = kMinInterval; - intervals[3] = kHourInterval; - for (i = 0; i < 4; i++) { - result[i].statistic = &sums[i]; - } - stats = census_window_stats_create(4, intervals, 100, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - /* add 10 stats within half of each time range */ - for (i = 0; i < 10; i++) { - when.tv_sec += 180; /* covers 30 min of one hour range */ - census_window_stats_add(stats, when, &value); - } - when.tv_sec += 120; - for (i = 0; i < 10; i++) { - when.tv_sec += 3; /* covers 30 sec of one minute range */ - census_window_stats_add(stats, when, &value); - } - when.tv_sec += 2; - for (i = 0; i < 10; i++) { - when.tv_nsec += 50000000; /* covers 0.5s of 1s range */ - census_window_stats_add(stats, when, &value); - } - when.tv_nsec += 2000000; - for (i = 0; i < 10; i++) { - when.tv_nsec += 50000; /* covers 0.5 ms of 1 ms range */ - census_window_stats_add(stats, when, &value); - } - when.tv_nsec += 20000; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[0].count, 10, epsilon) == 0 && - compare_double(sums[0].value1, value.value1 * 10, epsilon) == 0 && - sums[0].value2 == value.value2 * 10); - when.tv_nsec += 20000000; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[1].count, 20, epsilon) == 0 && - compare_double(sums[1].value1, value.value1 * 20, epsilon) == 0 && - sums[1].value2 == value.value2 * 20); - when.tv_sec += 2; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[2].count, 30, epsilon) == 0 && - compare_double(sums[2].value1, value.value1 * 30, epsilon) == 0 && - sums[2].value2 == value.value2 * 30); - when.tv_sec += 72; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[3].count, 40, epsilon) == 0 && - compare_double(sums[3].value1, value.value1 * 40, epsilon) == 0 && - sums[3].value2 == value.value2 * 40); - census_window_stats_destroy(stats); -} - -void rolling_time_test(void) { - const test_stat value = {0.1, 4}; - gpr_timespec when = {0, 0}; - census_window_stats_sums result; - test_stat sum; - int i; - gpr_timespec increment = {0, 0}; - struct census_window_stats *stats = - census_window_stats_create(1, &kMinInterval, 7, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - for (i = 0; i < 100000; i++) { - increment.tv_nsec = rand() % 100000000; /* up to 1/10th second */ - when = gpr_time_add(when, increment); - census_window_stats_add(stats, when, &value); - } - result.statistic = ∑ - census_window_stats_get_sums(stats, when, &result); - /* With 1/20th second average between samples, we expect 20*60 = 1200 - samples on average. Make sure we are within 100 of that. */ - GPR_ASSERT(compare_double(result.count, 1200, 100) == 0); - census_window_stats_destroy(stats); -} - -#include -void infinite_interval_test(void) { - const test_stat value = {0.1, 4}; - gpr_timespec when = {0, 0}; - census_window_stats_sums result; - test_stat sum; - int i; - const int count = 100000; - gpr_timespec increment = {0, 0}; - struct census_window_stats *stats = census_window_stats_create( - 1, &gpr_inf_future(GPR_CLOCK_REALTIME), 10, &kMyStatInfo); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - for (i = 0; i < count; i++) { - increment.tv_sec = rand() % 21600; /* 6 hours */ - when = gpr_time_add(when, increment); - census_window_stats_add(stats, when, &value); - } - result.statistic = ∑ - census_window_stats_get_sums(stats, when, &result); - /* The only thing it makes sense to compare for "infinite" periods is the - total counts */ - GPR_ASSERT(result.count == count); - census_window_stats_destroy(stats); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - empty_test(); - one_interval_test(); - many_interval_test(); - rolling_time_test(); - infinite_interval_test(); - return 0; -} diff --git a/test/core/statistics/window_stats_test.cc b/test/core/statistics/window_stats_test.cc new file mode 100644 index 0000000000..254c14a6a8 --- /dev/null +++ b/test/core/statistics/window_stats_test.cc @@ -0,0 +1,303 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/census/window_stats.h" +#include +#include +#include +#include "test/core/util/test_config.h" + +typedef struct test_stat { + double value1; + int value2; +} test_stat; + +void add_test_stat(void *base, const void *addme) { + test_stat *b = (test_stat *)base; + const test_stat *a = (const test_stat *)addme; + b->value1 += a->value1; + b->value2 += a->value2; +} + +void add_proportion_test_stat(double p, void *base, const void *addme) { + test_stat *b = (test_stat *)base; + const test_stat *a = (const test_stat *)addme; + b->value1 += p * a->value1; + b->value2 += p * a->value2 + 0.5; /* +0.5 is poor mans (no c99) round() */ +} + +const struct census_window_stats_stat_info kMyStatInfo = { + sizeof(test_stat), NULL, add_test_stat, add_proportion_test_stat}; + +const gpr_timespec kMilliSecInterval = {0, 1000000}; +const gpr_timespec kSecInterval = {1, 0}; +const gpr_timespec kMinInterval = {60, 0}; +const gpr_timespec kHourInterval = {3600, 0}; +const gpr_timespec kPrimeInterval = {0, 101}; + +static int compare_double(double a, double b, double epsilon) { + if (a >= b) { + return (a > b + epsilon) ? 1 : 0; + } else { + return (b > a + epsilon) ? -1 : 0; + } +} + +void empty_test(void) { + census_window_stats_sums result; + const gpr_timespec zero = {0, 0}; + test_stat sum; + struct census_window_stats *stats = + census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); + GPR_ASSERT(stats != NULL); + result.statistic = ∑ + census_window_stats_get_sums(stats, zero, &result); + GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); + census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), &result); + GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); + census_window_stats_destroy(stats); +} + +void one_interval_test(void) { + const test_stat value = {0.1, 4}; + const double epsilon = 1e10 - 11; + gpr_timespec when = {0, 0}; + census_window_stats_sums result; + test_stat sum; + /* granularity == 5 so width of internal windows should be 12s */ + struct census_window_stats *stats = + census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); + GPR_ASSERT(stats != NULL); + /* phase 1: insert a single value at t=0s, and check that various measurement + times result in expected output values */ + census_window_stats_add(stats, when, &value); + result.statistic = ∑ + /* when = 0s, values extracted should be everything */ + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 1, epsilon) == 0 && + compare_double(sum.value1, value.value1, epsilon) == 0 && + sum.value2 == value.value2); + /* when = 6,30,60s, should be all of the data */ + when.tv_sec = 6; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && + compare_double(sum.value1, value.value1, epsilon) == 0 && + sum.value2 == value.value2); + /* when == 30s,60s, should be all of the data */ + when.tv_sec = 30; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && + compare_double(sum.value1, value.value1, epsilon) == 0 && + sum.value2 == value.value2); + when.tv_sec = 60; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && + compare_double(sum.value1, value.value1, epsilon) == 0 && + sum.value2 == value.value2); + /* when = 66s, should be half (only take half of bottom bucket) */ + when.tv_sec = 66; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && + compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && + sum.value2 == value.value2 / 2); + /* when = 72s, should be completely out of window */ + when.tv_sec = 72; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && + compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); + + /* phase 2: tear down and do as before, but inserting two values */ + census_window_stats_destroy(stats); + stats = census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); + GPR_ASSERT(stats != NULL); + when.tv_sec = 0; + when.tv_nsec = 17; + census_window_stats_add(stats, when, &value); + when.tv_sec = 1; + census_window_stats_add(stats, when, &value); + when.tv_sec = 0; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && + compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); + /* time = 3s, 30s, should get all data */ + when.tv_sec = 3; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && + compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && + sum.value2 == 2 * value.value2); + when.tv_sec = 30; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && + compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && + sum.value2 == 2 * value.value2); + + /* phase 3: insert into "middle" bucket, and force a shift, pushing out + the two values in bottom bucket */ + when.tv_sec = 30; + census_window_stats_add(stats, when, &value); + when.tv_sec = 76; + census_window_stats_add(stats, when, &value); + when.tv_sec = 0; + census_window_stats_get_sums(stats, when, &result); + GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); + when.tv_sec = 30; + census_window_stats_get_sums(stats, when, &result); + /* half of the single value in the 30 second bucket */ + GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && + compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && + sum.value2 == value.value2 / 2); + when.tv_sec = 74; + census_window_stats_get_sums(stats, when, &result); + /* half of the 76 second bucket, all of the 30 second bucket */ + GPR_ASSERT(compare_double(result.count, 1.5, epsilon) == 0 && + compare_double(sum.value1, value.value1 * 1.5, epsilon) == 0 && + sum.value2 == value.value2 / 2 * 3); + when.tv_sec = 76; + census_window_stats_get_sums(stats, when, &result); + /* >=76s, get all of the 76 second bucket, all of the 30 second bucket */ + GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && + compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && + sum.value2 == value.value2 * 2); + when.tv_sec = 78; + census_window_stats_get_sums(stats, when, &result); + /* half of the 76 second bucket, all of the 30 second bucket */ + GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && + compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && + sum.value2 == value.value2 * 2); + census_window_stats_destroy(stats); +} + +void many_interval_test(void) { + gpr_timespec intervals[4]; + const test_stat value = {123.45, 8}; + const double epsilon = 1e10 - 11; + gpr_timespec when = {3600, 0}; /* one hour */ + census_window_stats_sums result[4]; + test_stat sums[4]; + int i; + struct census_window_stats *stats; + intervals[0] = kMilliSecInterval; + intervals[1] = kSecInterval; + intervals[2] = kMinInterval; + intervals[3] = kHourInterval; + for (i = 0; i < 4; i++) { + result[i].statistic = &sums[i]; + } + stats = census_window_stats_create(4, intervals, 100, &kMyStatInfo); + GPR_ASSERT(stats != NULL); + /* add 10 stats within half of each time range */ + for (i = 0; i < 10; i++) { + when.tv_sec += 180; /* covers 30 min of one hour range */ + census_window_stats_add(stats, when, &value); + } + when.tv_sec += 120; + for (i = 0; i < 10; i++) { + when.tv_sec += 3; /* covers 30 sec of one minute range */ + census_window_stats_add(stats, when, &value); + } + when.tv_sec += 2; + for (i = 0; i < 10; i++) { + when.tv_nsec += 50000000; /* covers 0.5s of 1s range */ + census_window_stats_add(stats, when, &value); + } + when.tv_nsec += 2000000; + for (i = 0; i < 10; i++) { + when.tv_nsec += 50000; /* covers 0.5 ms of 1 ms range */ + census_window_stats_add(stats, when, &value); + } + when.tv_nsec += 20000; + census_window_stats_get_sums(stats, when, result); + GPR_ASSERT(compare_double(result[0].count, 10, epsilon) == 0 && + compare_double(sums[0].value1, value.value1 * 10, epsilon) == 0 && + sums[0].value2 == value.value2 * 10); + when.tv_nsec += 20000000; + census_window_stats_get_sums(stats, when, result); + GPR_ASSERT(compare_double(result[1].count, 20, epsilon) == 0 && + compare_double(sums[1].value1, value.value1 * 20, epsilon) == 0 && + sums[1].value2 == value.value2 * 20); + when.tv_sec += 2; + census_window_stats_get_sums(stats, when, result); + GPR_ASSERT(compare_double(result[2].count, 30, epsilon) == 0 && + compare_double(sums[2].value1, value.value1 * 30, epsilon) == 0 && + sums[2].value2 == value.value2 * 30); + when.tv_sec += 72; + census_window_stats_get_sums(stats, when, result); + GPR_ASSERT(compare_double(result[3].count, 40, epsilon) == 0 && + compare_double(sums[3].value1, value.value1 * 40, epsilon) == 0 && + sums[3].value2 == value.value2 * 40); + census_window_stats_destroy(stats); +} + +void rolling_time_test(void) { + const test_stat value = {0.1, 4}; + gpr_timespec when = {0, 0}; + census_window_stats_sums result; + test_stat sum; + int i; + gpr_timespec increment = {0, 0}; + struct census_window_stats *stats = + census_window_stats_create(1, &kMinInterval, 7, &kMyStatInfo); + GPR_ASSERT(stats != NULL); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + for (i = 0; i < 100000; i++) { + increment.tv_nsec = rand() % 100000000; /* up to 1/10th second */ + when = gpr_time_add(when, increment); + census_window_stats_add(stats, when, &value); + } + result.statistic = ∑ + census_window_stats_get_sums(stats, when, &result); + /* With 1/20th second average between samples, we expect 20*60 = 1200 + samples on average. Make sure we are within 100 of that. */ + GPR_ASSERT(compare_double(result.count, 1200, 100) == 0); + census_window_stats_destroy(stats); +} + +#include +void infinite_interval_test(void) { + const test_stat value = {0.1, 4}; + gpr_timespec when = {0, 0}; + census_window_stats_sums result; + test_stat sum; + int i; + const int count = 100000; + gpr_timespec increment = {0, 0}; + struct census_window_stats *stats = census_window_stats_create( + 1, &gpr_inf_future(GPR_CLOCK_REALTIME), 10, &kMyStatInfo); + srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); + for (i = 0; i < count; i++) { + increment.tv_sec = rand() % 21600; /* 6 hours */ + when = gpr_time_add(when, increment); + census_window_stats_add(stats, when, &value); + } + result.statistic = ∑ + census_window_stats_get_sums(stats, when, &result); + /* The only thing it makes sense to compare for "infinite" periods is the + total counts */ + GPR_ASSERT(result.count == count); + census_window_stats_destroy(stats); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + empty_test(); + one_interval_test(); + many_interval_test(); + rolling_time_test(); + infinite_interval_test(); + return 0; +} diff --git a/test/core/support/alloc_test.c b/test/core/support/alloc_test.c deleted file mode 100644 index 088ae7d944..0000000000 --- a/test/core/support/alloc_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#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) { - *((intptr_t *)addr) = (intptr_t)0xdeadd00d; -} - -static void test_custom_allocs() { - const gpr_allocation_functions default_fns = gpr_get_allocation_functions(); - intptr_t addr_to_free = 0; - char *i; - gpr_allocation_functions fns = {fake_malloc, NULL, fake_realloc, fake_free}; - - gpr_set_allocation_functions(fns); - GPR_ASSERT((void *)(size_t)0xdeadbeef == gpr_malloc(0xdeadbeef)); - GPR_ASSERT((void *)(size_t)0xcafed00d == gpr_realloc(0, 0xcafed00d)); - - gpr_free(&addr_to_free); - GPR_ASSERT(addr_to_free == (intptr_t)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 *)sizeof(*i) != (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/alloc_test.cc b/test/core/support/alloc_test.cc new file mode 100644 index 0000000000..ef9785a275 --- /dev/null +++ b/test/core/support/alloc_test.cc @@ -0,0 +1,56 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#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) { + *((intptr_t *)addr) = (intptr_t)0xdeadd00d; +} + +static void test_custom_allocs() { + const gpr_allocation_functions default_fns = gpr_get_allocation_functions(); + intptr_t addr_to_free = 0; + char *i; + gpr_allocation_functions fns = {fake_malloc, NULL, fake_realloc, fake_free}; + + gpr_set_allocation_functions(fns); + GPR_ASSERT((void *)(size_t)0xdeadbeef == gpr_malloc(0xdeadbeef)); + GPR_ASSERT((void *)(size_t)0xcafed00d == gpr_realloc(0, 0xcafed00d)); + + gpr_free(&addr_to_free); + GPR_ASSERT(addr_to_free == (intptr_t)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 *)sizeof(*i) != + (i = static_cast(gpr_malloc(sizeof(*i))))); + GPR_ASSERT((void *)2 != (i = static_cast(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/arena_test.c b/test/core/support/arena_test.c deleted file mode 100644 index afb309280f..0000000000 --- a/test/core/support/arena_test.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/support/arena.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); } - -static void test(const char *name, size_t init_size, const size_t *allocs, - size_t nallocs) { - gpr_strvec v; - char *s; - gpr_strvec_init(&v); - gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size); - gpr_strvec_add(&v, s); - for (size_t i = 0; i < nallocs; i++) { - gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]); - gpr_strvec_add(&v, s); - } - gpr_strvec_add(&v, gpr_strdup("}")); - s = gpr_strvec_flatten(&v, NULL); - gpr_strvec_destroy(&v); - gpr_log(GPR_INFO, "%s", s); - gpr_free(s); - - gpr_arena *a = gpr_arena_create(init_size); - void **ps = gpr_zalloc(sizeof(*ps) * nallocs); - for (size_t i = 0; i < nallocs; i++) { - ps[i] = gpr_arena_alloc(a, allocs[i]); - // ensure no duplicate results - for (size_t j = 0; j < i; j++) { - GPR_ASSERT(ps[i] != ps[j]); - } - // ensure writable - memset(ps[i], 1, allocs[i]); - } - gpr_arena_destroy(a); - gpr_free(ps); -} - -#define TEST(name, init_size, ...) \ - static const size_t allocs_##name[] = {__VA_ARGS__}; \ - test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name)) - -#define CONCURRENT_TEST_THREADS 100 - -size_t concurrent_test_iterations() { - if (sizeof(void *) < 8) return 1000; - return 100000; -} - -typedef struct { - gpr_event ev_start; - gpr_arena *arena; -} concurrent_test_args; - -static void concurrent_test_body(void *arg) { - concurrent_test_args *a = arg; - gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME)); - for (size_t i = 0; i < concurrent_test_iterations(); i++) { - *(char *)gpr_arena_alloc(a->arena, 1) = (char)i; - } -} - -static void concurrent_test(void) { - gpr_log(GPR_DEBUG, "concurrent_test"); - - concurrent_test_args args; - gpr_event_init(&args.ev_start); - args.arena = gpr_arena_create(1024); - - gpr_thd_id thds[CONCURRENT_TEST_THREADS]; - - for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt); - } - - gpr_event_set(&args.ev_start, (void *)1); - - for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { - gpr_thd_join(thds[i]); - } - - gpr_arena_destroy(args.arena); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - - test_noop(); - TEST(0_1, 0, 1); - TEST(1_1, 1, 1); - TEST(1_2, 1, 2); - TEST(1_3, 1, 3); - TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); - TEST(6_123, 6, 1, 2, 3); - concurrent_test(); - - return 0; -} diff --git a/test/core/support/arena_test.cc b/test/core/support/arena_test.cc new file mode 100644 index 0000000000..021bd18f5e --- /dev/null +++ b/test/core/support/arena_test.cc @@ -0,0 +1,128 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/arena.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); } + +static void test(const char *name, size_t init_size, const size_t *allocs, + size_t nallocs) { + gpr_strvec v; + char *s; + gpr_strvec_init(&v); + gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size); + gpr_strvec_add(&v, s); + for (size_t i = 0; i < nallocs; i++) { + gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]); + gpr_strvec_add(&v, s); + } + gpr_strvec_add(&v, gpr_strdup("}")); + s = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + gpr_log(GPR_INFO, "%s", s); + gpr_free(s); + + gpr_arena *a = gpr_arena_create(init_size); + void **ps = static_cast(gpr_zalloc(sizeof(*ps) * nallocs)); + for (size_t i = 0; i < nallocs; i++) { + ps[i] = gpr_arena_alloc(a, allocs[i]); + // ensure no duplicate results + for (size_t j = 0; j < i; j++) { + GPR_ASSERT(ps[i] != ps[j]); + } + // ensure writable + memset(ps[i], 1, allocs[i]); + } + gpr_arena_destroy(a); + gpr_free(ps); +} + +#define TEST(name, init_size, ...) \ + static const size_t allocs_##name[] = {__VA_ARGS__}; \ + test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name)) + +#define CONCURRENT_TEST_THREADS 100 + +size_t concurrent_test_iterations() { + if (sizeof(void *) < 8) return 1000; + return 100000; +} + +typedef struct { + gpr_event ev_start; + gpr_arena *arena; +} concurrent_test_args; + +static void concurrent_test_body(void *arg) { + concurrent_test_args *a = static_cast(arg); + gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME)); + for (size_t i = 0; i < concurrent_test_iterations(); i++) { + *(char *)gpr_arena_alloc(a->arena, 1) = (char)i; + } +} + +static void concurrent_test(void) { + gpr_log(GPR_DEBUG, "concurrent_test"); + + concurrent_test_args args; + gpr_event_init(&args.ev_start); + args.arena = gpr_arena_create(1024); + + gpr_thd_id thds[CONCURRENT_TEST_THREADS]; + + for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt); + } + + gpr_event_set(&args.ev_start, (void *)1); + + for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { + gpr_thd_join(thds[i]); + } + + gpr_arena_destroy(args.arena); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + + test_noop(); + TEST(0_1, 0, 1); + TEST(1_1, 1, 1); + TEST(1_2, 1, 2); + TEST(1_3, 1, 3); + TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + TEST(6_123, 6, 1, 2, 3); + concurrent_test(); + + return 0; +} diff --git a/test/core/support/avl_test.c b/test/core/support/avl_test.c deleted file mode 100644 index 37424d6405..0000000000 --- a/test/core/support/avl_test.c +++ /dev/null @@ -1,3659 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include -#include -#include - -#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, void *unused) { - return (*(int *)int1) - (*(int *)int2); -} -static void *int_copy(void *p, void *unused) { return box(*(int *)p); } - -static void destroy(void *p, void *unused) { gpr_free(p); } - -static const gpr_avl_vtable int_int_vtable = {destroy, int_copy, int_compare, - destroy, 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, NULL) == 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) == NULL); - gpr_free(k); -} - -static gpr_avl remove_int(gpr_avl avl, int key) { - int *k = box(key); - avl = gpr_avl_remove(avl, k, NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(2), box(22), NULL); - avl = gpr_avl_add(avl, box(3), box(33), NULL); - check_get(avl, 1, 11); - check_get(avl, 2, 22); - check_get(avl, 3, 33); - check_negget(avl, 4); - gpr_avl_unref(avl, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(4), box(2), NULL); - avl = gpr_avl_add(avl, box(3), box(3), NULL); - 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, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(3), box(2), NULL); - avl = gpr_avl_add(avl, box(4), box(3), NULL); - 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, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(4), box(2), NULL); - avl = gpr_avl_add(avl, box(5), box(3), NULL); - 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, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(5), box(2), NULL); - avl = gpr_avl_add(avl, box(4), box(3), NULL); - 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, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(4), box(2), NULL); - avl = gpr_avl_add(avl, box(3), box(3), NULL); - avl = gpr_avl_add(avl, box(2), box(4), NULL); - avl = gpr_avl_add(avl, box(1), box(5), NULL); - 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, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(1), box(2), NULL); - check_get(avl, 1, 2); - check_negget(avl, 2); - gpr_avl_unref(avl, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(4), box(2), NULL); - avl = gpr_avl_add(avl, box(5), box(3), NULL); - - avl3 = remove_int(gpr_avl_ref(avl, NULL), 3); - avl4 = remove_int(gpr_avl_ref(avl, NULL), 4); - avl5 = remove_int(gpr_avl_ref(avl, NULL), 5); - avln = remove_int(gpr_avl_ref(avl, NULL), 1); - - gpr_avl_unref(avl, NULL); - - check_negget(avl3, 3); - check_get(avl3, 4, 2); - check_get(avl3, 5, 3); - gpr_avl_unref(avl3, NULL); - - check_get(avl4, 3, 1); - check_negget(avl4, 4); - check_get(avl4, 5, 3); - gpr_avl_unref(avl4, NULL); - - check_get(avl5, 3, 1); - check_get(avl5, 4, 2); - check_negget(avl5, 5); - gpr_avl_unref(avl5, NULL); - - check_get(avln, 3, 1); - check_get(avln, 4, 2); - check_get(avln, 5, 3); - gpr_avl_unref(avln, NULL); -} - -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), NULL); - avl = remove_int(avl, 643); - avl = remove_int(avl, 983); - avl = gpr_avl_add(avl, box(985), box(4), NULL); - avl = gpr_avl_add(avl, box(640), box(5), NULL); - avl = gpr_avl_add(avl, box(41), box(6), NULL); - avl = gpr_avl_add(avl, box(112), box(7), NULL); - avl = gpr_avl_add(avl, box(342), box(8), NULL); - avl = remove_int(avl, 1013); - avl = gpr_avl_add(avl, box(434), box(10), NULL); - avl = gpr_avl_add(avl, box(520), box(11), NULL); - avl = gpr_avl_add(avl, box(231), box(12), NULL); - avl = gpr_avl_add(avl, box(852), box(13), NULL); - avl = remove_int(avl, 461); - avl = gpr_avl_add(avl, box(108), box(15), NULL); - avl = gpr_avl_add(avl, box(806), box(16), NULL); - avl = gpr_avl_add(avl, box(827), box(17), NULL); - avl = remove_int(avl, 796); - avl = gpr_avl_add(avl, box(340), box(19), NULL); - avl = gpr_avl_add(avl, box(498), box(20), NULL); - avl = gpr_avl_add(avl, box(203), box(21), NULL); - avl = gpr_avl_add(avl, box(751), box(22), NULL); - avl = gpr_avl_add(avl, box(150), box(23), NULL); - avl = remove_int(avl, 237); - avl = gpr_avl_add(avl, box(830), box(25), NULL); - avl = remove_int(avl, 1007); - avl = remove_int(avl, 394); - avl = gpr_avl_add(avl, box(65), box(28), NULL); - avl = remove_int(avl, 904); - avl = remove_int(avl, 123); - avl = gpr_avl_add(avl, box(238), box(31), NULL); - avl = gpr_avl_add(avl, box(184), box(32), NULL); - avl = remove_int(avl, 331); - avl = gpr_avl_add(avl, box(827), box(34), NULL); - - check_get(avl, 830, 25); - - gpr_avl_unref(avl, NULL); -} - -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), NULL); - avl = remove_int(avl, 415); - avl = gpr_avl_add(avl, box(953), box(3), NULL); - avl = gpr_avl_add(avl, box(101), box(4), NULL); - avl = gpr_avl_add(avl, box(516), box(5), NULL); - avl = gpr_avl_add(avl, box(547), box(6), NULL); - avl = gpr_avl_add(avl, box(467), box(7), NULL); - avl = gpr_avl_add(avl, box(793), box(8), NULL); - avl = remove_int(avl, 190); - avl = gpr_avl_add(avl, box(687), box(10), NULL); - avl = gpr_avl_add(avl, box(242), box(11), NULL); - avl = gpr_avl_add(avl, box(142), box(12), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(622), box(18), NULL); - avl = remove_int(avl, 513); - avl = remove_int(avl, 429); - avl = gpr_avl_add(avl, box(205), box(21), NULL); - avl = remove_int(avl, 663); - avl = remove_int(avl, 953); - avl = remove_int(avl, 892); - avl = gpr_avl_add(avl, box(236), box(25), NULL); - avl = remove_int(avl, 982); - avl = remove_int(avl, 201); - avl = remove_int(avl, 684); - avl = gpr_avl_add(avl, box(572), box(29), NULL); - avl = remove_int(avl, 817); - avl = gpr_avl_add(avl, box(970), box(31), NULL); - avl = remove_int(avl, 347); - avl = remove_int(avl, 574); - avl = gpr_avl_add(avl, box(752), box(34), NULL); - avl = gpr_avl_add(avl, box(670), box(35), NULL); - avl = gpr_avl_add(avl, box(69), box(36), NULL); - avl = remove_int(avl, 111); - avl = remove_int(avl, 523); - avl = gpr_avl_add(avl, box(141), box(39), NULL); - avl = remove_int(avl, 159); - avl = gpr_avl_add(avl, box(947), box(41), NULL); - avl = gpr_avl_add(avl, box(855), box(42), NULL); - avl = remove_int(avl, 218); - avl = remove_int(avl, 6); - avl = gpr_avl_add(avl, box(753), box(45), NULL); - avl = remove_int(avl, 82); - avl = remove_int(avl, 799); - avl = gpr_avl_add(avl, box(572), box(48), NULL); - avl = remove_int(avl, 376); - avl = remove_int(avl, 413); - avl = gpr_avl_add(avl, box(458), box(51), NULL); - avl = remove_int(avl, 897); - avl = gpr_avl_add(avl, box(191), box(53), NULL); - avl = gpr_avl_add(avl, box(609), box(54), NULL); - 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), NULL); - avl = remove_int(avl, 641); - avl = gpr_avl_add(avl, box(462), box(62), NULL); - avl = remove_int(avl, 359); - avl = remove_int(avl, 767); - avl = gpr_avl_add(avl, box(310), box(65), NULL); - avl = remove_int(avl, 757); - avl = remove_int(avl, 639); - avl = remove_int(avl, 314); - avl = gpr_avl_add(avl, box(2), box(69), NULL); - avl = remove_int(avl, 138); - avl = gpr_avl_add(avl, box(669), box(71), NULL); - avl = remove_int(avl, 477); - avl = gpr_avl_add(avl, box(366), box(73), NULL); - avl = gpr_avl_add(avl, box(612), box(74), NULL); - avl = gpr_avl_add(avl, box(106), box(75), NULL); - avl = remove_int(avl, 161); - avl = gpr_avl_add(avl, box(388), box(77), NULL); - avl = gpr_avl_add(avl, box(141), box(78), NULL); - avl = remove_int(avl, 633); - avl = remove_int(avl, 459); - avl = gpr_avl_add(avl, box(40), box(81), NULL); - avl = remove_int(avl, 689); - avl = gpr_avl_add(avl, box(823), box(83), NULL); - avl = remove_int(avl, 485); - avl = gpr_avl_add(avl, box(903), box(85), NULL); - avl = gpr_avl_add(avl, box(592), box(86), NULL); - avl = remove_int(avl, 448); - avl = gpr_avl_add(avl, box(56), box(88), NULL); - avl = remove_int(avl, 333); - avl = gpr_avl_add(avl, box(189), box(90), NULL); - avl = gpr_avl_add(avl, box(103), box(91), NULL); - avl = remove_int(avl, 164); - avl = remove_int(avl, 974); - avl = gpr_avl_add(avl, box(215), box(94), NULL); - avl = remove_int(avl, 189); - avl = remove_int(avl, 504); - avl = gpr_avl_add(avl, box(868), box(97), NULL); - avl = remove_int(avl, 909); - avl = remove_int(avl, 148); - avl = remove_int(avl, 469); - avl = gpr_avl_add(avl, box(994), box(101), NULL); - avl = gpr_avl_add(avl, box(576), box(102), NULL); - avl = remove_int(avl, 82); - avl = remove_int(avl, 209); - avl = gpr_avl_add(avl, box(276), box(105), NULL); - avl = remove_int(avl, 856); - avl = gpr_avl_add(avl, box(750), box(107), NULL); - avl = remove_int(avl, 871); - avl = gpr_avl_add(avl, box(301), box(109), NULL); - avl = remove_int(avl, 260); - avl = remove_int(avl, 737); - avl = remove_int(avl, 719); - avl = gpr_avl_add(avl, box(933), box(113), NULL); - avl = gpr_avl_add(avl, box(225), box(114), NULL); - avl = gpr_avl_add(avl, box(975), box(115), NULL); - avl = gpr_avl_add(avl, box(86), box(116), NULL); - avl = remove_int(avl, 732); - avl = gpr_avl_add(avl, box(340), box(118), NULL); - avl = gpr_avl_add(avl, box(271), box(119), NULL); - avl = remove_int(avl, 206); - avl = gpr_avl_add(avl, box(949), box(121), NULL); - avl = gpr_avl_add(avl, box(927), box(122), NULL); - avl = gpr_avl_add(avl, box(34), box(123), NULL); - avl = gpr_avl_add(avl, box(351), box(124), NULL); - avl = remove_int(avl, 836); - avl = gpr_avl_add(avl, box(825), box(126), NULL); - avl = gpr_avl_add(avl, box(352), box(127), NULL); - avl = remove_int(avl, 107); - avl = remove_int(avl, 101); - avl = gpr_avl_add(avl, box(320), box(130), NULL); - avl = gpr_avl_add(avl, box(3), box(131), NULL); - avl = remove_int(avl, 998); - avl = remove_int(avl, 44); - avl = gpr_avl_add(avl, box(525), box(134), NULL); - avl = gpr_avl_add(avl, box(864), box(135), NULL); - avl = gpr_avl_add(avl, box(863), box(136), NULL); - avl = remove_int(avl, 770); - avl = gpr_avl_add(avl, box(440), box(138), NULL); - avl = remove_int(avl, 516); - avl = gpr_avl_add(avl, box(116), box(140), NULL); - avl = remove_int(avl, 380); - avl = gpr_avl_add(avl, box(878), box(142), NULL); - avl = remove_int(avl, 439); - avl = gpr_avl_add(avl, box(994), box(144), NULL); - avl = remove_int(avl, 294); - avl = remove_int(avl, 593); - avl = gpr_avl_add(avl, box(696), box(147), NULL); - avl = remove_int(avl, 8); - avl = gpr_avl_add(avl, box(881), box(149), NULL); - avl = remove_int(avl, 32); - avl = remove_int(avl, 242); - avl = gpr_avl_add(avl, box(487), box(152), NULL); - avl = gpr_avl_add(avl, box(637), box(153), NULL); - avl = gpr_avl_add(avl, box(793), box(154), NULL); - avl = gpr_avl_add(avl, box(696), box(155), NULL); - avl = remove_int(avl, 458); - avl = gpr_avl_add(avl, box(828), box(157), NULL); - avl = remove_int(avl, 784); - avl = remove_int(avl, 274); - avl = gpr_avl_add(avl, box(783), box(160), NULL); - avl = remove_int(avl, 21); - avl = gpr_avl_add(avl, box(866), box(162), NULL); - avl = remove_int(avl, 919); - avl = gpr_avl_add(avl, box(435), box(164), NULL); - avl = remove_int(avl, 385); - avl = gpr_avl_add(avl, box(475), box(166), NULL); - avl = remove_int(avl, 339); - avl = gpr_avl_add(avl, box(615), box(168), NULL); - avl = remove_int(avl, 866); - avl = remove_int(avl, 82); - avl = remove_int(avl, 271); - avl = gpr_avl_add(avl, box(590), box(172), NULL); - avl = gpr_avl_add(avl, box(852), box(173), NULL); - avl = remove_int(avl, 318); - avl = remove_int(avl, 82); - avl = gpr_avl_add(avl, box(672), box(176), NULL); - avl = remove_int(avl, 430); - avl = gpr_avl_add(avl, box(821), box(178), NULL); - avl = gpr_avl_add(avl, box(365), box(179), NULL); - avl = remove_int(avl, 78); - avl = gpr_avl_add(avl, box(700), box(181), NULL); - avl = gpr_avl_add(avl, box(353), box(182), NULL); - avl = remove_int(avl, 492); - avl = gpr_avl_add(avl, box(991), box(184), NULL); - avl = remove_int(avl, 330); - avl = gpr_avl_add(avl, box(873), box(186), NULL); - avl = remove_int(avl, 589); - avl = gpr_avl_add(avl, box(676), box(188), NULL); - avl = gpr_avl_add(avl, box(790), box(189), NULL); - avl = remove_int(avl, 521); - avl = remove_int(avl, 47); - avl = gpr_avl_add(avl, box(976), box(192), NULL); - avl = gpr_avl_add(avl, box(683), box(193), NULL); - avl = remove_int(avl, 803); - avl = remove_int(avl, 1006); - avl = gpr_avl_add(avl, box(775), box(196), NULL); - avl = gpr_avl_add(avl, box(411), box(197), NULL); - avl = gpr_avl_add(avl, box(697), box(198), NULL); - avl = remove_int(avl, 50); - avl = gpr_avl_add(avl, box(213), box(200), NULL); - avl = remove_int(avl, 714); - avl = gpr_avl_add(avl, box(981), box(202), NULL); - avl = gpr_avl_add(avl, box(502), box(203), NULL); - avl = gpr_avl_add(avl, box(697), box(204), NULL); - avl = gpr_avl_add(avl, box(603), box(205), NULL); - avl = gpr_avl_add(avl, box(117), box(206), NULL); - avl = remove_int(avl, 363); - avl = gpr_avl_add(avl, box(104), box(208), NULL); - avl = remove_int(avl, 842); - avl = gpr_avl_add(avl, box(48), box(210), NULL); - avl = remove_int(avl, 764); - avl = gpr_avl_add(avl, box(482), box(212), NULL); - avl = gpr_avl_add(avl, box(928), box(213), NULL); - avl = gpr_avl_add(avl, box(30), box(214), NULL); - avl = gpr_avl_add(avl, box(820), box(215), NULL); - avl = gpr_avl_add(avl, box(334), box(216), NULL); - avl = remove_int(avl, 306); - avl = gpr_avl_add(avl, box(789), box(218), NULL); - avl = remove_int(avl, 924); - avl = gpr_avl_add(avl, box(53), box(220), NULL); - avl = remove_int(avl, 657); - avl = gpr_avl_add(avl, box(130), box(222), NULL); - avl = gpr_avl_add(avl, box(239), box(223), NULL); - avl = remove_int(avl, 20); - avl = gpr_avl_add(avl, box(117), box(225), NULL); - avl = remove_int(avl, 882); - avl = remove_int(avl, 891); - avl = gpr_avl_add(avl, box(9), box(228), NULL); - avl = gpr_avl_add(avl, box(496), box(229), NULL); - avl = gpr_avl_add(avl, box(750), box(230), NULL); - avl = gpr_avl_add(avl, box(283), box(231), NULL); - avl = gpr_avl_add(avl, box(802), box(232), NULL); - avl = remove_int(avl, 352); - avl = gpr_avl_add(avl, box(374), box(234), NULL); - avl = gpr_avl_add(avl, box(6), box(235), NULL); - avl = gpr_avl_add(avl, box(756), box(236), NULL); - avl = gpr_avl_add(avl, box(597), box(237), NULL); - avl = gpr_avl_add(avl, box(661), box(238), NULL); - avl = remove_int(avl, 96); - avl = gpr_avl_add(avl, box(894), box(240), NULL); - avl = remove_int(avl, 749); - avl = gpr_avl_add(avl, box(71), box(242), NULL); - avl = remove_int(avl, 68); - avl = gpr_avl_add(avl, box(388), box(244), NULL); - avl = remove_int(avl, 119); - avl = remove_int(avl, 856); - avl = gpr_avl_add(avl, box(176), box(247), NULL); - avl = gpr_avl_add(avl, box(993), box(248), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(484), box(258), NULL); - avl = remove_int(avl, 837); - avl = gpr_avl_add(avl, box(388), box(260), NULL); - avl = remove_int(avl, 987); - avl = gpr_avl_add(avl, box(336), box(262), NULL); - avl = remove_int(avl, 855); - avl = gpr_avl_add(avl, box(668), box(264), NULL); - avl = remove_int(avl, 648); - avl = gpr_avl_add(avl, box(193), box(266), NULL); - avl = remove_int(avl, 939); - avl = gpr_avl_add(avl, box(740), box(268), NULL); - avl = gpr_avl_add(avl, box(503), box(269), NULL); - avl = gpr_avl_add(avl, box(765), box(270), NULL); - avl = remove_int(avl, 924); - avl = remove_int(avl, 513); - avl = gpr_avl_add(avl, box(161), box(273), NULL); - avl = gpr_avl_add(avl, box(502), box(274), NULL); - avl = gpr_avl_add(avl, box(846), box(275), NULL); - avl = remove_int(avl, 931); - avl = gpr_avl_add(avl, box(87), box(277), NULL); - avl = gpr_avl_add(avl, box(949), box(278), NULL); - avl = gpr_avl_add(avl, box(548), box(279), NULL); - avl = gpr_avl_add(avl, box(951), box(280), NULL); - avl = remove_int(avl, 1018); - avl = remove_int(avl, 568); - avl = gpr_avl_add(avl, box(138), box(283), NULL); - avl = gpr_avl_add(avl, box(202), box(284), NULL); - avl = gpr_avl_add(avl, box(157), box(285), NULL); - avl = gpr_avl_add(avl, box(264), box(286), NULL); - avl = gpr_avl_add(avl, box(370), box(287), NULL); - 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), NULL); - avl = remove_int(avl, 354); - avl = gpr_avl_add(avl, box(134), box(297), NULL); - avl = remove_int(avl, 781); - avl = remove_int(avl, 183); - avl = gpr_avl_add(avl, box(914), box(300), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(699), box(307), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(265), box(315), NULL); - avl = gpr_avl_add(avl, box(268), box(316), NULL); - avl = gpr_avl_add(avl, box(103), box(317), NULL); - avl = gpr_avl_add(avl, box(440), box(318), NULL); - avl = remove_int(avl, 777); - avl = gpr_avl_add(avl, box(670), box(320), NULL); - avl = remove_int(avl, 506); - avl = remove_int(avl, 487); - avl = gpr_avl_add(avl, box(421), box(323), NULL); - avl = remove_int(avl, 514); - avl = gpr_avl_add(avl, box(701), box(325), NULL); - avl = remove_int(avl, 949); - avl = remove_int(avl, 872); - avl = remove_int(avl, 139); - avl = gpr_avl_add(avl, box(781), box(329), NULL); - avl = gpr_avl_add(avl, box(543), box(330), NULL); - avl = gpr_avl_add(avl, box(147), box(331), NULL); - avl = remove_int(avl, 190); - avl = gpr_avl_add(avl, box(453), box(333), NULL); - 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), NULL); - avl = remove_int(avl, 812); - avl = gpr_avl_add(avl, box(431), box(340), NULL); - avl = gpr_avl_add(avl, box(8), box(341), NULL); - avl = remove_int(avl, 843); - avl = gpr_avl_add(avl, box(831), box(343), NULL); - avl = remove_int(avl, 472); - avl = remove_int(avl, 157); - avl = gpr_avl_add(avl, box(612), box(346), NULL); - avl = gpr_avl_add(avl, box(802), box(347), NULL); - avl = remove_int(avl, 554); - avl = gpr_avl_add(avl, box(409), box(349), NULL); - avl = gpr_avl_add(avl, box(439), box(350), NULL); - avl = gpr_avl_add(avl, box(725), box(351), NULL); - avl = gpr_avl_add(avl, box(568), box(352), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(950), box(358), NULL); - avl = gpr_avl_add(avl, box(532), box(359), NULL); - avl = gpr_avl_add(avl, box(832), box(360), NULL); - avl = remove_int(avl, 390); - avl = gpr_avl_add(avl, box(993), box(362), NULL); - avl = remove_int(avl, 198); - avl = remove_int(avl, 401); - avl = gpr_avl_add(avl, box(316), box(365), NULL); - avl = remove_int(avl, 843); - avl = gpr_avl_add(avl, box(541), box(367), NULL); - avl = gpr_avl_add(avl, box(505), box(368), NULL); - avl = remove_int(avl, 445); - avl = remove_int(avl, 256); - avl = gpr_avl_add(avl, box(232), box(371), NULL); - avl = remove_int(avl, 577); - avl = remove_int(avl, 558); - avl = gpr_avl_add(avl, box(910), box(374), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(655), box(381), NULL); - avl = remove_int(avl, 557); - avl = remove_int(avl, 102); - avl = remove_int(avl, 165); - avl = gpr_avl_add(avl, box(191), box(385), NULL); - avl = remove_int(avl, 30); - avl = gpr_avl_add(avl, box(406), box(387), NULL); - avl = gpr_avl_add(avl, box(66), box(388), NULL); - avl = gpr_avl_add(avl, box(87), box(389), NULL); - avl = remove_int(avl, 7); - avl = remove_int(avl, 671); - avl = gpr_avl_add(avl, box(234), box(392), NULL); - avl = remove_int(avl, 463); - avl = gpr_avl_add(avl, box(75), box(394), NULL); - avl = gpr_avl_add(avl, box(487), box(395), NULL); - avl = remove_int(avl, 203); - avl = gpr_avl_add(avl, box(711), box(397), NULL); - avl = remove_int(avl, 291); - avl = remove_int(avl, 798); - avl = remove_int(avl, 337); - avl = gpr_avl_add(avl, box(877), box(401), NULL); - avl = gpr_avl_add(avl, box(388), box(402), NULL); - avl = remove_int(avl, 975); - avl = gpr_avl_add(avl, box(200), box(404), NULL); - avl = gpr_avl_add(avl, box(408), box(405), NULL); - avl = gpr_avl_add(avl, box(3), box(406), NULL); - avl = gpr_avl_add(avl, box(971), box(407), NULL); - 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), NULL); - avl = remove_int(avl, 14); - avl = remove_int(avl, 364); - avl = gpr_avl_add(avl, box(215), box(415), NULL); - avl = remove_int(avl, 778); - avl = remove_int(avl, 45); - avl = gpr_avl_add(avl, box(328), box(418), NULL); - avl = gpr_avl_add(avl, box(597), box(419), NULL); - avl = remove_int(avl, 34); - avl = gpr_avl_add(avl, box(736), box(421), NULL); - avl = remove_int(avl, 37); - avl = gpr_avl_add(avl, box(275), box(423), NULL); - avl = gpr_avl_add(avl, box(70), box(424), NULL); - avl = gpr_avl_add(avl, box(771), box(425), NULL); - avl = remove_int(avl, 536); - avl = remove_int(avl, 421); - avl = gpr_avl_add(avl, box(186), box(428), NULL); - avl = gpr_avl_add(avl, box(788), box(429), NULL); - avl = gpr_avl_add(avl, box(224), box(430), NULL); - avl = remove_int(avl, 228); - avl = gpr_avl_add(avl, box(48), box(432), NULL); - avl = gpr_avl_add(avl, box(120), box(433), NULL); - avl = gpr_avl_add(avl, box(269), box(434), NULL); - avl = gpr_avl_add(avl, box(904), box(435), NULL); - avl = remove_int(avl, 699); - avl = gpr_avl_add(avl, box(340), box(437), NULL); - avl = remove_int(avl, 276); - avl = gpr_avl_add(avl, box(591), box(439), NULL); - avl = gpr_avl_add(avl, box(778), box(440), NULL); - avl = remove_int(avl, 490); - avl = remove_int(avl, 973); - avl = gpr_avl_add(avl, box(294), box(443), NULL); - avl = gpr_avl_add(avl, box(323), box(444), NULL); - avl = remove_int(avl, 685); - avl = gpr_avl_add(avl, box(38), box(446), NULL); - avl = gpr_avl_add(avl, box(525), box(447), NULL); - avl = remove_int(avl, 162); - avl = gpr_avl_add(avl, box(462), box(449), NULL); - avl = gpr_avl_add(avl, box(340), box(450), NULL); - avl = remove_int(avl, 734); - avl = remove_int(avl, 959); - avl = gpr_avl_add(avl, box(752), box(453), NULL); - avl = gpr_avl_add(avl, box(667), box(454), NULL); - avl = remove_int(avl, 558); - avl = remove_int(avl, 657); - avl = gpr_avl_add(avl, box(711), box(457), NULL); - avl = remove_int(avl, 937); - avl = gpr_avl_add(avl, box(741), box(459), NULL); - avl = gpr_avl_add(avl, box(40), box(460), NULL); - avl = remove_int(avl, 784); - avl = gpr_avl_add(avl, box(292), box(462), NULL); - avl = remove_int(avl, 164); - avl = remove_int(avl, 931); - avl = remove_int(avl, 886); - avl = gpr_avl_add(avl, box(968), box(466), NULL); - avl = remove_int(avl, 263); - avl = gpr_avl_add(avl, box(647), box(468), NULL); - avl = gpr_avl_add(avl, box(92), box(469), NULL); - avl = remove_int(avl, 310); - avl = gpr_avl_add(avl, box(711), box(471), NULL); - avl = gpr_avl_add(avl, box(675), box(472), NULL); - avl = remove_int(avl, 549); - avl = gpr_avl_add(avl, box(380), box(474), NULL); - avl = remove_int(avl, 825); - avl = gpr_avl_add(avl, box(668), box(476), NULL); - avl = remove_int(avl, 498); - avl = gpr_avl_add(avl, box(870), box(478), NULL); - avl = gpr_avl_add(avl, box(391), box(479), NULL); - avl = gpr_avl_add(avl, box(264), box(480), NULL); - 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), NULL); - avl = remove_int(avl, 849); - avl = remove_int(avl, 47); - avl = gpr_avl_add(avl, box(299), box(490), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(524), box(496), NULL); - avl = remove_int(avl, 210); - avl = remove_int(avl, 299); - avl = gpr_avl_add(avl, box(823), box(499), NULL); - avl = remove_int(avl, 479); - avl = remove_int(avl, 96); - avl = remove_int(avl, 1013); - avl = gpr_avl_add(avl, box(768), box(503), NULL); - avl = remove_int(avl, 638); - avl = remove_int(avl, 20); - avl = gpr_avl_add(avl, box(663), box(506), NULL); - avl = remove_int(avl, 882); - avl = gpr_avl_add(avl, box(745), box(508), NULL); - avl = remove_int(avl, 352); - avl = gpr_avl_add(avl, box(10), box(510), NULL); - avl = remove_int(avl, 484); - avl = gpr_avl_add(avl, box(420), box(512), NULL); - avl = gpr_avl_add(avl, box(884), box(513), NULL); - avl = gpr_avl_add(avl, box(993), box(514), NULL); - avl = gpr_avl_add(avl, box(251), box(515), NULL); - avl = remove_int(avl, 222); - avl = gpr_avl_add(avl, box(734), box(517), NULL); - avl = gpr_avl_add(avl, box(952), box(518), NULL); - 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), NULL); - avl = remove_int(avl, 897); - avl = gpr_avl_add(avl, box(719), box(526), NULL); - avl = gpr_avl_add(avl, box(622), box(527), NULL); - avl = remove_int(avl, 28); - avl = remove_int(avl, 836); - avl = remove_int(avl, 142); - avl = gpr_avl_add(avl, box(445), box(531), NULL); - avl = gpr_avl_add(avl, box(410), box(532), NULL); - avl = remove_int(avl, 575); - avl = gpr_avl_add(avl, box(634), box(534), NULL); - avl = gpr_avl_add(avl, box(906), box(535), NULL); - avl = remove_int(avl, 649); - avl = gpr_avl_add(avl, box(813), box(537), NULL); - avl = remove_int(avl, 702); - avl = remove_int(avl, 732); - avl = gpr_avl_add(avl, box(105), box(540), NULL); - avl = gpr_avl_add(avl, box(867), box(541), NULL); - avl = remove_int(avl, 964); - avl = remove_int(avl, 941); - avl = gpr_avl_add(avl, box(947), box(544), NULL); - avl = remove_int(avl, 990); - avl = gpr_avl_add(avl, box(816), box(546), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(786), box(552), NULL); - avl = gpr_avl_add(avl, box(526), box(553), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(749), box(559), NULL); - avl = gpr_avl_add(avl, box(194), box(560), NULL); - avl = remove_int(avl, 517); - avl = gpr_avl_add(avl, box(102), box(562), NULL); - avl = remove_int(avl, 189); - avl = gpr_avl_add(avl, box(927), box(564), NULL); - avl = remove_int(avl, 846); - avl = remove_int(avl, 130); - avl = gpr_avl_add(avl, box(694), box(567), NULL); - avl = remove_int(avl, 750); - avl = gpr_avl_add(avl, box(357), box(569), NULL); - avl = remove_int(avl, 431); - avl = remove_int(avl, 91); - avl = gpr_avl_add(avl, box(640), box(572), NULL); - avl = remove_int(avl, 4); - avl = gpr_avl_add(avl, box(81), box(574), NULL); - avl = gpr_avl_add(avl, box(595), box(575), NULL); - avl = remove_int(avl, 444); - avl = remove_int(avl, 262); - avl = remove_int(avl, 11); - avl = gpr_avl_add(avl, box(192), box(579), NULL); - avl = gpr_avl_add(avl, box(158), box(580), NULL); - avl = remove_int(avl, 401); - avl = remove_int(avl, 918); - avl = gpr_avl_add(avl, box(180), box(583), NULL); - avl = remove_int(avl, 268); - avl = gpr_avl_add(avl, box(1012), box(585), NULL); - avl = gpr_avl_add(avl, box(90), box(586), NULL); - avl = gpr_avl_add(avl, box(946), box(587), NULL); - avl = remove_int(avl, 719); - avl = gpr_avl_add(avl, box(874), box(589), NULL); - avl = gpr_avl_add(avl, box(679), box(590), NULL); - avl = remove_int(avl, 53); - avl = remove_int(avl, 534); - avl = gpr_avl_add(avl, box(646), box(593), NULL); - avl = gpr_avl_add(avl, box(767), box(594), NULL); - avl = gpr_avl_add(avl, box(460), box(595), NULL); - avl = gpr_avl_add(avl, box(852), box(596), NULL); - avl = gpr_avl_add(avl, box(189), box(597), NULL); - avl = remove_int(avl, 932); - avl = remove_int(avl, 366); - avl = remove_int(avl, 907); - avl = gpr_avl_add(avl, box(875), box(601), NULL); - avl = gpr_avl_add(avl, box(434), box(602), NULL); - avl = gpr_avl_add(avl, box(704), box(603), NULL); - avl = gpr_avl_add(avl, box(724), box(604), NULL); - avl = gpr_avl_add(avl, box(930), box(605), NULL); - avl = gpr_avl_add(avl, box(1000), box(606), NULL); - avl = remove_int(avl, 479); - avl = gpr_avl_add(avl, box(275), box(608), NULL); - avl = remove_int(avl, 32); - avl = gpr_avl_add(avl, box(939), box(610), NULL); - avl = remove_int(avl, 943); - avl = remove_int(avl, 329); - avl = gpr_avl_add(avl, box(490), box(613), NULL); - 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), NULL); - avl = remove_int(avl, 751); - avl = gpr_avl_add(avl, box(568), box(620), NULL); - avl = gpr_avl_add(avl, box(120), box(621), NULL); - avl = gpr_avl_add(avl, box(617), box(622), NULL); - avl = gpr_avl_add(avl, box(32), box(623), NULL); - avl = remove_int(avl, 701); - avl = gpr_avl_add(avl, box(910), box(625), NULL); - 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), NULL); - 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), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(6), box(642), NULL); - avl = gpr_avl_add(avl, box(680), box(643), NULL); - avl = remove_int(avl, 741); - avl = remove_int(avl, 309); - avl = remove_int(avl, 272); - avl = gpr_avl_add(avl, box(249), box(647), NULL); - avl = remove_int(avl, 97); - avl = remove_int(avl, 850); - avl = gpr_avl_add(avl, box(915), box(650), NULL); - avl = gpr_avl_add(avl, box(816), box(651), NULL); - avl = gpr_avl_add(avl, box(45), box(652), NULL); - avl = gpr_avl_add(avl, box(168), box(653), NULL); - avl = remove_int(avl, 153); - avl = remove_int(avl, 239); - avl = gpr_avl_add(avl, box(684), box(656), NULL); - avl = gpr_avl_add(avl, box(208), box(657), NULL); - avl = gpr_avl_add(avl, box(681), box(658), NULL); - avl = gpr_avl_add(avl, box(609), box(659), NULL); - avl = gpr_avl_add(avl, box(645), box(660), NULL); - avl = remove_int(avl, 799); - avl = gpr_avl_add(avl, box(955), box(662), NULL); - avl = gpr_avl_add(avl, box(946), box(663), NULL); - avl = gpr_avl_add(avl, box(744), box(664), NULL); - avl = gpr_avl_add(avl, box(201), box(665), NULL); - avl = gpr_avl_add(avl, box(136), box(666), NULL); - avl = remove_int(avl, 357); - avl = gpr_avl_add(avl, box(974), box(668), NULL); - avl = remove_int(avl, 485); - avl = gpr_avl_add(avl, box(1009), box(670), NULL); - avl = gpr_avl_add(avl, box(517), box(671), NULL); - avl = remove_int(avl, 491); - avl = gpr_avl_add(avl, box(336), box(673), NULL); - avl = gpr_avl_add(avl, box(589), box(674), NULL); - 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), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(25), box(685), NULL); - avl = remove_int(avl, 278); - avl = gpr_avl_add(avl, box(191), box(687), NULL); - avl = remove_int(avl, 243); - avl = remove_int(avl, 918); - avl = remove_int(avl, 449); - avl = gpr_avl_add(avl, box(19), box(691), NULL); - avl = gpr_avl_add(avl, box(762), box(692), NULL); - avl = gpr_avl_add(avl, box(13), box(693), NULL); - avl = gpr_avl_add(avl, box(151), box(694), NULL); - avl = gpr_avl_add(avl, box(152), box(695), NULL); - avl = gpr_avl_add(avl, box(793), box(696), NULL); - avl = remove_int(avl, 862); - avl = remove_int(avl, 890); - avl = gpr_avl_add(avl, box(687), box(699), NULL); - avl = gpr_avl_add(avl, box(509), box(700), NULL); - avl = gpr_avl_add(avl, box(973), box(701), NULL); - avl = remove_int(avl, 230); - avl = gpr_avl_add(avl, box(532), box(703), NULL); - avl = remove_int(avl, 668); - avl = gpr_avl_add(avl, box(281), box(705), NULL); - avl = gpr_avl_add(avl, box(867), box(706), NULL); - avl = gpr_avl_add(avl, box(359), box(707), NULL); - avl = remove_int(avl, 425); - avl = gpr_avl_add(avl, box(691), box(709), NULL); - avl = gpr_avl_add(avl, box(163), box(710), NULL); - avl = gpr_avl_add(avl, box(502), box(711), NULL); - avl = remove_int(avl, 674); - avl = gpr_avl_add(avl, box(697), box(713), NULL); - avl = remove_int(avl, 271); - avl = gpr_avl_add(avl, box(968), box(715), NULL); - avl = gpr_avl_add(avl, box(48), box(716), NULL); - avl = remove_int(avl, 543); - avl = gpr_avl_add(avl, box(35), box(718), NULL); - avl = gpr_avl_add(avl, box(751), box(719), NULL); - avl = gpr_avl_add(avl, box(478), box(720), NULL); - avl = remove_int(avl, 797); - avl = remove_int(avl, 309); - avl = gpr_avl_add(avl, box(927), box(723), NULL); - avl = remove_int(avl, 504); - avl = gpr_avl_add(avl, box(286), box(725), NULL); - avl = gpr_avl_add(avl, box(413), box(726), NULL); - avl = gpr_avl_add(avl, box(599), box(727), NULL); - avl = remove_int(avl, 105); - avl = remove_int(avl, 605); - avl = gpr_avl_add(avl, box(632), box(730), NULL); - avl = gpr_avl_add(avl, box(133), box(731), NULL); - avl = remove_int(avl, 443); - avl = gpr_avl_add(avl, box(958), box(733), NULL); - avl = gpr_avl_add(avl, box(729), box(734), NULL); - avl = remove_int(avl, 158); - avl = gpr_avl_add(avl, box(694), box(736), NULL); - avl = gpr_avl_add(avl, box(505), box(737), NULL); - avl = remove_int(avl, 63); - avl = remove_int(avl, 714); - avl = gpr_avl_add(avl, box(1002), box(740), NULL); - avl = remove_int(avl, 211); - avl = gpr_avl_add(avl, box(765), box(742), NULL); - avl = gpr_avl_add(avl, box(455), box(743), NULL); - avl = remove_int(avl, 59); - avl = remove_int(avl, 224); - avl = gpr_avl_add(avl, box(586), box(746), NULL); - avl = gpr_avl_add(avl, box(348), box(747), NULL); - avl = remove_int(avl, 10); - avl = remove_int(avl, 484); - avl = gpr_avl_add(avl, box(968), box(750), NULL); - avl = gpr_avl_add(avl, box(923), box(751), NULL); - avl = remove_int(avl, 573); - avl = remove_int(avl, 617); - avl = gpr_avl_add(avl, box(812), box(754), NULL); - avl = gpr_avl_add(avl, box(179), box(755), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(927), box(761), NULL); - avl = gpr_avl_add(avl, box(454), box(762), NULL); - avl = gpr_avl_add(avl, box(217), box(763), NULL); - avl = remove_int(avl, 534); - avl = gpr_avl_add(avl, box(180), box(765), NULL); - avl = gpr_avl_add(avl, box(319), box(766), NULL); - avl = remove_int(avl, 92); - avl = gpr_avl_add(avl, box(483), box(768), NULL); - 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), NULL); - avl = remove_int(avl, 807); - avl = gpr_avl_add(avl, box(463), box(775), NULL); - avl = gpr_avl_add(avl, box(271), box(776), NULL); - avl = gpr_avl_add(avl, box(644), box(777), NULL); - avl = remove_int(avl, 618); - avl = gpr_avl_add(avl, box(166), box(779), NULL); - avl = gpr_avl_add(avl, box(538), box(780), NULL); - avl = remove_int(avl, 606); - avl = gpr_avl_add(avl, box(425), box(782), NULL); - avl = remove_int(avl, 725); - avl = remove_int(avl, 383); - avl = gpr_avl_add(avl, box(155), box(785), NULL); - avl = remove_int(avl, 889); - avl = gpr_avl_add(avl, box(653), box(787), NULL); - avl = remove_int(avl, 386); - avl = gpr_avl_add(avl, box(142), box(789), NULL); - avl = remove_int(avl, 107); - avl = remove_int(avl, 603); - avl = remove_int(avl, 971); - avl = gpr_avl_add(avl, box(80), box(793), NULL); - avl = gpr_avl_add(avl, box(61), box(794), NULL); - avl = gpr_avl_add(avl, box(693), box(795), NULL); - avl = gpr_avl_add(avl, box(592), box(796), NULL); - avl = gpr_avl_add(avl, box(433), box(797), NULL); - avl = gpr_avl_add(avl, box(973), box(798), NULL); - avl = remove_int(avl, 901); - avl = remove_int(avl, 340); - avl = remove_int(avl, 709); - avl = gpr_avl_add(avl, box(224), box(802), NULL); - avl = remove_int(avl, 120); - avl = remove_int(avl, 271); - avl = gpr_avl_add(avl, box(780), box(805), NULL); - avl = gpr_avl_add(avl, box(867), box(806), NULL); - avl = gpr_avl_add(avl, box(756), box(807), NULL); - avl = gpr_avl_add(avl, box(583), box(808), NULL); - avl = gpr_avl_add(avl, box(356), box(809), NULL); - avl = gpr_avl_add(avl, box(58), box(810), NULL); - avl = remove_int(avl, 219); - avl = gpr_avl_add(avl, box(301), box(812), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(479), box(822), NULL); - avl = gpr_avl_add(avl, box(323), box(823), NULL); - avl = gpr_avl_add(avl, box(802), box(824), NULL); - avl = remove_int(avl, 682); - avl = remove_int(avl, 705); - avl = remove_int(avl, 487); - avl = gpr_avl_add(avl, box(530), box(828), NULL); - avl = gpr_avl_add(avl, box(232), box(829), NULL); - avl = remove_int(avl, 627); - avl = gpr_avl_add(avl, box(396), box(831), NULL); - avl = gpr_avl_add(avl, box(61), box(832), NULL); - avl = gpr_avl_add(avl, box(932), box(833), NULL); - avl = gpr_avl_add(avl, box(108), box(834), NULL); - avl = gpr_avl_add(avl, box(524), box(835), NULL); - avl = remove_int(avl, 390); - avl = remove_int(avl, 307); - avl = gpr_avl_add(avl, box(722), box(838), NULL); - avl = gpr_avl_add(avl, box(907), box(839), NULL); - avl = remove_int(avl, 286); - avl = remove_int(avl, 337); - avl = remove_int(avl, 443); - avl = gpr_avl_add(avl, box(973), box(843), NULL); - avl = remove_int(avl, 930); - avl = remove_int(avl, 242); - avl = gpr_avl_add(avl, box(997), box(846), NULL); - avl = gpr_avl_add(avl, box(689), box(847), NULL); - avl = remove_int(avl, 318); - avl = gpr_avl_add(avl, box(703), box(849), NULL); - avl = gpr_avl_add(avl, box(868), box(850), NULL); - avl = gpr_avl_add(avl, box(200), box(851), NULL); - avl = gpr_avl_add(avl, box(960), box(852), NULL); - avl = gpr_avl_add(avl, box(80), box(853), NULL); - avl = remove_int(avl, 113); - avl = gpr_avl_add(avl, box(135), box(855), NULL); - avl = remove_int(avl, 529); - avl = gpr_avl_add(avl, box(366), box(857), NULL); - avl = remove_int(avl, 272); - avl = gpr_avl_add(avl, box(921), box(859), NULL); - avl = remove_int(avl, 497); - avl = gpr_avl_add(avl, box(712), box(861), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(29), box(867), NULL); - avl = gpr_avl_add(avl, box(180), box(868), NULL); - avl = gpr_avl_add(avl, box(983), box(869), NULL); - avl = gpr_avl_add(avl, box(72), box(870), NULL); - avl = gpr_avl_add(avl, box(693), box(871), NULL); - avl = gpr_avl_add(avl, box(567), box(872), NULL); - avl = remove_int(avl, 549); - avl = remove_int(avl, 351); - avl = gpr_avl_add(avl, box(1019), box(875), NULL); - avl = remove_int(avl, 585); - avl = remove_int(avl, 294); - avl = remove_int(avl, 61); - avl = gpr_avl_add(avl, box(409), box(879), NULL); - avl = gpr_avl_add(avl, box(984), box(880), NULL); - avl = gpr_avl_add(avl, box(830), box(881), NULL); - avl = remove_int(avl, 579); - avl = gpr_avl_add(avl, box(672), box(883), NULL); - avl = remove_int(avl, 968); - - gpr_avl_unref(avl, NULL); -} - -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), NULL); - avl = gpr_avl_add(avl, box(494), box(3), NULL); - avl = gpr_avl_add(avl, box(226), box(4), NULL); - avl = remove_int(avl, 524); - avl = gpr_avl_add(avl, box(540), box(6), NULL); - avl = remove_int(avl, 1008); - avl = gpr_avl_add(avl, box(502), box(8), NULL); - avl = remove_int(avl, 267); - avl = remove_int(avl, 764); - avl = remove_int(avl, 443); - avl = gpr_avl_add(avl, box(8), box(12), NULL); - avl = remove_int(avl, 291); - avl = remove_int(avl, 796); - avl = remove_int(avl, 1002); - avl = gpr_avl_add(avl, box(778), box(16), NULL); - avl = remove_int(avl, 621); - avl = remove_int(avl, 891); - avl = remove_int(avl, 880); - avl = gpr_avl_add(avl, box(197), box(20), NULL); - avl = gpr_avl_add(avl, box(441), box(21), NULL); - avl = gpr_avl_add(avl, box(719), box(22), NULL); - avl = remove_int(avl, 109); - avl = gpr_avl_add(avl, box(458), box(24), NULL); - avl = remove_int(avl, 86); - avl = gpr_avl_add(avl, box(897), box(26), NULL); - avl = gpr_avl_add(avl, box(997), box(27), NULL); - avl = remove_int(avl, 235); - avl = remove_int(avl, 425); - avl = remove_int(avl, 186); - avl = gpr_avl_add(avl, box(887), box(31), NULL); - avl = gpr_avl_add(avl, box(1005), box(32), NULL); - avl = gpr_avl_add(avl, box(778), box(33), NULL); - avl = gpr_avl_add(avl, box(575), box(34), NULL); - avl = remove_int(avl, 966); - avl = remove_int(avl, 1015); - avl = gpr_avl_add(avl, box(486), box(37), NULL); - avl = gpr_avl_add(avl, box(809), box(38), NULL); - avl = gpr_avl_add(avl, box(907), box(39), NULL); - avl = gpr_avl_add(avl, box(971), box(40), NULL); - avl = remove_int(avl, 441); - avl = remove_int(avl, 498); - avl = gpr_avl_add(avl, box(727), box(43), NULL); - avl = remove_int(avl, 679); - avl = remove_int(avl, 740); - avl = remove_int(avl, 532); - avl = gpr_avl_add(avl, box(805), box(47), NULL); - avl = remove_int(avl, 64); - avl = gpr_avl_add(avl, box(362), box(49), NULL); - avl = gpr_avl_add(avl, box(170), box(50), NULL); - avl = gpr_avl_add(avl, box(389), box(51), NULL); - avl = gpr_avl_add(avl, box(689), box(52), NULL); - avl = remove_int(avl, 871); - avl = gpr_avl_add(avl, box(447), box(54), NULL); - avl = remove_int(avl, 718); - avl = gpr_avl_add(avl, box(724), box(56), NULL); - avl = remove_int(avl, 215); - avl = gpr_avl_add(avl, box(550), box(58), NULL); - avl = remove_int(avl, 932); - avl = gpr_avl_add(avl, box(47), box(60), NULL); - avl = remove_int(avl, 46); - avl = remove_int(avl, 229); - avl = gpr_avl_add(avl, box(68), box(63), NULL); - avl = gpr_avl_add(avl, box(387), box(64), NULL); - avl = remove_int(avl, 933); - avl = remove_int(avl, 736); - avl = remove_int(avl, 719); - avl = gpr_avl_add(avl, box(150), box(68), NULL); - avl = remove_int(avl, 875); - avl = remove_int(avl, 298); - avl = gpr_avl_add(avl, box(991), box(71), NULL); - avl = remove_int(avl, 705); - avl = gpr_avl_add(avl, box(197), box(73), NULL); - avl = gpr_avl_add(avl, box(101), box(74), NULL); - avl = remove_int(avl, 436); - avl = gpr_avl_add(avl, box(755), box(76), NULL); - avl = gpr_avl_add(avl, box(727), box(77), NULL); - avl = remove_int(avl, 309); - avl = remove_int(avl, 253); - avl = gpr_avl_add(avl, box(203), box(80), NULL); - avl = remove_int(avl, 231); - avl = gpr_avl_add(avl, box(461), box(82), NULL); - avl = remove_int(avl, 316); - avl = remove_int(avl, 493); - avl = gpr_avl_add(avl, box(184), box(85), NULL); - avl = remove_int(avl, 737); - avl = gpr_avl_add(avl, box(790), box(87), NULL); - avl = gpr_avl_add(avl, box(335), box(88), NULL); - avl = remove_int(avl, 649); - avl = gpr_avl_add(avl, box(69), box(90), NULL); - avl = remove_int(avl, 585); - avl = remove_int(avl, 543); - avl = gpr_avl_add(avl, box(784), box(93), NULL); - avl = gpr_avl_add(avl, box(60), box(94), NULL); - avl = gpr_avl_add(avl, box(525), box(95), NULL); - avl = gpr_avl_add(avl, box(177), box(96), NULL); - avl = gpr_avl_add(avl, box(178), box(97), NULL); - avl = gpr_avl_add(avl, box(683), box(98), NULL); - avl = gpr_avl_add(avl, box(226), box(99), NULL); - avl = gpr_avl_add(avl, box(662), box(100), NULL); - avl = remove_int(avl, 944); - avl = gpr_avl_add(avl, box(562), box(102), NULL); - avl = gpr_avl_add(avl, box(793), box(103), NULL); - avl = remove_int(avl, 673); - avl = gpr_avl_add(avl, box(310), box(105), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(483), box(111), NULL); - avl = gpr_avl_add(avl, box(84), box(112), NULL); - avl = remove_int(avl, 109); - avl = gpr_avl_add(avl, box(132), box(114), NULL); - avl = gpr_avl_add(avl, box(920), box(115), NULL); - avl = remove_int(avl, 746); - avl = gpr_avl_add(avl, box(145), box(117), NULL); - avl = gpr_avl_add(avl, box(526), box(118), NULL); - avl = remove_int(avl, 158); - avl = gpr_avl_add(avl, box(332), box(120), NULL); - avl = gpr_avl_add(avl, box(918), box(121), NULL); - avl = remove_int(avl, 339); - avl = gpr_avl_add(avl, box(809), box(123), NULL); - avl = gpr_avl_add(avl, box(742), box(124), NULL); - avl = gpr_avl_add(avl, box(718), box(125), NULL); - avl = remove_int(avl, 988); - avl = remove_int(avl, 531); - avl = remove_int(avl, 840); - avl = gpr_avl_add(avl, box(816), box(129), NULL); - avl = gpr_avl_add(avl, box(976), box(130), NULL); - avl = remove_int(avl, 743); - avl = remove_int(avl, 528); - avl = remove_int(avl, 982); - avl = gpr_avl_add(avl, box(803), box(134), NULL); - avl = gpr_avl_add(avl, box(205), box(135), NULL); - avl = gpr_avl_add(avl, box(584), box(136), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(333), box(143), NULL); - avl = remove_int(avl, 439); - avl = gpr_avl_add(avl, box(35), box(145), NULL); - avl = gpr_avl_add(avl, box(837), box(146), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(116), box(154), NULL); - avl = gpr_avl_add(avl, box(446), box(155), NULL); - avl = remove_int(avl, 91); - avl = remove_int(avl, 721); - avl = remove_int(avl, 537); - avl = gpr_avl_add(avl, box(448), box(159), NULL); - avl = remove_int(avl, 155); - avl = remove_int(avl, 344); - avl = remove_int(avl, 237); - avl = gpr_avl_add(avl, box(309), box(163), NULL); - avl = gpr_avl_add(avl, box(434), box(164), NULL); - avl = gpr_avl_add(avl, box(277), box(165), NULL); - avl = remove_int(avl, 233); - avl = gpr_avl_add(avl, box(275), box(167), NULL); - avl = gpr_avl_add(avl, box(218), box(168), NULL); - avl = gpr_avl_add(avl, box(76), box(169), NULL); - avl = gpr_avl_add(avl, box(898), box(170), NULL); - avl = remove_int(avl, 771); - avl = gpr_avl_add(avl, box(237), box(172), NULL); - avl = remove_int(avl, 327); - avl = gpr_avl_add(avl, box(499), box(174), NULL); - 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), NULL); - avl = remove_int(avl, 389); - avl = gpr_avl_add(avl, box(708), box(183), NULL); - avl = gpr_avl_add(avl, box(594), box(184), NULL); - avl = gpr_avl_add(avl, box(942), box(185), NULL); - avl = gpr_avl_add(avl, box(282), box(186), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(161), box(197), NULL); - avl = remove_int(avl, 484); - avl = gpr_avl_add(avl, box(72), box(199), NULL); - avl = remove_int(avl, 629); - avl = gpr_avl_add(avl, box(522), box(201), NULL); - avl = remove_int(avl, 679); - avl = gpr_avl_add(avl, box(407), box(203), NULL); - avl = remove_int(avl, 693); - avl = gpr_avl_add(avl, box(424), box(205), NULL); - avl = gpr_avl_add(avl, box(651), box(206), NULL); - avl = gpr_avl_add(avl, box(927), box(207), NULL); - avl = remove_int(avl, 553); - avl = gpr_avl_add(avl, box(128), box(209), NULL); - avl = gpr_avl_add(avl, box(616), box(210), NULL); - avl = gpr_avl_add(avl, box(690), box(211), NULL); - avl = remove_int(avl, 241); - avl = remove_int(avl, 179); - avl = gpr_avl_add(avl, box(697), box(214), NULL); - avl = remove_int(avl, 779); - avl = gpr_avl_add(avl, box(241), box(216), NULL); - avl = remove_int(avl, 190); - avl = remove_int(avl, 210); - avl = gpr_avl_add(avl, box(711), box(219), NULL); - avl = remove_int(avl, 251); - avl = remove_int(avl, 61); - avl = gpr_avl_add(avl, box(800), box(222), NULL); - avl = remove_int(avl, 551); - avl = gpr_avl_add(avl, box(61), box(224), NULL); - avl = gpr_avl_add(avl, box(656), box(225), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(125), box(231), NULL); - avl = remove_int(avl, 107); - avl = gpr_avl_add(avl, box(938), box(233), NULL); - avl = gpr_avl_add(avl, box(914), box(234), NULL); - avl = gpr_avl_add(avl, box(197), box(235), NULL); - avl = remove_int(avl, 736); - avl = gpr_avl_add(avl, box(20), box(237), NULL); - avl = remove_int(avl, 224); - avl = remove_int(avl, 841); - avl = gpr_avl_add(avl, box(226), box(240), NULL); - avl = remove_int(avl, 963); - avl = remove_int(avl, 796); - avl = remove_int(avl, 728); - avl = gpr_avl_add(avl, box(855), box(244), NULL); - avl = gpr_avl_add(avl, box(769), box(245), NULL); - avl = gpr_avl_add(avl, box(631), box(246), NULL); - avl = remove_int(avl, 648); - avl = gpr_avl_add(avl, box(187), box(248), NULL); - avl = gpr_avl_add(avl, box(31), box(249), NULL); - avl = remove_int(avl, 163); - avl = gpr_avl_add(avl, box(218), box(251), NULL); - avl = gpr_avl_add(avl, box(488), box(252), NULL); - avl = gpr_avl_add(avl, box(387), box(253), NULL); - avl = gpr_avl_add(avl, box(809), box(254), NULL); - avl = gpr_avl_add(avl, box(997), box(255), NULL); - avl = remove_int(avl, 678); - avl = gpr_avl_add(avl, box(368), box(257), NULL); - avl = gpr_avl_add(avl, box(220), box(258), NULL); - avl = gpr_avl_add(avl, box(373), box(259), NULL); - 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), NULL); - avl = remove_int(avl, 254); - avl = remove_int(avl, 456); - avl = gpr_avl_add(avl, box(906), box(267), NULL); - avl = remove_int(avl, 711); - avl = gpr_avl_add(avl, box(632), box(269), NULL); - avl = remove_int(avl, 474); - avl = gpr_avl_add(avl, box(508), box(271), NULL); - avl = gpr_avl_add(avl, box(518), box(272), NULL); - avl = remove_int(avl, 579); - avl = remove_int(avl, 948); - avl = gpr_avl_add(avl, box(789), box(275), NULL); - avl = gpr_avl_add(avl, box(48), box(276), NULL); - avl = gpr_avl_add(avl, box(256), box(277), NULL); - avl = gpr_avl_add(avl, box(754), box(278), NULL); - avl = remove_int(avl, 215); - avl = gpr_avl_add(avl, box(679), box(280), NULL); - avl = gpr_avl_add(avl, box(606), box(281), NULL); - avl = remove_int(avl, 941); - avl = remove_int(avl, 31); - avl = gpr_avl_add(avl, box(758), box(284), NULL); - avl = remove_int(avl, 101); - avl = gpr_avl_add(avl, box(244), box(286), NULL); - avl = gpr_avl_add(avl, box(337), box(287), NULL); - avl = gpr_avl_add(avl, box(461), box(288), NULL); - avl = remove_int(avl, 476); - avl = gpr_avl_add(avl, box(845), box(290), NULL); - avl = remove_int(avl, 160); - avl = gpr_avl_add(avl, box(690), box(292), NULL); - avl = remove_int(avl, 931); - avl = gpr_avl_add(avl, box(869), box(294), NULL); - avl = gpr_avl_add(avl, box(1019), box(295), NULL); - avl = remove_int(avl, 591); - avl = remove_int(avl, 635); - avl = remove_int(avl, 67); - avl = gpr_avl_add(avl, box(113), box(299), NULL); - avl = remove_int(avl, 305); - avl = gpr_avl_add(avl, box(10), box(301), NULL); - avl = remove_int(avl, 823); - avl = remove_int(avl, 288); - avl = remove_int(avl, 239); - avl = gpr_avl_add(avl, box(646), box(305), NULL); - avl = gpr_avl_add(avl, box(1006), box(306), NULL); - avl = gpr_avl_add(avl, box(954), box(307), NULL); - avl = gpr_avl_add(avl, box(199), box(308), NULL); - avl = gpr_avl_add(avl, box(69), box(309), NULL); - avl = gpr_avl_add(avl, box(984), box(310), NULL); - avl = remove_int(avl, 568); - avl = remove_int(avl, 666); - avl = remove_int(avl, 37); - avl = gpr_avl_add(avl, box(845), box(314), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(335), box(323), NULL); - avl = gpr_avl_add(avl, box(961), box(324), NULL); - avl = gpr_avl_add(avl, box(73), box(325), NULL); - avl = remove_int(avl, 469); - avl = gpr_avl_add(avl, box(449), box(327), NULL); - avl = remove_int(avl, 821); - avl = gpr_avl_add(avl, box(845), box(329), NULL); - avl = remove_int(avl, 637); - avl = gpr_avl_add(avl, box(769), box(331), NULL); - avl = gpr_avl_add(avl, box(901), box(332), NULL); - avl = remove_int(avl, 142); - avl = remove_int(avl, 361); - avl = remove_int(avl, 876); - avl = gpr_avl_add(avl, box(614), box(336), NULL); - avl = gpr_avl_add(avl, box(729), box(337), NULL); - avl = remove_int(avl, 120); - avl = remove_int(avl, 473); - avl = remove_int(avl, 445); - avl = gpr_avl_add(avl, box(978), box(341), NULL); - avl = gpr_avl_add(avl, box(164), box(342), NULL); - avl = gpr_avl_add(avl, box(1), box(343), NULL); - avl = remove_int(avl, 890); - avl = gpr_avl_add(avl, box(605), box(345), NULL); - avl = gpr_avl_add(avl, box(178), box(346), NULL); - avl = gpr_avl_add(avl, box(481), box(347), NULL); - avl = gpr_avl_add(avl, box(772), box(348), NULL); - avl = remove_int(avl, 824); - avl = remove_int(avl, 167); - avl = remove_int(avl, 151); - avl = gpr_avl_add(avl, box(698), box(352), NULL); - avl = gpr_avl_add(avl, box(202), box(353), NULL); - avl = gpr_avl_add(avl, box(921), box(354), NULL); - avl = gpr_avl_add(avl, box(875), box(355), NULL); - avl = remove_int(avl, 197); - avl = remove_int(avl, 232); - avl = gpr_avl_add(avl, box(209), box(358), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(113), box(365), NULL); - avl = remove_int(avl, 767); - avl = gpr_avl_add(avl, box(586), box(367), NULL); - avl = gpr_avl_add(avl, box(121), box(368), NULL); - avl = remove_int(avl, 235); - avl = remove_int(avl, 439); - avl = remove_int(avl, 360); - avl = gpr_avl_add(avl, box(916), box(372), NULL); - avl = remove_int(avl, 999); - avl = gpr_avl_add(avl, box(825), box(374), NULL); - avl = gpr_avl_add(avl, box(177), box(375), NULL); - avl = remove_int(avl, 204); - avl = remove_int(avl, 92); - avl = gpr_avl_add(avl, box(794), box(378), NULL); - avl = gpr_avl_add(avl, box(463), box(379), NULL); - avl = gpr_avl_add(avl, box(472), box(380), NULL); - avl = remove_int(avl, 235); - avl = gpr_avl_add(avl, box(840), box(382), NULL); - avl = remove_int(avl, 657); - avl = gpr_avl_add(avl, box(586), box(384), NULL); - avl = gpr_avl_add(avl, box(979), box(385), NULL); - avl = remove_int(avl, 979); - avl = gpr_avl_add(avl, box(639), box(387), NULL); - avl = remove_int(avl, 907); - avl = remove_int(avl, 973); - avl = gpr_avl_add(avl, box(913), box(390), NULL); - avl = gpr_avl_add(avl, box(566), box(391), NULL); - avl = gpr_avl_add(avl, box(883), box(392), NULL); - avl = gpr_avl_add(avl, box(552), box(393), NULL); - avl = gpr_avl_add(avl, box(16), box(394), NULL); - avl = remove_int(avl, 60); - avl = gpr_avl_add(avl, box(567), box(396), NULL); - avl = gpr_avl_add(avl, box(705), box(397), NULL); - avl = gpr_avl_add(avl, box(94), box(398), NULL); - avl = remove_int(avl, 321); - avl = gpr_avl_add(avl, box(207), box(400), NULL); - avl = gpr_avl_add(avl, box(682), box(401), NULL); - avl = gpr_avl_add(avl, box(592), box(402), NULL); - avl = gpr_avl_add(avl, box(10), box(403), NULL); - avl = remove_int(avl, 911); - avl = remove_int(avl, 161); - avl = gpr_avl_add(avl, box(86), box(406), NULL); - avl = remove_int(avl, 893); - avl = remove_int(avl, 362); - avl = gpr_avl_add(avl, box(599), box(409), NULL); - avl = remove_int(avl, 413); - avl = gpr_avl_add(avl, box(867), box(411), NULL); - avl = remove_int(avl, 955); - avl = gpr_avl_add(avl, box(341), box(413), NULL); - avl = gpr_avl_add(avl, box(887), box(414), NULL); - avl = remove_int(avl, 706); - avl = gpr_avl_add(avl, box(939), box(416), NULL); - 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), NULL); - avl = remove_int(avl, 848); - avl = gpr_avl_add(avl, box(235), box(423), NULL); - avl = remove_int(avl, 617); - avl = gpr_avl_add(avl, box(565), box(425), NULL); - avl = remove_int(avl, 469); - avl = gpr_avl_add(avl, box(988), box(427), NULL); - avl = remove_int(avl, 957); - avl = gpr_avl_add(avl, box(426), box(429), NULL); - avl = remove_int(avl, 967); - avl = gpr_avl_add(avl, box(890), box(431), NULL); - avl = gpr_avl_add(avl, box(473), box(432), NULL); - 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), NULL); - avl = remove_int(avl, 882); - avl = remove_int(avl, 782); - avl = gpr_avl_add(avl, box(408), box(442), NULL); - avl = gpr_avl_add(avl, box(728), box(443), NULL); - avl = remove_int(avl, 27); - avl = gpr_avl_add(avl, box(137), box(445), NULL); - avl = gpr_avl_add(avl, box(239), box(446), NULL); - avl = remove_int(avl, 854); - avl = gpr_avl_add(avl, box(104), box(448), NULL); - avl = gpr_avl_add(avl, box(823), box(449), NULL); - avl = gpr_avl_add(avl, box(524), box(450), NULL); - avl = gpr_avl_add(avl, box(995), box(451), NULL); - avl = remove_int(avl, 422); - avl = remove_int(avl, 220); - avl = gpr_avl_add(avl, box(856), box(454), NULL); - avl = remove_int(avl, 332); - avl = gpr_avl_add(avl, box(679), box(456), NULL); - avl = remove_int(avl, 18); - avl = gpr_avl_add(avl, box(837), box(458), NULL); - avl = remove_int(avl, 405); - avl = remove_int(avl, 877); - avl = remove_int(avl, 835); - avl = gpr_avl_add(avl, box(547), box(462), NULL); - avl = remove_int(avl, 805); - avl = remove_int(avl, 862); - avl = gpr_avl_add(avl, box(75), box(465), NULL); - avl = remove_int(avl, 41); - avl = gpr_avl_add(avl, box(310), box(467), NULL); - avl = remove_int(avl, 855); - avl = gpr_avl_add(avl, box(20), box(469), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(96), box(475), NULL); - avl = remove_int(avl, 854); - avl = gpr_avl_add(avl, box(65), box(477), NULL); - avl = gpr_avl_add(avl, box(573), box(478), NULL); - avl = gpr_avl_add(avl, box(4), box(479), NULL); - avl = gpr_avl_add(avl, box(451), box(480), NULL); - avl = gpr_avl_add(avl, box(774), box(481), NULL); - avl = gpr_avl_add(avl, box(126), box(482), NULL); - avl = remove_int(avl, 956); - avl = remove_int(avl, 591); - avl = remove_int(avl, 644); - avl = gpr_avl_add(avl, box(304), box(486), NULL); - avl = remove_int(avl, 620); - avl = remove_int(avl, 394); - avl = gpr_avl_add(avl, box(1002), box(489), NULL); - avl = gpr_avl_add(avl, box(837), box(490), NULL); - avl = remove_int(avl, 485); - avl = gpr_avl_add(avl, box(1005), box(492), NULL); - avl = remove_int(avl, 21); - avl = gpr_avl_add(avl, box(396), box(494), NULL); - avl = remove_int(avl, 966); - avl = gpr_avl_add(avl, box(105), box(496), NULL); - avl = gpr_avl_add(avl, box(316), box(497), NULL); - avl = remove_int(avl, 776); - avl = gpr_avl_add(avl, box(188), box(499), NULL); - avl = remove_int(avl, 200); - avl = gpr_avl_add(avl, box(98), box(501), NULL); - avl = gpr_avl_add(avl, box(831), box(502), NULL); - avl = gpr_avl_add(avl, box(227), box(503), NULL); - avl = gpr_avl_add(avl, box(220), box(504), NULL); - avl = remove_int(avl, 715); - avl = remove_int(avl, 279); - avl = gpr_avl_add(avl, box(701), box(507), NULL); - avl = gpr_avl_add(avl, box(726), box(508), NULL); - avl = gpr_avl_add(avl, box(815), box(509), NULL); - avl = gpr_avl_add(avl, box(749), box(510), NULL); - 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), NULL); - avl = remove_int(avl, 59); - avl = gpr_avl_add(avl, box(168), box(517), NULL); - avl = remove_int(avl, 337); - avl = gpr_avl_add(avl, box(69), box(519), NULL); - avl = remove_int(avl, 600); - avl = gpr_avl_add(avl, box(591), box(521), NULL); - avl = gpr_avl_add(avl, box(960), box(522), NULL); - avl = gpr_avl_add(avl, box(116), box(523), NULL); - avl = remove_int(avl, 991); - avl = gpr_avl_add(avl, box(760), box(525), NULL); - avl = gpr_avl_add(avl, box(664), box(526), NULL); - avl = gpr_avl_add(avl, box(547), box(527), NULL); - avl = remove_int(avl, 922); - avl = gpr_avl_add(avl, box(290), box(529), NULL); - avl = gpr_avl_add(avl, box(859), box(530), NULL); - avl = gpr_avl_add(avl, box(49), box(531), NULL); - avl = remove_int(avl, 455); - avl = remove_int(avl, 786); - avl = gpr_avl_add(avl, box(613), box(534), NULL); - avl = gpr_avl_add(avl, box(326), box(535), NULL); - avl = remove_int(avl, 615); - avl = gpr_avl_add(avl, box(45), box(537), NULL); - avl = gpr_avl_add(avl, box(162), box(538), NULL); - avl = gpr_avl_add(avl, box(189), box(539), NULL); - avl = remove_int(avl, 68); - avl = remove_int(avl, 846); - avl = gpr_avl_add(avl, box(608), box(542), NULL); - avl = remove_int(avl, 821); - avl = gpr_avl_add(avl, box(978), box(544), NULL); - avl = gpr_avl_add(avl, box(892), box(545), NULL); - avl = remove_int(avl, 924); - avl = gpr_avl_add(avl, box(708), box(547), NULL); - avl = remove_int(avl, 135); - avl = remove_int(avl, 124); - avl = gpr_avl_add(avl, box(301), box(550), NULL); - avl = gpr_avl_add(avl, box(939), box(551), NULL); - avl = gpr_avl_add(avl, box(344), box(552), NULL); - avl = remove_int(avl, 443); - avl = remove_int(avl, 122); - avl = gpr_avl_add(avl, box(636), box(555), NULL); - avl = remove_int(avl, 558); - avl = gpr_avl_add(avl, box(923), box(557), NULL); - avl = remove_int(avl, 827); - avl = gpr_avl_add(avl, box(649), box(559), NULL); - avl = gpr_avl_add(avl, box(808), box(560), NULL); - avl = remove_int(avl, 570); - avl = remove_int(avl, 434); - avl = gpr_avl_add(avl, box(40), box(563), NULL); - avl = gpr_avl_add(avl, box(725), box(564), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(512), box(572), NULL); - 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), NULL); - avl = remove_int(avl, 770); - avl = remove_int(avl, 776); - avl = gpr_avl_add(avl, box(602), box(581), NULL); - avl = remove_int(avl, 251); - avl = gpr_avl_add(avl, box(303), box(583), NULL); - avl = remove_int(avl, 837); - avl = gpr_avl_add(avl, box(714), box(585), NULL); - avl = remove_int(avl, 800); - avl = gpr_avl_add(avl, box(266), box(587), NULL); - avl = gpr_avl_add(avl, box(555), box(588), NULL); - avl = remove_int(avl, 604); - avl = remove_int(avl, 163); - avl = remove_int(avl, 497); - avl = gpr_avl_add(avl, box(296), box(592), NULL); - avl = remove_int(avl, 129); - avl = gpr_avl_add(avl, box(656), box(594), NULL); - avl = remove_int(avl, 769); - avl = remove_int(avl, 941); - avl = gpr_avl_add(avl, box(775), box(597), NULL); - avl = gpr_avl_add(avl, box(846), box(598), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(575), box(604), NULL); - avl = gpr_avl_add(avl, box(620), box(605), NULL); - avl = remove_int(avl, 100); - avl = remove_int(avl, 667); - avl = gpr_avl_add(avl, box(138), box(608), NULL); - avl = gpr_avl_add(avl, box(566), box(609), NULL); - avl = gpr_avl_add(avl, box(673), box(610), NULL); - avl = gpr_avl_add(avl, box(178), box(611), NULL); - avl = remove_int(avl, 659); - avl = gpr_avl_add(avl, box(759), box(613), NULL); - avl = gpr_avl_add(avl, box(1008), box(614), NULL); - avl = remove_int(avl, 116); - avl = gpr_avl_add(avl, box(608), box(616), NULL); - avl = gpr_avl_add(avl, box(339), box(617), NULL); - avl = gpr_avl_add(avl, box(197), box(618), NULL); - avl = remove_int(avl, 25); - avl = remove_int(avl, 628); - avl = gpr_avl_add(avl, box(487), box(621), NULL); - avl = remove_int(avl, 739); - avl = remove_int(avl, 100); - avl = remove_int(avl, 928); - avl = gpr_avl_add(avl, box(647), box(625), NULL); - avl = remove_int(avl, 978); - avl = remove_int(avl, 143); - avl = remove_int(avl, 755); - avl = gpr_avl_add(avl, box(71), box(629), NULL); - avl = remove_int(avl, 205); - avl = gpr_avl_add(avl, box(501), box(631), NULL); - 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), NULL); - avl = remove_int(avl, 264); - avl = gpr_avl_add(avl, box(69), box(639), NULL); - avl = remove_int(avl, 73); - avl = gpr_avl_add(avl, box(745), box(641), NULL); - avl = remove_int(avl, 518); - avl = remove_int(avl, 641); - avl = remove_int(avl, 768); - avl = gpr_avl_add(avl, box(988), box(645), NULL); - avl = gpr_avl_add(avl, box(899), box(646), NULL); - avl = remove_int(avl, 763); - avl = remove_int(avl, 281); - avl = remove_int(avl, 496); - avl = gpr_avl_add(avl, box(445), box(650), NULL); - avl = remove_int(avl, 905); - avl = gpr_avl_add(avl, box(275), box(652), NULL); - avl = gpr_avl_add(avl, box(137), box(653), NULL); - avl = remove_int(avl, 642); - avl = gpr_avl_add(avl, box(708), box(655), NULL); - avl = remove_int(avl, 922); - avl = gpr_avl_add(avl, box(743), box(657), NULL); - avl = remove_int(avl, 295); - avl = remove_int(avl, 665); - avl = remove_int(avl, 48); - avl = gpr_avl_add(avl, box(1012), box(661), NULL); - avl = remove_int(avl, 71); - avl = remove_int(avl, 523); - avl = gpr_avl_add(avl, box(319), box(664), NULL); - avl = remove_int(avl, 632); - avl = gpr_avl_add(avl, box(137), box(666), NULL); - avl = gpr_avl_add(avl, box(686), box(667), NULL); - avl = gpr_avl_add(avl, box(724), box(668), NULL); - avl = gpr_avl_add(avl, box(952), box(669), NULL); - avl = gpr_avl_add(avl, box(5), box(670), NULL); - avl = remove_int(avl, 35); - avl = gpr_avl_add(avl, box(43), box(672), NULL); - avl = gpr_avl_add(avl, box(320), box(673), NULL); - avl = gpr_avl_add(avl, box(115), box(674), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(605), box(680), NULL); - avl = gpr_avl_add(avl, box(152), box(681), NULL); - avl = gpr_avl_add(avl, box(113), box(682), NULL); - avl = remove_int(avl, 131); - avl = remove_int(avl, 637); - avl = gpr_avl_add(avl, box(156), box(685), NULL); - avl = remove_int(avl, 696); - avl = gpr_avl_add(avl, box(546), box(687), NULL); - 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), NULL); - avl = remove_int(avl, 924); - avl = gpr_avl_add(avl, box(825), box(703), NULL); - avl = remove_int(avl, 888); - avl = remove_int(avl, 931); - avl = gpr_avl_add(avl, box(285), box(706), NULL); - avl = remove_int(avl, 62); - avl = remove_int(avl, 444); - avl = remove_int(avl, 946); - avl = gpr_avl_add(avl, box(122), box(710), NULL); - avl = gpr_avl_add(avl, box(846), box(711), NULL); - avl = remove_int(avl, 628); - avl = gpr_avl_add(avl, box(511), box(713), NULL); - avl = gpr_avl_add(avl, box(398), box(714), NULL); - avl = remove_int(avl, 730); - avl = gpr_avl_add(avl, box(797), box(716), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(1015), box(726), NULL); - avl = remove_int(avl, 813); - avl = gpr_avl_add(avl, box(213), box(728), NULL); - avl = remove_int(avl, 468); - avl = remove_int(avl, 365); - avl = remove_int(avl, 399); - avl = gpr_avl_add(avl, box(380), box(732), NULL); - avl = remove_int(avl, 835); - avl = remove_int(avl, 970); - avl = gpr_avl_add(avl, box(700), box(735), NULL); - avl = gpr_avl_add(avl, box(807), box(736), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(332), box(744), NULL); - avl = remove_int(avl, 686); - avl = remove_int(avl, 206); - avl = remove_int(avl, 835); - avl = gpr_avl_add(avl, box(334), box(748), NULL); - avl = remove_int(avl, 171); - avl = gpr_avl_add(avl, box(1002), box(750), NULL); - avl = gpr_avl_add(avl, box(779), box(751), NULL); - avl = gpr_avl_add(avl, box(307), box(752), NULL); - avl = gpr_avl_add(avl, box(127), box(753), NULL); - avl = gpr_avl_add(avl, box(251), box(754), NULL); - 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), NULL); - avl = remove_int(avl, 43); - avl = gpr_avl_add(avl, box(871), box(762), NULL); - avl = gpr_avl_add(avl, box(580), box(763), NULL); - avl = remove_int(avl, 501); - avl = remove_int(avl, 462); - avl = remove_int(avl, 599); - avl = gpr_avl_add(avl, box(240), box(767), NULL); - avl = gpr_avl_add(avl, box(285), box(768), NULL); - avl = gpr_avl_add(avl, box(472), box(769), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(552), box(778), NULL); - avl = remove_int(avl, 19); - avl = remove_int(avl, 803); - avl = gpr_avl_add(avl, box(508), box(781), NULL); - 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), NULL); - 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), NULL); - 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), NULL); - avl = remove_int(avl, 38); - avl = remove_int(avl, 595); - avl = gpr_avl_add(avl, box(213), box(799), NULL); - avl = remove_int(avl, 7); - avl = remove_int(avl, 620); - avl = gpr_avl_add(avl, box(946), box(802), NULL); - avl = remove_int(avl, 145); - avl = gpr_avl_add(avl, box(628), box(804), NULL); - avl = remove_int(avl, 972); - avl = gpr_avl_add(avl, box(728), box(806), NULL); - avl = remove_int(avl, 91); - avl = gpr_avl_add(avl, box(136), box(808), NULL); - avl = gpr_avl_add(avl, box(841), box(809), NULL); - avl = gpr_avl_add(avl, box(265), box(810), NULL); - avl = gpr_avl_add(avl, box(701), box(811), NULL); - avl = gpr_avl_add(avl, box(27), box(812), NULL); - avl = remove_int(avl, 72); - avl = remove_int(avl, 14); - avl = gpr_avl_add(avl, box(286), box(815), NULL); - avl = remove_int(avl, 996); - avl = remove_int(avl, 998); - avl = gpr_avl_add(avl, box(466), box(818), NULL); - 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), NULL); - avl = remove_int(avl, 812); - avl = gpr_avl_add(avl, box(577), box(829), NULL); - avl = remove_int(avl, 624); - avl = remove_int(avl, 847); - avl = remove_int(avl, 745); - avl = gpr_avl_add(avl, box(491), box(833), NULL); - avl = gpr_avl_add(avl, box(941), box(834), NULL); - avl = remove_int(avl, 258); - avl = gpr_avl_add(avl, box(410), box(836), NULL); - avl = gpr_avl_add(avl, box(80), box(837), NULL); - avl = gpr_avl_add(avl, box(196), box(838), NULL); - avl = gpr_avl_add(avl, box(5), box(839), NULL); - avl = remove_int(avl, 782); - avl = gpr_avl_add(avl, box(827), box(841), NULL); - avl = remove_int(avl, 472); - avl = remove_int(avl, 664); - avl = gpr_avl_add(avl, box(409), box(844), NULL); - avl = gpr_avl_add(avl, box(62), box(845), NULL); - 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), NULL); - avl = remove_int(avl, 587); - avl = remove_int(avl, 350); - avl = gpr_avl_add(avl, box(980), box(855), NULL); - avl = gpr_avl_add(avl, box(992), box(856), NULL); - avl = gpr_avl_add(avl, box(818), box(857), NULL); - avl = remove_int(avl, 853); - avl = remove_int(avl, 701); - avl = gpr_avl_add(avl, box(675), box(860), NULL); - avl = remove_int(avl, 248); - avl = remove_int(avl, 649); - avl = gpr_avl_add(avl, box(508), box(863), NULL); - avl = remove_int(avl, 927); - avl = gpr_avl_add(avl, box(957), box(865), NULL); - avl = gpr_avl_add(avl, box(698), box(866), NULL); - avl = gpr_avl_add(avl, box(388), box(867), NULL); - avl = gpr_avl_add(avl, box(532), box(868), NULL); - avl = gpr_avl_add(avl, box(681), box(869), NULL); - avl = remove_int(avl, 544); - avl = remove_int(avl, 991); - avl = remove_int(avl, 397); - avl = gpr_avl_add(avl, box(954), box(873), NULL); - avl = gpr_avl_add(avl, box(219), box(874), NULL); - avl = gpr_avl_add(avl, box(465), box(875), NULL); - avl = remove_int(avl, 371); - avl = gpr_avl_add(avl, box(601), box(877), NULL); - avl = gpr_avl_add(avl, box(543), box(878), NULL); - avl = remove_int(avl, 329); - avl = gpr_avl_add(avl, box(560), box(880), NULL); - avl = remove_int(avl, 898); - avl = gpr_avl_add(avl, box(455), box(882), NULL); - avl = remove_int(avl, 313); - avl = gpr_avl_add(avl, box(215), box(884), NULL); - avl = remove_int(avl, 846); - avl = gpr_avl_add(avl, box(608), box(886), NULL); - avl = remove_int(avl, 248); - avl = gpr_avl_add(avl, box(575), box(888), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(329), box(894), NULL); - avl = gpr_avl_add(avl, box(326), box(895), NULL); - avl = remove_int(avl, 746); - avl = remove_int(avl, 99); - avl = gpr_avl_add(avl, box(464), box(898), NULL); - avl = gpr_avl_add(avl, box(141), box(899), NULL); - avl = remove_int(avl, 383); - avl = gpr_avl_add(avl, box(414), box(901), NULL); - avl = gpr_avl_add(avl, box(777), box(902), NULL); - avl = remove_int(avl, 972); - avl = remove_int(avl, 841); - avl = remove_int(avl, 100); - avl = gpr_avl_add(avl, box(828), box(906), NULL); - avl = remove_int(avl, 785); - avl = gpr_avl_add(avl, box(1008), box(908), NULL); - avl = gpr_avl_add(avl, box(46), box(909), NULL); - avl = remove_int(avl, 399); - avl = gpr_avl_add(avl, box(178), box(911), NULL); - avl = gpr_avl_add(avl, box(573), box(912), NULL); - avl = remove_int(avl, 299); - avl = gpr_avl_add(avl, box(690), box(914), NULL); - avl = gpr_avl_add(avl, box(692), box(915), NULL); - 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), NULL); - avl = remove_int(avl, 328); - avl = gpr_avl_add(avl, box(89), box(923), NULL); - avl = remove_int(avl, 867); - avl = remove_int(avl, 626); - avl = remove_int(avl, 507); - avl = gpr_avl_add(avl, box(365), box(927), NULL); - avl = gpr_avl_add(avl, box(58), box(928), NULL); - avl = gpr_avl_add(avl, box(70), box(929), NULL); - avl = remove_int(avl, 81); - avl = remove_int(avl, 797); - avl = gpr_avl_add(avl, box(846), box(932), NULL); - avl = remove_int(avl, 642); - avl = gpr_avl_add(avl, box(777), box(934), NULL); - avl = remove_int(avl, 107); - avl = gpr_avl_add(avl, box(691), box(936), NULL); - avl = gpr_avl_add(avl, box(820), box(937), NULL); - avl = gpr_avl_add(avl, box(202), box(938), NULL); - avl = gpr_avl_add(avl, box(308), box(939), NULL); - avl = gpr_avl_add(avl, box(20), box(940), NULL); - avl = remove_int(avl, 289); - avl = gpr_avl_add(avl, box(714), box(942), NULL); - avl = gpr_avl_add(avl, box(584), box(943), NULL); - avl = remove_int(avl, 294); - avl = gpr_avl_add(avl, box(496), box(945), NULL); - avl = gpr_avl_add(avl, box(394), box(946), NULL); - avl = gpr_avl_add(avl, box(860), box(947), NULL); - avl = gpr_avl_add(avl, box(58), box(948), NULL); - avl = remove_int(avl, 784); - avl = remove_int(avl, 584); - avl = remove_int(avl, 708); - avl = gpr_avl_add(avl, box(142), box(952), NULL); - avl = gpr_avl_add(avl, box(247), box(953), NULL); - avl = gpr_avl_add(avl, box(389), box(954), NULL); - avl = remove_int(avl, 390); - avl = gpr_avl_add(avl, box(465), box(956), NULL); - avl = gpr_avl_add(avl, box(936), box(957), NULL); - avl = gpr_avl_add(avl, box(309), box(958), NULL); - 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), NULL); - avl = remove_int(avl, 82); - avl = gpr_avl_add(avl, box(728), box(968), NULL); - avl = remove_int(avl, 852); - avl = gpr_avl_add(avl, box(884), box(970), NULL); - avl = gpr_avl_add(avl, box(502), box(971), NULL); - avl = remove_int(avl, 898); - avl = remove_int(avl, 481); - avl = gpr_avl_add(avl, box(911), box(974), NULL); - 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), NULL); - avl = remove_int(avl, 25); - avl = remove_int(avl, 697); - avl = gpr_avl_add(avl, box(645), box(986), NULL); - avl = gpr_avl_add(avl, box(211), box(987), NULL); - avl = gpr_avl_add(avl, box(589), box(988), NULL); - avl = remove_int(avl, 702); - avl = gpr_avl_add(avl, box(53), box(990), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(834), box(998), NULL); - avl = gpr_avl_add(avl, box(514), box(999), NULL); - avl = gpr_avl_add(avl, box(75), box(1000), NULL); - avl = remove_int(avl, 745); - avl = gpr_avl_add(avl, box(362), box(1002), NULL); - avl = remove_int(avl, 215); - avl = gpr_avl_add(avl, box(624), box(1004), NULL); - avl = remove_int(avl, 404); - avl = remove_int(avl, 359); - avl = remove_int(avl, 491); - avl = gpr_avl_add(avl, box(903), box(1008), NULL); - avl = gpr_avl_add(avl, box(240), box(1009), NULL); - avl = remove_int(avl, 95); - avl = gpr_avl_add(avl, box(119), box(1011), NULL); - avl = gpr_avl_add(avl, box(857), box(1012), NULL); - avl = remove_int(avl, 39); - avl = remove_int(avl, 866); - avl = gpr_avl_add(avl, box(503), box(1015), NULL); - avl = gpr_avl_add(avl, box(740), box(1016), NULL); - 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), NULL); - avl = remove_int(avl, 638); - avl = gpr_avl_add(avl, box(299), box(1025), NULL); - avl = gpr_avl_add(avl, box(584), box(1026), NULL); - avl = remove_int(avl, 863); - avl = gpr_avl_add(avl, box(612), box(1028), NULL); - avl = gpr_avl_add(avl, box(62), box(1029), NULL); - avl = gpr_avl_add(avl, box(432), box(1030), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(644), box(1036), NULL); - avl = remove_int(avl, 638); - avl = gpr_avl_add(avl, box(13), box(1038), NULL); - avl = remove_int(avl, 66); - avl = remove_int(avl, 82); - avl = gpr_avl_add(avl, box(362), box(1041), NULL); - avl = gpr_avl_add(avl, box(783), box(1042), NULL); - avl = remove_int(avl, 60); - avl = gpr_avl_add(avl, box(80), box(1044), NULL); - avl = gpr_avl_add(avl, box(825), box(1045), NULL); - avl = gpr_avl_add(avl, box(688), box(1046), NULL); - avl = gpr_avl_add(avl, box(662), box(1047), NULL); - avl = remove_int(avl, 156); - avl = remove_int(avl, 376); - avl = remove_int(avl, 99); - avl = gpr_avl_add(avl, box(526), box(1051), NULL); - avl = gpr_avl_add(avl, box(168), box(1052), NULL); - avl = remove_int(avl, 646); - avl = remove_int(avl, 380); - avl = remove_int(avl, 833); - avl = gpr_avl_add(avl, box(53), box(1056), NULL); - avl = remove_int(avl, 105); - avl = gpr_avl_add(avl, box(373), box(1058), NULL); - avl = gpr_avl_add(avl, box(184), box(1059), NULL); - avl = remove_int(avl, 288); - avl = gpr_avl_add(avl, box(966), box(1061), NULL); - avl = remove_int(avl, 158); - avl = gpr_avl_add(avl, box(406), box(1063), NULL); - avl = remove_int(avl, 470); - avl = gpr_avl_add(avl, box(283), box(1065), NULL); - avl = gpr_avl_add(avl, box(838), box(1066), NULL); - avl = gpr_avl_add(avl, box(288), box(1067), NULL); - avl = gpr_avl_add(avl, box(950), box(1068), NULL); - avl = gpr_avl_add(avl, box(163), box(1069), NULL); - avl = remove_int(avl, 623); - avl = remove_int(avl, 769); - avl = gpr_avl_add(avl, box(144), box(1072), NULL); - avl = gpr_avl_add(avl, box(489), box(1073), NULL); - avl = remove_int(avl, 15); - avl = gpr_avl_add(avl, box(971), box(1075), NULL); - avl = remove_int(avl, 660); - avl = gpr_avl_add(avl, box(255), box(1077), NULL); - avl = remove_int(avl, 494); - avl = gpr_avl_add(avl, box(109), box(1079), NULL); - avl = gpr_avl_add(avl, box(420), box(1080), NULL); - avl = gpr_avl_add(avl, box(509), box(1081), NULL); - avl = remove_int(avl, 178); - avl = gpr_avl_add(avl, box(216), box(1083), NULL); - avl = gpr_avl_add(avl, box(707), box(1084), NULL); - avl = gpr_avl_add(avl, box(411), box(1085), NULL); - avl = gpr_avl_add(avl, box(352), box(1086), NULL); - avl = remove_int(avl, 983); - avl = gpr_avl_add(avl, box(6), box(1088), NULL); - avl = gpr_avl_add(avl, box(1014), box(1089), NULL); - avl = remove_int(avl, 98); - avl = remove_int(avl, 325); - avl = gpr_avl_add(avl, box(851), box(1092), NULL); - avl = remove_int(avl, 553); - avl = gpr_avl_add(avl, box(218), box(1094), NULL); - avl = gpr_avl_add(avl, box(261), box(1095), NULL); - avl = remove_int(avl, 31); - avl = gpr_avl_add(avl, box(872), box(1097), NULL); - avl = remove_int(avl, 543); - avl = remove_int(avl, 314); - avl = remove_int(avl, 443); - avl = gpr_avl_add(avl, box(533), box(1101), NULL); - 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), NULL); - avl = remove_int(avl, 622); - avl = gpr_avl_add(avl, box(352), box(1112), NULL); - avl = remove_int(avl, 182); - avl = gpr_avl_add(avl, box(534), box(1114), NULL); - avl = gpr_avl_add(avl, box(97), box(1115), NULL); - avl = gpr_avl_add(avl, box(198), box(1116), NULL); - avl = remove_int(avl, 750); - avl = gpr_avl_add(avl, box(98), box(1118), NULL); - avl = remove_int(avl, 943); - avl = gpr_avl_add(avl, box(254), box(1120), NULL); - avl = gpr_avl_add(avl, box(30), box(1121), NULL); - avl = remove_int(avl, 14); - avl = remove_int(avl, 475); - avl = remove_int(avl, 82); - avl = gpr_avl_add(avl, box(789), box(1125), NULL); - avl = gpr_avl_add(avl, box(402), box(1126), NULL); - avl = remove_int(avl, 1019); - avl = gpr_avl_add(avl, box(858), box(1128), NULL); - avl = gpr_avl_add(avl, box(625), box(1129), NULL); - avl = remove_int(avl, 675); - avl = remove_int(avl, 323); - avl = gpr_avl_add(avl, box(329), box(1132), NULL); - avl = remove_int(avl, 929); - avl = remove_int(avl, 44); - avl = gpr_avl_add(avl, box(443), box(1135), NULL); - avl = gpr_avl_add(avl, box(653), box(1136), NULL); - avl = gpr_avl_add(avl, box(750), box(1137), NULL); - avl = gpr_avl_add(avl, box(252), box(1138), NULL); - avl = gpr_avl_add(avl, box(449), box(1139), NULL); - 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), NULL); - avl = remove_int(avl, 806); - avl = gpr_avl_add(avl, box(455), box(1146), NULL); - avl = remove_int(avl, 31); - avl = gpr_avl_add(avl, box(154), box(1148), NULL); - avl = gpr_avl_add(avl, box(189), box(1149), NULL); - avl = remove_int(avl, 786); - avl = gpr_avl_add(avl, box(496), box(1151), NULL); - avl = gpr_avl_add(avl, box(81), box(1152), NULL); - avl = gpr_avl_add(avl, box(59), box(1153), NULL); - avl = remove_int(avl, 424); - avl = remove_int(avl, 668); - avl = gpr_avl_add(avl, box(723), box(1156), NULL); - avl = gpr_avl_add(avl, box(822), box(1157), NULL); - avl = gpr_avl_add(avl, box(354), box(1158), NULL); - avl = remove_int(avl, 738); - avl = gpr_avl_add(avl, box(686), box(1160), NULL); - avl = gpr_avl_add(avl, box(43), box(1161), NULL); - avl = gpr_avl_add(avl, box(625), box(1162), NULL); - avl = gpr_avl_add(avl, box(902), box(1163), NULL); - avl = gpr_avl_add(avl, box(12), box(1164), NULL); - avl = gpr_avl_add(avl, box(977), box(1165), NULL); - avl = gpr_avl_add(avl, box(699), box(1166), NULL); - avl = gpr_avl_add(avl, box(189), box(1167), NULL); - 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), NULL); - avl = remove_int(avl, 758); - avl = remove_int(avl, 222); - avl = gpr_avl_add(avl, box(975), box(1175), NULL); - avl = remove_int(avl, 993); - avl = gpr_avl_add(avl, box(2), box(1177), NULL); - avl = gpr_avl_add(avl, box(70), box(1178), NULL); - avl = remove_int(avl, 350); - avl = remove_int(avl, 972); - avl = remove_int(avl, 880); - avl = gpr_avl_add(avl, box(753), box(1182), NULL); - avl = remove_int(avl, 404); - avl = gpr_avl_add(avl, box(294), box(1184), NULL); - avl = remove_int(avl, 474); - avl = gpr_avl_add(avl, box(228), box(1186), NULL); - avl = gpr_avl_add(avl, box(484), box(1187), NULL); - avl = remove_int(avl, 238); - avl = remove_int(avl, 53); - avl = remove_int(avl, 691); - avl = gpr_avl_add(avl, box(345), box(1191), NULL); - avl = remove_int(avl, 0); - avl = gpr_avl_add(avl, box(230), box(1193), NULL); - avl = remove_int(avl, 227); - avl = remove_int(avl, 152); - avl = gpr_avl_add(avl, box(884), box(1196), NULL); - avl = remove_int(avl, 823); - avl = remove_int(avl, 53); - avl = gpr_avl_add(avl, box(1015), box(1199), NULL); - avl = gpr_avl_add(avl, box(697), box(1200), NULL); - avl = gpr_avl_add(avl, box(376), box(1201), NULL); - avl = remove_int(avl, 411); - avl = gpr_avl_add(avl, box(888), box(1203), NULL); - avl = remove_int(avl, 55); - avl = gpr_avl_add(avl, box(85), box(1205), NULL); - avl = remove_int(avl, 947); - avl = remove_int(avl, 382); - avl = remove_int(avl, 777); - avl = gpr_avl_add(avl, box(1017), box(1209), NULL); - avl = gpr_avl_add(avl, box(169), box(1210), NULL); - avl = gpr_avl_add(avl, box(156), box(1211), NULL); - avl = remove_int(avl, 153); - avl = remove_int(avl, 642); - avl = remove_int(avl, 158); - avl = gpr_avl_add(avl, box(554), box(1215), NULL); - avl = gpr_avl_add(avl, box(76), box(1216), NULL); - avl = gpr_avl_add(avl, box(756), box(1217), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(712), box(1227), NULL); - avl = gpr_avl_add(avl, box(474), box(1228), NULL); - avl = gpr_avl_add(avl, box(882), box(1229), NULL); - avl = gpr_avl_add(avl, box(965), box(1230), NULL); - avl = remove_int(avl, 464); - avl = gpr_avl_add(avl, box(319), box(1232), NULL); - avl = gpr_avl_add(avl, box(504), box(1233), NULL); - avl = remove_int(avl, 818); - avl = gpr_avl_add(avl, box(884), box(1235), NULL); - avl = gpr_avl_add(avl, box(813), box(1236), NULL); - avl = gpr_avl_add(avl, box(795), box(1237), NULL); - avl = remove_int(avl, 306); - avl = gpr_avl_add(avl, box(799), box(1239), NULL); - avl = remove_int(avl, 534); - avl = gpr_avl_add(avl, box(480), box(1241), NULL); - avl = gpr_avl_add(avl, box(656), box(1242), NULL); - avl = gpr_avl_add(avl, box(709), box(1243), NULL); - avl = gpr_avl_add(avl, box(500), box(1244), NULL); - avl = remove_int(avl, 740); - avl = gpr_avl_add(avl, box(980), box(1246), NULL); - avl = gpr_avl_add(avl, box(458), box(1247), NULL); - avl = remove_int(avl, 377); - avl = remove_int(avl, 338); - avl = gpr_avl_add(avl, box(554), box(1250), NULL); - avl = gpr_avl_add(avl, box(504), box(1251), NULL); - avl = gpr_avl_add(avl, box(603), box(1252), NULL); - avl = gpr_avl_add(avl, box(761), box(1253), NULL); - avl = remove_int(avl, 431); - avl = gpr_avl_add(avl, box(707), box(1255), NULL); - avl = gpr_avl_add(avl, box(673), box(1256), NULL); - 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), NULL); - avl = remove_int(avl, 858); - avl = remove_int(avl, 997); - avl = gpr_avl_add(avl, box(519), box(1267), NULL); - avl = remove_int(avl, 614); - avl = remove_int(avl, 462); - avl = remove_int(avl, 792); - avl = gpr_avl_add(avl, box(987), box(1271), NULL); - avl = gpr_avl_add(avl, box(309), box(1272), NULL); - avl = remove_int(avl, 747); - avl = gpr_avl_add(avl, box(621), box(1274), NULL); - avl = gpr_avl_add(avl, box(450), box(1275), NULL); - avl = remove_int(avl, 265); - avl = remove_int(avl, 8); - avl = remove_int(avl, 383); - avl = gpr_avl_add(avl, box(238), box(1279), NULL); - avl = remove_int(avl, 241); - avl = gpr_avl_add(avl, box(180), box(1281), NULL); - avl = gpr_avl_add(avl, box(411), box(1282), NULL); - avl = gpr_avl_add(avl, box(791), box(1283), NULL); - avl = gpr_avl_add(avl, box(955), box(1284), NULL); - avl = remove_int(avl, 24); - avl = remove_int(avl, 375); - avl = gpr_avl_add(avl, box(140), box(1287), NULL); - avl = remove_int(avl, 949); - avl = gpr_avl_add(avl, box(301), box(1289), NULL); - avl = gpr_avl_add(avl, box(0), box(1290), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(127), box(1296), NULL); - avl = gpr_avl_add(avl, box(279), box(1297), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(304), box(1304), NULL); - avl = gpr_avl_add(avl, box(1), box(1305), NULL); - avl = gpr_avl_add(avl, box(339), box(1306), NULL); - 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), NULL); - avl = remove_int(avl, 85); - avl = gpr_avl_add(avl, box(964), box(1314), NULL); - avl = gpr_avl_add(avl, box(559), box(1315), NULL); - avl = remove_int(avl, 167); - avl = gpr_avl_add(avl, box(866), box(1317), NULL); - avl = remove_int(avl, 275); - avl = gpr_avl_add(avl, box(173), box(1319), NULL); - avl = gpr_avl_add(avl, box(765), box(1320), NULL); - avl = remove_int(avl, 883); - avl = gpr_avl_add(avl, box(547), box(1322), NULL); - avl = gpr_avl_add(avl, box(847), box(1323), NULL); - avl = remove_int(avl, 817); - avl = remove_int(avl, 850); - avl = remove_int(avl, 718); - avl = gpr_avl_add(avl, box(806), box(1327), NULL); - avl = gpr_avl_add(avl, box(360), box(1328), NULL); - avl = remove_int(avl, 991); - avl = gpr_avl_add(avl, box(493), box(1330), NULL); - avl = remove_int(avl, 516); - avl = gpr_avl_add(avl, box(361), box(1332), NULL); - avl = remove_int(avl, 355); - avl = gpr_avl_add(avl, box(512), box(1334), NULL); - avl = gpr_avl_add(avl, box(191), box(1335), NULL); - avl = remove_int(avl, 703); - avl = gpr_avl_add(avl, box(333), box(1337), NULL); - avl = remove_int(avl, 481); - avl = gpr_avl_add(avl, box(501), box(1339), NULL); - avl = remove_int(avl, 532); - avl = remove_int(avl, 510); - avl = gpr_avl_add(avl, box(793), box(1342), NULL); - avl = gpr_avl_add(avl, box(234), box(1343), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(702), box(1349), NULL); - avl = gpr_avl_add(avl, box(149), box(1350), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(455), box(1358), NULL); - avl = remove_int(avl, 782); - avl = remove_int(avl, 682); - avl = gpr_avl_add(avl, box(243), box(1361), NULL); - avl = gpr_avl_add(avl, box(109), box(1362), NULL); - avl = gpr_avl_add(avl, box(452), box(1363), NULL); - avl = remove_int(avl, 151); - avl = gpr_avl_add(avl, box(159), box(1365), NULL); - avl = remove_int(avl, 1023); - avl = gpr_avl_add(avl, box(129), box(1367), NULL); - avl = gpr_avl_add(avl, box(537), box(1368), NULL); - avl = remove_int(avl, 321); - avl = gpr_avl_add(avl, box(740), box(1370), NULL); - avl = remove_int(avl, 45); - avl = remove_int(avl, 136); - avl = gpr_avl_add(avl, box(229), box(1373), NULL); - avl = remove_int(avl, 772); - avl = gpr_avl_add(avl, box(181), box(1375), NULL); - avl = remove_int(avl, 175); - avl = gpr_avl_add(avl, box(817), box(1377), NULL); - avl = remove_int(avl, 956); - avl = gpr_avl_add(avl, box(675), box(1379), NULL); - avl = gpr_avl_add(avl, box(375), box(1380), NULL); - avl = remove_int(avl, 384); - avl = gpr_avl_add(avl, box(1016), box(1382), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(293), box(1389), NULL); - avl = remove_int(avl, 207); - avl = remove_int(avl, 46); - avl = gpr_avl_add(avl, box(899), box(1392), NULL); - avl = gpr_avl_add(avl, box(666), box(1393), NULL); - avl = gpr_avl_add(avl, box(85), box(1394), NULL); - avl = gpr_avl_add(avl, box(914), box(1395), NULL); - avl = gpr_avl_add(avl, box(128), box(1396), NULL); - avl = gpr_avl_add(avl, box(835), box(1397), NULL); - avl = gpr_avl_add(avl, box(787), box(1398), NULL); - avl = gpr_avl_add(avl, box(649), box(1399), NULL); - avl = gpr_avl_add(avl, box(723), box(1400), NULL); - avl = remove_int(avl, 874); - avl = gpr_avl_add(avl, box(778), box(1402), NULL); - avl = gpr_avl_add(avl, box(1015), box(1403), NULL); - avl = gpr_avl_add(avl, box(59), box(1404), NULL); - avl = gpr_avl_add(avl, box(259), box(1405), NULL); - avl = gpr_avl_add(avl, box(758), box(1406), NULL); - avl = remove_int(avl, 648); - avl = gpr_avl_add(avl, box(145), box(1408), NULL); - avl = gpr_avl_add(avl, box(440), box(1409), NULL); - avl = remove_int(avl, 608); - avl = remove_int(avl, 690); - avl = gpr_avl_add(avl, box(605), box(1412), NULL); - avl = remove_int(avl, 856); - avl = remove_int(avl, 608); - avl = gpr_avl_add(avl, box(829), box(1415), NULL); - avl = gpr_avl_add(avl, box(660), box(1416), NULL); - avl = remove_int(avl, 596); - avl = gpr_avl_add(avl, box(519), box(1418), NULL); - avl = gpr_avl_add(avl, box(35), box(1419), NULL); - avl = gpr_avl_add(avl, box(871), box(1420), NULL); - avl = remove_int(avl, 845); - avl = gpr_avl_add(avl, box(600), box(1422), NULL); - avl = gpr_avl_add(avl, box(215), box(1423), NULL); - avl = remove_int(avl, 761); - avl = gpr_avl_add(avl, box(975), box(1425), NULL); - avl = remove_int(avl, 987); - avl = gpr_avl_add(avl, box(58), box(1427), NULL); - avl = remove_int(avl, 119); - avl = gpr_avl_add(avl, box(937), box(1429), NULL); - avl = gpr_avl_add(avl, box(372), box(1430), NULL); - avl = gpr_avl_add(avl, box(11), box(1431), NULL); - avl = gpr_avl_add(avl, box(398), box(1432), NULL); - avl = gpr_avl_add(avl, box(423), box(1433), NULL); - avl = remove_int(avl, 171); - avl = gpr_avl_add(avl, box(473), box(1435), NULL); - 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), NULL); - 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), NULL); - avl = remove_int(avl, 152); - avl = gpr_avl_add(avl, box(61), box(1448), NULL); - avl = remove_int(avl, 929); - avl = remove_int(avl, 9); - avl = gpr_avl_add(avl, box(251), box(1451), NULL); - avl = gpr_avl_add(avl, box(672), box(1452), NULL); - avl = gpr_avl_add(avl, box(66), box(1453), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(495), box(1459), NULL); - avl = remove_int(avl, 450); - avl = gpr_avl_add(avl, box(533), box(1461), NULL); - avl = gpr_avl_add(avl, box(414), box(1462), NULL); - avl = remove_int(avl, 74); - avl = remove_int(avl, 236); - avl = gpr_avl_add(avl, box(707), box(1465), NULL); - avl = gpr_avl_add(avl, box(357), box(1466), NULL); - avl = gpr_avl_add(avl, box(1007), box(1467), NULL); - avl = gpr_avl_add(avl, box(811), box(1468), NULL); - avl = gpr_avl_add(avl, box(418), box(1469), NULL); - avl = gpr_avl_add(avl, box(164), box(1470), NULL); - avl = gpr_avl_add(avl, box(622), box(1471), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(202), box(1478), NULL); - avl = gpr_avl_add(avl, box(312), box(1479), NULL); - avl = remove_int(avl, 274); - avl = gpr_avl_add(avl, box(684), box(1481), NULL); - avl = gpr_avl_add(avl, box(954), box(1482), NULL); - avl = gpr_avl_add(avl, box(637), box(1483), NULL); - avl = remove_int(avl, 716); - avl = gpr_avl_add(avl, box(198), box(1485), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(862), box(1491), NULL); - avl = remove_int(avl, 527); - avl = gpr_avl_add(avl, box(945), box(1493), NULL); - avl = remove_int(avl, 355); - avl = remove_int(avl, 144); - avl = gpr_avl_add(avl, box(229), box(1496), NULL); - avl = gpr_avl_add(avl, box(237), box(1497), NULL); - avl = remove_int(avl, 471); - avl = remove_int(avl, 901); - avl = gpr_avl_add(avl, box(905), box(1500), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(552), box(1506), NULL); - avl = gpr_avl_add(avl, box(30), box(1507), NULL); - avl = gpr_avl_add(avl, box(445), box(1508), NULL); - avl = remove_int(avl, 785); - avl = remove_int(avl, 185); - avl = gpr_avl_add(avl, box(405), box(1511), NULL); - avl = gpr_avl_add(avl, box(733), box(1512), NULL); - avl = gpr_avl_add(avl, box(573), box(1513), NULL); - avl = gpr_avl_add(avl, box(492), box(1514), NULL); - avl = gpr_avl_add(avl, box(343), box(1515), NULL); - avl = gpr_avl_add(avl, box(527), box(1516), NULL); - avl = gpr_avl_add(avl, box(596), box(1517), NULL); - avl = gpr_avl_add(avl, box(519), box(1518), NULL); - avl = remove_int(avl, 243); - avl = remove_int(avl, 722); - avl = gpr_avl_add(avl, box(772), box(1521), NULL); - avl = remove_int(avl, 152); - avl = remove_int(avl, 305); - avl = gpr_avl_add(avl, box(754), box(1524), NULL); - avl = gpr_avl_add(avl, box(373), box(1525), NULL); - avl = remove_int(avl, 995); - avl = gpr_avl_add(avl, box(329), box(1527), NULL); - avl = remove_int(avl, 397); - avl = gpr_avl_add(avl, box(884), box(1529), NULL); - avl = remove_int(avl, 329); - avl = remove_int(avl, 240); - avl = gpr_avl_add(avl, box(566), box(1532), NULL); - avl = gpr_avl_add(avl, box(232), box(1533), NULL); - avl = remove_int(avl, 993); - avl = gpr_avl_add(avl, box(888), box(1535), NULL); - avl = remove_int(avl, 242); - avl = gpr_avl_add(avl, box(941), box(1537), NULL); - avl = remove_int(avl, 415); - avl = gpr_avl_add(avl, box(992), box(1539), NULL); - avl = remove_int(avl, 289); - avl = gpr_avl_add(avl, box(60), box(1541), NULL); - avl = gpr_avl_add(avl, box(97), box(1542), NULL); - avl = remove_int(avl, 965); - avl = remove_int(avl, 267); - avl = remove_int(avl, 360); - avl = gpr_avl_add(avl, box(5), box(1546), NULL); - avl = remove_int(avl, 429); - avl = gpr_avl_add(avl, box(412), box(1548), NULL); - avl = remove_int(avl, 632); - avl = remove_int(avl, 113); - avl = gpr_avl_add(avl, box(48), box(1551), NULL); - avl = gpr_avl_add(avl, box(108), box(1552), NULL); - avl = gpr_avl_add(avl, box(750), box(1553), NULL); - avl = remove_int(avl, 188); - avl = gpr_avl_add(avl, box(668), box(1555), NULL); - avl = remove_int(avl, 37); - avl = remove_int(avl, 737); - avl = gpr_avl_add(avl, box(93), box(1558), NULL); - avl = gpr_avl_add(avl, box(628), box(1559), NULL); - avl = gpr_avl_add(avl, box(480), box(1560), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(469), box(1567), NULL); - avl = remove_int(avl, 349); - avl = gpr_avl_add(avl, box(768), box(1569), NULL); - avl = gpr_avl_add(avl, box(915), box(1570), NULL); - avl = remove_int(avl, 1014); - avl = gpr_avl_add(avl, box(117), box(1572), NULL); - avl = remove_int(avl, 62); - avl = gpr_avl_add(avl, box(382), box(1574), NULL); - avl = remove_int(avl, 571); - avl = gpr_avl_add(avl, box(655), box(1576), NULL); - avl = gpr_avl_add(avl, box(323), box(1577), NULL); - avl = remove_int(avl, 869); - avl = remove_int(avl, 151); - avl = gpr_avl_add(avl, box(1019), box(1580), NULL); - avl = gpr_avl_add(avl, box(984), box(1581), NULL); - avl = gpr_avl_add(avl, box(870), box(1582), NULL); - avl = gpr_avl_add(avl, box(376), box(1583), NULL); - avl = remove_int(avl, 625); - avl = gpr_avl_add(avl, box(733), box(1585), NULL); - avl = remove_int(avl, 532); - avl = remove_int(avl, 444); - avl = gpr_avl_add(avl, box(428), box(1588), NULL); - avl = gpr_avl_add(avl, box(860), box(1589), NULL); - avl = gpr_avl_add(avl, box(173), box(1590), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(639), box(1596), NULL); - avl = remove_int(avl, 431); - avl = gpr_avl_add(avl, box(993), box(1598), NULL); - avl = remove_int(avl, 681); - avl = remove_int(avl, 927); - avl = gpr_avl_add(avl, box(87), box(1601), NULL); - avl = gpr_avl_add(avl, box(91), box(1602), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(951), box(1609), NULL); - avl = gpr_avl_add(avl, box(146), box(1610), NULL); - avl = gpr_avl_add(avl, box(482), box(1611), NULL); - avl = gpr_avl_add(avl, box(71), box(1612), NULL); - avl = remove_int(avl, 246); - avl = remove_int(avl, 696); - avl = gpr_avl_add(avl, box(636), box(1615), NULL); - avl = gpr_avl_add(avl, box(295), box(1616), NULL); - avl = remove_int(avl, 11); - avl = remove_int(avl, 231); - avl = gpr_avl_add(avl, box(905), box(1619), NULL); - avl = gpr_avl_add(avl, box(993), box(1620), NULL); - avl = gpr_avl_add(avl, box(433), box(1621), NULL); - avl = gpr_avl_add(avl, box(117), box(1622), NULL); - avl = gpr_avl_add(avl, box(467), box(1623), NULL); - avl = remove_int(avl, 419); - avl = gpr_avl_add(avl, box(179), box(1625), NULL); - avl = remove_int(avl, 926); - avl = remove_int(avl, 326); - avl = gpr_avl_add(avl, box(551), box(1628), NULL); - avl = remove_int(avl, 14); - avl = remove_int(avl, 476); - avl = remove_int(avl, 823); - avl = gpr_avl_add(avl, box(350), box(1632), NULL); - avl = gpr_avl_add(avl, box(133), box(1633), NULL); - avl = remove_int(avl, 906); - avl = gpr_avl_add(avl, box(827), box(1635), NULL); - avl = gpr_avl_add(avl, box(201), box(1636), NULL); - avl = remove_int(avl, 124); - avl = remove_int(avl, 662); - avl = gpr_avl_add(avl, box(314), box(1639), NULL); - avl = gpr_avl_add(avl, box(986), box(1640), NULL); - avl = gpr_avl_add(avl, box(622), box(1641), NULL); - avl = remove_int(avl, 130); - avl = gpr_avl_add(avl, box(861), box(1643), NULL); - avl = remove_int(avl, 497); - avl = remove_int(avl, 905); - avl = gpr_avl_add(avl, box(502), box(1646), NULL); - avl = remove_int(avl, 721); - avl = gpr_avl_add(avl, box(514), box(1648), NULL); - avl = gpr_avl_add(avl, box(410), box(1649), NULL); - avl = remove_int(avl, 869); - avl = remove_int(avl, 247); - avl = gpr_avl_add(avl, box(450), box(1652), NULL); - avl = remove_int(avl, 364); - avl = gpr_avl_add(avl, box(963), box(1654), NULL); - avl = gpr_avl_add(avl, box(146), box(1655), NULL); - avl = remove_int(avl, 147); - avl = remove_int(avl, 789); - avl = gpr_avl_add(avl, box(693), box(1658), NULL); - avl = gpr_avl_add(avl, box(959), box(1659), NULL); - avl = remove_int(avl, 478); - avl = gpr_avl_add(avl, box(116), box(1661), NULL); - avl = gpr_avl_add(avl, box(520), box(1662), NULL); - avl = gpr_avl_add(avl, box(809), box(1663), NULL); - avl = gpr_avl_add(avl, box(667), box(1664), NULL); - avl = gpr_avl_add(avl, box(406), box(1665), NULL); - avl = remove_int(avl, 409); - avl = gpr_avl_add(avl, box(558), box(1667), NULL); - avl = gpr_avl_add(avl, box(0), box(1668), NULL); - avl = gpr_avl_add(avl, box(948), box(1669), NULL); - avl = gpr_avl_add(avl, box(576), box(1670), NULL); - avl = remove_int(avl, 864); - avl = remove_int(avl, 840); - avl = remove_int(avl, 1001); - avl = gpr_avl_add(avl, box(232), box(1674), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(648), box(1680), NULL); - avl = gpr_avl_add(avl, box(761), box(1681), NULL); - avl = remove_int(avl, 293); - avl = remove_int(avl, 893); - avl = gpr_avl_add(avl, box(194), box(1684), NULL); - avl = remove_int(avl, 233); - avl = gpr_avl_add(avl, box(888), box(1686), NULL); - 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), NULL); - avl = remove_int(avl, 634); - avl = remove_int(avl, 335); - avl = gpr_avl_add(avl, box(718), box(1694), NULL); - avl = gpr_avl_add(avl, box(463), box(1695), NULL); - avl = gpr_avl_add(avl, box(233), box(1696), NULL); - 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), NULL); - avl = remove_int(avl, 329); - avl = gpr_avl_add(avl, box(716), box(1705), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(212), box(1714), NULL); - avl = gpr_avl_add(avl, box(266), box(1715), NULL); - avl = gpr_avl_add(avl, box(238), box(1716), NULL); - avl = remove_int(avl, 153); - avl = gpr_avl_add(avl, box(585), box(1718), NULL); - avl = remove_int(avl, 121); - avl = gpr_avl_add(avl, box(534), box(1720), NULL); - avl = remove_int(avl, 579); - avl = gpr_avl_add(avl, box(127), box(1722), NULL); - avl = gpr_avl_add(avl, box(399), box(1723), NULL); - avl = remove_int(avl, 417); - avl = gpr_avl_add(avl, box(978), box(1725), NULL); - avl = gpr_avl_add(avl, box(768), box(1726), NULL); - avl = remove_int(avl, 985); - avl = gpr_avl_add(avl, box(536), box(1728), NULL); - avl = gpr_avl_add(avl, box(449), box(1729), NULL); - avl = gpr_avl_add(avl, box(586), box(1730), NULL); - avl = remove_int(avl, 998); - avl = remove_int(avl, 394); - avl = remove_int(avl, 141); - avl = gpr_avl_add(avl, box(889), box(1734), NULL); - avl = gpr_avl_add(avl, box(871), box(1735), NULL); - avl = gpr_avl_add(avl, box(76), box(1736), NULL); - avl = gpr_avl_add(avl, box(549), box(1737), NULL); - avl = gpr_avl_add(avl, box(757), box(1738), NULL); - avl = remove_int(avl, 908); - avl = gpr_avl_add(avl, box(789), box(1740), NULL); - avl = remove_int(avl, 224); - avl = gpr_avl_add(avl, box(407), box(1742), NULL); - avl = gpr_avl_add(avl, box(381), box(1743), NULL); - avl = gpr_avl_add(avl, box(561), box(1744), NULL); - avl = gpr_avl_add(avl, box(667), box(1745), NULL); - avl = gpr_avl_add(avl, box(522), box(1746), NULL); - avl = gpr_avl_add(avl, box(948), box(1747), NULL); - avl = remove_int(avl, 770); - avl = gpr_avl_add(avl, box(872), box(1749), NULL); - avl = gpr_avl_add(avl, box(327), box(1750), NULL); - avl = remove_int(avl, 10); - avl = gpr_avl_add(avl, box(122), box(1752), NULL); - avl = remove_int(avl, 606); - avl = gpr_avl_add(avl, box(485), box(1754), NULL); - avl = remove_int(avl, 6); - avl = gpr_avl_add(avl, box(329), box(1756), NULL); - avl = gpr_avl_add(avl, box(783), box(1757), NULL); - avl = remove_int(avl, 416); - avl = gpr_avl_add(avl, box(656), box(1759), NULL); - avl = gpr_avl_add(avl, box(971), box(1760), NULL); - avl = gpr_avl_add(avl, box(77), box(1761), NULL); - avl = gpr_avl_add(avl, box(942), box(1762), NULL); - avl = remove_int(avl, 361); - avl = gpr_avl_add(avl, box(66), box(1764), NULL); - avl = gpr_avl_add(avl, box(299), box(1765), NULL); - avl = gpr_avl_add(avl, box(929), box(1766), NULL); - avl = gpr_avl_add(avl, box(797), box(1767), NULL); - avl = remove_int(avl, 869); - avl = remove_int(avl, 907); - avl = gpr_avl_add(avl, box(870), box(1770), NULL); - avl = remove_int(avl, 580); - avl = remove_int(avl, 120); - avl = gpr_avl_add(avl, box(913), box(1773), NULL); - avl = remove_int(avl, 480); - avl = gpr_avl_add(avl, box(489), box(1775), NULL); - avl = remove_int(avl, 845); - avl = gpr_avl_add(avl, box(896), box(1777), NULL); - avl = remove_int(avl, 567); - avl = remove_int(avl, 427); - avl = gpr_avl_add(avl, box(443), box(1780), NULL); - avl = gpr_avl_add(avl, box(3), box(1781), NULL); - avl = remove_int(avl, 12); - avl = gpr_avl_add(avl, box(376), box(1783), NULL); - avl = gpr_avl_add(avl, box(155), box(1784), NULL); - avl = gpr_avl_add(avl, box(188), box(1785), NULL); - avl = gpr_avl_add(avl, box(149), box(1786), NULL); - avl = gpr_avl_add(avl, box(178), box(1787), NULL); - avl = remove_int(avl, 84); - avl = gpr_avl_add(avl, box(805), box(1789), NULL); - avl = gpr_avl_add(avl, box(612), box(1790), NULL); - avl = remove_int(avl, 991); - avl = gpr_avl_add(avl, box(837), box(1792), NULL); - avl = remove_int(avl, 173); - avl = remove_int(avl, 72); - avl = gpr_avl_add(avl, box(1014), box(1795), NULL); - avl = remove_int(avl, 303); - avl = gpr_avl_add(avl, box(865), box(1797), NULL); - avl = gpr_avl_add(avl, box(793), box(1798), NULL); - avl = remove_int(avl, 173); - avl = remove_int(avl, 477); - avl = gpr_avl_add(avl, box(950), box(1801), NULL); - avl = gpr_avl_add(avl, box(105), box(1802), NULL); - avl = gpr_avl_add(avl, box(895), box(1803), NULL); - avl = gpr_avl_add(avl, box(171), box(1804), NULL); - avl = gpr_avl_add(avl, box(753), box(1805), NULL); - avl = gpr_avl_add(avl, box(946), box(1806), NULL); - avl = remove_int(avl, 194); - avl = remove_int(avl, 559); - avl = remove_int(avl, 116); - avl = gpr_avl_add(avl, box(968), box(1810), NULL); - avl = remove_int(avl, 124); - avl = remove_int(avl, 99); - avl = gpr_avl_add(avl, box(563), box(1813), NULL); - avl = remove_int(avl, 182); - avl = gpr_avl_add(avl, box(816), box(1815), NULL); - avl = remove_int(avl, 73); - avl = remove_int(avl, 261); - avl = gpr_avl_add(avl, box(847), box(1818), NULL); - avl = gpr_avl_add(avl, box(368), box(1819), NULL); - avl = gpr_avl_add(avl, box(808), box(1820), NULL); - avl = gpr_avl_add(avl, box(779), box(1821), NULL); - avl = remove_int(avl, 818); - avl = gpr_avl_add(avl, box(466), box(1823), NULL); - avl = remove_int(avl, 316); - avl = gpr_avl_add(avl, box(986), box(1825), NULL); - avl = gpr_avl_add(avl, box(688), box(1826), NULL); - avl = gpr_avl_add(avl, box(509), box(1827), NULL); - avl = gpr_avl_add(avl, box(51), box(1828), NULL); - avl = remove_int(avl, 655); - avl = remove_int(avl, 785); - avl = remove_int(avl, 893); - avl = gpr_avl_add(avl, box(167), box(1832), NULL); - avl = remove_int(avl, 13); - avl = remove_int(avl, 263); - avl = gpr_avl_add(avl, box(1009), box(1835), NULL); - 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), NULL); - avl = remove_int(avl, 267); - avl = gpr_avl_add(avl, box(676), box(1842), NULL); - avl = gpr_avl_add(avl, box(231), box(1843), NULL); - avl = gpr_avl_add(avl, box(824), box(1844), NULL); - avl = remove_int(avl, 961); - avl = gpr_avl_add(avl, box(311), box(1846), NULL); - avl = gpr_avl_add(avl, box(420), box(1847), NULL); - avl = gpr_avl_add(avl, box(960), box(1848), NULL); - avl = gpr_avl_add(avl, box(468), box(1849), NULL); - avl = gpr_avl_add(avl, box(815), box(1850), NULL); - avl = remove_int(avl, 247); - avl = remove_int(avl, 194); - avl = gpr_avl_add(avl, box(546), box(1853), NULL); - avl = remove_int(avl, 222); - avl = remove_int(avl, 914); - avl = remove_int(avl, 741); - avl = gpr_avl_add(avl, box(470), box(1857), NULL); - avl = gpr_avl_add(avl, box(933), box(1858), NULL); - avl = gpr_avl_add(avl, box(97), box(1859), NULL); - avl = remove_int(avl, 564); - avl = remove_int(avl, 295); - avl = gpr_avl_add(avl, box(864), box(1862), NULL); - avl = remove_int(avl, 329); - avl = gpr_avl_add(avl, box(124), box(1864), NULL); - avl = gpr_avl_add(avl, box(1000), box(1865), NULL); - avl = gpr_avl_add(avl, box(228), box(1866), NULL); - avl = gpr_avl_add(avl, box(187), box(1867), NULL); - avl = remove_int(avl, 224); - avl = remove_int(avl, 306); - avl = remove_int(avl, 884); - avl = gpr_avl_add(avl, box(449), box(1871), NULL); - avl = gpr_avl_add(avl, box(353), box(1872), NULL); - avl = gpr_avl_add(avl, box(994), box(1873), NULL); - avl = gpr_avl_add(avl, box(596), box(1874), NULL); - avl = gpr_avl_add(avl, box(996), box(1875), NULL); - avl = gpr_avl_add(avl, box(101), box(1876), NULL); - avl = gpr_avl_add(avl, box(1012), box(1877), NULL); - avl = gpr_avl_add(avl, box(982), box(1878), NULL); - avl = gpr_avl_add(avl, box(742), box(1879), NULL); - avl = remove_int(avl, 92); - avl = remove_int(avl, 1022); - avl = gpr_avl_add(avl, box(941), box(1882), NULL); - avl = remove_int(avl, 742); - avl = remove_int(avl, 919); - avl = gpr_avl_add(avl, box(588), box(1885), NULL); - avl = remove_int(avl, 221); - avl = gpr_avl_add(avl, box(356), box(1887), NULL); - avl = gpr_avl_add(avl, box(932), box(1888), NULL); - avl = remove_int(avl, 837); - avl = gpr_avl_add(avl, box(394), box(1890), NULL); - avl = gpr_avl_add(avl, box(642), box(1891), NULL); - avl = gpr_avl_add(avl, box(52), box(1892), NULL); - avl = gpr_avl_add(avl, box(437), box(1893), NULL); - avl = gpr_avl_add(avl, box(948), box(1894), NULL); - avl = gpr_avl_add(avl, box(93), box(1895), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(952), box(1901), NULL); - avl = gpr_avl_add(avl, box(510), box(1902), NULL); - avl = remove_int(avl, 876); - avl = remove_int(avl, 612); - avl = gpr_avl_add(avl, box(923), box(1905), NULL); - avl = gpr_avl_add(avl, box(475), box(1906), NULL); - avl = remove_int(avl, 478); - avl = remove_int(avl, 148); - avl = gpr_avl_add(avl, box(538), box(1909), NULL); - avl = remove_int(avl, 47); - avl = gpr_avl_add(avl, box(89), box(1911), NULL); - avl = remove_int(avl, 723); - avl = gpr_avl_add(avl, box(687), box(1913), NULL); - avl = gpr_avl_add(avl, box(480), box(1914), NULL); - avl = gpr_avl_add(avl, box(149), box(1915), NULL); - avl = remove_int(avl, 68); - avl = remove_int(avl, 862); - avl = remove_int(avl, 363); - avl = gpr_avl_add(avl, box(996), box(1919), NULL); - avl = remove_int(avl, 380); - avl = gpr_avl_add(avl, box(957), box(1921), NULL); - avl = remove_int(avl, 413); - avl = gpr_avl_add(avl, box(360), box(1923), NULL); - avl = gpr_avl_add(avl, box(304), box(1924), NULL); - avl = gpr_avl_add(avl, box(634), box(1925), NULL); - avl = gpr_avl_add(avl, box(506), box(1926), NULL); - avl = remove_int(avl, 248); - avl = gpr_avl_add(avl, box(124), box(1928), NULL); - avl = gpr_avl_add(avl, box(181), box(1929), NULL); - avl = remove_int(avl, 507); - avl = gpr_avl_add(avl, box(141), box(1931), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(906), box(1937), NULL); - avl = gpr_avl_add(avl, box(44), box(1938), NULL); - avl = remove_int(avl, 949); - avl = remove_int(avl, 117); - avl = gpr_avl_add(avl, box(700), box(1941), NULL); - avl = gpr_avl_add(avl, box(258), box(1942), NULL); - avl = remove_int(avl, 828); - avl = gpr_avl_add(avl, box(860), box(1944), NULL); - avl = gpr_avl_add(avl, box(987), box(1945), NULL); - avl = gpr_avl_add(avl, box(316), box(1946), NULL); - avl = gpr_avl_add(avl, box(919), box(1947), NULL); - avl = remove_int(avl, 84); - avl = gpr_avl_add(avl, box(473), box(1949), NULL); - avl = remove_int(avl, 127); - avl = remove_int(avl, 829); - avl = remove_int(avl, 829); - avl = gpr_avl_add(avl, box(488), box(1953), NULL); - avl = gpr_avl_add(avl, box(954), box(1954), NULL); - avl = remove_int(avl, 198); - avl = remove_int(avl, 972); - avl = remove_int(avl, 670); - avl = gpr_avl_add(avl, box(822), box(1958), NULL); - avl = remove_int(avl, 589); - avl = remove_int(avl, 459); - avl = gpr_avl_add(avl, box(1003), box(1961), NULL); - avl = gpr_avl_add(avl, box(657), box(1962), NULL); - avl = gpr_avl_add(avl, box(477), box(1963), NULL); - avl = gpr_avl_add(avl, box(923), box(1964), NULL); - avl = remove_int(avl, 496); - avl = remove_int(avl, 99); - avl = gpr_avl_add(avl, box(127), box(1967), NULL); - avl = gpr_avl_add(avl, box(1013), box(1968), NULL); - avl = gpr_avl_add(avl, box(778), box(1969), NULL); - 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), NULL); - 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), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(412), box(1986), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(408), box(1992), NULL); - avl = gpr_avl_add(avl, box(841), box(1993), NULL); - avl = remove_int(avl, 593); - avl = gpr_avl_add(avl, box(582), box(1995), NULL); - avl = gpr_avl_add(avl, box(597), box(1996), NULL); - avl = remove_int(avl, 49); - avl = remove_int(avl, 835); - avl = gpr_avl_add(avl, box(417), box(1999), NULL); - avl = gpr_avl_add(avl, box(191), box(2000), NULL); - avl = remove_int(avl, 406); - avl = gpr_avl_add(avl, box(30), box(2002), NULL); - avl = remove_int(avl, 841); - avl = remove_int(avl, 50); - avl = gpr_avl_add(avl, box(967), box(2005), NULL); - avl = gpr_avl_add(avl, box(849), box(2006), NULL); - avl = remove_int(avl, 608); - avl = gpr_avl_add(avl, box(306), box(2008), NULL); - avl = remove_int(avl, 779); - avl = gpr_avl_add(avl, box(897), box(2010), NULL); - avl = gpr_avl_add(avl, box(147), box(2011), NULL); - avl = remove_int(avl, 982); - avl = gpr_avl_add(avl, box(470), box(2013), NULL); - avl = remove_int(avl, 951); - avl = gpr_avl_add(avl, box(388), box(2015), NULL); - 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), NULL); - avl = remove_int(avl, 671); - avl = gpr_avl_add(avl, box(1020), box(2022), NULL); - avl = remove_int(avl, 277); - avl = gpr_avl_add(avl, box(681), box(2024), NULL); - avl = gpr_avl_add(avl, box(179), box(2025), NULL); - avl = gpr_avl_add(avl, box(370), box(2026), NULL); - avl = gpr_avl_add(avl, box(0), box(2027), NULL); - avl = remove_int(avl, 523); - avl = gpr_avl_add(avl, box(99), box(2029), NULL); - avl = gpr_avl_add(avl, box(334), box(2030), NULL); - avl = gpr_avl_add(avl, box(569), box(2031), NULL); - avl = gpr_avl_add(avl, box(257), box(2032), NULL); - avl = remove_int(avl, 572); - avl = gpr_avl_add(avl, box(805), box(2034), NULL); - avl = gpr_avl_add(avl, box(143), box(2035), NULL); - avl = gpr_avl_add(avl, box(670), box(2036), NULL); - avl = remove_int(avl, 42); - avl = gpr_avl_add(avl, box(46), box(2038), NULL); - avl = remove_int(avl, 970); - avl = gpr_avl_add(avl, box(353), box(2040), NULL); - avl = remove_int(avl, 258); - avl = gpr_avl_add(avl, box(451), box(2042), NULL); - avl = gpr_avl_add(avl, box(28), box(2043), NULL); - avl = gpr_avl_add(avl, box(729), box(2044), NULL); - avl = gpr_avl_add(avl, box(401), box(2045), NULL); - avl = gpr_avl_add(avl, box(614), box(2046), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(980), box(2052), NULL); - avl = gpr_avl_add(avl, box(990), box(2053), NULL); - avl = gpr_avl_add(avl, box(355), box(2054), NULL); - avl = remove_int(avl, 730); - avl = remove_int(avl, 37); - avl = gpr_avl_add(avl, box(407), box(2057), NULL); - avl = gpr_avl_add(avl, box(222), box(2058), NULL); - avl = gpr_avl_add(avl, box(439), box(2059), NULL); - avl = gpr_avl_add(avl, box(563), box(2060), NULL); - avl = remove_int(avl, 992); - avl = remove_int(avl, 786); - avl = gpr_avl_add(avl, box(1), box(2063), NULL); - avl = gpr_avl_add(avl, box(473), box(2064), NULL); - avl = gpr_avl_add(avl, box(992), box(2065), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(35), box(2071), NULL); - avl = remove_int(avl, 843); - avl = gpr_avl_add(avl, box(855), box(2073), NULL); - avl = remove_int(avl, 878); - avl = gpr_avl_add(avl, box(993), box(2075), NULL); - avl = gpr_avl_add(avl, box(87), box(2076), NULL); - avl = gpr_avl_add(avl, box(572), box(2077), NULL); - avl = remove_int(avl, 896); - avl = gpr_avl_add(avl, box(849), box(2079), NULL); - avl = remove_int(avl, 597); - avl = gpr_avl_add(avl, box(472), box(2081), NULL); - avl = remove_int(avl, 778); - avl = remove_int(avl, 934); - avl = remove_int(avl, 314); - avl = gpr_avl_add(avl, box(101), box(2085), NULL); - avl = remove_int(avl, 938); - avl = remove_int(avl, 1010); - avl = gpr_avl_add(avl, box(579), box(2088), NULL); - avl = remove_int(avl, 798); - avl = remove_int(avl, 88); - avl = gpr_avl_add(avl, box(851), box(2091), NULL); - avl = remove_int(avl, 705); - avl = gpr_avl_add(avl, box(26), box(2093), NULL); - avl = remove_int(avl, 973); - avl = gpr_avl_add(avl, box(923), box(2095), NULL); - avl = remove_int(avl, 668); - avl = gpr_avl_add(avl, box(310), box(2097), NULL); - avl = gpr_avl_add(avl, box(269), box(2098), NULL); - avl = remove_int(avl, 173); - avl = gpr_avl_add(avl, box(279), box(2100), NULL); - avl = remove_int(avl, 203); - avl = gpr_avl_add(avl, box(411), box(2102), NULL); - avl = remove_int(avl, 950); - avl = gpr_avl_add(avl, box(6), box(2104), NULL); - avl = remove_int(avl, 400); - avl = remove_int(avl, 468); - avl = remove_int(avl, 271); - avl = gpr_avl_add(avl, box(627), box(2108), NULL); - 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), NULL); - avl = remove_int(avl, 194); - avl = remove_int(avl, 18); - avl = gpr_avl_add(avl, box(727), box(2120), NULL); - avl = remove_int(avl, 295); - avl = gpr_avl_add(avl, box(645), box(2122), NULL); - avl = remove_int(avl, 321); - avl = remove_int(avl, 863); - avl = gpr_avl_add(avl, box(824), box(2125), NULL); - avl = gpr_avl_add(avl, box(651), box(2126), NULL); - avl = gpr_avl_add(avl, box(804), box(2127), NULL); - avl = remove_int(avl, 307); - avl = gpr_avl_add(avl, box(867), box(2129), NULL); - avl = remove_int(avl, 384); - avl = gpr_avl_add(avl, box(819), box(2131), NULL); - avl = remove_int(avl, 674); - avl = gpr_avl_add(avl, box(76), box(2133), NULL); - avl = remove_int(avl, 898); - avl = gpr_avl_add(avl, box(45), box(2135), NULL); - avl = gpr_avl_add(avl, box(512), box(2136), NULL); - 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), NULL); - avl = remove_int(avl, 509); - avl = remove_int(avl, 301); - avl = gpr_avl_add(avl, box(861), box(2146), NULL); - avl = gpr_avl_add(avl, box(918), box(2147), NULL); - avl = remove_int(avl, 992); - avl = gpr_avl_add(avl, box(356), box(2149), NULL); - avl = remove_int(avl, 64); - avl = remove_int(avl, 444); - avl = remove_int(avl, 741); - avl = gpr_avl_add(avl, box(710), box(2153), NULL); - avl = gpr_avl_add(avl, box(264), box(2154), NULL); - avl = remove_int(avl, 347); - avl = remove_int(avl, 250); - avl = gpr_avl_add(avl, box(82), box(2157), NULL); - avl = gpr_avl_add(avl, box(571), box(2158), NULL); - avl = remove_int(avl, 721); - avl = remove_int(avl, 622); - avl = gpr_avl_add(avl, box(950), box(2161), NULL); - avl = gpr_avl_add(avl, box(94), box(2162), NULL); - avl = remove_int(avl, 970); - avl = gpr_avl_add(avl, box(815), box(2164), NULL); - avl = remove_int(avl, 930); - avl = remove_int(avl, 703); - avl = gpr_avl_add(avl, box(432), box(2167), NULL); - avl = remove_int(avl, 544); - avl = gpr_avl_add(avl, box(21), box(2169), NULL); - avl = gpr_avl_add(avl, box(186), box(2170), NULL); - avl = remove_int(avl, 143); - avl = gpr_avl_add(avl, box(425), box(2172), NULL); - avl = remove_int(avl, 769); - avl = gpr_avl_add(avl, box(656), box(2174), NULL); - avl = remove_int(avl, 29); - avl = gpr_avl_add(avl, box(464), box(2176), NULL); - avl = remove_int(avl, 713); - avl = gpr_avl_add(avl, box(800), box(2178), NULL); - avl = remove_int(avl, 621); - avl = gpr_avl_add(avl, box(962), box(2180), NULL); - avl = remove_int(avl, 448); - avl = gpr_avl_add(avl, box(878), box(2182), NULL); - avl = remove_int(avl, 39); - avl = remove_int(avl, 999); - avl = gpr_avl_add(avl, box(182), box(2185), NULL); - avl = gpr_avl_add(avl, box(429), box(2186), NULL); - avl = gpr_avl_add(avl, box(598), box(2187), NULL); - avl = remove_int(avl, 551); - avl = gpr_avl_add(avl, box(827), box(2189), NULL); - avl = gpr_avl_add(avl, box(809), box(2190), NULL); - avl = remove_int(avl, 438); - avl = remove_int(avl, 811); - avl = gpr_avl_add(avl, box(808), box(2193), NULL); - avl = gpr_avl_add(avl, box(788), box(2194), NULL); - avl = remove_int(avl, 156); - avl = gpr_avl_add(avl, box(933), box(2196), NULL); - avl = gpr_avl_add(avl, box(344), box(2197), NULL); - avl = remove_int(avl, 460); - avl = gpr_avl_add(avl, box(161), box(2199), NULL); - avl = gpr_avl_add(avl, box(444), box(2200), NULL); - avl = remove_int(avl, 597); - avl = remove_int(avl, 668); - avl = gpr_avl_add(avl, box(703), box(2203), NULL); - avl = remove_int(avl, 515); - avl = gpr_avl_add(avl, box(380), box(2205), NULL); - avl = gpr_avl_add(avl, box(338), box(2206), NULL); - 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), NULL); - avl = remove_int(avl, 450); - avl = gpr_avl_add(avl, box(411), box(2213), NULL); - avl = gpr_avl_add(avl, box(117), box(2214), NULL); - avl = gpr_avl_add(avl, box(322), box(2215), NULL); - avl = gpr_avl_add(avl, box(915), box(2216), NULL); - avl = gpr_avl_add(avl, box(410), box(2217), NULL); - avl = gpr_avl_add(avl, box(66), box(2218), NULL); - avl = remove_int(avl, 756); - avl = remove_int(avl, 596); - avl = gpr_avl_add(avl, box(882), box(2221), NULL); - avl = gpr_avl_add(avl, box(930), box(2222), NULL); - avl = gpr_avl_add(avl, box(36), box(2223), NULL); - avl = remove_int(avl, 742); - avl = gpr_avl_add(avl, box(539), box(2225), NULL); - avl = gpr_avl_add(avl, box(596), box(2226), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(493), box(2233), NULL); - avl = gpr_avl_add(avl, box(839), box(2234), NULL); - avl = remove_int(avl, 774); - avl = gpr_avl_add(avl, box(337), box(2236), NULL); - avl = remove_int(avl, 322); - avl = gpr_avl_add(avl, box(16), box(2238), NULL); - 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), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(138), box(2249), NULL); - avl = gpr_avl_add(avl, box(437), box(2250), NULL); - avl = gpr_avl_add(avl, box(275), box(2251), NULL); - avl = remove_int(avl, 520); - avl = gpr_avl_add(avl, box(1019), box(2253), NULL); - avl = remove_int(avl, 955); - avl = gpr_avl_add(avl, box(270), box(2255), NULL); - avl = remove_int(avl, 680); - avl = remove_int(avl, 698); - avl = gpr_avl_add(avl, box(735), box(2258), NULL); - avl = gpr_avl_add(avl, box(400), box(2259), NULL); - avl = remove_int(avl, 991); - avl = gpr_avl_add(avl, box(263), box(2261), NULL); - avl = remove_int(avl, 704); - avl = gpr_avl_add(avl, box(757), box(2263), NULL); - avl = remove_int(avl, 194); - avl = remove_int(avl, 616); - avl = remove_int(avl, 784); - avl = gpr_avl_add(avl, box(382), box(2267), NULL); - avl = gpr_avl_add(avl, box(464), box(2268), NULL); - avl = gpr_avl_add(avl, box(817), box(2269), NULL); - avl = remove_int(avl, 445); - avl = gpr_avl_add(avl, box(412), box(2271), NULL); - avl = remove_int(avl, 525); - avl = gpr_avl_add(avl, box(299), box(2273), NULL); - avl = gpr_avl_add(avl, box(464), box(2274), NULL); - avl = gpr_avl_add(avl, box(715), box(2275), NULL); - avl = remove_int(avl, 58); - avl = remove_int(avl, 218); - avl = gpr_avl_add(avl, box(961), box(2278), NULL); - avl = gpr_avl_add(avl, box(491), box(2279), NULL); - avl = remove_int(avl, 846); - avl = gpr_avl_add(avl, box(762), box(2281), NULL); - avl = remove_int(avl, 974); - avl = remove_int(avl, 887); - avl = gpr_avl_add(avl, box(498), box(2284), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(1021), box(2290), NULL); - avl = remove_int(avl, 155); - avl = remove_int(avl, 128); - avl = gpr_avl_add(avl, box(819), box(2293), NULL); - avl = gpr_avl_add(avl, box(324), box(2294), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(474), box(2301), NULL); - avl = gpr_avl_add(avl, box(719), box(2302), NULL); - avl = gpr_avl_add(avl, box(236), box(2303), NULL); - avl = remove_int(avl, 818); - avl = gpr_avl_add(avl, box(727), box(2305), NULL); - avl = remove_int(avl, 892); - avl = remove_int(avl, 871); - avl = remove_int(avl, 231); - avl = gpr_avl_add(avl, box(62), box(2309), NULL); - avl = gpr_avl_add(avl, box(953), box(2310), NULL); - avl = remove_int(avl, 701); - avl = gpr_avl_add(avl, box(193), box(2312), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(751), box(2318), NULL); - avl = remove_int(avl, 525); - avl = gpr_avl_add(avl, box(217), box(2320), NULL); - avl = remove_int(avl, 336); - avl = gpr_avl_add(avl, box(86), box(2322), NULL); - avl = gpr_avl_add(avl, box(81), box(2323), NULL); - avl = gpr_avl_add(avl, box(850), box(2324), NULL); - avl = remove_int(avl, 872); - avl = gpr_avl_add(avl, box(402), box(2326), NULL); - avl = gpr_avl_add(avl, box(54), box(2327), NULL); - avl = gpr_avl_add(avl, box(980), box(2328), NULL); - avl = gpr_avl_add(avl, box(845), box(2329), NULL); - avl = remove_int(avl, 1004); - avl = remove_int(avl, 273); - avl = remove_int(avl, 879); - avl = gpr_avl_add(avl, box(354), box(2333), NULL); - avl = gpr_avl_add(avl, box(58), box(2334), NULL); - avl = gpr_avl_add(avl, box(127), box(2335), NULL); - avl = remove_int(avl, 84); - avl = gpr_avl_add(avl, box(360), box(2337), NULL); - 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), NULL); - avl = remove_int(avl, 558); - avl = remove_int(avl, 958); - avl = gpr_avl_add(avl, box(822), box(2345), NULL); - avl = remove_int(avl, 1004); - avl = remove_int(avl, 747); - avl = gpr_avl_add(avl, box(631), box(2348), NULL); - avl = gpr_avl_add(avl, box(442), box(2349), NULL); - avl = remove_int(avl, 957); - avl = remove_int(avl, 964); - avl = gpr_avl_add(avl, box(10), box(2352), NULL); - avl = remove_int(avl, 189); - avl = gpr_avl_add(avl, box(742), box(2354), NULL); - avl = remove_int(avl, 108); - avl = gpr_avl_add(avl, box(1014), box(2356), NULL); - avl = remove_int(avl, 266); - avl = remove_int(avl, 623); - avl = remove_int(avl, 697); - avl = gpr_avl_add(avl, box(180), box(2360), NULL); - avl = remove_int(avl, 472); - avl = gpr_avl_add(avl, box(567), box(2362), NULL); - avl = remove_int(avl, 1020); - avl = remove_int(avl, 273); - avl = gpr_avl_add(avl, box(864), box(2365), NULL); - avl = gpr_avl_add(avl, box(1009), box(2366), NULL); - avl = remove_int(avl, 224); - avl = remove_int(avl, 81); - avl = gpr_avl_add(avl, box(653), box(2369), NULL); - 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), NULL); - 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), NULL); - avl = gpr_avl_add(avl, box(925), box(2383), NULL); - avl = remove_int(avl, 994); - avl = remove_int(avl, 324); - avl = gpr_avl_add(avl, box(291), box(2386), NULL); - avl = remove_int(avl, 94); - avl = remove_int(avl, 795); - avl = remove_int(avl, 42); - avl = gpr_avl_add(avl, box(613), box(2390), NULL); - avl = remove_int(avl, 289); - avl = gpr_avl_add(avl, box(980), box(2392), NULL); - avl = remove_int(avl, 316); - avl = gpr_avl_add(avl, box(281), box(2394), NULL); - avl = gpr_avl_add(avl, box(1006), box(2395), NULL); - avl = remove_int(avl, 776); - avl = gpr_avl_add(avl, box(108), box(2397), NULL); - avl = gpr_avl_add(avl, box(918), box(2398), NULL); - avl = remove_int(avl, 721); - avl = remove_int(avl, 563); - avl = gpr_avl_add(avl, box(925), box(2401), NULL); - avl = remove_int(avl, 448); - avl = remove_int(avl, 198); - avl = remove_int(avl, 1); - avl = gpr_avl_add(avl, box(160), box(2405), NULL); - avl = remove_int(avl, 515); - avl = gpr_avl_add(avl, box(284), box(2407), NULL); - avl = gpr_avl_add(avl, box(225), box(2408), NULL); - avl = remove_int(avl, 304); - avl = gpr_avl_add(avl, box(714), box(2410), NULL); - avl = gpr_avl_add(avl, box(708), box(2411), NULL); - avl = gpr_avl_add(avl, box(624), box(2412), NULL); - 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), NULL); - avl = remove_int(avl, 280); - avl = remove_int(avl, 25); - avl = remove_int(avl, 633); - avl = gpr_avl_add(avl, box(897), box(2421), NULL); - 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), NULL); - avl = remove_int(avl, 948); - avl = remove_int(avl, 74); - avl = remove_int(avl, 571); - avl = gpr_avl_add(avl, box(486), box(2435), NULL); - avl = gpr_avl_add(avl, box(285), box(2436), NULL); - avl = remove_int(avl, 304); - avl = remove_int(avl, 516); - avl = gpr_avl_add(avl, box(758), box(2439), NULL); - avl = gpr_avl_add(avl, box(776), box(2440), NULL); - avl = remove_int(avl, 696); - avl = gpr_avl_add(avl, box(104), box(2442), NULL); - avl = gpr_avl_add(avl, box(700), box(2443), NULL); - avl = gpr_avl_add(avl, box(114), box(2444), NULL); - avl = gpr_avl_add(avl, box(567), box(2445), NULL); - avl = remove_int(avl, 620); - avl = gpr_avl_add(avl, box(270), box(2447), NULL); - avl = remove_int(avl, 730); - avl = gpr_avl_add(avl, box(749), box(2449), NULL); - avl = gpr_avl_add(avl, box(443), box(2450), NULL); - avl = remove_int(avl, 457); - avl = gpr_avl_add(avl, box(571), box(2452), NULL); - avl = gpr_avl_add(avl, box(626), box(2453), NULL); - avl = remove_int(avl, 638); - avl = remove_int(avl, 313); - - gpr_avl_unref(avl, NULL); -} - -static void test_stress(int amount_of_stress) { - int added[1024]; - int i, j; - int deletions = 0; - gpr_avl avl; - - unsigned seed = (unsigned)time(NULL); - - gpr_log(GPR_DEBUG, "test_stress amount=%d seed=%u", amount_of_stress, seed); - - srand((unsigned)time(NULL)); - avl = gpr_avl_create(&int_int_vtable); - - memset(added, 0, sizeof(added)); - - for (i = 1; deletions < amount_of_stress; i++) { - int idx = rand() % (int)GPR_ARRAY_SIZE(added); - GPR_ASSERT(i); - if (rand() < RAND_MAX / 2) { - added[idx] = i; - printf("avl = gpr_avl_add(avl, box(%d), box(%d), NULL); /* d=%d */\n", - idx, i, deletions); - avl = gpr_avl_add(avl, box(idx), box(i), NULL); - } else { - deletions += (added[idx] != 0); - added[idx] = 0; - printf("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, NULL); -} - -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(10); - - return 0; -} diff --git a/test/core/support/avl_test.cc b/test/core/support/avl_test.cc new file mode 100644 index 0000000000..474e773225 --- /dev/null +++ b/test/core/support/avl_test.cc @@ -0,0 +1,3659 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include +#include + +#include "test/core/util/test_config.h" + +static int *box(int x) { + int *b = static_cast(gpr_malloc(sizeof(*b))); + *b = x; + return b; +} + +static long int_compare(void *int1, void *int2, void *unused) { + return (*(int *)int1) - (*(int *)int2); +} +static void *int_copy(void *p, void *unused) { return box(*(int *)p); } + +static void destroy(void *p, void *unused) { gpr_free(p); } + +static const gpr_avl_vtable int_int_vtable = {destroy, int_copy, int_compare, + destroy, 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, NULL) == 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) == NULL); + gpr_free(k); +} + +static gpr_avl remove_int(gpr_avl avl, int key) { + int *k = box(key); + avl = gpr_avl_remove(avl, k, NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(2), box(22), NULL); + avl = gpr_avl_add(avl, box(3), box(33), NULL); + check_get(avl, 1, 11); + check_get(avl, 2, 22); + check_get(avl, 3, 33); + check_negget(avl, 4); + gpr_avl_unref(avl, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(4), box(2), NULL); + avl = gpr_avl_add(avl, box(3), box(3), NULL); + 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, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(3), box(2), NULL); + avl = gpr_avl_add(avl, box(4), box(3), NULL); + 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, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(4), box(2), NULL); + avl = gpr_avl_add(avl, box(5), box(3), NULL); + 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, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(5), box(2), NULL); + avl = gpr_avl_add(avl, box(4), box(3), NULL); + 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, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(4), box(2), NULL); + avl = gpr_avl_add(avl, box(3), box(3), NULL); + avl = gpr_avl_add(avl, box(2), box(4), NULL); + avl = gpr_avl_add(avl, box(1), box(5), NULL); + 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, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(1), box(2), NULL); + check_get(avl, 1, 2); + check_negget(avl, 2); + gpr_avl_unref(avl, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(4), box(2), NULL); + avl = gpr_avl_add(avl, box(5), box(3), NULL); + + avl3 = remove_int(gpr_avl_ref(avl, NULL), 3); + avl4 = remove_int(gpr_avl_ref(avl, NULL), 4); + avl5 = remove_int(gpr_avl_ref(avl, NULL), 5); + avln = remove_int(gpr_avl_ref(avl, NULL), 1); + + gpr_avl_unref(avl, NULL); + + check_negget(avl3, 3); + check_get(avl3, 4, 2); + check_get(avl3, 5, 3); + gpr_avl_unref(avl3, NULL); + + check_get(avl4, 3, 1); + check_negget(avl4, 4); + check_get(avl4, 5, 3); + gpr_avl_unref(avl4, NULL); + + check_get(avl5, 3, 1); + check_get(avl5, 4, 2); + check_negget(avl5, 5); + gpr_avl_unref(avl5, NULL); + + check_get(avln, 3, 1); + check_get(avln, 4, 2); + check_get(avln, 5, 3); + gpr_avl_unref(avln, NULL); +} + +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), NULL); + avl = remove_int(avl, 643); + avl = remove_int(avl, 983); + avl = gpr_avl_add(avl, box(985), box(4), NULL); + avl = gpr_avl_add(avl, box(640), box(5), NULL); + avl = gpr_avl_add(avl, box(41), box(6), NULL); + avl = gpr_avl_add(avl, box(112), box(7), NULL); + avl = gpr_avl_add(avl, box(342), box(8), NULL); + avl = remove_int(avl, 1013); + avl = gpr_avl_add(avl, box(434), box(10), NULL); + avl = gpr_avl_add(avl, box(520), box(11), NULL); + avl = gpr_avl_add(avl, box(231), box(12), NULL); + avl = gpr_avl_add(avl, box(852), box(13), NULL); + avl = remove_int(avl, 461); + avl = gpr_avl_add(avl, box(108), box(15), NULL); + avl = gpr_avl_add(avl, box(806), box(16), NULL); + avl = gpr_avl_add(avl, box(827), box(17), NULL); + avl = remove_int(avl, 796); + avl = gpr_avl_add(avl, box(340), box(19), NULL); + avl = gpr_avl_add(avl, box(498), box(20), NULL); + avl = gpr_avl_add(avl, box(203), box(21), NULL); + avl = gpr_avl_add(avl, box(751), box(22), NULL); + avl = gpr_avl_add(avl, box(150), box(23), NULL); + avl = remove_int(avl, 237); + avl = gpr_avl_add(avl, box(830), box(25), NULL); + avl = remove_int(avl, 1007); + avl = remove_int(avl, 394); + avl = gpr_avl_add(avl, box(65), box(28), NULL); + avl = remove_int(avl, 904); + avl = remove_int(avl, 123); + avl = gpr_avl_add(avl, box(238), box(31), NULL); + avl = gpr_avl_add(avl, box(184), box(32), NULL); + avl = remove_int(avl, 331); + avl = gpr_avl_add(avl, box(827), box(34), NULL); + + check_get(avl, 830, 25); + + gpr_avl_unref(avl, NULL); +} + +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), NULL); + avl = remove_int(avl, 415); + avl = gpr_avl_add(avl, box(953), box(3), NULL); + avl = gpr_avl_add(avl, box(101), box(4), NULL); + avl = gpr_avl_add(avl, box(516), box(5), NULL); + avl = gpr_avl_add(avl, box(547), box(6), NULL); + avl = gpr_avl_add(avl, box(467), box(7), NULL); + avl = gpr_avl_add(avl, box(793), box(8), NULL); + avl = remove_int(avl, 190); + avl = gpr_avl_add(avl, box(687), box(10), NULL); + avl = gpr_avl_add(avl, box(242), box(11), NULL); + avl = gpr_avl_add(avl, box(142), box(12), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(622), box(18), NULL); + avl = remove_int(avl, 513); + avl = remove_int(avl, 429); + avl = gpr_avl_add(avl, box(205), box(21), NULL); + avl = remove_int(avl, 663); + avl = remove_int(avl, 953); + avl = remove_int(avl, 892); + avl = gpr_avl_add(avl, box(236), box(25), NULL); + avl = remove_int(avl, 982); + avl = remove_int(avl, 201); + avl = remove_int(avl, 684); + avl = gpr_avl_add(avl, box(572), box(29), NULL); + avl = remove_int(avl, 817); + avl = gpr_avl_add(avl, box(970), box(31), NULL); + avl = remove_int(avl, 347); + avl = remove_int(avl, 574); + avl = gpr_avl_add(avl, box(752), box(34), NULL); + avl = gpr_avl_add(avl, box(670), box(35), NULL); + avl = gpr_avl_add(avl, box(69), box(36), NULL); + avl = remove_int(avl, 111); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(141), box(39), NULL); + avl = remove_int(avl, 159); + avl = gpr_avl_add(avl, box(947), box(41), NULL); + avl = gpr_avl_add(avl, box(855), box(42), NULL); + avl = remove_int(avl, 218); + avl = remove_int(avl, 6); + avl = gpr_avl_add(avl, box(753), box(45), NULL); + avl = remove_int(avl, 82); + avl = remove_int(avl, 799); + avl = gpr_avl_add(avl, box(572), box(48), NULL); + avl = remove_int(avl, 376); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(458), box(51), NULL); + avl = remove_int(avl, 897); + avl = gpr_avl_add(avl, box(191), box(53), NULL); + avl = gpr_avl_add(avl, box(609), box(54), NULL); + 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), NULL); + avl = remove_int(avl, 641); + avl = gpr_avl_add(avl, box(462), box(62), NULL); + avl = remove_int(avl, 359); + avl = remove_int(avl, 767); + avl = gpr_avl_add(avl, box(310), box(65), NULL); + avl = remove_int(avl, 757); + avl = remove_int(avl, 639); + avl = remove_int(avl, 314); + avl = gpr_avl_add(avl, box(2), box(69), NULL); + avl = remove_int(avl, 138); + avl = gpr_avl_add(avl, box(669), box(71), NULL); + avl = remove_int(avl, 477); + avl = gpr_avl_add(avl, box(366), box(73), NULL); + avl = gpr_avl_add(avl, box(612), box(74), NULL); + avl = gpr_avl_add(avl, box(106), box(75), NULL); + avl = remove_int(avl, 161); + avl = gpr_avl_add(avl, box(388), box(77), NULL); + avl = gpr_avl_add(avl, box(141), box(78), NULL); + avl = remove_int(avl, 633); + avl = remove_int(avl, 459); + avl = gpr_avl_add(avl, box(40), box(81), NULL); + avl = remove_int(avl, 689); + avl = gpr_avl_add(avl, box(823), box(83), NULL); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(903), box(85), NULL); + avl = gpr_avl_add(avl, box(592), box(86), NULL); + avl = remove_int(avl, 448); + avl = gpr_avl_add(avl, box(56), box(88), NULL); + avl = remove_int(avl, 333); + avl = gpr_avl_add(avl, box(189), box(90), NULL); + avl = gpr_avl_add(avl, box(103), box(91), NULL); + avl = remove_int(avl, 164); + avl = remove_int(avl, 974); + avl = gpr_avl_add(avl, box(215), box(94), NULL); + avl = remove_int(avl, 189); + avl = remove_int(avl, 504); + avl = gpr_avl_add(avl, box(868), box(97), NULL); + avl = remove_int(avl, 909); + avl = remove_int(avl, 148); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(994), box(101), NULL); + avl = gpr_avl_add(avl, box(576), box(102), NULL); + avl = remove_int(avl, 82); + avl = remove_int(avl, 209); + avl = gpr_avl_add(avl, box(276), box(105), NULL); + avl = remove_int(avl, 856); + avl = gpr_avl_add(avl, box(750), box(107), NULL); + avl = remove_int(avl, 871); + avl = gpr_avl_add(avl, box(301), box(109), NULL); + avl = remove_int(avl, 260); + avl = remove_int(avl, 737); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(933), box(113), NULL); + avl = gpr_avl_add(avl, box(225), box(114), NULL); + avl = gpr_avl_add(avl, box(975), box(115), NULL); + avl = gpr_avl_add(avl, box(86), box(116), NULL); + avl = remove_int(avl, 732); + avl = gpr_avl_add(avl, box(340), box(118), NULL); + avl = gpr_avl_add(avl, box(271), box(119), NULL); + avl = remove_int(avl, 206); + avl = gpr_avl_add(avl, box(949), box(121), NULL); + avl = gpr_avl_add(avl, box(927), box(122), NULL); + avl = gpr_avl_add(avl, box(34), box(123), NULL); + avl = gpr_avl_add(avl, box(351), box(124), NULL); + avl = remove_int(avl, 836); + avl = gpr_avl_add(avl, box(825), box(126), NULL); + avl = gpr_avl_add(avl, box(352), box(127), NULL); + avl = remove_int(avl, 107); + avl = remove_int(avl, 101); + avl = gpr_avl_add(avl, box(320), box(130), NULL); + avl = gpr_avl_add(avl, box(3), box(131), NULL); + avl = remove_int(avl, 998); + avl = remove_int(avl, 44); + avl = gpr_avl_add(avl, box(525), box(134), NULL); + avl = gpr_avl_add(avl, box(864), box(135), NULL); + avl = gpr_avl_add(avl, box(863), box(136), NULL); + avl = remove_int(avl, 770); + avl = gpr_avl_add(avl, box(440), box(138), NULL); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(116), box(140), NULL); + avl = remove_int(avl, 380); + avl = gpr_avl_add(avl, box(878), box(142), NULL); + avl = remove_int(avl, 439); + avl = gpr_avl_add(avl, box(994), box(144), NULL); + avl = remove_int(avl, 294); + avl = remove_int(avl, 593); + avl = gpr_avl_add(avl, box(696), box(147), NULL); + avl = remove_int(avl, 8); + avl = gpr_avl_add(avl, box(881), box(149), NULL); + avl = remove_int(avl, 32); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(487), box(152), NULL); + avl = gpr_avl_add(avl, box(637), box(153), NULL); + avl = gpr_avl_add(avl, box(793), box(154), NULL); + avl = gpr_avl_add(avl, box(696), box(155), NULL); + avl = remove_int(avl, 458); + avl = gpr_avl_add(avl, box(828), box(157), NULL); + avl = remove_int(avl, 784); + avl = remove_int(avl, 274); + avl = gpr_avl_add(avl, box(783), box(160), NULL); + avl = remove_int(avl, 21); + avl = gpr_avl_add(avl, box(866), box(162), NULL); + avl = remove_int(avl, 919); + avl = gpr_avl_add(avl, box(435), box(164), NULL); + avl = remove_int(avl, 385); + avl = gpr_avl_add(avl, box(475), box(166), NULL); + avl = remove_int(avl, 339); + avl = gpr_avl_add(avl, box(615), box(168), NULL); + avl = remove_int(avl, 866); + avl = remove_int(avl, 82); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(590), box(172), NULL); + avl = gpr_avl_add(avl, box(852), box(173), NULL); + avl = remove_int(avl, 318); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(672), box(176), NULL); + avl = remove_int(avl, 430); + avl = gpr_avl_add(avl, box(821), box(178), NULL); + avl = gpr_avl_add(avl, box(365), box(179), NULL); + avl = remove_int(avl, 78); + avl = gpr_avl_add(avl, box(700), box(181), NULL); + avl = gpr_avl_add(avl, box(353), box(182), NULL); + avl = remove_int(avl, 492); + avl = gpr_avl_add(avl, box(991), box(184), NULL); + avl = remove_int(avl, 330); + avl = gpr_avl_add(avl, box(873), box(186), NULL); + avl = remove_int(avl, 589); + avl = gpr_avl_add(avl, box(676), box(188), NULL); + avl = gpr_avl_add(avl, box(790), box(189), NULL); + avl = remove_int(avl, 521); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(976), box(192), NULL); + avl = gpr_avl_add(avl, box(683), box(193), NULL); + avl = remove_int(avl, 803); + avl = remove_int(avl, 1006); + avl = gpr_avl_add(avl, box(775), box(196), NULL); + avl = gpr_avl_add(avl, box(411), box(197), NULL); + avl = gpr_avl_add(avl, box(697), box(198), NULL); + avl = remove_int(avl, 50); + avl = gpr_avl_add(avl, box(213), box(200), NULL); + avl = remove_int(avl, 714); + avl = gpr_avl_add(avl, box(981), box(202), NULL); + avl = gpr_avl_add(avl, box(502), box(203), NULL); + avl = gpr_avl_add(avl, box(697), box(204), NULL); + avl = gpr_avl_add(avl, box(603), box(205), NULL); + avl = gpr_avl_add(avl, box(117), box(206), NULL); + avl = remove_int(avl, 363); + avl = gpr_avl_add(avl, box(104), box(208), NULL); + avl = remove_int(avl, 842); + avl = gpr_avl_add(avl, box(48), box(210), NULL); + avl = remove_int(avl, 764); + avl = gpr_avl_add(avl, box(482), box(212), NULL); + avl = gpr_avl_add(avl, box(928), box(213), NULL); + avl = gpr_avl_add(avl, box(30), box(214), NULL); + avl = gpr_avl_add(avl, box(820), box(215), NULL); + avl = gpr_avl_add(avl, box(334), box(216), NULL); + avl = remove_int(avl, 306); + avl = gpr_avl_add(avl, box(789), box(218), NULL); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(53), box(220), NULL); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(130), box(222), NULL); + avl = gpr_avl_add(avl, box(239), box(223), NULL); + avl = remove_int(avl, 20); + avl = gpr_avl_add(avl, box(117), box(225), NULL); + avl = remove_int(avl, 882); + avl = remove_int(avl, 891); + avl = gpr_avl_add(avl, box(9), box(228), NULL); + avl = gpr_avl_add(avl, box(496), box(229), NULL); + avl = gpr_avl_add(avl, box(750), box(230), NULL); + avl = gpr_avl_add(avl, box(283), box(231), NULL); + avl = gpr_avl_add(avl, box(802), box(232), NULL); + avl = remove_int(avl, 352); + avl = gpr_avl_add(avl, box(374), box(234), NULL); + avl = gpr_avl_add(avl, box(6), box(235), NULL); + avl = gpr_avl_add(avl, box(756), box(236), NULL); + avl = gpr_avl_add(avl, box(597), box(237), NULL); + avl = gpr_avl_add(avl, box(661), box(238), NULL); + avl = remove_int(avl, 96); + avl = gpr_avl_add(avl, box(894), box(240), NULL); + avl = remove_int(avl, 749); + avl = gpr_avl_add(avl, box(71), box(242), NULL); + avl = remove_int(avl, 68); + avl = gpr_avl_add(avl, box(388), box(244), NULL); + avl = remove_int(avl, 119); + avl = remove_int(avl, 856); + avl = gpr_avl_add(avl, box(176), box(247), NULL); + avl = gpr_avl_add(avl, box(993), box(248), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(484), box(258), NULL); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(388), box(260), NULL); + avl = remove_int(avl, 987); + avl = gpr_avl_add(avl, box(336), box(262), NULL); + avl = remove_int(avl, 855); + avl = gpr_avl_add(avl, box(668), box(264), NULL); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(193), box(266), NULL); + avl = remove_int(avl, 939); + avl = gpr_avl_add(avl, box(740), box(268), NULL); + avl = gpr_avl_add(avl, box(503), box(269), NULL); + avl = gpr_avl_add(avl, box(765), box(270), NULL); + avl = remove_int(avl, 924); + avl = remove_int(avl, 513); + avl = gpr_avl_add(avl, box(161), box(273), NULL); + avl = gpr_avl_add(avl, box(502), box(274), NULL); + avl = gpr_avl_add(avl, box(846), box(275), NULL); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(87), box(277), NULL); + avl = gpr_avl_add(avl, box(949), box(278), NULL); + avl = gpr_avl_add(avl, box(548), box(279), NULL); + avl = gpr_avl_add(avl, box(951), box(280), NULL); + avl = remove_int(avl, 1018); + avl = remove_int(avl, 568); + avl = gpr_avl_add(avl, box(138), box(283), NULL); + avl = gpr_avl_add(avl, box(202), box(284), NULL); + avl = gpr_avl_add(avl, box(157), box(285), NULL); + avl = gpr_avl_add(avl, box(264), box(286), NULL); + avl = gpr_avl_add(avl, box(370), box(287), NULL); + 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), NULL); + avl = remove_int(avl, 354); + avl = gpr_avl_add(avl, box(134), box(297), NULL); + avl = remove_int(avl, 781); + avl = remove_int(avl, 183); + avl = gpr_avl_add(avl, box(914), box(300), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(699), box(307), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(265), box(315), NULL); + avl = gpr_avl_add(avl, box(268), box(316), NULL); + avl = gpr_avl_add(avl, box(103), box(317), NULL); + avl = gpr_avl_add(avl, box(440), box(318), NULL); + avl = remove_int(avl, 777); + avl = gpr_avl_add(avl, box(670), box(320), NULL); + avl = remove_int(avl, 506); + avl = remove_int(avl, 487); + avl = gpr_avl_add(avl, box(421), box(323), NULL); + avl = remove_int(avl, 514); + avl = gpr_avl_add(avl, box(701), box(325), NULL); + avl = remove_int(avl, 949); + avl = remove_int(avl, 872); + avl = remove_int(avl, 139); + avl = gpr_avl_add(avl, box(781), box(329), NULL); + avl = gpr_avl_add(avl, box(543), box(330), NULL); + avl = gpr_avl_add(avl, box(147), box(331), NULL); + avl = remove_int(avl, 190); + avl = gpr_avl_add(avl, box(453), box(333), NULL); + 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), NULL); + avl = remove_int(avl, 812); + avl = gpr_avl_add(avl, box(431), box(340), NULL); + avl = gpr_avl_add(avl, box(8), box(341), NULL); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(831), box(343), NULL); + avl = remove_int(avl, 472); + avl = remove_int(avl, 157); + avl = gpr_avl_add(avl, box(612), box(346), NULL); + avl = gpr_avl_add(avl, box(802), box(347), NULL); + avl = remove_int(avl, 554); + avl = gpr_avl_add(avl, box(409), box(349), NULL); + avl = gpr_avl_add(avl, box(439), box(350), NULL); + avl = gpr_avl_add(avl, box(725), box(351), NULL); + avl = gpr_avl_add(avl, box(568), box(352), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(950), box(358), NULL); + avl = gpr_avl_add(avl, box(532), box(359), NULL); + avl = gpr_avl_add(avl, box(832), box(360), NULL); + avl = remove_int(avl, 390); + avl = gpr_avl_add(avl, box(993), box(362), NULL); + avl = remove_int(avl, 198); + avl = remove_int(avl, 401); + avl = gpr_avl_add(avl, box(316), box(365), NULL); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(541), box(367), NULL); + avl = gpr_avl_add(avl, box(505), box(368), NULL); + avl = remove_int(avl, 445); + avl = remove_int(avl, 256); + avl = gpr_avl_add(avl, box(232), box(371), NULL); + avl = remove_int(avl, 577); + avl = remove_int(avl, 558); + avl = gpr_avl_add(avl, box(910), box(374), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(655), box(381), NULL); + avl = remove_int(avl, 557); + avl = remove_int(avl, 102); + avl = remove_int(avl, 165); + avl = gpr_avl_add(avl, box(191), box(385), NULL); + avl = remove_int(avl, 30); + avl = gpr_avl_add(avl, box(406), box(387), NULL); + avl = gpr_avl_add(avl, box(66), box(388), NULL); + avl = gpr_avl_add(avl, box(87), box(389), NULL); + avl = remove_int(avl, 7); + avl = remove_int(avl, 671); + avl = gpr_avl_add(avl, box(234), box(392), NULL); + avl = remove_int(avl, 463); + avl = gpr_avl_add(avl, box(75), box(394), NULL); + avl = gpr_avl_add(avl, box(487), box(395), NULL); + avl = remove_int(avl, 203); + avl = gpr_avl_add(avl, box(711), box(397), NULL); + avl = remove_int(avl, 291); + avl = remove_int(avl, 798); + avl = remove_int(avl, 337); + avl = gpr_avl_add(avl, box(877), box(401), NULL); + avl = gpr_avl_add(avl, box(388), box(402), NULL); + avl = remove_int(avl, 975); + avl = gpr_avl_add(avl, box(200), box(404), NULL); + avl = gpr_avl_add(avl, box(408), box(405), NULL); + avl = gpr_avl_add(avl, box(3), box(406), NULL); + avl = gpr_avl_add(avl, box(971), box(407), NULL); + 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), NULL); + avl = remove_int(avl, 14); + avl = remove_int(avl, 364); + avl = gpr_avl_add(avl, box(215), box(415), NULL); + avl = remove_int(avl, 778); + avl = remove_int(avl, 45); + avl = gpr_avl_add(avl, box(328), box(418), NULL); + avl = gpr_avl_add(avl, box(597), box(419), NULL); + avl = remove_int(avl, 34); + avl = gpr_avl_add(avl, box(736), box(421), NULL); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(275), box(423), NULL); + avl = gpr_avl_add(avl, box(70), box(424), NULL); + avl = gpr_avl_add(avl, box(771), box(425), NULL); + avl = remove_int(avl, 536); + avl = remove_int(avl, 421); + avl = gpr_avl_add(avl, box(186), box(428), NULL); + avl = gpr_avl_add(avl, box(788), box(429), NULL); + avl = gpr_avl_add(avl, box(224), box(430), NULL); + avl = remove_int(avl, 228); + avl = gpr_avl_add(avl, box(48), box(432), NULL); + avl = gpr_avl_add(avl, box(120), box(433), NULL); + avl = gpr_avl_add(avl, box(269), box(434), NULL); + avl = gpr_avl_add(avl, box(904), box(435), NULL); + avl = remove_int(avl, 699); + avl = gpr_avl_add(avl, box(340), box(437), NULL); + avl = remove_int(avl, 276); + avl = gpr_avl_add(avl, box(591), box(439), NULL); + avl = gpr_avl_add(avl, box(778), box(440), NULL); + avl = remove_int(avl, 490); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(294), box(443), NULL); + avl = gpr_avl_add(avl, box(323), box(444), NULL); + avl = remove_int(avl, 685); + avl = gpr_avl_add(avl, box(38), box(446), NULL); + avl = gpr_avl_add(avl, box(525), box(447), NULL); + avl = remove_int(avl, 162); + avl = gpr_avl_add(avl, box(462), box(449), NULL); + avl = gpr_avl_add(avl, box(340), box(450), NULL); + avl = remove_int(avl, 734); + avl = remove_int(avl, 959); + avl = gpr_avl_add(avl, box(752), box(453), NULL); + avl = gpr_avl_add(avl, box(667), box(454), NULL); + avl = remove_int(avl, 558); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(711), box(457), NULL); + avl = remove_int(avl, 937); + avl = gpr_avl_add(avl, box(741), box(459), NULL); + avl = gpr_avl_add(avl, box(40), box(460), NULL); + avl = remove_int(avl, 784); + avl = gpr_avl_add(avl, box(292), box(462), NULL); + avl = remove_int(avl, 164); + avl = remove_int(avl, 931); + avl = remove_int(avl, 886); + avl = gpr_avl_add(avl, box(968), box(466), NULL); + avl = remove_int(avl, 263); + avl = gpr_avl_add(avl, box(647), box(468), NULL); + avl = gpr_avl_add(avl, box(92), box(469), NULL); + avl = remove_int(avl, 310); + avl = gpr_avl_add(avl, box(711), box(471), NULL); + avl = gpr_avl_add(avl, box(675), box(472), NULL); + avl = remove_int(avl, 549); + avl = gpr_avl_add(avl, box(380), box(474), NULL); + avl = remove_int(avl, 825); + avl = gpr_avl_add(avl, box(668), box(476), NULL); + avl = remove_int(avl, 498); + avl = gpr_avl_add(avl, box(870), box(478), NULL); + avl = gpr_avl_add(avl, box(391), box(479), NULL); + avl = gpr_avl_add(avl, box(264), box(480), NULL); + 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), NULL); + avl = remove_int(avl, 849); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(299), box(490), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(524), box(496), NULL); + avl = remove_int(avl, 210); + avl = remove_int(avl, 299); + avl = gpr_avl_add(avl, box(823), box(499), NULL); + avl = remove_int(avl, 479); + avl = remove_int(avl, 96); + avl = remove_int(avl, 1013); + avl = gpr_avl_add(avl, box(768), box(503), NULL); + avl = remove_int(avl, 638); + avl = remove_int(avl, 20); + avl = gpr_avl_add(avl, box(663), box(506), NULL); + avl = remove_int(avl, 882); + avl = gpr_avl_add(avl, box(745), box(508), NULL); + avl = remove_int(avl, 352); + avl = gpr_avl_add(avl, box(10), box(510), NULL); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(420), box(512), NULL); + avl = gpr_avl_add(avl, box(884), box(513), NULL); + avl = gpr_avl_add(avl, box(993), box(514), NULL); + avl = gpr_avl_add(avl, box(251), box(515), NULL); + avl = remove_int(avl, 222); + avl = gpr_avl_add(avl, box(734), box(517), NULL); + avl = gpr_avl_add(avl, box(952), box(518), NULL); + 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), NULL); + avl = remove_int(avl, 897); + avl = gpr_avl_add(avl, box(719), box(526), NULL); + avl = gpr_avl_add(avl, box(622), box(527), NULL); + avl = remove_int(avl, 28); + avl = remove_int(avl, 836); + avl = remove_int(avl, 142); + avl = gpr_avl_add(avl, box(445), box(531), NULL); + avl = gpr_avl_add(avl, box(410), box(532), NULL); + avl = remove_int(avl, 575); + avl = gpr_avl_add(avl, box(634), box(534), NULL); + avl = gpr_avl_add(avl, box(906), box(535), NULL); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(813), box(537), NULL); + avl = remove_int(avl, 702); + avl = remove_int(avl, 732); + avl = gpr_avl_add(avl, box(105), box(540), NULL); + avl = gpr_avl_add(avl, box(867), box(541), NULL); + avl = remove_int(avl, 964); + avl = remove_int(avl, 941); + avl = gpr_avl_add(avl, box(947), box(544), NULL); + avl = remove_int(avl, 990); + avl = gpr_avl_add(avl, box(816), box(546), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(786), box(552), NULL); + avl = gpr_avl_add(avl, box(526), box(553), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(749), box(559), NULL); + avl = gpr_avl_add(avl, box(194), box(560), NULL); + avl = remove_int(avl, 517); + avl = gpr_avl_add(avl, box(102), box(562), NULL); + avl = remove_int(avl, 189); + avl = gpr_avl_add(avl, box(927), box(564), NULL); + avl = remove_int(avl, 846); + avl = remove_int(avl, 130); + avl = gpr_avl_add(avl, box(694), box(567), NULL); + avl = remove_int(avl, 750); + avl = gpr_avl_add(avl, box(357), box(569), NULL); + avl = remove_int(avl, 431); + avl = remove_int(avl, 91); + avl = gpr_avl_add(avl, box(640), box(572), NULL); + avl = remove_int(avl, 4); + avl = gpr_avl_add(avl, box(81), box(574), NULL); + avl = gpr_avl_add(avl, box(595), box(575), NULL); + avl = remove_int(avl, 444); + avl = remove_int(avl, 262); + avl = remove_int(avl, 11); + avl = gpr_avl_add(avl, box(192), box(579), NULL); + avl = gpr_avl_add(avl, box(158), box(580), NULL); + avl = remove_int(avl, 401); + avl = remove_int(avl, 918); + avl = gpr_avl_add(avl, box(180), box(583), NULL); + avl = remove_int(avl, 268); + avl = gpr_avl_add(avl, box(1012), box(585), NULL); + avl = gpr_avl_add(avl, box(90), box(586), NULL); + avl = gpr_avl_add(avl, box(946), box(587), NULL); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(874), box(589), NULL); + avl = gpr_avl_add(avl, box(679), box(590), NULL); + avl = remove_int(avl, 53); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(646), box(593), NULL); + avl = gpr_avl_add(avl, box(767), box(594), NULL); + avl = gpr_avl_add(avl, box(460), box(595), NULL); + avl = gpr_avl_add(avl, box(852), box(596), NULL); + avl = gpr_avl_add(avl, box(189), box(597), NULL); + avl = remove_int(avl, 932); + avl = remove_int(avl, 366); + avl = remove_int(avl, 907); + avl = gpr_avl_add(avl, box(875), box(601), NULL); + avl = gpr_avl_add(avl, box(434), box(602), NULL); + avl = gpr_avl_add(avl, box(704), box(603), NULL); + avl = gpr_avl_add(avl, box(724), box(604), NULL); + avl = gpr_avl_add(avl, box(930), box(605), NULL); + avl = gpr_avl_add(avl, box(1000), box(606), NULL); + avl = remove_int(avl, 479); + avl = gpr_avl_add(avl, box(275), box(608), NULL); + avl = remove_int(avl, 32); + avl = gpr_avl_add(avl, box(939), box(610), NULL); + avl = remove_int(avl, 943); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(490), box(613), NULL); + 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), NULL); + avl = remove_int(avl, 751); + avl = gpr_avl_add(avl, box(568), box(620), NULL); + avl = gpr_avl_add(avl, box(120), box(621), NULL); + avl = gpr_avl_add(avl, box(617), box(622), NULL); + avl = gpr_avl_add(avl, box(32), box(623), NULL); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(910), box(625), NULL); + 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), NULL); + 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), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(6), box(642), NULL); + avl = gpr_avl_add(avl, box(680), box(643), NULL); + avl = remove_int(avl, 741); + avl = remove_int(avl, 309); + avl = remove_int(avl, 272); + avl = gpr_avl_add(avl, box(249), box(647), NULL); + avl = remove_int(avl, 97); + avl = remove_int(avl, 850); + avl = gpr_avl_add(avl, box(915), box(650), NULL); + avl = gpr_avl_add(avl, box(816), box(651), NULL); + avl = gpr_avl_add(avl, box(45), box(652), NULL); + avl = gpr_avl_add(avl, box(168), box(653), NULL); + avl = remove_int(avl, 153); + avl = remove_int(avl, 239); + avl = gpr_avl_add(avl, box(684), box(656), NULL); + avl = gpr_avl_add(avl, box(208), box(657), NULL); + avl = gpr_avl_add(avl, box(681), box(658), NULL); + avl = gpr_avl_add(avl, box(609), box(659), NULL); + avl = gpr_avl_add(avl, box(645), box(660), NULL); + avl = remove_int(avl, 799); + avl = gpr_avl_add(avl, box(955), box(662), NULL); + avl = gpr_avl_add(avl, box(946), box(663), NULL); + avl = gpr_avl_add(avl, box(744), box(664), NULL); + avl = gpr_avl_add(avl, box(201), box(665), NULL); + avl = gpr_avl_add(avl, box(136), box(666), NULL); + avl = remove_int(avl, 357); + avl = gpr_avl_add(avl, box(974), box(668), NULL); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(1009), box(670), NULL); + avl = gpr_avl_add(avl, box(517), box(671), NULL); + avl = remove_int(avl, 491); + avl = gpr_avl_add(avl, box(336), box(673), NULL); + avl = gpr_avl_add(avl, box(589), box(674), NULL); + 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), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(25), box(685), NULL); + avl = remove_int(avl, 278); + avl = gpr_avl_add(avl, box(191), box(687), NULL); + avl = remove_int(avl, 243); + avl = remove_int(avl, 918); + avl = remove_int(avl, 449); + avl = gpr_avl_add(avl, box(19), box(691), NULL); + avl = gpr_avl_add(avl, box(762), box(692), NULL); + avl = gpr_avl_add(avl, box(13), box(693), NULL); + avl = gpr_avl_add(avl, box(151), box(694), NULL); + avl = gpr_avl_add(avl, box(152), box(695), NULL); + avl = gpr_avl_add(avl, box(793), box(696), NULL); + avl = remove_int(avl, 862); + avl = remove_int(avl, 890); + avl = gpr_avl_add(avl, box(687), box(699), NULL); + avl = gpr_avl_add(avl, box(509), box(700), NULL); + avl = gpr_avl_add(avl, box(973), box(701), NULL); + avl = remove_int(avl, 230); + avl = gpr_avl_add(avl, box(532), box(703), NULL); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(281), box(705), NULL); + avl = gpr_avl_add(avl, box(867), box(706), NULL); + avl = gpr_avl_add(avl, box(359), box(707), NULL); + avl = remove_int(avl, 425); + avl = gpr_avl_add(avl, box(691), box(709), NULL); + avl = gpr_avl_add(avl, box(163), box(710), NULL); + avl = gpr_avl_add(avl, box(502), box(711), NULL); + avl = remove_int(avl, 674); + avl = gpr_avl_add(avl, box(697), box(713), NULL); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(968), box(715), NULL); + avl = gpr_avl_add(avl, box(48), box(716), NULL); + avl = remove_int(avl, 543); + avl = gpr_avl_add(avl, box(35), box(718), NULL); + avl = gpr_avl_add(avl, box(751), box(719), NULL); + avl = gpr_avl_add(avl, box(478), box(720), NULL); + avl = remove_int(avl, 797); + avl = remove_int(avl, 309); + avl = gpr_avl_add(avl, box(927), box(723), NULL); + avl = remove_int(avl, 504); + avl = gpr_avl_add(avl, box(286), box(725), NULL); + avl = gpr_avl_add(avl, box(413), box(726), NULL); + avl = gpr_avl_add(avl, box(599), box(727), NULL); + avl = remove_int(avl, 105); + avl = remove_int(avl, 605); + avl = gpr_avl_add(avl, box(632), box(730), NULL); + avl = gpr_avl_add(avl, box(133), box(731), NULL); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(958), box(733), NULL); + avl = gpr_avl_add(avl, box(729), box(734), NULL); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(694), box(736), NULL); + avl = gpr_avl_add(avl, box(505), box(737), NULL); + avl = remove_int(avl, 63); + avl = remove_int(avl, 714); + avl = gpr_avl_add(avl, box(1002), box(740), NULL); + avl = remove_int(avl, 211); + avl = gpr_avl_add(avl, box(765), box(742), NULL); + avl = gpr_avl_add(avl, box(455), box(743), NULL); + avl = remove_int(avl, 59); + avl = remove_int(avl, 224); + avl = gpr_avl_add(avl, box(586), box(746), NULL); + avl = gpr_avl_add(avl, box(348), box(747), NULL); + avl = remove_int(avl, 10); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(968), box(750), NULL); + avl = gpr_avl_add(avl, box(923), box(751), NULL); + avl = remove_int(avl, 573); + avl = remove_int(avl, 617); + avl = gpr_avl_add(avl, box(812), box(754), NULL); + avl = gpr_avl_add(avl, box(179), box(755), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(927), box(761), NULL); + avl = gpr_avl_add(avl, box(454), box(762), NULL); + avl = gpr_avl_add(avl, box(217), box(763), NULL); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(180), box(765), NULL); + avl = gpr_avl_add(avl, box(319), box(766), NULL); + avl = remove_int(avl, 92); + avl = gpr_avl_add(avl, box(483), box(768), NULL); + 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), NULL); + avl = remove_int(avl, 807); + avl = gpr_avl_add(avl, box(463), box(775), NULL); + avl = gpr_avl_add(avl, box(271), box(776), NULL); + avl = gpr_avl_add(avl, box(644), box(777), NULL); + avl = remove_int(avl, 618); + avl = gpr_avl_add(avl, box(166), box(779), NULL); + avl = gpr_avl_add(avl, box(538), box(780), NULL); + avl = remove_int(avl, 606); + avl = gpr_avl_add(avl, box(425), box(782), NULL); + avl = remove_int(avl, 725); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(155), box(785), NULL); + avl = remove_int(avl, 889); + avl = gpr_avl_add(avl, box(653), box(787), NULL); + avl = remove_int(avl, 386); + avl = gpr_avl_add(avl, box(142), box(789), NULL); + avl = remove_int(avl, 107); + avl = remove_int(avl, 603); + avl = remove_int(avl, 971); + avl = gpr_avl_add(avl, box(80), box(793), NULL); + avl = gpr_avl_add(avl, box(61), box(794), NULL); + avl = gpr_avl_add(avl, box(693), box(795), NULL); + avl = gpr_avl_add(avl, box(592), box(796), NULL); + avl = gpr_avl_add(avl, box(433), box(797), NULL); + avl = gpr_avl_add(avl, box(973), box(798), NULL); + avl = remove_int(avl, 901); + avl = remove_int(avl, 340); + avl = remove_int(avl, 709); + avl = gpr_avl_add(avl, box(224), box(802), NULL); + avl = remove_int(avl, 120); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(780), box(805), NULL); + avl = gpr_avl_add(avl, box(867), box(806), NULL); + avl = gpr_avl_add(avl, box(756), box(807), NULL); + avl = gpr_avl_add(avl, box(583), box(808), NULL); + avl = gpr_avl_add(avl, box(356), box(809), NULL); + avl = gpr_avl_add(avl, box(58), box(810), NULL); + avl = remove_int(avl, 219); + avl = gpr_avl_add(avl, box(301), box(812), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(479), box(822), NULL); + avl = gpr_avl_add(avl, box(323), box(823), NULL); + avl = gpr_avl_add(avl, box(802), box(824), NULL); + avl = remove_int(avl, 682); + avl = remove_int(avl, 705); + avl = remove_int(avl, 487); + avl = gpr_avl_add(avl, box(530), box(828), NULL); + avl = gpr_avl_add(avl, box(232), box(829), NULL); + avl = remove_int(avl, 627); + avl = gpr_avl_add(avl, box(396), box(831), NULL); + avl = gpr_avl_add(avl, box(61), box(832), NULL); + avl = gpr_avl_add(avl, box(932), box(833), NULL); + avl = gpr_avl_add(avl, box(108), box(834), NULL); + avl = gpr_avl_add(avl, box(524), box(835), NULL); + avl = remove_int(avl, 390); + avl = remove_int(avl, 307); + avl = gpr_avl_add(avl, box(722), box(838), NULL); + avl = gpr_avl_add(avl, box(907), box(839), NULL); + avl = remove_int(avl, 286); + avl = remove_int(avl, 337); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(973), box(843), NULL); + avl = remove_int(avl, 930); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(997), box(846), NULL); + avl = gpr_avl_add(avl, box(689), box(847), NULL); + avl = remove_int(avl, 318); + avl = gpr_avl_add(avl, box(703), box(849), NULL); + avl = gpr_avl_add(avl, box(868), box(850), NULL); + avl = gpr_avl_add(avl, box(200), box(851), NULL); + avl = gpr_avl_add(avl, box(960), box(852), NULL); + avl = gpr_avl_add(avl, box(80), box(853), NULL); + avl = remove_int(avl, 113); + avl = gpr_avl_add(avl, box(135), box(855), NULL); + avl = remove_int(avl, 529); + avl = gpr_avl_add(avl, box(366), box(857), NULL); + avl = remove_int(avl, 272); + avl = gpr_avl_add(avl, box(921), box(859), NULL); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(712), box(861), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(29), box(867), NULL); + avl = gpr_avl_add(avl, box(180), box(868), NULL); + avl = gpr_avl_add(avl, box(983), box(869), NULL); + avl = gpr_avl_add(avl, box(72), box(870), NULL); + avl = gpr_avl_add(avl, box(693), box(871), NULL); + avl = gpr_avl_add(avl, box(567), box(872), NULL); + avl = remove_int(avl, 549); + avl = remove_int(avl, 351); + avl = gpr_avl_add(avl, box(1019), box(875), NULL); + avl = remove_int(avl, 585); + avl = remove_int(avl, 294); + avl = remove_int(avl, 61); + avl = gpr_avl_add(avl, box(409), box(879), NULL); + avl = gpr_avl_add(avl, box(984), box(880), NULL); + avl = gpr_avl_add(avl, box(830), box(881), NULL); + avl = remove_int(avl, 579); + avl = gpr_avl_add(avl, box(672), box(883), NULL); + avl = remove_int(avl, 968); + + gpr_avl_unref(avl, NULL); +} + +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), NULL); + avl = gpr_avl_add(avl, box(494), box(3), NULL); + avl = gpr_avl_add(avl, box(226), box(4), NULL); + avl = remove_int(avl, 524); + avl = gpr_avl_add(avl, box(540), box(6), NULL); + avl = remove_int(avl, 1008); + avl = gpr_avl_add(avl, box(502), box(8), NULL); + avl = remove_int(avl, 267); + avl = remove_int(avl, 764); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(8), box(12), NULL); + avl = remove_int(avl, 291); + avl = remove_int(avl, 796); + avl = remove_int(avl, 1002); + avl = gpr_avl_add(avl, box(778), box(16), NULL); + avl = remove_int(avl, 621); + avl = remove_int(avl, 891); + avl = remove_int(avl, 880); + avl = gpr_avl_add(avl, box(197), box(20), NULL); + avl = gpr_avl_add(avl, box(441), box(21), NULL); + avl = gpr_avl_add(avl, box(719), box(22), NULL); + avl = remove_int(avl, 109); + avl = gpr_avl_add(avl, box(458), box(24), NULL); + avl = remove_int(avl, 86); + avl = gpr_avl_add(avl, box(897), box(26), NULL); + avl = gpr_avl_add(avl, box(997), box(27), NULL); + avl = remove_int(avl, 235); + avl = remove_int(avl, 425); + avl = remove_int(avl, 186); + avl = gpr_avl_add(avl, box(887), box(31), NULL); + avl = gpr_avl_add(avl, box(1005), box(32), NULL); + avl = gpr_avl_add(avl, box(778), box(33), NULL); + avl = gpr_avl_add(avl, box(575), box(34), NULL); + avl = remove_int(avl, 966); + avl = remove_int(avl, 1015); + avl = gpr_avl_add(avl, box(486), box(37), NULL); + avl = gpr_avl_add(avl, box(809), box(38), NULL); + avl = gpr_avl_add(avl, box(907), box(39), NULL); + avl = gpr_avl_add(avl, box(971), box(40), NULL); + avl = remove_int(avl, 441); + avl = remove_int(avl, 498); + avl = gpr_avl_add(avl, box(727), box(43), NULL); + avl = remove_int(avl, 679); + avl = remove_int(avl, 740); + avl = remove_int(avl, 532); + avl = gpr_avl_add(avl, box(805), box(47), NULL); + avl = remove_int(avl, 64); + avl = gpr_avl_add(avl, box(362), box(49), NULL); + avl = gpr_avl_add(avl, box(170), box(50), NULL); + avl = gpr_avl_add(avl, box(389), box(51), NULL); + avl = gpr_avl_add(avl, box(689), box(52), NULL); + avl = remove_int(avl, 871); + avl = gpr_avl_add(avl, box(447), box(54), NULL); + avl = remove_int(avl, 718); + avl = gpr_avl_add(avl, box(724), box(56), NULL); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(550), box(58), NULL); + avl = remove_int(avl, 932); + avl = gpr_avl_add(avl, box(47), box(60), NULL); + avl = remove_int(avl, 46); + avl = remove_int(avl, 229); + avl = gpr_avl_add(avl, box(68), box(63), NULL); + avl = gpr_avl_add(avl, box(387), box(64), NULL); + avl = remove_int(avl, 933); + avl = remove_int(avl, 736); + avl = remove_int(avl, 719); + avl = gpr_avl_add(avl, box(150), box(68), NULL); + avl = remove_int(avl, 875); + avl = remove_int(avl, 298); + avl = gpr_avl_add(avl, box(991), box(71), NULL); + avl = remove_int(avl, 705); + avl = gpr_avl_add(avl, box(197), box(73), NULL); + avl = gpr_avl_add(avl, box(101), box(74), NULL); + avl = remove_int(avl, 436); + avl = gpr_avl_add(avl, box(755), box(76), NULL); + avl = gpr_avl_add(avl, box(727), box(77), NULL); + avl = remove_int(avl, 309); + avl = remove_int(avl, 253); + avl = gpr_avl_add(avl, box(203), box(80), NULL); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(461), box(82), NULL); + avl = remove_int(avl, 316); + avl = remove_int(avl, 493); + avl = gpr_avl_add(avl, box(184), box(85), NULL); + avl = remove_int(avl, 737); + avl = gpr_avl_add(avl, box(790), box(87), NULL); + avl = gpr_avl_add(avl, box(335), box(88), NULL); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(69), box(90), NULL); + avl = remove_int(avl, 585); + avl = remove_int(avl, 543); + avl = gpr_avl_add(avl, box(784), box(93), NULL); + avl = gpr_avl_add(avl, box(60), box(94), NULL); + avl = gpr_avl_add(avl, box(525), box(95), NULL); + avl = gpr_avl_add(avl, box(177), box(96), NULL); + avl = gpr_avl_add(avl, box(178), box(97), NULL); + avl = gpr_avl_add(avl, box(683), box(98), NULL); + avl = gpr_avl_add(avl, box(226), box(99), NULL); + avl = gpr_avl_add(avl, box(662), box(100), NULL); + avl = remove_int(avl, 944); + avl = gpr_avl_add(avl, box(562), box(102), NULL); + avl = gpr_avl_add(avl, box(793), box(103), NULL); + avl = remove_int(avl, 673); + avl = gpr_avl_add(avl, box(310), box(105), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(483), box(111), NULL); + avl = gpr_avl_add(avl, box(84), box(112), NULL); + avl = remove_int(avl, 109); + avl = gpr_avl_add(avl, box(132), box(114), NULL); + avl = gpr_avl_add(avl, box(920), box(115), NULL); + avl = remove_int(avl, 746); + avl = gpr_avl_add(avl, box(145), box(117), NULL); + avl = gpr_avl_add(avl, box(526), box(118), NULL); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(332), box(120), NULL); + avl = gpr_avl_add(avl, box(918), box(121), NULL); + avl = remove_int(avl, 339); + avl = gpr_avl_add(avl, box(809), box(123), NULL); + avl = gpr_avl_add(avl, box(742), box(124), NULL); + avl = gpr_avl_add(avl, box(718), box(125), NULL); + avl = remove_int(avl, 988); + avl = remove_int(avl, 531); + avl = remove_int(avl, 840); + avl = gpr_avl_add(avl, box(816), box(129), NULL); + avl = gpr_avl_add(avl, box(976), box(130), NULL); + avl = remove_int(avl, 743); + avl = remove_int(avl, 528); + avl = remove_int(avl, 982); + avl = gpr_avl_add(avl, box(803), box(134), NULL); + avl = gpr_avl_add(avl, box(205), box(135), NULL); + avl = gpr_avl_add(avl, box(584), box(136), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(333), box(143), NULL); + avl = remove_int(avl, 439); + avl = gpr_avl_add(avl, box(35), box(145), NULL); + avl = gpr_avl_add(avl, box(837), box(146), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(116), box(154), NULL); + avl = gpr_avl_add(avl, box(446), box(155), NULL); + avl = remove_int(avl, 91); + avl = remove_int(avl, 721); + avl = remove_int(avl, 537); + avl = gpr_avl_add(avl, box(448), box(159), NULL); + avl = remove_int(avl, 155); + avl = remove_int(avl, 344); + avl = remove_int(avl, 237); + avl = gpr_avl_add(avl, box(309), box(163), NULL); + avl = gpr_avl_add(avl, box(434), box(164), NULL); + avl = gpr_avl_add(avl, box(277), box(165), NULL); + avl = remove_int(avl, 233); + avl = gpr_avl_add(avl, box(275), box(167), NULL); + avl = gpr_avl_add(avl, box(218), box(168), NULL); + avl = gpr_avl_add(avl, box(76), box(169), NULL); + avl = gpr_avl_add(avl, box(898), box(170), NULL); + avl = remove_int(avl, 771); + avl = gpr_avl_add(avl, box(237), box(172), NULL); + avl = remove_int(avl, 327); + avl = gpr_avl_add(avl, box(499), box(174), NULL); + 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), NULL); + avl = remove_int(avl, 389); + avl = gpr_avl_add(avl, box(708), box(183), NULL); + avl = gpr_avl_add(avl, box(594), box(184), NULL); + avl = gpr_avl_add(avl, box(942), box(185), NULL); + avl = gpr_avl_add(avl, box(282), box(186), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(161), box(197), NULL); + avl = remove_int(avl, 484); + avl = gpr_avl_add(avl, box(72), box(199), NULL); + avl = remove_int(avl, 629); + avl = gpr_avl_add(avl, box(522), box(201), NULL); + avl = remove_int(avl, 679); + avl = gpr_avl_add(avl, box(407), box(203), NULL); + avl = remove_int(avl, 693); + avl = gpr_avl_add(avl, box(424), box(205), NULL); + avl = gpr_avl_add(avl, box(651), box(206), NULL); + avl = gpr_avl_add(avl, box(927), box(207), NULL); + avl = remove_int(avl, 553); + avl = gpr_avl_add(avl, box(128), box(209), NULL); + avl = gpr_avl_add(avl, box(616), box(210), NULL); + avl = gpr_avl_add(avl, box(690), box(211), NULL); + avl = remove_int(avl, 241); + avl = remove_int(avl, 179); + avl = gpr_avl_add(avl, box(697), box(214), NULL); + avl = remove_int(avl, 779); + avl = gpr_avl_add(avl, box(241), box(216), NULL); + avl = remove_int(avl, 190); + avl = remove_int(avl, 210); + avl = gpr_avl_add(avl, box(711), box(219), NULL); + avl = remove_int(avl, 251); + avl = remove_int(avl, 61); + avl = gpr_avl_add(avl, box(800), box(222), NULL); + avl = remove_int(avl, 551); + avl = gpr_avl_add(avl, box(61), box(224), NULL); + avl = gpr_avl_add(avl, box(656), box(225), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(125), box(231), NULL); + avl = remove_int(avl, 107); + avl = gpr_avl_add(avl, box(938), box(233), NULL); + avl = gpr_avl_add(avl, box(914), box(234), NULL); + avl = gpr_avl_add(avl, box(197), box(235), NULL); + avl = remove_int(avl, 736); + avl = gpr_avl_add(avl, box(20), box(237), NULL); + avl = remove_int(avl, 224); + avl = remove_int(avl, 841); + avl = gpr_avl_add(avl, box(226), box(240), NULL); + avl = remove_int(avl, 963); + avl = remove_int(avl, 796); + avl = remove_int(avl, 728); + avl = gpr_avl_add(avl, box(855), box(244), NULL); + avl = gpr_avl_add(avl, box(769), box(245), NULL); + avl = gpr_avl_add(avl, box(631), box(246), NULL); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(187), box(248), NULL); + avl = gpr_avl_add(avl, box(31), box(249), NULL); + avl = remove_int(avl, 163); + avl = gpr_avl_add(avl, box(218), box(251), NULL); + avl = gpr_avl_add(avl, box(488), box(252), NULL); + avl = gpr_avl_add(avl, box(387), box(253), NULL); + avl = gpr_avl_add(avl, box(809), box(254), NULL); + avl = gpr_avl_add(avl, box(997), box(255), NULL); + avl = remove_int(avl, 678); + avl = gpr_avl_add(avl, box(368), box(257), NULL); + avl = gpr_avl_add(avl, box(220), box(258), NULL); + avl = gpr_avl_add(avl, box(373), box(259), NULL); + 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), NULL); + avl = remove_int(avl, 254); + avl = remove_int(avl, 456); + avl = gpr_avl_add(avl, box(906), box(267), NULL); + avl = remove_int(avl, 711); + avl = gpr_avl_add(avl, box(632), box(269), NULL); + avl = remove_int(avl, 474); + avl = gpr_avl_add(avl, box(508), box(271), NULL); + avl = gpr_avl_add(avl, box(518), box(272), NULL); + avl = remove_int(avl, 579); + avl = remove_int(avl, 948); + avl = gpr_avl_add(avl, box(789), box(275), NULL); + avl = gpr_avl_add(avl, box(48), box(276), NULL); + avl = gpr_avl_add(avl, box(256), box(277), NULL); + avl = gpr_avl_add(avl, box(754), box(278), NULL); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(679), box(280), NULL); + avl = gpr_avl_add(avl, box(606), box(281), NULL); + avl = remove_int(avl, 941); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(758), box(284), NULL); + avl = remove_int(avl, 101); + avl = gpr_avl_add(avl, box(244), box(286), NULL); + avl = gpr_avl_add(avl, box(337), box(287), NULL); + avl = gpr_avl_add(avl, box(461), box(288), NULL); + avl = remove_int(avl, 476); + avl = gpr_avl_add(avl, box(845), box(290), NULL); + avl = remove_int(avl, 160); + avl = gpr_avl_add(avl, box(690), box(292), NULL); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(869), box(294), NULL); + avl = gpr_avl_add(avl, box(1019), box(295), NULL); + avl = remove_int(avl, 591); + avl = remove_int(avl, 635); + avl = remove_int(avl, 67); + avl = gpr_avl_add(avl, box(113), box(299), NULL); + avl = remove_int(avl, 305); + avl = gpr_avl_add(avl, box(10), box(301), NULL); + avl = remove_int(avl, 823); + avl = remove_int(avl, 288); + avl = remove_int(avl, 239); + avl = gpr_avl_add(avl, box(646), box(305), NULL); + avl = gpr_avl_add(avl, box(1006), box(306), NULL); + avl = gpr_avl_add(avl, box(954), box(307), NULL); + avl = gpr_avl_add(avl, box(199), box(308), NULL); + avl = gpr_avl_add(avl, box(69), box(309), NULL); + avl = gpr_avl_add(avl, box(984), box(310), NULL); + avl = remove_int(avl, 568); + avl = remove_int(avl, 666); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(845), box(314), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(335), box(323), NULL); + avl = gpr_avl_add(avl, box(961), box(324), NULL); + avl = gpr_avl_add(avl, box(73), box(325), NULL); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(449), box(327), NULL); + avl = remove_int(avl, 821); + avl = gpr_avl_add(avl, box(845), box(329), NULL); + avl = remove_int(avl, 637); + avl = gpr_avl_add(avl, box(769), box(331), NULL); + avl = gpr_avl_add(avl, box(901), box(332), NULL); + avl = remove_int(avl, 142); + avl = remove_int(avl, 361); + avl = remove_int(avl, 876); + avl = gpr_avl_add(avl, box(614), box(336), NULL); + avl = gpr_avl_add(avl, box(729), box(337), NULL); + avl = remove_int(avl, 120); + avl = remove_int(avl, 473); + avl = remove_int(avl, 445); + avl = gpr_avl_add(avl, box(978), box(341), NULL); + avl = gpr_avl_add(avl, box(164), box(342), NULL); + avl = gpr_avl_add(avl, box(1), box(343), NULL); + avl = remove_int(avl, 890); + avl = gpr_avl_add(avl, box(605), box(345), NULL); + avl = gpr_avl_add(avl, box(178), box(346), NULL); + avl = gpr_avl_add(avl, box(481), box(347), NULL); + avl = gpr_avl_add(avl, box(772), box(348), NULL); + avl = remove_int(avl, 824); + avl = remove_int(avl, 167); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(698), box(352), NULL); + avl = gpr_avl_add(avl, box(202), box(353), NULL); + avl = gpr_avl_add(avl, box(921), box(354), NULL); + avl = gpr_avl_add(avl, box(875), box(355), NULL); + avl = remove_int(avl, 197); + avl = remove_int(avl, 232); + avl = gpr_avl_add(avl, box(209), box(358), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(113), box(365), NULL); + avl = remove_int(avl, 767); + avl = gpr_avl_add(avl, box(586), box(367), NULL); + avl = gpr_avl_add(avl, box(121), box(368), NULL); + avl = remove_int(avl, 235); + avl = remove_int(avl, 439); + avl = remove_int(avl, 360); + avl = gpr_avl_add(avl, box(916), box(372), NULL); + avl = remove_int(avl, 999); + avl = gpr_avl_add(avl, box(825), box(374), NULL); + avl = gpr_avl_add(avl, box(177), box(375), NULL); + avl = remove_int(avl, 204); + avl = remove_int(avl, 92); + avl = gpr_avl_add(avl, box(794), box(378), NULL); + avl = gpr_avl_add(avl, box(463), box(379), NULL); + avl = gpr_avl_add(avl, box(472), box(380), NULL); + avl = remove_int(avl, 235); + avl = gpr_avl_add(avl, box(840), box(382), NULL); + avl = remove_int(avl, 657); + avl = gpr_avl_add(avl, box(586), box(384), NULL); + avl = gpr_avl_add(avl, box(979), box(385), NULL); + avl = remove_int(avl, 979); + avl = gpr_avl_add(avl, box(639), box(387), NULL); + avl = remove_int(avl, 907); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(913), box(390), NULL); + avl = gpr_avl_add(avl, box(566), box(391), NULL); + avl = gpr_avl_add(avl, box(883), box(392), NULL); + avl = gpr_avl_add(avl, box(552), box(393), NULL); + avl = gpr_avl_add(avl, box(16), box(394), NULL); + avl = remove_int(avl, 60); + avl = gpr_avl_add(avl, box(567), box(396), NULL); + avl = gpr_avl_add(avl, box(705), box(397), NULL); + avl = gpr_avl_add(avl, box(94), box(398), NULL); + avl = remove_int(avl, 321); + avl = gpr_avl_add(avl, box(207), box(400), NULL); + avl = gpr_avl_add(avl, box(682), box(401), NULL); + avl = gpr_avl_add(avl, box(592), box(402), NULL); + avl = gpr_avl_add(avl, box(10), box(403), NULL); + avl = remove_int(avl, 911); + avl = remove_int(avl, 161); + avl = gpr_avl_add(avl, box(86), box(406), NULL); + avl = remove_int(avl, 893); + avl = remove_int(avl, 362); + avl = gpr_avl_add(avl, box(599), box(409), NULL); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(867), box(411), NULL); + avl = remove_int(avl, 955); + avl = gpr_avl_add(avl, box(341), box(413), NULL); + avl = gpr_avl_add(avl, box(887), box(414), NULL); + avl = remove_int(avl, 706); + avl = gpr_avl_add(avl, box(939), box(416), NULL); + 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), NULL); + avl = remove_int(avl, 848); + avl = gpr_avl_add(avl, box(235), box(423), NULL); + avl = remove_int(avl, 617); + avl = gpr_avl_add(avl, box(565), box(425), NULL); + avl = remove_int(avl, 469); + avl = gpr_avl_add(avl, box(988), box(427), NULL); + avl = remove_int(avl, 957); + avl = gpr_avl_add(avl, box(426), box(429), NULL); + avl = remove_int(avl, 967); + avl = gpr_avl_add(avl, box(890), box(431), NULL); + avl = gpr_avl_add(avl, box(473), box(432), NULL); + 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), NULL); + avl = remove_int(avl, 882); + avl = remove_int(avl, 782); + avl = gpr_avl_add(avl, box(408), box(442), NULL); + avl = gpr_avl_add(avl, box(728), box(443), NULL); + avl = remove_int(avl, 27); + avl = gpr_avl_add(avl, box(137), box(445), NULL); + avl = gpr_avl_add(avl, box(239), box(446), NULL); + avl = remove_int(avl, 854); + avl = gpr_avl_add(avl, box(104), box(448), NULL); + avl = gpr_avl_add(avl, box(823), box(449), NULL); + avl = gpr_avl_add(avl, box(524), box(450), NULL); + avl = gpr_avl_add(avl, box(995), box(451), NULL); + avl = remove_int(avl, 422); + avl = remove_int(avl, 220); + avl = gpr_avl_add(avl, box(856), box(454), NULL); + avl = remove_int(avl, 332); + avl = gpr_avl_add(avl, box(679), box(456), NULL); + avl = remove_int(avl, 18); + avl = gpr_avl_add(avl, box(837), box(458), NULL); + avl = remove_int(avl, 405); + avl = remove_int(avl, 877); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(547), box(462), NULL); + avl = remove_int(avl, 805); + avl = remove_int(avl, 862); + avl = gpr_avl_add(avl, box(75), box(465), NULL); + avl = remove_int(avl, 41); + avl = gpr_avl_add(avl, box(310), box(467), NULL); + avl = remove_int(avl, 855); + avl = gpr_avl_add(avl, box(20), box(469), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(96), box(475), NULL); + avl = remove_int(avl, 854); + avl = gpr_avl_add(avl, box(65), box(477), NULL); + avl = gpr_avl_add(avl, box(573), box(478), NULL); + avl = gpr_avl_add(avl, box(4), box(479), NULL); + avl = gpr_avl_add(avl, box(451), box(480), NULL); + avl = gpr_avl_add(avl, box(774), box(481), NULL); + avl = gpr_avl_add(avl, box(126), box(482), NULL); + avl = remove_int(avl, 956); + avl = remove_int(avl, 591); + avl = remove_int(avl, 644); + avl = gpr_avl_add(avl, box(304), box(486), NULL); + avl = remove_int(avl, 620); + avl = remove_int(avl, 394); + avl = gpr_avl_add(avl, box(1002), box(489), NULL); + avl = gpr_avl_add(avl, box(837), box(490), NULL); + avl = remove_int(avl, 485); + avl = gpr_avl_add(avl, box(1005), box(492), NULL); + avl = remove_int(avl, 21); + avl = gpr_avl_add(avl, box(396), box(494), NULL); + avl = remove_int(avl, 966); + avl = gpr_avl_add(avl, box(105), box(496), NULL); + avl = gpr_avl_add(avl, box(316), box(497), NULL); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(188), box(499), NULL); + avl = remove_int(avl, 200); + avl = gpr_avl_add(avl, box(98), box(501), NULL); + avl = gpr_avl_add(avl, box(831), box(502), NULL); + avl = gpr_avl_add(avl, box(227), box(503), NULL); + avl = gpr_avl_add(avl, box(220), box(504), NULL); + avl = remove_int(avl, 715); + avl = remove_int(avl, 279); + avl = gpr_avl_add(avl, box(701), box(507), NULL); + avl = gpr_avl_add(avl, box(726), box(508), NULL); + avl = gpr_avl_add(avl, box(815), box(509), NULL); + avl = gpr_avl_add(avl, box(749), box(510), NULL); + 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), NULL); + avl = remove_int(avl, 59); + avl = gpr_avl_add(avl, box(168), box(517), NULL); + avl = remove_int(avl, 337); + avl = gpr_avl_add(avl, box(69), box(519), NULL); + avl = remove_int(avl, 600); + avl = gpr_avl_add(avl, box(591), box(521), NULL); + avl = gpr_avl_add(avl, box(960), box(522), NULL); + avl = gpr_avl_add(avl, box(116), box(523), NULL); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(760), box(525), NULL); + avl = gpr_avl_add(avl, box(664), box(526), NULL); + avl = gpr_avl_add(avl, box(547), box(527), NULL); + avl = remove_int(avl, 922); + avl = gpr_avl_add(avl, box(290), box(529), NULL); + avl = gpr_avl_add(avl, box(859), box(530), NULL); + avl = gpr_avl_add(avl, box(49), box(531), NULL); + avl = remove_int(avl, 455); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(613), box(534), NULL); + avl = gpr_avl_add(avl, box(326), box(535), NULL); + avl = remove_int(avl, 615); + avl = gpr_avl_add(avl, box(45), box(537), NULL); + avl = gpr_avl_add(avl, box(162), box(538), NULL); + avl = gpr_avl_add(avl, box(189), box(539), NULL); + avl = remove_int(avl, 68); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(608), box(542), NULL); + avl = remove_int(avl, 821); + avl = gpr_avl_add(avl, box(978), box(544), NULL); + avl = gpr_avl_add(avl, box(892), box(545), NULL); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(708), box(547), NULL); + avl = remove_int(avl, 135); + avl = remove_int(avl, 124); + avl = gpr_avl_add(avl, box(301), box(550), NULL); + avl = gpr_avl_add(avl, box(939), box(551), NULL); + avl = gpr_avl_add(avl, box(344), box(552), NULL); + avl = remove_int(avl, 443); + avl = remove_int(avl, 122); + avl = gpr_avl_add(avl, box(636), box(555), NULL); + avl = remove_int(avl, 558); + avl = gpr_avl_add(avl, box(923), box(557), NULL); + avl = remove_int(avl, 827); + avl = gpr_avl_add(avl, box(649), box(559), NULL); + avl = gpr_avl_add(avl, box(808), box(560), NULL); + avl = remove_int(avl, 570); + avl = remove_int(avl, 434); + avl = gpr_avl_add(avl, box(40), box(563), NULL); + avl = gpr_avl_add(avl, box(725), box(564), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(512), box(572), NULL); + 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), NULL); + avl = remove_int(avl, 770); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(602), box(581), NULL); + avl = remove_int(avl, 251); + avl = gpr_avl_add(avl, box(303), box(583), NULL); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(714), box(585), NULL); + avl = remove_int(avl, 800); + avl = gpr_avl_add(avl, box(266), box(587), NULL); + avl = gpr_avl_add(avl, box(555), box(588), NULL); + avl = remove_int(avl, 604); + avl = remove_int(avl, 163); + avl = remove_int(avl, 497); + avl = gpr_avl_add(avl, box(296), box(592), NULL); + avl = remove_int(avl, 129); + avl = gpr_avl_add(avl, box(656), box(594), NULL); + avl = remove_int(avl, 769); + avl = remove_int(avl, 941); + avl = gpr_avl_add(avl, box(775), box(597), NULL); + avl = gpr_avl_add(avl, box(846), box(598), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(575), box(604), NULL); + avl = gpr_avl_add(avl, box(620), box(605), NULL); + avl = remove_int(avl, 100); + avl = remove_int(avl, 667); + avl = gpr_avl_add(avl, box(138), box(608), NULL); + avl = gpr_avl_add(avl, box(566), box(609), NULL); + avl = gpr_avl_add(avl, box(673), box(610), NULL); + avl = gpr_avl_add(avl, box(178), box(611), NULL); + avl = remove_int(avl, 659); + avl = gpr_avl_add(avl, box(759), box(613), NULL); + avl = gpr_avl_add(avl, box(1008), box(614), NULL); + avl = remove_int(avl, 116); + avl = gpr_avl_add(avl, box(608), box(616), NULL); + avl = gpr_avl_add(avl, box(339), box(617), NULL); + avl = gpr_avl_add(avl, box(197), box(618), NULL); + avl = remove_int(avl, 25); + avl = remove_int(avl, 628); + avl = gpr_avl_add(avl, box(487), box(621), NULL); + avl = remove_int(avl, 739); + avl = remove_int(avl, 100); + avl = remove_int(avl, 928); + avl = gpr_avl_add(avl, box(647), box(625), NULL); + avl = remove_int(avl, 978); + avl = remove_int(avl, 143); + avl = remove_int(avl, 755); + avl = gpr_avl_add(avl, box(71), box(629), NULL); + avl = remove_int(avl, 205); + avl = gpr_avl_add(avl, box(501), box(631), NULL); + 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), NULL); + avl = remove_int(avl, 264); + avl = gpr_avl_add(avl, box(69), box(639), NULL); + avl = remove_int(avl, 73); + avl = gpr_avl_add(avl, box(745), box(641), NULL); + avl = remove_int(avl, 518); + avl = remove_int(avl, 641); + avl = remove_int(avl, 768); + avl = gpr_avl_add(avl, box(988), box(645), NULL); + avl = gpr_avl_add(avl, box(899), box(646), NULL); + avl = remove_int(avl, 763); + avl = remove_int(avl, 281); + avl = remove_int(avl, 496); + avl = gpr_avl_add(avl, box(445), box(650), NULL); + avl = remove_int(avl, 905); + avl = gpr_avl_add(avl, box(275), box(652), NULL); + avl = gpr_avl_add(avl, box(137), box(653), NULL); + avl = remove_int(avl, 642); + avl = gpr_avl_add(avl, box(708), box(655), NULL); + avl = remove_int(avl, 922); + avl = gpr_avl_add(avl, box(743), box(657), NULL); + avl = remove_int(avl, 295); + avl = remove_int(avl, 665); + avl = remove_int(avl, 48); + avl = gpr_avl_add(avl, box(1012), box(661), NULL); + avl = remove_int(avl, 71); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(319), box(664), NULL); + avl = remove_int(avl, 632); + avl = gpr_avl_add(avl, box(137), box(666), NULL); + avl = gpr_avl_add(avl, box(686), box(667), NULL); + avl = gpr_avl_add(avl, box(724), box(668), NULL); + avl = gpr_avl_add(avl, box(952), box(669), NULL); + avl = gpr_avl_add(avl, box(5), box(670), NULL); + avl = remove_int(avl, 35); + avl = gpr_avl_add(avl, box(43), box(672), NULL); + avl = gpr_avl_add(avl, box(320), box(673), NULL); + avl = gpr_avl_add(avl, box(115), box(674), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(605), box(680), NULL); + avl = gpr_avl_add(avl, box(152), box(681), NULL); + avl = gpr_avl_add(avl, box(113), box(682), NULL); + avl = remove_int(avl, 131); + avl = remove_int(avl, 637); + avl = gpr_avl_add(avl, box(156), box(685), NULL); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(546), box(687), NULL); + 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), NULL); + avl = remove_int(avl, 924); + avl = gpr_avl_add(avl, box(825), box(703), NULL); + avl = remove_int(avl, 888); + avl = remove_int(avl, 931); + avl = gpr_avl_add(avl, box(285), box(706), NULL); + avl = remove_int(avl, 62); + avl = remove_int(avl, 444); + avl = remove_int(avl, 946); + avl = gpr_avl_add(avl, box(122), box(710), NULL); + avl = gpr_avl_add(avl, box(846), box(711), NULL); + avl = remove_int(avl, 628); + avl = gpr_avl_add(avl, box(511), box(713), NULL); + avl = gpr_avl_add(avl, box(398), box(714), NULL); + avl = remove_int(avl, 730); + avl = gpr_avl_add(avl, box(797), box(716), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(1015), box(726), NULL); + avl = remove_int(avl, 813); + avl = gpr_avl_add(avl, box(213), box(728), NULL); + avl = remove_int(avl, 468); + avl = remove_int(avl, 365); + avl = remove_int(avl, 399); + avl = gpr_avl_add(avl, box(380), box(732), NULL); + avl = remove_int(avl, 835); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(700), box(735), NULL); + avl = gpr_avl_add(avl, box(807), box(736), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(332), box(744), NULL); + avl = remove_int(avl, 686); + avl = remove_int(avl, 206); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(334), box(748), NULL); + avl = remove_int(avl, 171); + avl = gpr_avl_add(avl, box(1002), box(750), NULL); + avl = gpr_avl_add(avl, box(779), box(751), NULL); + avl = gpr_avl_add(avl, box(307), box(752), NULL); + avl = gpr_avl_add(avl, box(127), box(753), NULL); + avl = gpr_avl_add(avl, box(251), box(754), NULL); + 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), NULL); + avl = remove_int(avl, 43); + avl = gpr_avl_add(avl, box(871), box(762), NULL); + avl = gpr_avl_add(avl, box(580), box(763), NULL); + avl = remove_int(avl, 501); + avl = remove_int(avl, 462); + avl = remove_int(avl, 599); + avl = gpr_avl_add(avl, box(240), box(767), NULL); + avl = gpr_avl_add(avl, box(285), box(768), NULL); + avl = gpr_avl_add(avl, box(472), box(769), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(552), box(778), NULL); + avl = remove_int(avl, 19); + avl = remove_int(avl, 803); + avl = gpr_avl_add(avl, box(508), box(781), NULL); + 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), NULL); + 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), NULL); + 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), NULL); + avl = remove_int(avl, 38); + avl = remove_int(avl, 595); + avl = gpr_avl_add(avl, box(213), box(799), NULL); + avl = remove_int(avl, 7); + avl = remove_int(avl, 620); + avl = gpr_avl_add(avl, box(946), box(802), NULL); + avl = remove_int(avl, 145); + avl = gpr_avl_add(avl, box(628), box(804), NULL); + avl = remove_int(avl, 972); + avl = gpr_avl_add(avl, box(728), box(806), NULL); + avl = remove_int(avl, 91); + avl = gpr_avl_add(avl, box(136), box(808), NULL); + avl = gpr_avl_add(avl, box(841), box(809), NULL); + avl = gpr_avl_add(avl, box(265), box(810), NULL); + avl = gpr_avl_add(avl, box(701), box(811), NULL); + avl = gpr_avl_add(avl, box(27), box(812), NULL); + avl = remove_int(avl, 72); + avl = remove_int(avl, 14); + avl = gpr_avl_add(avl, box(286), box(815), NULL); + avl = remove_int(avl, 996); + avl = remove_int(avl, 998); + avl = gpr_avl_add(avl, box(466), box(818), NULL); + 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), NULL); + avl = remove_int(avl, 812); + avl = gpr_avl_add(avl, box(577), box(829), NULL); + avl = remove_int(avl, 624); + avl = remove_int(avl, 847); + avl = remove_int(avl, 745); + avl = gpr_avl_add(avl, box(491), box(833), NULL); + avl = gpr_avl_add(avl, box(941), box(834), NULL); + avl = remove_int(avl, 258); + avl = gpr_avl_add(avl, box(410), box(836), NULL); + avl = gpr_avl_add(avl, box(80), box(837), NULL); + avl = gpr_avl_add(avl, box(196), box(838), NULL); + avl = gpr_avl_add(avl, box(5), box(839), NULL); + avl = remove_int(avl, 782); + avl = gpr_avl_add(avl, box(827), box(841), NULL); + avl = remove_int(avl, 472); + avl = remove_int(avl, 664); + avl = gpr_avl_add(avl, box(409), box(844), NULL); + avl = gpr_avl_add(avl, box(62), box(845), NULL); + 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), NULL); + avl = remove_int(avl, 587); + avl = remove_int(avl, 350); + avl = gpr_avl_add(avl, box(980), box(855), NULL); + avl = gpr_avl_add(avl, box(992), box(856), NULL); + avl = gpr_avl_add(avl, box(818), box(857), NULL); + avl = remove_int(avl, 853); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(675), box(860), NULL); + avl = remove_int(avl, 248); + avl = remove_int(avl, 649); + avl = gpr_avl_add(avl, box(508), box(863), NULL); + avl = remove_int(avl, 927); + avl = gpr_avl_add(avl, box(957), box(865), NULL); + avl = gpr_avl_add(avl, box(698), box(866), NULL); + avl = gpr_avl_add(avl, box(388), box(867), NULL); + avl = gpr_avl_add(avl, box(532), box(868), NULL); + avl = gpr_avl_add(avl, box(681), box(869), NULL); + avl = remove_int(avl, 544); + avl = remove_int(avl, 991); + avl = remove_int(avl, 397); + avl = gpr_avl_add(avl, box(954), box(873), NULL); + avl = gpr_avl_add(avl, box(219), box(874), NULL); + avl = gpr_avl_add(avl, box(465), box(875), NULL); + avl = remove_int(avl, 371); + avl = gpr_avl_add(avl, box(601), box(877), NULL); + avl = gpr_avl_add(avl, box(543), box(878), NULL); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(560), box(880), NULL); + avl = remove_int(avl, 898); + avl = gpr_avl_add(avl, box(455), box(882), NULL); + avl = remove_int(avl, 313); + avl = gpr_avl_add(avl, box(215), box(884), NULL); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(608), box(886), NULL); + avl = remove_int(avl, 248); + avl = gpr_avl_add(avl, box(575), box(888), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(329), box(894), NULL); + avl = gpr_avl_add(avl, box(326), box(895), NULL); + avl = remove_int(avl, 746); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(464), box(898), NULL); + avl = gpr_avl_add(avl, box(141), box(899), NULL); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(414), box(901), NULL); + avl = gpr_avl_add(avl, box(777), box(902), NULL); + avl = remove_int(avl, 972); + avl = remove_int(avl, 841); + avl = remove_int(avl, 100); + avl = gpr_avl_add(avl, box(828), box(906), NULL); + avl = remove_int(avl, 785); + avl = gpr_avl_add(avl, box(1008), box(908), NULL); + avl = gpr_avl_add(avl, box(46), box(909), NULL); + avl = remove_int(avl, 399); + avl = gpr_avl_add(avl, box(178), box(911), NULL); + avl = gpr_avl_add(avl, box(573), box(912), NULL); + avl = remove_int(avl, 299); + avl = gpr_avl_add(avl, box(690), box(914), NULL); + avl = gpr_avl_add(avl, box(692), box(915), NULL); + 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), NULL); + avl = remove_int(avl, 328); + avl = gpr_avl_add(avl, box(89), box(923), NULL); + avl = remove_int(avl, 867); + avl = remove_int(avl, 626); + avl = remove_int(avl, 507); + avl = gpr_avl_add(avl, box(365), box(927), NULL); + avl = gpr_avl_add(avl, box(58), box(928), NULL); + avl = gpr_avl_add(avl, box(70), box(929), NULL); + avl = remove_int(avl, 81); + avl = remove_int(avl, 797); + avl = gpr_avl_add(avl, box(846), box(932), NULL); + avl = remove_int(avl, 642); + avl = gpr_avl_add(avl, box(777), box(934), NULL); + avl = remove_int(avl, 107); + avl = gpr_avl_add(avl, box(691), box(936), NULL); + avl = gpr_avl_add(avl, box(820), box(937), NULL); + avl = gpr_avl_add(avl, box(202), box(938), NULL); + avl = gpr_avl_add(avl, box(308), box(939), NULL); + avl = gpr_avl_add(avl, box(20), box(940), NULL); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(714), box(942), NULL); + avl = gpr_avl_add(avl, box(584), box(943), NULL); + avl = remove_int(avl, 294); + avl = gpr_avl_add(avl, box(496), box(945), NULL); + avl = gpr_avl_add(avl, box(394), box(946), NULL); + avl = gpr_avl_add(avl, box(860), box(947), NULL); + avl = gpr_avl_add(avl, box(58), box(948), NULL); + avl = remove_int(avl, 784); + avl = remove_int(avl, 584); + avl = remove_int(avl, 708); + avl = gpr_avl_add(avl, box(142), box(952), NULL); + avl = gpr_avl_add(avl, box(247), box(953), NULL); + avl = gpr_avl_add(avl, box(389), box(954), NULL); + avl = remove_int(avl, 390); + avl = gpr_avl_add(avl, box(465), box(956), NULL); + avl = gpr_avl_add(avl, box(936), box(957), NULL); + avl = gpr_avl_add(avl, box(309), box(958), NULL); + 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), NULL); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(728), box(968), NULL); + avl = remove_int(avl, 852); + avl = gpr_avl_add(avl, box(884), box(970), NULL); + avl = gpr_avl_add(avl, box(502), box(971), NULL); + avl = remove_int(avl, 898); + avl = remove_int(avl, 481); + avl = gpr_avl_add(avl, box(911), box(974), NULL); + 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), NULL); + avl = remove_int(avl, 25); + avl = remove_int(avl, 697); + avl = gpr_avl_add(avl, box(645), box(986), NULL); + avl = gpr_avl_add(avl, box(211), box(987), NULL); + avl = gpr_avl_add(avl, box(589), box(988), NULL); + avl = remove_int(avl, 702); + avl = gpr_avl_add(avl, box(53), box(990), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(834), box(998), NULL); + avl = gpr_avl_add(avl, box(514), box(999), NULL); + avl = gpr_avl_add(avl, box(75), box(1000), NULL); + avl = remove_int(avl, 745); + avl = gpr_avl_add(avl, box(362), box(1002), NULL); + avl = remove_int(avl, 215); + avl = gpr_avl_add(avl, box(624), box(1004), NULL); + avl = remove_int(avl, 404); + avl = remove_int(avl, 359); + avl = remove_int(avl, 491); + avl = gpr_avl_add(avl, box(903), box(1008), NULL); + avl = gpr_avl_add(avl, box(240), box(1009), NULL); + avl = remove_int(avl, 95); + avl = gpr_avl_add(avl, box(119), box(1011), NULL); + avl = gpr_avl_add(avl, box(857), box(1012), NULL); + avl = remove_int(avl, 39); + avl = remove_int(avl, 866); + avl = gpr_avl_add(avl, box(503), box(1015), NULL); + avl = gpr_avl_add(avl, box(740), box(1016), NULL); + 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), NULL); + avl = remove_int(avl, 638); + avl = gpr_avl_add(avl, box(299), box(1025), NULL); + avl = gpr_avl_add(avl, box(584), box(1026), NULL); + avl = remove_int(avl, 863); + avl = gpr_avl_add(avl, box(612), box(1028), NULL); + avl = gpr_avl_add(avl, box(62), box(1029), NULL); + avl = gpr_avl_add(avl, box(432), box(1030), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(644), box(1036), NULL); + avl = remove_int(avl, 638); + avl = gpr_avl_add(avl, box(13), box(1038), NULL); + avl = remove_int(avl, 66); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(362), box(1041), NULL); + avl = gpr_avl_add(avl, box(783), box(1042), NULL); + avl = remove_int(avl, 60); + avl = gpr_avl_add(avl, box(80), box(1044), NULL); + avl = gpr_avl_add(avl, box(825), box(1045), NULL); + avl = gpr_avl_add(avl, box(688), box(1046), NULL); + avl = gpr_avl_add(avl, box(662), box(1047), NULL); + avl = remove_int(avl, 156); + avl = remove_int(avl, 376); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(526), box(1051), NULL); + avl = gpr_avl_add(avl, box(168), box(1052), NULL); + avl = remove_int(avl, 646); + avl = remove_int(avl, 380); + avl = remove_int(avl, 833); + avl = gpr_avl_add(avl, box(53), box(1056), NULL); + avl = remove_int(avl, 105); + avl = gpr_avl_add(avl, box(373), box(1058), NULL); + avl = gpr_avl_add(avl, box(184), box(1059), NULL); + avl = remove_int(avl, 288); + avl = gpr_avl_add(avl, box(966), box(1061), NULL); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(406), box(1063), NULL); + avl = remove_int(avl, 470); + avl = gpr_avl_add(avl, box(283), box(1065), NULL); + avl = gpr_avl_add(avl, box(838), box(1066), NULL); + avl = gpr_avl_add(avl, box(288), box(1067), NULL); + avl = gpr_avl_add(avl, box(950), box(1068), NULL); + avl = gpr_avl_add(avl, box(163), box(1069), NULL); + avl = remove_int(avl, 623); + avl = remove_int(avl, 769); + avl = gpr_avl_add(avl, box(144), box(1072), NULL); + avl = gpr_avl_add(avl, box(489), box(1073), NULL); + avl = remove_int(avl, 15); + avl = gpr_avl_add(avl, box(971), box(1075), NULL); + avl = remove_int(avl, 660); + avl = gpr_avl_add(avl, box(255), box(1077), NULL); + avl = remove_int(avl, 494); + avl = gpr_avl_add(avl, box(109), box(1079), NULL); + avl = gpr_avl_add(avl, box(420), box(1080), NULL); + avl = gpr_avl_add(avl, box(509), box(1081), NULL); + avl = remove_int(avl, 178); + avl = gpr_avl_add(avl, box(216), box(1083), NULL); + avl = gpr_avl_add(avl, box(707), box(1084), NULL); + avl = gpr_avl_add(avl, box(411), box(1085), NULL); + avl = gpr_avl_add(avl, box(352), box(1086), NULL); + avl = remove_int(avl, 983); + avl = gpr_avl_add(avl, box(6), box(1088), NULL); + avl = gpr_avl_add(avl, box(1014), box(1089), NULL); + avl = remove_int(avl, 98); + avl = remove_int(avl, 325); + avl = gpr_avl_add(avl, box(851), box(1092), NULL); + avl = remove_int(avl, 553); + avl = gpr_avl_add(avl, box(218), box(1094), NULL); + avl = gpr_avl_add(avl, box(261), box(1095), NULL); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(872), box(1097), NULL); + avl = remove_int(avl, 543); + avl = remove_int(avl, 314); + avl = remove_int(avl, 443); + avl = gpr_avl_add(avl, box(533), box(1101), NULL); + 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), NULL); + avl = remove_int(avl, 622); + avl = gpr_avl_add(avl, box(352), box(1112), NULL); + avl = remove_int(avl, 182); + avl = gpr_avl_add(avl, box(534), box(1114), NULL); + avl = gpr_avl_add(avl, box(97), box(1115), NULL); + avl = gpr_avl_add(avl, box(198), box(1116), NULL); + avl = remove_int(avl, 750); + avl = gpr_avl_add(avl, box(98), box(1118), NULL); + avl = remove_int(avl, 943); + avl = gpr_avl_add(avl, box(254), box(1120), NULL); + avl = gpr_avl_add(avl, box(30), box(1121), NULL); + avl = remove_int(avl, 14); + avl = remove_int(avl, 475); + avl = remove_int(avl, 82); + avl = gpr_avl_add(avl, box(789), box(1125), NULL); + avl = gpr_avl_add(avl, box(402), box(1126), NULL); + avl = remove_int(avl, 1019); + avl = gpr_avl_add(avl, box(858), box(1128), NULL); + avl = gpr_avl_add(avl, box(625), box(1129), NULL); + avl = remove_int(avl, 675); + avl = remove_int(avl, 323); + avl = gpr_avl_add(avl, box(329), box(1132), NULL); + avl = remove_int(avl, 929); + avl = remove_int(avl, 44); + avl = gpr_avl_add(avl, box(443), box(1135), NULL); + avl = gpr_avl_add(avl, box(653), box(1136), NULL); + avl = gpr_avl_add(avl, box(750), box(1137), NULL); + avl = gpr_avl_add(avl, box(252), box(1138), NULL); + avl = gpr_avl_add(avl, box(449), box(1139), NULL); + 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), NULL); + avl = remove_int(avl, 806); + avl = gpr_avl_add(avl, box(455), box(1146), NULL); + avl = remove_int(avl, 31); + avl = gpr_avl_add(avl, box(154), box(1148), NULL); + avl = gpr_avl_add(avl, box(189), box(1149), NULL); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(496), box(1151), NULL); + avl = gpr_avl_add(avl, box(81), box(1152), NULL); + avl = gpr_avl_add(avl, box(59), box(1153), NULL); + avl = remove_int(avl, 424); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(723), box(1156), NULL); + avl = gpr_avl_add(avl, box(822), box(1157), NULL); + avl = gpr_avl_add(avl, box(354), box(1158), NULL); + avl = remove_int(avl, 738); + avl = gpr_avl_add(avl, box(686), box(1160), NULL); + avl = gpr_avl_add(avl, box(43), box(1161), NULL); + avl = gpr_avl_add(avl, box(625), box(1162), NULL); + avl = gpr_avl_add(avl, box(902), box(1163), NULL); + avl = gpr_avl_add(avl, box(12), box(1164), NULL); + avl = gpr_avl_add(avl, box(977), box(1165), NULL); + avl = gpr_avl_add(avl, box(699), box(1166), NULL); + avl = gpr_avl_add(avl, box(189), box(1167), NULL); + 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), NULL); + avl = remove_int(avl, 758); + avl = remove_int(avl, 222); + avl = gpr_avl_add(avl, box(975), box(1175), NULL); + avl = remove_int(avl, 993); + avl = gpr_avl_add(avl, box(2), box(1177), NULL); + avl = gpr_avl_add(avl, box(70), box(1178), NULL); + avl = remove_int(avl, 350); + avl = remove_int(avl, 972); + avl = remove_int(avl, 880); + avl = gpr_avl_add(avl, box(753), box(1182), NULL); + avl = remove_int(avl, 404); + avl = gpr_avl_add(avl, box(294), box(1184), NULL); + avl = remove_int(avl, 474); + avl = gpr_avl_add(avl, box(228), box(1186), NULL); + avl = gpr_avl_add(avl, box(484), box(1187), NULL); + avl = remove_int(avl, 238); + avl = remove_int(avl, 53); + avl = remove_int(avl, 691); + avl = gpr_avl_add(avl, box(345), box(1191), NULL); + avl = remove_int(avl, 0); + avl = gpr_avl_add(avl, box(230), box(1193), NULL); + avl = remove_int(avl, 227); + avl = remove_int(avl, 152); + avl = gpr_avl_add(avl, box(884), box(1196), NULL); + avl = remove_int(avl, 823); + avl = remove_int(avl, 53); + avl = gpr_avl_add(avl, box(1015), box(1199), NULL); + avl = gpr_avl_add(avl, box(697), box(1200), NULL); + avl = gpr_avl_add(avl, box(376), box(1201), NULL); + avl = remove_int(avl, 411); + avl = gpr_avl_add(avl, box(888), box(1203), NULL); + avl = remove_int(avl, 55); + avl = gpr_avl_add(avl, box(85), box(1205), NULL); + avl = remove_int(avl, 947); + avl = remove_int(avl, 382); + avl = remove_int(avl, 777); + avl = gpr_avl_add(avl, box(1017), box(1209), NULL); + avl = gpr_avl_add(avl, box(169), box(1210), NULL); + avl = gpr_avl_add(avl, box(156), box(1211), NULL); + avl = remove_int(avl, 153); + avl = remove_int(avl, 642); + avl = remove_int(avl, 158); + avl = gpr_avl_add(avl, box(554), box(1215), NULL); + avl = gpr_avl_add(avl, box(76), box(1216), NULL); + avl = gpr_avl_add(avl, box(756), box(1217), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(712), box(1227), NULL); + avl = gpr_avl_add(avl, box(474), box(1228), NULL); + avl = gpr_avl_add(avl, box(882), box(1229), NULL); + avl = gpr_avl_add(avl, box(965), box(1230), NULL); + avl = remove_int(avl, 464); + avl = gpr_avl_add(avl, box(319), box(1232), NULL); + avl = gpr_avl_add(avl, box(504), box(1233), NULL); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(884), box(1235), NULL); + avl = gpr_avl_add(avl, box(813), box(1236), NULL); + avl = gpr_avl_add(avl, box(795), box(1237), NULL); + avl = remove_int(avl, 306); + avl = gpr_avl_add(avl, box(799), box(1239), NULL); + avl = remove_int(avl, 534); + avl = gpr_avl_add(avl, box(480), box(1241), NULL); + avl = gpr_avl_add(avl, box(656), box(1242), NULL); + avl = gpr_avl_add(avl, box(709), box(1243), NULL); + avl = gpr_avl_add(avl, box(500), box(1244), NULL); + avl = remove_int(avl, 740); + avl = gpr_avl_add(avl, box(980), box(1246), NULL); + avl = gpr_avl_add(avl, box(458), box(1247), NULL); + avl = remove_int(avl, 377); + avl = remove_int(avl, 338); + avl = gpr_avl_add(avl, box(554), box(1250), NULL); + avl = gpr_avl_add(avl, box(504), box(1251), NULL); + avl = gpr_avl_add(avl, box(603), box(1252), NULL); + avl = gpr_avl_add(avl, box(761), box(1253), NULL); + avl = remove_int(avl, 431); + avl = gpr_avl_add(avl, box(707), box(1255), NULL); + avl = gpr_avl_add(avl, box(673), box(1256), NULL); + 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), NULL); + avl = remove_int(avl, 858); + avl = remove_int(avl, 997); + avl = gpr_avl_add(avl, box(519), box(1267), NULL); + avl = remove_int(avl, 614); + avl = remove_int(avl, 462); + avl = remove_int(avl, 792); + avl = gpr_avl_add(avl, box(987), box(1271), NULL); + avl = gpr_avl_add(avl, box(309), box(1272), NULL); + avl = remove_int(avl, 747); + avl = gpr_avl_add(avl, box(621), box(1274), NULL); + avl = gpr_avl_add(avl, box(450), box(1275), NULL); + avl = remove_int(avl, 265); + avl = remove_int(avl, 8); + avl = remove_int(avl, 383); + avl = gpr_avl_add(avl, box(238), box(1279), NULL); + avl = remove_int(avl, 241); + avl = gpr_avl_add(avl, box(180), box(1281), NULL); + avl = gpr_avl_add(avl, box(411), box(1282), NULL); + avl = gpr_avl_add(avl, box(791), box(1283), NULL); + avl = gpr_avl_add(avl, box(955), box(1284), NULL); + avl = remove_int(avl, 24); + avl = remove_int(avl, 375); + avl = gpr_avl_add(avl, box(140), box(1287), NULL); + avl = remove_int(avl, 949); + avl = gpr_avl_add(avl, box(301), box(1289), NULL); + avl = gpr_avl_add(avl, box(0), box(1290), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(127), box(1296), NULL); + avl = gpr_avl_add(avl, box(279), box(1297), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(304), box(1304), NULL); + avl = gpr_avl_add(avl, box(1), box(1305), NULL); + avl = gpr_avl_add(avl, box(339), box(1306), NULL); + 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), NULL); + avl = remove_int(avl, 85); + avl = gpr_avl_add(avl, box(964), box(1314), NULL); + avl = gpr_avl_add(avl, box(559), box(1315), NULL); + avl = remove_int(avl, 167); + avl = gpr_avl_add(avl, box(866), box(1317), NULL); + avl = remove_int(avl, 275); + avl = gpr_avl_add(avl, box(173), box(1319), NULL); + avl = gpr_avl_add(avl, box(765), box(1320), NULL); + avl = remove_int(avl, 883); + avl = gpr_avl_add(avl, box(547), box(1322), NULL); + avl = gpr_avl_add(avl, box(847), box(1323), NULL); + avl = remove_int(avl, 817); + avl = remove_int(avl, 850); + avl = remove_int(avl, 718); + avl = gpr_avl_add(avl, box(806), box(1327), NULL); + avl = gpr_avl_add(avl, box(360), box(1328), NULL); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(493), box(1330), NULL); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(361), box(1332), NULL); + avl = remove_int(avl, 355); + avl = gpr_avl_add(avl, box(512), box(1334), NULL); + avl = gpr_avl_add(avl, box(191), box(1335), NULL); + avl = remove_int(avl, 703); + avl = gpr_avl_add(avl, box(333), box(1337), NULL); + avl = remove_int(avl, 481); + avl = gpr_avl_add(avl, box(501), box(1339), NULL); + avl = remove_int(avl, 532); + avl = remove_int(avl, 510); + avl = gpr_avl_add(avl, box(793), box(1342), NULL); + avl = gpr_avl_add(avl, box(234), box(1343), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(702), box(1349), NULL); + avl = gpr_avl_add(avl, box(149), box(1350), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(455), box(1358), NULL); + avl = remove_int(avl, 782); + avl = remove_int(avl, 682); + avl = gpr_avl_add(avl, box(243), box(1361), NULL); + avl = gpr_avl_add(avl, box(109), box(1362), NULL); + avl = gpr_avl_add(avl, box(452), box(1363), NULL); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(159), box(1365), NULL); + avl = remove_int(avl, 1023); + avl = gpr_avl_add(avl, box(129), box(1367), NULL); + avl = gpr_avl_add(avl, box(537), box(1368), NULL); + avl = remove_int(avl, 321); + avl = gpr_avl_add(avl, box(740), box(1370), NULL); + avl = remove_int(avl, 45); + avl = remove_int(avl, 136); + avl = gpr_avl_add(avl, box(229), box(1373), NULL); + avl = remove_int(avl, 772); + avl = gpr_avl_add(avl, box(181), box(1375), NULL); + avl = remove_int(avl, 175); + avl = gpr_avl_add(avl, box(817), box(1377), NULL); + avl = remove_int(avl, 956); + avl = gpr_avl_add(avl, box(675), box(1379), NULL); + avl = gpr_avl_add(avl, box(375), box(1380), NULL); + avl = remove_int(avl, 384); + avl = gpr_avl_add(avl, box(1016), box(1382), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(293), box(1389), NULL); + avl = remove_int(avl, 207); + avl = remove_int(avl, 46); + avl = gpr_avl_add(avl, box(899), box(1392), NULL); + avl = gpr_avl_add(avl, box(666), box(1393), NULL); + avl = gpr_avl_add(avl, box(85), box(1394), NULL); + avl = gpr_avl_add(avl, box(914), box(1395), NULL); + avl = gpr_avl_add(avl, box(128), box(1396), NULL); + avl = gpr_avl_add(avl, box(835), box(1397), NULL); + avl = gpr_avl_add(avl, box(787), box(1398), NULL); + avl = gpr_avl_add(avl, box(649), box(1399), NULL); + avl = gpr_avl_add(avl, box(723), box(1400), NULL); + avl = remove_int(avl, 874); + avl = gpr_avl_add(avl, box(778), box(1402), NULL); + avl = gpr_avl_add(avl, box(1015), box(1403), NULL); + avl = gpr_avl_add(avl, box(59), box(1404), NULL); + avl = gpr_avl_add(avl, box(259), box(1405), NULL); + avl = gpr_avl_add(avl, box(758), box(1406), NULL); + avl = remove_int(avl, 648); + avl = gpr_avl_add(avl, box(145), box(1408), NULL); + avl = gpr_avl_add(avl, box(440), box(1409), NULL); + avl = remove_int(avl, 608); + avl = remove_int(avl, 690); + avl = gpr_avl_add(avl, box(605), box(1412), NULL); + avl = remove_int(avl, 856); + avl = remove_int(avl, 608); + avl = gpr_avl_add(avl, box(829), box(1415), NULL); + avl = gpr_avl_add(avl, box(660), box(1416), NULL); + avl = remove_int(avl, 596); + avl = gpr_avl_add(avl, box(519), box(1418), NULL); + avl = gpr_avl_add(avl, box(35), box(1419), NULL); + avl = gpr_avl_add(avl, box(871), box(1420), NULL); + avl = remove_int(avl, 845); + avl = gpr_avl_add(avl, box(600), box(1422), NULL); + avl = gpr_avl_add(avl, box(215), box(1423), NULL); + avl = remove_int(avl, 761); + avl = gpr_avl_add(avl, box(975), box(1425), NULL); + avl = remove_int(avl, 987); + avl = gpr_avl_add(avl, box(58), box(1427), NULL); + avl = remove_int(avl, 119); + avl = gpr_avl_add(avl, box(937), box(1429), NULL); + avl = gpr_avl_add(avl, box(372), box(1430), NULL); + avl = gpr_avl_add(avl, box(11), box(1431), NULL); + avl = gpr_avl_add(avl, box(398), box(1432), NULL); + avl = gpr_avl_add(avl, box(423), box(1433), NULL); + avl = remove_int(avl, 171); + avl = gpr_avl_add(avl, box(473), box(1435), NULL); + 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), NULL); + 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), NULL); + avl = remove_int(avl, 152); + avl = gpr_avl_add(avl, box(61), box(1448), NULL); + avl = remove_int(avl, 929); + avl = remove_int(avl, 9); + avl = gpr_avl_add(avl, box(251), box(1451), NULL); + avl = gpr_avl_add(avl, box(672), box(1452), NULL); + avl = gpr_avl_add(avl, box(66), box(1453), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(495), box(1459), NULL); + avl = remove_int(avl, 450); + avl = gpr_avl_add(avl, box(533), box(1461), NULL); + avl = gpr_avl_add(avl, box(414), box(1462), NULL); + avl = remove_int(avl, 74); + avl = remove_int(avl, 236); + avl = gpr_avl_add(avl, box(707), box(1465), NULL); + avl = gpr_avl_add(avl, box(357), box(1466), NULL); + avl = gpr_avl_add(avl, box(1007), box(1467), NULL); + avl = gpr_avl_add(avl, box(811), box(1468), NULL); + avl = gpr_avl_add(avl, box(418), box(1469), NULL); + avl = gpr_avl_add(avl, box(164), box(1470), NULL); + avl = gpr_avl_add(avl, box(622), box(1471), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(202), box(1478), NULL); + avl = gpr_avl_add(avl, box(312), box(1479), NULL); + avl = remove_int(avl, 274); + avl = gpr_avl_add(avl, box(684), box(1481), NULL); + avl = gpr_avl_add(avl, box(954), box(1482), NULL); + avl = gpr_avl_add(avl, box(637), box(1483), NULL); + avl = remove_int(avl, 716); + avl = gpr_avl_add(avl, box(198), box(1485), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(862), box(1491), NULL); + avl = remove_int(avl, 527); + avl = gpr_avl_add(avl, box(945), box(1493), NULL); + avl = remove_int(avl, 355); + avl = remove_int(avl, 144); + avl = gpr_avl_add(avl, box(229), box(1496), NULL); + avl = gpr_avl_add(avl, box(237), box(1497), NULL); + avl = remove_int(avl, 471); + avl = remove_int(avl, 901); + avl = gpr_avl_add(avl, box(905), box(1500), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(552), box(1506), NULL); + avl = gpr_avl_add(avl, box(30), box(1507), NULL); + avl = gpr_avl_add(avl, box(445), box(1508), NULL); + avl = remove_int(avl, 785); + avl = remove_int(avl, 185); + avl = gpr_avl_add(avl, box(405), box(1511), NULL); + avl = gpr_avl_add(avl, box(733), box(1512), NULL); + avl = gpr_avl_add(avl, box(573), box(1513), NULL); + avl = gpr_avl_add(avl, box(492), box(1514), NULL); + avl = gpr_avl_add(avl, box(343), box(1515), NULL); + avl = gpr_avl_add(avl, box(527), box(1516), NULL); + avl = gpr_avl_add(avl, box(596), box(1517), NULL); + avl = gpr_avl_add(avl, box(519), box(1518), NULL); + avl = remove_int(avl, 243); + avl = remove_int(avl, 722); + avl = gpr_avl_add(avl, box(772), box(1521), NULL); + avl = remove_int(avl, 152); + avl = remove_int(avl, 305); + avl = gpr_avl_add(avl, box(754), box(1524), NULL); + avl = gpr_avl_add(avl, box(373), box(1525), NULL); + avl = remove_int(avl, 995); + avl = gpr_avl_add(avl, box(329), box(1527), NULL); + avl = remove_int(avl, 397); + avl = gpr_avl_add(avl, box(884), box(1529), NULL); + avl = remove_int(avl, 329); + avl = remove_int(avl, 240); + avl = gpr_avl_add(avl, box(566), box(1532), NULL); + avl = gpr_avl_add(avl, box(232), box(1533), NULL); + avl = remove_int(avl, 993); + avl = gpr_avl_add(avl, box(888), box(1535), NULL); + avl = remove_int(avl, 242); + avl = gpr_avl_add(avl, box(941), box(1537), NULL); + avl = remove_int(avl, 415); + avl = gpr_avl_add(avl, box(992), box(1539), NULL); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(60), box(1541), NULL); + avl = gpr_avl_add(avl, box(97), box(1542), NULL); + avl = remove_int(avl, 965); + avl = remove_int(avl, 267); + avl = remove_int(avl, 360); + avl = gpr_avl_add(avl, box(5), box(1546), NULL); + avl = remove_int(avl, 429); + avl = gpr_avl_add(avl, box(412), box(1548), NULL); + avl = remove_int(avl, 632); + avl = remove_int(avl, 113); + avl = gpr_avl_add(avl, box(48), box(1551), NULL); + avl = gpr_avl_add(avl, box(108), box(1552), NULL); + avl = gpr_avl_add(avl, box(750), box(1553), NULL); + avl = remove_int(avl, 188); + avl = gpr_avl_add(avl, box(668), box(1555), NULL); + avl = remove_int(avl, 37); + avl = remove_int(avl, 737); + avl = gpr_avl_add(avl, box(93), box(1558), NULL); + avl = gpr_avl_add(avl, box(628), box(1559), NULL); + avl = gpr_avl_add(avl, box(480), box(1560), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(469), box(1567), NULL); + avl = remove_int(avl, 349); + avl = gpr_avl_add(avl, box(768), box(1569), NULL); + avl = gpr_avl_add(avl, box(915), box(1570), NULL); + avl = remove_int(avl, 1014); + avl = gpr_avl_add(avl, box(117), box(1572), NULL); + avl = remove_int(avl, 62); + avl = gpr_avl_add(avl, box(382), box(1574), NULL); + avl = remove_int(avl, 571); + avl = gpr_avl_add(avl, box(655), box(1576), NULL); + avl = gpr_avl_add(avl, box(323), box(1577), NULL); + avl = remove_int(avl, 869); + avl = remove_int(avl, 151); + avl = gpr_avl_add(avl, box(1019), box(1580), NULL); + avl = gpr_avl_add(avl, box(984), box(1581), NULL); + avl = gpr_avl_add(avl, box(870), box(1582), NULL); + avl = gpr_avl_add(avl, box(376), box(1583), NULL); + avl = remove_int(avl, 625); + avl = gpr_avl_add(avl, box(733), box(1585), NULL); + avl = remove_int(avl, 532); + avl = remove_int(avl, 444); + avl = gpr_avl_add(avl, box(428), box(1588), NULL); + avl = gpr_avl_add(avl, box(860), box(1589), NULL); + avl = gpr_avl_add(avl, box(173), box(1590), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(639), box(1596), NULL); + avl = remove_int(avl, 431); + avl = gpr_avl_add(avl, box(993), box(1598), NULL); + avl = remove_int(avl, 681); + avl = remove_int(avl, 927); + avl = gpr_avl_add(avl, box(87), box(1601), NULL); + avl = gpr_avl_add(avl, box(91), box(1602), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(951), box(1609), NULL); + avl = gpr_avl_add(avl, box(146), box(1610), NULL); + avl = gpr_avl_add(avl, box(482), box(1611), NULL); + avl = gpr_avl_add(avl, box(71), box(1612), NULL); + avl = remove_int(avl, 246); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(636), box(1615), NULL); + avl = gpr_avl_add(avl, box(295), box(1616), NULL); + avl = remove_int(avl, 11); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(905), box(1619), NULL); + avl = gpr_avl_add(avl, box(993), box(1620), NULL); + avl = gpr_avl_add(avl, box(433), box(1621), NULL); + avl = gpr_avl_add(avl, box(117), box(1622), NULL); + avl = gpr_avl_add(avl, box(467), box(1623), NULL); + avl = remove_int(avl, 419); + avl = gpr_avl_add(avl, box(179), box(1625), NULL); + avl = remove_int(avl, 926); + avl = remove_int(avl, 326); + avl = gpr_avl_add(avl, box(551), box(1628), NULL); + avl = remove_int(avl, 14); + avl = remove_int(avl, 476); + avl = remove_int(avl, 823); + avl = gpr_avl_add(avl, box(350), box(1632), NULL); + avl = gpr_avl_add(avl, box(133), box(1633), NULL); + avl = remove_int(avl, 906); + avl = gpr_avl_add(avl, box(827), box(1635), NULL); + avl = gpr_avl_add(avl, box(201), box(1636), NULL); + avl = remove_int(avl, 124); + avl = remove_int(avl, 662); + avl = gpr_avl_add(avl, box(314), box(1639), NULL); + avl = gpr_avl_add(avl, box(986), box(1640), NULL); + avl = gpr_avl_add(avl, box(622), box(1641), NULL); + avl = remove_int(avl, 130); + avl = gpr_avl_add(avl, box(861), box(1643), NULL); + avl = remove_int(avl, 497); + avl = remove_int(avl, 905); + avl = gpr_avl_add(avl, box(502), box(1646), NULL); + avl = remove_int(avl, 721); + avl = gpr_avl_add(avl, box(514), box(1648), NULL); + avl = gpr_avl_add(avl, box(410), box(1649), NULL); + avl = remove_int(avl, 869); + avl = remove_int(avl, 247); + avl = gpr_avl_add(avl, box(450), box(1652), NULL); + avl = remove_int(avl, 364); + avl = gpr_avl_add(avl, box(963), box(1654), NULL); + avl = gpr_avl_add(avl, box(146), box(1655), NULL); + avl = remove_int(avl, 147); + avl = remove_int(avl, 789); + avl = gpr_avl_add(avl, box(693), box(1658), NULL); + avl = gpr_avl_add(avl, box(959), box(1659), NULL); + avl = remove_int(avl, 478); + avl = gpr_avl_add(avl, box(116), box(1661), NULL); + avl = gpr_avl_add(avl, box(520), box(1662), NULL); + avl = gpr_avl_add(avl, box(809), box(1663), NULL); + avl = gpr_avl_add(avl, box(667), box(1664), NULL); + avl = gpr_avl_add(avl, box(406), box(1665), NULL); + avl = remove_int(avl, 409); + avl = gpr_avl_add(avl, box(558), box(1667), NULL); + avl = gpr_avl_add(avl, box(0), box(1668), NULL); + avl = gpr_avl_add(avl, box(948), box(1669), NULL); + avl = gpr_avl_add(avl, box(576), box(1670), NULL); + avl = remove_int(avl, 864); + avl = remove_int(avl, 840); + avl = remove_int(avl, 1001); + avl = gpr_avl_add(avl, box(232), box(1674), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(648), box(1680), NULL); + avl = gpr_avl_add(avl, box(761), box(1681), NULL); + avl = remove_int(avl, 293); + avl = remove_int(avl, 893); + avl = gpr_avl_add(avl, box(194), box(1684), NULL); + avl = remove_int(avl, 233); + avl = gpr_avl_add(avl, box(888), box(1686), NULL); + 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), NULL); + avl = remove_int(avl, 634); + avl = remove_int(avl, 335); + avl = gpr_avl_add(avl, box(718), box(1694), NULL); + avl = gpr_avl_add(avl, box(463), box(1695), NULL); + avl = gpr_avl_add(avl, box(233), box(1696), NULL); + 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), NULL); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(716), box(1705), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(212), box(1714), NULL); + avl = gpr_avl_add(avl, box(266), box(1715), NULL); + avl = gpr_avl_add(avl, box(238), box(1716), NULL); + avl = remove_int(avl, 153); + avl = gpr_avl_add(avl, box(585), box(1718), NULL); + avl = remove_int(avl, 121); + avl = gpr_avl_add(avl, box(534), box(1720), NULL); + avl = remove_int(avl, 579); + avl = gpr_avl_add(avl, box(127), box(1722), NULL); + avl = gpr_avl_add(avl, box(399), box(1723), NULL); + avl = remove_int(avl, 417); + avl = gpr_avl_add(avl, box(978), box(1725), NULL); + avl = gpr_avl_add(avl, box(768), box(1726), NULL); + avl = remove_int(avl, 985); + avl = gpr_avl_add(avl, box(536), box(1728), NULL); + avl = gpr_avl_add(avl, box(449), box(1729), NULL); + avl = gpr_avl_add(avl, box(586), box(1730), NULL); + avl = remove_int(avl, 998); + avl = remove_int(avl, 394); + avl = remove_int(avl, 141); + avl = gpr_avl_add(avl, box(889), box(1734), NULL); + avl = gpr_avl_add(avl, box(871), box(1735), NULL); + avl = gpr_avl_add(avl, box(76), box(1736), NULL); + avl = gpr_avl_add(avl, box(549), box(1737), NULL); + avl = gpr_avl_add(avl, box(757), box(1738), NULL); + avl = remove_int(avl, 908); + avl = gpr_avl_add(avl, box(789), box(1740), NULL); + avl = remove_int(avl, 224); + avl = gpr_avl_add(avl, box(407), box(1742), NULL); + avl = gpr_avl_add(avl, box(381), box(1743), NULL); + avl = gpr_avl_add(avl, box(561), box(1744), NULL); + avl = gpr_avl_add(avl, box(667), box(1745), NULL); + avl = gpr_avl_add(avl, box(522), box(1746), NULL); + avl = gpr_avl_add(avl, box(948), box(1747), NULL); + avl = remove_int(avl, 770); + avl = gpr_avl_add(avl, box(872), box(1749), NULL); + avl = gpr_avl_add(avl, box(327), box(1750), NULL); + avl = remove_int(avl, 10); + avl = gpr_avl_add(avl, box(122), box(1752), NULL); + avl = remove_int(avl, 606); + avl = gpr_avl_add(avl, box(485), box(1754), NULL); + avl = remove_int(avl, 6); + avl = gpr_avl_add(avl, box(329), box(1756), NULL); + avl = gpr_avl_add(avl, box(783), box(1757), NULL); + avl = remove_int(avl, 416); + avl = gpr_avl_add(avl, box(656), box(1759), NULL); + avl = gpr_avl_add(avl, box(971), box(1760), NULL); + avl = gpr_avl_add(avl, box(77), box(1761), NULL); + avl = gpr_avl_add(avl, box(942), box(1762), NULL); + avl = remove_int(avl, 361); + avl = gpr_avl_add(avl, box(66), box(1764), NULL); + avl = gpr_avl_add(avl, box(299), box(1765), NULL); + avl = gpr_avl_add(avl, box(929), box(1766), NULL); + avl = gpr_avl_add(avl, box(797), box(1767), NULL); + avl = remove_int(avl, 869); + avl = remove_int(avl, 907); + avl = gpr_avl_add(avl, box(870), box(1770), NULL); + avl = remove_int(avl, 580); + avl = remove_int(avl, 120); + avl = gpr_avl_add(avl, box(913), box(1773), NULL); + avl = remove_int(avl, 480); + avl = gpr_avl_add(avl, box(489), box(1775), NULL); + avl = remove_int(avl, 845); + avl = gpr_avl_add(avl, box(896), box(1777), NULL); + avl = remove_int(avl, 567); + avl = remove_int(avl, 427); + avl = gpr_avl_add(avl, box(443), box(1780), NULL); + avl = gpr_avl_add(avl, box(3), box(1781), NULL); + avl = remove_int(avl, 12); + avl = gpr_avl_add(avl, box(376), box(1783), NULL); + avl = gpr_avl_add(avl, box(155), box(1784), NULL); + avl = gpr_avl_add(avl, box(188), box(1785), NULL); + avl = gpr_avl_add(avl, box(149), box(1786), NULL); + avl = gpr_avl_add(avl, box(178), box(1787), NULL); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(805), box(1789), NULL); + avl = gpr_avl_add(avl, box(612), box(1790), NULL); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(837), box(1792), NULL); + avl = remove_int(avl, 173); + avl = remove_int(avl, 72); + avl = gpr_avl_add(avl, box(1014), box(1795), NULL); + avl = remove_int(avl, 303); + avl = gpr_avl_add(avl, box(865), box(1797), NULL); + avl = gpr_avl_add(avl, box(793), box(1798), NULL); + avl = remove_int(avl, 173); + avl = remove_int(avl, 477); + avl = gpr_avl_add(avl, box(950), box(1801), NULL); + avl = gpr_avl_add(avl, box(105), box(1802), NULL); + avl = gpr_avl_add(avl, box(895), box(1803), NULL); + avl = gpr_avl_add(avl, box(171), box(1804), NULL); + avl = gpr_avl_add(avl, box(753), box(1805), NULL); + avl = gpr_avl_add(avl, box(946), box(1806), NULL); + avl = remove_int(avl, 194); + avl = remove_int(avl, 559); + avl = remove_int(avl, 116); + avl = gpr_avl_add(avl, box(968), box(1810), NULL); + avl = remove_int(avl, 124); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(563), box(1813), NULL); + avl = remove_int(avl, 182); + avl = gpr_avl_add(avl, box(816), box(1815), NULL); + avl = remove_int(avl, 73); + avl = remove_int(avl, 261); + avl = gpr_avl_add(avl, box(847), box(1818), NULL); + avl = gpr_avl_add(avl, box(368), box(1819), NULL); + avl = gpr_avl_add(avl, box(808), box(1820), NULL); + avl = gpr_avl_add(avl, box(779), box(1821), NULL); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(466), box(1823), NULL); + avl = remove_int(avl, 316); + avl = gpr_avl_add(avl, box(986), box(1825), NULL); + avl = gpr_avl_add(avl, box(688), box(1826), NULL); + avl = gpr_avl_add(avl, box(509), box(1827), NULL); + avl = gpr_avl_add(avl, box(51), box(1828), NULL); + avl = remove_int(avl, 655); + avl = remove_int(avl, 785); + avl = remove_int(avl, 893); + avl = gpr_avl_add(avl, box(167), box(1832), NULL); + avl = remove_int(avl, 13); + avl = remove_int(avl, 263); + avl = gpr_avl_add(avl, box(1009), box(1835), NULL); + 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), NULL); + avl = remove_int(avl, 267); + avl = gpr_avl_add(avl, box(676), box(1842), NULL); + avl = gpr_avl_add(avl, box(231), box(1843), NULL); + avl = gpr_avl_add(avl, box(824), box(1844), NULL); + avl = remove_int(avl, 961); + avl = gpr_avl_add(avl, box(311), box(1846), NULL); + avl = gpr_avl_add(avl, box(420), box(1847), NULL); + avl = gpr_avl_add(avl, box(960), box(1848), NULL); + avl = gpr_avl_add(avl, box(468), box(1849), NULL); + avl = gpr_avl_add(avl, box(815), box(1850), NULL); + avl = remove_int(avl, 247); + avl = remove_int(avl, 194); + avl = gpr_avl_add(avl, box(546), box(1853), NULL); + avl = remove_int(avl, 222); + avl = remove_int(avl, 914); + avl = remove_int(avl, 741); + avl = gpr_avl_add(avl, box(470), box(1857), NULL); + avl = gpr_avl_add(avl, box(933), box(1858), NULL); + avl = gpr_avl_add(avl, box(97), box(1859), NULL); + avl = remove_int(avl, 564); + avl = remove_int(avl, 295); + avl = gpr_avl_add(avl, box(864), box(1862), NULL); + avl = remove_int(avl, 329); + avl = gpr_avl_add(avl, box(124), box(1864), NULL); + avl = gpr_avl_add(avl, box(1000), box(1865), NULL); + avl = gpr_avl_add(avl, box(228), box(1866), NULL); + avl = gpr_avl_add(avl, box(187), box(1867), NULL); + avl = remove_int(avl, 224); + avl = remove_int(avl, 306); + avl = remove_int(avl, 884); + avl = gpr_avl_add(avl, box(449), box(1871), NULL); + avl = gpr_avl_add(avl, box(353), box(1872), NULL); + avl = gpr_avl_add(avl, box(994), box(1873), NULL); + avl = gpr_avl_add(avl, box(596), box(1874), NULL); + avl = gpr_avl_add(avl, box(996), box(1875), NULL); + avl = gpr_avl_add(avl, box(101), box(1876), NULL); + avl = gpr_avl_add(avl, box(1012), box(1877), NULL); + avl = gpr_avl_add(avl, box(982), box(1878), NULL); + avl = gpr_avl_add(avl, box(742), box(1879), NULL); + avl = remove_int(avl, 92); + avl = remove_int(avl, 1022); + avl = gpr_avl_add(avl, box(941), box(1882), NULL); + avl = remove_int(avl, 742); + avl = remove_int(avl, 919); + avl = gpr_avl_add(avl, box(588), box(1885), NULL); + avl = remove_int(avl, 221); + avl = gpr_avl_add(avl, box(356), box(1887), NULL); + avl = gpr_avl_add(avl, box(932), box(1888), NULL); + avl = remove_int(avl, 837); + avl = gpr_avl_add(avl, box(394), box(1890), NULL); + avl = gpr_avl_add(avl, box(642), box(1891), NULL); + avl = gpr_avl_add(avl, box(52), box(1892), NULL); + avl = gpr_avl_add(avl, box(437), box(1893), NULL); + avl = gpr_avl_add(avl, box(948), box(1894), NULL); + avl = gpr_avl_add(avl, box(93), box(1895), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(952), box(1901), NULL); + avl = gpr_avl_add(avl, box(510), box(1902), NULL); + avl = remove_int(avl, 876); + avl = remove_int(avl, 612); + avl = gpr_avl_add(avl, box(923), box(1905), NULL); + avl = gpr_avl_add(avl, box(475), box(1906), NULL); + avl = remove_int(avl, 478); + avl = remove_int(avl, 148); + avl = gpr_avl_add(avl, box(538), box(1909), NULL); + avl = remove_int(avl, 47); + avl = gpr_avl_add(avl, box(89), box(1911), NULL); + avl = remove_int(avl, 723); + avl = gpr_avl_add(avl, box(687), box(1913), NULL); + avl = gpr_avl_add(avl, box(480), box(1914), NULL); + avl = gpr_avl_add(avl, box(149), box(1915), NULL); + avl = remove_int(avl, 68); + avl = remove_int(avl, 862); + avl = remove_int(avl, 363); + avl = gpr_avl_add(avl, box(996), box(1919), NULL); + avl = remove_int(avl, 380); + avl = gpr_avl_add(avl, box(957), box(1921), NULL); + avl = remove_int(avl, 413); + avl = gpr_avl_add(avl, box(360), box(1923), NULL); + avl = gpr_avl_add(avl, box(304), box(1924), NULL); + avl = gpr_avl_add(avl, box(634), box(1925), NULL); + avl = gpr_avl_add(avl, box(506), box(1926), NULL); + avl = remove_int(avl, 248); + avl = gpr_avl_add(avl, box(124), box(1928), NULL); + avl = gpr_avl_add(avl, box(181), box(1929), NULL); + avl = remove_int(avl, 507); + avl = gpr_avl_add(avl, box(141), box(1931), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(906), box(1937), NULL); + avl = gpr_avl_add(avl, box(44), box(1938), NULL); + avl = remove_int(avl, 949); + avl = remove_int(avl, 117); + avl = gpr_avl_add(avl, box(700), box(1941), NULL); + avl = gpr_avl_add(avl, box(258), box(1942), NULL); + avl = remove_int(avl, 828); + avl = gpr_avl_add(avl, box(860), box(1944), NULL); + avl = gpr_avl_add(avl, box(987), box(1945), NULL); + avl = gpr_avl_add(avl, box(316), box(1946), NULL); + avl = gpr_avl_add(avl, box(919), box(1947), NULL); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(473), box(1949), NULL); + avl = remove_int(avl, 127); + avl = remove_int(avl, 829); + avl = remove_int(avl, 829); + avl = gpr_avl_add(avl, box(488), box(1953), NULL); + avl = gpr_avl_add(avl, box(954), box(1954), NULL); + avl = remove_int(avl, 198); + avl = remove_int(avl, 972); + avl = remove_int(avl, 670); + avl = gpr_avl_add(avl, box(822), box(1958), NULL); + avl = remove_int(avl, 589); + avl = remove_int(avl, 459); + avl = gpr_avl_add(avl, box(1003), box(1961), NULL); + avl = gpr_avl_add(avl, box(657), box(1962), NULL); + avl = gpr_avl_add(avl, box(477), box(1963), NULL); + avl = gpr_avl_add(avl, box(923), box(1964), NULL); + avl = remove_int(avl, 496); + avl = remove_int(avl, 99); + avl = gpr_avl_add(avl, box(127), box(1967), NULL); + avl = gpr_avl_add(avl, box(1013), box(1968), NULL); + avl = gpr_avl_add(avl, box(778), box(1969), NULL); + 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), NULL); + 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), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(412), box(1986), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(408), box(1992), NULL); + avl = gpr_avl_add(avl, box(841), box(1993), NULL); + avl = remove_int(avl, 593); + avl = gpr_avl_add(avl, box(582), box(1995), NULL); + avl = gpr_avl_add(avl, box(597), box(1996), NULL); + avl = remove_int(avl, 49); + avl = remove_int(avl, 835); + avl = gpr_avl_add(avl, box(417), box(1999), NULL); + avl = gpr_avl_add(avl, box(191), box(2000), NULL); + avl = remove_int(avl, 406); + avl = gpr_avl_add(avl, box(30), box(2002), NULL); + avl = remove_int(avl, 841); + avl = remove_int(avl, 50); + avl = gpr_avl_add(avl, box(967), box(2005), NULL); + avl = gpr_avl_add(avl, box(849), box(2006), NULL); + avl = remove_int(avl, 608); + avl = gpr_avl_add(avl, box(306), box(2008), NULL); + avl = remove_int(avl, 779); + avl = gpr_avl_add(avl, box(897), box(2010), NULL); + avl = gpr_avl_add(avl, box(147), box(2011), NULL); + avl = remove_int(avl, 982); + avl = gpr_avl_add(avl, box(470), box(2013), NULL); + avl = remove_int(avl, 951); + avl = gpr_avl_add(avl, box(388), box(2015), NULL); + 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), NULL); + avl = remove_int(avl, 671); + avl = gpr_avl_add(avl, box(1020), box(2022), NULL); + avl = remove_int(avl, 277); + avl = gpr_avl_add(avl, box(681), box(2024), NULL); + avl = gpr_avl_add(avl, box(179), box(2025), NULL); + avl = gpr_avl_add(avl, box(370), box(2026), NULL); + avl = gpr_avl_add(avl, box(0), box(2027), NULL); + avl = remove_int(avl, 523); + avl = gpr_avl_add(avl, box(99), box(2029), NULL); + avl = gpr_avl_add(avl, box(334), box(2030), NULL); + avl = gpr_avl_add(avl, box(569), box(2031), NULL); + avl = gpr_avl_add(avl, box(257), box(2032), NULL); + avl = remove_int(avl, 572); + avl = gpr_avl_add(avl, box(805), box(2034), NULL); + avl = gpr_avl_add(avl, box(143), box(2035), NULL); + avl = gpr_avl_add(avl, box(670), box(2036), NULL); + avl = remove_int(avl, 42); + avl = gpr_avl_add(avl, box(46), box(2038), NULL); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(353), box(2040), NULL); + avl = remove_int(avl, 258); + avl = gpr_avl_add(avl, box(451), box(2042), NULL); + avl = gpr_avl_add(avl, box(28), box(2043), NULL); + avl = gpr_avl_add(avl, box(729), box(2044), NULL); + avl = gpr_avl_add(avl, box(401), box(2045), NULL); + avl = gpr_avl_add(avl, box(614), box(2046), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(980), box(2052), NULL); + avl = gpr_avl_add(avl, box(990), box(2053), NULL); + avl = gpr_avl_add(avl, box(355), box(2054), NULL); + avl = remove_int(avl, 730); + avl = remove_int(avl, 37); + avl = gpr_avl_add(avl, box(407), box(2057), NULL); + avl = gpr_avl_add(avl, box(222), box(2058), NULL); + avl = gpr_avl_add(avl, box(439), box(2059), NULL); + avl = gpr_avl_add(avl, box(563), box(2060), NULL); + avl = remove_int(avl, 992); + avl = remove_int(avl, 786); + avl = gpr_avl_add(avl, box(1), box(2063), NULL); + avl = gpr_avl_add(avl, box(473), box(2064), NULL); + avl = gpr_avl_add(avl, box(992), box(2065), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(35), box(2071), NULL); + avl = remove_int(avl, 843); + avl = gpr_avl_add(avl, box(855), box(2073), NULL); + avl = remove_int(avl, 878); + avl = gpr_avl_add(avl, box(993), box(2075), NULL); + avl = gpr_avl_add(avl, box(87), box(2076), NULL); + avl = gpr_avl_add(avl, box(572), box(2077), NULL); + avl = remove_int(avl, 896); + avl = gpr_avl_add(avl, box(849), box(2079), NULL); + avl = remove_int(avl, 597); + avl = gpr_avl_add(avl, box(472), box(2081), NULL); + avl = remove_int(avl, 778); + avl = remove_int(avl, 934); + avl = remove_int(avl, 314); + avl = gpr_avl_add(avl, box(101), box(2085), NULL); + avl = remove_int(avl, 938); + avl = remove_int(avl, 1010); + avl = gpr_avl_add(avl, box(579), box(2088), NULL); + avl = remove_int(avl, 798); + avl = remove_int(avl, 88); + avl = gpr_avl_add(avl, box(851), box(2091), NULL); + avl = remove_int(avl, 705); + avl = gpr_avl_add(avl, box(26), box(2093), NULL); + avl = remove_int(avl, 973); + avl = gpr_avl_add(avl, box(923), box(2095), NULL); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(310), box(2097), NULL); + avl = gpr_avl_add(avl, box(269), box(2098), NULL); + avl = remove_int(avl, 173); + avl = gpr_avl_add(avl, box(279), box(2100), NULL); + avl = remove_int(avl, 203); + avl = gpr_avl_add(avl, box(411), box(2102), NULL); + avl = remove_int(avl, 950); + avl = gpr_avl_add(avl, box(6), box(2104), NULL); + avl = remove_int(avl, 400); + avl = remove_int(avl, 468); + avl = remove_int(avl, 271); + avl = gpr_avl_add(avl, box(627), box(2108), NULL); + 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), NULL); + avl = remove_int(avl, 194); + avl = remove_int(avl, 18); + avl = gpr_avl_add(avl, box(727), box(2120), NULL); + avl = remove_int(avl, 295); + avl = gpr_avl_add(avl, box(645), box(2122), NULL); + avl = remove_int(avl, 321); + avl = remove_int(avl, 863); + avl = gpr_avl_add(avl, box(824), box(2125), NULL); + avl = gpr_avl_add(avl, box(651), box(2126), NULL); + avl = gpr_avl_add(avl, box(804), box(2127), NULL); + avl = remove_int(avl, 307); + avl = gpr_avl_add(avl, box(867), box(2129), NULL); + avl = remove_int(avl, 384); + avl = gpr_avl_add(avl, box(819), box(2131), NULL); + avl = remove_int(avl, 674); + avl = gpr_avl_add(avl, box(76), box(2133), NULL); + avl = remove_int(avl, 898); + avl = gpr_avl_add(avl, box(45), box(2135), NULL); + avl = gpr_avl_add(avl, box(512), box(2136), NULL); + 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), NULL); + avl = remove_int(avl, 509); + avl = remove_int(avl, 301); + avl = gpr_avl_add(avl, box(861), box(2146), NULL); + avl = gpr_avl_add(avl, box(918), box(2147), NULL); + avl = remove_int(avl, 992); + avl = gpr_avl_add(avl, box(356), box(2149), NULL); + avl = remove_int(avl, 64); + avl = remove_int(avl, 444); + avl = remove_int(avl, 741); + avl = gpr_avl_add(avl, box(710), box(2153), NULL); + avl = gpr_avl_add(avl, box(264), box(2154), NULL); + avl = remove_int(avl, 347); + avl = remove_int(avl, 250); + avl = gpr_avl_add(avl, box(82), box(2157), NULL); + avl = gpr_avl_add(avl, box(571), box(2158), NULL); + avl = remove_int(avl, 721); + avl = remove_int(avl, 622); + avl = gpr_avl_add(avl, box(950), box(2161), NULL); + avl = gpr_avl_add(avl, box(94), box(2162), NULL); + avl = remove_int(avl, 970); + avl = gpr_avl_add(avl, box(815), box(2164), NULL); + avl = remove_int(avl, 930); + avl = remove_int(avl, 703); + avl = gpr_avl_add(avl, box(432), box(2167), NULL); + avl = remove_int(avl, 544); + avl = gpr_avl_add(avl, box(21), box(2169), NULL); + avl = gpr_avl_add(avl, box(186), box(2170), NULL); + avl = remove_int(avl, 143); + avl = gpr_avl_add(avl, box(425), box(2172), NULL); + avl = remove_int(avl, 769); + avl = gpr_avl_add(avl, box(656), box(2174), NULL); + avl = remove_int(avl, 29); + avl = gpr_avl_add(avl, box(464), box(2176), NULL); + avl = remove_int(avl, 713); + avl = gpr_avl_add(avl, box(800), box(2178), NULL); + avl = remove_int(avl, 621); + avl = gpr_avl_add(avl, box(962), box(2180), NULL); + avl = remove_int(avl, 448); + avl = gpr_avl_add(avl, box(878), box(2182), NULL); + avl = remove_int(avl, 39); + avl = remove_int(avl, 999); + avl = gpr_avl_add(avl, box(182), box(2185), NULL); + avl = gpr_avl_add(avl, box(429), box(2186), NULL); + avl = gpr_avl_add(avl, box(598), box(2187), NULL); + avl = remove_int(avl, 551); + avl = gpr_avl_add(avl, box(827), box(2189), NULL); + avl = gpr_avl_add(avl, box(809), box(2190), NULL); + avl = remove_int(avl, 438); + avl = remove_int(avl, 811); + avl = gpr_avl_add(avl, box(808), box(2193), NULL); + avl = gpr_avl_add(avl, box(788), box(2194), NULL); + avl = remove_int(avl, 156); + avl = gpr_avl_add(avl, box(933), box(2196), NULL); + avl = gpr_avl_add(avl, box(344), box(2197), NULL); + avl = remove_int(avl, 460); + avl = gpr_avl_add(avl, box(161), box(2199), NULL); + avl = gpr_avl_add(avl, box(444), box(2200), NULL); + avl = remove_int(avl, 597); + avl = remove_int(avl, 668); + avl = gpr_avl_add(avl, box(703), box(2203), NULL); + avl = remove_int(avl, 515); + avl = gpr_avl_add(avl, box(380), box(2205), NULL); + avl = gpr_avl_add(avl, box(338), box(2206), NULL); + 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), NULL); + avl = remove_int(avl, 450); + avl = gpr_avl_add(avl, box(411), box(2213), NULL); + avl = gpr_avl_add(avl, box(117), box(2214), NULL); + avl = gpr_avl_add(avl, box(322), box(2215), NULL); + avl = gpr_avl_add(avl, box(915), box(2216), NULL); + avl = gpr_avl_add(avl, box(410), box(2217), NULL); + avl = gpr_avl_add(avl, box(66), box(2218), NULL); + avl = remove_int(avl, 756); + avl = remove_int(avl, 596); + avl = gpr_avl_add(avl, box(882), box(2221), NULL); + avl = gpr_avl_add(avl, box(930), box(2222), NULL); + avl = gpr_avl_add(avl, box(36), box(2223), NULL); + avl = remove_int(avl, 742); + avl = gpr_avl_add(avl, box(539), box(2225), NULL); + avl = gpr_avl_add(avl, box(596), box(2226), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(493), box(2233), NULL); + avl = gpr_avl_add(avl, box(839), box(2234), NULL); + avl = remove_int(avl, 774); + avl = gpr_avl_add(avl, box(337), box(2236), NULL); + avl = remove_int(avl, 322); + avl = gpr_avl_add(avl, box(16), box(2238), NULL); + 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), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(138), box(2249), NULL); + avl = gpr_avl_add(avl, box(437), box(2250), NULL); + avl = gpr_avl_add(avl, box(275), box(2251), NULL); + avl = remove_int(avl, 520); + avl = gpr_avl_add(avl, box(1019), box(2253), NULL); + avl = remove_int(avl, 955); + avl = gpr_avl_add(avl, box(270), box(2255), NULL); + avl = remove_int(avl, 680); + avl = remove_int(avl, 698); + avl = gpr_avl_add(avl, box(735), box(2258), NULL); + avl = gpr_avl_add(avl, box(400), box(2259), NULL); + avl = remove_int(avl, 991); + avl = gpr_avl_add(avl, box(263), box(2261), NULL); + avl = remove_int(avl, 704); + avl = gpr_avl_add(avl, box(757), box(2263), NULL); + avl = remove_int(avl, 194); + avl = remove_int(avl, 616); + avl = remove_int(avl, 784); + avl = gpr_avl_add(avl, box(382), box(2267), NULL); + avl = gpr_avl_add(avl, box(464), box(2268), NULL); + avl = gpr_avl_add(avl, box(817), box(2269), NULL); + avl = remove_int(avl, 445); + avl = gpr_avl_add(avl, box(412), box(2271), NULL); + avl = remove_int(avl, 525); + avl = gpr_avl_add(avl, box(299), box(2273), NULL); + avl = gpr_avl_add(avl, box(464), box(2274), NULL); + avl = gpr_avl_add(avl, box(715), box(2275), NULL); + avl = remove_int(avl, 58); + avl = remove_int(avl, 218); + avl = gpr_avl_add(avl, box(961), box(2278), NULL); + avl = gpr_avl_add(avl, box(491), box(2279), NULL); + avl = remove_int(avl, 846); + avl = gpr_avl_add(avl, box(762), box(2281), NULL); + avl = remove_int(avl, 974); + avl = remove_int(avl, 887); + avl = gpr_avl_add(avl, box(498), box(2284), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(1021), box(2290), NULL); + avl = remove_int(avl, 155); + avl = remove_int(avl, 128); + avl = gpr_avl_add(avl, box(819), box(2293), NULL); + avl = gpr_avl_add(avl, box(324), box(2294), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(474), box(2301), NULL); + avl = gpr_avl_add(avl, box(719), box(2302), NULL); + avl = gpr_avl_add(avl, box(236), box(2303), NULL); + avl = remove_int(avl, 818); + avl = gpr_avl_add(avl, box(727), box(2305), NULL); + avl = remove_int(avl, 892); + avl = remove_int(avl, 871); + avl = remove_int(avl, 231); + avl = gpr_avl_add(avl, box(62), box(2309), NULL); + avl = gpr_avl_add(avl, box(953), box(2310), NULL); + avl = remove_int(avl, 701); + avl = gpr_avl_add(avl, box(193), box(2312), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(751), box(2318), NULL); + avl = remove_int(avl, 525); + avl = gpr_avl_add(avl, box(217), box(2320), NULL); + avl = remove_int(avl, 336); + avl = gpr_avl_add(avl, box(86), box(2322), NULL); + avl = gpr_avl_add(avl, box(81), box(2323), NULL); + avl = gpr_avl_add(avl, box(850), box(2324), NULL); + avl = remove_int(avl, 872); + avl = gpr_avl_add(avl, box(402), box(2326), NULL); + avl = gpr_avl_add(avl, box(54), box(2327), NULL); + avl = gpr_avl_add(avl, box(980), box(2328), NULL); + avl = gpr_avl_add(avl, box(845), box(2329), NULL); + avl = remove_int(avl, 1004); + avl = remove_int(avl, 273); + avl = remove_int(avl, 879); + avl = gpr_avl_add(avl, box(354), box(2333), NULL); + avl = gpr_avl_add(avl, box(58), box(2334), NULL); + avl = gpr_avl_add(avl, box(127), box(2335), NULL); + avl = remove_int(avl, 84); + avl = gpr_avl_add(avl, box(360), box(2337), NULL); + 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), NULL); + avl = remove_int(avl, 558); + avl = remove_int(avl, 958); + avl = gpr_avl_add(avl, box(822), box(2345), NULL); + avl = remove_int(avl, 1004); + avl = remove_int(avl, 747); + avl = gpr_avl_add(avl, box(631), box(2348), NULL); + avl = gpr_avl_add(avl, box(442), box(2349), NULL); + avl = remove_int(avl, 957); + avl = remove_int(avl, 964); + avl = gpr_avl_add(avl, box(10), box(2352), NULL); + avl = remove_int(avl, 189); + avl = gpr_avl_add(avl, box(742), box(2354), NULL); + avl = remove_int(avl, 108); + avl = gpr_avl_add(avl, box(1014), box(2356), NULL); + avl = remove_int(avl, 266); + avl = remove_int(avl, 623); + avl = remove_int(avl, 697); + avl = gpr_avl_add(avl, box(180), box(2360), NULL); + avl = remove_int(avl, 472); + avl = gpr_avl_add(avl, box(567), box(2362), NULL); + avl = remove_int(avl, 1020); + avl = remove_int(avl, 273); + avl = gpr_avl_add(avl, box(864), box(2365), NULL); + avl = gpr_avl_add(avl, box(1009), box(2366), NULL); + avl = remove_int(avl, 224); + avl = remove_int(avl, 81); + avl = gpr_avl_add(avl, box(653), box(2369), NULL); + 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), NULL); + 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), NULL); + avl = gpr_avl_add(avl, box(925), box(2383), NULL); + avl = remove_int(avl, 994); + avl = remove_int(avl, 324); + avl = gpr_avl_add(avl, box(291), box(2386), NULL); + avl = remove_int(avl, 94); + avl = remove_int(avl, 795); + avl = remove_int(avl, 42); + avl = gpr_avl_add(avl, box(613), box(2390), NULL); + avl = remove_int(avl, 289); + avl = gpr_avl_add(avl, box(980), box(2392), NULL); + avl = remove_int(avl, 316); + avl = gpr_avl_add(avl, box(281), box(2394), NULL); + avl = gpr_avl_add(avl, box(1006), box(2395), NULL); + avl = remove_int(avl, 776); + avl = gpr_avl_add(avl, box(108), box(2397), NULL); + avl = gpr_avl_add(avl, box(918), box(2398), NULL); + avl = remove_int(avl, 721); + avl = remove_int(avl, 563); + avl = gpr_avl_add(avl, box(925), box(2401), NULL); + avl = remove_int(avl, 448); + avl = remove_int(avl, 198); + avl = remove_int(avl, 1); + avl = gpr_avl_add(avl, box(160), box(2405), NULL); + avl = remove_int(avl, 515); + avl = gpr_avl_add(avl, box(284), box(2407), NULL); + avl = gpr_avl_add(avl, box(225), box(2408), NULL); + avl = remove_int(avl, 304); + avl = gpr_avl_add(avl, box(714), box(2410), NULL); + avl = gpr_avl_add(avl, box(708), box(2411), NULL); + avl = gpr_avl_add(avl, box(624), box(2412), NULL); + 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), NULL); + avl = remove_int(avl, 280); + avl = remove_int(avl, 25); + avl = remove_int(avl, 633); + avl = gpr_avl_add(avl, box(897), box(2421), NULL); + 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), NULL); + avl = remove_int(avl, 948); + avl = remove_int(avl, 74); + avl = remove_int(avl, 571); + avl = gpr_avl_add(avl, box(486), box(2435), NULL); + avl = gpr_avl_add(avl, box(285), box(2436), NULL); + avl = remove_int(avl, 304); + avl = remove_int(avl, 516); + avl = gpr_avl_add(avl, box(758), box(2439), NULL); + avl = gpr_avl_add(avl, box(776), box(2440), NULL); + avl = remove_int(avl, 696); + avl = gpr_avl_add(avl, box(104), box(2442), NULL); + avl = gpr_avl_add(avl, box(700), box(2443), NULL); + avl = gpr_avl_add(avl, box(114), box(2444), NULL); + avl = gpr_avl_add(avl, box(567), box(2445), NULL); + avl = remove_int(avl, 620); + avl = gpr_avl_add(avl, box(270), box(2447), NULL); + avl = remove_int(avl, 730); + avl = gpr_avl_add(avl, box(749), box(2449), NULL); + avl = gpr_avl_add(avl, box(443), box(2450), NULL); + avl = remove_int(avl, 457); + avl = gpr_avl_add(avl, box(571), box(2452), NULL); + avl = gpr_avl_add(avl, box(626), box(2453), NULL); + avl = remove_int(avl, 638); + avl = remove_int(avl, 313); + + gpr_avl_unref(avl, NULL); +} + +static void test_stress(int amount_of_stress) { + int added[1024]; + int i, j; + int deletions = 0; + gpr_avl avl; + + unsigned seed = (unsigned)time(NULL); + + gpr_log(GPR_DEBUG, "test_stress amount=%d seed=%u", amount_of_stress, seed); + + srand((unsigned)time(NULL)); + avl = gpr_avl_create(&int_int_vtable); + + memset(added, 0, sizeof(added)); + + for (i = 1; deletions < amount_of_stress; i++) { + int idx = rand() % (int)GPR_ARRAY_SIZE(added); + GPR_ASSERT(i); + if (rand() < RAND_MAX / 2) { + added[idx] = i; + printf("avl = gpr_avl_add(avl, box(%d), box(%d), NULL); /* d=%d */\n", + idx, i, deletions); + avl = gpr_avl_add(avl, box(idx), box(i), NULL); + } else { + deletions += (added[idx] != 0); + added[idx] = 0; + printf("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, NULL); +} + +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(10); + + return 0; +} diff --git a/test/core/support/cmdline_test.c b/test/core/support/cmdline_test.c deleted file mode 100644 index 72e7c7f9fc..0000000000 --- a/test/core/support/cmdline_test.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -#define LOG_TEST() gpr_log(GPR_INFO, "test at %s:%d", __FILE__, __LINE__) - -static void test_simple_int(void) { - int x = 1; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "-foo", "3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_int(cl, "foo", NULL, &x); - GPR_ASSERT(x == 1); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 3); - gpr_cmdline_destroy(cl); -} - -static void test_eq_int(void) { - int x = 1; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "-foo=3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_int(cl, "foo", NULL, &x); - GPR_ASSERT(x == 1); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 3); - gpr_cmdline_destroy(cl); -} - -static void test_2dash_int(void) { - int x = 1; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo", "3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_int(cl, "foo", NULL, &x); - GPR_ASSERT(x == 1); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 3); - gpr_cmdline_destroy(cl); -} - -static void test_2dash_eq_int(void) { - int x = 1; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_int(cl, "foo", NULL, &x); - GPR_ASSERT(x == 1); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 3); - gpr_cmdline_destroy(cl); -} - -static void test_simple_string(void) { - char *x = NULL; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "-foo", "3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_string(cl, "foo", NULL, &x); - GPR_ASSERT(x == NULL); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(0 == strcmp(x, "3")); - gpr_cmdline_destroy(cl); -} - -static void test_eq_string(void) { - char *x = NULL; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "-foo=3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_string(cl, "foo", NULL, &x); - GPR_ASSERT(x == NULL); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(0 == strcmp(x, "3")); - gpr_cmdline_destroy(cl); -} - -static void test_2dash_string(void) { - char *x = NULL; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo", "3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_string(cl, "foo", NULL, &x); - GPR_ASSERT(x == NULL); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(0 == strcmp(x, "3")); - gpr_cmdline_destroy(cl); -} - -static void test_2dash_eq_string(void) { - char *x = NULL; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=3"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_string(cl, "foo", NULL, &x); - GPR_ASSERT(x == NULL); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(0 == strcmp(x, "3")); - gpr_cmdline_destroy(cl); -} - -static void test_flag_on(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 1); - gpr_cmdline_destroy(cl); -} - -static void test_flag_no(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--no-foo"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 0); - gpr_cmdline_destroy(cl); -} - -static void test_flag_val_1(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=1"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 1); - gpr_cmdline_destroy(cl); -} - -static void test_flag_val_0(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=0"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 0); - gpr_cmdline_destroy(cl); -} - -static void test_flag_val_true(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=true"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 1); - gpr_cmdline_destroy(cl); -} - -static void test_flag_val_false(void) { - int x = 2; - gpr_cmdline *cl; - char *args[] = {(char *)__FILE__, "--foo=false"}; - - LOG_TEST(); - - cl = gpr_cmdline_create(NULL); - gpr_cmdline_add_flag(cl, "foo", NULL, &x); - GPR_ASSERT(x == 2); - gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 0); - gpr_cmdline_destroy(cl); -} - -static void test_many(void) { - char *str = NULL; - int x = 0; - int flag = 2; - gpr_cmdline *cl; - - char *args[] = {(char *)__FILE__, "--str", "hello", "-x=4", "-no-flag"}; - - 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_parse(cl, GPR_ARRAY_SIZE(args), args); - GPR_ASSERT(x == 4); - GPR_ASSERT(0 == strcmp(str, "hello")); - GPR_ASSERT(flag == 0); - 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; - - char *str = NULL; - 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] [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(); - test_eq_int(); - test_2dash_int(); - test_2dash_eq_int(); - test_simple_string(); - test_eq_string(); - test_2dash_string(); - test_2dash_eq_string(); - test_flag_on(); - test_flag_no(); - test_flag_val_1(); - test_flag_val_0(); - 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/cmdline_test.cc b/test/core/support/cmdline_test.cc new file mode 100644 index 0000000000..a3740d4881 --- /dev/null +++ b/test/core/support/cmdline_test.cc @@ -0,0 +1,492 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +#define LOG_TEST() gpr_log(GPR_INFO, "test at %s:%d", __FILE__, __LINE__) + +static void test_simple_int(void) { + int x = 1; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("-foo"), + const_cast("3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_int(cl, "foo", NULL, &x); + GPR_ASSERT(x == 1); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 3); + gpr_cmdline_destroy(cl); +} + +static void test_eq_int(void) { + int x = 1; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("-foo=3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_int(cl, "foo", NULL, &x); + GPR_ASSERT(x == 1); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 3); + gpr_cmdline_destroy(cl); +} + +static void test_2dash_int(void) { + int x = 1; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo"), + const_cast("3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_int(cl, "foo", NULL, &x); + GPR_ASSERT(x == 1); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 3); + gpr_cmdline_destroy(cl); +} + +static void test_2dash_eq_int(void) { + int x = 1; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_int(cl, "foo", NULL, &x); + GPR_ASSERT(x == 1); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 3); + gpr_cmdline_destroy(cl); +} + +static void test_simple_string(void) { + const char *x = NULL; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("-foo"), + const_cast("3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "foo", NULL, &x); + GPR_ASSERT(x == NULL); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(0 == strcmp(x, "3")); + gpr_cmdline_destroy(cl); +} + +static void test_eq_string(void) { + const char *x = NULL; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("-foo=3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "foo", NULL, &x); + GPR_ASSERT(x == NULL); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(0 == strcmp(x, "3")); + gpr_cmdline_destroy(cl); +} + +static void test_2dash_string(void) { + const char *x = NULL; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo"), + const_cast("3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "foo", NULL, &x); + GPR_ASSERT(x == NULL); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(0 == strcmp(x, "3")); + gpr_cmdline_destroy(cl); +} + +static void test_2dash_eq_string(void) { + const char *x = NULL; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=3")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "foo", NULL, &x); + GPR_ASSERT(x == NULL); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(0 == strcmp(x, "3")); + gpr_cmdline_destroy(cl); +} + +static void test_flag_on(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 1); + gpr_cmdline_destroy(cl); +} + +static void test_flag_no(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--no-foo")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 0); + gpr_cmdline_destroy(cl); +} + +static void test_flag_val_1(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=1")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 1); + gpr_cmdline_destroy(cl); +} + +static void test_flag_val_0(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=0")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 0); + gpr_cmdline_destroy(cl); +} + +static void test_flag_val_true(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=true")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 1); + gpr_cmdline_destroy(cl); +} + +static void test_flag_val_false(void) { + int x = 2; + gpr_cmdline *cl; + char *args[] = {(char *)__FILE__, const_cast("--foo=false")}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_flag(cl, "foo", NULL, &x); + GPR_ASSERT(x == 2); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 0); + gpr_cmdline_destroy(cl); +} + +static void test_many(void) { + const char *str = NULL; + int x = 0; + int flag = 2; + gpr_cmdline *cl; + + char *args[] = {(char *)__FILE__, const_cast("--str"), + const_cast("hello"), const_cast("-x=4"), + const_cast("-no-flag")}; + + 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_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(x == 4); + GPR_ASSERT(0 == strcmp(str, "hello")); + GPR_ASSERT(flag == 0); + gpr_cmdline_destroy(cl); +} + +static void extra_arg_cb(void *user_data, const char *arg) { + int *count = static_cast(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__, const_cast("a"), + const_cast("b"), const_cast("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__, const_cast("--"), + const_cast("a"), const_cast("b"), + const_cast("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; + + const char *str = NULL; + 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] [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; + + const char *str = NULL; + int x = 0; + int flag = 2; + + char *help[] = {(char *)__FILE__, const_cast("-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; + + const char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_arg_name[] = {(char *)__FILE__, const_cast("--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; + + const char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_int_value[] = {(char *)__FILE__, const_cast("--x"), + const_cast("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; + + const char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, + const_cast("--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; + + const char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, const_cast("--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(); + test_eq_int(); + test_2dash_int(); + test_2dash_eq_int(); + test_simple_string(); + test_eq_string(); + test_2dash_string(); + test_2dash_eq_string(); + test_flag_on(); + test_flag_no(); + test_flag_val_1(); + test_flag_val_0(); + 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/cpu_test.c b/test/core/support/cpu_test.c deleted file mode 100644 index 72db53fa49..0000000000 --- a/test/core/support/cpu_test.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test gpr per-cpu support: - gpr_cpu_num_cores() - gpr_cpu_current_cpu() -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -/* Test structure is essentially: - 1) Figure out how many cores are present on the test system - 2) Create 3 times that many threads - 3) Have each thread do some amount of work (basically want to - gaurantee that all threads are running at once, and enough of them - to run on all cores). - 4) Each thread checks what core it is running on, and marks that core - as "used" in the test. - 5) Count number of "used" cores. - - The test will fail if: - 1) gpr_cpu_num_cores() == 0 - 2) Any result from gpr_cpu_current_cpu() >= gpr_cpu_num_cores() - 3) Ideally, we would fail if not all cores were seen as used. Unfortunately, - this is only probabilistically true, and depends on the OS, it's - scheduler, etc. So we just print out an indication of how many were seen; - hopefully developers can use this to sanity check their system. -*/ - -/* Status shared across threads */ -struct cpu_test { - gpr_mu mu; - int nthreads; - uint32_t ncores; - int is_done; - gpr_cv done_cv; - int *used; /* is this core used? */ - unsigned r; /* random number */ -}; - -static void worker_thread(void *arg) { - struct cpu_test *ct = (struct cpu_test *)arg; - uint32_t cpu; - unsigned r = 12345678; - unsigned i, j; - /* Avoid repetitive division calculations */ - int64_t max_i = 1000 / grpc_test_slowdown_factor(); - int64_t max_j = 1000000 / grpc_test_slowdown_factor(); - for (i = 0; i < max_i; i++) { - /* run for a bit - just calculate something random. */ - for (j = 0; j < max_j; j++) { - r = (r * 17) & ((r - i) | (r * i)); - } - cpu = gpr_cpu_current_cpu(); - GPR_ASSERT(cpu < ct->ncores); - gpr_mu_lock(&ct->mu); - ct->used[cpu] = 1; - for (j = 0; j < ct->ncores; j++) { - if (!ct->used[j]) break; - } - gpr_mu_unlock(&ct->mu); - if (j == ct->ncores) { - break; /* all cpus have been used - no further use in running this test */ - } - } - gpr_mu_lock(&ct->mu); - ct->r = r; /* make it look like we care about r's value... */ - ct->nthreads--; - if (ct->nthreads == 0) { - ct->is_done = 1; - gpr_cv_signal(&ct->done_cv); - } - gpr_mu_unlock(&ct->mu); -} - -static void cpu_test(void) { - uint32_t i; - int cores_seen = 0; - struct cpu_test ct; - gpr_thd_id thd; - ct.ncores = gpr_cpu_num_cores(); - GPR_ASSERT(ct.ncores > 0); - ct.nthreads = (int)ct.ncores * 3; - ct.used = gpr_malloc(ct.ncores * sizeof(int)); - memset(ct.used, 0, ct.ncores * sizeof(int)); - gpr_mu_init(&ct.mu); - gpr_cv_init(&ct.done_cv); - ct.is_done = 0; - for (i = 0; i < ct.ncores * 3; i++) { - GPR_ASSERT(gpr_thd_new(&thd, &worker_thread, &ct, NULL)); - } - gpr_mu_lock(&ct.mu); - while (!ct.is_done) { - gpr_cv_wait(&ct.done_cv, &ct.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&ct.mu); - fprintf(stderr, "Saw cores ["); - for (i = 0; i < ct.ncores; i++) { - if (ct.used[i]) { - fprintf(stderr, "%d,", i); - cores_seen++; - } - } - fprintf(stderr, "] (%d/%d)\n", cores_seen, ct.ncores); - gpr_free(ct.used); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - cpu_test(); - return 0; -} diff --git a/test/core/support/cpu_test.cc b/test/core/support/cpu_test.cc new file mode 100644 index 0000000000..7eaf65b110 --- /dev/null +++ b/test/core/support/cpu_test.cc @@ -0,0 +1,135 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test gpr per-cpu support: + gpr_cpu_num_cores() + gpr_cpu_current_cpu() +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* Test structure is essentially: + 1) Figure out how many cores are present on the test system + 2) Create 3 times that many threads + 3) Have each thread do some amount of work (basically want to + gaurantee that all threads are running at once, and enough of them + to run on all cores). + 4) Each thread checks what core it is running on, and marks that core + as "used" in the test. + 5) Count number of "used" cores. + + The test will fail if: + 1) gpr_cpu_num_cores() == 0 + 2) Any result from gpr_cpu_current_cpu() >= gpr_cpu_num_cores() + 3) Ideally, we would fail if not all cores were seen as used. Unfortunately, + this is only probabilistically true, and depends on the OS, it's + scheduler, etc. So we just print out an indication of how many were seen; + hopefully developers can use this to sanity check their system. +*/ + +/* Status shared across threads */ +struct cpu_test { + gpr_mu mu; + int nthreads; + uint32_t ncores; + int is_done; + gpr_cv done_cv; + int *used; /* is this core used? */ + unsigned r; /* random number */ +}; + +static void worker_thread(void *arg) { + struct cpu_test *ct = (struct cpu_test *)arg; + uint32_t cpu; + unsigned r = 12345678; + unsigned i, j; + /* Avoid repetitive division calculations */ + int64_t max_i = 1000 / grpc_test_slowdown_factor(); + int64_t max_j = 1000000 / grpc_test_slowdown_factor(); + for (i = 0; i < max_i; i++) { + /* run for a bit - just calculate something random. */ + for (j = 0; j < max_j; j++) { + r = (r * 17) & ((r - i) | (r * i)); + } + cpu = gpr_cpu_current_cpu(); + GPR_ASSERT(cpu < ct->ncores); + gpr_mu_lock(&ct->mu); + ct->used[cpu] = 1; + for (j = 0; j < ct->ncores; j++) { + if (!ct->used[j]) break; + } + gpr_mu_unlock(&ct->mu); + if (j == ct->ncores) { + break; /* all cpus have been used - no further use in running this test */ + } + } + gpr_mu_lock(&ct->mu); + ct->r = r; /* make it look like we care about r's value... */ + ct->nthreads--; + if (ct->nthreads == 0) { + ct->is_done = 1; + gpr_cv_signal(&ct->done_cv); + } + gpr_mu_unlock(&ct->mu); +} + +static void cpu_test(void) { + uint32_t i; + int cores_seen = 0; + struct cpu_test ct; + gpr_thd_id thd; + ct.ncores = gpr_cpu_num_cores(); + GPR_ASSERT(ct.ncores > 0); + ct.nthreads = (int)ct.ncores * 3; + ct.used = static_cast(gpr_malloc(ct.ncores * sizeof(int))); + memset(ct.used, 0, ct.ncores * sizeof(int)); + gpr_mu_init(&ct.mu); + gpr_cv_init(&ct.done_cv); + ct.is_done = 0; + for (i = 0; i < ct.ncores * 3; i++) { + GPR_ASSERT(gpr_thd_new(&thd, &worker_thread, &ct, NULL)); + } + gpr_mu_lock(&ct.mu); + while (!ct.is_done) { + gpr_cv_wait(&ct.done_cv, &ct.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&ct.mu); + fprintf(stderr, "Saw cores ["); + for (i = 0; i < ct.ncores; i++) { + if (ct.used[i]) { + fprintf(stderr, "%d,", i); + cores_seen++; + } + } + fprintf(stderr, "] (%d/%d)\n", cores_seen, ct.ncores); + gpr_free(ct.used); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + cpu_test(); + return 0; +} diff --git a/test/core/support/env_test.c b/test/core/support/env_test.c deleted file mode 100644 index 661a546720..0000000000 --- a/test/core/support/env_test.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include - -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) - -static void test_setenv_getenv(void) { - const char *name = "FOO"; - const char *value = "BAR"; - char *retrieved_value; - - LOG_TEST_NAME("test_setenv_getenv"); - - gpr_setenv(name, value); - retrieved_value = gpr_getenv(name); - GPR_ASSERT(retrieved_value != NULL); - GPR_ASSERT(strcmp(value, retrieved_value) == 0); - gpr_free(retrieved_value); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_setenv_getenv(); - return 0; -} diff --git a/test/core/support/env_test.cc b/test/core/support/env_test.cc new file mode 100644 index 0000000000..661a546720 --- /dev/null +++ b/test/core/support/env_test.cc @@ -0,0 +1,49 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include + +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) + +static void test_setenv_getenv(void) { + const char *name = "FOO"; + const char *value = "BAR"; + char *retrieved_value; + + LOG_TEST_NAME("test_setenv_getenv"); + + gpr_setenv(name, value); + retrieved_value = gpr_getenv(name); + GPR_ASSERT(retrieved_value != NULL); + GPR_ASSERT(strcmp(value, retrieved_value) == 0); + gpr_free(retrieved_value); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_setenv_getenv(); + return 0; +} diff --git a/test/core/support/histogram_test.c b/test/core/support/histogram_test.c deleted file mode 100644 index 0ee5d5cdd1..0000000000 --- a/test/core/support/histogram_test.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x); - -static void test_no_op(void) { - gpr_histogram_destroy(gpr_histogram_create(0.01, 60e9)); -} - -static void expect_percentile(gpr_histogram *h, double percentile, - double min_expect, double max_expect) { - double got = gpr_histogram_percentile(h, percentile); - gpr_log(GPR_INFO, "@%f%%, expect %f <= %f <= %f", percentile, min_expect, got, - max_expect); - GPR_ASSERT(min_expect <= got); - GPR_ASSERT(got <= max_expect); -} - -static void test_simple(void) { - gpr_histogram *h; - - LOG_TEST("test_simple"); - - h = gpr_histogram_create(0.01, 60e9); - gpr_histogram_add(h, 10000); - gpr_histogram_add(h, 10000); - gpr_histogram_add(h, 11000); - gpr_histogram_add(h, 11000); - - expect_percentile(h, 50, 10001, 10999); - GPR_ASSERT(gpr_histogram_mean(h) == 10500); - - gpr_histogram_destroy(h); -} - -static void test_percentile(void) { - gpr_histogram *h; - double last; - double i; - double cur; - - LOG_TEST("test_percentile"); - - h = gpr_histogram_create(0.05, 1e9); - gpr_histogram_add(h, 2.5); - gpr_histogram_add(h, 2.5); - gpr_histogram_add(h, 8); - gpr_histogram_add(h, 4); - - GPR_ASSERT(gpr_histogram_count(h) == 4); - GPR_ASSERT(gpr_histogram_minimum(h) == 2.5); - GPR_ASSERT(gpr_histogram_maximum(h) == 8); - GPR_ASSERT(gpr_histogram_sum(h) == 17); - GPR_ASSERT(gpr_histogram_sum_of_squares(h) == 92.5); - GPR_ASSERT(gpr_histogram_mean(h) == 4.25); - GPR_ASSERT(gpr_histogram_variance(h) == 5.0625); - GPR_ASSERT(gpr_histogram_stddev(h) == 2.25); - - expect_percentile(h, -10, 2.5, 2.5); - expect_percentile(h, 0, 2.5, 2.5); - expect_percentile(h, 12.5, 2.5, 2.5); - expect_percentile(h, 25, 2.5, 2.5); - expect_percentile(h, 37.5, 2.5, 2.8); - expect_percentile(h, 50, 3.0, 3.5); - expect_percentile(h, 62.5, 3.5, 4.5); - expect_percentile(h, 75, 5, 7.9); - expect_percentile(h, 100, 8, 8); - expect_percentile(h, 110, 8, 8); - - /* test monotonicity */ - last = 0.0; - for (i = 0; i < 100.0; i += 0.01) { - cur = gpr_histogram_percentile(h, i); - GPR_ASSERT(cur >= last); - last = cur; - } - - gpr_histogram_destroy(h); -} - -static void test_merge(void) { - gpr_histogram *h1, *h2; - double last; - double i; - double cur; - - LOG_TEST("test_merge"); - - h1 = gpr_histogram_create(0.05, 1e9); - gpr_histogram_add(h1, 2.5); - gpr_histogram_add(h1, 2.5); - gpr_histogram_add(h1, 8); - gpr_histogram_add(h1, 4); - - h2 = gpr_histogram_create(0.01, 1e9); - GPR_ASSERT(gpr_histogram_merge(h1, h2) == 0); - gpr_histogram_destroy(h2); - - h2 = gpr_histogram_create(0.05, 1e10); - GPR_ASSERT(gpr_histogram_merge(h1, h2) == 0); - gpr_histogram_destroy(h2); - - h2 = gpr_histogram_create(0.05, 1e9); - GPR_ASSERT(gpr_histogram_merge(h1, h2) == 1); - GPR_ASSERT(gpr_histogram_count(h1) == 4); - GPR_ASSERT(gpr_histogram_minimum(h1) == 2.5); - GPR_ASSERT(gpr_histogram_maximum(h1) == 8); - GPR_ASSERT(gpr_histogram_sum(h1) == 17); - GPR_ASSERT(gpr_histogram_sum_of_squares(h1) == 92.5); - GPR_ASSERT(gpr_histogram_mean(h1) == 4.25); - GPR_ASSERT(gpr_histogram_variance(h1) == 5.0625); - GPR_ASSERT(gpr_histogram_stddev(h1) == 2.25); - gpr_histogram_destroy(h2); - - h2 = gpr_histogram_create(0.05, 1e9); - gpr_histogram_add(h2, 7.0); - gpr_histogram_add(h2, 17.0); - gpr_histogram_add(h2, 1.0); - GPR_ASSERT(gpr_histogram_merge(h1, h2) == 1); - GPR_ASSERT(gpr_histogram_count(h1) == 7); - GPR_ASSERT(gpr_histogram_minimum(h1) == 1.0); - GPR_ASSERT(gpr_histogram_maximum(h1) == 17.0); - GPR_ASSERT(gpr_histogram_sum(h1) == 42.0); - GPR_ASSERT(gpr_histogram_sum_of_squares(h1) == 431.5); - GPR_ASSERT(gpr_histogram_mean(h1) == 6.0); - - /* test monotonicity */ - last = 0.0; - for (i = 0; i < 100.0; i += 0.01) { - cur = gpr_histogram_percentile(h1, i); - GPR_ASSERT(cur >= last); - last = cur; - } - - gpr_histogram_destroy(h1); - gpr_histogram_destroy(h2); -} - -int main(void) { - test_no_op(); - test_simple(); - test_percentile(); - test_merge(); - return 0; -} diff --git a/test/core/support/histogram_test.cc b/test/core/support/histogram_test.cc new file mode 100644 index 0000000000..0ee5d5cdd1 --- /dev/null +++ b/test/core/support/histogram_test.cc @@ -0,0 +1,163 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x); + +static void test_no_op(void) { + gpr_histogram_destroy(gpr_histogram_create(0.01, 60e9)); +} + +static void expect_percentile(gpr_histogram *h, double percentile, + double min_expect, double max_expect) { + double got = gpr_histogram_percentile(h, percentile); + gpr_log(GPR_INFO, "@%f%%, expect %f <= %f <= %f", percentile, min_expect, got, + max_expect); + GPR_ASSERT(min_expect <= got); + GPR_ASSERT(got <= max_expect); +} + +static void test_simple(void) { + gpr_histogram *h; + + LOG_TEST("test_simple"); + + h = gpr_histogram_create(0.01, 60e9); + gpr_histogram_add(h, 10000); + gpr_histogram_add(h, 10000); + gpr_histogram_add(h, 11000); + gpr_histogram_add(h, 11000); + + expect_percentile(h, 50, 10001, 10999); + GPR_ASSERT(gpr_histogram_mean(h) == 10500); + + gpr_histogram_destroy(h); +} + +static void test_percentile(void) { + gpr_histogram *h; + double last; + double i; + double cur; + + LOG_TEST("test_percentile"); + + h = gpr_histogram_create(0.05, 1e9); + gpr_histogram_add(h, 2.5); + gpr_histogram_add(h, 2.5); + gpr_histogram_add(h, 8); + gpr_histogram_add(h, 4); + + GPR_ASSERT(gpr_histogram_count(h) == 4); + GPR_ASSERT(gpr_histogram_minimum(h) == 2.5); + GPR_ASSERT(gpr_histogram_maximum(h) == 8); + GPR_ASSERT(gpr_histogram_sum(h) == 17); + GPR_ASSERT(gpr_histogram_sum_of_squares(h) == 92.5); + GPR_ASSERT(gpr_histogram_mean(h) == 4.25); + GPR_ASSERT(gpr_histogram_variance(h) == 5.0625); + GPR_ASSERT(gpr_histogram_stddev(h) == 2.25); + + expect_percentile(h, -10, 2.5, 2.5); + expect_percentile(h, 0, 2.5, 2.5); + expect_percentile(h, 12.5, 2.5, 2.5); + expect_percentile(h, 25, 2.5, 2.5); + expect_percentile(h, 37.5, 2.5, 2.8); + expect_percentile(h, 50, 3.0, 3.5); + expect_percentile(h, 62.5, 3.5, 4.5); + expect_percentile(h, 75, 5, 7.9); + expect_percentile(h, 100, 8, 8); + expect_percentile(h, 110, 8, 8); + + /* test monotonicity */ + last = 0.0; + for (i = 0; i < 100.0; i += 0.01) { + cur = gpr_histogram_percentile(h, i); + GPR_ASSERT(cur >= last); + last = cur; + } + + gpr_histogram_destroy(h); +} + +static void test_merge(void) { + gpr_histogram *h1, *h2; + double last; + double i; + double cur; + + LOG_TEST("test_merge"); + + h1 = gpr_histogram_create(0.05, 1e9); + gpr_histogram_add(h1, 2.5); + gpr_histogram_add(h1, 2.5); + gpr_histogram_add(h1, 8); + gpr_histogram_add(h1, 4); + + h2 = gpr_histogram_create(0.01, 1e9); + GPR_ASSERT(gpr_histogram_merge(h1, h2) == 0); + gpr_histogram_destroy(h2); + + h2 = gpr_histogram_create(0.05, 1e10); + GPR_ASSERT(gpr_histogram_merge(h1, h2) == 0); + gpr_histogram_destroy(h2); + + h2 = gpr_histogram_create(0.05, 1e9); + GPR_ASSERT(gpr_histogram_merge(h1, h2) == 1); + GPR_ASSERT(gpr_histogram_count(h1) == 4); + GPR_ASSERT(gpr_histogram_minimum(h1) == 2.5); + GPR_ASSERT(gpr_histogram_maximum(h1) == 8); + GPR_ASSERT(gpr_histogram_sum(h1) == 17); + GPR_ASSERT(gpr_histogram_sum_of_squares(h1) == 92.5); + GPR_ASSERT(gpr_histogram_mean(h1) == 4.25); + GPR_ASSERT(gpr_histogram_variance(h1) == 5.0625); + GPR_ASSERT(gpr_histogram_stddev(h1) == 2.25); + gpr_histogram_destroy(h2); + + h2 = gpr_histogram_create(0.05, 1e9); + gpr_histogram_add(h2, 7.0); + gpr_histogram_add(h2, 17.0); + gpr_histogram_add(h2, 1.0); + GPR_ASSERT(gpr_histogram_merge(h1, h2) == 1); + GPR_ASSERT(gpr_histogram_count(h1) == 7); + GPR_ASSERT(gpr_histogram_minimum(h1) == 1.0); + GPR_ASSERT(gpr_histogram_maximum(h1) == 17.0); + GPR_ASSERT(gpr_histogram_sum(h1) == 42.0); + GPR_ASSERT(gpr_histogram_sum_of_squares(h1) == 431.5); + GPR_ASSERT(gpr_histogram_mean(h1) == 6.0); + + /* test monotonicity */ + last = 0.0; + for (i = 0; i < 100.0; i += 0.01) { + cur = gpr_histogram_percentile(h1, i); + GPR_ASSERT(cur >= last); + last = cur; + } + + gpr_histogram_destroy(h1); + gpr_histogram_destroy(h2); +} + +int main(void) { + test_no_op(); + test_simple(); + test_percentile(); + test_merge(); + return 0; +} diff --git a/test/core/support/host_port_test.c b/test/core/support/host_port_test.c deleted file mode 100644 index 2ff3bcf68e..0000000000 --- a/test/core/support/host_port_test.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -static void join_host_port_expect(const char *host, int port, - const char *expected) { - char *buf; - int len; - len = gpr_join_host_port(&buf, host, port); - GPR_ASSERT(len >= 0); - GPR_ASSERT(strlen(expected) == (size_t)len); - GPR_ASSERT(strcmp(expected, buf) == 0); - gpr_free(buf); -} - -static void test_join_host_port(void) { - join_host_port_expect("foo", 101, "foo:101"); - join_host_port_expect("", 102, ":102"); - join_host_port_expect("1::2", 103, "[1::2]:103"); - join_host_port_expect("[::1]", 104, "[::1]:104"); -} - -/* Garbage in, garbage out. */ -static void test_join_host_port_garbage(void) { - join_host_port_expect("[foo]", 105, "[foo]:105"); - join_host_port_expect("[::", 106, "[:::106"); - join_host_port_expect("::]", 107, "[::]]:107"); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - test_join_host_port(); - test_join_host_port_garbage(); - - return 0; -} diff --git a/test/core/support/host_port_test.cc b/test/core/support/host_port_test.cc new file mode 100644 index 0000000000..2ff3bcf68e --- /dev/null +++ b/test/core/support/host_port_test.cc @@ -0,0 +1,58 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +static void join_host_port_expect(const char *host, int port, + const char *expected) { + char *buf; + int len; + len = gpr_join_host_port(&buf, host, port); + GPR_ASSERT(len >= 0); + GPR_ASSERT(strlen(expected) == (size_t)len); + GPR_ASSERT(strcmp(expected, buf) == 0); + gpr_free(buf); +} + +static void test_join_host_port(void) { + join_host_port_expect("foo", 101, "foo:101"); + join_host_port_expect("", 102, ":102"); + join_host_port_expect("1::2", 103, "[1::2]:103"); + join_host_port_expect("[::1]", 104, "[::1]:104"); +} + +/* Garbage in, garbage out. */ +static void test_join_host_port_garbage(void) { + join_host_port_expect("[foo]", 105, "[foo]:105"); + join_host_port_expect("[::", 106, "[:::106"); + join_host_port_expect("::]", 107, "[::]]:107"); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + test_join_host_port(); + test_join_host_port_garbage(); + + return 0; +} diff --git a/test/core/support/log_test.c b/test/core/support/log_test.c deleted file mode 100644 index c221ff6783..0000000000 --- a/test/core/support/log_test.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include "src/core/lib/support/env.h" -#include "test/core/util/test_config.h" - -static bool log_func_reached = false; - -static void test_callback(gpr_log_func_args *args) { - GPR_ASSERT(0 == strcmp(__FILE__, args->file)); - GPR_ASSERT(args->severity == GPR_LOG_SEVERITY_INFO); - GPR_ASSERT(0 == strcmp(args->message, "hello 1 2 3")); -} - -static void test_should_log(gpr_log_func_args *args) { - log_func_reached = true; -} - -static void test_should_not_log(gpr_log_func_args *args) { GPR_ASSERT(false); } - -#define test_log_function_reached(SEVERITY) \ - gpr_set_log_function(test_should_log); \ - log_func_reached = false; \ - gpr_log_message(SEVERITY, "hello 1 2 3"); \ - GPR_ASSERT(log_func_reached); \ - log_func_reached = false; \ - gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); \ - GPR_ASSERT(log_func_reached); - -#define test_log_function_unreached(SEVERITY) \ - gpr_set_log_function(test_should_not_log); \ - gpr_log_message(SEVERITY, "hello 1 2 3"); \ - gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - /* test logging at various verbosity levels */ - gpr_log(GPR_DEBUG, "%s", "hello world"); - gpr_log(GPR_INFO, "%s", "hello world"); - gpr_log(GPR_ERROR, "%s", "hello world"); - /* should succeed */ - GPR_ASSERT(1); - gpr_set_log_function(test_callback); - gpr_log_message(GPR_INFO, "hello 1 2 3"); - gpr_log(GPR_INFO, "hello %d %d %d", 1, 2, 3); - gpr_set_log_function(NULL); - - /* gpr_log_verbosity_init() will be effective only once, and only before - * gpr_set_log_verbosity() is called */ - gpr_setenv("GRPC_VERBOSITY", "ERROR"); - gpr_log_verbosity_init(); - - test_log_function_reached(GPR_ERROR); - test_log_function_unreached(GPR_INFO); - test_log_function_unreached(GPR_DEBUG); - - /* gpr_log_verbosity_init() should not be effective */ - gpr_setenv("GRPC_VERBOSITY", "DEBUG"); - gpr_log_verbosity_init(); - test_log_function_reached(GPR_ERROR); - test_log_function_unreached(GPR_INFO); - test_log_function_unreached(GPR_DEBUG); - - gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); - test_log_function_reached(GPR_ERROR); - test_log_function_reached(GPR_INFO); - test_log_function_reached(GPR_DEBUG); - - gpr_set_log_verbosity(GPR_LOG_SEVERITY_INFO); - test_log_function_reached(GPR_ERROR); - test_log_function_reached(GPR_INFO); - test_log_function_unreached(GPR_DEBUG); - - gpr_set_log_verbosity(GPR_LOG_SEVERITY_ERROR); - test_log_function_reached(GPR_ERROR); - test_log_function_unreached(GPR_INFO); - test_log_function_unreached(GPR_DEBUG); - - /* gpr_log_verbosity_init() should not be effective */ - gpr_setenv("GRPC_VERBOSITY", "DEBUG"); - gpr_log_verbosity_init(); - test_log_function_reached(GPR_ERROR); - test_log_function_unreached(GPR_INFO); - test_log_function_unreached(GPR_DEBUG); - - /* TODO(ctiller): should we add a GPR_ASSERT failure test here */ - return 0; -} diff --git a/test/core/support/log_test.cc b/test/core/support/log_test.cc new file mode 100644 index 0000000000..c221ff6783 --- /dev/null +++ b/test/core/support/log_test.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/lib/support/env.h" +#include "test/core/util/test_config.h" + +static bool log_func_reached = false; + +static void test_callback(gpr_log_func_args *args) { + GPR_ASSERT(0 == strcmp(__FILE__, args->file)); + GPR_ASSERT(args->severity == GPR_LOG_SEVERITY_INFO); + GPR_ASSERT(0 == strcmp(args->message, "hello 1 2 3")); +} + +static void test_should_log(gpr_log_func_args *args) { + log_func_reached = true; +} + +static void test_should_not_log(gpr_log_func_args *args) { GPR_ASSERT(false); } + +#define test_log_function_reached(SEVERITY) \ + gpr_set_log_function(test_should_log); \ + log_func_reached = false; \ + gpr_log_message(SEVERITY, "hello 1 2 3"); \ + GPR_ASSERT(log_func_reached); \ + log_func_reached = false; \ + gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); \ + GPR_ASSERT(log_func_reached); + +#define test_log_function_unreached(SEVERITY) \ + gpr_set_log_function(test_should_not_log); \ + gpr_log_message(SEVERITY, "hello 1 2 3"); \ + gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + /* test logging at various verbosity levels */ + gpr_log(GPR_DEBUG, "%s", "hello world"); + gpr_log(GPR_INFO, "%s", "hello world"); + gpr_log(GPR_ERROR, "%s", "hello world"); + /* should succeed */ + GPR_ASSERT(1); + gpr_set_log_function(test_callback); + gpr_log_message(GPR_INFO, "hello 1 2 3"); + gpr_log(GPR_INFO, "hello %d %d %d", 1, 2, 3); + gpr_set_log_function(NULL); + + /* gpr_log_verbosity_init() will be effective only once, and only before + * gpr_set_log_verbosity() is called */ + gpr_setenv("GRPC_VERBOSITY", "ERROR"); + gpr_log_verbosity_init(); + + test_log_function_reached(GPR_ERROR); + test_log_function_unreached(GPR_INFO); + test_log_function_unreached(GPR_DEBUG); + + /* gpr_log_verbosity_init() should not be effective */ + gpr_setenv("GRPC_VERBOSITY", "DEBUG"); + gpr_log_verbosity_init(); + test_log_function_reached(GPR_ERROR); + test_log_function_unreached(GPR_INFO); + test_log_function_unreached(GPR_DEBUG); + + gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); + test_log_function_reached(GPR_ERROR); + test_log_function_reached(GPR_INFO); + test_log_function_reached(GPR_DEBUG); + + gpr_set_log_verbosity(GPR_LOG_SEVERITY_INFO); + test_log_function_reached(GPR_ERROR); + test_log_function_reached(GPR_INFO); + test_log_function_unreached(GPR_DEBUG); + + gpr_set_log_verbosity(GPR_LOG_SEVERITY_ERROR); + test_log_function_reached(GPR_ERROR); + test_log_function_unreached(GPR_INFO); + test_log_function_unreached(GPR_DEBUG); + + /* gpr_log_verbosity_init() should not be effective */ + gpr_setenv("GRPC_VERBOSITY", "DEBUG"); + gpr_log_verbosity_init(); + test_log_function_reached(GPR_ERROR); + test_log_function_unreached(GPR_INFO); + test_log_function_unreached(GPR_DEBUG); + + /* TODO(ctiller): should we add a GPR_ASSERT failure test here */ + return 0; +} diff --git a/test/core/support/mpscq_test.c b/test/core/support/mpscq_test.c deleted file mode 100644 index 5e7dc9fca5..0000000000 --- a/test/core/support/mpscq_test.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/support/mpscq.h" - -#include - -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -typedef struct test_node { - gpr_mpscq_node node; - size_t i; - size_t *ctr; -} test_node; - -static test_node *new_node(size_t i, size_t *ctr) { - test_node *n = gpr_malloc(sizeof(test_node)); - n->i = i; - n->ctr = ctr; - return n; -} - -static void test_serial(void) { - gpr_log(GPR_DEBUG, "test_serial"); - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < 10000000; i++) { - gpr_mpscq_push(&q, &new_node(i, NULL)->node); - } - for (size_t i = 0; i < 10000000; i++) { - test_node *n = (test_node *)gpr_mpscq_pop(&q); - GPR_ASSERT(n); - GPR_ASSERT(n->i == i); - gpr_free(n); - } -} - -typedef struct { - size_t ctr; - gpr_mpscq *q; - gpr_event *start; -} thd_args; - -#define THREAD_ITERATIONS 10000 - -static void test_thread(void *args) { - thd_args *a = args; - gpr_event_wait(a->start, gpr_inf_future(GPR_CLOCK_REALTIME)); - for (size_t i = 1; i <= THREAD_ITERATIONS; i++) { - gpr_mpscq_push(a->q, &new_node(i, &a->ctr)->node); - } -} - -static void test_mt(void) { - gpr_log(GPR_DEBUG, "test_mt"); - gpr_event start; - gpr_event_init(&start); - gpr_thd_id thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].q = &q; - ta[i].start = &start; - GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); - } - size_t num_done = 0; - size_t spins = 0; - gpr_event_set(&start, (void *)1); - while (num_done != GPR_ARRAY_SIZE(thds)) { - gpr_mpscq_node *n; - while ((n = gpr_mpscq_pop(&q)) == NULL) { - spins++; - } - test_node *tn = (test_node *)n; - GPR_ASSERT(*tn->ctr == tn->i - 1); - *tn->ctr = tn->i; - if (tn->i == THREAD_ITERATIONS) num_done++; - gpr_free(tn); - } - gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - gpr_mpscq_destroy(&q); -} - -typedef struct { - thd_args *ta; - size_t num_thds; - gpr_mu mu; - size_t num_done; - size_t spins; - gpr_mpscq *q; - gpr_event *start; -} pull_args; - -static void pull_thread(void *arg) { - pull_args *pa = arg; - gpr_event_wait(pa->start, gpr_inf_future(GPR_CLOCK_REALTIME)); - - for (;;) { - gpr_mu_lock(&pa->mu); - if (pa->num_done == pa->num_thds) { - gpr_mu_unlock(&pa->mu); - return; - } - gpr_mpscq_node *n; - while ((n = gpr_mpscq_pop(pa->q)) == NULL) { - pa->spins++; - } - test_node *tn = (test_node *)n; - GPR_ASSERT(*tn->ctr == tn->i - 1); - *tn->ctr = tn->i; - if (tn->i == THREAD_ITERATIONS) pa->num_done++; - gpr_free(tn); - gpr_mu_unlock(&pa->mu); - } -} - -static void test_mt_multipop(void) { - gpr_log(GPR_DEBUG, "test_mt_multipop"); - gpr_event start; - gpr_event_init(&start); - gpr_thd_id thds[100]; - gpr_thd_id pull_thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].q = &q; - ta[i].start = &start; - GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); - } - pull_args pa; - pa.ta = ta; - pa.num_thds = GPR_ARRAY_SIZE(thds); - pa.spins = 0; - pa.num_done = 0; - pa.q = &q; - pa.start = &start; - gpr_mu_init(&pa.mu); - for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); - } - gpr_event_set(&start, (void *)1); - for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { - gpr_thd_join(pull_thds[i]); - } - gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - gpr_mpscq_destroy(&q); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_serial(); - test_mt(); - test_mt_multipop(); - return 0; -} diff --git a/test/core/support/mpscq_test.cc b/test/core/support/mpscq_test.cc new file mode 100644 index 0000000000..a4fa6a3e34 --- /dev/null +++ b/test/core/support/mpscq_test.cc @@ -0,0 +1,191 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/mpscq.h" + +#include + +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +typedef struct test_node { + gpr_mpscq_node node; + size_t i; + size_t *ctr; +} test_node; + +static test_node *new_node(size_t i, size_t *ctr) { + test_node *n = static_cast(gpr_malloc(sizeof(test_node))); + n->i = i; + n->ctr = ctr; + return n; +} + +static void test_serial(void) { + gpr_log(GPR_DEBUG, "test_serial"); + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < 10000000; i++) { + gpr_mpscq_push(&q, &new_node(i, NULL)->node); + } + for (size_t i = 0; i < 10000000; i++) { + test_node *n = (test_node *)gpr_mpscq_pop(&q); + GPR_ASSERT(n); + GPR_ASSERT(n->i == i); + gpr_free(n); + } +} + +typedef struct { + size_t ctr; + gpr_mpscq *q; + gpr_event *start; +} thd_args; + +#define THREAD_ITERATIONS 10000 + +static void test_thread(void *args) { + thd_args *a = static_cast(args); + gpr_event_wait(a->start, gpr_inf_future(GPR_CLOCK_REALTIME)); + for (size_t i = 1; i <= THREAD_ITERATIONS; i++) { + gpr_mpscq_push(a->q, &new_node(i, &a->ctr)->node); + } +} + +static void test_mt(void) { + gpr_log(GPR_DEBUG, "test_mt"); + gpr_event start; + gpr_event_init(&start); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].q = &q; + ta[i].start = &start; + GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); + } + size_t num_done = 0; + size_t spins = 0; + gpr_event_set(&start, (void *)1); + while (num_done != GPR_ARRAY_SIZE(thds)) { + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(&q)) == NULL) { + spins++; + } + test_node *tn = (test_node *)n; + GPR_ASSERT(*tn->ctr == tn->i - 1); + *tn->ctr = tn->i; + if (tn->i == THREAD_ITERATIONS) num_done++; + gpr_free(tn); + } + gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + gpr_mpscq_destroy(&q); +} + +typedef struct { + thd_args *ta; + size_t num_thds; + gpr_mu mu; + size_t num_done; + size_t spins; + gpr_mpscq *q; + gpr_event *start; +} pull_args; + +static void pull_thread(void *arg) { + pull_args *pa = static_cast(arg); + gpr_event_wait(pa->start, gpr_inf_future(GPR_CLOCK_REALTIME)); + + for (;;) { + gpr_mu_lock(&pa->mu); + if (pa->num_done == pa->num_thds) { + gpr_mu_unlock(&pa->mu); + return; + } + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(pa->q)) == NULL) { + pa->spins++; + } + test_node *tn = (test_node *)n; + GPR_ASSERT(*tn->ctr == tn->i - 1); + *tn->ctr = tn->i; + if (tn->i == THREAD_ITERATIONS) pa->num_done++; + gpr_free(tn); + gpr_mu_unlock(&pa->mu); + } +} + +static void test_mt_multipop(void) { + gpr_log(GPR_DEBUG, "test_mt_multipop"); + gpr_event start; + gpr_event_init(&start); + gpr_thd_id thds[100]; + gpr_thd_id pull_thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].q = &q; + ta[i].start = &start; + GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); + } + pull_args pa; + pa.ta = ta; + pa.num_thds = GPR_ARRAY_SIZE(thds); + pa.spins = 0; + pa.num_done = 0; + pa.q = &q; + pa.start = &start; + gpr_mu_init(&pa.mu); + for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); + } + gpr_event_set(&start, (void *)1); + for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { + gpr_thd_join(pull_thds[i]); + } + gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + gpr_mpscq_destroy(&q); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_serial(); + test_mt(); + test_mt_multipop(); + return 0; +} diff --git a/test/core/support/murmur_hash_test.c b/test/core/support/murmur_hash_test.c deleted file mode 100644 index 5677515d04..0000000000 --- a/test/core/support/murmur_hash_test.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/support/murmur_hash.h" -#include -#include -#include "test/core/util/test_config.h" - -#include - -typedef uint32_t (*hash_func)(const void *key, size_t len, uint32_t seed); - -/* From smhasher: - This should hopefully be a thorough and uambiguous test of whether a hash - is correctly implemented on a given platform */ - -static void verification_test(hash_func hash, uint32_t expected) { - uint8_t key[256]; - uint32_t hashes[256]; - uint32_t final = 0; - size_t i; - - memset(key, 0, sizeof(key)); - memset(hashes, 0, sizeof(hashes)); - - /* Hash keys of the form {0}, {0,1}, {0,1,2}... up to N=255,using 256-N as - the seed */ - - for (i = 0; i < 256; i++) { - key[i] = (uint8_t)i; - hashes[i] = hash(key, i, (uint32_t)(256u - i)); - } - - /* Then hash the result array */ - - final = hash(hashes, sizeof(hashes), 0); - - /* The first four bytes of that hash, interpreted as a little-endian integer, - is our - verification value */ - - if (expected != final) { - gpr_log(GPR_INFO, "Verification value 0x%08X : Failed! (Expected 0x%08x)", - final, expected); - abort(); - } else { - gpr_log(GPR_INFO, "Verification value 0x%08X : Passed!", final); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - /* basic tests to verify that things don't crash */ - gpr_murmur_hash3("", 0, 0); - gpr_murmur_hash3("xyz", 3, 0); - verification_test(gpr_murmur_hash3, 0xB0F57EE3); - return 0; -} diff --git a/test/core/support/murmur_hash_test.cc b/test/core/support/murmur_hash_test.cc new file mode 100644 index 0000000000..5677515d04 --- /dev/null +++ b/test/core/support/murmur_hash_test.cc @@ -0,0 +1,73 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/murmur_hash.h" +#include +#include +#include "test/core/util/test_config.h" + +#include + +typedef uint32_t (*hash_func)(const void *key, size_t len, uint32_t seed); + +/* From smhasher: + This should hopefully be a thorough and uambiguous test of whether a hash + is correctly implemented on a given platform */ + +static void verification_test(hash_func hash, uint32_t expected) { + uint8_t key[256]; + uint32_t hashes[256]; + uint32_t final = 0; + size_t i; + + memset(key, 0, sizeof(key)); + memset(hashes, 0, sizeof(hashes)); + + /* Hash keys of the form {0}, {0,1}, {0,1,2}... up to N=255,using 256-N as + the seed */ + + for (i = 0; i < 256; i++) { + key[i] = (uint8_t)i; + hashes[i] = hash(key, i, (uint32_t)(256u - i)); + } + + /* Then hash the result array */ + + final = hash(hashes, sizeof(hashes), 0); + + /* The first four bytes of that hash, interpreted as a little-endian integer, + is our + verification value */ + + if (expected != final) { + gpr_log(GPR_INFO, "Verification value 0x%08X : Failed! (Expected 0x%08x)", + final, expected); + abort(); + } else { + gpr_log(GPR_INFO, "Verification value 0x%08X : Passed!", final); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + /* basic tests to verify that things don't crash */ + gpr_murmur_hash3("", 0, 0); + gpr_murmur_hash3("xyz", 3, 0); + verification_test(gpr_murmur_hash3, 0xB0F57EE3); + return 0; +} diff --git a/test/core/support/spinlock_test.c b/test/core/support/spinlock_test.c deleted file mode 100644 index b236a88ab7..0000000000 --- a/test/core/support/spinlock_test.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test of gpr synchronization support. */ - -#include "src/core/lib/support/spinlock.h" -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -/* ------------------------------------------------- */ -/* Tests for gpr_spinlock. */ -struct test { - int thread_count; /* number of threads */ - gpr_thd_id *threads; - - int64_t iterations; /* number of iterations per thread */ - int64_t counter; - int incr_step; /* how much to increment/decrement refcount each time */ - - gpr_spinlock mu; /* protects iterations, counter */ -}; - -/* Return pointer to a new struct test. */ -static struct test *test_new(int threads, int64_t iterations, int incr_step) { - struct test *m = gpr_malloc(sizeof(*m)); - m->thread_count = threads; - m->threads = gpr_malloc(sizeof(*m->threads) * (size_t)threads); - m->iterations = iterations; - m->counter = 0; - m->thread_count = 0; - m->incr_step = incr_step; - m->mu = GPR_SPINLOCK_INITIALIZER; - return m; -} - -/* Return pointer to a new struct test. */ -static void test_destroy(struct test *m) { - gpr_free(m->threads); - gpr_free(m); -} - -/* Create m->threads threads, each running (*body)(m) */ -static void test_create_threads(struct test *m, void (*body)(void *arg)) { - int i; - for (i = 0; i != m->thread_count; i++) { - gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&opt); - GPR_ASSERT(gpr_thd_new(&m->threads[i], body, m, &opt)); - } -} - -/* Wait until all threads report done. */ -static void test_wait(struct test *m) { - int i; - for (i = 0; i != m->thread_count; i++) { - gpr_thd_join(m->threads[i]); - } -} - -/* 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. - 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), int timeout_s, - int incr_step) { - int64_t iterations = 1024; - struct test *m; - gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); - gpr_timespec time_taken; - gpr_timespec deadline = gpr_time_add( - start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); - fprintf(stderr, "%s:", name); - while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { - if (iterations < INT64_MAX / 2) iterations <<= 1; - fprintf(stderr, " %ld", (long)iterations); - m = test_new(10, iterations, incr_step); - test_create_threads(m, body); - test_wait(m); - if (m->counter != m->thread_count * m->iterations * m->incr_step) { - fprintf(stderr, "counter %ld threads %d iterations %ld\n", - (long)m->counter, m->thread_count, (long)m->iterations); - GPR_ASSERT(0); - } - test_destroy(m); - } - time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); - fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, - (int)time_taken.tv_nsec); -} - -/* Increment m->counter on each iteration; then mark thread as done. */ -static void inc(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations; i++) { - gpr_spinlock_lock(&m->mu); - m->counter++; - gpr_spinlock_unlock(&m->mu); - } -} - -/* Increment m->counter under lock acquired with trylock, m->iterations times; - then mark thread as done. */ -static void inctry(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations;) { - if (gpr_spinlock_trylock(&m->mu)) { - m->counter++; - gpr_spinlock_unlock(&m->mu); - i++; - } - } -} - -/* ------------------------------------------------- */ - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - test("spinlock", &inc, 1, 1); - test("spinlock try", &inctry, 1, 1); - return 0; -} diff --git a/test/core/support/spinlock_test.cc b/test/core/support/spinlock_test.cc new file mode 100644 index 0000000000..8c8c8cedfa --- /dev/null +++ b/test/core/support/spinlock_test.cc @@ -0,0 +1,147 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test of gpr synchronization support. */ + +#include "src/core/lib/support/spinlock.h" +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* ------------------------------------------------- */ +/* Tests for gpr_spinlock. */ +struct test { + int thread_count; /* number of threads */ + gpr_thd_id *threads; + + int64_t iterations; /* number of iterations per thread */ + int64_t counter; + int incr_step; /* how much to increment/decrement refcount each time */ + + gpr_spinlock mu; /* protects iterations, counter */ +}; + +/* Return pointer to a new struct test. */ +static struct test *test_new(int threads, int64_t iterations, int incr_step) { + struct test *m = static_cast(gpr_malloc(sizeof(*m))); + m->thread_count = threads; + m->threads = static_cast( + gpr_malloc(sizeof(*m->threads) * (size_t)threads)); + m->iterations = iterations; + m->counter = 0; + m->thread_count = 0; + m->incr_step = incr_step; + m->mu = GPR_SPINLOCK_INITIALIZER; + return m; +} + +/* Return pointer to a new struct test. */ +static void test_destroy(struct test *m) { + gpr_free(m->threads); + gpr_free(m); +} + +/* Create m->threads threads, each running (*body)(m) */ +static void test_create_threads(struct test *m, void (*body)(void *arg)) { + int i; + for (i = 0; i != m->thread_count; i++) { + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + GPR_ASSERT(gpr_thd_new(&m->threads[i], body, m, &opt)); + } +} + +/* Wait until all threads report done. */ +static void test_wait(struct test *m) { + int i; + for (i = 0; i != m->thread_count; i++) { + gpr_thd_join(m->threads[i]); + } +} + +/* 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. + 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), int timeout_s, + int incr_step) { + int64_t iterations = 1024; + struct test *m; + gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); + gpr_timespec time_taken; + gpr_timespec deadline = gpr_time_add( + start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); + fprintf(stderr, "%s:", name); + while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { + if (iterations < INT64_MAX / 2) iterations <<= 1; + fprintf(stderr, " %ld", (long)iterations); + m = test_new(10, iterations, incr_step); + test_create_threads(m, body); + test_wait(m); + if (m->counter != m->thread_count * m->iterations * m->incr_step) { + fprintf(stderr, "counter %ld threads %d iterations %ld\n", + (long)m->counter, m->thread_count, (long)m->iterations); + GPR_ASSERT(0); + } + test_destroy(m); + } + time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); + fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, + (int)time_taken.tv_nsec); +} + +/* Increment m->counter on each iteration; then mark thread as done. */ +static void inc(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + gpr_spinlock_lock(&m->mu); + m->counter++; + gpr_spinlock_unlock(&m->mu); + } +} + +/* Increment m->counter under lock acquired with trylock, m->iterations times; + then mark thread as done. */ +static void inctry(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations;) { + if (gpr_spinlock_trylock(&m->mu)) { + m->counter++; + gpr_spinlock_unlock(&m->mu); + i++; + } + } +} + +/* ------------------------------------------------- */ + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + test("spinlock", &inc, 1, 1); + test("spinlock try", &inctry, 1, 1); + return 0; +} diff --git a/test/core/support/stack_lockfree_test.c b/test/core/support/stack_lockfree_test.c deleted file mode 100644 index 4b1f60ce01..0000000000 --- a/test/core/support/stack_lockfree_test.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/support/stack_lockfree.h" - -#include - -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -/* max stack size supported */ -#define MAX_STACK_SIZE 65534 - -#define MAX_THREADS 32 - -static void test_serial_sized(size_t size) { - gpr_stack_lockfree *stack = gpr_stack_lockfree_create(size); - size_t i; - size_t j; - - /* First try popping empty */ - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); - - /* Now add one item and check it */ - gpr_stack_lockfree_push(stack, 3); - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == 3); - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); - - /* Now add repeatedly more items and check them */ - for (i = 1; i < size; i *= 2) { - for (j = 0; j <= i; j++) { - GPR_ASSERT(gpr_stack_lockfree_push(stack, (int)j) == (j == 0)); - } - for (j = 0; j <= i; j++) { - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == (int)(i - j)); - } - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); - } - - gpr_stack_lockfree_destroy(stack); -} - -static void test_serial() { - size_t i; - for (i = 128; i < MAX_STACK_SIZE; i *= 2) { - test_serial_sized(i); - } - test_serial_sized(MAX_STACK_SIZE); -} - -struct test_arg { - gpr_stack_lockfree *stack; - int stack_size; - int nthreads; - int rank; - int sum; -}; - -static void test_mt_body(void *v) { - struct test_arg *arg = (struct test_arg *)v; - int lo, hi; - int i; - int res; - lo = arg->rank * arg->stack_size / arg->nthreads; - hi = (arg->rank + 1) * arg->stack_size / arg->nthreads; - for (i = lo; i < hi; i++) { - gpr_stack_lockfree_push(arg->stack, i); - if ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { - arg->sum += res; - } - } - while ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { - arg->sum += res; - } -} - -static void test_mt_sized(size_t size, int nth) { - gpr_stack_lockfree *stack; - struct test_arg args[MAX_THREADS]; - gpr_thd_id thds[MAX_THREADS]; - int sum; - int i; - gpr_thd_options options = gpr_thd_options_default(); - - stack = gpr_stack_lockfree_create(size); - for (i = 0; i < nth; i++) { - args[i].stack = stack; - args[i].stack_size = (int)size; - args[i].nthreads = nth; - args[i].rank = i; - args[i].sum = 0; - } - gpr_thd_options_set_joinable(&options); - for (i = 0; i < nth; i++) { - GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options)); - } - sum = 0; - for (i = 0; i < nth; i++) { - gpr_thd_join(thds[i]); - sum = sum + args[i].sum; - } - GPR_ASSERT((unsigned)sum == ((unsigned)size * (size - 1)) / 2); - gpr_stack_lockfree_destroy(stack); -} - -static void test_mt() { - size_t size; - int nth; - for (nth = 1; nth < MAX_THREADS; nth++) { - for (size = 128; size < MAX_STACK_SIZE; size *= 2) { - test_mt_sized(size, nth); - } - test_mt_sized(MAX_STACK_SIZE, nth); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_serial(); - test_mt(); - return 0; -} diff --git a/test/core/support/stack_lockfree_test.cc b/test/core/support/stack_lockfree_test.cc new file mode 100644 index 0000000000..4b1f60ce01 --- /dev/null +++ b/test/core/support/stack_lockfree_test.cc @@ -0,0 +1,140 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/stack_lockfree.h" + +#include + +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* max stack size supported */ +#define MAX_STACK_SIZE 65534 + +#define MAX_THREADS 32 + +static void test_serial_sized(size_t size) { + gpr_stack_lockfree *stack = gpr_stack_lockfree_create(size); + size_t i; + size_t j; + + /* First try popping empty */ + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); + + /* Now add one item and check it */ + gpr_stack_lockfree_push(stack, 3); + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == 3); + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); + + /* Now add repeatedly more items and check them */ + for (i = 1; i < size; i *= 2) { + for (j = 0; j <= i; j++) { + GPR_ASSERT(gpr_stack_lockfree_push(stack, (int)j) == (j == 0)); + } + for (j = 0; j <= i; j++) { + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == (int)(i - j)); + } + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); + } + + gpr_stack_lockfree_destroy(stack); +} + +static void test_serial() { + size_t i; + for (i = 128; i < MAX_STACK_SIZE; i *= 2) { + test_serial_sized(i); + } + test_serial_sized(MAX_STACK_SIZE); +} + +struct test_arg { + gpr_stack_lockfree *stack; + int stack_size; + int nthreads; + int rank; + int sum; +}; + +static void test_mt_body(void *v) { + struct test_arg *arg = (struct test_arg *)v; + int lo, hi; + int i; + int res; + lo = arg->rank * arg->stack_size / arg->nthreads; + hi = (arg->rank + 1) * arg->stack_size / arg->nthreads; + for (i = lo; i < hi; i++) { + gpr_stack_lockfree_push(arg->stack, i); + if ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { + arg->sum += res; + } + } + while ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { + arg->sum += res; + } +} + +static void test_mt_sized(size_t size, int nth) { + gpr_stack_lockfree *stack; + struct test_arg args[MAX_THREADS]; + gpr_thd_id thds[MAX_THREADS]; + int sum; + int i; + gpr_thd_options options = gpr_thd_options_default(); + + stack = gpr_stack_lockfree_create(size); + for (i = 0; i < nth; i++) { + args[i].stack = stack; + args[i].stack_size = (int)size; + args[i].nthreads = nth; + args[i].rank = i; + args[i].sum = 0; + } + gpr_thd_options_set_joinable(&options); + for (i = 0; i < nth; i++) { + GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options)); + } + sum = 0; + for (i = 0; i < nth; i++) { + gpr_thd_join(thds[i]); + sum = sum + args[i].sum; + } + GPR_ASSERT((unsigned)sum == ((unsigned)size * (size - 1)) / 2); + gpr_stack_lockfree_destroy(stack); +} + +static void test_mt() { + size_t size; + int nth; + for (nth = 1; nth < MAX_THREADS; nth++) { + for (size = 128; size < MAX_STACK_SIZE; size *= 2) { + test_mt_sized(size, nth); + } + test_mt_sized(MAX_STACK_SIZE, nth); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_serial(); + test_mt(); + return 0; +} diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c deleted file mode 100644 index bee2139477..0000000000 --- a/test/core/support/string_test.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/support/string.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) - -static void test_strdup(void) { - static const char *src1 = "hello world"; - char *dst1; - - LOG_TEST_NAME("test_strdup"); - - dst1 = gpr_strdup(src1); - GPR_ASSERT(0 == strcmp(src1, dst1)); - gpr_free(dst1); - - GPR_ASSERT(NULL == gpr_strdup(NULL)); -} - -static void expect_dump(const char *buf, size_t len, uint32_t flags, - const char *result) { - char *got = gpr_dump(buf, len, flags); - GPR_ASSERT(0 == strcmp(got, result)); - gpr_free(got); -} - -static void test_dump(void) { - LOG_TEST_NAME("test_dump"); - expect_dump("\x01", 1, GPR_DUMP_HEX, "01"); - expect_dump("\x01", 1, GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); - expect_dump("\x01\x02", 2, GPR_DUMP_HEX, "01 02"); - expect_dump("\x01\x23\x45\x67\x89\xab\xcd\xef", 8, GPR_DUMP_HEX, - "01 23 45 67 89 ab cd ef"); - expect_dump("ab", 2, GPR_DUMP_HEX | GPR_DUMP_ASCII, "61 62 'ab'"); -} - -static void test_pu32_fail(const char *s) { - uint32_t out; - GPR_ASSERT(!gpr_parse_bytes_to_uint32(s, strlen(s), &out)); -} - -static void test_pu32_succeed(const char *s, uint32_t want) { - uint32_t out; - GPR_ASSERT(gpr_parse_bytes_to_uint32(s, strlen(s), &out)); - GPR_ASSERT(out == want); -} - -static void test_parse_uint32(void) { - LOG_TEST_NAME("test_parse_uint32"); - - test_pu32_fail("-1"); - test_pu32_fail("a"); - test_pu32_fail(""); - test_pu32_succeed("0", 0); - test_pu32_succeed("1", 1); - test_pu32_succeed("2", 2); - test_pu32_succeed("3", 3); - test_pu32_succeed("4", 4); - test_pu32_succeed("5", 5); - test_pu32_succeed("6", 6); - test_pu32_succeed("7", 7); - test_pu32_succeed("8", 8); - test_pu32_succeed("9", 9); - test_pu32_succeed("10", 10); - test_pu32_succeed("11", 11); - test_pu32_succeed("12", 12); - test_pu32_succeed("13", 13); - test_pu32_succeed("14", 14); - test_pu32_succeed("15", 15); - test_pu32_succeed("16", 16); - test_pu32_succeed("17", 17); - test_pu32_succeed("18", 18); - test_pu32_succeed("19", 19); - test_pu32_succeed("1234567890", 1234567890); - test_pu32_succeed("4294967295", 4294967295u); - test_pu32_fail("4294967296"); - test_pu32_fail("4294967297"); - test_pu32_fail("4294967298"); - test_pu32_fail("4294967299"); -} - -static void test_asprintf(void) { - char *buf; - int i, j; - - LOG_TEST_NAME("test_asprintf"); - - /* Print an empty string. */ - GPR_ASSERT(gpr_asprintf(&buf, "%s", "") == 0); - GPR_ASSERT(buf[0] == '\0'); - gpr_free(buf); - - /* Print strings of various lengths. */ - for (i = 1; i < 100; i++) { - GPR_ASSERT(gpr_asprintf(&buf, "%0*d", i, 1) == i); - - /* The buffer should resemble "000001\0". */ - for (j = 0; j < i - 2; j++) { - GPR_ASSERT(buf[j] == '0'); - } - GPR_ASSERT(buf[i - 1] == '1'); - GPR_ASSERT(buf[i] == '\0'); - gpr_free(buf); - } -} - -static void test_strjoin(void) { - const char *parts[4] = {"one", "two", "three", "four"}; - size_t joined_len; - char *joined; - - LOG_TEST_NAME("test_strjoin"); - - joined = gpr_strjoin(parts, 4, &joined_len); - GPR_ASSERT(0 == strcmp("onetwothreefour", joined)); - gpr_free(joined); - - joined = gpr_strjoin(parts, 0, &joined_len); - GPR_ASSERT(0 == strcmp("", joined)); - gpr_free(joined); - - joined = gpr_strjoin(parts, 1, &joined_len); - GPR_ASSERT(0 == strcmp("one", joined)); - gpr_free(joined); -} - -static void test_strjoin_sep(void) { - const char *parts[4] = {"one", "two", "three", "four"}; - size_t joined_len; - char *joined; - - LOG_TEST_NAME("test_strjoin_sep"); - - joined = gpr_strjoin_sep(parts, 4, ", ", &joined_len); - GPR_ASSERT(0 == strcmp("one, two, three, four", joined)); - gpr_free(joined); - - /* empty separator */ - joined = gpr_strjoin_sep(parts, 4, "", &joined_len); - GPR_ASSERT(0 == strcmp("onetwothreefour", joined)); - gpr_free(joined); - - /* degenerated case specifying zero input parts */ - joined = gpr_strjoin_sep(parts, 0, ", ", &joined_len); - GPR_ASSERT(0 == strcmp("", joined)); - gpr_free(joined); - - /* single part should have no separator */ - joined = gpr_strjoin_sep(parts, 1, ", ", &joined_len); - GPR_ASSERT(0 == strcmp("one", joined)); - gpr_free(joined); -} - -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 == int64_ttoa(0, buf)); - GPR_ASSERT(0 == strcmp("0", buf)); - - /* positive */ - GPR_ASSERT(3 == int64_ttoa(123, buf)); - GPR_ASSERT(0 == strcmp("123", buf)); - - /* large positive */ - GPR_ASSERT(19 == int64_ttoa(9223372036854775807LL, buf)); - GPR_ASSERT(0 == strcmp("9223372036854775807", buf)); - - /* large negative */ - GPR_ASSERT(20 == int64_ttoa(-9223372036854775807LL - 1, buf)); - GPR_ASSERT(0 == strcmp("-9223372036854775808", buf)); -} - -static void test_leftpad() { - char *padded; - - LOG_TEST_NAME("test_leftpad"); - - padded = gpr_leftpad("foo", ' ', 5); - GPR_ASSERT(0 == strcmp(" foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", ' ', 4); - GPR_ASSERT(0 == strcmp(" foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", ' ', 3); - GPR_ASSERT(0 == strcmp("foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", ' ', 2); - GPR_ASSERT(0 == strcmp("foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", ' ', 1); - GPR_ASSERT(0 == strcmp("foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", ' ', 0); - GPR_ASSERT(0 == strcmp("foo", padded)); - gpr_free(padded); - - padded = gpr_leftpad("foo", '0', 5); - GPR_ASSERT(0 == strcmp("00foo", padded)); - gpr_free(padded); -} - -static void test_stricmp(void) { - LOG_TEST_NAME("test_stricmp"); - - GPR_ASSERT(0 == gpr_stricmp("hello", "hello")); - GPR_ASSERT(0 == gpr_stricmp("HELLO", "hello")); - GPR_ASSERT(gpr_stricmp("a", "b") < 0); - GPR_ASSERT(gpr_stricmp("b", "a") > 0); -} - -static void test_memrchr(void) { - LOG_TEST_NAME("test_memrchr"); - - GPR_ASSERT(NULL == gpr_memrchr(NULL, 'a', 0)); - GPR_ASSERT(NULL == gpr_memrchr("", 'a', 0)); - GPR_ASSERT(NULL == gpr_memrchr("hello", 'b', 5)); - GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'h', 5), "hello")); - GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'o', 5), "o")); - GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'l', 5), "lo")); -} - -static void test_is_true(void) { - LOG_TEST_NAME("test_is_true"); - - GPR_ASSERT(true == gpr_is_true("True")); - GPR_ASSERT(true == gpr_is_true("true")); - GPR_ASSERT(true == gpr_is_true("TRUE")); - GPR_ASSERT(true == gpr_is_true("Yes")); - GPR_ASSERT(true == gpr_is_true("yes")); - GPR_ASSERT(true == gpr_is_true("YES")); - GPR_ASSERT(true == gpr_is_true("1")); - GPR_ASSERT(false == gpr_is_true(NULL)); - GPR_ASSERT(false == gpr_is_true("")); - GPR_ASSERT(false == gpr_is_true("0")); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_strdup(); - test_dump(); - test_parse_uint32(); - test_asprintf(); - test_strjoin(); - test_strjoin_sep(); - test_ltoa(); - test_int64toa(); - test_leftpad(); - test_stricmp(); - test_memrchr(); - test_is_true(); - return 0; -} diff --git a/test/core/support/string_test.cc b/test/core/support/string_test.cc new file mode 100644 index 0000000000..bee2139477 --- /dev/null +++ b/test/core/support/string_test.cc @@ -0,0 +1,312 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/support/string.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) + +static void test_strdup(void) { + static const char *src1 = "hello world"; + char *dst1; + + LOG_TEST_NAME("test_strdup"); + + dst1 = gpr_strdup(src1); + GPR_ASSERT(0 == strcmp(src1, dst1)); + gpr_free(dst1); + + GPR_ASSERT(NULL == gpr_strdup(NULL)); +} + +static void expect_dump(const char *buf, size_t len, uint32_t flags, + const char *result) { + char *got = gpr_dump(buf, len, flags); + GPR_ASSERT(0 == strcmp(got, result)); + gpr_free(got); +} + +static void test_dump(void) { + LOG_TEST_NAME("test_dump"); + expect_dump("\x01", 1, GPR_DUMP_HEX, "01"); + expect_dump("\x01", 1, GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); + expect_dump("\x01\x02", 2, GPR_DUMP_HEX, "01 02"); + expect_dump("\x01\x23\x45\x67\x89\xab\xcd\xef", 8, GPR_DUMP_HEX, + "01 23 45 67 89 ab cd ef"); + expect_dump("ab", 2, GPR_DUMP_HEX | GPR_DUMP_ASCII, "61 62 'ab'"); +} + +static void test_pu32_fail(const char *s) { + uint32_t out; + GPR_ASSERT(!gpr_parse_bytes_to_uint32(s, strlen(s), &out)); +} + +static void test_pu32_succeed(const char *s, uint32_t want) { + uint32_t out; + GPR_ASSERT(gpr_parse_bytes_to_uint32(s, strlen(s), &out)); + GPR_ASSERT(out == want); +} + +static void test_parse_uint32(void) { + LOG_TEST_NAME("test_parse_uint32"); + + test_pu32_fail("-1"); + test_pu32_fail("a"); + test_pu32_fail(""); + test_pu32_succeed("0", 0); + test_pu32_succeed("1", 1); + test_pu32_succeed("2", 2); + test_pu32_succeed("3", 3); + test_pu32_succeed("4", 4); + test_pu32_succeed("5", 5); + test_pu32_succeed("6", 6); + test_pu32_succeed("7", 7); + test_pu32_succeed("8", 8); + test_pu32_succeed("9", 9); + test_pu32_succeed("10", 10); + test_pu32_succeed("11", 11); + test_pu32_succeed("12", 12); + test_pu32_succeed("13", 13); + test_pu32_succeed("14", 14); + test_pu32_succeed("15", 15); + test_pu32_succeed("16", 16); + test_pu32_succeed("17", 17); + test_pu32_succeed("18", 18); + test_pu32_succeed("19", 19); + test_pu32_succeed("1234567890", 1234567890); + test_pu32_succeed("4294967295", 4294967295u); + test_pu32_fail("4294967296"); + test_pu32_fail("4294967297"); + test_pu32_fail("4294967298"); + test_pu32_fail("4294967299"); +} + +static void test_asprintf(void) { + char *buf; + int i, j; + + LOG_TEST_NAME("test_asprintf"); + + /* Print an empty string. */ + GPR_ASSERT(gpr_asprintf(&buf, "%s", "") == 0); + GPR_ASSERT(buf[0] == '\0'); + gpr_free(buf); + + /* Print strings of various lengths. */ + for (i = 1; i < 100; i++) { + GPR_ASSERT(gpr_asprintf(&buf, "%0*d", i, 1) == i); + + /* The buffer should resemble "000001\0". */ + for (j = 0; j < i - 2; j++) { + GPR_ASSERT(buf[j] == '0'); + } + GPR_ASSERT(buf[i - 1] == '1'); + GPR_ASSERT(buf[i] == '\0'); + gpr_free(buf); + } +} + +static void test_strjoin(void) { + const char *parts[4] = {"one", "two", "three", "four"}; + size_t joined_len; + char *joined; + + LOG_TEST_NAME("test_strjoin"); + + joined = gpr_strjoin(parts, 4, &joined_len); + GPR_ASSERT(0 == strcmp("onetwothreefour", joined)); + gpr_free(joined); + + joined = gpr_strjoin(parts, 0, &joined_len); + GPR_ASSERT(0 == strcmp("", joined)); + gpr_free(joined); + + joined = gpr_strjoin(parts, 1, &joined_len); + GPR_ASSERT(0 == strcmp("one", joined)); + gpr_free(joined); +} + +static void test_strjoin_sep(void) { + const char *parts[4] = {"one", "two", "three", "four"}; + size_t joined_len; + char *joined; + + LOG_TEST_NAME("test_strjoin_sep"); + + joined = gpr_strjoin_sep(parts, 4, ", ", &joined_len); + GPR_ASSERT(0 == strcmp("one, two, three, four", joined)); + gpr_free(joined); + + /* empty separator */ + joined = gpr_strjoin_sep(parts, 4, "", &joined_len); + GPR_ASSERT(0 == strcmp("onetwothreefour", joined)); + gpr_free(joined); + + /* degenerated case specifying zero input parts */ + joined = gpr_strjoin_sep(parts, 0, ", ", &joined_len); + GPR_ASSERT(0 == strcmp("", joined)); + gpr_free(joined); + + /* single part should have no separator */ + joined = gpr_strjoin_sep(parts, 1, ", ", &joined_len); + GPR_ASSERT(0 == strcmp("one", joined)); + gpr_free(joined); +} + +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 == int64_ttoa(0, buf)); + GPR_ASSERT(0 == strcmp("0", buf)); + + /* positive */ + GPR_ASSERT(3 == int64_ttoa(123, buf)); + GPR_ASSERT(0 == strcmp("123", buf)); + + /* large positive */ + GPR_ASSERT(19 == int64_ttoa(9223372036854775807LL, buf)); + GPR_ASSERT(0 == strcmp("9223372036854775807", buf)); + + /* large negative */ + GPR_ASSERT(20 == int64_ttoa(-9223372036854775807LL - 1, buf)); + GPR_ASSERT(0 == strcmp("-9223372036854775808", buf)); +} + +static void test_leftpad() { + char *padded; + + LOG_TEST_NAME("test_leftpad"); + + padded = gpr_leftpad("foo", ' ', 5); + GPR_ASSERT(0 == strcmp(" foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", ' ', 4); + GPR_ASSERT(0 == strcmp(" foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", ' ', 3); + GPR_ASSERT(0 == strcmp("foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", ' ', 2); + GPR_ASSERT(0 == strcmp("foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", ' ', 1); + GPR_ASSERT(0 == strcmp("foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", ' ', 0); + GPR_ASSERT(0 == strcmp("foo", padded)); + gpr_free(padded); + + padded = gpr_leftpad("foo", '0', 5); + GPR_ASSERT(0 == strcmp("00foo", padded)); + gpr_free(padded); +} + +static void test_stricmp(void) { + LOG_TEST_NAME("test_stricmp"); + + GPR_ASSERT(0 == gpr_stricmp("hello", "hello")); + GPR_ASSERT(0 == gpr_stricmp("HELLO", "hello")); + GPR_ASSERT(gpr_stricmp("a", "b") < 0); + GPR_ASSERT(gpr_stricmp("b", "a") > 0); +} + +static void test_memrchr(void) { + LOG_TEST_NAME("test_memrchr"); + + GPR_ASSERT(NULL == gpr_memrchr(NULL, 'a', 0)); + GPR_ASSERT(NULL == gpr_memrchr("", 'a', 0)); + GPR_ASSERT(NULL == gpr_memrchr("hello", 'b', 5)); + GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'h', 5), "hello")); + GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'o', 5), "o")); + GPR_ASSERT(0 == strcmp((const char *)gpr_memrchr("hello", 'l', 5), "lo")); +} + +static void test_is_true(void) { + LOG_TEST_NAME("test_is_true"); + + GPR_ASSERT(true == gpr_is_true("True")); + GPR_ASSERT(true == gpr_is_true("true")); + GPR_ASSERT(true == gpr_is_true("TRUE")); + GPR_ASSERT(true == gpr_is_true("Yes")); + GPR_ASSERT(true == gpr_is_true("yes")); + GPR_ASSERT(true == gpr_is_true("YES")); + GPR_ASSERT(true == gpr_is_true("1")); + GPR_ASSERT(false == gpr_is_true(NULL)); + GPR_ASSERT(false == gpr_is_true("")); + GPR_ASSERT(false == gpr_is_true("0")); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_strdup(); + test_dump(); + test_parse_uint32(); + test_asprintf(); + test_strjoin(); + test_strjoin_sep(); + test_ltoa(); + test_int64toa(); + test_leftpad(); + test_stricmp(); + test_memrchr(); + test_is_true(); + return 0; +} diff --git a/test/core/support/sync_test.c b/test/core/support/sync_test.c deleted file mode 100644 index 178d77edcd..0000000000 --- a/test/core/support/sync_test.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test of gpr synchronization support. */ - -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -/* ==================Example use of interface=================== - - A producer-consumer queue of up to N integers, - illustrating the use of the calls in this interface. */ - -#define N 4 - -typedef struct queue { - gpr_cv non_empty; /* Signalled when length becomes non-zero. */ - gpr_cv non_full; /* Signalled when length becomes non-N. */ - gpr_mu mu; /* Protects all fields below. - (That is, except during initialization or - destruction, the fields below should be accessed - only by a thread that holds mu.) */ - int head; /* Index of head of queue 0..N-1. */ - int length; /* Number of valid elements in queue 0..N. */ - int elem[N]; /* elem[head .. head+length-1] are queue elements. */ -} queue; - -/* Initialize *q. */ -void queue_init(queue *q) { - gpr_mu_init(&q->mu); - gpr_cv_init(&q->non_empty); - gpr_cv_init(&q->non_full); - q->head = 0; - q->length = 0; -} - -/* Free storage associated with *q. */ -void queue_destroy(queue *q) { - gpr_mu_destroy(&q->mu); - gpr_cv_destroy(&q->non_empty); - gpr_cv_destroy(&q->non_full); -} - -/* Wait until there is room in *q, then append x to *q. */ -void queue_append(queue *q, int x) { - gpr_mu_lock(&q->mu); - /* To wait for a predicate without a deadline, loop on the negation of the - predicate, and use gpr_cv_wait(..., gpr_inf_future(GPR_CLOCK_REALTIME)) - inside the loop - to release the lock, wait, and reacquire on each iteration. Code that - makes the condition true should use gpr_cv_broadcast() on the - corresponding condition variable. The predicate must be on state - protected by the lock. */ - while (q->length == N) { - gpr_cv_wait(&q->non_full, &q->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ - /* It's normal to use gpr_cv_broadcast() or gpr_signal() while - holding the lock. */ - gpr_cv_broadcast(&q->non_empty); - } - q->elem[(q->head + q->length) % N] = x; - q->length++; - gpr_mu_unlock(&q->mu); -} - -/* If it can be done without blocking, append x to *q and return non-zero. - Otherwise return 0. */ -int queue_try_append(queue *q, int x) { - int result = 0; - if (gpr_mu_trylock(&q->mu)) { - if (q->length != N) { - if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ - gpr_cv_broadcast(&q->non_empty); - } - q->elem[(q->head + q->length) % N] = x; - q->length++; - result = 1; - } - gpr_mu_unlock(&q->mu); - } - return result; -} - -/* Wait until the *q is non-empty or deadline abs_deadline passes. If the - queue is non-empty, remove its head entry, place it in *head, and return - non-zero. Otherwise return 0. */ -int queue_remove(queue *q, int *head, gpr_timespec abs_deadline) { - int result = 0; - gpr_mu_lock(&q->mu); - /* To wait for a predicate with a deadline, loop on the negation of the - predicate or until gpr_cv_wait() returns true. Code that makes - the condition true should use gpr_cv_broadcast() on the corresponding - condition variable. The predicate must be on state protected by the - lock. */ - while (q->length == 0 && !gpr_cv_wait(&q->non_empty, &q->mu, abs_deadline)) { - } - if (q->length != 0) { /* Queue is non-empty. */ - result = 1; - if (q->length == N) { /* Wake threads blocked in queue_append(). */ - gpr_cv_broadcast(&q->non_full); - } - *head = q->elem[q->head]; - q->head = (q->head + 1) % N; - q->length--; - } /* else deadline exceeded */ - gpr_mu_unlock(&q->mu); - return result; -} - -/* ------------------------------------------------- */ -/* Tests for gpr_mu and gpr_cv, and the queue example. */ -struct test { - int threads; /* number of threads */ - - int64_t iterations; /* number of iterations per thread */ - int64_t 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 */ - - gpr_cv cv; /* signalling depends on test */ - - gpr_cv done_cv; /* signalled when done == 0 */ - - queue q; - - gpr_stats_counter stats_counter; - - gpr_refcount refcount; - gpr_refcount thread_refcount; - gpr_event event; -}; - -/* Return pointer to a new struct test. */ -static struct test *test_new(int threads, int64_t 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); - queue_init(&m->q); - gpr_stats_init(&m->stats_counter, 0); - gpr_ref_init(&m->refcount, 0); - gpr_ref_init(&m->thread_refcount, threads); - gpr_event_init(&m->event); - return m; -} - -/* Return pointer to a new struct test. */ -static void test_destroy(struct test *m) { - gpr_mu_destroy(&m->mu); - gpr_cv_destroy(&m->cv); - gpr_cv_destroy(&m->done_cv); - queue_destroy(&m->q); - gpr_free(m); -} - -/* Create m->threads threads, each running (*body)(m) */ -static void test_create_threads(struct test *m, void (*body)(void *arg)) { - gpr_thd_id id; - int i; - for (i = 0; i != m->threads; i++) { - GPR_ASSERT(gpr_thd_new(&id, body, m, NULL)); - } -} - -/* Wait until all threads report done. */ -static void test_wait(struct test *m) { - gpr_mu_lock(&m->mu); - while (m->done != 0) { - gpr_cv_wait(&m->done_cv, &m->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&m->mu); -} - -/* Get an integer thread id in the raneg 0..threads-1 */ -static int thread_id(struct test *m) { - int id; - gpr_mu_lock(&m->mu); - id = m->thread_count++; - gpr_mu_unlock(&m->mu); - return id; -} - -/* Indicate that a thread is done, by decrementing m->done - and signalling done_cv if m->done==0. */ -static void mark_thread_done(struct test *m) { - gpr_mu_lock(&m->mu); - GPR_ASSERT(m->done != 0); - m->done--; - if (m->done == 0) { - gpr_cv_signal(&m->done_cv); - } - gpr_mu_unlock(&m->mu); -} - -/* 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. - 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, int incr_step) { - int64_t iterations = 1024; - struct test *m; - gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); - gpr_timespec time_taken; - gpr_timespec deadline = gpr_time_add( - start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); - fprintf(stderr, "%s:", name); - while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { - iterations <<= 1; - fprintf(stderr, " %ld", (long)iterations); - m = test_new(10, iterations, incr_step); - if (extra != NULL) { - gpr_thd_id id; - GPR_ASSERT(gpr_thd_new(&id, extra, m, NULL)); - m->done++; /* one more thread to wait for */ - } - test_create_threads(m, body); - test_wait(m); - 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); - } - test_destroy(m); - } - time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); - fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, - (int)time_taken.tv_nsec); -} - -/* Increment m->counter on each iteration; then mark thread as done. */ -static void inc(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations; i++) { - gpr_mu_lock(&m->mu); - m->counter++; - gpr_mu_unlock(&m->mu); - } - mark_thread_done(m); -} - -/* Increment m->counter under lock acquired with trylock, m->iterations times; - then mark thread as done. */ -static void inctry(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations;) { - if (gpr_mu_trylock(&m->mu)) { - m->counter++; - gpr_mu_unlock(&m->mu); - i++; - } - } - mark_thread_done(m); -} - -/* Increment counter only when (m->counter%m->threads)==m->thread_id; then mark - thread as done. */ -static void inc_by_turns(void *v /*=m*/) { - struct test *m = v; - int64_t i; - int id = thread_id(m); - for (i = 0; i != m->iterations; i++) { - gpr_mu_lock(&m->mu); - while ((m->counter % m->threads) != id) { - gpr_cv_wait(&m->cv, &m->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - m->counter++; - gpr_cv_broadcast(&m->cv); - gpr_mu_unlock(&m->mu); - } - mark_thread_done(m); -} - -/* Wait a millisecond and increment counter on each iteration; - then mark thread as done. */ -static void inc_with_1ms_delay(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations; i++) { - gpr_timespec deadline; - gpr_mu_lock(&m->mu); - deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000, GPR_TIMESPAN)); - while (!gpr_cv_wait(&m->cv, &m->mu, deadline)) { - } - m->counter++; - gpr_mu_unlock(&m->mu); - } - mark_thread_done(m); -} - -/* Wait a millisecond and increment counter on each iteration, using an event - for timing; then mark thread as done. */ -static void inc_with_1ms_delay_event(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations; i++) { - gpr_timespec deadline; - deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000, GPR_TIMESPAN)); - GPR_ASSERT(gpr_event_wait(&m->event, deadline) == NULL); - gpr_mu_lock(&m->mu); - m->counter++; - gpr_mu_unlock(&m->mu); - } - mark_thread_done(m); -} - -/* Produce m->iterations elements on queue m->q, then mark thread as done. - Even threads use queue_append(), and odd threads use queue_try_append() - until it succeeds. */ -static void many_producers(void *v /*=m*/) { - struct test *m = v; - int64_t i; - int x = thread_id(m); - if ((x & 1) == 0) { - for (i = 0; i != m->iterations; i++) { - queue_append(&m->q, 1); - } - } else { - for (i = 0; i != m->iterations; i++) { - while (!queue_try_append(&m->q, 1)) { - } - } - } - mark_thread_done(m); -} - -/* Consume elements from m->q until m->threads*m->iterations are seen, - wait an extra second to confirm that no more elements are arriving, - then mark thread as done. */ -static void consumer(void *v /*=m*/) { - struct test *m = v; - int64_t n = m->iterations * m->threads; - int64_t i; - int value; - for (i = 0; i != n; i++) { - queue_remove(&m->q, &value, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_lock(&m->mu); - m->counter = n; - gpr_mu_unlock(&m->mu); - GPR_ASSERT( - !queue_remove(&m->q, &value, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000000, GPR_TIMESPAN)))); - mark_thread_done(m); -} - -/* Increment m->stats_counter m->iterations times, transfer counter value to - m->counter, then mark thread as done. */ -static void statsinc(void *v /*=m*/) { - struct test *m = v; - int64_t i; - for (i = 0; i != m->iterations; i++) { - gpr_stats_inc(&m->stats_counter, 1); - } - gpr_mu_lock(&m->mu); - m->counter = gpr_stats_read(&m->stats_counter); - gpr_mu_unlock(&m->mu); - mark_thread_done(m); -} - -/* 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; - int64_t i; - for (i = 0; i != m->iterations; i++) { - 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); - } - mark_thread_done(m); -} - -/* Wait until m->event is set to (void *)1, then decrement m->refcount by 1 - (m->threads * m->iterations * m->incr_step) times, and ensure that the last - decrement caused the counter to reach zero, then mark thread as done. */ -static void refcheck(void *v /*=m*/) { - struct test *m = v; - int64_t n = m->iterations * m->threads * m->incr_step; - int64_t i; - GPR_ASSERT(gpr_event_wait(&m->event, gpr_inf_future(GPR_CLOCK_REALTIME)) == - (void *)1); - GPR_ASSERT(gpr_event_get(&m->event) == (void *)1); - for (i = 1; i != n; i++) { - GPR_ASSERT(!gpr_unref(&m->refcount)); - m->counter++; - } - GPR_ASSERT(gpr_unref(&m->refcount)); - m->counter++; - mark_thread_done(m); -} - -/* ------------------------------------------------- */ - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - 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/sync_test.cc b/test/core/support/sync_test.cc new file mode 100644 index 0000000000..c005a2bbb1 --- /dev/null +++ b/test/core/support/sync_test.cc @@ -0,0 +1,453 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test of gpr synchronization support. */ + +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* ==================Example use of interface=================== + + A producer-consumer queue of up to N integers, + illustrating the use of the calls in this interface. */ + +#define N 4 + +typedef struct queue { + gpr_cv non_empty; /* Signalled when length becomes non-zero. */ + gpr_cv non_full; /* Signalled when length becomes non-N. */ + gpr_mu mu; /* Protects all fields below. + (That is, except during initialization or + destruction, the fields below should be accessed + only by a thread that holds mu.) */ + int head; /* Index of head of queue 0..N-1. */ + int length; /* Number of valid elements in queue 0..N. */ + int elem[N]; /* elem[head .. head+length-1] are queue elements. */ +} queue; + +/* Initialize *q. */ +void queue_init(queue *q) { + gpr_mu_init(&q->mu); + gpr_cv_init(&q->non_empty); + gpr_cv_init(&q->non_full); + q->head = 0; + q->length = 0; +} + +/* Free storage associated with *q. */ +void queue_destroy(queue *q) { + gpr_mu_destroy(&q->mu); + gpr_cv_destroy(&q->non_empty); + gpr_cv_destroy(&q->non_full); +} + +/* Wait until there is room in *q, then append x to *q. */ +void queue_append(queue *q, int x) { + gpr_mu_lock(&q->mu); + /* To wait for a predicate without a deadline, loop on the negation of the + predicate, and use gpr_cv_wait(..., gpr_inf_future(GPR_CLOCK_REALTIME)) + inside the loop + to release the lock, wait, and reacquire on each iteration. Code that + makes the condition true should use gpr_cv_broadcast() on the + corresponding condition variable. The predicate must be on state + protected by the lock. */ + while (q->length == N) { + gpr_cv_wait(&q->non_full, &q->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ + /* It's normal to use gpr_cv_broadcast() or gpr_signal() while + holding the lock. */ + gpr_cv_broadcast(&q->non_empty); + } + q->elem[(q->head + q->length) % N] = x; + q->length++; + gpr_mu_unlock(&q->mu); +} + +/* If it can be done without blocking, append x to *q and return non-zero. + Otherwise return 0. */ +int queue_try_append(queue *q, int x) { + int result = 0; + if (gpr_mu_trylock(&q->mu)) { + if (q->length != N) { + if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ + gpr_cv_broadcast(&q->non_empty); + } + q->elem[(q->head + q->length) % N] = x; + q->length++; + result = 1; + } + gpr_mu_unlock(&q->mu); + } + return result; +} + +/* Wait until the *q is non-empty or deadline abs_deadline passes. If the + queue is non-empty, remove its head entry, place it in *head, and return + non-zero. Otherwise return 0. */ +int queue_remove(queue *q, int *head, gpr_timespec abs_deadline) { + int result = 0; + gpr_mu_lock(&q->mu); + /* To wait for a predicate with a deadline, loop on the negation of the + predicate or until gpr_cv_wait() returns true. Code that makes + the condition true should use gpr_cv_broadcast() on the corresponding + condition variable. The predicate must be on state protected by the + lock. */ + while (q->length == 0 && !gpr_cv_wait(&q->non_empty, &q->mu, abs_deadline)) { + } + if (q->length != 0) { /* Queue is non-empty. */ + result = 1; + if (q->length == N) { /* Wake threads blocked in queue_append(). */ + gpr_cv_broadcast(&q->non_full); + } + *head = q->elem[q->head]; + q->head = (q->head + 1) % N; + q->length--; + } /* else deadline exceeded */ + gpr_mu_unlock(&q->mu); + return result; +} + +/* ------------------------------------------------- */ +/* Tests for gpr_mu and gpr_cv, and the queue example. */ +struct test { + int threads; /* number of threads */ + + int64_t iterations; /* number of iterations per thread */ + int64_t 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 */ + + gpr_cv cv; /* signalling depends on test */ + + gpr_cv done_cv; /* signalled when done == 0 */ + + queue q; + + gpr_stats_counter stats_counter; + + gpr_refcount refcount; + gpr_refcount thread_refcount; + gpr_event event; +}; + +/* Return pointer to a new struct test. */ +static struct test *test_new(int threads, int64_t iterations, int incr_step) { + struct test *m = static_cast(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); + queue_init(&m->q); + gpr_stats_init(&m->stats_counter, 0); + gpr_ref_init(&m->refcount, 0); + gpr_ref_init(&m->thread_refcount, threads); + gpr_event_init(&m->event); + return m; +} + +/* Return pointer to a new struct test. */ +static void test_destroy(struct test *m) { + gpr_mu_destroy(&m->mu); + gpr_cv_destroy(&m->cv); + gpr_cv_destroy(&m->done_cv); + queue_destroy(&m->q); + gpr_free(m); +} + +/* Create m->threads threads, each running (*body)(m) */ +static void test_create_threads(struct test *m, void (*body)(void *arg)) { + gpr_thd_id id; + int i; + for (i = 0; i != m->threads; i++) { + GPR_ASSERT(gpr_thd_new(&id, body, m, NULL)); + } +} + +/* Wait until all threads report done. */ +static void test_wait(struct test *m) { + gpr_mu_lock(&m->mu); + while (m->done != 0) { + gpr_cv_wait(&m->done_cv, &m->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&m->mu); +} + +/* Get an integer thread id in the raneg 0..threads-1 */ +static int thread_id(struct test *m) { + int id; + gpr_mu_lock(&m->mu); + id = m->thread_count++; + gpr_mu_unlock(&m->mu); + return id; +} + +/* Indicate that a thread is done, by decrementing m->done + and signalling done_cv if m->done==0. */ +static void mark_thread_done(struct test *m) { + gpr_mu_lock(&m->mu); + GPR_ASSERT(m->done != 0); + m->done--; + if (m->done == 0) { + gpr_cv_signal(&m->done_cv); + } + gpr_mu_unlock(&m->mu); +} + +/* 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. + 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, int incr_step) { + int64_t iterations = 1024; + struct test *m; + gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); + gpr_timespec time_taken; + gpr_timespec deadline = gpr_time_add( + start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN)); + fprintf(stderr, "%s:", name); + while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) { + iterations <<= 1; + fprintf(stderr, " %ld", (long)iterations); + m = test_new(10, iterations, incr_step); + if (extra != NULL) { + gpr_thd_id id; + GPR_ASSERT(gpr_thd_new(&id, extra, m, NULL)); + m->done++; /* one more thread to wait for */ + } + test_create_threads(m, body); + test_wait(m); + 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); + } + test_destroy(m); + } + time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start); + fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec, + (int)time_taken.tv_nsec); +} + +/* Increment m->counter on each iteration; then mark thread as done. */ +static void inc(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + gpr_mu_lock(&m->mu); + m->counter++; + gpr_mu_unlock(&m->mu); + } + mark_thread_done(m); +} + +/* Increment m->counter under lock acquired with trylock, m->iterations times; + then mark thread as done. */ +static void inctry(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations;) { + if (gpr_mu_trylock(&m->mu)) { + m->counter++; + gpr_mu_unlock(&m->mu); + i++; + } + } + mark_thread_done(m); +} + +/* Increment counter only when (m->counter%m->threads)==m->thread_id; then mark + thread as done. */ +static void inc_by_turns(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + int id = thread_id(m); + for (i = 0; i != m->iterations; i++) { + gpr_mu_lock(&m->mu); + while ((m->counter % m->threads) != id) { + gpr_cv_wait(&m->cv, &m->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + m->counter++; + gpr_cv_broadcast(&m->cv); + gpr_mu_unlock(&m->mu); + } + mark_thread_done(m); +} + +/* Wait a millisecond and increment counter on each iteration; + then mark thread as done. */ +static void inc_with_1ms_delay(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + gpr_timespec deadline; + gpr_mu_lock(&m->mu); + deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN)); + while (!gpr_cv_wait(&m->cv, &m->mu, deadline)) { + } + m->counter++; + gpr_mu_unlock(&m->mu); + } + mark_thread_done(m); +} + +/* Wait a millisecond and increment counter on each iteration, using an event + for timing; then mark thread as done. */ +static void inc_with_1ms_delay_event(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + gpr_timespec deadline; + deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN)); + GPR_ASSERT(gpr_event_wait(&m->event, deadline) == NULL); + gpr_mu_lock(&m->mu); + m->counter++; + gpr_mu_unlock(&m->mu); + } + mark_thread_done(m); +} + +/* Produce m->iterations elements on queue m->q, then mark thread as done. + Even threads use queue_append(), and odd threads use queue_try_append() + until it succeeds. */ +static void many_producers(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + int x = thread_id(m); + if ((x & 1) == 0) { + for (i = 0; i != m->iterations; i++) { + queue_append(&m->q, 1); + } + } else { + for (i = 0; i != m->iterations; i++) { + while (!queue_try_append(&m->q, 1)) { + } + } + } + mark_thread_done(m); +} + +/* Consume elements from m->q until m->threads*m->iterations are seen, + wait an extra second to confirm that no more elements are arriving, + then mark thread as done. */ +static void consumer(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t n = m->iterations * m->threads; + int64_t i; + int value; + for (i = 0; i != n; i++) { + queue_remove(&m->q, &value, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_lock(&m->mu); + m->counter = n; + gpr_mu_unlock(&m->mu); + GPR_ASSERT( + !queue_remove(&m->q, &value, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000000, GPR_TIMESPAN)))); + mark_thread_done(m); +} + +/* Increment m->stats_counter m->iterations times, transfer counter value to + m->counter, then mark thread as done. */ +static void statsinc(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + gpr_stats_inc(&m->stats_counter, 1); + } + gpr_mu_lock(&m->mu); + m->counter = gpr_stats_read(&m->stats_counter); + gpr_mu_unlock(&m->mu); + mark_thread_done(m); +} + +/* 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 = static_cast(v); + int64_t i; + for (i = 0; i != m->iterations; i++) { + 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); + } + mark_thread_done(m); +} + +/* Wait until m->event is set to (void *)1, then decrement m->refcount by 1 + (m->threads * m->iterations * m->incr_step) times, and ensure that the last + decrement caused the counter to reach zero, then mark thread as done. */ +static void refcheck(void *v /*=m*/) { + struct test *m = static_cast(v); + int64_t n = m->iterations * m->threads * m->incr_step; + int64_t i; + GPR_ASSERT(gpr_event_wait(&m->event, gpr_inf_future(GPR_CLOCK_REALTIME)) == + (void *)1); + GPR_ASSERT(gpr_event_get(&m->event) == (void *)1); + for (i = 1; i != n; i++) { + GPR_ASSERT(!gpr_unref(&m->refcount)); + m->counter++; + } + GPR_ASSERT(gpr_unref(&m->refcount)); + m->counter++; + mark_thread_done(m); +} + +/* ------------------------------------------------- */ + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + 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 deleted file mode 100644 index 2c578a242c..0000000000 --- a/test/core/support/thd_test.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test of gpr thread support. */ - -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -#define NUM_THREADS 300 - -struct test { - gpr_mu mu; - int n; - int is_done; - gpr_cv done_cv; -}; - -/* A Thread body. Decrement t->n, and if is becomes zero, set t->done. */ -static void thd_body(void *v) { - struct test *t = v; - gpr_mu_lock(&t->mu); - t->n--; - if (t->n == 0) { - t->is_done = 1; - gpr_cv_signal(&t->done_cv); - } - gpr_mu_unlock(&t->mu); -} - -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; - gpr_thd_id thd; - gpr_thd_id thds[NUM_THREADS]; - struct test t; - gpr_thd_options options = gpr_thd_options_default(); - gpr_mu_init(&t.mu); - gpr_cv_init(&t.done_cv); - t.n = NUM_THREADS; - t.is_done = 0; - for (i = 0; i < NUM_THREADS; i++) { - GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL)); - } - gpr_mu_lock(&t.mu); - while (!t.is_done) { - gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&t.mu); - GPR_ASSERT(t.n == 0); - gpr_thd_options_set_joinable(&options); - for (i = 0; i < NUM_THREADS; i++) { - GPR_ASSERT(gpr_thd_new(&thds[i], &thd_body_joinable, NULL, &options)); - } - for (i = 0; i < NUM_THREADS; i++) { - gpr_thd_join(thds[i]); - } -} - -/* ------------------------------------------------- */ - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - test_options(); - test(); - return 0; -} diff --git a/test/core/support/thd_test.cc b/test/core/support/thd_test.cc new file mode 100644 index 0000000000..e6b4ea405b --- /dev/null +++ b/test/core/support/thd_test.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test of gpr thread support. */ + +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +#define NUM_THREADS 300 + +struct test { + gpr_mu mu; + int n; + int is_done; + gpr_cv done_cv; +}; + +/* A Thread body. Decrement t->n, and if is becomes zero, set t->done. */ +static void thd_body(void *v) { + struct test *t = static_cast(v); + gpr_mu_lock(&t->mu); + t->n--; + if (t->n == 0) { + t->is_done = 1; + gpr_cv_signal(&t->done_cv); + } + gpr_mu_unlock(&t->mu); +} + +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; + gpr_thd_id thd; + gpr_thd_id thds[NUM_THREADS]; + struct test t; + gpr_thd_options options = gpr_thd_options_default(); + gpr_mu_init(&t.mu); + gpr_cv_init(&t.done_cv); + t.n = NUM_THREADS; + t.is_done = 0; + for (i = 0; i < NUM_THREADS; i++) { + GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL)); + } + gpr_mu_lock(&t.mu); + while (!t.is_done) { + gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + gpr_mu_unlock(&t.mu); + GPR_ASSERT(t.n == 0); + gpr_thd_options_set_joinable(&options); + for (i = 0; i < NUM_THREADS; i++) { + GPR_ASSERT(gpr_thd_new(&thds[i], &thd_body_joinable, NULL, &options)); + } + for (i = 0; i < NUM_THREADS; i++) { + gpr_thd_join(thds[i]); + } +} + +/* ------------------------------------------------- */ + +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 deleted file mode 100644 index 74b5ef6114..0000000000 --- a/test/core/support/time_test.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test of gpr time support. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -static void to_fp(void *arg, const char *buf, size_t len) { - fwrite(buf, 1, len, (FILE *)arg); -} - -/* Convert gpr_intmax x to ascii base b (2..16), and write with - (*writer)(arg, ...), zero padding to "chars" digits). */ -static void i_to_s(intmax_t x, int base, int chars, - void (*writer)(void *arg, const char *buf, size_t len), - void *arg) { - char buf[64]; - char fmt[32]; - GPR_ASSERT(base == 16 || base == 10); - sprintf(fmt, "%%0%d%s", chars, base == 16 ? PRIxMAX : PRIdMAX); - sprintf(buf, fmt, x); - (*writer)(arg, buf, strlen(buf)); -} - -/* Convert ts to ascii, and write with (*writer)(arg, ...). */ -static void ts_to_s(gpr_timespec t, - void (*writer)(void *arg, const char *buf, size_t len), - void *arg) { - if (t.tv_sec < 0 && t.tv_nsec != 0) { - t.tv_sec++; - t.tv_nsec = GPR_NS_PER_SEC - t.tv_nsec; - } - i_to_s(t.tv_sec, 10, 0, writer, arg); - (*writer)(arg, ".", 1); - i_to_s(t.tv_nsec, 10, 9, writer, arg); -} - -static void test_values(void) { - int i; - - gpr_timespec x = gpr_time_0(GPR_CLOCK_REALTIME); - GPR_ASSERT(x.tv_sec == 0 && x.tv_nsec == 0); - - x = gpr_inf_future(GPR_CLOCK_REALTIME); - fprintf(stderr, "far future "); - i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); - fprintf(stderr, "\n"); - GPR_ASSERT(x.tv_sec == INT64_MAX); - fprintf(stderr, "far future "); - ts_to_s(x, &to_fp, stderr); - fprintf(stderr, "\n"); - - x = gpr_inf_past(GPR_CLOCK_REALTIME); - fprintf(stderr, "far past "); - i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); - fprintf(stderr, "\n"); - GPR_ASSERT(x.tv_sec == INT64_MIN); - fprintf(stderr, "far past "); - ts_to_s(x, &to_fp, stderr); - fprintf(stderr, "\n"); - - for (i = 1; i != 1000 * 1000 * 1000; i *= 10) { - x = gpr_time_from_micros(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec == i / GPR_US_PER_SEC && - x.tv_nsec == (i % GPR_US_PER_SEC) * GPR_NS_PER_US); - x = gpr_time_from_nanos(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec == i / GPR_NS_PER_SEC && - x.tv_nsec == (i % GPR_NS_PER_SEC)); - x = gpr_time_from_millis(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec == i / GPR_MS_PER_SEC && - x.tv_nsec == (i % GPR_MS_PER_SEC) * GPR_NS_PER_MS); - } - - /* Test possible overflow in conversion of -ve values. */ - x = gpr_time_from_micros(-(INT64_MAX - 999997), GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec < 0); - GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); - - x = gpr_time_from_nanos(-(INT64_MAX - 999999997), GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec < 0); - GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); - - x = gpr_time_from_millis(-(INT64_MAX - 997), GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec < 0); - GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); - - /* Test general -ve values. */ - for (i = -1; i > -1000 * 1000 * 1000; i *= 7) { - x = gpr_time_from_micros(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec * GPR_US_PER_SEC + x.tv_nsec / GPR_NS_PER_US == i); - x = gpr_time_from_nanos(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec * GPR_NS_PER_SEC + x.tv_nsec == i); - x = gpr_time_from_millis(i, GPR_TIMESPAN); - GPR_ASSERT(x.tv_sec * GPR_MS_PER_SEC + x.tv_nsec / GPR_NS_PER_MS == i); - } -} - -static void test_add_sub(void) { - int i; - int j; - int k; - /* Basic addition and subtraction. */ - for (i = -100; i <= 100; i++) { - for (j = -100; j <= 100; j++) { - for (k = 1; k <= 10000000; k *= 10) { - int sum = i + j; - int diff = i - j; - gpr_timespec it = gpr_time_from_micros(i * k, GPR_TIMESPAN); - gpr_timespec jt = gpr_time_from_micros(j * k, GPR_TIMESPAN); - gpr_timespec sumt = gpr_time_add(it, jt); - gpr_timespec difft = gpr_time_sub(it, jt); - if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) != - 0) { - fprintf(stderr, "i %d j %d sum %d sumt ", i, j, sum); - ts_to_s(sumt, &to_fp, stderr); - fprintf(stderr, "\n"); - GPR_ASSERT(0); - } - if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) != - 0) { - fprintf(stderr, "i %d j %d diff %d diff ", i, j, diff); - ts_to_s(sumt, &to_fp, stderr); - fprintf(stderr, "\n"); - GPR_ASSERT(0); - } - } - } - } -} - -static void test_overflow(void) { - /* overflow */ - gpr_timespec x = gpr_time_from_micros(1, GPR_TIMESPAN); - do { - x = gpr_time_add(x, x); - } while (gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) < 0); - GPR_ASSERT(gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) == 0); - x = gpr_time_from_micros(-1, GPR_TIMESPAN); - do { - x = gpr_time_add(x, x); - } while (gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) > 0); - GPR_ASSERT(gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) == 0); -} - -static void test_sticky_infinities(void) { - int i; - int j; - int k; - gpr_timespec infinity[2]; - gpr_timespec addend[3]; - infinity[0] = gpr_inf_future(GPR_TIMESPAN); - infinity[1] = gpr_inf_past(GPR_TIMESPAN); - addend[0] = gpr_inf_future(GPR_TIMESPAN); - addend[1] = gpr_inf_past(GPR_TIMESPAN); - addend[2] = gpr_time_0(GPR_TIMESPAN); - - /* Infinities are sticky */ - for (i = 0; i != sizeof(infinity) / sizeof(infinity[0]); i++) { - for (j = 0; j != sizeof(addend) / sizeof(addend[0]); j++) { - gpr_timespec x = gpr_time_add(infinity[i], addend[j]); - GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); - x = gpr_time_sub(infinity[i], addend[j]); - GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); - } - for (k = -200; k <= 200; k++) { - gpr_timespec y = gpr_time_from_micros(k * 100000, GPR_TIMESPAN); - gpr_timespec x = gpr_time_add(infinity[i], y); - GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); - x = gpr_time_sub(infinity[i], y); - GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); - } - } -} - -static void test_similar(void) { - GPR_ASSERT(1 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN), - gpr_inf_future(GPR_TIMESPAN), - gpr_time_0(GPR_TIMESPAN))); - GPR_ASSERT(1 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN), - gpr_inf_past(GPR_TIMESPAN), - gpr_time_0(GPR_TIMESPAN))); - GPR_ASSERT(0 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN), - gpr_inf_future(GPR_TIMESPAN), - gpr_time_0(GPR_TIMESPAN))); - GPR_ASSERT(0 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN), - gpr_inf_past(GPR_TIMESPAN), - gpr_time_0(GPR_TIMESPAN))); - GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_0(GPR_TIMESPAN))); - GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_from_micros(15, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN))); - GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(15, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN))); - GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_from_micros(25, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN))); - GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(25, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN), - gpr_time_from_micros(10, GPR_TIMESPAN))); -} - -static void test_convert_extreme(void) { - gpr_timespec realtime = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; - gpr_timespec monotime = gpr_convert_clock_type(realtime, GPR_CLOCK_MONOTONIC); - GPR_ASSERT(monotime.tv_sec == realtime.tv_sec); - GPR_ASSERT(monotime.clock_type == GPR_CLOCK_MONOTONIC); -} - -static void test_cmp_extreme(void) { - gpr_timespec t1 = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; - gpr_timespec t2 = {INT64_MAX, 2, GPR_CLOCK_REALTIME}; - GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); - t1.tv_sec = INT64_MIN; - t2.tv_sec = INT64_MIN; - GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); -} - -int main(int argc, char *argv[]) { - grpc_test_init(argc, argv); - - test_values(); - test_add_sub(); - test_overflow(); - test_sticky_infinities(); - test_similar(); - test_convert_extreme(); - test_cmp_extreme(); - return 0; -} diff --git a/test/core/support/time_test.cc b/test/core/support/time_test.cc new file mode 100644 index 0000000000..74b5ef6114 --- /dev/null +++ b/test/core/support/time_test.cc @@ -0,0 +1,255 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test of gpr time support. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +static void to_fp(void *arg, const char *buf, size_t len) { + fwrite(buf, 1, len, (FILE *)arg); +} + +/* Convert gpr_intmax x to ascii base b (2..16), and write with + (*writer)(arg, ...), zero padding to "chars" digits). */ +static void i_to_s(intmax_t x, int base, int chars, + void (*writer)(void *arg, const char *buf, size_t len), + void *arg) { + char buf[64]; + char fmt[32]; + GPR_ASSERT(base == 16 || base == 10); + sprintf(fmt, "%%0%d%s", chars, base == 16 ? PRIxMAX : PRIdMAX); + sprintf(buf, fmt, x); + (*writer)(arg, buf, strlen(buf)); +} + +/* Convert ts to ascii, and write with (*writer)(arg, ...). */ +static void ts_to_s(gpr_timespec t, + void (*writer)(void *arg, const char *buf, size_t len), + void *arg) { + if (t.tv_sec < 0 && t.tv_nsec != 0) { + t.tv_sec++; + t.tv_nsec = GPR_NS_PER_SEC - t.tv_nsec; + } + i_to_s(t.tv_sec, 10, 0, writer, arg); + (*writer)(arg, ".", 1); + i_to_s(t.tv_nsec, 10, 9, writer, arg); +} + +static void test_values(void) { + int i; + + gpr_timespec x = gpr_time_0(GPR_CLOCK_REALTIME); + GPR_ASSERT(x.tv_sec == 0 && x.tv_nsec == 0); + + x = gpr_inf_future(GPR_CLOCK_REALTIME); + fprintf(stderr, "far future "); + i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); + fprintf(stderr, "\n"); + GPR_ASSERT(x.tv_sec == INT64_MAX); + fprintf(stderr, "far future "); + ts_to_s(x, &to_fp, stderr); + fprintf(stderr, "\n"); + + x = gpr_inf_past(GPR_CLOCK_REALTIME); + fprintf(stderr, "far past "); + i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); + fprintf(stderr, "\n"); + GPR_ASSERT(x.tv_sec == INT64_MIN); + fprintf(stderr, "far past "); + ts_to_s(x, &to_fp, stderr); + fprintf(stderr, "\n"); + + for (i = 1; i != 1000 * 1000 * 1000; i *= 10) { + x = gpr_time_from_micros(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec == i / GPR_US_PER_SEC && + x.tv_nsec == (i % GPR_US_PER_SEC) * GPR_NS_PER_US); + x = gpr_time_from_nanos(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec == i / GPR_NS_PER_SEC && + x.tv_nsec == (i % GPR_NS_PER_SEC)); + x = gpr_time_from_millis(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec == i / GPR_MS_PER_SEC && + x.tv_nsec == (i % GPR_MS_PER_SEC) * GPR_NS_PER_MS); + } + + /* Test possible overflow in conversion of -ve values. */ + x = gpr_time_from_micros(-(INT64_MAX - 999997), GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec < 0); + GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); + + x = gpr_time_from_nanos(-(INT64_MAX - 999999997), GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec < 0); + GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); + + x = gpr_time_from_millis(-(INT64_MAX - 997), GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec < 0); + GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); + + /* Test general -ve values. */ + for (i = -1; i > -1000 * 1000 * 1000; i *= 7) { + x = gpr_time_from_micros(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec * GPR_US_PER_SEC + x.tv_nsec / GPR_NS_PER_US == i); + x = gpr_time_from_nanos(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec * GPR_NS_PER_SEC + x.tv_nsec == i); + x = gpr_time_from_millis(i, GPR_TIMESPAN); + GPR_ASSERT(x.tv_sec * GPR_MS_PER_SEC + x.tv_nsec / GPR_NS_PER_MS == i); + } +} + +static void test_add_sub(void) { + int i; + int j; + int k; + /* Basic addition and subtraction. */ + for (i = -100; i <= 100; i++) { + for (j = -100; j <= 100; j++) { + for (k = 1; k <= 10000000; k *= 10) { + int sum = i + j; + int diff = i - j; + gpr_timespec it = gpr_time_from_micros(i * k, GPR_TIMESPAN); + gpr_timespec jt = gpr_time_from_micros(j * k, GPR_TIMESPAN); + gpr_timespec sumt = gpr_time_add(it, jt); + gpr_timespec difft = gpr_time_sub(it, jt); + if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) != + 0) { + fprintf(stderr, "i %d j %d sum %d sumt ", i, j, sum); + ts_to_s(sumt, &to_fp, stderr); + fprintf(stderr, "\n"); + GPR_ASSERT(0); + } + if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) != + 0) { + fprintf(stderr, "i %d j %d diff %d diff ", i, j, diff); + ts_to_s(sumt, &to_fp, stderr); + fprintf(stderr, "\n"); + GPR_ASSERT(0); + } + } + } + } +} + +static void test_overflow(void) { + /* overflow */ + gpr_timespec x = gpr_time_from_micros(1, GPR_TIMESPAN); + do { + x = gpr_time_add(x, x); + } while (gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) < 0); + GPR_ASSERT(gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) == 0); + x = gpr_time_from_micros(-1, GPR_TIMESPAN); + do { + x = gpr_time_add(x, x); + } while (gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) > 0); + GPR_ASSERT(gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) == 0); +} + +static void test_sticky_infinities(void) { + int i; + int j; + int k; + gpr_timespec infinity[2]; + gpr_timespec addend[3]; + infinity[0] = gpr_inf_future(GPR_TIMESPAN); + infinity[1] = gpr_inf_past(GPR_TIMESPAN); + addend[0] = gpr_inf_future(GPR_TIMESPAN); + addend[1] = gpr_inf_past(GPR_TIMESPAN); + addend[2] = gpr_time_0(GPR_TIMESPAN); + + /* Infinities are sticky */ + for (i = 0; i != sizeof(infinity) / sizeof(infinity[0]); i++) { + for (j = 0; j != sizeof(addend) / sizeof(addend[0]); j++) { + gpr_timespec x = gpr_time_add(infinity[i], addend[j]); + GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); + x = gpr_time_sub(infinity[i], addend[j]); + GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); + } + for (k = -200; k <= 200; k++) { + gpr_timespec y = gpr_time_from_micros(k * 100000, GPR_TIMESPAN); + gpr_timespec x = gpr_time_add(infinity[i], y); + GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); + x = gpr_time_sub(infinity[i], y); + GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0); + } + } +} + +static void test_similar(void) { + GPR_ASSERT(1 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN), + gpr_inf_future(GPR_TIMESPAN), + gpr_time_0(GPR_TIMESPAN))); + GPR_ASSERT(1 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN), + gpr_inf_past(GPR_TIMESPAN), + gpr_time_0(GPR_TIMESPAN))); + GPR_ASSERT(0 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN), + gpr_inf_future(GPR_TIMESPAN), + gpr_time_0(GPR_TIMESPAN))); + GPR_ASSERT(0 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN), + gpr_inf_past(GPR_TIMESPAN), + gpr_time_0(GPR_TIMESPAN))); + GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_0(GPR_TIMESPAN))); + GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_from_micros(15, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN))); + GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(15, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN))); + GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_from_micros(25, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN))); + GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(25, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN), + gpr_time_from_micros(10, GPR_TIMESPAN))); +} + +static void test_convert_extreme(void) { + gpr_timespec realtime = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; + gpr_timespec monotime = gpr_convert_clock_type(realtime, GPR_CLOCK_MONOTONIC); + GPR_ASSERT(monotime.tv_sec == realtime.tv_sec); + GPR_ASSERT(monotime.clock_type == GPR_CLOCK_MONOTONIC); +} + +static void test_cmp_extreme(void) { + gpr_timespec t1 = {INT64_MAX, 1, GPR_CLOCK_REALTIME}; + gpr_timespec t2 = {INT64_MAX, 2, GPR_CLOCK_REALTIME}; + GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); + t1.tv_sec = INT64_MIN; + t2.tv_sec = INT64_MIN; + GPR_ASSERT(gpr_time_cmp(t1, t2) == 0); +} + +int main(int argc, char *argv[]) { + grpc_test_init(argc, argv); + + test_values(); + test_add_sub(); + test_overflow(); + test_sticky_infinities(); + test_similar(); + test_convert_extreme(); + test_cmp_extreme(); + return 0; +} diff --git a/test/core/support/tls_test.c b/test/core/support/tls_test.c deleted file mode 100644 index 5529d5cf59..0000000000 --- a/test/core/support/tls_test.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* Test of gpr thread local storage support. */ - -#include -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -#define NUM_THREADS 100 - -GPR_TLS_DECL(test_var); - -static void thd_body(void *arg) { - intptr_t i; - - GPR_ASSERT(gpr_tls_get(&test_var) == 0); - - for (i = 0; i < 100000; i++) { - gpr_tls_set(&test_var, i); - GPR_ASSERT(gpr_tls_get(&test_var) == i); - } - gpr_tls_set(&test_var, 0); -} - -/* ------------------------------------------------- */ - -int main(int argc, char *argv[]) { - gpr_thd_options opt = gpr_thd_options_default(); - int i; - gpr_thd_id threads[NUM_THREADS]; - - grpc_test_init(argc, argv); - - gpr_tls_init(&test_var); - - gpr_thd_options_set_joinable(&opt); - - for (i = 0; i < NUM_THREADS; i++) { - gpr_thd_new(&threads[i], thd_body, NULL, &opt); - } - for (i = 0; i < NUM_THREADS; i++) { - gpr_thd_join(threads[i]); - } - - gpr_tls_destroy(&test_var); - - return 0; -} diff --git a/test/core/support/tls_test.cc b/test/core/support/tls_test.cc new file mode 100644 index 0000000000..5529d5cf59 --- /dev/null +++ b/test/core/support/tls_test.cc @@ -0,0 +1,68 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* Test of gpr thread local storage support. */ + +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +#define NUM_THREADS 100 + +GPR_TLS_DECL(test_var); + +static void thd_body(void *arg) { + intptr_t i; + + GPR_ASSERT(gpr_tls_get(&test_var) == 0); + + for (i = 0; i < 100000; i++) { + gpr_tls_set(&test_var, i); + GPR_ASSERT(gpr_tls_get(&test_var) == i); + } + gpr_tls_set(&test_var, 0); +} + +/* ------------------------------------------------- */ + +int main(int argc, char *argv[]) { + gpr_thd_options opt = gpr_thd_options_default(); + int i; + gpr_thd_id threads[NUM_THREADS]; + + grpc_test_init(argc, argv); + + gpr_tls_init(&test_var); + + gpr_thd_options_set_joinable(&opt); + + for (i = 0; i < NUM_THREADS; i++) { + gpr_thd_new(&threads[i], thd_body, NULL, &opt); + } + for (i = 0; i < NUM_THREADS; i++) { + gpr_thd_join(threads[i]); + } + + gpr_tls_destroy(&test_var); + + return 0; +} diff --git a/test/core/support/useful_test.c b/test/core/support/useful_test.c deleted file mode 100644 index 2f84f485fc..0000000000 --- a/test/core/support/useful_test.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include "test/core/util/test_config.h" - -int main(int argc, char **argv) { - int four[4]; - int five[5]; - uint32_t bitset = 0; - grpc_test_init(argc, argv); - - GPR_ASSERT(GPR_MIN(1, 2) == 1); - GPR_ASSERT(GPR_MAX(1, 2) == 2); - GPR_ASSERT(GPR_MIN(2, 1) == 1); - GPR_ASSERT(GPR_MAX(2, 1) == 2); - GPR_ASSERT(GPR_CLAMP(1, 0, 2) == 1); - GPR_ASSERT(GPR_CLAMP(0, 0, 2) == 0); - GPR_ASSERT(GPR_CLAMP(2, 0, 2) == 2); - GPR_ASSERT(GPR_CLAMP(-1, 0, 2) == 0); - GPR_ASSERT(GPR_CLAMP(3, 0, 2) == 2); - GPR_ASSERT(GPR_ROTL((uint32_t)0x80000001, 1) == 3); - GPR_ASSERT(GPR_ROTR((uint32_t)0x80000001, 1) == 0xc0000000); - GPR_ASSERT(GPR_ARRAY_SIZE(four) == 4); - GPR_ASSERT(GPR_ARRAY_SIZE(five) == 5); - - GPR_ASSERT(GPR_BITCOUNT((1u << 31) - 1) == 31); - GPR_ASSERT(GPR_BITCOUNT(1u << 3) == 1); - GPR_ASSERT(GPR_BITCOUNT(0) == 0); - - GPR_ASSERT(GPR_BITSET(&bitset, 3) == 8); - GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); - GPR_ASSERT(GPR_BITGET(bitset, 3) == 1); - GPR_ASSERT(GPR_BITSET(&bitset, 1) == 10); - GPR_ASSERT(GPR_BITCOUNT(bitset) == 2); - GPR_ASSERT(GPR_BITCLEAR(&bitset, 3) == 2); - GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); - GPR_ASSERT(GPR_BITGET(bitset, 3) == 0); - - return 0; -} diff --git a/test/core/support/useful_test.cc b/test/core/support/useful_test.cc new file mode 100644 index 0000000000..2f84f485fc --- /dev/null +++ b/test/core/support/useful_test.cc @@ -0,0 +1,58 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include "test/core/util/test_config.h" + +int main(int argc, char **argv) { + int four[4]; + int five[5]; + uint32_t bitset = 0; + grpc_test_init(argc, argv); + + GPR_ASSERT(GPR_MIN(1, 2) == 1); + GPR_ASSERT(GPR_MAX(1, 2) == 2); + GPR_ASSERT(GPR_MIN(2, 1) == 1); + GPR_ASSERT(GPR_MAX(2, 1) == 2); + GPR_ASSERT(GPR_CLAMP(1, 0, 2) == 1); + GPR_ASSERT(GPR_CLAMP(0, 0, 2) == 0); + GPR_ASSERT(GPR_CLAMP(2, 0, 2) == 2); + GPR_ASSERT(GPR_CLAMP(-1, 0, 2) == 0); + GPR_ASSERT(GPR_CLAMP(3, 0, 2) == 2); + GPR_ASSERT(GPR_ROTL((uint32_t)0x80000001, 1) == 3); + GPR_ASSERT(GPR_ROTR((uint32_t)0x80000001, 1) == 0xc0000000); + GPR_ASSERT(GPR_ARRAY_SIZE(four) == 4); + GPR_ASSERT(GPR_ARRAY_SIZE(five) == 5); + + GPR_ASSERT(GPR_BITCOUNT((1u << 31) - 1) == 31); + GPR_ASSERT(GPR_BITCOUNT(1u << 3) == 1); + GPR_ASSERT(GPR_BITCOUNT(0) == 0); + + GPR_ASSERT(GPR_BITSET(&bitset, 3) == 8); + GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); + GPR_ASSERT(GPR_BITGET(bitset, 3) == 1); + GPR_ASSERT(GPR_BITSET(&bitset, 1) == 10); + GPR_ASSERT(GPR_BITCOUNT(bitset) == 2); + GPR_ASSERT(GPR_BITCLEAR(&bitset, 3) == 2); + GPR_ASSERT(GPR_BITCOUNT(bitset) == 1); + GPR_ASSERT(GPR_BITGET(bitset, 3) == 0); + + return 0; +} diff --git a/test/core/surface/alarm_test.c b/test/core/surface/alarm_test.c deleted file mode 100644 index 4fd7cb93c6..0000000000 --- a/test/core/surface/alarm_test.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void *create_test_tag(void) { - static intptr_t i = 0; - return (void *)(++i); -} - -/* helper for tests to shutdown correctly and tersely */ -static void shutdown_and_destroy(grpc_completion_queue *cc) { - grpc_event ev; - grpc_completion_queue_shutdown(cc); - ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cc); -} - -static void test_alarm(void) { - grpc_completion_queue *cc; - - LOG_TEST("test_alarm"); - cc = grpc_completion_queue_create_for_next(NULL); - { - /* regular expiry */ - grpc_event ev; - void *tag = create_test_tag(); - grpc_alarm *alarm = grpc_alarm_create(NULL); - grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(1), tag, NULL); - - ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(2), - NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag); - GPR_ASSERT(ev.success); - grpc_alarm_destroy(alarm, NULL); - } - { - /* cancellation */ - grpc_event ev; - void *tag = create_test_tag(); - grpc_alarm *alarm = grpc_alarm_create(NULL); - grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(2), tag, NULL); - - grpc_alarm_cancel(alarm, NULL); - ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1), - NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag); - GPR_ASSERT(ev.success == 0); - grpc_alarm_destroy(alarm, NULL); - } - { - /* alarm_destroy before cq_next */ - grpc_event ev; - void *tag = create_test_tag(); - grpc_alarm *alarm = grpc_alarm_create(NULL); - grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(2), tag, NULL); - - grpc_alarm_destroy(alarm, NULL); - ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1), - NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag); - GPR_ASSERT(ev.success == 0); - } - { - /* alarm_destroy before set */ - grpc_alarm *alarm = grpc_alarm_create(NULL); - grpc_alarm_destroy(alarm, NULL); - } - - shutdown_and_destroy(cc); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_alarm(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/surface/alarm_test.cc b/test/core/surface/alarm_test.cc new file mode 100644 index 0000000000..4fd7cb93c6 --- /dev/null +++ b/test/core/surface/alarm_test.cc @@ -0,0 +1,105 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void *create_test_tag(void) { + static intptr_t i = 0; + return (void *)(++i); +} + +/* helper for tests to shutdown correctly and tersely */ +static void shutdown_and_destroy(grpc_completion_queue *cc) { + grpc_event ev; + grpc_completion_queue_shutdown(cc); + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + +static void test_alarm(void) { + grpc_completion_queue *cc; + + LOG_TEST("test_alarm"); + cc = grpc_completion_queue_create_for_next(NULL); + { + /* regular expiry */ + grpc_event ev; + void *tag = create_test_tag(); + grpc_alarm *alarm = grpc_alarm_create(NULL); + grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(1), tag, NULL); + + ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(2), + NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag); + GPR_ASSERT(ev.success); + grpc_alarm_destroy(alarm, NULL); + } + { + /* cancellation */ + grpc_event ev; + void *tag = create_test_tag(); + grpc_alarm *alarm = grpc_alarm_create(NULL); + grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(2), tag, NULL); + + grpc_alarm_cancel(alarm, NULL); + ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1), + NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag); + GPR_ASSERT(ev.success == 0); + grpc_alarm_destroy(alarm, NULL); + } + { + /* alarm_destroy before cq_next */ + grpc_event ev; + void *tag = create_test_tag(); + grpc_alarm *alarm = grpc_alarm_create(NULL); + grpc_alarm_set(alarm, cc, grpc_timeout_seconds_to_deadline(2), tag, NULL); + + grpc_alarm_destroy(alarm, NULL); + ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1), + NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag); + GPR_ASSERT(ev.success == 0); + } + { + /* alarm_destroy before set */ + grpc_alarm *alarm = grpc_alarm_create(NULL); + grpc_alarm_destroy(alarm, NULL); + } + + shutdown_and_destroy(cc); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_alarm(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c deleted file mode 100644 index a6b4c86abc..0000000000 --- a/test/core/surface/byte_buffer_reader_test.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/compression/message_compress.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/util/test_config.h" - -#include - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void test_read_one_slice(void) { - grpc_slice slice; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - grpc_slice first_slice, second_slice; - int first_code, second_code; - - LOG_TEST("test_read_one_slice"); - slice = grpc_slice_from_copied_string("test"); - buffer = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); - GPR_ASSERT(first_code != 0); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); - grpc_slice_unref(first_slice); - second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); - GPR_ASSERT(second_code == 0); - grpc_byte_buffer_destroy(buffer); -} - -static void test_read_one_slice_malloc(void) { - grpc_slice slice; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - grpc_slice first_slice, second_slice; - int first_code, second_code; - - LOG_TEST("test_read_one_slice_malloc"); - slice = grpc_slice_malloc(4); - memcpy(GRPC_SLICE_START_PTR(slice), "test", 4); - buffer = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); - GPR_ASSERT(first_code != 0); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); - grpc_slice_unref(first_slice); - second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); - GPR_ASSERT(second_code == 0); - grpc_byte_buffer_destroy(buffer); -} - -static void test_read_none_compressed_slice(void) { - grpc_slice slice; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - grpc_slice first_slice, second_slice; - int first_code, second_code; - - LOG_TEST("test_read_none_compressed_slice"); - slice = grpc_slice_from_copied_string("test"); - buffer = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); - GPR_ASSERT(first_code != 0); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); - grpc_slice_unref(first_slice); - second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); - GPR_ASSERT(second_code == 0); - grpc_byte_buffer_destroy(buffer); -} - -static void test_read_corrupted_slice(void) { - grpc_slice slice; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - - LOG_TEST("test_read_corrupted_slice"); - slice = grpc_slice_from_copied_string("test"); - buffer = grpc_raw_byte_buffer_create(&slice, 1); - buffer->data.raw.compression = GRPC_COMPRESS_GZIP; /* lies! */ - grpc_slice_unref(slice); - GPR_ASSERT(!grpc_byte_buffer_reader_init(&reader, buffer)); - grpc_byte_buffer_destroy(buffer); -} - -static void read_compressed_slice(grpc_compression_algorithm algorithm, - size_t input_size) { - grpc_slice input_slice; - grpc_slice_buffer sliceb_in; - grpc_slice_buffer sliceb_out; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - grpc_slice read_slice; - size_t read_count = 0; - - grpc_slice_buffer_init(&sliceb_in); - grpc_slice_buffer_init(&sliceb_out); - - input_slice = grpc_slice_malloc(input_size); - memset(GRPC_SLICE_START_PTR(input_slice), 'a', input_size); - grpc_slice_buffer_add(&sliceb_in, input_slice); /* takes ownership */ - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT( - grpc_msg_compress(&exec_ctx, algorithm, &sliceb_in, &sliceb_out)); - grpc_exec_ctx_finish(&exec_ctx); - } - - buffer = grpc_raw_compressed_byte_buffer_create(sliceb_out.slices, - sliceb_out.count, algorithm); - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - - while (grpc_byte_buffer_reader_next(&reader, &read_slice)) { - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(read_slice), - GRPC_SLICE_START_PTR(input_slice) + read_count, - GRPC_SLICE_LENGTH(read_slice)) == 0); - read_count += GRPC_SLICE_LENGTH(read_slice); - grpc_slice_unref(read_slice); - } - GPR_ASSERT(read_count == input_size); - grpc_byte_buffer_reader_destroy(&reader); - grpc_byte_buffer_destroy(buffer); - grpc_slice_buffer_destroy(&sliceb_out); - grpc_slice_buffer_destroy(&sliceb_in); -} - -static void test_read_gzip_compressed_slice(void) { - const size_t INPUT_SIZE = 2048; - LOG_TEST("test_read_gzip_compressed_slice"); - read_compressed_slice(GRPC_COMPRESS_GZIP, INPUT_SIZE); -} - -static void test_read_deflate_compressed_slice(void) { - const size_t INPUT_SIZE = 2048; - LOG_TEST("test_read_deflate_compressed_slice"); - read_compressed_slice(GRPC_COMPRESS_DEFLATE, INPUT_SIZE); -} - -static void test_byte_buffer_from_reader(void) { - grpc_slice slice; - grpc_byte_buffer *buffer, *buffer_from_reader; - grpc_byte_buffer_reader reader; - - LOG_TEST("test_byte_buffer_from_reader"); - slice = grpc_slice_malloc(4); - memcpy(GRPC_SLICE_START_PTR(slice), "test", 4); - buffer = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - - buffer_from_reader = grpc_raw_byte_buffer_from_reader(&reader); - GPR_ASSERT(buffer->type == buffer_from_reader->type); - GPR_ASSERT(buffer_from_reader->data.raw.compression == GRPC_COMPRESS_NONE); - GPR_ASSERT(buffer_from_reader->data.raw.slice_buffer.count == 1); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR( - buffer_from_reader->data.raw.slice_buffer.slices[0]), - "test", 4) == 0); - - grpc_byte_buffer_destroy(buffer); - grpc_byte_buffer_destroy(buffer_from_reader); -} - -static void test_readall(void) { - char *lotsa_as[512]; - char *lotsa_bs[1024]; - grpc_slice slices[2]; - grpc_byte_buffer *buffer; - grpc_byte_buffer_reader reader; - grpc_slice slice_out; - - LOG_TEST("test_readall"); - - memset(lotsa_as, 'a', 512); - memset(lotsa_bs, 'b', 1024); - /* use slices large enough to overflow inlining */ - slices[0] = grpc_slice_malloc(512); - memcpy(GRPC_SLICE_START_PTR(slices[0]), lotsa_as, 512); - slices[1] = grpc_slice_malloc(1024); - memcpy(GRPC_SLICE_START_PTR(slices[1]), lotsa_bs, 1024); - - buffer = grpc_raw_byte_buffer_create(slices, 2); - grpc_slice_unref(slices[0]); - grpc_slice_unref(slices[1]); - - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - slice_out = grpc_byte_buffer_reader_readall(&reader); - - GPR_ASSERT(GRPC_SLICE_LENGTH(slice_out) == 512 + 1024); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0); - GPR_ASSERT(memcmp(&(GRPC_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) == - 0); - grpc_slice_unref(slice_out); - grpc_byte_buffer_destroy(buffer); -} - -static void test_byte_buffer_copy(void) { - char *lotsa_as[512]; - char *lotsa_bs[1024]; - grpc_slice slices[2]; - grpc_byte_buffer *buffer; - grpc_byte_buffer *copied_buffer; - grpc_byte_buffer_reader reader; - grpc_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] = grpc_slice_malloc(512); - memcpy(GRPC_SLICE_START_PTR(slices[0]), lotsa_as, 512); - slices[1] = grpc_slice_malloc(1024); - memcpy(GRPC_SLICE_START_PTR(slices[1]), lotsa_bs, 1024); - - buffer = grpc_raw_byte_buffer_create(slices, 2); - grpc_slice_unref(slices[0]); - grpc_slice_unref(slices[1]); - copied_buffer = grpc_byte_buffer_copy(buffer); - - GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && - "Couldn't init byte buffer reader"); - slice_out = grpc_byte_buffer_reader_readall(&reader); - - GPR_ASSERT(GRPC_SLICE_LENGTH(slice_out) == 512 + 1024); - GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0); - GPR_ASSERT(memcmp(&(GRPC_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) == - 0); - grpc_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(); - test_read_one_slice_malloc(); - test_read_none_compressed_slice(); - test_read_gzip_compressed_slice(); - test_read_deflate_compressed_slice(); - test_read_corrupted_slice(); - test_byte_buffer_from_reader(); - test_byte_buffer_copy(); - test_readall(); - return 0; -} diff --git a/test/core/surface/byte_buffer_reader_test.cc b/test/core/surface/byte_buffer_reader_test.cc new file mode 100644 index 0000000000..a6b4c86abc --- /dev/null +++ b/test/core/surface/byte_buffer_reader_test.cc @@ -0,0 +1,280 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/compression/message_compress.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/util/test_config.h" + +#include + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void test_read_one_slice(void) { + grpc_slice slice; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + grpc_slice first_slice, second_slice; + int first_code, second_code; + + LOG_TEST("test_read_one_slice"); + slice = grpc_slice_from_copied_string("test"); + buffer = grpc_raw_byte_buffer_create(&slice, 1); + grpc_slice_unref(slice); + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); + GPR_ASSERT(first_code != 0); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); + grpc_slice_unref(first_slice); + second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); + GPR_ASSERT(second_code == 0); + grpc_byte_buffer_destroy(buffer); +} + +static void test_read_one_slice_malloc(void) { + grpc_slice slice; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + grpc_slice first_slice, second_slice; + int first_code, second_code; + + LOG_TEST("test_read_one_slice_malloc"); + slice = grpc_slice_malloc(4); + memcpy(GRPC_SLICE_START_PTR(slice), "test", 4); + buffer = grpc_raw_byte_buffer_create(&slice, 1); + grpc_slice_unref(slice); + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); + GPR_ASSERT(first_code != 0); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); + grpc_slice_unref(first_slice); + second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); + GPR_ASSERT(second_code == 0); + grpc_byte_buffer_destroy(buffer); +} + +static void test_read_none_compressed_slice(void) { + grpc_slice slice; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + grpc_slice first_slice, second_slice; + int first_code, second_code; + + LOG_TEST("test_read_none_compressed_slice"); + slice = grpc_slice_from_copied_string("test"); + buffer = grpc_raw_byte_buffer_create(&slice, 1); + grpc_slice_unref(slice); + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); + GPR_ASSERT(first_code != 0); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(first_slice), "test", 4) == 0); + grpc_slice_unref(first_slice); + second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); + GPR_ASSERT(second_code == 0); + grpc_byte_buffer_destroy(buffer); +} + +static void test_read_corrupted_slice(void) { + grpc_slice slice; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + + LOG_TEST("test_read_corrupted_slice"); + slice = grpc_slice_from_copied_string("test"); + buffer = grpc_raw_byte_buffer_create(&slice, 1); + buffer->data.raw.compression = GRPC_COMPRESS_GZIP; /* lies! */ + grpc_slice_unref(slice); + GPR_ASSERT(!grpc_byte_buffer_reader_init(&reader, buffer)); + grpc_byte_buffer_destroy(buffer); +} + +static void read_compressed_slice(grpc_compression_algorithm algorithm, + size_t input_size) { + grpc_slice input_slice; + grpc_slice_buffer sliceb_in; + grpc_slice_buffer sliceb_out; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + grpc_slice read_slice; + size_t read_count = 0; + + grpc_slice_buffer_init(&sliceb_in); + grpc_slice_buffer_init(&sliceb_out); + + input_slice = grpc_slice_malloc(input_size); + memset(GRPC_SLICE_START_PTR(input_slice), 'a', input_size); + grpc_slice_buffer_add(&sliceb_in, input_slice); /* takes ownership */ + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT( + grpc_msg_compress(&exec_ctx, algorithm, &sliceb_in, &sliceb_out)); + grpc_exec_ctx_finish(&exec_ctx); + } + + buffer = grpc_raw_compressed_byte_buffer_create(sliceb_out.slices, + sliceb_out.count, algorithm); + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + + while (grpc_byte_buffer_reader_next(&reader, &read_slice)) { + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(read_slice), + GRPC_SLICE_START_PTR(input_slice) + read_count, + GRPC_SLICE_LENGTH(read_slice)) == 0); + read_count += GRPC_SLICE_LENGTH(read_slice); + grpc_slice_unref(read_slice); + } + GPR_ASSERT(read_count == input_size); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(buffer); + grpc_slice_buffer_destroy(&sliceb_out); + grpc_slice_buffer_destroy(&sliceb_in); +} + +static void test_read_gzip_compressed_slice(void) { + const size_t INPUT_SIZE = 2048; + LOG_TEST("test_read_gzip_compressed_slice"); + read_compressed_slice(GRPC_COMPRESS_GZIP, INPUT_SIZE); +} + +static void test_read_deflate_compressed_slice(void) { + const size_t INPUT_SIZE = 2048; + LOG_TEST("test_read_deflate_compressed_slice"); + read_compressed_slice(GRPC_COMPRESS_DEFLATE, INPUT_SIZE); +} + +static void test_byte_buffer_from_reader(void) { + grpc_slice slice; + grpc_byte_buffer *buffer, *buffer_from_reader; + grpc_byte_buffer_reader reader; + + LOG_TEST("test_byte_buffer_from_reader"); + slice = grpc_slice_malloc(4); + memcpy(GRPC_SLICE_START_PTR(slice), "test", 4); + buffer = grpc_raw_byte_buffer_create(&slice, 1); + grpc_slice_unref(slice); + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + + buffer_from_reader = grpc_raw_byte_buffer_from_reader(&reader); + GPR_ASSERT(buffer->type == buffer_from_reader->type); + GPR_ASSERT(buffer_from_reader->data.raw.compression == GRPC_COMPRESS_NONE); + GPR_ASSERT(buffer_from_reader->data.raw.slice_buffer.count == 1); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR( + buffer_from_reader->data.raw.slice_buffer.slices[0]), + "test", 4) == 0); + + grpc_byte_buffer_destroy(buffer); + grpc_byte_buffer_destroy(buffer_from_reader); +} + +static void test_readall(void) { + char *lotsa_as[512]; + char *lotsa_bs[1024]; + grpc_slice slices[2]; + grpc_byte_buffer *buffer; + grpc_byte_buffer_reader reader; + grpc_slice slice_out; + + LOG_TEST("test_readall"); + + memset(lotsa_as, 'a', 512); + memset(lotsa_bs, 'b', 1024); + /* use slices large enough to overflow inlining */ + slices[0] = grpc_slice_malloc(512); + memcpy(GRPC_SLICE_START_PTR(slices[0]), lotsa_as, 512); + slices[1] = grpc_slice_malloc(1024); + memcpy(GRPC_SLICE_START_PTR(slices[1]), lotsa_bs, 1024); + + buffer = grpc_raw_byte_buffer_create(slices, 2); + grpc_slice_unref(slices[0]); + grpc_slice_unref(slices[1]); + + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + slice_out = grpc_byte_buffer_reader_readall(&reader); + + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_out) == 512 + 1024); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0); + GPR_ASSERT(memcmp(&(GRPC_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) == + 0); + grpc_slice_unref(slice_out); + grpc_byte_buffer_destroy(buffer); +} + +static void test_byte_buffer_copy(void) { + char *lotsa_as[512]; + char *lotsa_bs[1024]; + grpc_slice slices[2]; + grpc_byte_buffer *buffer; + grpc_byte_buffer *copied_buffer; + grpc_byte_buffer_reader reader; + grpc_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] = grpc_slice_malloc(512); + memcpy(GRPC_SLICE_START_PTR(slices[0]), lotsa_as, 512); + slices[1] = grpc_slice_malloc(1024); + memcpy(GRPC_SLICE_START_PTR(slices[1]), lotsa_bs, 1024); + + buffer = grpc_raw_byte_buffer_create(slices, 2); + grpc_slice_unref(slices[0]); + grpc_slice_unref(slices[1]); + copied_buffer = grpc_byte_buffer_copy(buffer); + + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, buffer) && + "Couldn't init byte buffer reader"); + slice_out = grpc_byte_buffer_reader_readall(&reader); + + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_out) == 512 + 1024); + GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0); + GPR_ASSERT(memcmp(&(GRPC_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) == + 0); + grpc_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(); + test_read_one_slice_malloc(); + test_read_none_compressed_slice(); + test_read_gzip_compressed_slice(); + test_read_deflate_compressed_slice(); + test_read_corrupted_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 deleted file mode 100644 index a6884750e7..0000000000 --- a/test/core/surface/channel_create_test.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include - -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/surface/channel.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); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_element *elem = - grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); - GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_channel_destroy(chan); -} - -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/channel_create_test.cc b/test/core/surface/channel_create_test.cc new file mode 100644 index 0000000000..a6884750e7 --- /dev/null +++ b/test/core/surface/channel_create_test.cc @@ -0,0 +1,53 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/surface/channel.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); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_element *elem = + grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_channel_destroy(chan); +} + +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 deleted file mode 100644 index e6372a379c..0000000000 --- a/test/core/surface/completion_queue_test.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/completion_queue.h" - -#include -#include -#include -#include -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void *create_test_tag(void) { - static intptr_t i = 0; - return (void *)(++i); -} - -/* helper for tests to shutdown correctly and tersely */ -static void shutdown_and_destroy(grpc_completion_queue *cc) { - grpc_event ev; - grpc_completion_queue_shutdown(cc); - - switch (grpc_get_cq_completion_type(cc)) { - case GRPC_CQ_NEXT: { - ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), - NULL); - break; - } - case GRPC_CQ_PLUCK: { - ev = grpc_completion_queue_pluck(cc, create_test_tag(), - gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - break; - } - default: { - gpr_log(GPR_ERROR, "Unknown completion type"); - break; - } - } - - GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cc); -} - -/* ensure we can create and destroy a completion channel */ -static void test_no_op(void) { - grpc_cq_completion_type completion_types[] = {GRPC_CQ_NEXT, GRPC_CQ_PLUCK}; - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue_attributes attr; - LOG_TEST("test_no_op"); - - attr.version = 1; - for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) { - for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) { - attr.cq_completion_type = completion_types[i]; - attr.cq_polling_type = polling_types[j]; - shutdown_and_destroy(grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL)); - } - } -} - -static void test_pollset_conversion(void) { - grpc_cq_completion_type completion_types[] = {GRPC_CQ_NEXT, GRPC_CQ_PLUCK}; - grpc_cq_polling_type polling_types[] = {GRPC_CQ_DEFAULT_POLLING, - GRPC_CQ_NON_LISTENING}; - grpc_completion_queue *cq; - grpc_completion_queue_attributes attr; - - LOG_TEST("test_pollset_conversion"); - - attr.version = 1; - for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) { - for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) { - attr.cq_completion_type = completion_types[i]; - attr.cq_polling_type = polling_types[j]; - cq = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - GPR_ASSERT(grpc_cq_pollset(cq) != NULL); - shutdown_and_destroy(cq); - } - } -} - -static void test_wait_empty(void) { - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue *cc; - grpc_completion_queue_attributes attr; - grpc_event event; - - LOG_TEST("test_wait_empty"); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_NEXT; - for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { - attr.cq_polling_type = polling_types[i]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - event = grpc_completion_queue_next(cc, gpr_now(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); - shutdown_and_destroy(cc); - } -} - -static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, - grpc_cq_completion *c) {} - -static void test_cq_end_op(void) { - grpc_event ev; - grpc_completion_queue *cc; - grpc_cq_completion completion; - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue_attributes attr; - grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_exec_ctx exec_ctx; - void *tag = create_test_tag(); - - LOG_TEST("test_cq_end_op"); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_NEXT; - for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { - exec_ctx = init_exec_ctx; // Reset exec_ctx - attr.cq_polling_type = polling_types[i]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - GPR_ASSERT(grpc_cq_begin_op(cc, tag)); - grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE, - do_nothing_end_completion, NULL, &completion); - - ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == tag); - GPR_ASSERT(ev.success); - - shutdown_and_destroy(cc); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_shutdown_then_next_polling(void) { - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue *cc; - grpc_completion_queue_attributes attr; - grpc_event event; - LOG_TEST("test_shutdown_then_next_polling"); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_NEXT; - for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { - attr.cq_polling_type = polling_types[i]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - grpc_completion_queue_shutdown(cc); - event = - grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(event.type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cc); - } -} - -static void test_shutdown_then_next_with_timeout(void) { - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue *cc; - grpc_completion_queue_attributes attr; - grpc_event event; - LOG_TEST("test_shutdown_then_next_with_timeout"); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_NEXT; - for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { - attr.cq_polling_type = polling_types[i]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - grpc_completion_queue_shutdown(cc); - event = grpc_completion_queue_next(cc, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); - GPR_ASSERT(event.type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cc); - } -} - -static void test_pluck(void) { - grpc_event ev; - grpc_completion_queue *cc; - void *tags[128]; - grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_completion_queue_attributes attr; - grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_exec_ctx exec_ctx; - unsigned i, j; - - LOG_TEST("test_pluck"); - - 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]); - } - } - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_PLUCK; - for (size_t pidx = 0; pidx < GPR_ARRAY_SIZE(polling_types); pidx++) { - exec_ctx = init_exec_ctx; // reset exec_ctx - attr.cq_polling_type = polling_types[pidx]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, NULL); - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); - grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, - do_nothing_end_completion, NULL, &completions[i]); - } - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - ev = grpc_completion_queue_pluck(cc, tags[i], - gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.tag == tags[i]); - } - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); - grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, - do_nothing_end_completion, NULL, &completions[i]); - } - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - ev = grpc_completion_queue_pluck(cc, tags[GPR_ARRAY_SIZE(tags) - i - 1], - gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.tag == tags[GPR_ARRAY_SIZE(tags) - i - 1]); - } - - shutdown_and_destroy(cc); - grpc_exec_ctx_finish(&exec_ctx); - } -} - -static void test_pluck_after_shutdown(void) { - grpc_cq_polling_type polling_types[] = { - GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; - grpc_event ev; - grpc_completion_queue *cc; - grpc_completion_queue_attributes attr; - - LOG_TEST("test_pluck_after_shutdown"); - - attr.version = 1; - attr.cq_completion_type = GRPC_CQ_PLUCK; - for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { - attr.cq_polling_type = polling_types[i]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, 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; -}; - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_no_op(); - test_pollset_conversion(); - test_wait_empty(); - test_shutdown_then_next_polling(); - test_shutdown_then_next_with_timeout(); - test_cq_end_op(); - test_pluck(); - test_pluck_after_shutdown(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/surface/completion_queue_test.cc b/test/core/surface/completion_queue_test.cc new file mode 100644 index 0000000000..e6372a379c --- /dev/null +++ b/test/core/surface/completion_queue_test.cc @@ -0,0 +1,305 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/completion_queue.h" + +#include +#include +#include +#include +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void *create_test_tag(void) { + static intptr_t i = 0; + return (void *)(++i); +} + +/* helper for tests to shutdown correctly and tersely */ +static void shutdown_and_destroy(grpc_completion_queue *cc) { + grpc_event ev; + grpc_completion_queue_shutdown(cc); + + switch (grpc_get_cq_completion_type(cc)) { + case GRPC_CQ_NEXT: { + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), + NULL); + break; + } + case GRPC_CQ_PLUCK: { + ev = grpc_completion_queue_pluck(cc, create_test_tag(), + gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + break; + } + default: { + gpr_log(GPR_ERROR, "Unknown completion type"); + break; + } + } + + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + +/* ensure we can create and destroy a completion channel */ +static void test_no_op(void) { + grpc_cq_completion_type completion_types[] = {GRPC_CQ_NEXT, GRPC_CQ_PLUCK}; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + LOG_TEST("test_no_op"); + + attr.version = 1; + for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) { + for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) { + attr.cq_completion_type = completion_types[i]; + attr.cq_polling_type = polling_types[j]; + shutdown_and_destroy(grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL)); + } + } +} + +static void test_pollset_conversion(void) { + grpc_cq_completion_type completion_types[] = {GRPC_CQ_NEXT, GRPC_CQ_PLUCK}; + grpc_cq_polling_type polling_types[] = {GRPC_CQ_DEFAULT_POLLING, + GRPC_CQ_NON_LISTENING}; + grpc_completion_queue *cq; + grpc_completion_queue_attributes attr; + + LOG_TEST("test_pollset_conversion"); + + attr.version = 1; + for (size_t i = 0; i < GPR_ARRAY_SIZE(completion_types); i++) { + for (size_t j = 0; j < GPR_ARRAY_SIZE(polling_types); j++) { + attr.cq_completion_type = completion_types[i]; + attr.cq_polling_type = polling_types[j]; + cq = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + GPR_ASSERT(grpc_cq_pollset(cq) != NULL); + shutdown_and_destroy(cq); + } + } +} + +static void test_wait_empty(void) { + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue *cc; + grpc_completion_queue_attributes attr; + grpc_event event; + + LOG_TEST("test_wait_empty"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + event = grpc_completion_queue_next(cc, gpr_now(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + shutdown_and_destroy(cc); + } +} + +static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, + grpc_cq_completion *c) {} + +static void test_cq_end_op(void) { + grpc_event ev; + grpc_completion_queue *cc; + grpc_cq_completion completion; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + void *tag = create_test_tag(); + + LOG_TEST("test_cq_end_op"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + exec_ctx = init_exec_ctx; // Reset exec_ctx + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + GPR_ASSERT(grpc_cq_begin_op(cc, tag)); + grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completion); + + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == tag); + GPR_ASSERT(ev.success); + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_shutdown_then_next_polling(void) { + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue *cc; + grpc_completion_queue_attributes attr; + grpc_event event; + LOG_TEST("test_shutdown_then_next_polling"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + grpc_completion_queue_shutdown(cc); + event = + grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(event.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); + } +} + +static void test_shutdown_then_next_with_timeout(void) { + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue *cc; + grpc_completion_queue_attributes attr; + grpc_event event; + LOG_TEST("test_shutdown_then_next_with_timeout"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + grpc_completion_queue_shutdown(cc); + event = grpc_completion_queue_next(cc, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + GPR_ASSERT(event.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); + } +} + +static void test_pluck(void) { + grpc_event ev; + grpc_completion_queue *cc; + void *tags[128]; + grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + unsigned i, j; + + LOG_TEST("test_pluck"); + + 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]); + } + } + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_PLUCK; + for (size_t pidx = 0; pidx < GPR_ARRAY_SIZE(polling_types); pidx++) { + exec_ctx = init_exec_ctx; // reset exec_ctx + attr.cq_polling_type = polling_types[pidx]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); + grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completions[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + ev = grpc_completion_queue_pluck(cc, tags[i], + gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.tag == tags[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); + grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completions[i]); + } + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + ev = grpc_completion_queue_pluck(cc, tags[GPR_ARRAY_SIZE(tags) - i - 1], + gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.tag == tags[GPR_ARRAY_SIZE(tags) - i - 1]); + } + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_pluck_after_shutdown(void) { + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_event ev; + grpc_completion_queue *cc; + grpc_completion_queue_attributes attr; + + LOG_TEST("test_pluck_after_shutdown"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_PLUCK; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, 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; +}; + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_no_op(); + test_pollset_conversion(); + test_wait_empty(); + test_shutdown_then_next_polling(); + test_shutdown_then_next_with_timeout(); + test_cq_end_op(); + test_pluck(); + test_pluck_after_shutdown(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/completion_queue_threading_test.c b/test/core/surface/completion_queue_threading_test.c deleted file mode 100644 index 9996b6b840..0000000000 --- a/test/core/surface/completion_queue_threading_test.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/surface/completion_queue.h" - -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/iomgr.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void *create_test_tag(void) { - static intptr_t i = 0; - return (void *)(++i); -} - -/* helper for tests to shutdown correctly and tersely */ -static void shutdown_and_destroy(grpc_completion_queue *cc) { - grpc_event ev; - grpc_completion_queue_shutdown(cc); - - switch (grpc_get_cq_completion_type(cc)) { - case GRPC_CQ_NEXT: { - ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), - NULL); - break; - } - case GRPC_CQ_PLUCK: { - ev = grpc_completion_queue_pluck(cc, create_test_tag(), - gpr_inf_past(GPR_CLOCK_REALTIME), NULL); - break; - } - default: { - gpr_log(GPR_ERROR, "Unknown completion type"); - break; - } - } - - GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cc); -} - -static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, - grpc_cq_completion *c) {} - -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_for_pluck(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_milliseconds_to_deadline(1000)); - - ev = grpc_completion_queue_pluck(cc, create_test_tag(), - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); - - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); - grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, - 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 { - gpr_event on_started; - gpr_event *phase1; - gpr_event on_phase1_done; - gpr_event *phase2; - gpr_event on_finished; - size_t events_triggered; - int id; - grpc_completion_queue *cc; -} test_thread_options; - -gpr_timespec ten_seconds_time(void) { - return grpc_timeout_seconds_to_deadline(10); -} - -static void free_completion(grpc_exec_ctx *exec_ctx, void *arg, - grpc_cq_completion *completion) { - gpr_free(completion); -} - -static void producer_thread(void *arg) { - test_thread_options *opt = arg; - int i; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - gpr_log(GPR_INFO, "producer %d started", opt->id); - gpr_event_set(&opt->on_started, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); - - gpr_log(GPR_INFO, "producer %d phase 1", opt->id); - for (i = 0; i < TEST_THREAD_EVENTS; i++) { - GPR_ASSERT(grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1)); - } - - gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id); - gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); - - gpr_log(GPR_INFO, "producer %d phase 2", opt->id); - for (i = 0; i < TEST_THREAD_EVENTS; i++) { - grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, GRPC_ERROR_NONE, - free_completion, NULL, - gpr_malloc(sizeof(grpc_cq_completion))); - opt->events_triggered++; - grpc_exec_ctx_finish(&exec_ctx); - } - - gpr_log(GPR_INFO, "producer %d phase 2 done", opt->id); - gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void consumer_thread(void *arg) { - test_thread_options *opt = arg; - grpc_event ev; - - gpr_log(GPR_INFO, "consumer %d started", opt->id); - gpr_event_set(&opt->on_started, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); - - gpr_log(GPR_INFO, "consumer %d phase 1", opt->id); - - gpr_log(GPR_INFO, "consumer %d phase 1 done", opt->id); - gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); - GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); - - gpr_log(GPR_INFO, "consumer %d phase 2", opt->id); - for (;;) { - ev = grpc_completion_queue_next(opt->cc, - gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); - switch (ev.type) { - case GRPC_OP_COMPLETE: - GPR_ASSERT(ev.success); - opt->events_triggered++; - break; - case GRPC_QUEUE_SHUTDOWN: - gpr_log(GPR_INFO, "consumer %d phase 2 done", opt->id); - gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); - return; - case GRPC_QUEUE_TIMEOUT: - gpr_log(GPR_ERROR, "Invalid timeout received"); - abort(); - } - } -} - -static void test_threading(size_t producers, size_t consumers) { - test_thread_options *options = - gpr_malloc((producers + consumers) * sizeof(test_thread_options)); - gpr_event phase1 = GPR_EVENT_INIT; - gpr_event phase2 = GPR_EVENT_INIT; - grpc_completion_queue *cc = grpc_completion_queue_create_for_next(NULL); - size_t i; - size_t total_consumed = 0; - static int optid = 101; - - gpr_log(GPR_INFO, "%s: %" PRIuPTR " producers, %" PRIuPTR " consumers", - "test_threading", producers, consumers); - - /* start all threads: they will wait for phase1 */ - for (i = 0; i < producers + consumers; i++) { - gpr_thd_id id; - gpr_event_init(&options[i].on_started); - gpr_event_init(&options[i].on_phase1_done); - gpr_event_init(&options[i].on_finished); - options[i].phase1 = &phase1; - options[i].phase2 = &phase2; - options[i].events_triggered = 0; - options[i].cc = cc; - options[i].id = optid++; - GPR_ASSERT(gpr_thd_new(&id, - i < producers ? producer_thread : consumer_thread, - options + i, NULL)); - gpr_event_wait(&options[i].on_started, ten_seconds_time()); - } - - /* start phase1: producers will pre-declare all operations they will - complete */ - gpr_log(GPR_INFO, "start phase 1"); - gpr_event_set(&phase1, (void *)(intptr_t)1); - - gpr_log(GPR_INFO, "wait phase 1"); - for (i = 0; i < producers + consumers; i++) { - GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); - } - gpr_log(GPR_INFO, "done phase 1"); - - /* start phase2: operations will complete, and consumers will consume them */ - gpr_log(GPR_INFO, "start phase 2"); - gpr_event_set(&phase2, (void *)(intptr_t)1); - - /* in parallel, we shutdown the completion channel - all events should still - be consumed */ - grpc_completion_queue_shutdown(cc); - - /* join all threads */ - gpr_log(GPR_INFO, "wait phase 2"); - for (i = 0; i < producers + consumers; i++) { - GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); - } - gpr_log(GPR_INFO, "done phase 2"); - - /* destroy the completion channel */ - grpc_completion_queue_destroy(cc); - - /* verify that everything was produced and consumed */ - for (i = 0; i < producers + consumers; i++) { - if (i < producers) { - GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); - } else { - total_consumed += options[i].events_triggered; - } - } - GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); - - gpr_free(options); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_too_many_plucks(); - test_threading(1, 1); - test_threading(1, 10); - test_threading(10, 1); - test_threading(10, 10); - grpc_shutdown(); - return 0; -} diff --git a/test/core/surface/completion_queue_threading_test.cc b/test/core/surface/completion_queue_threading_test.cc new file mode 100644 index 0000000000..abe119789f --- /dev/null +++ b/test/core/surface/completion_queue_threading_test.cc @@ -0,0 +1,294 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/surface/completion_queue.h" + +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void *create_test_tag(void) { + static intptr_t i = 0; + return (void *)(++i); +} + +/* helper for tests to shutdown correctly and tersely */ +static void shutdown_and_destroy(grpc_completion_queue *cc) { + grpc_event ev; + grpc_completion_queue_shutdown(cc); + + switch (grpc_get_cq_completion_type(cc)) { + case GRPC_CQ_NEXT: { + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), + NULL); + break; + } + case GRPC_CQ_PLUCK: { + ev = grpc_completion_queue_pluck(cc, create_test_tag(), + gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + break; + } + default: { + gpr_log(GPR_ERROR, "Unknown completion type"); + break; + } + } + + GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + +static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, + grpc_cq_completion *c) {} + +struct thread_state { + grpc_completion_queue *cc; + void *tag; +}; + +static void pluck_one(void *arg) { + struct thread_state *state = static_cast(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_for_pluck(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_milliseconds_to_deadline(1000)); + + ev = grpc_completion_queue_pluck(cc, create_test_tag(), + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); + grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, + 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 { + gpr_event on_started; + gpr_event *phase1; + gpr_event on_phase1_done; + gpr_event *phase2; + gpr_event on_finished; + size_t events_triggered; + int id; + grpc_completion_queue *cc; +} test_thread_options; + +gpr_timespec ten_seconds_time(void) { + return grpc_timeout_seconds_to_deadline(10); +} + +static void free_completion(grpc_exec_ctx *exec_ctx, void *arg, + grpc_cq_completion *completion) { + gpr_free(completion); +} + +static void producer_thread(void *arg) { + test_thread_options *opt = static_cast(arg); + int i; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + gpr_log(GPR_INFO, "producer %d started", opt->id); + gpr_event_set(&opt->on_started, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); + + gpr_log(GPR_INFO, "producer %d phase 1", opt->id); + for (i = 0; i < TEST_THREAD_EVENTS; i++) { + GPR_ASSERT(grpc_cq_begin_op(opt->cc, (void *)(intptr_t)1)); + } + + gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id); + gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); + + gpr_log(GPR_INFO, "producer %d phase 2", opt->id); + for (i = 0; i < TEST_THREAD_EVENTS; i++) { + grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, GRPC_ERROR_NONE, + free_completion, NULL, + static_cast( + gpr_malloc(sizeof(grpc_cq_completion)))); + opt->events_triggered++; + grpc_exec_ctx_finish(&exec_ctx); + } + + gpr_log(GPR_INFO, "producer %d phase 2 done", opt->id); + gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void consumer_thread(void *arg) { + test_thread_options *opt = static_cast(arg); + grpc_event ev; + + gpr_log(GPR_INFO, "consumer %d started", opt->id); + gpr_event_set(&opt->on_started, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase1, ten_seconds_time())); + + gpr_log(GPR_INFO, "consumer %d phase 1", opt->id); + + gpr_log(GPR_INFO, "consumer %d phase 1 done", opt->id); + gpr_event_set(&opt->on_phase1_done, (void *)(intptr_t)1); + GPR_ASSERT(gpr_event_wait(opt->phase2, ten_seconds_time())); + + gpr_log(GPR_INFO, "consumer %d phase 2", opt->id); + for (;;) { + ev = grpc_completion_queue_next(opt->cc, + gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); + switch (ev.type) { + case GRPC_OP_COMPLETE: + GPR_ASSERT(ev.success); + opt->events_triggered++; + break; + case GRPC_QUEUE_SHUTDOWN: + gpr_log(GPR_INFO, "consumer %d phase 2 done", opt->id); + gpr_event_set(&opt->on_finished, (void *)(intptr_t)1); + return; + case GRPC_QUEUE_TIMEOUT: + gpr_log(GPR_ERROR, "Invalid timeout received"); + abort(); + } + } +} + +static void test_threading(size_t producers, size_t consumers) { + test_thread_options *options = static_cast( + gpr_malloc((producers + consumers) * sizeof(test_thread_options))); + gpr_event phase1 = GPR_EVENT_INIT; + gpr_event phase2 = GPR_EVENT_INIT; + grpc_completion_queue *cc = grpc_completion_queue_create_for_next(NULL); + size_t i; + size_t total_consumed = 0; + static int optid = 101; + + gpr_log(GPR_INFO, "%s: %" PRIuPTR " producers, %" PRIuPTR " consumers", + "test_threading", producers, consumers); + + /* start all threads: they will wait for phase1 */ + for (i = 0; i < producers + consumers; i++) { + gpr_thd_id id; + gpr_event_init(&options[i].on_started); + gpr_event_init(&options[i].on_phase1_done); + gpr_event_init(&options[i].on_finished); + options[i].phase1 = &phase1; + options[i].phase2 = &phase2; + options[i].events_triggered = 0; + options[i].cc = cc; + options[i].id = optid++; + GPR_ASSERT(gpr_thd_new(&id, + i < producers ? producer_thread : consumer_thread, + options + i, NULL)); + gpr_event_wait(&options[i].on_started, ten_seconds_time()); + } + + /* start phase1: producers will pre-declare all operations they will + complete */ + gpr_log(GPR_INFO, "start phase 1"); + gpr_event_set(&phase1, (void *)(intptr_t)1); + + gpr_log(GPR_INFO, "wait phase 1"); + for (i = 0; i < producers + consumers; i++) { + GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); + } + gpr_log(GPR_INFO, "done phase 1"); + + /* start phase2: operations will complete, and consumers will consume them */ + gpr_log(GPR_INFO, "start phase 2"); + gpr_event_set(&phase2, (void *)(intptr_t)1); + + /* in parallel, we shutdown the completion channel - all events should still + be consumed */ + grpc_completion_queue_shutdown(cc); + + /* join all threads */ + gpr_log(GPR_INFO, "wait phase 2"); + for (i = 0; i < producers + consumers; i++) { + GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); + } + gpr_log(GPR_INFO, "done phase 2"); + + /* destroy the completion channel */ + grpc_completion_queue_destroy(cc); + + /* verify that everything was produced and consumed */ + for (i = 0; i < producers + consumers; i++) { + if (i < producers) { + GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); + } else { + total_consumed += options[i].events_triggered; + } + } + GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); + + gpr_free(options); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_too_many_plucks(); + test_threading(1, 1); + test_threading(1, 10); + test_threading(10, 1); + test_threading(10, 10); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c deleted file mode 100644 index 3595885ff6..0000000000 --- a/test/core/surface/concurrent_connectivity_test.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/tcp_server.h" - -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#define NUM_THREADS 100 -#define NUM_OUTER_LOOPS 10 -#define NUM_INNER_LOOPS 10 -#define DELAY_MILLIS 10 -#define POLL_MILLIS 3000 - -#define NUM_OUTER_LOOPS_SHORT_TIMEOUTS 10 -#define NUM_INNER_LOOPS_SHORT_TIMEOUTS 100 -#define DELAY_MILLIS_SHORT_TIMEOUTS 1 -// in a successful test run, POLL_MILLIS should never be reached beause all runs -// should -// end after the shorter delay_millis -#define POLL_MILLIS_SHORT_TIMEOUTS 30000 - -static void *tag(int n) { return (void *)(uintptr_t)n; } -static int detag(void *p) { return (int)(uintptr_t)p; } - -void create_loop_destroy(void *addr) { - for (int i = 0; i < NUM_OUTER_LOOPS; ++i) { - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); - - for (int j = 0; j < NUM_INNER_LOOPS; ++j) { - gpr_timespec later_time = - grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS); - grpc_connectivity_state state = - grpc_channel_check_connectivity_state(chan, 1); - grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); - gpr_timespec poll_time = - grpc_timeout_milliseconds_to_deadline(POLL_MILLIS); - GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type == - GRPC_OP_COMPLETE); - /* check that the watcher from "watch state" was free'd */ - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); - } - grpc_channel_destroy(chan); - grpc_completion_queue_destroy(cq); - } -} - -struct server_thread_args { - char *addr; - grpc_server *server; - grpc_completion_queue *cq; - grpc_pollset *pollset; - gpr_mu *mu; - gpr_event ready; - gpr_atm stop; -}; - -void server_thread(void *vargs) { - struct server_thread_args *args = (struct server_thread_args *)vargs; - grpc_event ev; - gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); - ev = grpc_completion_queue_next(args->cq, deadline, NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(detag(ev.tag) == 0xd1e); -} - -static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp, - grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - gpr_free(acceptor); - struct server_thread_args *args = (struct server_thread_args *)vargs; - grpc_endpoint_shutdown(exec_ctx, tcp, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); - grpc_endpoint_destroy(exec_ctx, tcp); - gpr_mu_lock(args->mu); - GRPC_LOG_IF_ERROR("pollset_kick", - grpc_pollset_kick(exec_ctx, args->pollset, NULL)); - gpr_mu_unlock(args->mu); -} - -void bad_server_thread(void *vargs) { - struct server_thread_args *args = (struct server_thread_args *)vargs; - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_resolved_address resolved_addr; - struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; - int port; - grpc_tcp_server *s; - grpc_error *error = grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s); - GPR_ASSERT(error == GRPC_ERROR_NONE); - memset(&resolved_addr, 0, sizeof(resolved_addr)); - addr->ss_family = AF_INET; - error = grpc_tcp_server_add_port(s, &resolved_addr, &port); - GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error)); - GPR_ASSERT(port > 0); - gpr_asprintf(&args->addr, "localhost:%d", port); - - grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); - gpr_event_set(&args->ready, (void *)1); - - gpr_mu_lock(args->mu); - while (gpr_atm_acq_load(&args->stop) == 0) { - grpc_millis deadline = grpc_exec_ctx_now(&exec_ctx) + 100; - - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, args->pollset, &worker, deadline))) { - gpr_atm_rel_store(&args->stop, 1); - } - gpr_mu_unlock(args->mu); - grpc_exec_ctx_finish(&exec_ctx); - gpr_mu_lock(args->mu); - } - gpr_mu_unlock(args->mu); - - grpc_tcp_server_unref(&exec_ctx, s); - - grpc_exec_ctx_finish(&exec_ctx); - - gpr_free(args->addr); -} - -static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, pollset); - gpr_free(pollset); -} - -int run_concurrent_connectivity_test() { - struct server_thread_args args; - memset(&args, 0, sizeof(args)); - - grpc_init(); - - gpr_thd_id threads[NUM_THREADS]; - gpr_thd_id server; - - char *localhost = gpr_strdup("localhost:54321"); - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - - /* First round, no server */ - gpr_log(GPR_DEBUG, "Wave 1"); - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options); - } - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_join(threads[i]); - } - gpr_free(localhost); - - /* Second round, actual grpc server */ - gpr_log(GPR_DEBUG, "Wave 2"); - int port = grpc_pick_unused_port_or_die(); - gpr_asprintf(&args.addr, "localhost:%d", port); - args.server = grpc_server_create(NULL, NULL); - grpc_server_add_insecure_http2_port(args.server, args.addr); - args.cq = grpc_completion_queue_create_for_next(NULL); - grpc_server_register_completion_queue(args.server, args.cq, NULL); - grpc_server_start(args.server); - gpr_thd_new(&server, server_thread, &args, &options); - - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); - } - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_join(threads[i]); - } - grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e)); - - gpr_thd_join(server); - grpc_server_destroy(args.server); - grpc_completion_queue_destroy(args.cq); - gpr_free(args.addr); - - /* Third round, bogus tcp server */ - gpr_log(GPR_DEBUG, "Wave 3"); - args.pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(args.pollset, &args.mu); - gpr_event_init(&args.ready); - gpr_thd_new(&server, bad_server_thread, &args, &options); - gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); - } - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_join(threads[i]); - } - - gpr_atm_rel_store(&args.stop, 1); - gpr_thd_join(server); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_pollset_shutdown(&exec_ctx, args.pollset, - GRPC_CLOSURE_CREATE(done_pollset_shutdown, args.pollset, - grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_finish(&exec_ctx); - - grpc_shutdown(); - return 0; -} - -void watches_with_short_timeouts(void *addr) { - for (int i = 0; i < NUM_OUTER_LOOPS_SHORT_TIMEOUTS; ++i) { - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); - - for (int j = 0; j < NUM_INNER_LOOPS_SHORT_TIMEOUTS; ++j) { - gpr_timespec later_time = - grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS_SHORT_TIMEOUTS); - grpc_connectivity_state state = - grpc_channel_check_connectivity_state(chan, 0); - GPR_ASSERT(state == GRPC_CHANNEL_IDLE); - grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); - gpr_timespec poll_time = - grpc_timeout_milliseconds_to_deadline(POLL_MILLIS_SHORT_TIMEOUTS); - grpc_event ev = grpc_completion_queue_next(cq, poll_time, NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.success == false); - /* check that the watcher from "watch state" was free'd */ - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); - } - grpc_channel_destroy(chan); - grpc_completion_queue_destroy(cq); - } -} - -// This test tries to catch deadlock situations. -// With short timeouts on "watches" and long timeouts on cq next calls, -// so that a QUEUE_TIMEOUT likely means that something is stuck. -int run_concurrent_watches_with_short_timeouts_test() { - grpc_init(); - - gpr_thd_id threads[NUM_THREADS]; - - char *localhost = gpr_strdup("localhost:54321"); - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(&threads[i], watches_with_short_timeouts, localhost, &options); - } - for (size_t i = 0; i < NUM_THREADS; ++i) { - gpr_thd_join(threads[i]); - } - gpr_free(localhost); - - grpc_shutdown(); - return 0; -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - run_concurrent_connectivity_test(); - run_concurrent_watches_with_short_timeouts_test(); -} diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc new file mode 100644 index 0000000000..303180c0d1 --- /dev/null +++ b/test/core/surface/concurrent_connectivity_test.cc @@ -0,0 +1,293 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/tcp_server.h" + +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define NUM_THREADS 100 +#define NUM_OUTER_LOOPS 10 +#define NUM_INNER_LOOPS 10 +#define DELAY_MILLIS 10 +#define POLL_MILLIS 3000 + +#define NUM_OUTER_LOOPS_SHORT_TIMEOUTS 10 +#define NUM_INNER_LOOPS_SHORT_TIMEOUTS 100 +#define DELAY_MILLIS_SHORT_TIMEOUTS 1 +// in a successful test run, POLL_MILLIS should never be reached beause all runs +// should +// end after the shorter delay_millis +#define POLL_MILLIS_SHORT_TIMEOUTS 30000 + +static void *tag(int n) { return (void *)(uintptr_t)n; } +static int detag(void *p) { return (int)(uintptr_t)p; } + +void create_loop_destroy(void *addr) { + for (int i = 0; i < NUM_OUTER_LOOPS; ++i) { + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); + + for (int j = 0; j < NUM_INNER_LOOPS; ++j) { + gpr_timespec later_time = + grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS); + grpc_connectivity_state state = + grpc_channel_check_connectivity_state(chan, 1); + grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); + gpr_timespec poll_time = + grpc_timeout_milliseconds_to_deadline(POLL_MILLIS); + GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type == + GRPC_OP_COMPLETE); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); + } + grpc_channel_destroy(chan); + grpc_completion_queue_destroy(cq); + } +} + +struct server_thread_args { + char *addr; + grpc_server *server; + grpc_completion_queue *cq; + grpc_pollset *pollset; + gpr_mu *mu; + gpr_event ready; + gpr_atm stop; +}; + +void server_thread(void *vargs) { + struct server_thread_args *args = (struct server_thread_args *)vargs; + grpc_event ev; + gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); + ev = grpc_completion_queue_next(args->cq, deadline, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(detag(ev.tag) == 0xd1e); +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp, + grpc_pollset *accepting_pollset, + grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); + struct server_thread_args *args = (struct server_thread_args *)vargs; + grpc_endpoint_shutdown(exec_ctx, tcp, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); + grpc_endpoint_destroy(exec_ctx, tcp); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", + grpc_pollset_kick(exec_ctx, args->pollset, NULL)); + gpr_mu_unlock(args->mu); +} + +void bad_server_thread(void *vargs) { + struct server_thread_args *args = (struct server_thread_args *)vargs; + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_resolved_address resolved_addr; + struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; + int port; + grpc_tcp_server *s; + grpc_error *error = grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s); + GPR_ASSERT(error == GRPC_ERROR_NONE); + memset(&resolved_addr, 0, sizeof(resolved_addr)); + addr->ss_family = AF_INET; + error = grpc_tcp_server_add_port(s, &resolved_addr, &port); + GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error)); + GPR_ASSERT(port > 0); + gpr_asprintf(&args->addr, "localhost:%d", port); + + grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); + gpr_event_set(&args->ready, (void *)1); + + gpr_mu_lock(args->mu); + while (gpr_atm_acq_load(&args->stop) == 0) { + grpc_millis deadline = grpc_exec_ctx_now(&exec_ctx) + 100; + + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, args->pollset, &worker, deadline))) { + gpr_atm_rel_store(&args->stop, 1); + } + gpr_mu_unlock(args->mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(args->mu); + } + gpr_mu_unlock(args->mu); + + grpc_tcp_server_unref(&exec_ctx, s); + + grpc_exec_ctx_finish(&exec_ctx); + + gpr_free(args->addr); +} + +static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(pollset)); + gpr_free(pollset); +} + +int run_concurrent_connectivity_test() { + struct server_thread_args args; + memset(&args, 0, sizeof(args)); + + grpc_init(); + + gpr_thd_id threads[NUM_THREADS]; + gpr_thd_id server; + + char *localhost = gpr_strdup("localhost:54321"); + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + + /* First round, no server */ + gpr_log(GPR_DEBUG, "Wave 1"); + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options); + } + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_join(threads[i]); + } + gpr_free(localhost); + + /* Second round, actual grpc server */ + gpr_log(GPR_DEBUG, "Wave 2"); + int port = grpc_pick_unused_port_or_die(); + gpr_asprintf(&args.addr, "localhost:%d", port); + args.server = grpc_server_create(NULL, NULL); + grpc_server_add_insecure_http2_port(args.server, args.addr); + args.cq = grpc_completion_queue_create_for_next(NULL); + grpc_server_register_completion_queue(args.server, args.cq, NULL); + grpc_server_start(args.server); + gpr_thd_new(&server, server_thread, &args, &options); + + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); + } + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_join(threads[i]); + } + grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e)); + + gpr_thd_join(server); + grpc_server_destroy(args.server); + grpc_completion_queue_destroy(args.cq); + gpr_free(args.addr); + + /* Third round, bogus tcp server */ + gpr_log(GPR_DEBUG, "Wave 3"); + args.pollset = static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(args.pollset, &args.mu); + gpr_event_init(&args.ready); + gpr_thd_new(&server, bad_server_thread, &args, &options); + gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); + } + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_join(threads[i]); + } + + gpr_atm_rel_store(&args.stop, 1); + gpr_thd_join(server); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_pollset_shutdown(&exec_ctx, args.pollset, + GRPC_CLOSURE_CREATE(done_pollset_shutdown, args.pollset, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + + grpc_shutdown(); + return 0; +} + +void watches_with_short_timeouts(void *addr) { + for (int i = 0; i < NUM_OUTER_LOOPS_SHORT_TIMEOUTS; ++i) { + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); + + for (int j = 0; j < NUM_INNER_LOOPS_SHORT_TIMEOUTS; ++j) { + gpr_timespec later_time = + grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS_SHORT_TIMEOUTS); + grpc_connectivity_state state = + grpc_channel_check_connectivity_state(chan, 0); + GPR_ASSERT(state == GRPC_CHANNEL_IDLE); + grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); + gpr_timespec poll_time = + grpc_timeout_milliseconds_to_deadline(POLL_MILLIS_SHORT_TIMEOUTS); + grpc_event ev = grpc_completion_queue_next(cq, poll_time, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.success == false); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); + } + grpc_channel_destroy(chan); + grpc_completion_queue_destroy(cq); + } +} + +// This test tries to catch deadlock situations. +// With short timeouts on "watches" and long timeouts on cq next calls, +// so that a QUEUE_TIMEOUT likely means that something is stuck. +int run_concurrent_watches_with_short_timeouts_test() { + grpc_init(); + + gpr_thd_id threads[NUM_THREADS]; + + char *localhost = gpr_strdup("localhost:54321"); + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(&threads[i], watches_with_short_timeouts, localhost, &options); + } + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_join(threads[i]); + } + gpr_free(localhost); + + grpc_shutdown(); + return 0; +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + run_concurrent_connectivity_test(); + run_concurrent_watches_with_short_timeouts_test(); +} diff --git a/test/core/surface/init_test.c b/test/core/surface/init_test.c deleted file mode 100644 index b835a2a884..0000000000 --- a/test/core/surface/init_test.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#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); -} - -static void test_repeatedly() { - for (int i = 0; i < 1000; i++) { - grpc_init(); - grpc_shutdown(); - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test(1); - test(2); - test(3); - test_mixed(); - test_plugin(); - test_repeatedly(); - return 0; -} diff --git a/test/core/surface/init_test.cc b/test/core/surface/init_test.cc new file mode 100644 index 0000000000..b835a2a884 --- /dev/null +++ b/test/core/surface/init_test.cc @@ -0,0 +1,71 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#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); +} + +static void test_repeatedly() { + for (int i = 0; i < 1000; i++) { + grpc_init(); + grpc_shutdown(); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test(1); + test(2); + test(3); + test_mixed(); + test_plugin(); + test_repeatedly(); + return 0; +} diff --git a/test/core/surface/invalid_channel_args_test.c b/test/core/surface/invalid_channel_args_test.c deleted file mode 100644 index 9c84c30f03..0000000000 --- a/test/core/surface/invalid_channel_args_test.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -static char *g_last_log_error_message = NULL; -static const char *g_file_name = "channel.cc"; - -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_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_default_authority_type(); - test_ssl_name_override_type(); - test_ssl_name_override_failed(); - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/surface/invalid_channel_args_test.cc b/test/core/surface/invalid_channel_args_test.cc new file mode 100644 index 0000000000..e6099d4fca --- /dev/null +++ b/test/core/surface/invalid_channel_args_test.cc @@ -0,0 +1,137 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +static char *g_last_log_error_message = NULL; +static const char *g_file_name = "channel.cc"; + +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_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 = const_cast(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 = const_cast(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 = const_cast(GRPC_ARG_DEFAULT_AUTHORITY); + client_arg[0].value.string = const_cast("default"); + client_arg[1].type = GRPC_ARG_STRING; + client_arg[1].key = const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); + client_arg[1].value.string = const_cast("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_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 deleted file mode 100644 index f623e1a743..0000000000 --- a/test/core/surface/lame_client_test.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/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(intptr_t x) { return (void *)x; } - -void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_connectivity_state *state = arg; - GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state); - GPR_ASSERT(error == GRPC_ERROR_NONE); -} - -void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} - -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; - - GRPC_CLOSURE_INIT(&transport_op_cb, verify_connectivity, &state, - grpc_schedule_on_exec_ctx); - - op = grpc_make_transport_op(NULL); - 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); - - GRPC_CLOSURE_INIT(&transport_op_cb, do_nothing, NULL, - grpc_schedule_on_exec_ctx); - op = grpc_make_transport_op(&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; - grpc_completion_queue *cq; - 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; - grpc_slice details; - 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_SHUTDOWN == - grpc_channel_check_connectivity_state(chan, 0)); - - cq = grpc_completion_queue_create_for_next(NULL); - - grpc_slice host = grpc_slice_from_static_string("anywhere"); - call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, - grpc_slice_from_static_string("/Foo"), &host, - grpc_timeout_seconds_to_deadline(100), NULL); - GPR_ASSERT(call); - cqv = cq_verifier_create(cq); - - memset(ops, 0, sizeof(ops)); - 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_INITIAL_METADATA; - op->data.recv_initial_metadata.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); - - memset(ops, 0, sizeof(ops)); - 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->flags = 0; - op->reserved = NULL; - op++; - 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(2), 1); - cq_verify(cqv); - - peer = grpc_call_get_peer(call); - GPR_ASSERT(strcmp(peer, "lampoon:national") == 0); - gpr_free(peer); - - grpc_call_unref(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); - grpc_slice_unref(details); - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc new file mode 100644 index 0000000000..6d563d2f1f --- /dev/null +++ b/test/core/surface/lame_client_test.cc @@ -0,0 +1,156 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/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(intptr_t x) { return (void *)x; } + +void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_connectivity_state *state = static_cast(arg); + GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state); + GPR_ASSERT(error == GRPC_ERROR_NONE); +} + +void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} + +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; + + GRPC_CLOSURE_INIT(&transport_op_cb, verify_connectivity, &state, + grpc_schedule_on_exec_ctx); + + op = grpc_make_transport_op(NULL); + 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); + + GRPC_CLOSURE_INIT(&transport_op_cb, do_nothing, NULL, + grpc_schedule_on_exec_ctx); + op = grpc_make_transport_op(&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; + grpc_completion_queue *cq; + 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; + grpc_slice details; + 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_SHUTDOWN == + grpc_channel_check_connectivity_state(chan, 0)); + + cq = grpc_completion_queue_create_for_next(NULL); + + grpc_slice host = grpc_slice_from_static_string("anywhere"); + call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, + grpc_slice_from_static_string("/Foo"), &host, + grpc_timeout_seconds_to_deadline(100), NULL); + GPR_ASSERT(call); + cqv = cq_verifier_create(cq); + + memset(ops, 0, sizeof(ops)); + 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_INITIAL_METADATA; + op->data.recv_initial_metadata.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); + + memset(ops, 0, sizeof(ops)); + 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->flags = 0; + op->reserved = NULL; + op++; + 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(2), 1); + cq_verify(cqv); + + peer = grpc_call_get_peer(call); + GPR_ASSERT(strcmp(peer, "lampoon:national") == 0); + gpr_free(peer); + + grpc_call_unref(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); + grpc_slice_unref(details); + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/surface/num_external_connectivity_watchers_test.c b/test/core/surface/num_external_connectivity_watchers_test.c deleted file mode 100644 index 16401bb7ac..0000000000 --- a/test/core/surface/num_external_connectivity_watchers_test.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct test_fixture { - const char *name; - grpc_channel *(*create_channel)(const char *addr); -} test_fixture; - -static size_t next_tag = 1; - -static void channel_idle_start_watch(grpc_channel *channel, - grpc_completion_queue *cq) { - gpr_timespec connect_deadline = grpc_timeout_milliseconds_to_deadline(1); - GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == - GRPC_CHANNEL_IDLE); - - grpc_channel_watch_connectivity_state( - channel, GRPC_CHANNEL_IDLE, connect_deadline, cq, (void *)(next_tag++)); - gpr_log(GPR_DEBUG, "number of active connect watchers: %d", - grpc_channel_num_external_connectivity_watchers(channel)); -} - -static void channel_idle_poll_for_timeout(grpc_channel *channel, - grpc_completion_queue *cq) { - grpc_event ev = - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - - /* expect watch_connectivity_state to end with a timeout */ - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.success == false); - GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == - GRPC_CHANNEL_IDLE); -} - -/* Test and use the "num_external_watchers" call to make sure - * that "connectivity watcher" structs are free'd just after, if - * their corresponding timeouts occur. */ -static void run_timeouts_test(const test_fixture *fixture) { - gpr_log(GPR_INFO, "TEST: %s", fixture->name); - - char *addr; - - grpc_init(); - - gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); - - grpc_channel *channel = fixture->create_channel(addr); - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - /* start 1 watcher and then let it time out */ - channel_idle_start_watch(channel, cq); - channel_idle_poll_for_timeout(channel, cq); - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); - - /* start 3 watchers and then let them all time out */ - for (size_t i = 1; i <= 3; i++) { - channel_idle_start_watch(channel, cq); - } - for (size_t i = 1; i <= 3; i++) { - channel_idle_poll_for_timeout(channel, cq); - } - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); - - /* start 3 watchers, see one time out, start another 3, and then see them all - * time out */ - for (size_t i = 1; i <= 3; i++) { - channel_idle_start_watch(channel, cq); - } - channel_idle_poll_for_timeout(channel, cq); - for (size_t i = 3; i <= 5; i++) { - channel_idle_start_watch(channel, cq); - } - for (size_t i = 1; i <= 5; i++) { - channel_idle_poll_for_timeout(channel, cq); - } - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); - - grpc_channel_destroy(channel); - grpc_completion_queue_shutdown(cq); - GPR_ASSERT( - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cq); - - grpc_shutdown(); - gpr_free(addr); -} - -/* An edge scenario; sets channel state to explicitly, and outside - * of a polling call. */ -static void run_channel_shutdown_before_timeout_test( - const test_fixture *fixture) { - gpr_log(GPR_INFO, "TEST: %s", fixture->name); - - char *addr; - - grpc_init(); - - gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); - - grpc_channel *channel = fixture->create_channel(addr); - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - /* start 1 watcher and then shut down the channel before the timer goes off */ - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); - - /* expecting a 30 second timeout to go off much later than the shutdown. */ - gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30); - GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == - GRPC_CHANNEL_IDLE); - - grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE, - connect_deadline, cq, (void *)1); - grpc_channel_destroy(channel); - - grpc_event ev = - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - /* expect success with a state transition to CHANNEL_SHUTDOWN */ - GPR_ASSERT(ev.success == true); - - grpc_completion_queue_shutdown(cq); - GPR_ASSERT( - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cq); - - grpc_shutdown(); - gpr_free(addr); -} - -static grpc_channel *insecure_test_create_channel(const char *addr) { - return grpc_insecure_channel_create(addr, NULL, NULL); -} - -static const test_fixture insecure_test = { - "insecure", insecure_test_create_channel, -}; - -static grpc_channel *secure_test_create_channel(const char *addr) { - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1); - grpc_channel *channel = - grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_channel_credentials_release(ssl_creds); - return channel; -} - -static const test_fixture secure_test = { - "secure", secure_test_create_channel, -}; - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - run_timeouts_test(&insecure_test); - run_timeouts_test(&secure_test); - - run_channel_shutdown_before_timeout_test(&insecure_test); - run_channel_shutdown_before_timeout_test(&secure_test); -} diff --git a/test/core/surface/num_external_connectivity_watchers_test.cc b/test/core/surface/num_external_connectivity_watchers_test.cc new file mode 100644 index 0000000000..f5f09b38e2 --- /dev/null +++ b/test/core/surface/num_external_connectivity_watchers_test.cc @@ -0,0 +1,200 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct test_fixture { + const char *name; + grpc_channel *(*create_channel)(const char *addr); +} test_fixture; + +static size_t next_tag = 1; + +static void channel_idle_start_watch(grpc_channel *channel, + grpc_completion_queue *cq) { + gpr_timespec connect_deadline = grpc_timeout_milliseconds_to_deadline(1); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); + + grpc_channel_watch_connectivity_state( + channel, GRPC_CHANNEL_IDLE, connect_deadline, cq, (void *)(next_tag++)); + gpr_log(GPR_DEBUG, "number of active connect watchers: %d", + grpc_channel_num_external_connectivity_watchers(channel)); +} + +static void channel_idle_poll_for_timeout(grpc_channel *channel, + grpc_completion_queue *cq) { + grpc_event ev = + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + /* expect watch_connectivity_state to end with a timeout */ + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.success == false); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); +} + +/* Test and use the "num_external_watchers" call to make sure + * that "connectivity watcher" structs are free'd just after, if + * their corresponding timeouts occur. */ +static void run_timeouts_test(const test_fixture *fixture) { + gpr_log(GPR_INFO, "TEST: %s", fixture->name); + + char *addr; + + grpc_init(); + + gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); + + grpc_channel *channel = fixture->create_channel(addr); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + /* start 1 watcher and then let it time out */ + channel_idle_start_watch(channel, cq); + channel_idle_poll_for_timeout(channel, cq); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* start 3 watchers and then let them all time out */ + for (size_t i = 1; i <= 3; i++) { + channel_idle_start_watch(channel, cq); + } + for (size_t i = 1; i <= 3; i++) { + channel_idle_poll_for_timeout(channel, cq); + } + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* start 3 watchers, see one time out, start another 3, and then see them all + * time out */ + for (size_t i = 1; i <= 3; i++) { + channel_idle_start_watch(channel, cq); + } + channel_idle_poll_for_timeout(channel, cq); + for (size_t i = 3; i <= 5; i++) { + channel_idle_start_watch(channel, cq); + } + for (size_t i = 1; i <= 5; i++) { + channel_idle_poll_for_timeout(channel, cq); + } + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + GPR_ASSERT( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_free(addr); +} + +/* An edge scenario; sets channel state to explicitly, and outside + * of a polling call. */ +static void run_channel_shutdown_before_timeout_test( + const test_fixture *fixture) { + gpr_log(GPR_INFO, "TEST: %s", fixture->name); + + char *addr; + + grpc_init(); + + gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); + + grpc_channel *channel = fixture->create_channel(addr); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + /* start 1 watcher and then shut down the channel before the timer goes off */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* expecting a 30 second timeout to go off much later than the shutdown. */ + gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); + + grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE, + connect_deadline, cq, (void *)1); + grpc_channel_destroy(channel); + + grpc_event ev = + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + /* expect success with a state transition to CHANNEL_SHUTDOWN */ + GPR_ASSERT(ev.success == true); + + grpc_completion_queue_shutdown(cq); + GPR_ASSERT( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_free(addr); +} + +static grpc_channel *insecure_test_create_channel(const char *addr) { + return grpc_insecure_channel_create(addr, NULL, NULL); +} + +static const test_fixture insecure_test = { + "insecure", insecure_test_create_channel, +}; + +static grpc_channel *secure_test_create_channel(const char *addr) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1); + grpc_channel *channel = + grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_channel_credentials_release(ssl_creds); + return channel; +} + +static const test_fixture secure_test = { + "secure", secure_test_create_channel, +}; + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + run_timeouts_test(&insecure_test); + run_timeouts_test(&secure_test); + + run_channel_shutdown_before_timeout_test(&insecure_test); + run_channel_shutdown_before_timeout_test(&secure_test); +} diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c deleted file mode 100644 index 0c45135501..0000000000 --- a/test/core/surface/secure_channel_create_test.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include "src/core/ext/filters/client_channel/resolver_registry.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/core/lib/security/transport/security_connector.h" -#include "src/core/lib/surface/channel.h" -#include "test/core/util/test_config.h" - -void test_unknown_scheme_target(void) { - grpc_resolver_registry_shutdown(); - grpc_resolver_registry_init(); - grpc_channel_credentials *creds = - grpc_fake_transport_security_credentials_create(); - grpc_channel *chan = - grpc_secure_channel_create(creds, "blah://blah", NULL, NULL); - grpc_channel_element *elem = - grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); - GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); - grpc_channel_credentials_unref(&exec_ctx, creds); - grpc_exec_ctx_finish(&exec_ctx); -} - -void test_security_connector_already_in_arg(void) { - grpc_arg arg; - arg.type = GRPC_ARG_POINTER; - arg.value.pointer.p = NULL; - arg.key = GRPC_ARG_SECURITY_CONNECTOR; - grpc_channel_args args; - args.num_args = 1; - args.args = &arg; - grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, &args, NULL); - grpc_channel_element *elem = - grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); - GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); - grpc_exec_ctx_finish(&exec_ctx); -} - -void test_null_creds(void) { - grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, NULL, NULL); - grpc_channel_element *elem = - grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); - GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - 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/secure_channel_create_test.cc b/test/core/surface/secure_channel_create_test.cc new file mode 100644 index 0000000000..ccb58ee793 --- /dev/null +++ b/test/core/surface/secure_channel_create_test.cc @@ -0,0 +1,81 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/lib/surface/channel.h" +#include "test/core/util/test_config.h" + +void test_unknown_scheme_target(void) { + grpc_resolver_registry_shutdown(); + grpc_resolver_registry_init(); + grpc_channel_credentials *creds = + grpc_fake_transport_security_credentials_create(); + grpc_channel *chan = + grpc_secure_channel_create(creds, "blah://blah", NULL, NULL); + grpc_channel_element *elem = + grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); + grpc_channel_credentials_unref(&exec_ctx, creds); + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_security_connector_already_in_arg(void) { + grpc_arg arg; + arg.type = GRPC_ARG_POINTER; + arg.value.pointer.p = NULL; + arg.key = const_cast(GRPC_ARG_SECURITY_CONNECTOR); + grpc_channel_args args; + args.num_args = 1; + args.args = &arg; + grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, &args, NULL); + grpc_channel_element *elem = + grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test"); + grpc_exec_ctx_finish(&exec_ctx); +} + +void test_null_creds(void) { + grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, NULL, NULL); + grpc_channel_element *elem = + grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0); + GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + 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/sequential_connectivity_test.c b/test/core/surface/sequential_connectivity_test.c deleted file mode 100644 index d5fd2db81b..0000000000 --- a/test/core/surface/sequential_connectivity_test.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -typedef struct test_fixture { - const char *name; - void (*add_server_port)(grpc_server *server, const char *addr); - grpc_channel *(*create_channel)(const char *addr); -} test_fixture; - -#define NUM_CONNECTIONS 1000 - -typedef struct { - grpc_server *server; - grpc_completion_queue *cq; -} server_thread_args; - -static void server_thread_func(void *args) { - server_thread_args *a = args; - grpc_event ev = grpc_completion_queue_next( - a->cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == NULL); - GPR_ASSERT(ev.success == true); -} - -static void run_test(const test_fixture *fixture) { - gpr_log(GPR_INFO, "TEST: %s", fixture->name); - - grpc_init(); - - char *addr; - gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); - - grpc_server *server = grpc_server_create(NULL, NULL); - fixture->add_server_port(server, addr); - grpc_completion_queue *server_cq = - grpc_completion_queue_create_for_next(NULL); - grpc_server_register_completion_queue(server, server_cq, NULL); - grpc_server_start(server); - - server_thread_args sta = {server, server_cq}; - gpr_thd_id server_thread; - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&thdopt); - gpr_thd_new(&server_thread, server_thread_func, &sta, &thdopt); - - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_channel *channels[NUM_CONNECTIONS]; - for (size_t i = 0; i < NUM_CONNECTIONS; i++) { - channels[i] = fixture->create_channel(addr); - - gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30); - grpc_connectivity_state state; - while ((state = grpc_channel_check_connectivity_state(channels[i], 1)) != - GRPC_CHANNEL_READY) { - grpc_channel_watch_connectivity_state(channels[i], state, - connect_deadline, cq, NULL); - grpc_event ev = grpc_completion_queue_next( - cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - /* check that the watcher from "watch state" was free'd */ - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channels[i]) == - 0); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == NULL); - GPR_ASSERT(ev.success == true); - } - } - - grpc_server_shutdown_and_notify(server, server_cq, NULL); - gpr_thd_join(server_thread); - - grpc_completion_queue_shutdown(server_cq); - grpc_completion_queue_shutdown(cq); - - while (grpc_completion_queue_next(server_cq, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type != GRPC_QUEUE_SHUTDOWN) - ; - while ( - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) - .type != GRPC_QUEUE_SHUTDOWN) - ; - - for (size_t i = 0; i < NUM_CONNECTIONS; i++) { - grpc_channel_destroy(channels[i]); - } - - grpc_server_destroy(server); - grpc_completion_queue_destroy(server_cq); - grpc_completion_queue_destroy(cq); - - grpc_shutdown(); - gpr_free(addr); -} - -static void insecure_test_add_port(grpc_server *server, const char *addr) { - grpc_server_add_insecure_http2_port(server, addr); -} - -static grpc_channel *insecure_test_create_channel(const char *addr) { - return grpc_insecure_channel_create(addr, NULL, NULL); -} - -static const test_fixture insecure_test = { - "insecure", insecure_test_add_port, insecure_test_create_channel, -}; - -static void secure_test_add_port(grpc_server *server, const char *addr) { - grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, - test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); - grpc_server_add_secure_http2_port(server, addr, ssl_creds); - grpc_server_credentials_release(ssl_creds); -} - -static grpc_channel *secure_test_create_channel(const char *addr) { - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL, NULL); - grpc_arg ssl_name_override = {GRPC_ARG_STRING, - GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.fr"}}; - grpc_channel_args *new_client_args = - grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1); - grpc_channel *channel = - grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL); - { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args_destroy(&exec_ctx, new_client_args); - grpc_exec_ctx_finish(&exec_ctx); - } - grpc_channel_credentials_release(ssl_creds); - return channel; -} - -static const test_fixture secure_test = { - "secure", secure_test_add_port, secure_test_create_channel, -}; - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - run_test(&insecure_test); - run_test(&secure_test); -} diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc new file mode 100644 index 0000000000..6596a3a0ce --- /dev/null +++ b/test/core/surface/sequential_connectivity_test.cc @@ -0,0 +1,174 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct test_fixture { + const char *name; + void (*add_server_port)(grpc_server *server, const char *addr); + grpc_channel *(*create_channel)(const char *addr); +} test_fixture; + +#define NUM_CONNECTIONS 1000 + +typedef struct { + grpc_server *server; + grpc_completion_queue *cq; +} server_thread_args; + +static void server_thread_func(void *args) { + server_thread_args *a = static_cast(args); + grpc_event ev = grpc_completion_queue_next( + a->cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == NULL); + GPR_ASSERT(ev.success == true); +} + +static void run_test(const test_fixture *fixture) { + gpr_log(GPR_INFO, "TEST: %s", fixture->name); + + grpc_init(); + + char *addr; + gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); + + grpc_server *server = grpc_server_create(NULL, NULL); + fixture->add_server_port(server, addr); + grpc_completion_queue *server_cq = + grpc_completion_queue_create_for_next(NULL); + grpc_server_register_completion_queue(server, server_cq, NULL); + grpc_server_start(server); + + server_thread_args sta = {server, server_cq}; + gpr_thd_id server_thread; + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&thdopt); + gpr_thd_new(&server_thread, server_thread_func, &sta, &thdopt); + + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_channel *channels[NUM_CONNECTIONS]; + for (size_t i = 0; i < NUM_CONNECTIONS; i++) { + channels[i] = fixture->create_channel(addr); + + gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30); + grpc_connectivity_state state; + while ((state = grpc_channel_check_connectivity_state(channels[i], 1)) != + GRPC_CHANNEL_READY) { + grpc_channel_watch_connectivity_state(channels[i], state, + connect_deadline, cq, NULL); + grpc_event ev = grpc_completion_queue_next( + cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channels[i]) == + 0); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.tag == NULL); + GPR_ASSERT(ev.success == true); + } + } + + grpc_server_shutdown_and_notify(server, server_cq, NULL); + gpr_thd_join(server_thread); + + grpc_completion_queue_shutdown(server_cq); + grpc_completion_queue_shutdown(cq); + + while (grpc_completion_queue_next(server_cq, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type != GRPC_QUEUE_SHUTDOWN) + ; + while ( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type != GRPC_QUEUE_SHUTDOWN) + ; + + for (size_t i = 0; i < NUM_CONNECTIONS; i++) { + grpc_channel_destroy(channels[i]); + } + + grpc_server_destroy(server); + grpc_completion_queue_destroy(server_cq); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_free(addr); +} + +static void insecure_test_add_port(grpc_server *server, const char *addr) { + grpc_server_add_insecure_http2_port(server, addr); +} + +static grpc_channel *insecure_test_create_channel(const char *addr) { + return grpc_insecure_channel_create(addr, NULL, NULL); +} + +static const test_fixture insecure_test = { + "insecure", insecure_test_add_port, insecure_test_create_channel, +}; + +static void secure_test_add_port(grpc_server *server, const char *addr) { + grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); + grpc_server_add_secure_http2_port(server, addr, ssl_creds); + grpc_server_credentials_release(ssl_creds); +} + +static grpc_channel *secure_test_create_channel(const char *addr) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1); + grpc_channel *channel = + grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_channel_credentials_release(ssl_creds); + return channel; +} + +static const test_fixture secure_test = { + "secure", secure_test_add_port, secure_test_create_channel, +}; + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + run_test(&insecure_test); + run_test(&secure_test); +} diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c deleted file mode 100644 index cd8931e0d7..0000000000 --- a/test/core/surface/server_chttp2_test.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "src/core/tsi/fake_transport_security.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -void test_unparsable_target(void) { - grpc_channel_args args = {0, NULL}; - grpc_server *server = grpc_server_create(&args, NULL); - int port = grpc_server_add_insecure_http2_port(server, "["); - GPR_ASSERT(port == 0); - grpc_server_destroy(server); -} - -void test_add_same_port_twice() { - grpc_arg a; - a.type = GRPC_ARG_INTEGER; - a.key = GRPC_ARG_ALLOW_REUSEPORT; - a.value.integer = 0; - grpc_channel_args args = {1, &a}; - - int port = grpc_pick_unused_port_or_die(); - char *addr = NULL; - grpc_completion_queue *cq = grpc_completion_queue_create_for_pluck(NULL); - grpc_server *server = grpc_server_create(&args, NULL); - grpc_server_credentials *fake_creds = - grpc_fake_transport_security_server_credentials_create(); - gpr_join_host_port(&addr, "localhost", port); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds)); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds) == 0); - - grpc_server_credentials_release(fake_creds); - gpr_free(addr); - grpc_server_shutdown_and_notify(server, cq, NULL); - grpc_completion_queue_pluck(cq, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_unparsable_target(); - test_add_same_port_twice(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/surface/server_chttp2_test.cc b/test/core/surface/server_chttp2_test.cc new file mode 100644 index 0000000000..ecd5314b83 --- /dev/null +++ b/test/core/surface/server_chttp2_test.cc @@ -0,0 +1,72 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/tsi/fake_transport_security.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +void test_unparsable_target(void) { + grpc_channel_args args = {0, NULL}; + grpc_server *server = grpc_server_create(&args, NULL); + int port = grpc_server_add_insecure_http2_port(server, "["); + GPR_ASSERT(port == 0); + grpc_server_destroy(server); +} + +void test_add_same_port_twice() { + grpc_arg a; + a.type = GRPC_ARG_INTEGER; + a.key = const_cast(GRPC_ARG_ALLOW_REUSEPORT); + a.value.integer = 0; + grpc_channel_args args = {1, &a}; + + int port = grpc_pick_unused_port_or_die(); + char *addr = NULL; + grpc_completion_queue *cq = grpc_completion_queue_create_for_pluck(NULL); + grpc_server *server = grpc_server_create(&args, NULL); + grpc_server_credentials *fake_creds = + grpc_fake_transport_security_server_credentials_create(); + gpr_join_host_port(&addr, "localhost", port); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds)); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds) == 0); + + grpc_server_credentials_release(fake_creds); + gpr_free(addr); + grpc_server_shutdown_and_notify(server, cq, NULL); + grpc_completion_queue_pluck(cq, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_unparsable_target(); + test_add_same_port_twice(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c deleted file mode 100644 index 4c185cd8ea..0000000000 --- a/test/core/surface/server_test.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.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, GRPC_SRM_PAYLOAD_NONE, 0); - GPR_ASSERT(method == NULL); - method_old = - grpc_server_register_method(server, "m", "h", GRPC_SRM_PAYLOAD_NONE, 0); - GPR_ASSERT(method_old != NULL); - method = grpc_server_register_method( - server, "m", "h", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0); - GPR_ASSERT(method == NULL); - method_old = - grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, - GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); - GPR_ASSERT(method_old != NULL); - method = - grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, 0); - GPR_ASSERT(method == NULL); - method = grpc_server_register_method( - server, "m2", "h2", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, - GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); - 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_for_next(NULL); - grpc_server *server = grpc_server_create(NULL, NULL); - GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == - grpc_server_request_call(server, NULL, NULL, NULL, cc, cc, NULL)); - GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == - grpc_server_request_registered_call(server, NULL, NULL, NULL, NULL, - NULL, cc, cc, NULL)); - grpc_completion_queue_destroy(cc); - grpc_server_destroy(server); -} - -void test_bind_server_twice(void) { - grpc_arg a; - a.type = GRPC_ARG_INTEGER; - a.key = GRPC_ARG_ALLOW_REUSEPORT; - a.value.integer = 0; - grpc_channel_args args = {1, &a}; - - char *addr; - grpc_server *server1 = grpc_server_create(&args, NULL); - grpc_server *server2 = grpc_server_create(&args, NULL); - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(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(0 == grpc_server_add_secure_http2_port(server2, addr, 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_credentials *fake_creds = - grpc_fake_transport_security_server_credentials_create(); - GPR_ASSERT(0 == grpc_server_add_secure_http2_port(server2, addr, fake_creds)); - grpc_server_credentials_release(fake_creds); - 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); -} - -void test_bind_server_to_addr(const char *host, bool secure) { - int port = grpc_pick_unused_port_or_die(); - char *addr; - gpr_join_host_port(&addr, host, port); - gpr_log(GPR_INFO, "Test bind to %s", addr); - - grpc_server *server = grpc_server_create(NULL, NULL); - if (secure) { - grpc_server_credentials *fake_creds = - grpc_fake_transport_security_server_credentials_create(); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds)); - grpc_server_credentials_release(fake_creds); - } else { - GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); - } - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - grpc_server_register_completion_queue(server, cq, NULL); - grpc_server_start(server); - grpc_server_shutdown_and_notify(server, cq, NULL); - grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - gpr_free(addr); -} - -static int external_dns_works(const char *host) { - grpc_resolved_addresses *res = NULL; - grpc_error *error = grpc_blocking_resolve_address(host, "80", &res); - GRPC_ERROR_UNREF(error); - if (res != NULL) { - grpc_resolved_addresses_destroy(res); - return 1; - } - return 0; -} - -static void test_bind_server_to_addrs(const char **addrs, size_t n) { - for (size_t i = 0; i < n; i++) { - test_bind_server_to_addr(addrs[i], false); - test_bind_server_to_addr(addrs[i], true); - } -} - -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(); - - static const char *addrs[] = { - "::1", "127.0.0.1", "::ffff:127.0.0.1", "localhost", "0.0.0.0", "::", - }; - test_bind_server_to_addrs(addrs, GPR_ARRAY_SIZE(addrs)); - - if (external_dns_works("loopback46.unittest.grpc.io")) { - static const char *dns_addrs[] = { - "loopback46.unittest.grpc.io", "loopback4.unittest.grpc.io", - }; - test_bind_server_to_addrs(dns_addrs, GPR_ARRAY_SIZE(dns_addrs)); - } - - grpc_shutdown(); - return 0; -} diff --git a/test/core/surface/server_test.cc b/test/core/surface/server_test.cc new file mode 100644 index 0000000000..08b8dca4d7 --- /dev/null +++ b/test/core/surface/server_test.cc @@ -0,0 +1,165 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.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, GRPC_SRM_PAYLOAD_NONE, 0); + GPR_ASSERT(method == NULL); + method_old = + grpc_server_register_method(server, "m", "h", GRPC_SRM_PAYLOAD_NONE, 0); + GPR_ASSERT(method_old != NULL); + method = grpc_server_register_method( + server, "m", "h", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0); + GPR_ASSERT(method == NULL); + method_old = + grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, + GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); + GPR_ASSERT(method_old != NULL); + method = + grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, 0); + GPR_ASSERT(method == NULL); + method = grpc_server_register_method( + server, "m2", "h2", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, + GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); + 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_for_next(NULL); + grpc_server *server = grpc_server_create(NULL, NULL); + GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == + grpc_server_request_call(server, NULL, NULL, NULL, cc, cc, NULL)); + GPR_ASSERT(GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE == + grpc_server_request_registered_call(server, NULL, NULL, NULL, NULL, + NULL, cc, cc, NULL)); + grpc_completion_queue_destroy(cc); + grpc_server_destroy(server); +} + +void test_bind_server_twice(void) { + grpc_arg a; + a.type = GRPC_ARG_INTEGER; + a.key = const_cast(GRPC_ARG_ALLOW_REUSEPORT); + a.value.integer = 0; + grpc_channel_args args = {1, &a}; + + char *addr; + grpc_server *server1 = grpc_server_create(&args, NULL); + grpc_server *server2 = grpc_server_create(&args, NULL); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(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(0 == grpc_server_add_secure_http2_port(server2, addr, 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_credentials *fake_creds = + grpc_fake_transport_security_server_credentials_create(); + GPR_ASSERT(0 == grpc_server_add_secure_http2_port(server2, addr, fake_creds)); + grpc_server_credentials_release(fake_creds); + 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); +} + +void test_bind_server_to_addr(const char *host, bool secure) { + int port = grpc_pick_unused_port_or_die(); + char *addr; + gpr_join_host_port(&addr, host, port); + gpr_log(GPR_INFO, "Test bind to %s", addr); + + grpc_server *server = grpc_server_create(NULL, NULL); + if (secure) { + grpc_server_credentials *fake_creds = + grpc_fake_transport_security_server_credentials_create(); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds)); + grpc_server_credentials_release(fake_creds); + } else { + GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); + } + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + grpc_server_shutdown_and_notify(server, cq, NULL); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL); + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + gpr_free(addr); +} + +static int external_dns_works(const char *host) { + grpc_resolved_addresses *res = NULL; + grpc_error *error = grpc_blocking_resolve_address(host, "80", &res); + GRPC_ERROR_UNREF(error); + if (res != NULL) { + grpc_resolved_addresses_destroy(res); + return 1; + } + return 0; +} + +static void test_bind_server_to_addrs(const char **addrs, size_t n) { + for (size_t i = 0; i < n; i++) { + test_bind_server_to_addr(addrs[i], false); + test_bind_server_to_addr(addrs[i], true); + } +} + +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(); + + static const char *addrs[] = { + "::1", "127.0.0.1", "::ffff:127.0.0.1", "localhost", "0.0.0.0", "::", + }; + test_bind_server_to_addrs(addrs, GPR_ARRAY_SIZE(addrs)); + + if (external_dns_works("loopback46.unittest.grpc.io")) { + static const char *dns_addrs[] = { + "loopback46.unittest.grpc.io", "loopback4.unittest.grpc.io", + }; + test_bind_server_to_addrs(dns_addrs, GPR_ARRAY_SIZE(dns_addrs)); + } + + grpc_shutdown(); + return 0; +} diff --git a/test/core/transport/byte_stream_test.c b/test/core/transport/byte_stream_test.c deleted file mode 100644 index a0c5f961cf..0000000000 --- a/test/core/transport/byte_stream_test.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/byte_stream.h" - -#include -#include -#include - -#include "src/core/lib/slice/slice_internal.h" - -#include "test/core/util/test_config.h" - -// -// grpc_slice_buffer_stream tests -// - -static void not_called_closure(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_ASSERT(false); -} - -static void test_slice_buffer_stream_basic(void) { - gpr_log(GPR_DEBUG, "test_slice_buffer_stream_basic"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - // Create and populate slice buffer. - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - grpc_slice input[] = { - grpc_slice_from_static_string("foo"), - grpc_slice_from_static_string("bar"), - }; - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - grpc_slice_buffer_add(&buffer, input[i]); - } - // Create byte stream. - grpc_slice_buffer_stream stream; - grpc_slice_buffer_stream_init(&stream, &buffer, 0); - GPR_ASSERT(stream.base.length == 6); - grpc_closure closure; - GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, - grpc_schedule_on_exec_ctx); - // Read each slice. Note that next() always returns synchronously. - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - grpc_slice output; - grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[i], output)); - grpc_slice_unref_internal(&exec_ctx, output); - } - // Clean up. - grpc_byte_stream_destroy(&exec_ctx, &stream.base); - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_slice_buffer_stream_shutdown(void) { - gpr_log(GPR_DEBUG, "test_slice_buffer_stream_shutdown"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - // Create and populate slice buffer. - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - grpc_slice input[] = { - grpc_slice_from_static_string("foo"), - grpc_slice_from_static_string("bar"), - }; - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - grpc_slice_buffer_add(&buffer, input[i]); - } - // Create byte stream. - grpc_slice_buffer_stream stream; - grpc_slice_buffer_stream_init(&stream, &buffer, 0); - GPR_ASSERT(stream.base.length == 6); - grpc_closure closure; - GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, - grpc_schedule_on_exec_ctx); - // Read the first slice. - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - grpc_slice output; - grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[0], output)); - grpc_slice_unref_internal(&exec_ctx, output); - // Now shutdown. - grpc_error *shutdown_error = - GRPC_ERROR_CREATE_FROM_STATIC_STRING("shutdown error"); - grpc_byte_stream_shutdown(&exec_ctx, &stream.base, - GRPC_ERROR_REF(shutdown_error)); - // After shutdown, the next pull() should return the error. - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == shutdown_error); - GRPC_ERROR_UNREF(error); - GRPC_ERROR_UNREF(shutdown_error); - // Clean up. - grpc_byte_stream_destroy(&exec_ctx, &stream.base); - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); -} - -// -// grpc_caching_byte_stream tests -// - -static void test_caching_byte_stream_basic(void) { - gpr_log(GPR_DEBUG, "test_caching_byte_stream_basic"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - // Create and populate slice buffer byte stream. - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - grpc_slice input[] = { - grpc_slice_from_static_string("foo"), - grpc_slice_from_static_string("bar"), - }; - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - grpc_slice_buffer_add(&buffer, input[i]); - } - grpc_slice_buffer_stream underlying_stream; - grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); - // Create cache and caching stream. - grpc_byte_stream_cache cache; - grpc_byte_stream_cache_init(&cache, &underlying_stream.base); - grpc_caching_byte_stream stream; - grpc_caching_byte_stream_init(&stream, &cache); - grpc_closure closure; - GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, - grpc_schedule_on_exec_ctx); - // Read each slice. Note that next() always returns synchronously, - // because the underlying byte stream always does. - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - grpc_slice output; - grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[i], output)); - grpc_slice_unref_internal(&exec_ctx, output); - } - // Clean up. - grpc_byte_stream_destroy(&exec_ctx, &stream.base); - grpc_byte_stream_cache_destroy(&exec_ctx, &cache); - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_caching_byte_stream_reset(void) { - gpr_log(GPR_DEBUG, "test_caching_byte_stream_reset"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - // Create and populate slice buffer byte stream. - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - grpc_slice input[] = { - grpc_slice_from_static_string("foo"), - grpc_slice_from_static_string("bar"), - }; - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - grpc_slice_buffer_add(&buffer, input[i]); - } - grpc_slice_buffer_stream underlying_stream; - grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); - // Create cache and caching stream. - grpc_byte_stream_cache cache; - grpc_byte_stream_cache_init(&cache, &underlying_stream.base); - grpc_caching_byte_stream stream; - grpc_caching_byte_stream_init(&stream, &cache); - grpc_closure closure; - GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, - grpc_schedule_on_exec_ctx); - // Read one slice. - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - grpc_slice output; - grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[0], output)); - grpc_slice_unref_internal(&exec_ctx, output); - // Reset the caching stream. The reads should start over from the - // first slice. - grpc_caching_byte_stream_reset(&stream); - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); - error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[i], output)); - grpc_slice_unref_internal(&exec_ctx, output); - } - // Clean up. - grpc_byte_stream_destroy(&exec_ctx, &stream.base); - grpc_byte_stream_cache_destroy(&exec_ctx, &cache); - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_caching_byte_stream_shared_cache(void) { - gpr_log(GPR_DEBUG, "test_caching_byte_stream_shared_cache"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - // Create and populate slice buffer byte stream. - grpc_slice_buffer buffer; - grpc_slice_buffer_init(&buffer); - grpc_slice input[] = { - grpc_slice_from_static_string("foo"), - grpc_slice_from_static_string("bar"), - }; - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - grpc_slice_buffer_add(&buffer, input[i]); - } - grpc_slice_buffer_stream underlying_stream; - grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); - // Create cache and two caching streams. - grpc_byte_stream_cache cache; - grpc_byte_stream_cache_init(&cache, &underlying_stream.base); - grpc_caching_byte_stream stream1; - grpc_caching_byte_stream_init(&stream1, &cache); - grpc_caching_byte_stream stream2; - grpc_caching_byte_stream_init(&stream2, &cache); - grpc_closure closure; - GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, - grpc_schedule_on_exec_ctx); - // Read one slice from stream1. - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure)); - grpc_slice output; - grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[0], output)); - grpc_slice_unref_internal(&exec_ctx, output); - // Read all slices from stream2. - for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream2.base, ~(size_t)0, &closure)); - error = grpc_byte_stream_pull(&exec_ctx, &stream2.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[i], output)); - grpc_slice_unref_internal(&exec_ctx, output); - } - // Now read the second slice from stream1. - GPR_ASSERT( - grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure)); - error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(grpc_slice_eq(input[1], output)); - grpc_slice_unref_internal(&exec_ctx, output); - // Clean up. - grpc_byte_stream_destroy(&exec_ctx, &stream1.base); - grpc_byte_stream_destroy(&exec_ctx, &stream2.base); - grpc_byte_stream_cache_destroy(&exec_ctx, &cache); - grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_slice_buffer_stream_basic(); - test_slice_buffer_stream_shutdown(); - test_caching_byte_stream_basic(); - test_caching_byte_stream_reset(); - test_caching_byte_stream_shared_cache(); - return 0; -} diff --git a/test/core/transport/byte_stream_test.cc b/test/core/transport/byte_stream_test.cc new file mode 100644 index 0000000000..a0c5f961cf --- /dev/null +++ b/test/core/transport/byte_stream_test.cc @@ -0,0 +1,279 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/byte_stream.h" + +#include +#include +#include + +#include "src/core/lib/slice/slice_internal.h" + +#include "test/core/util/test_config.h" + +// +// grpc_slice_buffer_stream tests +// + +static void not_called_closure(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(false); +} + +static void test_slice_buffer_stream_basic(void) { + gpr_log(GPR_DEBUG, "test_slice_buffer_stream_basic"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + // Create and populate slice buffer. + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + grpc_slice input[] = { + grpc_slice_from_static_string("foo"), + grpc_slice_from_static_string("bar"), + }; + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + grpc_slice_buffer_add(&buffer, input[i]); + } + // Create byte stream. + grpc_slice_buffer_stream stream; + grpc_slice_buffer_stream_init(&stream, &buffer, 0); + GPR_ASSERT(stream.base.length == 6); + grpc_closure closure; + GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, + grpc_schedule_on_exec_ctx); + // Read each slice. Note that next() always returns synchronously. + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + grpc_slice output; + grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[i], output)); + grpc_slice_unref_internal(&exec_ctx, output); + } + // Clean up. + grpc_byte_stream_destroy(&exec_ctx, &stream.base); + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_slice_buffer_stream_shutdown(void) { + gpr_log(GPR_DEBUG, "test_slice_buffer_stream_shutdown"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + // Create and populate slice buffer. + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + grpc_slice input[] = { + grpc_slice_from_static_string("foo"), + grpc_slice_from_static_string("bar"), + }; + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + grpc_slice_buffer_add(&buffer, input[i]); + } + // Create byte stream. + grpc_slice_buffer_stream stream; + grpc_slice_buffer_stream_init(&stream, &buffer, 0); + GPR_ASSERT(stream.base.length == 6); + grpc_closure closure; + GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, + grpc_schedule_on_exec_ctx); + // Read the first slice. + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + grpc_slice output; + grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[0], output)); + grpc_slice_unref_internal(&exec_ctx, output); + // Now shutdown. + grpc_error *shutdown_error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("shutdown error"); + grpc_byte_stream_shutdown(&exec_ctx, &stream.base, + GRPC_ERROR_REF(shutdown_error)); + // After shutdown, the next pull() should return the error. + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == shutdown_error); + GRPC_ERROR_UNREF(error); + GRPC_ERROR_UNREF(shutdown_error); + // Clean up. + grpc_byte_stream_destroy(&exec_ctx, &stream.base); + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); +} + +// +// grpc_caching_byte_stream tests +// + +static void test_caching_byte_stream_basic(void) { + gpr_log(GPR_DEBUG, "test_caching_byte_stream_basic"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + // Create and populate slice buffer byte stream. + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + grpc_slice input[] = { + grpc_slice_from_static_string("foo"), + grpc_slice_from_static_string("bar"), + }; + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + grpc_slice_buffer_add(&buffer, input[i]); + } + grpc_slice_buffer_stream underlying_stream; + grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); + // Create cache and caching stream. + grpc_byte_stream_cache cache; + grpc_byte_stream_cache_init(&cache, &underlying_stream.base); + grpc_caching_byte_stream stream; + grpc_caching_byte_stream_init(&stream, &cache); + grpc_closure closure; + GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, + grpc_schedule_on_exec_ctx); + // Read each slice. Note that next() always returns synchronously, + // because the underlying byte stream always does. + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + grpc_slice output; + grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[i], output)); + grpc_slice_unref_internal(&exec_ctx, output); + } + // Clean up. + grpc_byte_stream_destroy(&exec_ctx, &stream.base); + grpc_byte_stream_cache_destroy(&exec_ctx, &cache); + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_caching_byte_stream_reset(void) { + gpr_log(GPR_DEBUG, "test_caching_byte_stream_reset"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + // Create and populate slice buffer byte stream. + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + grpc_slice input[] = { + grpc_slice_from_static_string("foo"), + grpc_slice_from_static_string("bar"), + }; + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + grpc_slice_buffer_add(&buffer, input[i]); + } + grpc_slice_buffer_stream underlying_stream; + grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); + // Create cache and caching stream. + grpc_byte_stream_cache cache; + grpc_byte_stream_cache_init(&cache, &underlying_stream.base); + grpc_caching_byte_stream stream; + grpc_caching_byte_stream_init(&stream, &cache); + grpc_closure closure; + GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, + grpc_schedule_on_exec_ctx); + // Read one slice. + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + grpc_slice output; + grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[0], output)); + grpc_slice_unref_internal(&exec_ctx, output); + // Reset the caching stream. The reads should start over from the + // first slice. + grpc_caching_byte_stream_reset(&stream); + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream.base, ~(size_t)0, &closure)); + error = grpc_byte_stream_pull(&exec_ctx, &stream.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[i], output)); + grpc_slice_unref_internal(&exec_ctx, output); + } + // Clean up. + grpc_byte_stream_destroy(&exec_ctx, &stream.base); + grpc_byte_stream_cache_destroy(&exec_ctx, &cache); + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_caching_byte_stream_shared_cache(void) { + gpr_log(GPR_DEBUG, "test_caching_byte_stream_shared_cache"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + // Create and populate slice buffer byte stream. + grpc_slice_buffer buffer; + grpc_slice_buffer_init(&buffer); + grpc_slice input[] = { + grpc_slice_from_static_string("foo"), + grpc_slice_from_static_string("bar"), + }; + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + grpc_slice_buffer_add(&buffer, input[i]); + } + grpc_slice_buffer_stream underlying_stream; + grpc_slice_buffer_stream_init(&underlying_stream, &buffer, 0); + // Create cache and two caching streams. + grpc_byte_stream_cache cache; + grpc_byte_stream_cache_init(&cache, &underlying_stream.base); + grpc_caching_byte_stream stream1; + grpc_caching_byte_stream_init(&stream1, &cache); + grpc_caching_byte_stream stream2; + grpc_caching_byte_stream_init(&stream2, &cache); + grpc_closure closure; + GRPC_CLOSURE_INIT(&closure, not_called_closure, NULL, + grpc_schedule_on_exec_ctx); + // Read one slice from stream1. + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure)); + grpc_slice output; + grpc_error *error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[0], output)); + grpc_slice_unref_internal(&exec_ctx, output); + // Read all slices from stream2. + for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream2.base, ~(size_t)0, &closure)); + error = grpc_byte_stream_pull(&exec_ctx, &stream2.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[i], output)); + grpc_slice_unref_internal(&exec_ctx, output); + } + // Now read the second slice from stream1. + GPR_ASSERT( + grpc_byte_stream_next(&exec_ctx, &stream1.base, ~(size_t)0, &closure)); + error = grpc_byte_stream_pull(&exec_ctx, &stream1.base, &output); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_slice_eq(input[1], output)); + grpc_slice_unref_internal(&exec_ctx, output); + // Clean up. + grpc_byte_stream_destroy(&exec_ctx, &stream1.base); + grpc_byte_stream_destroy(&exec_ctx, &stream2.base); + grpc_byte_stream_cache_destroy(&exec_ctx, &cache); + grpc_slice_buffer_destroy_internal(&exec_ctx, &buffer); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_slice_buffer_stream_basic(); + test_slice_buffer_stream_shutdown(); + test_caching_byte_stream_basic(); + test_caching_byte_stream_reset(); + test_caching_byte_stream_shared_cache(); + return 0; +} diff --git a/test/core/transport/chttp2/alpn_test.c b/test/core/transport/chttp2/alpn_test.c deleted file mode 100644 index 72c30c40eb..0000000000 --- a/test/core/transport/chttp2/alpn_test.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/alpn/alpn.h" - -#include -#include "test/core/util/test_config.h" - -static void test_alpn_success(void) { - GPR_ASSERT(grpc_chttp2_is_alpn_version_supported("h2", 2)); - GPR_ASSERT(grpc_chttp2_is_alpn_version_supported("grpc-exp", 8)); -} - -static void test_alpn_failure(void) { - GPR_ASSERT(!grpc_chttp2_is_alpn_version_supported("h2-155", 6)); - GPR_ASSERT(!grpc_chttp2_is_alpn_version_supported("h1-15", 5)); -} - -// First index in ALPN supported version list of a given protocol. Returns a -// value one beyond the last valid element index if not found. -static size_t alpn_version_index(const char *version, size_t size) { - size_t i; - for (i = 0; i < grpc_chttp2_num_alpn_versions(); ++i) { - if (!strncmp(version, grpc_chttp2_get_alpn_version_index(i), size)) { - return i; - } - } - return i; -} - -static void test_alpn_grpc_before_h2(void) { - // grpc-exp is preferred over h2. - GPR_ASSERT(alpn_version_index("grpc-exp", 8) < alpn_version_index("h2", 2)); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_alpn_success(); - test_alpn_failure(); - test_alpn_grpc_before_h2(); - return 0; -} diff --git a/test/core/transport/chttp2/alpn_test.cc b/test/core/transport/chttp2/alpn_test.cc new file mode 100644 index 0000000000..72c30c40eb --- /dev/null +++ b/test/core/transport/chttp2/alpn_test.cc @@ -0,0 +1,57 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" + +#include +#include "test/core/util/test_config.h" + +static void test_alpn_success(void) { + GPR_ASSERT(grpc_chttp2_is_alpn_version_supported("h2", 2)); + GPR_ASSERT(grpc_chttp2_is_alpn_version_supported("grpc-exp", 8)); +} + +static void test_alpn_failure(void) { + GPR_ASSERT(!grpc_chttp2_is_alpn_version_supported("h2-155", 6)); + GPR_ASSERT(!grpc_chttp2_is_alpn_version_supported("h1-15", 5)); +} + +// First index in ALPN supported version list of a given protocol. Returns a +// value one beyond the last valid element index if not found. +static size_t alpn_version_index(const char *version, size_t size) { + size_t i; + for (i = 0; i < grpc_chttp2_num_alpn_versions(); ++i) { + if (!strncmp(version, grpc_chttp2_get_alpn_version_index(i), size)) { + return i; + } + } + return i; +} + +static void test_alpn_grpc_before_h2(void) { + // grpc-exp is preferred over h2. + GPR_ASSERT(alpn_version_index("grpc-exp", 8) < alpn_version_index("h2", 2)); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_alpn_success(); + test_alpn_failure(); + test_alpn_grpc_before_h2(); + return 0; +} diff --git a/test/core/transport/chttp2/bin_decoder_test.c b/test/core/transport/chttp2/bin_decoder_test.c deleted file mode 100644 index 775161ec91..0000000000 --- a/test/core/transport/chttp2/bin_decoder_test.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/bin_decoder.h" - -#include - -#include -#include -#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" - -static int all_ok = 1; - -static void expect_slice_eq(grpc_exec_ctx *exec_ctx, grpc_slice expected, - grpc_slice slice, char *debug, int line) { - if (!grpc_slice_eq(slice, expected)) { - char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot: %s\nwant: %s", line, debug, hs, - he); - gpr_free(hs); - gpr_free(he); - all_ok = 0; - } - grpc_slice_unref_internal(exec_ctx, expected); - grpc_slice_unref_internal(exec_ctx, slice); -} - -static grpc_slice base64_encode(grpc_exec_ctx *exec_ctx, const char *s) { - grpc_slice ss = grpc_slice_from_copied_string(s); - grpc_slice out = grpc_chttp2_base64_encode(ss); - grpc_slice_unref_internal(exec_ctx, ss); - return out; -} - -static grpc_slice base64_decode(grpc_exec_ctx *exec_ctx, const char *s) { - grpc_slice ss = grpc_slice_from_copied_string(s); - grpc_slice out = grpc_chttp2_base64_decode(exec_ctx, ss); - grpc_slice_unref_internal(exec_ctx, ss); - return out; -} - -static grpc_slice base64_decode_with_length(grpc_exec_ctx *exec_ctx, - const char *s, - size_t output_length) { - grpc_slice ss = grpc_slice_from_copied_string(s); - grpc_slice out = - grpc_chttp2_base64_decode_with_length(exec_ctx, ss, output_length); - grpc_slice_unref_internal(exec_ctx, ss); - return out; -} - -#define EXPECT_SLICE_EQ(exec_ctx, expected, slice) \ - expect_slice_eq( \ - exec_ctx, grpc_slice_from_copied_buffer(expected, sizeof(expected) - 1), \ - slice, #slice, __LINE__); - -#define ENCODE_AND_DECODE(exec_ctx, s) \ - EXPECT_SLICE_EQ(exec_ctx, s, \ - grpc_chttp2_base64_decode_with_length( \ - exec_ctx, base64_encode(exec_ctx, s), strlen(s))); - -int main(int argc, char **argv) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - /* ENCODE_AND_DECODE tests grpc_chttp2_base64_decode_with_length(), which - takes encoded base64 strings without pad chars, but output length is - required. */ - /* Base64 test vectors from RFC 4648 */ - ENCODE_AND_DECODE(&exec_ctx, ""); - ENCODE_AND_DECODE(&exec_ctx, "f"); - ENCODE_AND_DECODE(&exec_ctx, "foo"); - ENCODE_AND_DECODE(&exec_ctx, "fo"); - ENCODE_AND_DECODE(&exec_ctx, "foob"); - ENCODE_AND_DECODE(&exec_ctx, "fooba"); - ENCODE_AND_DECODE(&exec_ctx, "foobar"); - - ENCODE_AND_DECODE(&exec_ctx, "\xc0\xc1\xc2\xc3\xc4\xc5"); - - /* Base64 test vectors from RFC 4648, with pad chars */ - /* BASE64("") = "" */ - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "")); - /* BASE64("f") = "Zg==" */ - EXPECT_SLICE_EQ(&exec_ctx, "f", base64_decode(&exec_ctx, "Zg==")); - /* BASE64("fo") = "Zm8=" */ - EXPECT_SLICE_EQ(&exec_ctx, "fo", base64_decode(&exec_ctx, "Zm8=")); - /* BASE64("foo") = "Zm9v" */ - EXPECT_SLICE_EQ(&exec_ctx, "foo", base64_decode(&exec_ctx, "Zm9v")); - /* BASE64("foob") = "Zm9vYg==" */ - EXPECT_SLICE_EQ(&exec_ctx, "foob", base64_decode(&exec_ctx, "Zm9vYg==")); - /* BASE64("fooba") = "Zm9vYmE=" */ - EXPECT_SLICE_EQ(&exec_ctx, "fooba", base64_decode(&exec_ctx, "Zm9vYmE=")); - /* BASE64("foobar") = "Zm9vYmFy" */ - EXPECT_SLICE_EQ(&exec_ctx, "foobar", base64_decode(&exec_ctx, "Zm9vYmFy")); - - EXPECT_SLICE_EQ(&exec_ctx, "\xc0\xc1\xc2\xc3\xc4\xc5", - base64_decode(&exec_ctx, "wMHCw8TF")); - - // Test illegal input length in grpc_chttp2_base64_decode - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "a")); - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "ab")); - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "abc")); - - // Test illegal charactors in grpc_chttp2_base64_decode - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "Zm:v")); - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "Zm=v")); - - // Test output_length longer than max possible output length in - // grpc_chttp2_base64_decode_with_length - EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode_with_length(&exec_ctx, "Zg", 2)); - EXPECT_SLICE_EQ(&exec_ctx, "", - base64_decode_with_length(&exec_ctx, "Zm8", 3)); - EXPECT_SLICE_EQ(&exec_ctx, "", - base64_decode_with_length(&exec_ctx, "Zm9v", 4)); - - // Test illegal charactors in grpc_chttp2_base64_decode_with_length - EXPECT_SLICE_EQ(&exec_ctx, "", - base64_decode_with_length(&exec_ctx, "Zm:v", 3)); - EXPECT_SLICE_EQ(&exec_ctx, "", - base64_decode_with_length(&exec_ctx, "Zm=v", 3)); - - grpc_exec_ctx_finish(&exec_ctx); - - return all_ok ? 0 : 1; -} diff --git a/test/core/transport/chttp2/bin_decoder_test.cc b/test/core/transport/chttp2/bin_decoder_test.cc new file mode 100644 index 0000000000..a09aadb18d --- /dev/null +++ b/test/core/transport/chttp2/bin_decoder_test.cc @@ -0,0 +1,143 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/bin_decoder.h" + +#include + +#include +#include +#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" + +static int all_ok = 1; + +static void expect_slice_eq(grpc_exec_ctx *exec_ctx, grpc_slice expected, + grpc_slice slice, const char *debug, int line) { + if (!grpc_slice_eq(slice, expected)) { + char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot: %s\nwant: %s", line, debug, hs, + he); + gpr_free(hs); + gpr_free(he); + all_ok = 0; + } + grpc_slice_unref_internal(exec_ctx, expected); + grpc_slice_unref_internal(exec_ctx, slice); +} + +static grpc_slice base64_encode(grpc_exec_ctx *exec_ctx, const char *s) { + grpc_slice ss = grpc_slice_from_copied_string(s); + grpc_slice out = grpc_chttp2_base64_encode(ss); + grpc_slice_unref_internal(exec_ctx, ss); + return out; +} + +static grpc_slice base64_decode(grpc_exec_ctx *exec_ctx, const char *s) { + grpc_slice ss = grpc_slice_from_copied_string(s); + grpc_slice out = grpc_chttp2_base64_decode(exec_ctx, ss); + grpc_slice_unref_internal(exec_ctx, ss); + return out; +} + +static grpc_slice base64_decode_with_length(grpc_exec_ctx *exec_ctx, + const char *s, + size_t output_length) { + grpc_slice ss = grpc_slice_from_copied_string(s); + grpc_slice out = + grpc_chttp2_base64_decode_with_length(exec_ctx, ss, output_length); + grpc_slice_unref_internal(exec_ctx, ss); + return out; +} + +#define EXPECT_SLICE_EQ(exec_ctx, expected, slice) \ + expect_slice_eq( \ + exec_ctx, grpc_slice_from_copied_buffer(expected, sizeof(expected) - 1), \ + slice, #slice, __LINE__); + +#define ENCODE_AND_DECODE(exec_ctx, s) \ + EXPECT_SLICE_EQ(exec_ctx, s, \ + grpc_chttp2_base64_decode_with_length( \ + exec_ctx, base64_encode(exec_ctx, s), strlen(s))); + +int main(int argc, char **argv) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + /* ENCODE_AND_DECODE tests grpc_chttp2_base64_decode_with_length(), which + takes encoded base64 strings without pad chars, but output length is + required. */ + /* Base64 test vectors from RFC 4648 */ + ENCODE_AND_DECODE(&exec_ctx, ""); + ENCODE_AND_DECODE(&exec_ctx, "f"); + ENCODE_AND_DECODE(&exec_ctx, "foo"); + ENCODE_AND_DECODE(&exec_ctx, "fo"); + ENCODE_AND_DECODE(&exec_ctx, "foob"); + ENCODE_AND_DECODE(&exec_ctx, "fooba"); + ENCODE_AND_DECODE(&exec_ctx, "foobar"); + + ENCODE_AND_DECODE(&exec_ctx, "\xc0\xc1\xc2\xc3\xc4\xc5"); + + /* Base64 test vectors from RFC 4648, with pad chars */ + /* BASE64("") = "" */ + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "")); + /* BASE64("f") = "Zg==" */ + EXPECT_SLICE_EQ(&exec_ctx, "f", base64_decode(&exec_ctx, "Zg==")); + /* BASE64("fo") = "Zm8=" */ + EXPECT_SLICE_EQ(&exec_ctx, "fo", base64_decode(&exec_ctx, "Zm8=")); + /* BASE64("foo") = "Zm9v" */ + EXPECT_SLICE_EQ(&exec_ctx, "foo", base64_decode(&exec_ctx, "Zm9v")); + /* BASE64("foob") = "Zm9vYg==" */ + EXPECT_SLICE_EQ(&exec_ctx, "foob", base64_decode(&exec_ctx, "Zm9vYg==")); + /* BASE64("fooba") = "Zm9vYmE=" */ + EXPECT_SLICE_EQ(&exec_ctx, "fooba", base64_decode(&exec_ctx, "Zm9vYmE=")); + /* BASE64("foobar") = "Zm9vYmFy" */ + EXPECT_SLICE_EQ(&exec_ctx, "foobar", base64_decode(&exec_ctx, "Zm9vYmFy")); + + EXPECT_SLICE_EQ(&exec_ctx, "\xc0\xc1\xc2\xc3\xc4\xc5", + base64_decode(&exec_ctx, "wMHCw8TF")); + + // Test illegal input length in grpc_chttp2_base64_decode + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "a")); + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "ab")); + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "abc")); + + // Test illegal charactors in grpc_chttp2_base64_decode + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "Zm:v")); + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode(&exec_ctx, "Zm=v")); + + // Test output_length longer than max possible output length in + // grpc_chttp2_base64_decode_with_length + EXPECT_SLICE_EQ(&exec_ctx, "", base64_decode_with_length(&exec_ctx, "Zg", 2)); + EXPECT_SLICE_EQ(&exec_ctx, "", + base64_decode_with_length(&exec_ctx, "Zm8", 3)); + EXPECT_SLICE_EQ(&exec_ctx, "", + base64_decode_with_length(&exec_ctx, "Zm9v", 4)); + + // Test illegal charactors in grpc_chttp2_base64_decode_with_length + EXPECT_SLICE_EQ(&exec_ctx, "", + base64_decode_with_length(&exec_ctx, "Zm:v", 3)); + EXPECT_SLICE_EQ(&exec_ctx, "", + base64_decode_with_length(&exec_ctx, "Zm=v", 3)); + + grpc_exec_ctx_finish(&exec_ctx); + + return all_ok ? 0 : 1; +} diff --git a/test/core/transport/chttp2/bin_encoder_test.c b/test/core/transport/chttp2/bin_encoder_test.c deleted file mode 100644 index acadcf6c89..0000000000 --- a/test/core/transport/chttp2/bin_encoder_test.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" - -#include - -/* This is here for grpc_is_binary_header - * TODO(murgatroid99): Remove this - */ -#include -#include -#include -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" - -static int all_ok = 1; - -static void expect_slice_eq(grpc_slice expected, grpc_slice slice, char *debug, - int line) { - if (!grpc_slice_eq(slice, expected)) { - char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot: %s\nwant: %s", line, debug, hs, - he); - gpr_free(hs); - gpr_free(he); - all_ok = 0; - } - grpc_slice_unref(expected); - grpc_slice_unref(slice); -} - -static grpc_slice B64(const char *s) { - grpc_slice ss = grpc_slice_from_copied_string(s); - grpc_slice out = grpc_chttp2_base64_encode(ss); - grpc_slice_unref(ss); - return out; -} - -static grpc_slice HUFF(const char *s) { - grpc_slice ss = grpc_slice_from_copied_string(s); - grpc_slice out = grpc_chttp2_huffman_compress(ss); - grpc_slice_unref(ss); - return out; -} - -#define EXPECT_SLICE_EQ(expected, slice) \ - expect_slice_eq( \ - grpc_slice_from_copied_buffer(expected, sizeof(expected) - 1), slice, \ - #slice, __LINE__); - -static void expect_combined_equiv(const char *s, size_t len, int line) { - grpc_slice input = grpc_slice_from_copied_buffer(s, len); - grpc_slice base64 = grpc_chttp2_base64_encode(input); - grpc_slice expect = grpc_chttp2_huffman_compress(base64); - grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input); - if (!grpc_slice_eq(expect, got)) { - char *t = grpc_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *e = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *g = grpc_dump_slice(got, GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_ERROR, "FAILED:%d:\ntest: %s\ngot: %s\nwant: %s", line, t, g, - e); - gpr_free(t); - gpr_free(e); - gpr_free(g); - all_ok = 0; - } - grpc_slice_unref(input); - grpc_slice_unref(base64); - grpc_slice_unref(expect); - grpc_slice_unref(got); -} - -#define EXPECT_COMBINED_EQUIV(x) \ - expect_combined_equiv(x, sizeof(x) - 1, __LINE__) - -static void expect_binary_header(const char *hdr, int binary) { - if (grpc_is_binary_header(grpc_slice_from_static_string(hdr)) != binary) { - gpr_log(GPR_ERROR, "FAILED: expected header '%s' to be %s", hdr, - binary ? "binary" : "not binary"); - all_ok = 0; - } -} - -int main(int argc, char **argv) { - /* Base64 test vectors from RFC 4648, with padding removed */ - /* BASE64("") = "" */ - EXPECT_SLICE_EQ("", B64("")); - /* BASE64("f") = "Zg" */ - EXPECT_SLICE_EQ("Zg", B64("f")); - /* BASE64("fo") = "Zm8" */ - EXPECT_SLICE_EQ("Zm8", B64("fo")); - /* BASE64("foo") = "Zm9v" */ - EXPECT_SLICE_EQ("Zm9v", B64("foo")); - /* BASE64("foob") = "Zm9vYg" */ - EXPECT_SLICE_EQ("Zm9vYg", B64("foob")); - /* BASE64("fooba") = "Zm9vYmE" */ - EXPECT_SLICE_EQ("Zm9vYmE", B64("fooba")); - /* BASE64("foobar") = "Zm9vYmFy" */ - EXPECT_SLICE_EQ("Zm9vYmFy", B64("foobar")); - - EXPECT_SLICE_EQ("wMHCw8TF", B64("\xc0\xc1\xc2\xc3\xc4\xc5")); - - /* Huffman encoding tests */ - EXPECT_SLICE_EQ("\xf1\xe3\xc2\xe5\xf2\x3a\x6b\xa0\xab\x90\xf4\xff", - HUFF("www.example.com")); - EXPECT_SLICE_EQ("\xa8\xeb\x10\x64\x9c\xbf", HUFF("no-cache")); - EXPECT_SLICE_EQ("\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f", HUFF("custom-key")); - EXPECT_SLICE_EQ("\x25\xa8\x49\xe9\x5b\xb8\xe8\xb4\xbf", HUFF("custom-value")); - EXPECT_SLICE_EQ("\xae\xc3\x77\x1a\x4b", HUFF("private")); - EXPECT_SLICE_EQ( - "\xd0\x7a\xbe\x94\x10\x54\xd4\x44\xa8\x20\x05\x95\x04\x0b\x81\x66\xe0\x82" - "\xa6\x2d\x1b\xff", - HUFF("Mon, 21 Oct 2013 20:13:21 GMT")); - EXPECT_SLICE_EQ( - "\x9d\x29\xad\x17\x18\x63\xc7\x8f\x0b\x97\xc8\xe9\xae\x82\xae\x43\xd3", - HUFF("https://www.example.com")); - - /* Various test vectors for combined encoding */ - EXPECT_COMBINED_EQUIV(""); - EXPECT_COMBINED_EQUIV("f"); - EXPECT_COMBINED_EQUIV("fo"); - EXPECT_COMBINED_EQUIV("foo"); - EXPECT_COMBINED_EQUIV("foob"); - EXPECT_COMBINED_EQUIV("fooba"); - EXPECT_COMBINED_EQUIV("foobar"); - EXPECT_COMBINED_EQUIV("www.example.com"); - EXPECT_COMBINED_EQUIV("no-cache"); - EXPECT_COMBINED_EQUIV("custom-key"); - EXPECT_COMBINED_EQUIV("custom-value"); - EXPECT_COMBINED_EQUIV("private"); - EXPECT_COMBINED_EQUIV("Mon, 21 Oct 2013 20:13:21 GMT"); - EXPECT_COMBINED_EQUIV("https://www.example.com"); - EXPECT_COMBINED_EQUIV( - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"); - - expect_binary_header("foo-bin", 1); - expect_binary_header("foo-bar", 0); - expect_binary_header("-bin", 0); - - return all_ok ? 0 : 1; -} diff --git a/test/core/transport/chttp2/bin_encoder_test.cc b/test/core/transport/chttp2/bin_encoder_test.cc new file mode 100644 index 0000000000..d073f74d27 --- /dev/null +++ b/test/core/transport/chttp2/bin_encoder_test.cc @@ -0,0 +1,173 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" + +#include + +/* This is here for grpc_is_binary_header + * TODO(murgatroid99): Remove this + */ +#include +#include +#include +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" + +static int all_ok = 1; + +static void expect_slice_eq(grpc_slice expected, grpc_slice slice, + const char *debug, int line) { + if (!grpc_slice_eq(slice, expected)) { + char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot: %s\nwant: %s", line, debug, hs, + he); + gpr_free(hs); + gpr_free(he); + all_ok = 0; + } + grpc_slice_unref(expected); + grpc_slice_unref(slice); +} + +static grpc_slice B64(const char *s) { + grpc_slice ss = grpc_slice_from_copied_string(s); + grpc_slice out = grpc_chttp2_base64_encode(ss); + grpc_slice_unref(ss); + return out; +} + +static grpc_slice HUFF(const char *s) { + grpc_slice ss = grpc_slice_from_copied_string(s); + grpc_slice out = grpc_chttp2_huffman_compress(ss); + grpc_slice_unref(ss); + return out; +} + +#define EXPECT_SLICE_EQ(expected, slice) \ + expect_slice_eq( \ + grpc_slice_from_copied_buffer(expected, sizeof(expected) - 1), slice, \ + #slice, __LINE__); + +static void expect_combined_equiv(const char *s, size_t len, int line) { + grpc_slice input = grpc_slice_from_copied_buffer(s, len); + grpc_slice base64 = grpc_chttp2_base64_encode(input); + grpc_slice expect = grpc_chttp2_huffman_compress(base64); + grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input); + if (!grpc_slice_eq(expect, got)) { + char *t = grpc_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *e = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *g = grpc_dump_slice(got, GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_ERROR, "FAILED:%d:\ntest: %s\ngot: %s\nwant: %s", line, t, g, + e); + gpr_free(t); + gpr_free(e); + gpr_free(g); + all_ok = 0; + } + grpc_slice_unref(input); + grpc_slice_unref(base64); + grpc_slice_unref(expect); + grpc_slice_unref(got); +} + +#define EXPECT_COMBINED_EQUIV(x) \ + expect_combined_equiv(x, sizeof(x) - 1, __LINE__) + +static void expect_binary_header(const char *hdr, int binary) { + if (grpc_is_binary_header(grpc_slice_from_static_string(hdr)) != binary) { + gpr_log(GPR_ERROR, "FAILED: expected header '%s' to be %s", hdr, + binary ? "binary" : "not binary"); + all_ok = 0; + } +} + +int main(int argc, char **argv) { + /* Base64 test vectors from RFC 4648, with padding removed */ + /* BASE64("") = "" */ + EXPECT_SLICE_EQ("", B64("")); + /* BASE64("f") = "Zg" */ + EXPECT_SLICE_EQ("Zg", B64("f")); + /* BASE64("fo") = "Zm8" */ + EXPECT_SLICE_EQ("Zm8", B64("fo")); + /* BASE64("foo") = "Zm9v" */ + EXPECT_SLICE_EQ("Zm9v", B64("foo")); + /* BASE64("foob") = "Zm9vYg" */ + EXPECT_SLICE_EQ("Zm9vYg", B64("foob")); + /* BASE64("fooba") = "Zm9vYmE" */ + EXPECT_SLICE_EQ("Zm9vYmE", B64("fooba")); + /* BASE64("foobar") = "Zm9vYmFy" */ + EXPECT_SLICE_EQ("Zm9vYmFy", B64("foobar")); + + EXPECT_SLICE_EQ("wMHCw8TF", B64("\xc0\xc1\xc2\xc3\xc4\xc5")); + + /* Huffman encoding tests */ + EXPECT_SLICE_EQ("\xf1\xe3\xc2\xe5\xf2\x3a\x6b\xa0\xab\x90\xf4\xff", + HUFF("www.example.com")); + EXPECT_SLICE_EQ("\xa8\xeb\x10\x64\x9c\xbf", HUFF("no-cache")); + EXPECT_SLICE_EQ("\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f", HUFF("custom-key")); + EXPECT_SLICE_EQ("\x25\xa8\x49\xe9\x5b\xb8\xe8\xb4\xbf", HUFF("custom-value")); + EXPECT_SLICE_EQ("\xae\xc3\x77\x1a\x4b", HUFF("private")); + EXPECT_SLICE_EQ( + "\xd0\x7a\xbe\x94\x10\x54\xd4\x44\xa8\x20\x05\x95\x04\x0b\x81\x66\xe0\x82" + "\xa6\x2d\x1b\xff", + HUFF("Mon, 21 Oct 2013 20:13:21 GMT")); + EXPECT_SLICE_EQ( + "\x9d\x29\xad\x17\x18\x63\xc7\x8f\x0b\x97\xc8\xe9\xae\x82\xae\x43\xd3", + HUFF("https://www.example.com")); + + /* Various test vectors for combined encoding */ + EXPECT_COMBINED_EQUIV(""); + EXPECT_COMBINED_EQUIV("f"); + EXPECT_COMBINED_EQUIV("fo"); + EXPECT_COMBINED_EQUIV("foo"); + EXPECT_COMBINED_EQUIV("foob"); + EXPECT_COMBINED_EQUIV("fooba"); + EXPECT_COMBINED_EQUIV("foobar"); + EXPECT_COMBINED_EQUIV("www.example.com"); + EXPECT_COMBINED_EQUIV("no-cache"); + EXPECT_COMBINED_EQUIV("custom-key"); + EXPECT_COMBINED_EQUIV("custom-value"); + EXPECT_COMBINED_EQUIV("private"); + EXPECT_COMBINED_EQUIV("Mon, 21 Oct 2013 20:13:21 GMT"); + EXPECT_COMBINED_EQUIV("https://www.example.com"); + EXPECT_COMBINED_EQUIV( + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"); + + expect_binary_header("foo-bin", 1); + expect_binary_header("foo-bar", 0); + expect_binary_header("-bin", 0); + + return all_ok ? 0 : 1; +} diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c deleted file mode 100644 index a2af83b6cb..0000000000 --- a/test/core/transport/chttp2/hpack_encoder_test.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" - -#include -#include - -#include -#include -#include - -#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/transport/metadata.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; - -typedef struct { - bool eof; - bool use_true_binary_metadata; - bool only_intern_key; -} verify_params; - -/* verify that the output generated by encoding the stream matches the - hexstring passed in */ -static void verify(grpc_exec_ctx *exec_ctx, const verify_params params, - const char *expected, size_t nheaders, ...) { - grpc_slice_buffer output; - grpc_slice merged; - grpc_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]; - } - grpc_slice value_slice = grpc_slice_from_static_string(value); - if (!params.only_intern_key) { - value_slice = grpc_slice_intern(value_slice); - } - e[i].md = grpc_mdelem_from_slices( - exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), - value_slice); - } - e[0].prev = NULL; - e[nheaders - 1].next = NULL; - va_end(l); - - b.list.head = &e[0]; - b.list.tail = &e[nheaders - 1]; - b.list.count = nheaders; - - 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_slice_buffer_init(&output); - - grpc_transport_one_way_stats stats; - memset(&stats, 0, sizeof(stats)); - grpc_encode_header_options hopt = { - .stream_id = 0xdeadbeef, - .is_eof = params.eof, - .use_true_binary_metadata = params.use_true_binary_metadata, - .max_frame_size = 16384, - .stats = &stats, - }; - grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt, - &output); - merged = grpc_slice_merge(output.slices, output.count); - grpc_slice_buffer_destroy_internal(exec_ctx, &output); - grpc_metadata_batch_destroy(exec_ctx, &b); - - if (!grpc_slice_eq(merged, expect)) { - char *expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); - char *got_str = grpc_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; - } - - grpc_slice_unref_internal(exec_ctx, merged); - grpc_slice_unref_internal(exec_ctx, expect); -} - -static void test_basic_headers(grpc_exec_ctx *exec_ctx) { - int i; - - verify_params params = { - .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, - }; - verify(exec_ctx, params, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a"); - verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); - verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); - verify(exec_ctx, params, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", - "b", "c"); - verify(exec_ctx, params, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c"); - verify(exec_ctx, params, "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(exec_ctx, params, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", - "c", "a", "d"); - } - - verify(exec_ctx, params, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", - "k", "v"); - /* this could be 000004 0104 deadbeef 0f 30 0176 also */ - verify(exec_ctx, params, "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(grpc_exec_ctx *exec_ctx) { - int i; - char key[3], value[3]; - char *expect; - - verify_params params = { - .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, - }; - - 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(exec_ctx, params, expect, 2, "aa", "ba", key, value); - } else { - verify(exec_ctx, params, 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(exec_ctx, params, "000007 0104 deadbeef 40 026161 026261", 1, "aa", - "ba"); -} - -static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx, - const char *key, - const char *value, - bool use_true_binary) { - grpc_slice_buffer output; - grpc_mdelem elem = grpc_mdelem_from_slices( - exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), - grpc_slice_intern(grpc_slice_from_static_string(value))); - size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, use_true_binary); - size_t initial_table_size = g_compressor.table_size; - grpc_linked_mdelem *e = gpr_malloc(sizeof(*e)); - grpc_metadata_batch b; - grpc_metadata_batch_init(&b); - e[0].md = elem; - e[0].prev = NULL; - e[0].next = NULL; - b.list.head = &e[0]; - b.list.tail = &e[0]; - b.list.count = 1; - grpc_slice_buffer_init(&output); - - grpc_transport_one_way_stats stats; - memset(&stats, 0, sizeof(stats)); - grpc_encode_header_options hopt = { - .stream_id = 0xdeadbeef, - .is_eof = false, - .use_true_binary_metadata = use_true_binary, - .max_frame_size = 16384, - .stats = &stats}; - grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt, - &output); - grpc_slice_buffer_destroy_internal(exec_ctx, &output); - grpc_metadata_batch_destroy(exec_ctx, &b); - - GPR_ASSERT(g_compressor.table_size == elem_size + initial_table_size); - gpr_free(e); -} - -static void test_encode_header_size(grpc_exec_ctx *exec_ctx) { - verify_table_size_change_match_elem_size(exec_ctx, "hello", "world", false); - verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world", - false); - verify_table_size_change_match_elem_size(exec_ctx, "true-binary-bin", - "I_am_true_binary_value", true); -} - -static void test_interned_key_indexed(grpc_exec_ctx *exec_ctx) { - int i; - verify_params params = { - .eof = false, .use_true_binary_metadata = false, .only_intern_key = true, - }; - verify(exec_ctx, params, "000009 0104 deadbeef 40 0161 0162 0f2f 0163", 2, - "a", "b", "a", "c"); - for (i = 0; i < 10; i++) { - verify(exec_ctx, params, "000008 0104 deadbeef 0f2f 0162 0f2f 0163", 2, "a", - "b", "a", "c"); - } -} - -static void run_test(void (*test)(grpc_exec_ctx *exec_ctx), const char *name) { - gpr_log(GPR_INFO, "RUN TEST: %s", name); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_chttp2_hpack_compressor_init(&g_compressor); - test(&exec_ctx); - grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &g_compressor); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - size_t i; - grpc_test_only_set_slice_hash_seed(0); - grpc_test_init(argc, argv); - grpc_init(); - TEST(test_basic_headers); - TEST(test_decode_table_overflow); - TEST(test_encode_header_size); - TEST(test_interned_key_indexed); - 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_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc new file mode 100644 index 0000000000..b203df1892 --- /dev/null +++ b/test/core/transport/chttp2/hpack_encoder_test.cc @@ -0,0 +1,287 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" + +#include +#include + +#include +#include +#include + +#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/transport/metadata.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; + +typedef struct { + bool eof; + bool use_true_binary_metadata; + bool only_intern_key; +} verify_params; + +/* verify that the output generated by encoding the stream matches the + hexstring passed in */ +static void verify(grpc_exec_ctx *exec_ctx, const verify_params params, + const char *expected, size_t nheaders, ...) { + grpc_slice_buffer output; + grpc_slice merged; + grpc_slice expect = parse_hexstring(expected); + size_t i; + va_list l; + grpc_linked_mdelem *e = + static_cast(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]; + } + grpc_slice value_slice = grpc_slice_from_static_string(value); + if (!params.only_intern_key) { + value_slice = grpc_slice_intern(value_slice); + } + e[i].md = grpc_mdelem_from_slices( + exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), + value_slice); + } + e[0].prev = NULL; + e[nheaders - 1].next = NULL; + va_end(l); + + b.list.head = &e[0]; + b.list.tail = &e[nheaders - 1]; + b.list.count = nheaders; + + if (cap_to_delete == num_to_delete) { + cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000); + to_delete = static_cast( + gpr_realloc(to_delete, sizeof(*to_delete) * cap_to_delete)); + } + to_delete[num_to_delete++] = e; + + grpc_slice_buffer_init(&output); + + grpc_transport_one_way_stats stats; + memset(&stats, 0, sizeof(stats)); + grpc_encode_header_options hopt = { + .stream_id = 0xdeadbeef, + .is_eof = params.eof, + .use_true_binary_metadata = params.use_true_binary_metadata, + .max_frame_size = 16384, + .stats = &stats, + }; + grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt, + &output); + merged = grpc_slice_merge(output.slices, output.count); + grpc_slice_buffer_destroy_internal(exec_ctx, &output); + grpc_metadata_batch_destroy(exec_ctx, &b); + + if (!grpc_slice_eq(merged, expect)) { + char *expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII); + char *got_str = grpc_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; + } + + grpc_slice_unref_internal(exec_ctx, merged); + grpc_slice_unref_internal(exec_ctx, expect); +} + +static void test_basic_headers(grpc_exec_ctx *exec_ctx) { + int i; + + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, + }; + verify(exec_ctx, params, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a"); + verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); + verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a"); + verify(exec_ctx, params, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a", + "b", "c"); + verify(exec_ctx, params, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c"); + verify(exec_ctx, params, "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(exec_ctx, params, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b", + "c", "a", "d"); + } + + verify(exec_ctx, params, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a", + "k", "v"); + /* this could be 000004 0104 deadbeef 0f 30 0176 also */ + verify(exec_ctx, params, "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(grpc_exec_ctx *exec_ctx) { + int i; + char key[3], value[3]; + char *expect; + + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = false, + }; + + 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(exec_ctx, params, expect, 2, "aa", "ba", key, value); + } else { + verify(exec_ctx, params, 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(exec_ctx, params, "000007 0104 deadbeef 40 026161 026261", 1, "aa", + "ba"); +} + +static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx, + const char *key, + const char *value, + bool use_true_binary) { + grpc_slice_buffer output; + grpc_mdelem elem = grpc_mdelem_from_slices( + exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)), + grpc_slice_intern(grpc_slice_from_static_string(value))); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, use_true_binary); + size_t initial_table_size = g_compressor.table_size; + grpc_linked_mdelem *e = + static_cast(gpr_malloc(sizeof(*e))); + grpc_metadata_batch b; + grpc_metadata_batch_init(&b); + e[0].md = elem; + e[0].prev = NULL; + e[0].next = NULL; + b.list.head = &e[0]; + b.list.tail = &e[0]; + b.list.count = 1; + grpc_slice_buffer_init(&output); + + grpc_transport_one_way_stats stats; + memset(&stats, 0, sizeof(stats)); + grpc_encode_header_options hopt = { + .stream_id = 0xdeadbeef, + .is_eof = false, + .use_true_binary_metadata = use_true_binary, + .max_frame_size = 16384, + .stats = &stats}; + grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt, + &output); + grpc_slice_buffer_destroy_internal(exec_ctx, &output); + grpc_metadata_batch_destroy(exec_ctx, &b); + + GPR_ASSERT(g_compressor.table_size == elem_size + initial_table_size); + gpr_free(e); +} + +static void test_encode_header_size(grpc_exec_ctx *exec_ctx) { + verify_table_size_change_match_elem_size(exec_ctx, "hello", "world", false); + verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world", + false); + verify_table_size_change_match_elem_size(exec_ctx, "true-binary-bin", + "I_am_true_binary_value", true); +} + +static void test_interned_key_indexed(grpc_exec_ctx *exec_ctx) { + int i; + verify_params params = { + .eof = false, .use_true_binary_metadata = false, .only_intern_key = true, + }; + verify(exec_ctx, params, "000009 0104 deadbeef 40 0161 0162 0f2f 0163", 2, + "a", "b", "a", "c"); + for (i = 0; i < 10; i++) { + verify(exec_ctx, params, "000008 0104 deadbeef 0f2f 0162 0f2f 0163", 2, "a", + "b", "a", "c"); + } +} + +static void run_test(void (*test)(grpc_exec_ctx *exec_ctx), const char *name) { + gpr_log(GPR_INFO, "RUN TEST: %s", name); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hpack_compressor_init(&g_compressor); + test(&exec_ctx); + grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &g_compressor); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + size_t i; + grpc_test_only_set_slice_hash_seed(0); + grpc_test_init(argc, argv); + grpc_init(); + TEST(test_basic_headers); + TEST(test_decode_table_overflow); + TEST(test_encode_header_size); + TEST(test_interned_key_indexed); + 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_fuzzer_test.c b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c deleted file mode 100644 index 03834084cb..0000000000 --- a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include -#include - -#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" -#include "src/core/lib/slice/slice_internal.h" - -bool squelch = true; -bool leak_check = true; - -static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) { - GRPC_MDELEM_UNREF(exec_ctx, md); -} -static void dont_log(gpr_log_func_args *args) {} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - grpc_test_only_set_slice_hash_seed(0); - if (squelch) gpr_set_log_function(dont_log); - grpc_init(); - grpc_chttp2_hpack_parser parser; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - parser.on_header = onhdr; - GRPC_ERROR_UNREF(grpc_chttp2_hpack_parser_parse( - &exec_ctx, &parser, grpc_slice_from_static_buffer(data, size))); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - return 0; -} diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc b/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc new file mode 100644 index 0000000000..03834084cb --- /dev/null +++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc @@ -0,0 +1,51 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" +#include "src/core/lib/slice/slice_internal.h" + +bool squelch = true; +bool leak_check = true; + +static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) { + GRPC_MDELEM_UNREF(exec_ctx, md); +} +static void dont_log(gpr_log_func_args *args) {} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + grpc_test_only_set_slice_hash_seed(0); + if (squelch) gpr_set_log_function(dont_log); + grpc_init(); + grpc_chttp2_hpack_parser parser; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + parser.on_header = onhdr; + GRPC_ERROR_UNREF(grpc_chttp2_hpack_parser_parse( + &exec_ctx, &parser, grpc_slice_from_static_buffer(data, size))); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + return 0; +} diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c deleted file mode 100644 index 0946c05261..0000000000 --- a/test/core/transport/chttp2/hpack_parser_test.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" - -#include - -#include -#include -#include -#include -#include "test/core/util/parse_hexstring.h" -#include "test/core/util/slice_splitter.h" -#include "test/core/util/test_config.h" - -typedef struct { va_list args; } test_checker; - -static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) { - const char *ekey, *evalue; - test_checker *chk = ud; - ekey = va_arg(chk->args, char *); - GPR_ASSERT(ekey); - evalue = va_arg(chk->args, char *); - GPR_ASSERT(evalue); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(md), ekey) == 0); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md), evalue) == 0); - GRPC_MDELEM_UNREF(exec_ctx, md); -} - -static void test_vector(grpc_chttp2_hpack_parser *parser, - grpc_slice_split_mode mode, const char *hexstring, - ... /* char *key, char *value */) { - grpc_slice input = parse_hexstring(hexstring); - grpc_slice *slices; - size_t nslices; - size_t i; - test_checker chk; - - va_start(chk.args, hexstring); - - parser->on_header = onhdr; - parser->on_header_user_data = &chk; - - grpc_split_slices(mode, &input, 1, &slices, &nslices); - grpc_slice_unref(input); - - for (i = 0; i < nslices; i++) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - GPR_ASSERT(grpc_chttp2_hpack_parser_parse(&exec_ctx, parser, slices[i]) == - GRPC_ERROR_NONE); - grpc_exec_ctx_finish(&exec_ctx); - } - - for (i = 0; i < nslices; i++) { - grpc_slice_unref(slices[i]); - } - gpr_free(slices); - - GPR_ASSERT(NULL == va_arg(chk.args, char *)); - - va_end(chk.args); -} - -static void test_vectors(grpc_slice_split_mode mode) { - grpc_chttp2_hpack_parser parser; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - /* D.2.1 */ - test_vector(&parser, mode, - "400a 6375 7374 6f6d 2d6b 6579 0d63 7573" - "746f 6d2d 6865 6164 6572", - "custom-key", "custom-header", NULL); - /* D.2.2 */ - test_vector(&parser, mode, "040c 2f73 616d 706c 652f 7061 7468", ":path", - "/sample/path", NULL); - /* D.2.3 */ - test_vector(&parser, mode, - "1008 7061 7373 776f 7264 0673 6563 7265" - "74", - "password", "secret", NULL); - /* D.2.4 */ - test_vector(&parser, mode, "82", ":method", "GET", NULL); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - /* D.3.1 */ - test_vector(&parser, mode, - "8286 8441 0f77 7777 2e65 7861 6d70 6c65" - "2e63 6f6d", - ":method", "GET", ":scheme", "http", ":path", "/", ":authority", - "www.example.com", NULL); - /* D.3.2 */ - test_vector(&parser, mode, "8286 84be 5808 6e6f 2d63 6163 6865", ":method", - "GET", ":scheme", "http", ":path", "/", ":authority", - "www.example.com", "cache-control", "no-cache", NULL); - /* D.3.3 */ - test_vector(&parser, mode, - "8287 85bf 400a 6375 7374 6f6d 2d6b 6579" - "0c63 7573 746f 6d2d 7661 6c75 65", - ":method", "GET", ":scheme", "https", ":path", "/index.html", - ":authority", "www.example.com", "custom-key", "custom-value", - NULL); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - /* D.4.1 */ - test_vector(&parser, mode, - "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4" - "ff", - ":method", "GET", ":scheme", "http", ":path", "/", ":authority", - "www.example.com", NULL); - /* D.4.2 */ - test_vector(&parser, mode, "8286 84be 5886 a8eb 1064 9cbf", ":method", "GET", - ":scheme", "http", ":path", "/", ":authority", "www.example.com", - "cache-control", "no-cache", NULL); - /* D.4.3 */ - test_vector(&parser, mode, - "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925" - "a849 e95b b8e8 b4bf", - ":method", "GET", ":scheme", "https", ":path", "/index.html", - ":authority", "www.example.com", "custom-key", "custom-value", - NULL); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - grpc_chttp2_hptbl_set_max_bytes(&exec_ctx, &parser.table, 256); - grpc_chttp2_hptbl_set_current_table_size(&exec_ctx, &parser.table, 256); - /* D.5.1 */ - test_vector(&parser, mode, - "4803 3330 3258 0770 7269 7661 7465 611d" - "4d6f 6e2c 2032 3120 4f63 7420 3230 3133" - "2032 303a 3133 3a32 3120 474d 546e 1768" - "7474 7073 3a2f 2f77 7777 2e65 7861 6d70" - "6c65 2e63 6f6d", - ":status", "302", "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:21 GMT", "location", - "https://www.example.com", NULL); - /* D.5.2 */ - test_vector(&parser, mode, "4803 3330 37c1 c0bf", ":status", "307", - "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:21 GMT", "location", - "https://www.example.com", NULL); - /* D.5.3 */ - test_vector(&parser, mode, - "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420" - "3230 3133 2032 303a 3133 3a32 3220 474d" - "54c0 5a04 677a 6970 7738 666f 6f3d 4153" - "444a 4b48 514b 425a 584f 5157 454f 5049" - "5541 5851 5745 4f49 553b 206d 6178 2d61" - "6765 3d33 3630 303b 2076 6572 7369 6f6e" - "3d31", - ":status", "200", "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:22 GMT", "location", - "https://www.example.com", "content-encoding", "gzip", - "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - - grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); - grpc_chttp2_hptbl_set_max_bytes(&exec_ctx, &parser.table, 256); - grpc_chttp2_hptbl_set_current_table_size(&exec_ctx, &parser.table, 256); - /* D.6.1 */ - test_vector(&parser, mode, - "4882 6402 5885 aec3 771a 4b61 96d0 7abe" - "9410 54d4 44a8 2005 9504 0b81 66e0 82a6" - "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8" - "e9ae 82ae 43d3", - ":status", "302", "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:21 GMT", "location", - "https://www.example.com", NULL); - /* D.6.2 */ - test_vector(&parser, mode, "4883 640e ffc1 c0bf", ":status", "307", - "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:21 GMT", "location", - "https://www.example.com", NULL); - /* D.6.3 */ - test_vector(&parser, mode, - "88c1 6196 d07a be94 1054 d444 a820 0595" - "040b 8166 e084 a62d 1bff c05a 839b d9ab" - "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b" - "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f" - "9587 3160 65c0 03ed 4ee5 b106 3d50 07", - ":status", "200", "cache-control", "private", "date", - "Mon, 21 Oct 2013 20:13:22 GMT", "location", - "https://www.example.com", "content-encoding", "gzip", - "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); - grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); - - grpc_exec_ctx_finish(&exec_ctx); -} - -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_parser_test.cc b/test/core/transport/chttp2/hpack_parser_test.cc new file mode 100644 index 0000000000..27b4a1c2c0 --- /dev/null +++ b/test/core/transport/chttp2/hpack_parser_test.cc @@ -0,0 +1,216 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" + +#include + +#include +#include +#include +#include +#include "test/core/util/parse_hexstring.h" +#include "test/core/util/slice_splitter.h" +#include "test/core/util/test_config.h" + +typedef struct { va_list args; } test_checker; + +static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) { + const char *ekey, *evalue; + test_checker *chk = static_cast(ud); + ekey = va_arg(chk->args, char *); + GPR_ASSERT(ekey); + evalue = va_arg(chk->args, char *); + GPR_ASSERT(evalue); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(md), ekey) == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md), evalue) == 0); + GRPC_MDELEM_UNREF(exec_ctx, md); +} + +static void test_vector(grpc_chttp2_hpack_parser *parser, + grpc_slice_split_mode mode, const char *hexstring, + ... /* char *key, char *value */) { + grpc_slice input = parse_hexstring(hexstring); + grpc_slice *slices; + size_t nslices; + size_t i; + test_checker chk; + + va_start(chk.args, hexstring); + + parser->on_header = onhdr; + parser->on_header_user_data = &chk; + + grpc_split_slices(mode, &input, 1, &slices, &nslices); + grpc_slice_unref(input); + + for (i = 0; i < nslices; i++) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GPR_ASSERT(grpc_chttp2_hpack_parser_parse(&exec_ctx, parser, slices[i]) == + GRPC_ERROR_NONE); + grpc_exec_ctx_finish(&exec_ctx); + } + + for (i = 0; i < nslices; i++) { + grpc_slice_unref(slices[i]); + } + gpr_free(slices); + + GPR_ASSERT(NULL == va_arg(chk.args, char *)); + + va_end(chk.args); +} + +static void test_vectors(grpc_slice_split_mode mode) { + grpc_chttp2_hpack_parser parser; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + /* D.2.1 */ + test_vector(&parser, mode, + "400a 6375 7374 6f6d 2d6b 6579 0d63 7573" + "746f 6d2d 6865 6164 6572", + "custom-key", "custom-header", NULL); + /* D.2.2 */ + test_vector(&parser, mode, "040c 2f73 616d 706c 652f 7061 7468", ":path", + "/sample/path", NULL); + /* D.2.3 */ + test_vector(&parser, mode, + "1008 7061 7373 776f 7264 0673 6563 7265" + "74", + "password", "secret", NULL); + /* D.2.4 */ + test_vector(&parser, mode, "82", ":method", "GET", NULL); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + /* D.3.1 */ + test_vector(&parser, mode, + "8286 8441 0f77 7777 2e65 7861 6d70 6c65" + "2e63 6f6d", + ":method", "GET", ":scheme", "http", ":path", "/", ":authority", + "www.example.com", NULL); + /* D.3.2 */ + test_vector(&parser, mode, "8286 84be 5808 6e6f 2d63 6163 6865", ":method", + "GET", ":scheme", "http", ":path", "/", ":authority", + "www.example.com", "cache-control", "no-cache", NULL); + /* D.3.3 */ + test_vector(&parser, mode, + "8287 85bf 400a 6375 7374 6f6d 2d6b 6579" + "0c63 7573 746f 6d2d 7661 6c75 65", + ":method", "GET", ":scheme", "https", ":path", "/index.html", + ":authority", "www.example.com", "custom-key", "custom-value", + NULL); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + /* D.4.1 */ + test_vector(&parser, mode, + "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4" + "ff", + ":method", "GET", ":scheme", "http", ":path", "/", ":authority", + "www.example.com", NULL); + /* D.4.2 */ + test_vector(&parser, mode, "8286 84be 5886 a8eb 1064 9cbf", ":method", "GET", + ":scheme", "http", ":path", "/", ":authority", "www.example.com", + "cache-control", "no-cache", NULL); + /* D.4.3 */ + test_vector(&parser, mode, + "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925" + "a849 e95b b8e8 b4bf", + ":method", "GET", ":scheme", "https", ":path", "/index.html", + ":authority", "www.example.com", "custom-key", "custom-value", + NULL); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + grpc_chttp2_hptbl_set_max_bytes(&exec_ctx, &parser.table, 256); + grpc_chttp2_hptbl_set_current_table_size(&exec_ctx, &parser.table, 256); + /* D.5.1 */ + test_vector(&parser, mode, + "4803 3330 3258 0770 7269 7661 7465 611d" + "4d6f 6e2c 2032 3120 4f63 7420 3230 3133" + "2032 303a 3133 3a32 3120 474d 546e 1768" + "7474 7073 3a2f 2f77 7777 2e65 7861 6d70" + "6c65 2e63 6f6d", + ":status", "302", "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:21 GMT", "location", + "https://www.example.com", NULL); + /* D.5.2 */ + test_vector(&parser, mode, "4803 3330 37c1 c0bf", ":status", "307", + "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:21 GMT", "location", + "https://www.example.com", NULL); + /* D.5.3 */ + test_vector(&parser, mode, + "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420" + "3230 3133 2032 303a 3133 3a32 3220 474d" + "54c0 5a04 677a 6970 7738 666f 6f3d 4153" + "444a 4b48 514b 425a 584f 5157 454f 5049" + "5541 5851 5745 4f49 553b 206d 6178 2d61" + "6765 3d33 3630 303b 2076 6572 7369 6f6e" + "3d31", + ":status", "200", "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:22 GMT", "location", + "https://www.example.com", "content-encoding", "gzip", + "set-cookie", + "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + + grpc_chttp2_hpack_parser_init(&exec_ctx, &parser); + grpc_chttp2_hptbl_set_max_bytes(&exec_ctx, &parser.table, 256); + grpc_chttp2_hptbl_set_current_table_size(&exec_ctx, &parser.table, 256); + /* D.6.1 */ + test_vector(&parser, mode, + "4882 6402 5885 aec3 771a 4b61 96d0 7abe" + "9410 54d4 44a8 2005 9504 0b81 66e0 82a6" + "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8" + "e9ae 82ae 43d3", + ":status", "302", "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:21 GMT", "location", + "https://www.example.com", NULL); + /* D.6.2 */ + test_vector(&parser, mode, "4883 640e ffc1 c0bf", ":status", "307", + "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:21 GMT", "location", + "https://www.example.com", NULL); + /* D.6.3 */ + test_vector(&parser, mode, + "88c1 6196 d07a be94 1054 d444 a820 0595" + "040b 8166 e084 a62d 1bff c05a 839b d9ab" + "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b" + "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f" + "9587 3160 65c0 03ed 4ee5 b106 3d50 07", + ":status", "200", "cache-control", "private", "date", + "Mon, 21 Oct 2013 20:13:22 GMT", "location", + "https://www.example.com", "content-encoding", "gzip", + "set-cookie", + "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", NULL); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser); + + grpc_exec_ctx_finish(&exec_ctx); +} + +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 deleted file mode 100644 index 430ece33c7..0000000000 --- a/test/core/transport/chttp2/hpack_table_test.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/hpack_table.h" - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_slice mdstr, - const char *str) { - GPR_ASSERT(grpc_slice_str_cmp(mdstr, str) == 0); -} - -static void assert_index(const grpc_chttp2_hptbl *tbl, uint32_t idx, - const char *key, const char *value) { - grpc_mdelem md = grpc_chttp2_hptbl_lookup(tbl, idx); - assert_str(tbl, GRPC_MDKEY(md), key); - assert_str(tbl, GRPC_MDVALUE(md), value); -} - -static void test_static_lookup(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_chttp2_hptbl tbl; - - grpc_chttp2_hptbl_init(&exec_ctx, &tbl); - - LOG_TEST("test_static_lookup"); - assert_index(&tbl, 1, ":authority", ""); - assert_index(&tbl, 2, ":method", "GET"); - assert_index(&tbl, 3, ":method", "POST"); - assert_index(&tbl, 4, ":path", "/"); - assert_index(&tbl, 5, ":path", "/index.html"); - assert_index(&tbl, 6, ":scheme", "http"); - assert_index(&tbl, 7, ":scheme", "https"); - assert_index(&tbl, 8, ":status", "200"); - assert_index(&tbl, 9, ":status", "204"); - assert_index(&tbl, 10, ":status", "206"); - assert_index(&tbl, 11, ":status", "304"); - assert_index(&tbl, 12, ":status", "400"); - assert_index(&tbl, 13, ":status", "404"); - assert_index(&tbl, 14, ":status", "500"); - assert_index(&tbl, 15, "accept-charset", ""); - assert_index(&tbl, 16, "accept-encoding", "gzip, deflate"); - assert_index(&tbl, 17, "accept-language", ""); - assert_index(&tbl, 18, "accept-ranges", ""); - assert_index(&tbl, 19, "accept", ""); - assert_index(&tbl, 20, "access-control-allow-origin", ""); - assert_index(&tbl, 21, "age", ""); - assert_index(&tbl, 22, "allow", ""); - assert_index(&tbl, 23, "authorization", ""); - assert_index(&tbl, 24, "cache-control", ""); - assert_index(&tbl, 25, "content-disposition", ""); - assert_index(&tbl, 26, "content-encoding", ""); - assert_index(&tbl, 27, "content-language", ""); - assert_index(&tbl, 28, "content-length", ""); - assert_index(&tbl, 29, "content-location", ""); - assert_index(&tbl, 30, "content-range", ""); - assert_index(&tbl, 31, "content-type", ""); - assert_index(&tbl, 32, "cookie", ""); - assert_index(&tbl, 33, "date", ""); - assert_index(&tbl, 34, "etag", ""); - assert_index(&tbl, 35, "expect", ""); - assert_index(&tbl, 36, "expires", ""); - assert_index(&tbl, 37, "from", ""); - assert_index(&tbl, 38, "host", ""); - assert_index(&tbl, 39, "if-match", ""); - assert_index(&tbl, 40, "if-modified-since", ""); - assert_index(&tbl, 41, "if-none-match", ""); - assert_index(&tbl, 42, "if-range", ""); - assert_index(&tbl, 43, "if-unmodified-since", ""); - assert_index(&tbl, 44, "last-modified", ""); - assert_index(&tbl, 45, "link", ""); - assert_index(&tbl, 46, "location", ""); - assert_index(&tbl, 47, "max-forwards", ""); - assert_index(&tbl, 48, "proxy-authenticate", ""); - assert_index(&tbl, 49, "proxy-authorization", ""); - assert_index(&tbl, 50, "range", ""); - assert_index(&tbl, 51, "referer", ""); - assert_index(&tbl, 52, "refresh", ""); - assert_index(&tbl, 53, "retry-after", ""); - assert_index(&tbl, 54, "server", ""); - assert_index(&tbl, 55, "set-cookie", ""); - assert_index(&tbl, 56, "strict-transport-security", ""); - assert_index(&tbl, 57, "transfer-encoding", ""); - assert_index(&tbl, 58, "user-agent", ""); - assert_index(&tbl, 59, "vary", ""); - assert_index(&tbl, 60, "via", ""); - assert_index(&tbl, 61, "www-authenticate", ""); - - grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_many_additions(void) { - grpc_chttp2_hptbl tbl; - int i; - char *key; - char *value; - - LOG_TEST("test_many_additions"); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_chttp2_hptbl_init(&exec_ctx, &tbl); - - for (i = 0; i < 100000; i++) { - grpc_mdelem elem; - gpr_asprintf(&key, "K:%d", i); - gpr_asprintf(&value, "VALUE:%d", i); - elem = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), - grpc_slice_from_copied_string(value)); - GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); - GRPC_MDELEM_UNREF(&exec_ctx, elem); - assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value); - gpr_free(key); - gpr_free(value); - if (i) { - gpr_asprintf(&key, "K:%d", i - 1); - gpr_asprintf(&value, "VALUE:%d", i - 1); - assert_index(&tbl, 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value); - gpr_free(key); - gpr_free(value); - } - } - - grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); - grpc_exec_ctx_finish(&exec_ctx); -} - -static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl, - const char *key, - const char *value) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem md = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), - grpc_slice_from_copied_string(value)); - grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md); - GRPC_MDELEM_UNREF(&exec_ctx, md); - grpc_exec_ctx_finish(&exec_ctx); - return r; -} - -static void test_find(void) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_chttp2_hptbl tbl; - uint32_t i; - char buffer[32]; - grpc_mdelem elem; - grpc_chttp2_hptbl_find_result r; - - LOG_TEST("test_find"); - - grpc_chttp2_hptbl_init(&exec_ctx, &tbl); - elem = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"), - grpc_slice_from_static_string("xyz")); - GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); - GRPC_MDELEM_UNREF(&exec_ctx, elem); - elem = - grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"), - grpc_slice_from_static_string("123")); - GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); - GRPC_MDELEM_UNREF(&exec_ctx, elem); - elem = grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("x"), - grpc_slice_from_static_string("1")); - GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); - GRPC_MDELEM_UNREF(&exec_ctx, elem); - - r = find_simple(&tbl, "abc", "123"); - GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, "abc", "xyz"); - GPR_ASSERT(r.index == 3 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, "x", "1"); - GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, "x", "2"); - GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 0); - - r = find_simple(&tbl, "vary", "some-vary-arg"); - GPR_ASSERT(r.index == 59); - GPR_ASSERT(r.has_value == 0); - - r = find_simple(&tbl, "accept-encoding", "gzip, deflate"); - GPR_ASSERT(r.index == 16); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, "accept-encoding", "gzip"); - GPR_ASSERT(r.index == 16); - GPR_ASSERT(r.has_value == 0); - - r = find_simple(&tbl, ":method", "GET"); - GPR_ASSERT(r.index == 2); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, ":method", "POST"); - GPR_ASSERT(r.index == 3); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, ":method", "PUT"); - GPR_ASSERT(r.index == 2 || r.index == 3); - GPR_ASSERT(r.has_value == 0); - - r = find_simple(&tbl, "this-does-not-exist", ""); - GPR_ASSERT(r.index == 0); - GPR_ASSERT(r.has_value == 0); - - /* overflow the string buffer, check find still works */ - for (i = 0; i < 10000; i++) { - int64_ttoa(i, buffer); - elem = grpc_mdelem_from_slices(&exec_ctx, - grpc_slice_from_static_string("test"), - grpc_slice_from_copied_string(buffer)); - GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); - GRPC_MDELEM_UNREF(&exec_ctx, elem); - } - - r = find_simple(&tbl, "abc", "123"); - GPR_ASSERT(r.index == 0); - GPR_ASSERT(r.has_value == 0); - - r = find_simple(&tbl, "test", "9999"); - GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - - r = find_simple(&tbl, "test", "9998"); - GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - - for (i = 0; i < tbl.num_ents; i++) { - uint32_t expect = 9999 - i; - int64_ttoa(expect, buffer); - - r = find_simple(&tbl, "test", buffer); - GPR_ASSERT(r.index == i + 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); - GPR_ASSERT(r.has_value == 1); - } - - r = find_simple(&tbl, "test", "10000"); - GPR_ASSERT(r.index != 0); - GPR_ASSERT(r.has_value == 0); - - grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); - grpc_exec_ctx_finish(&exec_ctx); -} - -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/hpack_table_test.cc b/test/core/transport/chttp2/hpack_table_test.cc new file mode 100644 index 0000000000..430ece33c7 --- /dev/null +++ b/test/core/transport/chttp2/hpack_table_test.cc @@ -0,0 +1,285 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/hpack_table.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_slice mdstr, + const char *str) { + GPR_ASSERT(grpc_slice_str_cmp(mdstr, str) == 0); +} + +static void assert_index(const grpc_chttp2_hptbl *tbl, uint32_t idx, + const char *key, const char *value) { + grpc_mdelem md = grpc_chttp2_hptbl_lookup(tbl, idx); + assert_str(tbl, GRPC_MDKEY(md), key); + assert_str(tbl, GRPC_MDVALUE(md), value); +} + +static void test_static_lookup(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hptbl tbl; + + grpc_chttp2_hptbl_init(&exec_ctx, &tbl); + + LOG_TEST("test_static_lookup"); + assert_index(&tbl, 1, ":authority", ""); + assert_index(&tbl, 2, ":method", "GET"); + assert_index(&tbl, 3, ":method", "POST"); + assert_index(&tbl, 4, ":path", "/"); + assert_index(&tbl, 5, ":path", "/index.html"); + assert_index(&tbl, 6, ":scheme", "http"); + assert_index(&tbl, 7, ":scheme", "https"); + assert_index(&tbl, 8, ":status", "200"); + assert_index(&tbl, 9, ":status", "204"); + assert_index(&tbl, 10, ":status", "206"); + assert_index(&tbl, 11, ":status", "304"); + assert_index(&tbl, 12, ":status", "400"); + assert_index(&tbl, 13, ":status", "404"); + assert_index(&tbl, 14, ":status", "500"); + assert_index(&tbl, 15, "accept-charset", ""); + assert_index(&tbl, 16, "accept-encoding", "gzip, deflate"); + assert_index(&tbl, 17, "accept-language", ""); + assert_index(&tbl, 18, "accept-ranges", ""); + assert_index(&tbl, 19, "accept", ""); + assert_index(&tbl, 20, "access-control-allow-origin", ""); + assert_index(&tbl, 21, "age", ""); + assert_index(&tbl, 22, "allow", ""); + assert_index(&tbl, 23, "authorization", ""); + assert_index(&tbl, 24, "cache-control", ""); + assert_index(&tbl, 25, "content-disposition", ""); + assert_index(&tbl, 26, "content-encoding", ""); + assert_index(&tbl, 27, "content-language", ""); + assert_index(&tbl, 28, "content-length", ""); + assert_index(&tbl, 29, "content-location", ""); + assert_index(&tbl, 30, "content-range", ""); + assert_index(&tbl, 31, "content-type", ""); + assert_index(&tbl, 32, "cookie", ""); + assert_index(&tbl, 33, "date", ""); + assert_index(&tbl, 34, "etag", ""); + assert_index(&tbl, 35, "expect", ""); + assert_index(&tbl, 36, "expires", ""); + assert_index(&tbl, 37, "from", ""); + assert_index(&tbl, 38, "host", ""); + assert_index(&tbl, 39, "if-match", ""); + assert_index(&tbl, 40, "if-modified-since", ""); + assert_index(&tbl, 41, "if-none-match", ""); + assert_index(&tbl, 42, "if-range", ""); + assert_index(&tbl, 43, "if-unmodified-since", ""); + assert_index(&tbl, 44, "last-modified", ""); + assert_index(&tbl, 45, "link", ""); + assert_index(&tbl, 46, "location", ""); + assert_index(&tbl, 47, "max-forwards", ""); + assert_index(&tbl, 48, "proxy-authenticate", ""); + assert_index(&tbl, 49, "proxy-authorization", ""); + assert_index(&tbl, 50, "range", ""); + assert_index(&tbl, 51, "referer", ""); + assert_index(&tbl, 52, "refresh", ""); + assert_index(&tbl, 53, "retry-after", ""); + assert_index(&tbl, 54, "server", ""); + assert_index(&tbl, 55, "set-cookie", ""); + assert_index(&tbl, 56, "strict-transport-security", ""); + assert_index(&tbl, 57, "transfer-encoding", ""); + assert_index(&tbl, 58, "user-agent", ""); + assert_index(&tbl, 59, "vary", ""); + assert_index(&tbl, 60, "via", ""); + assert_index(&tbl, 61, "www-authenticate", ""); + + grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_many_additions(void) { + grpc_chttp2_hptbl tbl; + int i; + char *key; + char *value; + + LOG_TEST("test_many_additions"); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hptbl_init(&exec_ctx, &tbl); + + for (i = 0; i < 100000; i++) { + grpc_mdelem elem; + gpr_asprintf(&key, "K:%d", i); + gpr_asprintf(&value, "VALUE:%d", i); + elem = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), + grpc_slice_from_copied_string(value)); + GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); + GRPC_MDELEM_UNREF(&exec_ctx, elem); + assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value); + gpr_free(key); + gpr_free(value); + if (i) { + gpr_asprintf(&key, "K:%d", i - 1); + gpr_asprintf(&value, "VALUE:%d", i - 1); + assert_index(&tbl, 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value); + gpr_free(key); + gpr_free(value); + } + } + + grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); + grpc_exec_ctx_finish(&exec_ctx); +} + +static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl, + const char *key, + const char *value) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem md = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key), + grpc_slice_from_copied_string(value)); + grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md); + GRPC_MDELEM_UNREF(&exec_ctx, md); + grpc_exec_ctx_finish(&exec_ctx); + return r; +} + +static void test_find(void) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hptbl tbl; + uint32_t i; + char buffer[32]; + grpc_mdelem elem; + grpc_chttp2_hptbl_find_result r; + + LOG_TEST("test_find"); + + grpc_chttp2_hptbl_init(&exec_ctx, &tbl); + elem = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"), + grpc_slice_from_static_string("xyz")); + GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); + GRPC_MDELEM_UNREF(&exec_ctx, elem); + elem = + grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"), + grpc_slice_from_static_string("123")); + GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); + GRPC_MDELEM_UNREF(&exec_ctx, elem); + elem = grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("x"), + grpc_slice_from_static_string("1")); + GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); + GRPC_MDELEM_UNREF(&exec_ctx, elem); + + r = find_simple(&tbl, "abc", "123"); + GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, "abc", "xyz"); + GPR_ASSERT(r.index == 3 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, "x", "1"); + GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, "x", "2"); + GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 0); + + r = find_simple(&tbl, "vary", "some-vary-arg"); + GPR_ASSERT(r.index == 59); + GPR_ASSERT(r.has_value == 0); + + r = find_simple(&tbl, "accept-encoding", "gzip, deflate"); + GPR_ASSERT(r.index == 16); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, "accept-encoding", "gzip"); + GPR_ASSERT(r.index == 16); + GPR_ASSERT(r.has_value == 0); + + r = find_simple(&tbl, ":method", "GET"); + GPR_ASSERT(r.index == 2); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, ":method", "POST"); + GPR_ASSERT(r.index == 3); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, ":method", "PUT"); + GPR_ASSERT(r.index == 2 || r.index == 3); + GPR_ASSERT(r.has_value == 0); + + r = find_simple(&tbl, "this-does-not-exist", ""); + GPR_ASSERT(r.index == 0); + GPR_ASSERT(r.has_value == 0); + + /* overflow the string buffer, check find still works */ + for (i = 0; i < 10000; i++) { + int64_ttoa(i, buffer); + elem = grpc_mdelem_from_slices(&exec_ctx, + grpc_slice_from_static_string("test"), + grpc_slice_from_copied_string(buffer)); + GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE); + GRPC_MDELEM_UNREF(&exec_ctx, elem); + } + + r = find_simple(&tbl, "abc", "123"); + GPR_ASSERT(r.index == 0); + GPR_ASSERT(r.has_value == 0); + + r = find_simple(&tbl, "test", "9999"); + GPR_ASSERT(r.index == 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + + r = find_simple(&tbl, "test", "9998"); + GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + + for (i = 0; i < tbl.num_ents; i++) { + uint32_t expect = 9999 - i; + int64_ttoa(expect, buffer); + + r = find_simple(&tbl, "test", buffer); + GPR_ASSERT(r.index == i + 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY); + GPR_ASSERT(r.has_value == 1); + } + + r = find_simple(&tbl, "test", "10000"); + GPR_ASSERT(r.index != 0); + GPR_ASSERT(r.has_value == 0); + + grpc_chttp2_hptbl_destroy(&exec_ctx, &tbl); + grpc_exec_ctx_finish(&exec_ctx); +} + +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_map_test.c b/test/core/transport/chttp2/stream_map_test.c deleted file mode 100644 index ae2583ab84..0000000000 --- a/test/core/transport/chttp2/stream_map_test.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/stream_map.h" -#include -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -/* test creation & destruction */ -static void test_no_op(void) { - grpc_chttp2_stream_map map; - - LOG_TEST("test_no_op"); - - grpc_chttp2_stream_map_init(&map, 8); - grpc_chttp2_stream_map_destroy(&map); -} - -/* test lookup on an empty map */ -static void test_empty_find(void) { - grpc_chttp2_stream_map map; - - LOG_TEST("test_empty_find"); - - grpc_chttp2_stream_map_init(&map, 8); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 39128)); - grpc_chttp2_stream_map_destroy(&map); -} - -/* test it's safe to delete twice */ -static void test_double_deletion(void) { - grpc_chttp2_stream_map map; - - LOG_TEST("test_double_deletion"); - - grpc_chttp2_stream_map_init(&map, 8); - GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); - grpc_chttp2_stream_map_add(&map, 1, (void *)1); - GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_find(&map, 1)); - GPR_ASSERT(1 == grpc_chttp2_stream_map_size(&map)); - GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_delete(&map, 1)); - GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); - grpc_chttp2_stream_map_destroy(&map); -} - -/* test add & lookup */ -static void test_basic_add_find(uint32_t n) { - grpc_chttp2_stream_map map; - uint32_t i; - size_t got; - - LOG_TEST("test_basic_add_find"); - gpr_log(GPR_INFO, "n = %d", n); - - grpc_chttp2_stream_map_init(&map, 8); - GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); - for (i = 1; i <= n; i++) { - grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); - } - GPR_ASSERT(n == grpc_chttp2_stream_map_size(&map)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 0)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, n + 1)); - for (i = 1; i <= n; i++) { - got = (uintptr_t)grpc_chttp2_stream_map_find(&map, i); - GPR_ASSERT(i == got); - } - grpc_chttp2_stream_map_destroy(&map); -} - -/* verify that for_each gets the right values during test_delete_evens_XXX */ -static void verify_for_each(void *user_data, uint32_t stream_id, void *ptr) { - uint32_t *for_each_check = user_data; - GPR_ASSERT(ptr); - GPR_ASSERT(*for_each_check == stream_id); - *for_each_check += 2; -} - -static void check_delete_evens(grpc_chttp2_stream_map *map, uint32_t n) { - uint32_t for_each_check = 1; - uint32_t i; - size_t got; - - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, 0)); - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, n + 1)); - for (i = 1; i <= n; i++) { - if (i & 1) { - got = (uintptr_t)grpc_chttp2_stream_map_find(map, i); - GPR_ASSERT(i == got); - } else { - GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, i)); - } - } - - grpc_chttp2_stream_map_for_each(map, verify_for_each, &for_each_check); - if (n & 1) { - GPR_ASSERT(for_each_check == n + 2); - } else { - GPR_ASSERT(for_each_check == n + 1); - } -} - -/* add a bunch of keys, delete the even ones, and make sure the map is - consistent */ -static void test_delete_evens_sweep(uint32_t n) { - grpc_chttp2_stream_map map; - uint32_t i; - - LOG_TEST("test_delete_evens_sweep"); - gpr_log(GPR_INFO, "n = %d", n); - - grpc_chttp2_stream_map_init(&map, 8); - for (i = 1; i <= n; i++) { - grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); - } - for (i = 1; i <= n; i++) { - if ((i & 1) == 0) { - GPR_ASSERT((void *)(uintptr_t)i == - grpc_chttp2_stream_map_delete(&map, i)); - } - } - check_delete_evens(&map, n); - grpc_chttp2_stream_map_destroy(&map); -} - -/* add a bunch of keys, delete the even ones immediately, and make sure the map - is consistent */ -static void test_delete_evens_incremental(uint32_t n) { - grpc_chttp2_stream_map map; - uint32_t i; - - LOG_TEST("test_delete_evens_incremental"); - gpr_log(GPR_INFO, "n = %d", n); - - grpc_chttp2_stream_map_init(&map, 8); - for (i = 1; i <= n; i++) { - grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); - if ((i & 1) == 0) { - grpc_chttp2_stream_map_delete(&map, i); - } - } - check_delete_evens(&map, n); - grpc_chttp2_stream_map_destroy(&map); -} - -/* add a bunch of keys, delete old ones after some time, ensure the - backing array does not grow */ -static void test_periodic_compaction(uint32_t n) { - grpc_chttp2_stream_map map; - uint32_t i; - uint32_t del; - - LOG_TEST("test_periodic_compaction"); - gpr_log(GPR_INFO, "n = %d", n); - - grpc_chttp2_stream_map_init(&map, 16); - GPR_ASSERT(map.capacity == 16); - for (i = 1; i <= n; i++) { - grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); - if (i > 8) { - del = i - 8; - GPR_ASSERT((void *)(uintptr_t)del == - grpc_chttp2_stream_map_delete(&map, del)); - } - } - GPR_ASSERT(map.capacity == 16); - grpc_chttp2_stream_map_destroy(&map); -} - -int main(int argc, char **argv) { - uint32_t n = 1; - uint32_t prev = 1; - uint32_t tmp; - - grpc_test_init(argc, argv); - - test_no_op(); - test_empty_find(); - test_double_deletion(); - - while (n < 100000) { - test_basic_add_find(n); - test_delete_evens_sweep(n); - test_delete_evens_incremental(n); - test_periodic_compaction(n); - - tmp = n; - n += prev; - prev = tmp; - } - - return 0; -} diff --git a/test/core/transport/chttp2/stream_map_test.cc b/test/core/transport/chttp2/stream_map_test.cc new file mode 100644 index 0000000000..7df7b1b2a6 --- /dev/null +++ b/test/core/transport/chttp2/stream_map_test.cc @@ -0,0 +1,215 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/stream_map.h" +#include +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +/* test creation & destruction */ +static void test_no_op(void) { + grpc_chttp2_stream_map map; + + LOG_TEST("test_no_op"); + + grpc_chttp2_stream_map_init(&map, 8); + grpc_chttp2_stream_map_destroy(&map); +} + +/* test lookup on an empty map */ +static void test_empty_find(void) { + grpc_chttp2_stream_map map; + + LOG_TEST("test_empty_find"); + + grpc_chttp2_stream_map_init(&map, 8); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 39128)); + grpc_chttp2_stream_map_destroy(&map); +} + +/* test it's safe to delete twice */ +static void test_double_deletion(void) { + grpc_chttp2_stream_map map; + + LOG_TEST("test_double_deletion"); + + grpc_chttp2_stream_map_init(&map, 8); + GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); + grpc_chttp2_stream_map_add(&map, 1, (void *)1); + GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_find(&map, 1)); + GPR_ASSERT(1 == grpc_chttp2_stream_map_size(&map)); + GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_delete(&map, 1)); + GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); + grpc_chttp2_stream_map_destroy(&map); +} + +/* test add & lookup */ +static void test_basic_add_find(uint32_t n) { + grpc_chttp2_stream_map map; + uint32_t i; + size_t got; + + LOG_TEST("test_basic_add_find"); + gpr_log(GPR_INFO, "n = %d", n); + + grpc_chttp2_stream_map_init(&map, 8); + GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); + for (i = 1; i <= n; i++) { + grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); + } + GPR_ASSERT(n == grpc_chttp2_stream_map_size(&map)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 0)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, n + 1)); + for (i = 1; i <= n; i++) { + got = (uintptr_t)grpc_chttp2_stream_map_find(&map, i); + GPR_ASSERT(i == got); + } + grpc_chttp2_stream_map_destroy(&map); +} + +/* verify that for_each gets the right values during test_delete_evens_XXX */ +static void verify_for_each(void *user_data, uint32_t stream_id, void *ptr) { + uint32_t *for_each_check = static_cast(user_data); + GPR_ASSERT(ptr); + GPR_ASSERT(*for_each_check == stream_id); + *for_each_check += 2; +} + +static void check_delete_evens(grpc_chttp2_stream_map *map, uint32_t n) { + uint32_t for_each_check = 1; + uint32_t i; + size_t got; + + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, 0)); + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, n + 1)); + for (i = 1; i <= n; i++) { + if (i & 1) { + got = (uintptr_t)grpc_chttp2_stream_map_find(map, i); + GPR_ASSERT(i == got); + } else { + GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, i)); + } + } + + grpc_chttp2_stream_map_for_each(map, verify_for_each, &for_each_check); + if (n & 1) { + GPR_ASSERT(for_each_check == n + 2); + } else { + GPR_ASSERT(for_each_check == n + 1); + } +} + +/* add a bunch of keys, delete the even ones, and make sure the map is + consistent */ +static void test_delete_evens_sweep(uint32_t n) { + grpc_chttp2_stream_map map; + uint32_t i; + + LOG_TEST("test_delete_evens_sweep"); + gpr_log(GPR_INFO, "n = %d", n); + + grpc_chttp2_stream_map_init(&map, 8); + for (i = 1; i <= n; i++) { + grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); + } + for (i = 1; i <= n; i++) { + if ((i & 1) == 0) { + GPR_ASSERT((void *)(uintptr_t)i == + grpc_chttp2_stream_map_delete(&map, i)); + } + } + check_delete_evens(&map, n); + grpc_chttp2_stream_map_destroy(&map); +} + +/* add a bunch of keys, delete the even ones immediately, and make sure the map + is consistent */ +static void test_delete_evens_incremental(uint32_t n) { + grpc_chttp2_stream_map map; + uint32_t i; + + LOG_TEST("test_delete_evens_incremental"); + gpr_log(GPR_INFO, "n = %d", n); + + grpc_chttp2_stream_map_init(&map, 8); + for (i = 1; i <= n; i++) { + grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); + if ((i & 1) == 0) { + grpc_chttp2_stream_map_delete(&map, i); + } + } + check_delete_evens(&map, n); + grpc_chttp2_stream_map_destroy(&map); +} + +/* add a bunch of keys, delete old ones after some time, ensure the + backing array does not grow */ +static void test_periodic_compaction(uint32_t n) { + grpc_chttp2_stream_map map; + uint32_t i; + uint32_t del; + + LOG_TEST("test_periodic_compaction"); + gpr_log(GPR_INFO, "n = %d", n); + + grpc_chttp2_stream_map_init(&map, 16); + GPR_ASSERT(map.capacity == 16); + for (i = 1; i <= n; i++) { + grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); + if (i > 8) { + del = i - 8; + GPR_ASSERT((void *)(uintptr_t)del == + grpc_chttp2_stream_map_delete(&map, del)); + } + } + GPR_ASSERT(map.capacity == 16); + grpc_chttp2_stream_map_destroy(&map); +} + +int main(int argc, char **argv) { + uint32_t n = 1; + uint32_t prev = 1; + uint32_t tmp; + + grpc_test_init(argc, argv); + + test_no_op(); + test_empty_find(); + test_double_deletion(); + + while (n < 100000) { + test_basic_add_find(n); + test_delete_evens_sweep(n); + test_delete_evens_incremental(n); + test_periodic_compaction(n); + + tmp = n; + n += prev; + prev = tmp; + } + + return 0; +} diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c deleted file mode 100644 index 0986a2cde6..0000000000 --- a/test/core/transport/chttp2/varint_test.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/transport/chttp2/transport/varint.h" - -#include -#include - -#include "test/core/util/test_config.h" - -static void test_varint(uint32_t value, uint32_t prefix_bits, uint8_t prefix_or, - const char *expect_bytes, size_t expect_length) { - uint32_t nbytes = GRPC_CHTTP2_VARINT_LENGTH(value, prefix_bits); - grpc_slice expect = - grpc_slice_from_copied_buffer(expect_bytes, expect_length); - grpc_slice slice; - gpr_log(GPR_DEBUG, "Test: 0x%08x", value); - GPR_ASSERT(nbytes == expect_length); - slice = grpc_slice_malloc(nbytes); - GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or, - GRPC_SLICE_START_PTR(slice), nbytes); - GPR_ASSERT(grpc_slice_eq(expect, slice)); - grpc_slice_unref(expect); - grpc_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/chttp2/varint_test.cc b/test/core/transport/chttp2/varint_test.cc new file mode 100644 index 0000000000..0986a2cde6 --- /dev/null +++ b/test/core/transport/chttp2/varint_test.cc @@ -0,0 +1,54 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/transport/chttp2/transport/varint.h" + +#include +#include + +#include "test/core/util/test_config.h" + +static void test_varint(uint32_t value, uint32_t prefix_bits, uint8_t prefix_or, + const char *expect_bytes, size_t expect_length) { + uint32_t nbytes = GRPC_CHTTP2_VARINT_LENGTH(value, prefix_bits); + grpc_slice expect = + grpc_slice_from_copied_buffer(expect_bytes, expect_length); + grpc_slice slice; + gpr_log(GPR_DEBUG, "Test: 0x%08x", value); + GPR_ASSERT(nbytes == expect_length); + slice = grpc_slice_malloc(nbytes); + GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or, + GRPC_SLICE_START_PTR(slice), nbytes); + GPR_ASSERT(grpc_slice_eq(expect, slice)); + grpc_slice_unref(expect); + grpc_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 deleted file mode 100644 index 4ef8683107..0000000000 --- a/test/core/transport/connectivity_state_test.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/connectivity_state.h" - -#include - -#include - -#include "test/core/util/test_config.h" - -#define THE_ARG ((void *)(size_t)0xcafebabe) - -int g_counter; - -static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(arg == THE_ARG); - g_counter++; -} - -static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_ASSERT(error != GRPC_ERROR_NONE); - 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_SHUTDOWN), - "SHUTDOWN")); -} - -static void test_check(void) { - grpc_connectivity_state_tracker tracker; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_error *error; - gpr_log(GPR_DEBUG, "test_check"); - grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); - GPR_ASSERT(grpc_connectivity_state_get(&tracker, &error) == - GRPC_CHANNEL_IDLE); - GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE); - GPR_ASSERT(error == GRPC_ERROR_NONE); - 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_schedule_on_exec_ctx); - 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_schedule_on_exec_ctx); - 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_SHUTDOWN); - 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_schedule_on_exec_ctx); - grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN; - 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_SHUTDOWN, "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_SHUTDOWN); - GPR_ASSERT(g_counter == 0); - grpc_connectivity_state_destroy(&exec_ctx, &tracker); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(state == GRPC_CHANNEL_SHUTDOWN); - GPR_ASSERT(g_counter == 1); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_connectivity_state_trace.value = 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/connectivity_state_test.cc b/test/core/transport/connectivity_state_test.cc new file mode 100644 index 0000000000..4ef8683107 --- /dev/null +++ b/test/core/transport/connectivity_state_test.cc @@ -0,0 +1,146 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/connectivity_state.h" + +#include + +#include + +#include "test/core/util/test_config.h" + +#define THE_ARG ((void *)(size_t)0xcafebabe) + +int g_counter; + +static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(arg == THE_ARG); + g_counter++; +} + +static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + 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_SHUTDOWN), + "SHUTDOWN")); +} + +static void test_check(void) { + grpc_connectivity_state_tracker tracker; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_error *error; + gpr_log(GPR_DEBUG, "test_check"); + grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); + GPR_ASSERT(grpc_connectivity_state_get(&tracker, &error) == + GRPC_CHANNEL_IDLE); + GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE); + GPR_ASSERT(error == GRPC_ERROR_NONE); + 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_schedule_on_exec_ctx); + 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_schedule_on_exec_ctx); + 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_SHUTDOWN); + 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_schedule_on_exec_ctx); + grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN; + 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_SHUTDOWN, "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_SHUTDOWN); + GPR_ASSERT(g_counter == 0); + grpc_connectivity_state_destroy(&exec_ctx, &tracker); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(state == GRPC_CHANNEL_SHUTDOWN); + GPR_ASSERT(g_counter == 1); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_connectivity_state_trace.value = 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 deleted file mode 100644 index f7124d29a7..0000000000 --- a/test/core/transport/metadata_test.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/metadata.h" - -#include -#include - -#include -#include -#include -#include - -#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/transport/static_metadata.h" -#include "test/core/util/test_config.h" - -/* a large number */ -#define MANY 10000 - -static void test_no_op(void) { - gpr_log(GPR_INFO, "test_no_op"); - grpc_init(); - grpc_shutdown(); -} - -static grpc_slice maybe_intern(grpc_slice in, bool intern) { - grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in); - grpc_slice_unref(in); - return out; -} - -static grpc_slice maybe_dup(grpc_slice in, bool dup) { - grpc_slice out = dup ? grpc_slice_dup(in) : grpc_slice_ref(in); - grpc_slice_unref(in); - return out; -} - -static void test_create_metadata(bool intern_keys, bool intern_values) { - grpc_mdelem m1, m2, m3; - - gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d", - intern_keys, intern_values); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - m1 = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values)); - m2 = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values)); - m3 = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("c"), intern_values)); - GPR_ASSERT(grpc_mdelem_eq(m1, m2)); - GPR_ASSERT(!grpc_mdelem_eq(m3, m1)); - GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(m3), GRPC_MDKEY(m1))); - GPR_ASSERT(!grpc_slice_eq(GRPC_MDVALUE(m3), GRPC_MDVALUE(m1))); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(m1), "a") == 0); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m1), "b") == 0); - GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m3), "c") == 0); - GRPC_MDELEM_UNREF(&exec_ctx, m1); - GRPC_MDELEM_UNREF(&exec_ctx, m2); - GRPC_MDELEM_UNREF(&exec_ctx, m3); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void test_create_many_ephemeral_metadata(bool intern_keys, - bool intern_values) { - char buffer[GPR_LTOA_MIN_BUFSIZE]; - long i; - - gpr_log( - GPR_INFO, - "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d", - intern_keys, intern_values); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - /* add, and immediately delete a bunch of different elements */ - for (i = 0; i < MANY; i++) { - gpr_ltoa(i, buffer); - GRPC_MDELEM_UNREF( - &exec_ctx, - grpc_mdelem_from_slices( - &exec_ctx, - maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_copied_string(buffer), - intern_values))); - } - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void test_create_many_persistant_metadata(void) { - char buffer[GPR_LTOA_MIN_BUFSIZE]; - long i; - grpc_mdelem *created = gpr_malloc(sizeof(grpc_mdelem) * MANY); - grpc_mdelem md; - - gpr_log(GPR_INFO, "test_create_many_persistant_metadata"); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - /* add phase */ - for (i = 0; i < MANY; i++) { - gpr_ltoa(i, buffer); - created[i] = grpc_mdelem_from_slices( - &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")), - grpc_slice_intern(grpc_slice_from_static_string(buffer))); - } - /* verify phase */ - for (i = 0; i < MANY; i++) { - gpr_ltoa(i, buffer); - md = grpc_mdelem_from_slices( - &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")), - grpc_slice_intern(grpc_slice_from_static_string(buffer))); - GPR_ASSERT(grpc_mdelem_eq(md, created[i])); - GRPC_MDELEM_UNREF(&exec_ctx, md); - } - /* cleanup phase */ - for (i = 0; i < MANY; i++) { - GRPC_MDELEM_UNREF(&exec_ctx, created[i]); - } - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - - gpr_free(created); -} - -static void test_spin_creating_the_same_thing(bool intern_keys, - bool intern_values) { - gpr_log(GPR_INFO, - "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d", - intern_keys, intern_values); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem a, b, c; - GRPC_MDELEM_UNREF( - &exec_ctx, - a = grpc_mdelem_from_slices( - &exec_ctx, - maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values))); - GRPC_MDELEM_UNREF( - &exec_ctx, - b = grpc_mdelem_from_slices( - &exec_ctx, - maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values))); - GRPC_MDELEM_UNREF( - &exec_ctx, - c = grpc_mdelem_from_slices( - &exec_ctx, - maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values))); - if (intern_keys && intern_values) { - GPR_ASSERT(a.payload == b.payload); - GPR_ASSERT(a.payload == c.payload); - } - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void test_identity_laws(bool intern_keys, bool intern_values) { - gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d", - intern_keys, intern_values); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_mdelem a, b, c; - a = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values)); - b = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values)); - c = grpc_mdelem_from_slices( - &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), - maybe_intern(grpc_slice_from_static_string("b"), intern_values)); - GPR_ASSERT(grpc_mdelem_eq(a, a)); - GPR_ASSERT(grpc_mdelem_eq(b, b)); - GPR_ASSERT(grpc_mdelem_eq(c, c)); - GPR_ASSERT(grpc_mdelem_eq(a, b)); - GPR_ASSERT(grpc_mdelem_eq(b, c)); - GPR_ASSERT(grpc_mdelem_eq(a, c)); - GPR_ASSERT(grpc_mdelem_eq(b, a)); - GPR_ASSERT(grpc_mdelem_eq(c, b)); - GPR_ASSERT(grpc_mdelem_eq(c, a)); - if (intern_keys && intern_values) { - GPR_ASSERT(a.payload == b.payload); - GPR_ASSERT(a.payload == c.payload); - } else { - GPR_ASSERT(a.payload != b.payload); - GPR_ASSERT(a.payload != c.payload); - GPR_ASSERT(b.payload != c.payload); - } - GRPC_MDELEM_UNREF(&exec_ctx, a); - GRPC_MDELEM_UNREF(&exec_ctx, b); - GRPC_MDELEM_UNREF(&exec_ctx, c); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void test_things_stick_around(void) { - size_t i, j; - char *buffer; - size_t nstrs = 1000; - grpc_slice *strs = gpr_malloc(sizeof(grpc_slice) * nstrs); - size_t *shuf = gpr_malloc(sizeof(size_t) * nstrs); - grpc_slice test; - - gpr_log(GPR_INFO, "test_things_stick_around"); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - for (i = 0; i < nstrs; i++) { - gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", i); - strs[i] = grpc_slice_intern(grpc_slice_from_static_string(buffer)); - shuf[i] = i; - gpr_free(buffer); - } - - for (i = 0; i < nstrs; i++) { - grpc_slice_ref_internal(strs[i]); - grpc_slice_unref_internal(&exec_ctx, strs[i]); - } - - for (i = 0; i < nstrs; i++) { - size_t p = (size_t)rand() % nstrs; - size_t q = (size_t)rand() % nstrs; - size_t temp = shuf[p]; - shuf[p] = shuf[q]; - shuf[q] = temp; - } - - for (i = 0; i < nstrs; i++) { - grpc_slice_unref_internal(&exec_ctx, strs[shuf[i]]); - for (j = i + 1; j < nstrs; j++) { - gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", - shuf[j]); - test = grpc_slice_intern(grpc_slice_from_static_string(buffer)); - GPR_ASSERT(grpc_slice_is_equivalent(test, strs[shuf[j]])); - grpc_slice_unref_internal(&exec_ctx, test); - gpr_free(buffer); - } - } - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - gpr_free(strs); - gpr_free(shuf); -} - -static void test_user_data_works(void) { - int *ud1; - int *ud2; - grpc_mdelem md; - gpr_log(GPR_INFO, "test_user_data_works"); - - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - ud1 = gpr_malloc(sizeof(int)); - *ud1 = 1; - ud2 = gpr_malloc(sizeof(int)); - *ud2 = 2; - md = grpc_mdelem_from_slices( - &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")), - grpc_slice_intern(grpc_slice_from_static_string("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(&exec_ctx, md); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void verify_ascii_header_size(grpc_exec_ctx *exec_ctx, const char *key, - const char *value, bool intern_key, - bool intern_value) { - grpc_mdelem elem = grpc_mdelem_from_slices( - exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key), - maybe_intern(grpc_slice_from_static_string(value), intern_value)); - size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); - size_t expected_size = 32 + strlen(key) + strlen(value); - GPR_ASSERT(expected_size == elem_size); - GRPC_MDELEM_UNREF(exec_ctx, elem); -} - -static void verify_binary_header_size(grpc_exec_ctx *exec_ctx, const char *key, - const uint8_t *value, size_t value_len, - bool intern_key, bool intern_value) { - grpc_mdelem elem = grpc_mdelem_from_slices( - exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key), - maybe_intern(grpc_slice_from_static_buffer(value, value_len), - intern_value)); - GPR_ASSERT(grpc_is_binary_header(GRPC_MDKEY(elem))); - size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); - grpc_slice value_slice = - grpc_slice_from_copied_buffer((const char *)value, value_len); - grpc_slice base64_encoded = grpc_chttp2_base64_encode(value_slice); - size_t expected_size = 32 + strlen(key) + GRPC_SLICE_LENGTH(base64_encoded); - GPR_ASSERT(expected_size == elem_size); - grpc_slice_unref_internal(exec_ctx, value_slice); - grpc_slice_unref_internal(exec_ctx, base64_encoded); - GRPC_MDELEM_UNREF(exec_ctx, elem); -} - -#define BUFFER_SIZE 64 -static void test_mdelem_sizes_in_hpack(bool intern_key, bool intern_value) { - gpr_log(GPR_INFO, "test_mdelem_size: intern_key=%d intern_value=%d", - intern_key, intern_value); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - uint8_t binary_value[BUFFER_SIZE] = {0}; - for (uint8_t i = 0; i < BUFFER_SIZE; i++) { - binary_value[i] = i; - } - - verify_ascii_header_size(&exec_ctx, "hello", "world", intern_key, - intern_value); - verify_ascii_header_size(&exec_ctx, "hello", - "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", intern_key, - intern_value); - verify_ascii_header_size(&exec_ctx, ":scheme", "http", intern_key, - intern_value); - - for (uint8_t i = 0; i < BUFFER_SIZE; i++) { - verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i, - intern_key, intern_value); - } - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -static void test_copied_static_metadata(bool dup_key, bool dup_value) { - gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key, - dup_value); - grpc_init(); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { - grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i], - GRPC_MDELEM_STORAGE_STATIC); - grpc_mdelem q = - grpc_mdelem_from_slices(&exec_ctx, maybe_dup(GRPC_MDKEY(p), dup_key), - maybe_dup(GRPC_MDVALUE(p), dup_value)); - GPR_ASSERT(grpc_mdelem_eq(p, q)); - if (dup_key || dup_value) { - GPR_ASSERT(p.payload != q.payload); - } else { - GPR_ASSERT(p.payload == q.payload); - } - GRPC_MDELEM_UNREF(&exec_ctx, p); - GRPC_MDELEM_UNREF(&exec_ctx, q); - } - - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_no_op(); - for (int k = 0; k <= 1; k++) { - for (int v = 0; v <= 1; v++) { - test_create_metadata(k, v); - test_create_many_ephemeral_metadata(k, v); - test_identity_laws(k, v); - test_spin_creating_the_same_thing(k, v); - test_mdelem_sizes_in_hpack(k, v); - test_copied_static_metadata(k, v); - } - } - test_create_many_persistant_metadata(); - test_things_stick_around(); - test_user_data_works(); - return 0; -} diff --git a/test/core/transport/metadata_test.cc b/test/core/transport/metadata_test.cc new file mode 100644 index 0000000000..e043078560 --- /dev/null +++ b/test/core/transport/metadata_test.cc @@ -0,0 +1,404 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/metadata.h" + +#include +#include + +#include +#include +#include +#include + +#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/util/test_config.h" + +/* a large number */ +#define MANY 10000 + +static void test_no_op(void) { + gpr_log(GPR_INFO, "test_no_op"); + grpc_init(); + grpc_shutdown(); +} + +static grpc_slice maybe_intern(grpc_slice in, bool intern) { + grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in); + grpc_slice_unref(in); + return out; +} + +static grpc_slice maybe_dup(grpc_slice in, bool dup) { + grpc_slice out = dup ? grpc_slice_dup(in) : grpc_slice_ref(in); + grpc_slice_unref(in); + return out; +} + +static void test_create_metadata(bool intern_keys, bool intern_values) { + grpc_mdelem m1, m2, m3; + + gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + m1 = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + m2 = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + m3 = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("c"), intern_values)); + GPR_ASSERT(grpc_mdelem_eq(m1, m2)); + GPR_ASSERT(!grpc_mdelem_eq(m3, m1)); + GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(m3), GRPC_MDKEY(m1))); + GPR_ASSERT(!grpc_slice_eq(GRPC_MDVALUE(m3), GRPC_MDVALUE(m1))); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(m1), "a") == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m1), "b") == 0); + GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m3), "c") == 0); + GRPC_MDELEM_UNREF(&exec_ctx, m1); + GRPC_MDELEM_UNREF(&exec_ctx, m2); + GRPC_MDELEM_UNREF(&exec_ctx, m3); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void test_create_many_ephemeral_metadata(bool intern_keys, + bool intern_values) { + char buffer[GPR_LTOA_MIN_BUFSIZE]; + long i; + + gpr_log( + GPR_INFO, + "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + /* add, and immediately delete a bunch of different elements */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + GRPC_MDELEM_UNREF( + &exec_ctx, + grpc_mdelem_from_slices( + &exec_ctx, + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_copied_string(buffer), + intern_values))); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void test_create_many_persistant_metadata(void) { + char buffer[GPR_LTOA_MIN_BUFSIZE]; + long i; + grpc_mdelem *created = + static_cast(gpr_malloc(sizeof(grpc_mdelem) * MANY)); + grpc_mdelem md; + + gpr_log(GPR_INFO, "test_create_many_persistant_metadata"); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + /* add phase */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + created[i] = grpc_mdelem_from_slices( + &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")), + grpc_slice_intern(grpc_slice_from_static_string(buffer))); + } + /* verify phase */ + for (i = 0; i < MANY; i++) { + gpr_ltoa(i, buffer); + md = grpc_mdelem_from_slices( + &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")), + grpc_slice_intern(grpc_slice_from_static_string(buffer))); + GPR_ASSERT(grpc_mdelem_eq(md, created[i])); + GRPC_MDELEM_UNREF(&exec_ctx, md); + } + /* cleanup phase */ + for (i = 0; i < MANY; i++) { + GRPC_MDELEM_UNREF(&exec_ctx, created[i]); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_free(created); +} + +static void test_spin_creating_the_same_thing(bool intern_keys, + bool intern_values) { + gpr_log(GPR_INFO, + "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem a, b, c; + GRPC_MDELEM_UNREF( + &exec_ctx, + a = grpc_mdelem_from_slices( + &exec_ctx, + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + GRPC_MDELEM_UNREF( + &exec_ctx, + b = grpc_mdelem_from_slices( + &exec_ctx, + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + GRPC_MDELEM_UNREF( + &exec_ctx, + c = grpc_mdelem_from_slices( + &exec_ctx, + maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values))); + if (intern_keys && intern_values) { + GPR_ASSERT(a.payload == b.payload); + GPR_ASSERT(a.payload == c.payload); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void test_identity_laws(bool intern_keys, bool intern_values) { + gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d", + intern_keys, intern_values); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem a, b, c; + a = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + b = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + c = grpc_mdelem_from_slices( + &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys), + maybe_intern(grpc_slice_from_static_string("b"), intern_values)); + GPR_ASSERT(grpc_mdelem_eq(a, a)); + GPR_ASSERT(grpc_mdelem_eq(b, b)); + GPR_ASSERT(grpc_mdelem_eq(c, c)); + GPR_ASSERT(grpc_mdelem_eq(a, b)); + GPR_ASSERT(grpc_mdelem_eq(b, c)); + GPR_ASSERT(grpc_mdelem_eq(a, c)); + GPR_ASSERT(grpc_mdelem_eq(b, a)); + GPR_ASSERT(grpc_mdelem_eq(c, b)); + GPR_ASSERT(grpc_mdelem_eq(c, a)); + if (intern_keys && intern_values) { + GPR_ASSERT(a.payload == b.payload); + GPR_ASSERT(a.payload == c.payload); + } else { + GPR_ASSERT(a.payload != b.payload); + GPR_ASSERT(a.payload != c.payload); + GPR_ASSERT(b.payload != c.payload); + } + GRPC_MDELEM_UNREF(&exec_ctx, a); + GRPC_MDELEM_UNREF(&exec_ctx, b); + GRPC_MDELEM_UNREF(&exec_ctx, c); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void test_things_stick_around(void) { + size_t i, j; + char *buffer; + size_t nstrs = 1000; + grpc_slice *strs = + static_cast(gpr_malloc(sizeof(grpc_slice) * nstrs)); + size_t *shuf = static_cast(gpr_malloc(sizeof(size_t) * nstrs)); + grpc_slice test; + + gpr_log(GPR_INFO, "test_things_stick_around"); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + for (i = 0; i < nstrs; i++) { + gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", i); + strs[i] = grpc_slice_intern(grpc_slice_from_static_string(buffer)); + shuf[i] = i; + gpr_free(buffer); + } + + for (i = 0; i < nstrs; i++) { + grpc_slice_ref_internal(strs[i]); + grpc_slice_unref_internal(&exec_ctx, strs[i]); + } + + for (i = 0; i < nstrs; i++) { + size_t p = (size_t)rand() % nstrs; + size_t q = (size_t)rand() % nstrs; + size_t temp = shuf[p]; + shuf[p] = shuf[q]; + shuf[q] = temp; + } + + for (i = 0; i < nstrs; i++) { + grpc_slice_unref_internal(&exec_ctx, strs[shuf[i]]); + for (j = i + 1; j < nstrs; j++) { + gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", + shuf[j]); + test = grpc_slice_intern(grpc_slice_from_static_string(buffer)); + GPR_ASSERT(grpc_slice_is_equivalent(test, strs[shuf[j]])); + grpc_slice_unref_internal(&exec_ctx, test); + gpr_free(buffer); + } + } + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + gpr_free(strs); + gpr_free(shuf); +} + +static void test_user_data_works(void) { + int *ud1; + int *ud2; + grpc_mdelem md; + gpr_log(GPR_INFO, "test_user_data_works"); + + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + ud1 = static_cast(gpr_malloc(sizeof(int))); + *ud1 = 1; + ud2 = static_cast(gpr_malloc(sizeof(int))); + *ud2 = 2; + md = grpc_mdelem_from_slices( + &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")), + grpc_slice_intern(grpc_slice_from_static_string("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(&exec_ctx, md); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void verify_ascii_header_size(grpc_exec_ctx *exec_ctx, const char *key, + const char *value, bool intern_key, + bool intern_value) { + grpc_mdelem elem = grpc_mdelem_from_slices( + exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key), + maybe_intern(grpc_slice_from_static_string(value), intern_value)); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); + size_t expected_size = 32 + strlen(key) + strlen(value); + GPR_ASSERT(expected_size == elem_size); + GRPC_MDELEM_UNREF(exec_ctx, elem); +} + +static void verify_binary_header_size(grpc_exec_ctx *exec_ctx, const char *key, + const uint8_t *value, size_t value_len, + bool intern_key, bool intern_value) { + grpc_mdelem elem = grpc_mdelem_from_slices( + exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key), + maybe_intern(grpc_slice_from_static_buffer(value, value_len), + intern_value)); + GPR_ASSERT(grpc_is_binary_header(GRPC_MDKEY(elem))); + size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false); + grpc_slice value_slice = + grpc_slice_from_copied_buffer((const char *)value, value_len); + grpc_slice base64_encoded = grpc_chttp2_base64_encode(value_slice); + size_t expected_size = 32 + strlen(key) + GRPC_SLICE_LENGTH(base64_encoded); + GPR_ASSERT(expected_size == elem_size); + grpc_slice_unref_internal(exec_ctx, value_slice); + grpc_slice_unref_internal(exec_ctx, base64_encoded); + GRPC_MDELEM_UNREF(exec_ctx, elem); +} + +#define BUFFER_SIZE 64 +static void test_mdelem_sizes_in_hpack(bool intern_key, bool intern_value) { + gpr_log(GPR_INFO, "test_mdelem_size: intern_key=%d intern_value=%d", + intern_key, intern_value); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + uint8_t binary_value[BUFFER_SIZE] = {0}; + for (uint8_t i = 0; i < BUFFER_SIZE; i++) { + binary_value[i] = i; + } + + verify_ascii_header_size(&exec_ctx, "hello", "world", intern_key, + intern_value); + verify_ascii_header_size(&exec_ctx, "hello", + "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", intern_key, + intern_value); + verify_ascii_header_size(&exec_ctx, ":scheme", "http", intern_key, + intern_value); + + for (uint8_t i = 0; i < BUFFER_SIZE; i++) { + verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i, + intern_key, intern_value); + } + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +static void test_copied_static_metadata(bool dup_key, bool dup_value) { + gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key, + dup_value); + grpc_init(); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { + grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i], + GRPC_MDELEM_STORAGE_STATIC); + grpc_mdelem q = + grpc_mdelem_from_slices(&exec_ctx, maybe_dup(GRPC_MDKEY(p), dup_key), + maybe_dup(GRPC_MDVALUE(p), dup_value)); + GPR_ASSERT(grpc_mdelem_eq(p, q)); + if (dup_key || dup_value) { + GPR_ASSERT(p.payload != q.payload); + } else { + GPR_ASSERT(p.payload == q.payload); + } + GRPC_MDELEM_UNREF(&exec_ctx, p); + GRPC_MDELEM_UNREF(&exec_ctx, q); + } + + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_no_op(); + for (int k = 0; k <= 1; k++) { + for (int v = 0; v <= 1; v++) { + test_create_metadata(k, v); + test_create_many_ephemeral_metadata(k, v); + test_identity_laws(k, v); + test_spin_creating_the_same_thing(k, v); + test_mdelem_sizes_in_hpack(k, v); + test_copied_static_metadata(k, v); + } + } + test_create_many_persistant_metadata(); + test_things_stick_around(); + test_user_data_works(); + return 0; +} diff --git a/test/core/transport/status_conversion_test.c b/test/core/transport/status_conversion_test.c deleted file mode 100644 index de8fa4458a..0000000000 --- a/test/core/transport/status_conversion_test.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/status_conversion.h" -#include -#include "test/core/util/test_config.h" - -#define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \ - GPR_ASSERT(grpc_status_to_http2_error(a) == (b)) -#define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \ - do { \ - grpc_exec_ctx my_exec_ctx = GRPC_EXEC_CTX_INIT; \ - GPR_ASSERT(grpc_http2_error_to_grpc_status(&my_exec_ctx, a, deadline) == \ - (b)); \ - grpc_exec_ctx_finish(&my_exec_ctx); \ - } while (0) -#define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \ - GPR_ASSERT(grpc_status_to_http2_status(a) == (b)) -#define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \ - GPR_ASSERT(grpc_http2_status_to_grpc_status(a) == (b)) - -int main(int argc, char **argv) { - int i; - - grpc_test_init(argc, argv); - - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_HTTP2_NO_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_HTTP2_CANCEL); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_HTTP2_CANCEL); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_PERMISSION_DENIED, - GRPC_HTTP2_INADEQUATE_SECURITY); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAUTHENTICATED, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_RESOURCE_EXHAUSTED, - GRPC_HTTP2_ENHANCE_YOUR_CALM); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_FAILED_PRECONDITION, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OUT_OF_RANGE, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNIMPLEMENTED, - GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_HTTP2_INTERNAL_ERROR); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAVAILABLE, - GRPC_HTTP2_REFUSED_STREAM); - GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_HTTP2_INTERNAL_ERROR); - - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OK, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_CANCELLED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNKNOWN, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INVALID_ARGUMENT, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DEADLINE_EXCEEDED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_NOT_FOUND, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ALREADY_EXISTS, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_PERMISSION_DENIED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAUTHENTICATED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_RESOURCE_EXHAUSTED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_FAILED_PRECONDITION, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ABORTED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OUT_OF_RANGE, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNIMPLEMENTED, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INTERNAL, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAVAILABLE, 200); - GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200); - - const grpc_millis before_deadline = GRPC_MILLIS_INF_FUTURE; - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, before_deadline, - GRPC_STATUS_UNAVAILABLE); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, before_deadline, - GRPC_STATUS_CANCELLED); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, before_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, before_deadline, - GRPC_STATUS_RESOURCE_EXHAUSTED); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, before_deadline, - GRPC_STATUS_PERMISSION_DENIED); - - const grpc_millis after_deadline = 0; - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, after_deadline, - GRPC_STATUS_UNAVAILABLE); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, after_deadline, - GRPC_STATUS_DEADLINE_EXCEEDED); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, after_deadline, - GRPC_STATUS_INTERNAL); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, after_deadline, - GRPC_STATUS_RESOURCE_EXHAUSTED); - HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, after_deadline, - GRPC_STATUS_PERMISSION_DENIED); - - HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK); - HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INVALID_ARGUMENT); - HTTP2_STATUS_TO_GRPC_STATUS(401, GRPC_STATUS_UNAUTHENTICATED); - HTTP2_STATUS_TO_GRPC_STATUS(403, GRPC_STATUS_PERMISSION_DENIED); - HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_NOT_FOUND); - HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_ABORTED); - HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_FAILED_PRECONDITION); - HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_RESOURCE_EXHAUSTED); - HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_CANCELLED); - HTTP2_STATUS_TO_GRPC_STATUS(500, GRPC_STATUS_UNKNOWN); - HTTP2_STATUS_TO_GRPC_STATUS(503, GRPC_STATUS_UNAVAILABLE); - HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_DEADLINE_EXCEEDED); - - /* check all status values can be converted */ - for (i = 0; i <= 999; i++) { - grpc_http2_status_to_grpc_status(i); - } - - return 0; -} diff --git a/test/core/transport/status_conversion_test.cc b/test/core/transport/status_conversion_test.cc new file mode 100644 index 0000000000..de8fa4458a --- /dev/null +++ b/test/core/transport/status_conversion_test.cc @@ -0,0 +1,162 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/status_conversion.h" +#include +#include "test/core/util/test_config.h" + +#define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \ + GPR_ASSERT(grpc_status_to_http2_error(a) == (b)) +#define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \ + do { \ + grpc_exec_ctx my_exec_ctx = GRPC_EXEC_CTX_INIT; \ + GPR_ASSERT(grpc_http2_error_to_grpc_status(&my_exec_ctx, a, deadline) == \ + (b)); \ + grpc_exec_ctx_finish(&my_exec_ctx); \ + } while (0) +#define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \ + GPR_ASSERT(grpc_status_to_http2_status(a) == (b)) +#define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \ + GPR_ASSERT(grpc_http2_status_to_grpc_status(a) == (b)) + +int main(int argc, char **argv) { + int i; + + grpc_test_init(argc, argv); + + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_HTTP2_NO_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_HTTP2_CANCEL); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_HTTP2_CANCEL); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_PERMISSION_DENIED, + GRPC_HTTP2_INADEQUATE_SECURITY); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAUTHENTICATED, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_RESOURCE_EXHAUSTED, + GRPC_HTTP2_ENHANCE_YOUR_CALM); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_FAILED_PRECONDITION, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OUT_OF_RANGE, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNIMPLEMENTED, + GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_HTTP2_INTERNAL_ERROR); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAVAILABLE, + GRPC_HTTP2_REFUSED_STREAM); + GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_HTTP2_INTERNAL_ERROR); + + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OK, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_CANCELLED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNKNOWN, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INVALID_ARGUMENT, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DEADLINE_EXCEEDED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_NOT_FOUND, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ALREADY_EXISTS, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_PERMISSION_DENIED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAUTHENTICATED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_RESOURCE_EXHAUSTED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_FAILED_PRECONDITION, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ABORTED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OUT_OF_RANGE, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNIMPLEMENTED, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INTERNAL, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAVAILABLE, 200); + GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200); + + const grpc_millis before_deadline = GRPC_MILLIS_INF_FUTURE; + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, before_deadline, + GRPC_STATUS_UNAVAILABLE); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, before_deadline, + GRPC_STATUS_CANCELLED); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, before_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, before_deadline, + GRPC_STATUS_RESOURCE_EXHAUSTED); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, before_deadline, + GRPC_STATUS_PERMISSION_DENIED); + + const grpc_millis after_deadline = 0; + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, after_deadline, + GRPC_STATUS_UNAVAILABLE); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, after_deadline, + GRPC_STATUS_DEADLINE_EXCEEDED); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, after_deadline, + GRPC_STATUS_INTERNAL); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, after_deadline, + GRPC_STATUS_RESOURCE_EXHAUSTED); + HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, after_deadline, + GRPC_STATUS_PERMISSION_DENIED); + + HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK); + HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INVALID_ARGUMENT); + HTTP2_STATUS_TO_GRPC_STATUS(401, GRPC_STATUS_UNAUTHENTICATED); + HTTP2_STATUS_TO_GRPC_STATUS(403, GRPC_STATUS_PERMISSION_DENIED); + HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_NOT_FOUND); + HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_ABORTED); + HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_FAILED_PRECONDITION); + HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_RESOURCE_EXHAUSTED); + HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_CANCELLED); + HTTP2_STATUS_TO_GRPC_STATUS(500, GRPC_STATUS_UNKNOWN); + HTTP2_STATUS_TO_GRPC_STATUS(503, GRPC_STATUS_UNAVAILABLE); + HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_DEADLINE_EXCEEDED); + + /* check all status values can be converted */ + for (i = 0; i <= 999; i++) { + grpc_http2_status_to_grpc_status(i); + } + + return 0; +} diff --git a/test/core/transport/stream_owned_slice_test.c b/test/core/transport/stream_owned_slice_test.c deleted file mode 100644 index 774ad4e72e..0000000000 --- a/test/core/transport/stream_owned_slice_test.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/transport.h" - -#include "test/core/util/test_config.h" - -#include - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - - uint8_t buffer[] = "abc123"; - grpc_stream_refcount r; - GRPC_STREAM_REF_INIT(&r, 1, do_nothing, NULL, "test"); - GPR_ASSERT(r.refs.count == 1); - grpc_slice slice = - grpc_slice_from_stream_owned_buffer(&r, buffer, sizeof(buffer)); - GPR_ASSERT(GRPC_SLICE_START_PTR(slice) == buffer); - GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == sizeof(buffer)); - GPR_ASSERT(r.refs.count == 2); - grpc_slice_unref(slice); - GPR_ASSERT(r.refs.count == 1); - - return 0; -} diff --git a/test/core/transport/stream_owned_slice_test.cc b/test/core/transport/stream_owned_slice_test.cc new file mode 100644 index 0000000000..774ad4e72e --- /dev/null +++ b/test/core/transport/stream_owned_slice_test.cc @@ -0,0 +1,43 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/transport.h" + +#include "test/core/util/test_config.h" + +#include + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + uint8_t buffer[] = "abc123"; + grpc_stream_refcount r; + GRPC_STREAM_REF_INIT(&r, 1, do_nothing, NULL, "test"); + GPR_ASSERT(r.refs.count == 1); + grpc_slice slice = + grpc_slice_from_stream_owned_buffer(&r, buffer, sizeof(buffer)); + GPR_ASSERT(GRPC_SLICE_START_PTR(slice) == buffer); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == sizeof(buffer)); + GPR_ASSERT(r.refs.count == 2); + grpc_slice_unref(slice); + GPR_ASSERT(r.refs.count == 1); + + return 0; +} diff --git a/test/core/transport/timeout_encoding_test.c b/test/core/transport/timeout_encoding_test.c deleted file mode 100644 index 30357faed3..0000000000 --- a/test/core/transport/timeout_encoding_test.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/transport/timeout_encoding.h" - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/support/murmur_hash.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) - -static void assert_encodes_as(grpc_millis ts, const char *s) { - char buffer[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; - grpc_http2_encode_timeout(ts, buffer); - gpr_log(GPR_INFO, "check '%s' == '%s'", buffer, s); - GPR_ASSERT(0 == strcmp(buffer, s)); -} - -void test_encoding(void) { - LOG_TEST("test_encoding"); - assert_encodes_as(-1, "1n"); - assert_encodes_as(-10, "1n"); - assert_encodes_as(1, "1m"); - assert_encodes_as(10, "10m"); - assert_encodes_as(100, "100m"); - assert_encodes_as(890, "890m"); - assert_encodes_as(900, "900m"); - assert_encodes_as(901, "901m"); - assert_encodes_as(1000, "1S"); - assert_encodes_as(2000, "2S"); - assert_encodes_as(2500, "2500m"); - assert_encodes_as(59900, "59900m"); - assert_encodes_as(50000, "50S"); - assert_encodes_as(59000, "59S"); - assert_encodes_as(60000, "1M"); - assert_encodes_as(80000, "80S"); - assert_encodes_as(90000, "90S"); - assert_encodes_as(120000, "2M"); - assert_encodes_as(20 * 60 * GPR_MS_PER_SEC, "20M"); - assert_encodes_as(60 * 60 * GPR_MS_PER_SEC, "1H"); - assert_encodes_as(10 * 60 * 60 * GPR_MS_PER_SEC, "10H"); -} - -static void assert_decodes_as(const char *buffer, grpc_millis expected) { - grpc_millis got; - uint32_t hash = gpr_murmur_hash3(buffer, strlen(buffer), 0); - gpr_log(GPR_INFO, "check decoding '%s' (hash=0x%x)", buffer, hash); - GPR_ASSERT(1 == grpc_http2_decode_timeout( - grpc_slice_from_static_string(buffer), &got)); - if (got != expected) { - gpr_log(GPR_ERROR, "got:'%" PRIdPTR "' != expected:'%" PRIdPTR "'", got, - expected); - abort(); - } -} - -void decode_suite(char ext, grpc_millis (*answer)(int64_t x)) { - long test_vals[] = {1, 12, 123, 1234, 12345, 123456, - 1234567, 12345678, 123456789, 98765432, 9876543, 987654, - 98765, 9876, 987, 98, 9}; - unsigned i; - char *input; - for (i = 0; i < GPR_ARRAY_SIZE(test_vals); i++) { - gpr_asprintf(&input, "%ld%c", test_vals[i], ext); - assert_decodes_as(input, answer(test_vals[i])); - gpr_free(input); - - gpr_asprintf(&input, " %ld%c", test_vals[i], ext); - assert_decodes_as(input, answer(test_vals[i])); - gpr_free(input); - - gpr_asprintf(&input, "%ld %c", test_vals[i], ext); - assert_decodes_as(input, answer(test_vals[i])); - gpr_free(input); - - gpr_asprintf(&input, "%ld %c ", test_vals[i], ext); - assert_decodes_as(input, answer(test_vals[i])); - gpr_free(input); - } -} - -static grpc_millis millis_from_nanos(int64_t x) { - return (grpc_millis)(x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0)); -} -static grpc_millis millis_from_micros(int64_t x) { - return (grpc_millis)(x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0)); -} -static grpc_millis millis_from_millis(int64_t x) { return (grpc_millis)x; } -static grpc_millis millis_from_seconds(int64_t x) { - return (grpc_millis)(x * GPR_MS_PER_SEC); -} -static grpc_millis millis_from_minutes(int64_t x) { - return (grpc_millis)(x * 60 * GPR_MS_PER_SEC); -} -static grpc_millis millis_from_hours(int64_t x) { - return (grpc_millis)(x * 3600 * GPR_MS_PER_SEC); -} - -void test_decoding(void) { - LOG_TEST("test_decoding"); - decode_suite('n', millis_from_nanos); - decode_suite('u', millis_from_micros); - decode_suite('m', millis_from_millis); - decode_suite('S', millis_from_seconds); - decode_suite('M', millis_from_minutes); - decode_suite('H', millis_from_hours); - assert_decodes_as("1000000000S", millis_from_seconds(1000 * 1000 * 1000)); - assert_decodes_as("1000000000000000000000u", GRPC_MILLIS_INF_FUTURE); - assert_decodes_as("1000000001S", GRPC_MILLIS_INF_FUTURE); - assert_decodes_as("2000000001S", GRPC_MILLIS_INF_FUTURE); - assert_decodes_as("9999999999S", GRPC_MILLIS_INF_FUTURE); -} - -static void assert_decoding_fails(const char *s) { - grpc_millis x; - GPR_ASSERT(0 == - grpc_http2_decode_timeout(grpc_slice_from_static_string(s), &x)); -} - -void test_decoding_fails(void) { - LOG_TEST("test_decoding_fails"); - assert_decoding_fails(""); - assert_decoding_fails(" "); - assert_decoding_fails("x"); - assert_decoding_fails("1"); - assert_decoding_fails("1x"); - assert_decoding_fails("1ux"); - assert_decoding_fails("!"); - assert_decoding_fails("n1"); - assert_decoding_fails("-1u"); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_encoding(); - test_decoding(); - test_decoding_fails(); - return 0; -} diff --git a/test/core/transport/timeout_encoding_test.cc b/test/core/transport/timeout_encoding_test.cc new file mode 100644 index 0000000000..30357faed3 --- /dev/null +++ b/test/core/transport/timeout_encoding_test.cc @@ -0,0 +1,161 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/transport/timeout_encoding.h" + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/support/murmur_hash.h" +#include "src/core/lib/support/string.h" +#include "test/core/util/test_config.h" + +#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) + +static void assert_encodes_as(grpc_millis ts, const char *s) { + char buffer[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; + grpc_http2_encode_timeout(ts, buffer); + gpr_log(GPR_INFO, "check '%s' == '%s'", buffer, s); + GPR_ASSERT(0 == strcmp(buffer, s)); +} + +void test_encoding(void) { + LOG_TEST("test_encoding"); + assert_encodes_as(-1, "1n"); + assert_encodes_as(-10, "1n"); + assert_encodes_as(1, "1m"); + assert_encodes_as(10, "10m"); + assert_encodes_as(100, "100m"); + assert_encodes_as(890, "890m"); + assert_encodes_as(900, "900m"); + assert_encodes_as(901, "901m"); + assert_encodes_as(1000, "1S"); + assert_encodes_as(2000, "2S"); + assert_encodes_as(2500, "2500m"); + assert_encodes_as(59900, "59900m"); + assert_encodes_as(50000, "50S"); + assert_encodes_as(59000, "59S"); + assert_encodes_as(60000, "1M"); + assert_encodes_as(80000, "80S"); + assert_encodes_as(90000, "90S"); + assert_encodes_as(120000, "2M"); + assert_encodes_as(20 * 60 * GPR_MS_PER_SEC, "20M"); + assert_encodes_as(60 * 60 * GPR_MS_PER_SEC, "1H"); + assert_encodes_as(10 * 60 * 60 * GPR_MS_PER_SEC, "10H"); +} + +static void assert_decodes_as(const char *buffer, grpc_millis expected) { + grpc_millis got; + uint32_t hash = gpr_murmur_hash3(buffer, strlen(buffer), 0); + gpr_log(GPR_INFO, "check decoding '%s' (hash=0x%x)", buffer, hash); + GPR_ASSERT(1 == grpc_http2_decode_timeout( + grpc_slice_from_static_string(buffer), &got)); + if (got != expected) { + gpr_log(GPR_ERROR, "got:'%" PRIdPTR "' != expected:'%" PRIdPTR "'", got, + expected); + abort(); + } +} + +void decode_suite(char ext, grpc_millis (*answer)(int64_t x)) { + long test_vals[] = {1, 12, 123, 1234, 12345, 123456, + 1234567, 12345678, 123456789, 98765432, 9876543, 987654, + 98765, 9876, 987, 98, 9}; + unsigned i; + char *input; + for (i = 0; i < GPR_ARRAY_SIZE(test_vals); i++) { + gpr_asprintf(&input, "%ld%c", test_vals[i], ext); + assert_decodes_as(input, answer(test_vals[i])); + gpr_free(input); + + gpr_asprintf(&input, " %ld%c", test_vals[i], ext); + assert_decodes_as(input, answer(test_vals[i])); + gpr_free(input); + + gpr_asprintf(&input, "%ld %c", test_vals[i], ext); + assert_decodes_as(input, answer(test_vals[i])); + gpr_free(input); + + gpr_asprintf(&input, "%ld %c ", test_vals[i], ext); + assert_decodes_as(input, answer(test_vals[i])); + gpr_free(input); + } +} + +static grpc_millis millis_from_nanos(int64_t x) { + return (grpc_millis)(x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0)); +} +static grpc_millis millis_from_micros(int64_t x) { + return (grpc_millis)(x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0)); +} +static grpc_millis millis_from_millis(int64_t x) { return (grpc_millis)x; } +static grpc_millis millis_from_seconds(int64_t x) { + return (grpc_millis)(x * GPR_MS_PER_SEC); +} +static grpc_millis millis_from_minutes(int64_t x) { + return (grpc_millis)(x * 60 * GPR_MS_PER_SEC); +} +static grpc_millis millis_from_hours(int64_t x) { + return (grpc_millis)(x * 3600 * GPR_MS_PER_SEC); +} + +void test_decoding(void) { + LOG_TEST("test_decoding"); + decode_suite('n', millis_from_nanos); + decode_suite('u', millis_from_micros); + decode_suite('m', millis_from_millis); + decode_suite('S', millis_from_seconds); + decode_suite('M', millis_from_minutes); + decode_suite('H', millis_from_hours); + assert_decodes_as("1000000000S", millis_from_seconds(1000 * 1000 * 1000)); + assert_decodes_as("1000000000000000000000u", GRPC_MILLIS_INF_FUTURE); + assert_decodes_as("1000000001S", GRPC_MILLIS_INF_FUTURE); + assert_decodes_as("2000000001S", GRPC_MILLIS_INF_FUTURE); + assert_decodes_as("9999999999S", GRPC_MILLIS_INF_FUTURE); +} + +static void assert_decoding_fails(const char *s) { + grpc_millis x; + GPR_ASSERT(0 == + grpc_http2_decode_timeout(grpc_slice_from_static_string(s), &x)); +} + +void test_decoding_fails(void) { + LOG_TEST("test_decoding_fails"); + assert_decoding_fails(""); + assert_decoding_fails(" "); + assert_decoding_fails("x"); + assert_decoding_fails("1"); + assert_decoding_fails("1x"); + assert_decoding_fails("1ux"); + assert_decoding_fails("!"); + assert_decoding_fails("n1"); + assert_decoding_fails("-1u"); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_encoding(); + test_decoding(); + test_decoding_fails(); + return 0; +} diff --git a/test/core/tsi/fake_transport_security_test.c b/test/core/tsi/fake_transport_security_test.c deleted file mode 100644 index 11be8802b7..0000000000 --- a/test/core/tsi/fake_transport_security_test.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include "src/core/lib/security/transport/security_connector.h" -#include "src/core/tsi/fake_transport_security.h" -#include "test/core/tsi/transport_security_test_lib.h" -#include "test/core/util/test_config.h" - -#include -#include -#include - -typedef struct fake_tsi_test_fixture { - tsi_test_fixture base; -} fake_tsi_test_fixture; - -static void fake_test_setup_handshakers(tsi_test_fixture *fixture) { - fixture->client_handshaker = - tsi_create_fake_handshaker(true /* is_client. */); - fixture->server_handshaker = - tsi_create_fake_handshaker(false /* is_client. */); -} - -static void validate_handshaker_peers(tsi_handshaker_result *result) { - GPR_ASSERT(result != NULL); - tsi_peer peer; - GPR_ASSERT(tsi_handshaker_result_extract_peer(result, &peer) == TSI_OK); - const tsi_peer_property *property = - tsi_peer_get_property_by_name(&peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); - GPR_ASSERT(property != NULL); - GPR_ASSERT(memcmp(property->value.data, TSI_FAKE_CERTIFICATE_TYPE, - property->value.length) == 0); - tsi_peer_destruct(&peer); -} - -static void fake_test_check_handshaker_peers(tsi_test_fixture *fixture) { - validate_handshaker_peers(fixture->client_result); - validate_handshaker_peers(fixture->server_result); -} - -static void fake_test_destruct(tsi_test_fixture *fixture) {} - -static const struct tsi_test_fixture_vtable vtable = { - fake_test_setup_handshakers, fake_test_check_handshaker_peers, - fake_test_destruct}; - -static tsi_test_fixture *fake_tsi_test_fixture_create() { - fake_tsi_test_fixture *fake_fixture = gpr_zalloc(sizeof(*fake_fixture)); - tsi_test_fixture_init(&fake_fixture->base); - fake_fixture->base.vtable = &vtable; - return &fake_fixture->base; -} - -void fake_tsi_test_do_handshake_tiny_handshake_buffer() { - tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); - fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void fake_tsi_test_do_handshake_small_handshake_buffer() { - tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); - fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void fake_tsi_test_do_handshake() { - tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void fake_tsi_test_do_round_trip_for_all_configs() { - unsigned int *bit_array = - gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS); - const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1); - for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) { - unsigned int v = val; - for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) { - bit_array[ind] = (v & mask) ? 1 : 0; - v <<= 1; - } - tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); - fake_tsi_test_fixture *fake_fixture = (fake_tsi_test_fixture *)fixture; - tsi_test_frame_protector_config_destroy(fake_fixture->base.config); - fake_fixture->base.config = tsi_test_frame_protector_config_create( - bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4], - bit_array[5], bit_array[6], bit_array[7]); - tsi_test_do_round_trip(&fake_fixture->base); - tsi_test_fixture_destroy(fixture); - } - gpr_free(bit_array); -} - -void fake_tsi_test_do_round_trip_odd_buffer_size() { - const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409}; - const size_t size = sizeof(odd_sizes) / sizeof(size_t); - for (size_t ind1 = 0; ind1 < size; ind1++) { - for (size_t ind2 = 0; ind2 < size; ind2++) { - for (size_t ind3 = 0; ind3 < size; ind3++) { - for (size_t ind4 = 0; ind4 < size; ind4++) { - for (size_t ind5 = 0; ind5 < size; ind5++) { - tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); - fake_tsi_test_fixture *fake_fixture = - (fake_tsi_test_fixture *)fixture; - tsi_test_frame_protector_config_set_buffer_size( - fake_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2], - odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]); - tsi_test_do_round_trip(&fake_fixture->base); - tsi_test_fixture_destroy(fixture); - } - } - } - } - } -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - fake_tsi_test_do_handshake_tiny_handshake_buffer(); - fake_tsi_test_do_handshake_small_handshake_buffer(); - fake_tsi_test_do_handshake(); - fake_tsi_test_do_round_trip_for_all_configs(); - fake_tsi_test_do_round_trip_odd_buffer_size(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/tsi/fake_transport_security_test.cc b/test/core/tsi/fake_transport_security_test.cc new file mode 100644 index 0000000000..6561028860 --- /dev/null +++ b/test/core/tsi/fake_transport_security_test.cc @@ -0,0 +1,149 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/tsi/fake_transport_security.h" +#include "test/core/tsi/transport_security_test_lib.h" +#include "test/core/util/test_config.h" + +#include +#include +#include + +typedef struct fake_tsi_test_fixture { + tsi_test_fixture base; +} fake_tsi_test_fixture; + +static void fake_test_setup_handshakers(tsi_test_fixture *fixture) { + fixture->client_handshaker = + tsi_create_fake_handshaker(true /* is_client. */); + fixture->server_handshaker = + tsi_create_fake_handshaker(false /* is_client. */); +} + +static void validate_handshaker_peers(tsi_handshaker_result *result) { + GPR_ASSERT(result != NULL); + tsi_peer peer; + GPR_ASSERT(tsi_handshaker_result_extract_peer(result, &peer) == TSI_OK); + const tsi_peer_property *property = + tsi_peer_get_property_by_name(&peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); + GPR_ASSERT(property != NULL); + GPR_ASSERT(memcmp(property->value.data, TSI_FAKE_CERTIFICATE_TYPE, + property->value.length) == 0); + tsi_peer_destruct(&peer); +} + +static void fake_test_check_handshaker_peers(tsi_test_fixture *fixture) { + validate_handshaker_peers(fixture->client_result); + validate_handshaker_peers(fixture->server_result); +} + +static void fake_test_destruct(tsi_test_fixture *fixture) {} + +static const struct tsi_test_fixture_vtable vtable = { + fake_test_setup_handshakers, fake_test_check_handshaker_peers, + fake_test_destruct}; + +static tsi_test_fixture *fake_tsi_test_fixture_create() { + fake_tsi_test_fixture *fake_fixture = + static_cast(gpr_zalloc(sizeof(*fake_fixture))); + tsi_test_fixture_init(&fake_fixture->base); + fake_fixture->base.vtable = &vtable; + return &fake_fixture->base; +} + +void fake_tsi_test_do_handshake_tiny_handshake_buffer() { + tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); + fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void fake_tsi_test_do_handshake_small_handshake_buffer() { + tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); + fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void fake_tsi_test_do_handshake() { + tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void fake_tsi_test_do_round_trip_for_all_configs() { + unsigned int *bit_array = static_cast( + gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS)); + const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1); + for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) { + unsigned int v = val; + for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) { + bit_array[ind] = (v & mask) ? 1 : 0; + v <<= 1; + } + tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); + fake_tsi_test_fixture *fake_fixture = (fake_tsi_test_fixture *)fixture; + tsi_test_frame_protector_config_destroy(fake_fixture->base.config); + fake_fixture->base.config = tsi_test_frame_protector_config_create( + bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4], + bit_array[5], bit_array[6], bit_array[7]); + tsi_test_do_round_trip(&fake_fixture->base); + tsi_test_fixture_destroy(fixture); + } + gpr_free(bit_array); +} + +void fake_tsi_test_do_round_trip_odd_buffer_size() { + const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409}; + const size_t size = sizeof(odd_sizes) / sizeof(size_t); + for (size_t ind1 = 0; ind1 < size; ind1++) { + for (size_t ind2 = 0; ind2 < size; ind2++) { + for (size_t ind3 = 0; ind3 < size; ind3++) { + for (size_t ind4 = 0; ind4 < size; ind4++) { + for (size_t ind5 = 0; ind5 < size; ind5++) { + tsi_test_fixture *fixture = fake_tsi_test_fixture_create(); + fake_tsi_test_fixture *fake_fixture = + (fake_tsi_test_fixture *)fixture; + tsi_test_frame_protector_config_set_buffer_size( + fake_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2], + odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]); + tsi_test_do_round_trip(&fake_fixture->base); + tsi_test_fixture_destroy(fixture); + } + } + } + } + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + fake_tsi_test_do_handshake_tiny_handshake_buffer(); + fake_tsi_test_do_handshake_small_handshake_buffer(); + fake_tsi_test_do_handshake(); + fake_tsi_test_do_round_trip_for_all_configs(); + fake_tsi_test_do_round_trip_odd_buffer_size(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/tsi/ssl_transport_security_test.c b/test/core/tsi/ssl_transport_security_test.c deleted file mode 100644 index 2399b054b1..0000000000 --- a/test/core/tsi/ssl_transport_security_test.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/security/transport/security_connector.h" -#include "src/core/tsi/ssl_transport_security.h" -#include "src/core/tsi/transport_security.h" -#include "src/core/tsi/transport_security_adapter.h" -#include "src/core/tsi/transport_security_interface.h" -#include "test/core/tsi/transport_security_test_lib.h" -#include "test/core/util/test_config.h" - -#include -#include -#include -#include - -#define SSL_TSI_TEST_ALPN1 "foo" -#define SSL_TSI_TEST_ALPN2 "toto" -#define SSL_TSI_TEST_ALPN3 "baz" -#define SSL_TSI_TEST_ALPN_NUM 2 -#define SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM 2 -#define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1 -#define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/" - -typedef enum AlpnMode { - NO_ALPN, - ALPN_CLIENT_NO_SERVER, - ALPN_SERVER_NO_CLIENT, - ALPN_CLIENT_SERVER_OK, - ALPN_CLIENT_SERVER_MISMATCH -} AlpnMode; - -typedef struct ssl_alpn_lib { - AlpnMode alpn_mode; - char **server_alpn_protocols; - char **client_alpn_protocols; - uint16_t num_server_alpn_protocols; - uint16_t num_client_alpn_protocols; -} ssl_alpn_lib; - -typedef struct ssl_key_cert_lib { - bool use_bad_server_cert; - bool use_bad_client_cert; - char *root_cert; - tsi_ssl_pem_key_cert_pair *server_pem_key_cert_pairs; - tsi_ssl_pem_key_cert_pair *bad_server_pem_key_cert_pairs; - tsi_ssl_pem_key_cert_pair client_pem_key_cert_pair; - tsi_ssl_pem_key_cert_pair bad_client_pem_key_cert_pair; - uint16_t server_num_key_cert_pairs; - uint16_t bad_server_num_key_cert_pairs; -} ssl_key_cert_lib; - -typedef struct ssl_tsi_test_fixture { - tsi_test_fixture base; - ssl_key_cert_lib *key_cert_lib; - ssl_alpn_lib *alpn_lib; - bool force_client_auth; - char *server_name_indication; - tsi_ssl_server_handshaker_factory *server_handshaker_factory; - tsi_ssl_client_handshaker_factory *client_handshaker_factory; -} ssl_tsi_test_fixture; - -static void ssl_test_setup_handshakers(tsi_test_fixture *fixture) { - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - GPR_ASSERT(ssl_fixture != NULL); - GPR_ASSERT(ssl_fixture->key_cert_lib != NULL); - GPR_ASSERT(ssl_fixture->alpn_lib != NULL); - ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; - ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; - /* Create client handshaker factory. */ - tsi_ssl_pem_key_cert_pair *client_key_cert_pair = NULL; - if (ssl_fixture->force_client_auth) { - client_key_cert_pair = key_cert_lib->use_bad_client_cert - ? &key_cert_lib->bad_client_pem_key_cert_pair - : &key_cert_lib->client_pem_key_cert_pair; - } - char **client_alpn_protocols = NULL; - uint16_t num_client_alpn_protocols = 0; - if (alpn_lib->alpn_mode == ALPN_CLIENT_NO_SERVER || - alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK || - alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { - client_alpn_protocols = alpn_lib->client_alpn_protocols; - num_client_alpn_protocols = alpn_lib->num_client_alpn_protocols; - } - GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( - client_key_cert_pair, key_cert_lib->root_cert, NULL, - (const char **)client_alpn_protocols, - num_client_alpn_protocols, - &ssl_fixture->client_handshaker_factory) == TSI_OK); - /* Create server handshaker factory. */ - char **server_alpn_protocols = NULL; - uint16_t num_server_alpn_protocols = 0; - if (alpn_lib->alpn_mode == ALPN_SERVER_NO_CLIENT || - alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK || - alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { - server_alpn_protocols = alpn_lib->server_alpn_protocols; - num_server_alpn_protocols = alpn_lib->num_server_alpn_protocols; - if (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { - num_server_alpn_protocols--; - } - } - GPR_ASSERT(tsi_create_ssl_server_handshaker_factory( - key_cert_lib->use_bad_server_cert - ? key_cert_lib->bad_server_pem_key_cert_pairs - : key_cert_lib->server_pem_key_cert_pairs, - key_cert_lib->use_bad_server_cert - ? key_cert_lib->bad_server_num_key_cert_pairs - : key_cert_lib->server_num_key_cert_pairs, - key_cert_lib->root_cert, ssl_fixture->force_client_auth, NULL, - (const char **)server_alpn_protocols, - num_server_alpn_protocols, - &ssl_fixture->server_handshaker_factory) == TSI_OK); - /* Create server and client handshakers. */ - tsi_handshaker *client_handshaker = NULL; - GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker( - ssl_fixture->client_handshaker_factory, - ssl_fixture->server_name_indication, - &client_handshaker) == TSI_OK); - ssl_fixture->base.client_handshaker = - tsi_create_adapter_handshaker(client_handshaker); - tsi_handshaker *server_handshaker = NULL; - GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker( - ssl_fixture->server_handshaker_factory, &server_handshaker) == - TSI_OK); - ssl_fixture->base.server_handshaker = - tsi_create_adapter_handshaker(server_handshaker); -} - -static void check_alpn(ssl_tsi_test_fixture *ssl_fixture, - const tsi_peer *peer) { - GPR_ASSERT(ssl_fixture != NULL); - GPR_ASSERT(ssl_fixture->alpn_lib != NULL); - ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; - const tsi_peer_property *alpn_property = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (alpn_lib->alpn_mode != ALPN_CLIENT_SERVER_OK) { - GPR_ASSERT(alpn_property == NULL); - } else { - GPR_ASSERT(alpn_property != NULL); - const char *expected_match = "baz"; - GPR_ASSERT(memcmp(alpn_property->value.data, expected_match, - alpn_property->value.length) == 0); - } -} - -static const tsi_peer_property * -check_basic_authenticated_peer_and_get_common_name(const tsi_peer *peer) { - const tsi_peer_property *cert_type_property = - tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); - GPR_ASSERT(cert_type_property != NULL); - GPR_ASSERT(memcmp(cert_type_property->value.data, TSI_X509_CERTIFICATE_TYPE, - cert_type_property->value.length) == 0); - const tsi_peer_property *property = tsi_peer_get_property_by_name( - peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); - GPR_ASSERT(property != NULL); - return property; -} - -void check_server0_peer(tsi_peer *peer) { - const tsi_peer_property *property = - check_basic_authenticated_peer_and_get_common_name(peer); - const char *expected_match = "*.test.google.com.au"; - GPR_ASSERT(memcmp(property->value.data, expected_match, - property->value.length) == 0); - GPR_ASSERT(tsi_peer_get_property_by_name( - peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == - NULL); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.com.au") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.com.au") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.blah") == 0); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.bar.test.google.com.au") == - 0); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.com.au") == 0); - tsi_peer_destruct(peer); -} - -static bool check_subject_alt_name(tsi_peer *peer, const char *name) { - for (size_t i = 0; i < peer->property_count; i++) { - const tsi_peer_property *prop = &peer->properties[i]; - if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == - 0) { - if (memcmp(prop->value.data, name, prop->value.length) == 0) { - return true; - } - } - } - return false; -} - -void check_server1_peer(tsi_peer *peer) { - const tsi_peer_property *property = - check_basic_authenticated_peer_and_get_common_name(peer); - const char *expected_match = "*.test.google.com"; - GPR_ASSERT(memcmp(property->value.data, expected_match, - property->value.length) == 0); - GPR_ASSERT(check_subject_alt_name(peer, "*.test.google.fr") == 1); - GPR_ASSERT(check_subject_alt_name(peer, "waterzooi.test.google.be") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.fr") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.fr") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "waterzooi.test.google.be") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.youtube.com") == 1); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.foo.test.google.com") == 0); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.fr") == 0); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.test.google.be") == 0); - GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.youtube.com") == 0); - tsi_peer_destruct(peer); -} - -static void check_client_peer(ssl_tsi_test_fixture *ssl_fixture, - tsi_peer *peer) { - GPR_ASSERT(ssl_fixture != NULL); - GPR_ASSERT(ssl_fixture->alpn_lib != NULL); - ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; - if (!ssl_fixture->force_client_auth) { - GPR_ASSERT(peer->property_count == - (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 1 : 0)); - } else { - const tsi_peer_property *property = - check_basic_authenticated_peer_and_get_common_name(peer); - const char *expected_match = "testclient"; - GPR_ASSERT(memcmp(property->value.data, expected_match, - property->value.length) == 0); - } - tsi_peer_destruct(peer); -} - -static void ssl_test_check_handshaker_peers(tsi_test_fixture *fixture) { - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - GPR_ASSERT(ssl_fixture != NULL); - GPR_ASSERT(ssl_fixture->key_cert_lib != NULL); - ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; - tsi_peer peer; - bool expect_success = - !(key_cert_lib->use_bad_server_cert || - (key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth)); - if (expect_success) { - GPR_ASSERT(tsi_handshaker_result_extract_peer( - ssl_fixture->base.client_result, &peer) == TSI_OK); - check_alpn(ssl_fixture, &peer); - - if (ssl_fixture->server_name_indication != NULL) { - check_server1_peer(&peer); - } else { - check_server0_peer(&peer); - } - } else { - GPR_ASSERT(ssl_fixture->base.client_result == NULL); - } - if (expect_success) { - GPR_ASSERT(tsi_handshaker_result_extract_peer( - ssl_fixture->base.server_result, &peer) == TSI_OK); - check_alpn(ssl_fixture, &peer); - check_client_peer(ssl_fixture, &peer); - } else { - GPR_ASSERT(ssl_fixture->base.server_result == NULL); - } -} - -static void ssl_test_pem_key_cert_pair_destroy(tsi_ssl_pem_key_cert_pair kp) { - gpr_free((void *)kp.private_key); - gpr_free((void *)kp.cert_chain); -} - -static void ssl_test_destruct(tsi_test_fixture *fixture) { - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - if (ssl_fixture == NULL) { - return; - } - /* Destroy ssl_alpn_lib. */ - ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; - for (size_t i = 0; i < alpn_lib->num_server_alpn_protocols; i++) { - gpr_free(alpn_lib->server_alpn_protocols[i]); - } - gpr_free(alpn_lib->server_alpn_protocols); - for (size_t i = 0; i < alpn_lib->num_client_alpn_protocols; i++) { - gpr_free(alpn_lib->client_alpn_protocols[i]); - } - gpr_free(alpn_lib->client_alpn_protocols); - gpr_free(alpn_lib); - /* Destroy ssl_key_cert_lib. */ - ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; - for (size_t i = 0; i < key_cert_lib->server_num_key_cert_pairs; i++) { - ssl_test_pem_key_cert_pair_destroy( - key_cert_lib->server_pem_key_cert_pairs[i]); - } - gpr_free(key_cert_lib->server_pem_key_cert_pairs); - for (size_t i = 0; i < key_cert_lib->bad_server_num_key_cert_pairs; i++) { - ssl_test_pem_key_cert_pair_destroy( - key_cert_lib->bad_server_pem_key_cert_pairs[i]); - } - gpr_free(key_cert_lib->bad_server_pem_key_cert_pairs); - ssl_test_pem_key_cert_pair_destroy(key_cert_lib->client_pem_key_cert_pair); - ssl_test_pem_key_cert_pair_destroy( - key_cert_lib->bad_client_pem_key_cert_pair); - gpr_free(key_cert_lib->root_cert); - gpr_free(key_cert_lib); - /* Unreference others. */ - tsi_ssl_server_handshaker_factory_unref( - ssl_fixture->server_handshaker_factory); - tsi_ssl_client_handshaker_factory_unref( - ssl_fixture->client_handshaker_factory); -} - -static const struct tsi_test_fixture_vtable vtable = { - ssl_test_setup_handshakers, ssl_test_check_handshaker_peers, - ssl_test_destruct}; - -static char *load_file(const char *dir_path, const char *file_name) { - char *file_path = - gpr_zalloc(sizeof(char) * (strlen(dir_path) + strlen(file_name) + 1)); - memcpy(file_path, dir_path, strlen(dir_path)); - memcpy(file_path + strlen(dir_path), file_name, strlen(file_name)); - grpc_slice slice; - GPR_ASSERT(grpc_load_file(file_path, 1, &slice) == GRPC_ERROR_NONE); - char *data = grpc_slice_to_c_string(slice); - grpc_slice_unref(slice); - gpr_free(file_path); - return data; -} - -static tsi_test_fixture *ssl_tsi_test_fixture_create() { - ssl_tsi_test_fixture *ssl_fixture = gpr_zalloc(sizeof(*ssl_fixture)); - tsi_test_fixture_init(&ssl_fixture->base); - ssl_fixture->base.test_unused_bytes = false; - ssl_fixture->base.vtable = &vtable; - /* Create ssl_key_cert_lib. */ - ssl_key_cert_lib *key_cert_lib = gpr_zalloc(sizeof(*key_cert_lib)); - key_cert_lib->use_bad_server_cert = false; - key_cert_lib->use_bad_client_cert = false; - key_cert_lib->server_num_key_cert_pairs = - SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM; - key_cert_lib->bad_server_num_key_cert_pairs = - SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM; - key_cert_lib->server_pem_key_cert_pairs = - gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) * - key_cert_lib->server_num_key_cert_pairs); - key_cert_lib->bad_server_pem_key_cert_pairs = - gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) * - key_cert_lib->bad_server_num_key_cert_pairs); - key_cert_lib->server_pem_key_cert_pairs[0].private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key"); - key_cert_lib->server_pem_key_cert_pairs[0].cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem"); - key_cert_lib->server_pem_key_cert_pairs[1].private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.key"); - key_cert_lib->server_pem_key_cert_pairs[1].cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.pem"); - key_cert_lib->bad_server_pem_key_cert_pairs[0].private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.key"); - key_cert_lib->bad_server_pem_key_cert_pairs[0].cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.pem"); - key_cert_lib->client_pem_key_cert_pair.private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.key"); - key_cert_lib->client_pem_key_cert_pair.cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem"); - key_cert_lib->bad_client_pem_key_cert_pair.private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.key"); - key_cert_lib->bad_client_pem_key_cert_pair.cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.pem"); - key_cert_lib->root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); - ssl_fixture->key_cert_lib = key_cert_lib; - /* Create ssl_alpn_lib. */ - ssl_alpn_lib *alpn_lib = gpr_zalloc(sizeof(*alpn_lib)); - alpn_lib->server_alpn_protocols = - gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM); - alpn_lib->client_alpn_protocols = - gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM); - alpn_lib->server_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN1); - alpn_lib->server_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3); - alpn_lib->client_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN2); - alpn_lib->client_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3); - alpn_lib->num_server_alpn_protocols = SSL_TSI_TEST_ALPN_NUM; - alpn_lib->num_client_alpn_protocols = SSL_TSI_TEST_ALPN_NUM; - alpn_lib->alpn_mode = NO_ALPN; - ssl_fixture->alpn_lib = alpn_lib; - ssl_fixture->base.vtable = &vtable; - ssl_fixture->server_name_indication = NULL; - ssl_fixture->force_client_auth = false; - return &ssl_fixture->base; -} - -void ssl_tsi_test_do_handshake_tiny_handshake_buffer() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_small_handshake_buffer() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_with_client_authentication() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->force_client_auth = true; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain() { - /* server1 cert contains "waterzooi.test.google.be" in SAN. */ - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->server_name_indication = "waterzooi.test.google.be"; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain() { - /* server1 cert contains "*.test.google.fr" in SAN. */ - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->server_name_indication = "juju.test.google.fr"; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_with_bad_server_cert() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->key_cert_lib->use_bad_server_cert = true; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_with_bad_client_cert() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->key_cert_lib->use_bad_client_cert = true; - ssl_fixture->force_client_auth = true; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_alpn_client_no_server() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_NO_SERVER; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_alpn_server_no_client() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->alpn_lib->alpn_mode = ALPN_SERVER_NO_CLIENT; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_alpn_client_server_mismatch() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_MISMATCH; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_handshake_alpn_client_server_ok() { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_OK; - tsi_test_do_handshake(fixture); - tsi_test_fixture_destroy(fixture); -} - -void ssl_tsi_test_do_round_trip_for_all_configs() { - unsigned int *bit_array = - gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS); - const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1); - for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) { - unsigned int v = val; - for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) { - bit_array[ind] = (v & mask) ? 1 : 0; - v <<= 1; - } - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - tsi_test_frame_protector_config_destroy(ssl_fixture->base.config); - ssl_fixture->base.config = tsi_test_frame_protector_config_create( - bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4], - bit_array[5], bit_array[6], bit_array[7]); - tsi_test_do_round_trip(&ssl_fixture->base); - tsi_test_fixture_destroy(fixture); - } - gpr_free(bit_array); -} - -void ssl_tsi_test_do_round_trip_odd_buffer_size() { - const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409}; - const size_t size = sizeof(odd_sizes) / sizeof(size_t); - for (size_t ind1 = 0; ind1 < size; ind1++) { - for (size_t ind2 = 0; ind2 < size; ind2++) { - for (size_t ind3 = 0; ind3 < size; ind3++) { - for (size_t ind4 = 0; ind4 < size; ind4++) { - for (size_t ind5 = 0; ind5 < size; ind5++) { - tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); - ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; - tsi_test_frame_protector_config_set_buffer_size( - ssl_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2], - odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]); - tsi_test_do_round_trip(&ssl_fixture->base); - tsi_test_fixture_destroy(fixture); - } - } - } - } - } -} - -static const tsi_ssl_handshaker_factory_vtable *original_vtable; -static bool handshaker_factory_destructor_called; - -static void ssl_tsi_test_handshaker_factory_destructor( - tsi_ssl_handshaker_factory *factory) { - GPR_ASSERT(factory != NULL); - handshaker_factory_destructor_called = true; - if (original_vtable != NULL && original_vtable->destroy != NULL) { - original_vtable->destroy(factory); - } -} - -static tsi_ssl_handshaker_factory_vtable test_handshaker_factory_vtable = { - ssl_tsi_test_handshaker_factory_destructor}; - -void test_tsi_ssl_client_handshaker_factory_refcounting() { - int i; - const char *cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem"); - - tsi_ssl_client_handshaker_factory *client_handshaker_factory; - GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( - NULL, cert_chain, NULL, NULL, 0, &client_handshaker_factory) == - TSI_OK); - - handshaker_factory_destructor_called = false; - original_vtable = tsi_ssl_handshaker_factory_swap_vtable( - (tsi_ssl_handshaker_factory *)client_handshaker_factory, - &test_handshaker_factory_vtable); - - tsi_handshaker *handshaker[3]; - - for (i = 0; i < 3; ++i) { - GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker( - client_handshaker_factory, "google.com", &handshaker[i]) == - TSI_OK); - } - - tsi_handshaker_destroy(handshaker[1]); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_handshaker_destroy(handshaker[0]); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_handshaker_destroy(handshaker[2]); - GPR_ASSERT(handshaker_factory_destructor_called); - - gpr_free((void *)cert_chain); -} - -void test_tsi_ssl_server_handshaker_factory_refcounting() { - int i; - tsi_ssl_server_handshaker_factory *server_handshaker_factory; - tsi_handshaker *handshaker[3]; - const char *cert_chain = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem"); - tsi_ssl_pem_key_cert_pair cert_pair; - - cert_pair.cert_chain = cert_chain; - cert_pair.private_key = - load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key"); - - GPR_ASSERT(tsi_create_ssl_server_handshaker_factory( - &cert_pair, 1, cert_chain, 0, NULL, NULL, 0, - &server_handshaker_factory) == TSI_OK); - - handshaker_factory_destructor_called = false; - original_vtable = tsi_ssl_handshaker_factory_swap_vtable( - (tsi_ssl_handshaker_factory *)server_handshaker_factory, - &test_handshaker_factory_vtable); - - for (i = 0; i < 3; ++i) { - GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker( - server_handshaker_factory, &handshaker[i]) == TSI_OK); - } - - tsi_handshaker_destroy(handshaker[1]); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_handshaker_destroy(handshaker[0]); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory); - GPR_ASSERT(!handshaker_factory_destructor_called); - - tsi_handshaker_destroy(handshaker[2]); - GPR_ASSERT(handshaker_factory_destructor_called); - - ssl_test_pem_key_cert_pair_destroy(cert_pair); -} - -/* Attempting to create a handshaker factory with invalid parameters should fail - * but not crash. */ -void test_tsi_ssl_client_handshaker_factory_bad_params() { - const char *cert_chain = "This is not a valid PEM file."; - - tsi_ssl_client_handshaker_factory *client_handshaker_factory; - GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( - NULL, cert_chain, NULL, NULL, 0, &client_handshaker_factory) == - TSI_INVALID_ARGUMENT); - tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory); -} - -void ssl_tsi_test_handshaker_factory_internals() { - test_tsi_ssl_client_handshaker_factory_refcounting(); - test_tsi_ssl_server_handshaker_factory_refcounting(); - test_tsi_ssl_client_handshaker_factory_bad_params(); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - ssl_tsi_test_do_handshake_tiny_handshake_buffer(); - ssl_tsi_test_do_handshake_small_handshake_buffer(); - ssl_tsi_test_do_handshake(); - ssl_tsi_test_do_handshake_with_client_authentication(); - ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain(); - ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain(); - ssl_tsi_test_do_handshake_with_bad_server_cert(); - ssl_tsi_test_do_handshake_with_bad_client_cert(); - ssl_tsi_test_do_handshake_alpn_client_no_server(); - ssl_tsi_test_do_handshake_alpn_server_no_client(); - ssl_tsi_test_do_handshake_alpn_client_server_mismatch(); - ssl_tsi_test_do_handshake_alpn_client_server_ok(); - ssl_tsi_test_do_round_trip_for_all_configs(); - ssl_tsi_test_do_round_trip_odd_buffer_size(); - ssl_tsi_test_handshaker_factory_internals(); - grpc_shutdown(); - return 0; -} diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc new file mode 100644 index 0000000000..27b2049dd8 --- /dev/null +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -0,0 +1,680 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" +#include "src/core/tsi/transport_security_adapter.h" +#include "src/core/tsi/transport_security_interface.h" +#include "test/core/tsi/transport_security_test_lib.h" +#include "test/core/util/test_config.h" + +#include +#include +#include +#include + +#define SSL_TSI_TEST_ALPN1 "foo" +#define SSL_TSI_TEST_ALPN2 "toto" +#define SSL_TSI_TEST_ALPN3 "baz" +#define SSL_TSI_TEST_ALPN_NUM 2 +#define SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM 2 +#define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1 +#define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/" + +typedef enum AlpnMode { + NO_ALPN, + ALPN_CLIENT_NO_SERVER, + ALPN_SERVER_NO_CLIENT, + ALPN_CLIENT_SERVER_OK, + ALPN_CLIENT_SERVER_MISMATCH +} AlpnMode; + +typedef struct ssl_alpn_lib { + AlpnMode alpn_mode; + char **server_alpn_protocols; + char **client_alpn_protocols; + uint16_t num_server_alpn_protocols; + uint16_t num_client_alpn_protocols; +} ssl_alpn_lib; + +typedef struct ssl_key_cert_lib { + bool use_bad_server_cert; + bool use_bad_client_cert; + char *root_cert; + tsi_ssl_pem_key_cert_pair *server_pem_key_cert_pairs; + tsi_ssl_pem_key_cert_pair *bad_server_pem_key_cert_pairs; + tsi_ssl_pem_key_cert_pair client_pem_key_cert_pair; + tsi_ssl_pem_key_cert_pair bad_client_pem_key_cert_pair; + uint16_t server_num_key_cert_pairs; + uint16_t bad_server_num_key_cert_pairs; +} ssl_key_cert_lib; + +typedef struct ssl_tsi_test_fixture { + tsi_test_fixture base; + ssl_key_cert_lib *key_cert_lib; + ssl_alpn_lib *alpn_lib; + bool force_client_auth; + char *server_name_indication; + tsi_ssl_server_handshaker_factory *server_handshaker_factory; + tsi_ssl_client_handshaker_factory *client_handshaker_factory; +} ssl_tsi_test_fixture; + +static void ssl_test_setup_handshakers(tsi_test_fixture *fixture) { + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + GPR_ASSERT(ssl_fixture != NULL); + GPR_ASSERT(ssl_fixture->key_cert_lib != NULL); + GPR_ASSERT(ssl_fixture->alpn_lib != NULL); + ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; + ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; + /* Create client handshaker factory. */ + tsi_ssl_pem_key_cert_pair *client_key_cert_pair = NULL; + if (ssl_fixture->force_client_auth) { + client_key_cert_pair = key_cert_lib->use_bad_client_cert + ? &key_cert_lib->bad_client_pem_key_cert_pair + : &key_cert_lib->client_pem_key_cert_pair; + } + char **client_alpn_protocols = NULL; + uint16_t num_client_alpn_protocols = 0; + if (alpn_lib->alpn_mode == ALPN_CLIENT_NO_SERVER || + alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK || + alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { + client_alpn_protocols = alpn_lib->client_alpn_protocols; + num_client_alpn_protocols = alpn_lib->num_client_alpn_protocols; + } + GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( + client_key_cert_pair, key_cert_lib->root_cert, NULL, + (const char **)client_alpn_protocols, + num_client_alpn_protocols, + &ssl_fixture->client_handshaker_factory) == TSI_OK); + /* Create server handshaker factory. */ + char **server_alpn_protocols = NULL; + uint16_t num_server_alpn_protocols = 0; + if (alpn_lib->alpn_mode == ALPN_SERVER_NO_CLIENT || + alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK || + alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { + server_alpn_protocols = alpn_lib->server_alpn_protocols; + num_server_alpn_protocols = alpn_lib->num_server_alpn_protocols; + if (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) { + num_server_alpn_protocols--; + } + } + GPR_ASSERT(tsi_create_ssl_server_handshaker_factory( + key_cert_lib->use_bad_server_cert + ? key_cert_lib->bad_server_pem_key_cert_pairs + : key_cert_lib->server_pem_key_cert_pairs, + key_cert_lib->use_bad_server_cert + ? key_cert_lib->bad_server_num_key_cert_pairs + : key_cert_lib->server_num_key_cert_pairs, + key_cert_lib->root_cert, ssl_fixture->force_client_auth, NULL, + (const char **)server_alpn_protocols, + num_server_alpn_protocols, + &ssl_fixture->server_handshaker_factory) == TSI_OK); + /* Create server and client handshakers. */ + tsi_handshaker *client_handshaker = NULL; + GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker( + ssl_fixture->client_handshaker_factory, + ssl_fixture->server_name_indication, + &client_handshaker) == TSI_OK); + ssl_fixture->base.client_handshaker = + tsi_create_adapter_handshaker(client_handshaker); + tsi_handshaker *server_handshaker = NULL; + GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker( + ssl_fixture->server_handshaker_factory, &server_handshaker) == + TSI_OK); + ssl_fixture->base.server_handshaker = + tsi_create_adapter_handshaker(server_handshaker); +} + +static void check_alpn(ssl_tsi_test_fixture *ssl_fixture, + const tsi_peer *peer) { + GPR_ASSERT(ssl_fixture != NULL); + GPR_ASSERT(ssl_fixture->alpn_lib != NULL); + ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; + const tsi_peer_property *alpn_property = + tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); + if (alpn_lib->alpn_mode != ALPN_CLIENT_SERVER_OK) { + GPR_ASSERT(alpn_property == NULL); + } else { + GPR_ASSERT(alpn_property != NULL); + const char *expected_match = "baz"; + GPR_ASSERT(memcmp(alpn_property->value.data, expected_match, + alpn_property->value.length) == 0); + } +} + +static const tsi_peer_property * +check_basic_authenticated_peer_and_get_common_name(const tsi_peer *peer) { + const tsi_peer_property *cert_type_property = + tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY); + GPR_ASSERT(cert_type_property != NULL); + GPR_ASSERT(memcmp(cert_type_property->value.data, TSI_X509_CERTIFICATE_TYPE, + cert_type_property->value.length) == 0); + const tsi_peer_property *property = tsi_peer_get_property_by_name( + peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); + GPR_ASSERT(property != NULL); + return property; +} + +void check_server0_peer(tsi_peer *peer) { + const tsi_peer_property *property = + check_basic_authenticated_peer_and_get_common_name(peer); + const char *expected_match = "*.test.google.com.au"; + GPR_ASSERT(memcmp(property->value.data, expected_match, + property->value.length) == 0); + GPR_ASSERT(tsi_peer_get_property_by_name( + peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == + NULL); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.com.au") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.com.au") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.blah") == 0); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.bar.test.google.com.au") == + 0); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.com.au") == 0); + tsi_peer_destruct(peer); +} + +static bool check_subject_alt_name(tsi_peer *peer, const char *name) { + for (size_t i = 0; i < peer->property_count; i++) { + const tsi_peer_property *prop = &peer->properties[i]; + if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == + 0) { + if (memcmp(prop->value.data, name, prop->value.length) == 0) { + return true; + } + } + } + return false; +} + +void check_server1_peer(tsi_peer *peer) { + const tsi_peer_property *property = + check_basic_authenticated_peer_and_get_common_name(peer); + const char *expected_match = "*.test.google.com"; + GPR_ASSERT(memcmp(property->value.data, expected_match, + property->value.length) == 0); + GPR_ASSERT(check_subject_alt_name(peer, "*.test.google.fr") == 1); + GPR_ASSERT(check_subject_alt_name(peer, "waterzooi.test.google.be") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.fr") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.fr") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "waterzooi.test.google.be") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.youtube.com") == 1); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.foo.test.google.com") == 0); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.fr") == 0); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.test.google.be") == 0); + GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.youtube.com") == 0); + tsi_peer_destruct(peer); +} + +static void check_client_peer(ssl_tsi_test_fixture *ssl_fixture, + tsi_peer *peer) { + GPR_ASSERT(ssl_fixture != NULL); + GPR_ASSERT(ssl_fixture->alpn_lib != NULL); + ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; + if (!ssl_fixture->force_client_auth) { + GPR_ASSERT(peer->property_count == + (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 1 : 0)); + } else { + const tsi_peer_property *property = + check_basic_authenticated_peer_and_get_common_name(peer); + const char *expected_match = "testclient"; + GPR_ASSERT(memcmp(property->value.data, expected_match, + property->value.length) == 0); + } + tsi_peer_destruct(peer); +} + +static void ssl_test_check_handshaker_peers(tsi_test_fixture *fixture) { + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + GPR_ASSERT(ssl_fixture != NULL); + GPR_ASSERT(ssl_fixture->key_cert_lib != NULL); + ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; + tsi_peer peer; + bool expect_success = + !(key_cert_lib->use_bad_server_cert || + (key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth)); + if (expect_success) { + GPR_ASSERT(tsi_handshaker_result_extract_peer( + ssl_fixture->base.client_result, &peer) == TSI_OK); + check_alpn(ssl_fixture, &peer); + + if (ssl_fixture->server_name_indication != NULL) { + check_server1_peer(&peer); + } else { + check_server0_peer(&peer); + } + } else { + GPR_ASSERT(ssl_fixture->base.client_result == NULL); + } + if (expect_success) { + GPR_ASSERT(tsi_handshaker_result_extract_peer( + ssl_fixture->base.server_result, &peer) == TSI_OK); + check_alpn(ssl_fixture, &peer); + check_client_peer(ssl_fixture, &peer); + } else { + GPR_ASSERT(ssl_fixture->base.server_result == NULL); + } +} + +static void ssl_test_pem_key_cert_pair_destroy(tsi_ssl_pem_key_cert_pair kp) { + gpr_free((void *)kp.private_key); + gpr_free((void *)kp.cert_chain); +} + +static void ssl_test_destruct(tsi_test_fixture *fixture) { + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + if (ssl_fixture == NULL) { + return; + } + /* Destroy ssl_alpn_lib. */ + ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib; + for (size_t i = 0; i < alpn_lib->num_server_alpn_protocols; i++) { + gpr_free(alpn_lib->server_alpn_protocols[i]); + } + gpr_free(alpn_lib->server_alpn_protocols); + for (size_t i = 0; i < alpn_lib->num_client_alpn_protocols; i++) { + gpr_free(alpn_lib->client_alpn_protocols[i]); + } + gpr_free(alpn_lib->client_alpn_protocols); + gpr_free(alpn_lib); + /* Destroy ssl_key_cert_lib. */ + ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib; + for (size_t i = 0; i < key_cert_lib->server_num_key_cert_pairs; i++) { + ssl_test_pem_key_cert_pair_destroy( + key_cert_lib->server_pem_key_cert_pairs[i]); + } + gpr_free(key_cert_lib->server_pem_key_cert_pairs); + for (size_t i = 0; i < key_cert_lib->bad_server_num_key_cert_pairs; i++) { + ssl_test_pem_key_cert_pair_destroy( + key_cert_lib->bad_server_pem_key_cert_pairs[i]); + } + gpr_free(key_cert_lib->bad_server_pem_key_cert_pairs); + ssl_test_pem_key_cert_pair_destroy(key_cert_lib->client_pem_key_cert_pair); + ssl_test_pem_key_cert_pair_destroy( + key_cert_lib->bad_client_pem_key_cert_pair); + gpr_free(key_cert_lib->root_cert); + gpr_free(key_cert_lib); + /* Unreference others. */ + tsi_ssl_server_handshaker_factory_unref( + ssl_fixture->server_handshaker_factory); + tsi_ssl_client_handshaker_factory_unref( + ssl_fixture->client_handshaker_factory); +} + +static const struct tsi_test_fixture_vtable vtable = { + ssl_test_setup_handshakers, ssl_test_check_handshaker_peers, + ssl_test_destruct}; + +static char *load_file(const char *dir_path, const char *file_name) { + char *file_path = static_cast( + gpr_zalloc(sizeof(char) * (strlen(dir_path) + strlen(file_name) + 1))); + memcpy(file_path, dir_path, strlen(dir_path)); + memcpy(file_path + strlen(dir_path), file_name, strlen(file_name)); + grpc_slice slice; + GPR_ASSERT(grpc_load_file(file_path, 1, &slice) == GRPC_ERROR_NONE); + char *data = grpc_slice_to_c_string(slice); + grpc_slice_unref(slice); + gpr_free(file_path); + return data; +} + +static tsi_test_fixture *ssl_tsi_test_fixture_create() { + ssl_tsi_test_fixture *ssl_fixture = + static_cast(gpr_zalloc(sizeof(*ssl_fixture))); + tsi_test_fixture_init(&ssl_fixture->base); + ssl_fixture->base.test_unused_bytes = false; + ssl_fixture->base.vtable = &vtable; + /* Create ssl_key_cert_lib. */ + ssl_key_cert_lib *key_cert_lib = + static_cast(gpr_zalloc(sizeof(*key_cert_lib))); + key_cert_lib->use_bad_server_cert = false; + key_cert_lib->use_bad_client_cert = false; + key_cert_lib->server_num_key_cert_pairs = + SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM; + key_cert_lib->bad_server_num_key_cert_pairs = + SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM; + key_cert_lib->server_pem_key_cert_pairs = + static_cast( + gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) * + key_cert_lib->server_num_key_cert_pairs)); + key_cert_lib->bad_server_pem_key_cert_pairs = + static_cast( + gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) * + key_cert_lib->bad_server_num_key_cert_pairs)); + key_cert_lib->server_pem_key_cert_pairs[0].private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key"); + key_cert_lib->server_pem_key_cert_pairs[0].cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem"); + key_cert_lib->server_pem_key_cert_pairs[1].private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.key"); + key_cert_lib->server_pem_key_cert_pairs[1].cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.pem"); + key_cert_lib->bad_server_pem_key_cert_pairs[0].private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.key"); + key_cert_lib->bad_server_pem_key_cert_pairs[0].cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.pem"); + key_cert_lib->client_pem_key_cert_pair.private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.key"); + key_cert_lib->client_pem_key_cert_pair.cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem"); + key_cert_lib->bad_client_pem_key_cert_pair.private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.key"); + key_cert_lib->bad_client_pem_key_cert_pair.cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.pem"); + key_cert_lib->root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); + ssl_fixture->key_cert_lib = key_cert_lib; + /* Create ssl_alpn_lib. */ + ssl_alpn_lib *alpn_lib = + static_cast(gpr_zalloc(sizeof(*alpn_lib))); + alpn_lib->server_alpn_protocols = + static_cast(gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM)); + alpn_lib->client_alpn_protocols = + static_cast(gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM)); + alpn_lib->server_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN1); + alpn_lib->server_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3); + alpn_lib->client_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN2); + alpn_lib->client_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3); + alpn_lib->num_server_alpn_protocols = SSL_TSI_TEST_ALPN_NUM; + alpn_lib->num_client_alpn_protocols = SSL_TSI_TEST_ALPN_NUM; + alpn_lib->alpn_mode = NO_ALPN; + ssl_fixture->alpn_lib = alpn_lib; + ssl_fixture->base.vtable = &vtable; + ssl_fixture->server_name_indication = NULL; + ssl_fixture->force_client_auth = false; + return &ssl_fixture->base; +} + +void ssl_tsi_test_do_handshake_tiny_handshake_buffer() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_small_handshake_buffer() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_with_client_authentication() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->force_client_auth = true; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain() { + /* server1 cert contains "waterzooi.test.google.be" in SAN. */ + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->server_name_indication = + const_cast("waterzooi.test.google.be"); + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain() { + /* server1 cert contains "*.test.google.fr" in SAN. */ + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->server_name_indication = + const_cast("juju.test.google.fr"); + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_with_bad_server_cert() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->key_cert_lib->use_bad_server_cert = true; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_with_bad_client_cert() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->key_cert_lib->use_bad_client_cert = true; + ssl_fixture->force_client_auth = true; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_alpn_client_no_server() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_NO_SERVER; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_alpn_server_no_client() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->alpn_lib->alpn_mode = ALPN_SERVER_NO_CLIENT; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_alpn_client_server_mismatch() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_MISMATCH; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_handshake_alpn_client_server_ok() { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_OK; + tsi_test_do_handshake(fixture); + tsi_test_fixture_destroy(fixture); +} + +void ssl_tsi_test_do_round_trip_for_all_configs() { + unsigned int *bit_array = static_cast( + gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS)); + const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1); + for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) { + unsigned int v = val; + for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) { + bit_array[ind] = (v & mask) ? 1 : 0; + v <<= 1; + } + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + tsi_test_frame_protector_config_destroy(ssl_fixture->base.config); + ssl_fixture->base.config = tsi_test_frame_protector_config_create( + bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4], + bit_array[5], bit_array[6], bit_array[7]); + tsi_test_do_round_trip(&ssl_fixture->base); + tsi_test_fixture_destroy(fixture); + } + gpr_free(bit_array); +} + +void ssl_tsi_test_do_round_trip_odd_buffer_size() { + const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409}; + const size_t size = sizeof(odd_sizes) / sizeof(size_t); + for (size_t ind1 = 0; ind1 < size; ind1++) { + for (size_t ind2 = 0; ind2 < size; ind2++) { + for (size_t ind3 = 0; ind3 < size; ind3++) { + for (size_t ind4 = 0; ind4 < size; ind4++) { + for (size_t ind5 = 0; ind5 < size; ind5++) { + tsi_test_fixture *fixture = ssl_tsi_test_fixture_create(); + ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture; + tsi_test_frame_protector_config_set_buffer_size( + ssl_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2], + odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]); + tsi_test_do_round_trip(&ssl_fixture->base); + tsi_test_fixture_destroy(fixture); + } + } + } + } + } +} + +static const tsi_ssl_handshaker_factory_vtable *original_vtable; +static bool handshaker_factory_destructor_called; + +static void ssl_tsi_test_handshaker_factory_destructor( + tsi_ssl_handshaker_factory *factory) { + GPR_ASSERT(factory != NULL); + handshaker_factory_destructor_called = true; + if (original_vtable != NULL && original_vtable->destroy != NULL) { + original_vtable->destroy(factory); + } +} + +static tsi_ssl_handshaker_factory_vtable test_handshaker_factory_vtable = { + ssl_tsi_test_handshaker_factory_destructor}; + +void test_tsi_ssl_client_handshaker_factory_refcounting() { + int i; + const char *cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem"); + + tsi_ssl_client_handshaker_factory *client_handshaker_factory; + GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( + NULL, cert_chain, NULL, NULL, 0, &client_handshaker_factory) == + TSI_OK); + + handshaker_factory_destructor_called = false; + original_vtable = tsi_ssl_handshaker_factory_swap_vtable( + (tsi_ssl_handshaker_factory *)client_handshaker_factory, + &test_handshaker_factory_vtable); + + tsi_handshaker *handshaker[3]; + + for (i = 0; i < 3; ++i) { + GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker( + client_handshaker_factory, "google.com", &handshaker[i]) == + TSI_OK); + } + + tsi_handshaker_destroy(handshaker[1]); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_handshaker_destroy(handshaker[0]); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_handshaker_destroy(handshaker[2]); + GPR_ASSERT(handshaker_factory_destructor_called); + + gpr_free((void *)cert_chain); +} + +void test_tsi_ssl_server_handshaker_factory_refcounting() { + int i; + tsi_ssl_server_handshaker_factory *server_handshaker_factory; + tsi_handshaker *handshaker[3]; + const char *cert_chain = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem"); + tsi_ssl_pem_key_cert_pair cert_pair; + + cert_pair.cert_chain = cert_chain; + cert_pair.private_key = + load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key"); + + GPR_ASSERT(tsi_create_ssl_server_handshaker_factory( + &cert_pair, 1, cert_chain, 0, NULL, NULL, 0, + &server_handshaker_factory) == TSI_OK); + + handshaker_factory_destructor_called = false; + original_vtable = tsi_ssl_handshaker_factory_swap_vtable( + (tsi_ssl_handshaker_factory *)server_handshaker_factory, + &test_handshaker_factory_vtable); + + for (i = 0; i < 3; ++i) { + GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker( + server_handshaker_factory, &handshaker[i]) == TSI_OK); + } + + tsi_handshaker_destroy(handshaker[1]); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_handshaker_destroy(handshaker[0]); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory); + GPR_ASSERT(!handshaker_factory_destructor_called); + + tsi_handshaker_destroy(handshaker[2]); + GPR_ASSERT(handshaker_factory_destructor_called); + + ssl_test_pem_key_cert_pair_destroy(cert_pair); +} + +/* Attempting to create a handshaker factory with invalid parameters should fail + * but not crash. */ +void test_tsi_ssl_client_handshaker_factory_bad_params() { + const char *cert_chain = "This is not a valid PEM file."; + + tsi_ssl_client_handshaker_factory *client_handshaker_factory; + GPR_ASSERT(tsi_create_ssl_client_handshaker_factory( + NULL, cert_chain, NULL, NULL, 0, &client_handshaker_factory) == + TSI_INVALID_ARGUMENT); + tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory); +} + +void ssl_tsi_test_handshaker_factory_internals() { + test_tsi_ssl_client_handshaker_factory_refcounting(); + test_tsi_ssl_server_handshaker_factory_refcounting(); + test_tsi_ssl_client_handshaker_factory_bad_params(); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + ssl_tsi_test_do_handshake_tiny_handshake_buffer(); + ssl_tsi_test_do_handshake_small_handshake_buffer(); + ssl_tsi_test_do_handshake(); + ssl_tsi_test_do_handshake_with_client_authentication(); + ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain(); + ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain(); + ssl_tsi_test_do_handshake_with_bad_server_cert(); + ssl_tsi_test_do_handshake_with_bad_client_cert(); + ssl_tsi_test_do_handshake_alpn_client_no_server(); + ssl_tsi_test_do_handshake_alpn_server_no_client(); + ssl_tsi_test_do_handshake_alpn_client_server_mismatch(); + ssl_tsi_test_do_handshake_alpn_client_server_ok(); + ssl_tsi_test_do_round_trip_for_all_configs(); + ssl_tsi_test_do_round_trip_odd_buffer_size(); + ssl_tsi_test_handshaker_factory_internals(); + grpc_shutdown(); + return 0; +} diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c deleted file mode 100644 index 27932a8169..0000000000 --- a/test/core/tsi/transport_security_test.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/tsi/transport_security.h" - -#include - -#include -#include -#include -#include - -#include - -#include "src/core/lib/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" - -typedef struct { - /* 1 if success, 0 if failure. */ - int expected; - - /* Host name to match. */ - const char *host_name; - - /* Common name (CN). */ - const char *common_name; - - /* Comma separated list of certificate names to match against. Any occurrence - of '#' will be replaced with a null character before processing. */ - const char *dns_names; - - /* Comma separated list of IP SANs to match aggainst */ - const char *ip_names; -} cert_name_test_entry; - -/* Largely inspired from: - chromium/src/net/cert/x509_certificate_unittest.cc. - TODO(jboeuf) uncomment test cases as we fix tsi_ssl_peer_matches_name. */ -const cert_name_test_entry cert_name_test_entries[] = { - {1, "foo.com", "foo.com", NULL, NULL}, - {1, "f", "f", NULL, NULL}, - {0, "h", "i", NULL, NULL}, - {1, "bar.foo.com", "*.foo.com", NULL, NULL}, - {1, "www.test.fr", "common.name", - "*.test.com,*.test.co.uk,*.test.de,*.test.fr", NULL}, - /* - {1, "wwW.tESt.fr", "common.name", ",*.*,*.test.de,*.test.FR,www"}, - */ - {0, "f.uk", ".uk", NULL, NULL}, - {0, "w.bar.foo.com", "?.bar.foo.com", NULL, NULL}, - {0, "www.foo.com", "(www|ftp).foo.com", NULL, NULL}, - {0, "www.foo.com", "www.foo.com#", NULL, NULL}, /* # = null char. */ - {0, "www.foo.com", "", "www.foo.com#*.foo.com,#,#", NULL}, - {0, "www.house.example", "ww.house.example", NULL, NULL}, - {0, "test.org", "", "www.test.org,*.test.org,*.org", NULL}, - {0, "w.bar.foo.com", "w*.bar.foo.com", NULL, NULL}, - {0, "www.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL}, - {0, "wwww.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL}, - {0, "wwww.bar.foo.com", "w*w.bar.foo.com", NULL, NULL}, - {0, "wwww.bar.foo.com", "w*w.bar.foo.c0m", NULL, NULL}, - {0, "WALLY.bar.foo.com", "wa*.bar.foo.com", NULL, NULL}, - {0, "wally.bar.foo.com", "*Ly.bar.foo.com", NULL, NULL}, - /* - {1, "ww%57.foo.com", "", "www.foo.com"}, - {1, "www&.foo.com", "www%26.foo.com", NULL}, - */ - - /* Common name must not be used if subject alternative name was provided. */ - {0, "www.test.co.jp", "www.test.co.jp", - "*.test.de,*.jp,www.test.co.uk,www.*.co.jp", NULL}, - {0, "www.bar.foo.com", "www.bar.foo.com", - "*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com,", NULL}, - - /* IDN tests */ - {1, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br", NULL, NULL}, - {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL}, - {0, "xn--poema-9qae5a.com.br", "", - "*.xn--poema-9qae5a.com.br," - "xn--poema-*.com.br," - "xn--*-9qae5a.com.br," - "*--poema-9qae5a.com.br", - NULL}, - - /* The following are adapted from the examples quoted from - http://tools.ietf.org/html/rfc6125#section-6.4.3 - (e.g., *.example.com would match foo.example.com but - not bar.foo.example.com or example.com). */ - {1, "foo.example.com", "*.example.com", NULL, NULL}, - {0, "bar.foo.example.com", "*.example.com", NULL, NULL}, - {0, "example.com", "*.example.com", NULL, NULL}, - - /* Partial wildcards are disallowed, though RFC 2818 rules allow them. - That is, forms such as baz*.example.net, *baz.example.net, and - b*z.example.net should NOT match domains. Instead, the wildcard must - always be the left-most label, and only a single label. */ - {0, "baz1.example.net", "baz*.example.net", NULL, NULL}, - {0, "foobaz.example.net", "*baz.example.net", NULL, NULL}, - {0, "buzz.example.net", "b*z.example.net", NULL, NULL}, - {0, "www.test.example.net", "www.*.example.net", NULL, NULL}, - - /* Wildcards should not be valid for public registry controlled domains, - and unknown/unrecognized domains, at least three domain components must - be present. */ - {1, "www.test.example", "*.test.example", NULL, NULL}, - {1, "test.example.co.uk", "*.example.co.uk", NULL, NULL}, - {0, "test.example", "*.example", NULL, NULL}, - /* - {0, "example.co.uk", "*.co.uk", NULL}, - */ - {0, "foo.com", "*.com", NULL, NULL}, - {0, "foo.us", "*.us", NULL, NULL}, - {0, "foo", "*", NULL, NULL}, - - /* IDN variants of wildcards and registry controlled domains. */ - {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL}, - {1, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h", NULL, NULL}, - /* - {0, "xn--poema-9qae5a.com.br", "*.com.br", NULL}, - */ - {0, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h", NULL, NULL}, - - /* Wildcards should be permissible for 'private' registry controlled - domains. */ - {1, "www.appspot.com", "*.appspot.com", NULL, NULL}, - {1, "foo.s3.amazonaws.com", "*.s3.amazonaws.com", NULL, NULL}, - - /* Multiple wildcards are not valid. */ - {0, "foo.example.com", "*.*.com", NULL, NULL}, - {0, "foo.bar.example.com", "*.bar.*.com", NULL, NULL}, - - /* Absolute vs relative DNS name tests. Although not explicitly specified - in RFC 6125, absolute reference names (those ending in a .) should - match either absolute or relative presented names. */ - {1, "foo.com", "foo.com.", NULL, NULL}, - {1, "foo.com.", "foo.com", NULL, NULL}, - {1, "foo.com.", "foo.com.", NULL, NULL}, - {1, "f", "f.", NULL, NULL}, - {1, "f.", "f", NULL, NULL}, - {1, "f.", "f.", NULL, NULL}, - {1, "www-3.bar.foo.com", "*.bar.foo.com.", NULL, NULL}, - {1, "www-3.bar.foo.com.", "*.bar.foo.com", NULL, NULL}, - {1, "www-3.bar.foo.com.", "*.bar.foo.com.", NULL, NULL}, - {0, ".", ".", NULL, NULL}, - {0, "example.com", "*.com.", NULL, NULL}, - {0, "example.com.", "*.com", NULL, NULL}, - {0, "example.com.", "*.com.", NULL, NULL}, - {0, "foo.", "*.", NULL, NULL}, - {0, "foo", "*.", NULL, NULL}, - /* - {0, "foo.co.uk", "*.co.uk.", NULL}, - {0, "foo.co.uk.", "*.co.uk.", NULL}, - */ - - /* An empty CN is OK. */ - {1, "test.foo.com", "", "test.foo.com", NULL}, - - /* An IP should not be used for the CN. */ - {0, "173.194.195.139", "173.194.195.139", NULL, NULL}, - /* An IP can be used if the SAN IP is present */ - {1, "173.194.195.139", "foo.example.com", NULL, "173.194.195.139"}, - {0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8"}, - {0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,8.8.4.4"}, - {1, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,173.194.195.139"}, - {0, "173.194.195.139", "foo.example.com", NULL, "173.194.195.13"}, - {0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, "173.194.195.13"}, - {1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, - "2001:db8:a0b:12f0::1"}, - {0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, - "2001:db8:a0b:12f0::2"}, - {1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, - "2001:db8:a0b:12f0::2,2001:db8:a0b:12f0::1,8.8.8.8"}, -}; - -typedef struct name_list { - const char *name; - struct name_list *next; -} name_list; - -typedef struct { - size_t name_count; - char *buffer; - name_list *names; -} parsed_names; - -name_list *name_list_add(const char *n) { - name_list *result = gpr_malloc(sizeof(name_list)); - result->name = n; - result->next = NULL; - return result; -} - -static parsed_names parse_names(const char *names_str) { - parsed_names result; - name_list *current_nl; - size_t i; - memset(&result, 0, sizeof(parsed_names)); - if (names_str == 0) return result; - result.name_count = 1; - result.buffer = gpr_strdup(names_str); - result.names = name_list_add(result.buffer); - current_nl = result.names; - for (i = 0; i < strlen(names_str); i++) { - if (names_str[i] == ',') { - result.buffer[i] = '\0'; - result.name_count++; - i++; - current_nl->next = name_list_add(result.buffer + i); - current_nl = current_nl->next; - } - } - return result; -} - -static void destruct_parsed_names(parsed_names *pdn) { - name_list *nl = pdn->names; - if (pdn->buffer != NULL) gpr_free(pdn->buffer); - while (nl != NULL) { - name_list *to_be_free = nl; - nl = nl->next; - gpr_free(to_be_free); - } -} - -static char *processed_name(const char *name) { - char *result = gpr_strdup(name); - size_t i; - for (i = 0; i < strlen(result); i++) { - if (result[i] == '#') { - result[i] = '\0'; - } - } - return result; -} - -static tsi_peer peer_from_cert_name_test_entry( - const cert_name_test_entry *entry) { - size_t i; - tsi_peer peer; - name_list *nl; - parsed_names dns_entries = parse_names(entry->dns_names); - parsed_names ip_entries = parse_names(entry->ip_names); - nl = dns_entries.names; - GPR_ASSERT(tsi_construct_peer( - 1 + dns_entries.name_count + ip_entries.name_count, &peer) == - TSI_OK); - GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, entry->common_name, - &peer.properties[0]) == TSI_OK); - i = 1; - while (nl != NULL) { - char *processed = processed_name(nl->name); - GPR_ASSERT(tsi_construct_string_peer_property( - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed, - strlen(nl->name), &peer.properties[i++]) == TSI_OK); - nl = nl->next; - gpr_free(processed); - } - - nl = ip_entries.names; - while (nl != NULL) { - char *processed = processed_name(nl->name); - GPR_ASSERT(tsi_construct_string_peer_property( - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed, - strlen(nl->name), &peer.properties[i++]) == TSI_OK); - nl = nl->next; - gpr_free(processed); - } - destruct_parsed_names(&dns_entries); - destruct_parsed_names(&ip_entries); - return peer; -} - -char *cert_name_test_entry_to_string(const cert_name_test_entry *entry) { - char *s; - gpr_asprintf(&s, - "{ success = %s, host_name = %s, common_name = %s, dns_names = " - "%s, ip_names = %s}", - entry->expected ? "true" : "false", entry->host_name, - entry->common_name, - entry->dns_names != NULL ? entry->dns_names : "", - entry->ip_names != NULL ? entry->ip_names : ""); - return s; -} - -static void test_peer_matches_name(void) { - size_t i = 0; - for (i = 0; i < GPR_ARRAY_SIZE(cert_name_test_entries); i++) { - const cert_name_test_entry *entry = &cert_name_test_entries[i]; - tsi_peer peer = peer_from_cert_name_test_entry(entry); - int result = tsi_ssl_peer_matches_name(&peer, entry->host_name); - if (result != entry->expected) { - char *entry_str = cert_name_test_entry_to_string(entry); - gpr_log(GPR_ERROR, "%s", entry_str); - gpr_free(entry_str); - GPR_ASSERT(0); /* Unexpected result. */ - } - tsi_peer_destruct(&peer); - } -} - -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); - GPR_ASSERT(tsi_handshaker_next(NULL, NULL, 0, NULL, NULL, 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/tsi/transport_security_test.cc b/test/core/tsi/transport_security_test.cc new file mode 100644 index 0000000000..c1be1e952d --- /dev/null +++ b/test/core/tsi/transport_security_test.cc @@ -0,0 +1,386 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/tsi/transport_security.h" + +#include + +#include +#include +#include +#include + +#include + +#include "src/core/lib/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" + +typedef struct { + /* 1 if success, 0 if failure. */ + int expected; + + /* Host name to match. */ + const char *host_name; + + /* Common name (CN). */ + const char *common_name; + + /* Comma separated list of certificate names to match against. Any occurrence + of '#' will be replaced with a null character before processing. */ + const char *dns_names; + + /* Comma separated list of IP SANs to match aggainst */ + const char *ip_names; +} cert_name_test_entry; + +/* Largely inspired from: + chromium/src/net/cert/x509_certificate_unittest.cc. + TODO(jboeuf) uncomment test cases as we fix tsi_ssl_peer_matches_name. */ +const cert_name_test_entry cert_name_test_entries[] = { + {1, "foo.com", "foo.com", NULL, NULL}, + {1, "f", "f", NULL, NULL}, + {0, "h", "i", NULL, NULL}, + {1, "bar.foo.com", "*.foo.com", NULL, NULL}, + {1, "www.test.fr", "common.name", + "*.test.com,*.test.co.uk,*.test.de,*.test.fr", NULL}, + /* + {1, "wwW.tESt.fr", "common.name", ",*.*,*.test.de,*.test.FR,www"}, + */ + {0, "f.uk", ".uk", NULL, NULL}, + {0, "w.bar.foo.com", "?.bar.foo.com", NULL, NULL}, + {0, "www.foo.com", "(www|ftp).foo.com", NULL, NULL}, + {0, "www.foo.com", "www.foo.com#", NULL, NULL}, /* # = null char. */ + {0, "www.foo.com", "", "www.foo.com#*.foo.com,#,#", NULL}, + {0, "www.house.example", "ww.house.example", NULL, NULL}, + {0, "test.org", "", "www.test.org,*.test.org,*.org", NULL}, + {0, "w.bar.foo.com", "w*.bar.foo.com", NULL, NULL}, + {0, "www.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL}, + {0, "wwww.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL}, + {0, "wwww.bar.foo.com", "w*w.bar.foo.com", NULL, NULL}, + {0, "wwww.bar.foo.com", "w*w.bar.foo.c0m", NULL, NULL}, + {0, "WALLY.bar.foo.com", "wa*.bar.foo.com", NULL, NULL}, + {0, "wally.bar.foo.com", "*Ly.bar.foo.com", NULL, NULL}, + /* + {1, "ww%57.foo.com", "", "www.foo.com"}, + {1, "www&.foo.com", "www%26.foo.com", NULL}, + */ + + /* Common name must not be used if subject alternative name was provided. */ + {0, "www.test.co.jp", "www.test.co.jp", + "*.test.de,*.jp,www.test.co.uk,www.*.co.jp", NULL}, + {0, "www.bar.foo.com", "www.bar.foo.com", + "*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com,", NULL}, + + /* IDN tests */ + {1, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br", NULL, NULL}, + {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL}, + {0, "xn--poema-9qae5a.com.br", "", + "*.xn--poema-9qae5a.com.br," + "xn--poema-*.com.br," + "xn--*-9qae5a.com.br," + "*--poema-9qae5a.com.br", + NULL}, + + /* The following are adapted from the examples quoted from + http://tools.ietf.org/html/rfc6125#section-6.4.3 + (e.g., *.example.com would match foo.example.com but + not bar.foo.example.com or example.com). */ + {1, "foo.example.com", "*.example.com", NULL, NULL}, + {0, "bar.foo.example.com", "*.example.com", NULL, NULL}, + {0, "example.com", "*.example.com", NULL, NULL}, + + /* Partial wildcards are disallowed, though RFC 2818 rules allow them. + That is, forms such as baz*.example.net, *baz.example.net, and + b*z.example.net should NOT match domains. Instead, the wildcard must + always be the left-most label, and only a single label. */ + {0, "baz1.example.net", "baz*.example.net", NULL, NULL}, + {0, "foobaz.example.net", "*baz.example.net", NULL, NULL}, + {0, "buzz.example.net", "b*z.example.net", NULL, NULL}, + {0, "www.test.example.net", "www.*.example.net", NULL, NULL}, + + /* Wildcards should not be valid for public registry controlled domains, + and unknown/unrecognized domains, at least three domain components must + be present. */ + {1, "www.test.example", "*.test.example", NULL, NULL}, + {1, "test.example.co.uk", "*.example.co.uk", NULL, NULL}, + {0, "test.example", "*.example", NULL, NULL}, + /* + {0, "example.co.uk", "*.co.uk", NULL}, + */ + {0, "foo.com", "*.com", NULL, NULL}, + {0, "foo.us", "*.us", NULL, NULL}, + {0, "foo", "*", NULL, NULL}, + + /* IDN variants of wildcards and registry controlled domains. */ + {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL}, + {1, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h", NULL, NULL}, + /* + {0, "xn--poema-9qae5a.com.br", "*.com.br", NULL}, + */ + {0, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h", NULL, NULL}, + + /* Wildcards should be permissible for 'private' registry controlled + domains. */ + {1, "www.appspot.com", "*.appspot.com", NULL, NULL}, + {1, "foo.s3.amazonaws.com", "*.s3.amazonaws.com", NULL, NULL}, + + /* Multiple wildcards are not valid. */ + {0, "foo.example.com", "*.*.com", NULL, NULL}, + {0, "foo.bar.example.com", "*.bar.*.com", NULL, NULL}, + + /* Absolute vs relative DNS name tests. Although not explicitly specified + in RFC 6125, absolute reference names (those ending in a .) should + match either absolute or relative presented names. */ + {1, "foo.com", "foo.com.", NULL, NULL}, + {1, "foo.com.", "foo.com", NULL, NULL}, + {1, "foo.com.", "foo.com.", NULL, NULL}, + {1, "f", "f.", NULL, NULL}, + {1, "f.", "f", NULL, NULL}, + {1, "f.", "f.", NULL, NULL}, + {1, "www-3.bar.foo.com", "*.bar.foo.com.", NULL, NULL}, + {1, "www-3.bar.foo.com.", "*.bar.foo.com", NULL, NULL}, + {1, "www-3.bar.foo.com.", "*.bar.foo.com.", NULL, NULL}, + {0, ".", ".", NULL, NULL}, + {0, "example.com", "*.com.", NULL, NULL}, + {0, "example.com.", "*.com", NULL, NULL}, + {0, "example.com.", "*.com.", NULL, NULL}, + {0, "foo.", "*.", NULL, NULL}, + {0, "foo", "*.", NULL, NULL}, + /* + {0, "foo.co.uk", "*.co.uk.", NULL}, + {0, "foo.co.uk.", "*.co.uk.", NULL}, + */ + + /* An empty CN is OK. */ + {1, "test.foo.com", "", "test.foo.com", NULL}, + + /* An IP should not be used for the CN. */ + {0, "173.194.195.139", "173.194.195.139", NULL, NULL}, + /* An IP can be used if the SAN IP is present */ + {1, "173.194.195.139", "foo.example.com", NULL, "173.194.195.139"}, + {0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8"}, + {0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,8.8.4.4"}, + {1, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,173.194.195.139"}, + {0, "173.194.195.139", "foo.example.com", NULL, "173.194.195.13"}, + {0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, "173.194.195.13"}, + {1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, + "2001:db8:a0b:12f0::1"}, + {0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, + "2001:db8:a0b:12f0::2"}, + {1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, + "2001:db8:a0b:12f0::2,2001:db8:a0b:12f0::1,8.8.8.8"}, +}; + +typedef struct name_list { + const char *name; + struct name_list *next; +} name_list; + +typedef struct { + size_t name_count; + char *buffer; + name_list *names; +} parsed_names; + +name_list *name_list_add(const char *n) { + name_list *result = static_cast(gpr_malloc(sizeof(name_list))); + result->name = n; + result->next = NULL; + return result; +} + +static parsed_names parse_names(const char *names_str) { + parsed_names result; + name_list *current_nl; + size_t i; + memset(&result, 0, sizeof(parsed_names)); + if (names_str == 0) return result; + result.name_count = 1; + result.buffer = gpr_strdup(names_str); + result.names = name_list_add(result.buffer); + current_nl = result.names; + for (i = 0; i < strlen(names_str); i++) { + if (names_str[i] == ',') { + result.buffer[i] = '\0'; + result.name_count++; + i++; + current_nl->next = name_list_add(result.buffer + i); + current_nl = current_nl->next; + } + } + return result; +} + +static void destruct_parsed_names(parsed_names *pdn) { + name_list *nl = pdn->names; + if (pdn->buffer != NULL) gpr_free(pdn->buffer); + while (nl != NULL) { + name_list *to_be_free = nl; + nl = nl->next; + gpr_free(to_be_free); + } +} + +static char *processed_name(const char *name) { + char *result = gpr_strdup(name); + size_t i; + for (i = 0; i < strlen(result); i++) { + if (result[i] == '#') { + result[i] = '\0'; + } + } + return result; +} + +static tsi_peer peer_from_cert_name_test_entry( + const cert_name_test_entry *entry) { + size_t i; + tsi_peer peer; + name_list *nl; + parsed_names dns_entries = parse_names(entry->dns_names); + parsed_names ip_entries = parse_names(entry->ip_names); + nl = dns_entries.names; + GPR_ASSERT(tsi_construct_peer( + 1 + dns_entries.name_count + ip_entries.name_count, &peer) == + TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, entry->common_name, + &peer.properties[0]) == TSI_OK); + i = 1; + while (nl != NULL) { + char *processed = processed_name(nl->name); + GPR_ASSERT(tsi_construct_string_peer_property( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed, + strlen(nl->name), &peer.properties[i++]) == TSI_OK); + nl = nl->next; + gpr_free(processed); + } + + nl = ip_entries.names; + while (nl != NULL) { + char *processed = processed_name(nl->name); + GPR_ASSERT(tsi_construct_string_peer_property( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed, + strlen(nl->name), &peer.properties[i++]) == TSI_OK); + nl = nl->next; + gpr_free(processed); + } + destruct_parsed_names(&dns_entries); + destruct_parsed_names(&ip_entries); + return peer; +} + +char *cert_name_test_entry_to_string(const cert_name_test_entry *entry) { + char *s; + gpr_asprintf(&s, + "{ success = %s, host_name = %s, common_name = %s, dns_names = " + "%s, ip_names = %s}", + entry->expected ? "true" : "false", entry->host_name, + entry->common_name, + entry->dns_names != NULL ? entry->dns_names : "", + entry->ip_names != NULL ? entry->ip_names : ""); + return s; +} + +static void test_peer_matches_name(void) { + size_t i = 0; + for (i = 0; i < GPR_ARRAY_SIZE(cert_name_test_entries); i++) { + const cert_name_test_entry *entry = &cert_name_test_entries[i]; + tsi_peer peer = peer_from_cert_name_test_entry(entry); + int result = tsi_ssl_peer_matches_name(&peer, entry->host_name); + if (result != entry->expected) { + char *entry_str = cert_name_test_entry_to_string(entry); + gpr_log(GPR_ERROR, "%s", entry_str); + gpr_free(entry_str); + GPR_ASSERT(0); /* Unexpected result. */ + } + tsi_peer_destruct(&peer); + } +} + +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); + GPR_ASSERT(tsi_handshaker_next(NULL, NULL, 0, NULL, NULL, 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/tsi/transport_security_test_lib.c b/test/core/tsi/transport_security_test_lib.c deleted file mode 100644 index 329b2371bf..0000000000 --- a/test/core/tsi/transport_security_test_lib.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/security/transport/tsi_error.h" -#include "test/core/tsi/transport_security_test_lib.h" - -static void notification_signal(tsi_test_fixture *fixture) { - gpr_mu_lock(&fixture->mu); - fixture->notified = true; - gpr_cv_signal(&fixture->cv); - gpr_mu_unlock(&fixture->mu); -} - -static void notification_wait(tsi_test_fixture *fixture) { - gpr_mu_lock(&fixture->mu); - while (!fixture->notified) { - gpr_cv_wait(&fixture->cv, &fixture->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - fixture->notified = false; - gpr_mu_unlock(&fixture->mu); -} - -typedef struct handshaker_args { - tsi_test_fixture *fixture; - unsigned char *handshake_buffer; - size_t handshake_buffer_size; - bool is_client; - bool transferred_data; - bool appended_unused_bytes; - grpc_error *error; -} handshaker_args; - -static handshaker_args *handshaker_args_create(tsi_test_fixture *fixture, - bool is_client) { - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(fixture->config != NULL); - handshaker_args *args = gpr_zalloc(sizeof(*args)); - args->fixture = fixture; - args->handshake_buffer_size = fixture->handshake_buffer_size; - args->handshake_buffer = gpr_zalloc(args->handshake_buffer_size); - args->is_client = is_client; - args->error = GRPC_ERROR_NONE; - return args; -} - -static void handshaker_args_destroy(handshaker_args *args) { - gpr_free(args->handshake_buffer); - GRPC_ERROR_UNREF(args->error); - gpr_free(args); -} - -static void do_handshaker_next(handshaker_args *args); - -static void setup_handshakers(tsi_test_fixture *fixture) { - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(fixture->vtable != NULL); - GPR_ASSERT(fixture->vtable->setup_handshakers != NULL); - fixture->vtable->setup_handshakers(fixture); -} - -static void check_unused_bytes(tsi_test_fixture *fixture) { - tsi_handshaker_result *result_with_unused_bytes = - fixture->has_client_finished_first ? fixture->server_result - : fixture->client_result; - tsi_handshaker_result *result_without_unused_bytes = - fixture->has_client_finished_first ? fixture->client_result - : fixture->server_result; - const unsigned char *bytes = NULL; - size_t bytes_size = 0; - GPR_ASSERT(tsi_handshaker_result_get_unused_bytes( - result_with_unused_bytes, &bytes, &bytes_size) == TSI_OK); - GPR_ASSERT(bytes_size == strlen(TSI_TEST_UNUSED_BYTES)); - GPR_ASSERT(memcmp(bytes, TSI_TEST_UNUSED_BYTES, bytes_size) == 0); - GPR_ASSERT(tsi_handshaker_result_get_unused_bytes( - result_without_unused_bytes, &bytes, &bytes_size) == TSI_OK); - GPR_ASSERT(bytes_size == 0); - GPR_ASSERT(bytes == NULL); -} - -static void check_handshake_results(tsi_test_fixture *fixture) { - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(fixture->vtable != NULL); - GPR_ASSERT(fixture->vtable->check_handshaker_peers != NULL); - /* Check handshaker peers. */ - fixture->vtable->check_handshaker_peers(fixture); - /* Check unused bytes. */ - if (fixture->test_unused_bytes) { - if (fixture->server_result != NULL && fixture->client_result != NULL) { - check_unused_bytes(fixture); - } - fixture->bytes_written_to_server_channel = 0; - fixture->bytes_written_to_client_channel = 0; - fixture->bytes_read_from_client_channel = 0; - fixture->bytes_read_from_server_channel = 0; - } -} - -static void send_bytes_to_peer(tsi_test_fixture *fixture, - const unsigned char *buf, size_t buf_size, - bool is_client) { - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(buf != NULL); - uint8_t *channel = - is_client ? fixture->server_channel : fixture->client_channel; - GPR_ASSERT(channel != NULL); - size_t *bytes_written = is_client ? &fixture->bytes_written_to_server_channel - : &fixture->bytes_written_to_client_channel; - GPR_ASSERT(bytes_written != NULL); - GPR_ASSERT(*bytes_written + buf_size <= TSI_TEST_DEFAULT_CHANNEL_SIZE); - /* Write data to channel. */ - memcpy(channel + *bytes_written, buf, buf_size); - *bytes_written += buf_size; -} - -static void maybe_append_unused_bytes(handshaker_args *args) { - GPR_ASSERT(args != NULL); - GPR_ASSERT(args->fixture != NULL); - tsi_test_fixture *fixture = args->fixture; - if (fixture->test_unused_bytes && !args->appended_unused_bytes) { - args->appended_unused_bytes = true; - send_bytes_to_peer(fixture, (const unsigned char *)TSI_TEST_UNUSED_BYTES, - strlen(TSI_TEST_UNUSED_BYTES), args->is_client); - if (fixture->client_result != NULL && fixture->server_result == NULL) { - fixture->has_client_finished_first = true; - } - } -} - -static void receive_bytes_from_peer(tsi_test_fixture *fixture, - unsigned char **buf, size_t *buf_size, - bool is_client) { - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(*buf != NULL); - GPR_ASSERT(buf_size != NULL); - uint8_t *channel = - is_client ? fixture->client_channel : fixture->server_channel; - GPR_ASSERT(channel != NULL); - size_t *bytes_read = is_client ? &fixture->bytes_read_from_client_channel - : &fixture->bytes_read_from_server_channel; - size_t *bytes_written = is_client ? &fixture->bytes_written_to_client_channel - : &fixture->bytes_written_to_server_channel; - GPR_ASSERT(bytes_read != NULL); - GPR_ASSERT(bytes_written != NULL); - size_t to_read = *buf_size < *bytes_written - *bytes_read - ? *buf_size - : *bytes_written - *bytes_read; - /* Read data from channel. */ - memcpy(*buf, channel + *bytes_read, to_read); - *buf_size = to_read; - *bytes_read += to_read; -} - -static void send_message_to_peer(tsi_test_fixture *fixture, - tsi_frame_protector *protector, - bool is_client) { - /* Initialization. */ - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(fixture->config != NULL); - GPR_ASSERT(protector != NULL); - tsi_test_frame_protector_config *config = fixture->config; - unsigned char *protected_buffer = gpr_zalloc(config->protected_buffer_size); - size_t message_size = - is_client ? config->client_message_size : config->server_message_size; - uint8_t *message = - is_client ? config->client_message : config->server_message; - GPR_ASSERT(message != NULL); - const unsigned char *message_bytes = (const unsigned char *)message; - tsi_result result = TSI_OK; - /* Do protect and send protected data to peer. */ - while (message_size > 0 && result == TSI_OK) { - size_t protected_buffer_size_to_send = config->protected_buffer_size; - size_t processed_message_size = message_size; - /* Do protect. */ - result = tsi_frame_protector_protect( - protector, message_bytes, &processed_message_size, protected_buffer, - &protected_buffer_size_to_send); - GPR_ASSERT(result == TSI_OK); - /* Send protected data to peer. */ - send_bytes_to_peer(fixture, protected_buffer, protected_buffer_size_to_send, - is_client); - message_bytes += processed_message_size; - message_size -= processed_message_size; - /* Flush if we're done. */ - if (message_size == 0) { - size_t still_pending_size; - do { - protected_buffer_size_to_send = config->protected_buffer_size; - result = tsi_frame_protector_protect_flush( - protector, protected_buffer, &protected_buffer_size_to_send, - &still_pending_size); - GPR_ASSERT(result == TSI_OK); - send_bytes_to_peer(fixture, protected_buffer, - protected_buffer_size_to_send, is_client); - } while (still_pending_size > 0 && result == TSI_OK); - GPR_ASSERT(result == TSI_OK); - } - } - GPR_ASSERT(result == TSI_OK); - gpr_free(protected_buffer); -} - -static void receive_message_from_peer(tsi_test_fixture *fixture, - tsi_frame_protector *protector, - unsigned char *message, - size_t *bytes_received, bool is_client) { - /* Initialization. */ - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(protector != NULL); - GPR_ASSERT(message != NULL); - GPR_ASSERT(bytes_received != NULL); - GPR_ASSERT(fixture->config != NULL); - tsi_test_frame_protector_config *config = fixture->config; - size_t read_offset = 0; - size_t message_offset = 0; - size_t read_from_peer_size = 0; - tsi_result result = TSI_OK; - bool done = false; - unsigned char *read_buffer = gpr_zalloc(config->read_buffer_allocated_size); - unsigned char *message_buffer = - gpr_zalloc(config->message_buffer_allocated_size); - /* Do unprotect on data received from peer. */ - while (!done && result == TSI_OK) { - /* Receive data from peer. */ - if (read_from_peer_size == 0) { - read_from_peer_size = config->read_buffer_allocated_size; - receive_bytes_from_peer(fixture, &read_buffer, &read_from_peer_size, - is_client); - read_offset = 0; - } - if (read_from_peer_size == 0) { - done = true; - } - /* Do unprotect. */ - size_t message_buffer_size; - do { - message_buffer_size = config->message_buffer_allocated_size; - size_t processed_size = read_from_peer_size; - result = tsi_frame_protector_unprotect( - protector, read_buffer + read_offset, &processed_size, message_buffer, - &message_buffer_size); - GPR_ASSERT(result == TSI_OK); - if (message_buffer_size > 0) { - memcpy(message + message_offset, message_buffer, message_buffer_size); - message_offset += message_buffer_size; - } - read_offset += processed_size; - read_from_peer_size -= processed_size; - } while ((read_from_peer_size > 0 || message_buffer_size > 0) && - result == TSI_OK); - GPR_ASSERT(result == TSI_OK); - } - GPR_ASSERT(result == TSI_OK); - *bytes_received = message_offset; - gpr_free(read_buffer); - gpr_free(message_buffer); -} - -grpc_error *on_handshake_next_done(tsi_result result, void *user_data, - const unsigned char *bytes_to_send, - size_t bytes_to_send_size, - tsi_handshaker_result *handshaker_result) { - handshaker_args *args = (handshaker_args *)user_data; - GPR_ASSERT(args != NULL); - GPR_ASSERT(args->fixture != NULL); - tsi_test_fixture *fixture = args->fixture; - grpc_error *error = GRPC_ERROR_NONE; - /* Read more data if we need to. */ - if (result == TSI_INCOMPLETE_DATA) { - GPR_ASSERT(bytes_to_send_size == 0); - notification_signal(fixture); - return error; - } - if (result != TSI_OK) { - notification_signal(fixture); - return grpc_set_tsi_error_result( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result); - } - /* Update handshaker result. */ - if (handshaker_result != NULL) { - tsi_handshaker_result **result_to_write = - args->is_client ? &fixture->client_result : &fixture->server_result; - GPR_ASSERT(*result_to_write == NULL); - *result_to_write = handshaker_result; - } - /* Send data to peer, if needed. */ - if (bytes_to_send_size > 0) { - send_bytes_to_peer(args->fixture, bytes_to_send, bytes_to_send_size, - args->is_client); - args->transferred_data = true; - } - if (handshaker_result != NULL) { - maybe_append_unused_bytes(args); - } - notification_signal(fixture); - return error; -} - -static void on_handshake_next_done_wrapper( - tsi_result result, void *user_data, const unsigned char *bytes_to_send, - size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) { - handshaker_args *args = (handshaker_args *)user_data; - args->error = on_handshake_next_done(result, user_data, bytes_to_send, - bytes_to_send_size, handshaker_result); -} - -static bool is_handshake_finished_properly(handshaker_args *args) { - GPR_ASSERT(args != NULL); - GPR_ASSERT(args->fixture != NULL); - tsi_test_fixture *fixture = args->fixture; - if ((args->is_client && fixture->client_result != NULL) || - (!args->is_client && fixture->server_result != NULL)) { - return true; - } - return false; -} - -static void do_handshaker_next(handshaker_args *args) { - /* Initialization. */ - GPR_ASSERT(args != NULL); - GPR_ASSERT(args->fixture != NULL); - tsi_test_fixture *fixture = args->fixture; - tsi_handshaker *handshaker = - args->is_client ? fixture->client_handshaker : fixture->server_handshaker; - if (is_handshake_finished_properly(args)) { - return; - } - tsi_handshaker_result *handshaker_result = NULL; - unsigned char *bytes_to_send = NULL; - size_t bytes_to_send_size = 0; - /* Receive data from peer, if available. */ - size_t buf_size = args->handshake_buffer_size; - receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size, - args->is_client); - if (buf_size > 0) { - args->transferred_data = true; - } - /* Peform handshaker next. */ - tsi_result result = tsi_handshaker_next( - handshaker, args->handshake_buffer, buf_size, - (const unsigned char **)&bytes_to_send, &bytes_to_send_size, - &handshaker_result, &on_handshake_next_done_wrapper, args); - if (result != TSI_ASYNC) { - args->error = on_handshake_next_done(result, args, bytes_to_send, - bytes_to_send_size, handshaker_result); - if (args->error != GRPC_ERROR_NONE) { - return; - } - } - notification_wait(fixture); -} - -void tsi_test_do_handshake(tsi_test_fixture *fixture) { - /* Initializaiton. */ - setup_handshakers(fixture); - handshaker_args *client_args = - handshaker_args_create(fixture, true /* is_client */); - handshaker_args *server_args = - handshaker_args_create(fixture, false /* is_client */); - /* Do handshake. */ - do { - client_args->transferred_data = false; - server_args->transferred_data = false; - do_handshaker_next(client_args); - if (client_args->error != GRPC_ERROR_NONE) { - break; - } - do_handshaker_next(server_args); - if (server_args->error != GRPC_ERROR_NONE) { - break; - } - GPR_ASSERT(client_args->transferred_data || server_args->transferred_data); - } while (fixture->client_result == NULL || fixture->server_result == NULL); - /* Verify handshake results. */ - check_handshake_results(fixture); - /* Cleanup. */ - handshaker_args_destroy(client_args); - handshaker_args_destroy(server_args); -} - -void tsi_test_do_round_trip(tsi_test_fixture *fixture) { - /* Initialization. */ - GPR_ASSERT(fixture != NULL); - GPR_ASSERT(fixture->config != NULL); - tsi_test_frame_protector_config *config = fixture->config; - tsi_frame_protector *client_frame_protector = NULL; - tsi_frame_protector *server_frame_protector = NULL; - /* Perform handshake. */ - tsi_test_do_handshake(fixture); - /* Create frame protectors.*/ - size_t client_max_output_protected_frame_size = - config->client_max_output_protected_frame_size; - GPR_ASSERT(tsi_handshaker_result_create_frame_protector( - fixture->client_result, - client_max_output_protected_frame_size == 0 - ? NULL - : &client_max_output_protected_frame_size, - &client_frame_protector) == TSI_OK); - size_t server_max_output_protected_frame_size = - config->server_max_output_protected_frame_size; - GPR_ASSERT(tsi_handshaker_result_create_frame_protector( - fixture->server_result, - server_max_output_protected_frame_size == 0 - ? NULL - : &server_max_output_protected_frame_size, - &server_frame_protector) == TSI_OK); - /* Client sends a message to server. */ - send_message_to_peer(fixture, client_frame_protector, true /* is_client */); - unsigned char *server_received_message = - gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE); - size_t server_received_message_size = 0; - receive_message_from_peer( - fixture, server_frame_protector, server_received_message, - &server_received_message_size, false /* is_client */); - GPR_ASSERT(config->client_message_size == server_received_message_size); - GPR_ASSERT(memcmp(config->client_message, server_received_message, - server_received_message_size) == 0); - /* Server sends a message to client. */ - send_message_to_peer(fixture, server_frame_protector, false /* is_client */); - unsigned char *client_received_message = - gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE); - size_t client_received_message_size = 0; - receive_message_from_peer( - fixture, client_frame_protector, client_received_message, - &client_received_message_size, true /* is_client */); - GPR_ASSERT(config->server_message_size == client_received_message_size); - GPR_ASSERT(memcmp(config->server_message, client_received_message, - client_received_message_size) == 0); - /* Destroy server and client frame protectors. */ - tsi_frame_protector_destroy(client_frame_protector); - tsi_frame_protector_destroy(server_frame_protector); - gpr_free(server_received_message); - gpr_free(client_received_message); -} - -static unsigned char *generate_random_message(size_t size) { - size_t i; - unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - unsigned char *output = gpr_zalloc(sizeof(unsigned char) * size); - for (i = 0; i < size - 1; ++i) { - output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; - } - return output; -} - -tsi_test_frame_protector_config *tsi_test_frame_protector_config_create( - bool use_default_read_buffer_allocated_size, - bool use_default_message_buffer_allocated_size, - bool use_default_protected_buffer_size, bool use_default_client_message, - bool use_default_server_message, - bool use_default_client_max_output_protected_frame_size, - bool use_default_server_max_output_protected_frame_size, - bool use_default_handshake_buffer_size) { - tsi_test_frame_protector_config *config = gpr_zalloc(sizeof(*config)); - /* Set the value for read_buffer_allocated_size. */ - config->read_buffer_allocated_size = - use_default_read_buffer_allocated_size - ? TSI_TEST_DEFAULT_BUFFER_SIZE - : TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE; - /* Set the value for message_buffer_allocated_size. */ - config->message_buffer_allocated_size = - use_default_message_buffer_allocated_size - ? TSI_TEST_DEFAULT_BUFFER_SIZE - : TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE; - /* Set the value for protected_buffer_size. */ - config->protected_buffer_size = use_default_protected_buffer_size - ? TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE - : TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE; - /* Set the value for client message. */ - config->client_message_size = use_default_client_message - ? TSI_TEST_BIG_MESSAGE_SIZE - : TSI_TEST_SMALL_MESSAGE_SIZE; - config->client_message = - use_default_client_message - ? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE) - : generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE); - /* Set the value for server message. */ - config->server_message_size = use_default_server_message - ? TSI_TEST_BIG_MESSAGE_SIZE - : TSI_TEST_SMALL_MESSAGE_SIZE; - config->server_message = - use_default_server_message - ? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE) - : generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE); - /* Set the value for client max_output_protected_frame_size. - If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(), - which then uses default protected frame size for it. */ - config->client_max_output_protected_frame_size = - use_default_client_max_output_protected_frame_size - ? 0 - : TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE; - /* Set the value for server max_output_protected_frame_size. - If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(), - which then uses default protected frame size for it. */ - config->server_max_output_protected_frame_size = - use_default_server_max_output_protected_frame_size - ? 0 - : TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE; - return config; -} - -void tsi_test_frame_protector_config_set_buffer_size( - tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size, - size_t message_buffer_allocated_size, size_t protected_buffer_size, - size_t client_max_output_protected_frame_size, - size_t server_max_output_protected_frame_size) { - GPR_ASSERT(config != NULL); - config->read_buffer_allocated_size = read_buffer_allocated_size; - config->message_buffer_allocated_size = message_buffer_allocated_size; - config->protected_buffer_size = protected_buffer_size; - config->client_max_output_protected_frame_size = - client_max_output_protected_frame_size; - config->server_max_output_protected_frame_size = - server_max_output_protected_frame_size; -} - -void tsi_test_frame_protector_config_destroy( - tsi_test_frame_protector_config *config) { - GPR_ASSERT(config != NULL); - gpr_free(config->client_message); - gpr_free(config->server_message); - gpr_free(config); -} - -void tsi_test_fixture_init(tsi_test_fixture *fixture) { - fixture->config = tsi_test_frame_protector_config_create( - true, true, true, true, true, true, true, true); - fixture->handshake_buffer_size = TSI_TEST_DEFAULT_BUFFER_SIZE; - fixture->client_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE); - fixture->server_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE); - fixture->bytes_written_to_client_channel = 0; - fixture->bytes_written_to_server_channel = 0; - fixture->bytes_read_from_client_channel = 0; - fixture->bytes_read_from_server_channel = 0; - fixture->test_unused_bytes = true; - fixture->has_client_finished_first = false; - gpr_mu_init(&fixture->mu); - gpr_cv_init(&fixture->cv); - fixture->notified = false; -} - -void tsi_test_fixture_destroy(tsi_test_fixture *fixture) { - GPR_ASSERT(fixture != NULL); - tsi_test_frame_protector_config_destroy(fixture->config); - tsi_handshaker_destroy(fixture->client_handshaker); - tsi_handshaker_destroy(fixture->server_handshaker); - tsi_handshaker_result_destroy(fixture->client_result); - tsi_handshaker_result_destroy(fixture->server_result); - gpr_free(fixture->client_channel); - gpr_free(fixture->server_channel); - GPR_ASSERT(fixture->vtable != NULL); - GPR_ASSERT(fixture->vtable->destruct != NULL); - fixture->vtable->destruct(fixture); - gpr_mu_destroy(&fixture->mu); - gpr_cv_destroy(&fixture->cv); - gpr_free(fixture); -} diff --git a/test/core/tsi/transport_security_test_lib.cc b/test/core/tsi/transport_security_test_lib.cc new file mode 100644 index 0000000000..454b79c0cc --- /dev/null +++ b/test/core/tsi/transport_security_test_lib.cc @@ -0,0 +1,588 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/security/transport/tsi_error.h" +#include "test/core/tsi/transport_security_test_lib.h" + +static void notification_signal(tsi_test_fixture *fixture) { + gpr_mu_lock(&fixture->mu); + fixture->notified = true; + gpr_cv_signal(&fixture->cv); + gpr_mu_unlock(&fixture->mu); +} + +static void notification_wait(tsi_test_fixture *fixture) { + gpr_mu_lock(&fixture->mu); + while (!fixture->notified) { + gpr_cv_wait(&fixture->cv, &fixture->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + fixture->notified = false; + gpr_mu_unlock(&fixture->mu); +} + +typedef struct handshaker_args { + tsi_test_fixture *fixture; + unsigned char *handshake_buffer; + size_t handshake_buffer_size; + bool is_client; + bool transferred_data; + bool appended_unused_bytes; + grpc_error *error; +} handshaker_args; + +static handshaker_args *handshaker_args_create(tsi_test_fixture *fixture, + bool is_client) { + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(fixture->config != NULL); + handshaker_args *args = + static_cast(gpr_zalloc(sizeof(*args))); + args->fixture = fixture; + args->handshake_buffer_size = fixture->handshake_buffer_size; + args->handshake_buffer = + static_cast(gpr_zalloc(args->handshake_buffer_size)); + args->is_client = is_client; + args->error = GRPC_ERROR_NONE; + return args; +} + +static void handshaker_args_destroy(handshaker_args *args) { + gpr_free(args->handshake_buffer); + GRPC_ERROR_UNREF(args->error); + gpr_free(args); +} + +static void do_handshaker_next(handshaker_args *args); + +static void setup_handshakers(tsi_test_fixture *fixture) { + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(fixture->vtable != NULL); + GPR_ASSERT(fixture->vtable->setup_handshakers != NULL); + fixture->vtable->setup_handshakers(fixture); +} + +static void check_unused_bytes(tsi_test_fixture *fixture) { + tsi_handshaker_result *result_with_unused_bytes = + fixture->has_client_finished_first ? fixture->server_result + : fixture->client_result; + tsi_handshaker_result *result_without_unused_bytes = + fixture->has_client_finished_first ? fixture->client_result + : fixture->server_result; + const unsigned char *bytes = NULL; + size_t bytes_size = 0; + GPR_ASSERT(tsi_handshaker_result_get_unused_bytes( + result_with_unused_bytes, &bytes, &bytes_size) == TSI_OK); + GPR_ASSERT(bytes_size == strlen(TSI_TEST_UNUSED_BYTES)); + GPR_ASSERT(memcmp(bytes, TSI_TEST_UNUSED_BYTES, bytes_size) == 0); + GPR_ASSERT(tsi_handshaker_result_get_unused_bytes( + result_without_unused_bytes, &bytes, &bytes_size) == TSI_OK); + GPR_ASSERT(bytes_size == 0); + GPR_ASSERT(bytes == NULL); +} + +static void check_handshake_results(tsi_test_fixture *fixture) { + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(fixture->vtable != NULL); + GPR_ASSERT(fixture->vtable->check_handshaker_peers != NULL); + /* Check handshaker peers. */ + fixture->vtable->check_handshaker_peers(fixture); + /* Check unused bytes. */ + if (fixture->test_unused_bytes) { + if (fixture->server_result != NULL && fixture->client_result != NULL) { + check_unused_bytes(fixture); + } + fixture->bytes_written_to_server_channel = 0; + fixture->bytes_written_to_client_channel = 0; + fixture->bytes_read_from_client_channel = 0; + fixture->bytes_read_from_server_channel = 0; + } +} + +static void send_bytes_to_peer(tsi_test_fixture *fixture, + const unsigned char *buf, size_t buf_size, + bool is_client) { + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(buf != NULL); + uint8_t *channel = + is_client ? fixture->server_channel : fixture->client_channel; + GPR_ASSERT(channel != NULL); + size_t *bytes_written = is_client ? &fixture->bytes_written_to_server_channel + : &fixture->bytes_written_to_client_channel; + GPR_ASSERT(bytes_written != NULL); + GPR_ASSERT(*bytes_written + buf_size <= TSI_TEST_DEFAULT_CHANNEL_SIZE); + /* Write data to channel. */ + memcpy(channel + *bytes_written, buf, buf_size); + *bytes_written += buf_size; +} + +static void maybe_append_unused_bytes(handshaker_args *args) { + GPR_ASSERT(args != NULL); + GPR_ASSERT(args->fixture != NULL); + tsi_test_fixture *fixture = args->fixture; + if (fixture->test_unused_bytes && !args->appended_unused_bytes) { + args->appended_unused_bytes = true; + send_bytes_to_peer(fixture, (const unsigned char *)TSI_TEST_UNUSED_BYTES, + strlen(TSI_TEST_UNUSED_BYTES), args->is_client); + if (fixture->client_result != NULL && fixture->server_result == NULL) { + fixture->has_client_finished_first = true; + } + } +} + +static void receive_bytes_from_peer(tsi_test_fixture *fixture, + unsigned char **buf, size_t *buf_size, + bool is_client) { + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(*buf != NULL); + GPR_ASSERT(buf_size != NULL); + uint8_t *channel = + is_client ? fixture->client_channel : fixture->server_channel; + GPR_ASSERT(channel != NULL); + size_t *bytes_read = is_client ? &fixture->bytes_read_from_client_channel + : &fixture->bytes_read_from_server_channel; + size_t *bytes_written = is_client ? &fixture->bytes_written_to_client_channel + : &fixture->bytes_written_to_server_channel; + GPR_ASSERT(bytes_read != NULL); + GPR_ASSERT(bytes_written != NULL); + size_t to_read = *buf_size < *bytes_written - *bytes_read + ? *buf_size + : *bytes_written - *bytes_read; + /* Read data from channel. */ + memcpy(*buf, channel + *bytes_read, to_read); + *buf_size = to_read; + *bytes_read += to_read; +} + +static void send_message_to_peer(tsi_test_fixture *fixture, + tsi_frame_protector *protector, + bool is_client) { + /* Initialization. */ + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(fixture->config != NULL); + GPR_ASSERT(protector != NULL); + tsi_test_frame_protector_config *config = fixture->config; + unsigned char *protected_buffer = + static_cast(gpr_zalloc(config->protected_buffer_size)); + size_t message_size = + is_client ? config->client_message_size : config->server_message_size; + uint8_t *message = + is_client ? config->client_message : config->server_message; + GPR_ASSERT(message != NULL); + const unsigned char *message_bytes = (const unsigned char *)message; + tsi_result result = TSI_OK; + /* Do protect and send protected data to peer. */ + while (message_size > 0 && result == TSI_OK) { + size_t protected_buffer_size_to_send = config->protected_buffer_size; + size_t processed_message_size = message_size; + /* Do protect. */ + result = tsi_frame_protector_protect( + protector, message_bytes, &processed_message_size, protected_buffer, + &protected_buffer_size_to_send); + GPR_ASSERT(result == TSI_OK); + /* Send protected data to peer. */ + send_bytes_to_peer(fixture, protected_buffer, protected_buffer_size_to_send, + is_client); + message_bytes += processed_message_size; + message_size -= processed_message_size; + /* Flush if we're done. */ + if (message_size == 0) { + size_t still_pending_size; + do { + protected_buffer_size_to_send = config->protected_buffer_size; + result = tsi_frame_protector_protect_flush( + protector, protected_buffer, &protected_buffer_size_to_send, + &still_pending_size); + GPR_ASSERT(result == TSI_OK); + send_bytes_to_peer(fixture, protected_buffer, + protected_buffer_size_to_send, is_client); + } while (still_pending_size > 0 && result == TSI_OK); + GPR_ASSERT(result == TSI_OK); + } + } + GPR_ASSERT(result == TSI_OK); + gpr_free(protected_buffer); +} + +static void receive_message_from_peer(tsi_test_fixture *fixture, + tsi_frame_protector *protector, + unsigned char *message, + size_t *bytes_received, bool is_client) { + /* Initialization. */ + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(protector != NULL); + GPR_ASSERT(message != NULL); + GPR_ASSERT(bytes_received != NULL); + GPR_ASSERT(fixture->config != NULL); + tsi_test_frame_protector_config *config = fixture->config; + size_t read_offset = 0; + size_t message_offset = 0; + size_t read_from_peer_size = 0; + tsi_result result = TSI_OK; + bool done = false; + unsigned char *read_buffer = static_cast( + gpr_zalloc(config->read_buffer_allocated_size)); + unsigned char *message_buffer = static_cast( + gpr_zalloc(config->message_buffer_allocated_size)); + /* Do unprotect on data received from peer. */ + while (!done && result == TSI_OK) { + /* Receive data from peer. */ + if (read_from_peer_size == 0) { + read_from_peer_size = config->read_buffer_allocated_size; + receive_bytes_from_peer(fixture, &read_buffer, &read_from_peer_size, + is_client); + read_offset = 0; + } + if (read_from_peer_size == 0) { + done = true; + } + /* Do unprotect. */ + size_t message_buffer_size; + do { + message_buffer_size = config->message_buffer_allocated_size; + size_t processed_size = read_from_peer_size; + result = tsi_frame_protector_unprotect( + protector, read_buffer + read_offset, &processed_size, message_buffer, + &message_buffer_size); + GPR_ASSERT(result == TSI_OK); + if (message_buffer_size > 0) { + memcpy(message + message_offset, message_buffer, message_buffer_size); + message_offset += message_buffer_size; + } + read_offset += processed_size; + read_from_peer_size -= processed_size; + } while ((read_from_peer_size > 0 || message_buffer_size > 0) && + result == TSI_OK); + GPR_ASSERT(result == TSI_OK); + } + GPR_ASSERT(result == TSI_OK); + *bytes_received = message_offset; + gpr_free(read_buffer); + gpr_free(message_buffer); +} + +grpc_error *on_handshake_next_done(tsi_result result, void *user_data, + const unsigned char *bytes_to_send, + size_t bytes_to_send_size, + tsi_handshaker_result *handshaker_result) { + handshaker_args *args = (handshaker_args *)user_data; + GPR_ASSERT(args != NULL); + GPR_ASSERT(args->fixture != NULL); + tsi_test_fixture *fixture = args->fixture; + grpc_error *error = GRPC_ERROR_NONE; + /* Read more data if we need to. */ + if (result == TSI_INCOMPLETE_DATA) { + GPR_ASSERT(bytes_to_send_size == 0); + notification_signal(fixture); + return error; + } + if (result != TSI_OK) { + notification_signal(fixture); + return grpc_set_tsi_error_result( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result); + } + /* Update handshaker result. */ + if (handshaker_result != NULL) { + tsi_handshaker_result **result_to_write = + args->is_client ? &fixture->client_result : &fixture->server_result; + GPR_ASSERT(*result_to_write == NULL); + *result_to_write = handshaker_result; + } + /* Send data to peer, if needed. */ + if (bytes_to_send_size > 0) { + send_bytes_to_peer(args->fixture, bytes_to_send, bytes_to_send_size, + args->is_client); + args->transferred_data = true; + } + if (handshaker_result != NULL) { + maybe_append_unused_bytes(args); + } + notification_signal(fixture); + return error; +} + +static void on_handshake_next_done_wrapper( + tsi_result result, void *user_data, const unsigned char *bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) { + handshaker_args *args = (handshaker_args *)user_data; + args->error = on_handshake_next_done(result, user_data, bytes_to_send, + bytes_to_send_size, handshaker_result); +} + +static bool is_handshake_finished_properly(handshaker_args *args) { + GPR_ASSERT(args != NULL); + GPR_ASSERT(args->fixture != NULL); + tsi_test_fixture *fixture = args->fixture; + if ((args->is_client && fixture->client_result != NULL) || + (!args->is_client && fixture->server_result != NULL)) { + return true; + } + return false; +} + +static void do_handshaker_next(handshaker_args *args) { + /* Initialization. */ + GPR_ASSERT(args != NULL); + GPR_ASSERT(args->fixture != NULL); + tsi_test_fixture *fixture = args->fixture; + tsi_handshaker *handshaker = + args->is_client ? fixture->client_handshaker : fixture->server_handshaker; + if (is_handshake_finished_properly(args)) { + return; + } + tsi_handshaker_result *handshaker_result = NULL; + unsigned char *bytes_to_send = NULL; + size_t bytes_to_send_size = 0; + /* Receive data from peer, if available. */ + size_t buf_size = args->handshake_buffer_size; + receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size, + args->is_client); + if (buf_size > 0) { + args->transferred_data = true; + } + /* Peform handshaker next. */ + tsi_result result = tsi_handshaker_next( + handshaker, args->handshake_buffer, buf_size, + (const unsigned char **)&bytes_to_send, &bytes_to_send_size, + &handshaker_result, &on_handshake_next_done_wrapper, args); + if (result != TSI_ASYNC) { + args->error = on_handshake_next_done(result, args, bytes_to_send, + bytes_to_send_size, handshaker_result); + if (args->error != GRPC_ERROR_NONE) { + return; + } + } + notification_wait(fixture); +} + +void tsi_test_do_handshake(tsi_test_fixture *fixture) { + /* Initializaiton. */ + setup_handshakers(fixture); + handshaker_args *client_args = + handshaker_args_create(fixture, true /* is_client */); + handshaker_args *server_args = + handshaker_args_create(fixture, false /* is_client */); + /* Do handshake. */ + do { + client_args->transferred_data = false; + server_args->transferred_data = false; + do_handshaker_next(client_args); + if (client_args->error != GRPC_ERROR_NONE) { + break; + } + do_handshaker_next(server_args); + if (server_args->error != GRPC_ERROR_NONE) { + break; + } + GPR_ASSERT(client_args->transferred_data || server_args->transferred_data); + } while (fixture->client_result == NULL || fixture->server_result == NULL); + /* Verify handshake results. */ + check_handshake_results(fixture); + /* Cleanup. */ + handshaker_args_destroy(client_args); + handshaker_args_destroy(server_args); +} + +void tsi_test_do_round_trip(tsi_test_fixture *fixture) { + /* Initialization. */ + GPR_ASSERT(fixture != NULL); + GPR_ASSERT(fixture->config != NULL); + tsi_test_frame_protector_config *config = fixture->config; + tsi_frame_protector *client_frame_protector = NULL; + tsi_frame_protector *server_frame_protector = NULL; + /* Perform handshake. */ + tsi_test_do_handshake(fixture); + /* Create frame protectors.*/ + size_t client_max_output_protected_frame_size = + config->client_max_output_protected_frame_size; + GPR_ASSERT(tsi_handshaker_result_create_frame_protector( + fixture->client_result, + client_max_output_protected_frame_size == 0 + ? NULL + : &client_max_output_protected_frame_size, + &client_frame_protector) == TSI_OK); + size_t server_max_output_protected_frame_size = + config->server_max_output_protected_frame_size; + GPR_ASSERT(tsi_handshaker_result_create_frame_protector( + fixture->server_result, + server_max_output_protected_frame_size == 0 + ? NULL + : &server_max_output_protected_frame_size, + &server_frame_protector) == TSI_OK); + /* Client sends a message to server. */ + send_message_to_peer(fixture, client_frame_protector, true /* is_client */); + unsigned char *server_received_message = + static_cast(gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE)); + size_t server_received_message_size = 0; + receive_message_from_peer( + fixture, server_frame_protector, server_received_message, + &server_received_message_size, false /* is_client */); + GPR_ASSERT(config->client_message_size == server_received_message_size); + GPR_ASSERT(memcmp(config->client_message, server_received_message, + server_received_message_size) == 0); + /* Server sends a message to client. */ + send_message_to_peer(fixture, server_frame_protector, false /* is_client */); + unsigned char *client_received_message = + static_cast(gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE)); + size_t client_received_message_size = 0; + receive_message_from_peer( + fixture, client_frame_protector, client_received_message, + &client_received_message_size, true /* is_client */); + GPR_ASSERT(config->server_message_size == client_received_message_size); + GPR_ASSERT(memcmp(config->server_message, client_received_message, + client_received_message_size) == 0); + /* Destroy server and client frame protectors. */ + tsi_frame_protector_destroy(client_frame_protector); + tsi_frame_protector_destroy(server_frame_protector); + gpr_free(server_received_message); + gpr_free(client_received_message); +} + +static unsigned char *generate_random_message(size_t size) { + size_t i; + unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + unsigned char *output = + static_cast(gpr_zalloc(sizeof(unsigned char) * size)); + for (i = 0; i < size - 1; ++i) { + output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + return output; +} + +tsi_test_frame_protector_config *tsi_test_frame_protector_config_create( + bool use_default_read_buffer_allocated_size, + bool use_default_message_buffer_allocated_size, + bool use_default_protected_buffer_size, bool use_default_client_message, + bool use_default_server_message, + bool use_default_client_max_output_protected_frame_size, + bool use_default_server_max_output_protected_frame_size, + bool use_default_handshake_buffer_size) { + tsi_test_frame_protector_config *config = + static_cast( + gpr_zalloc(sizeof(*config))); + /* Set the value for read_buffer_allocated_size. */ + config->read_buffer_allocated_size = + use_default_read_buffer_allocated_size + ? TSI_TEST_DEFAULT_BUFFER_SIZE + : TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE; + /* Set the value for message_buffer_allocated_size. */ + config->message_buffer_allocated_size = + use_default_message_buffer_allocated_size + ? TSI_TEST_DEFAULT_BUFFER_SIZE + : TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE; + /* Set the value for protected_buffer_size. */ + config->protected_buffer_size = use_default_protected_buffer_size + ? TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE + : TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE; + /* Set the value for client message. */ + config->client_message_size = use_default_client_message + ? TSI_TEST_BIG_MESSAGE_SIZE + : TSI_TEST_SMALL_MESSAGE_SIZE; + config->client_message = + use_default_client_message + ? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE) + : generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE); + /* Set the value for server message. */ + config->server_message_size = use_default_server_message + ? TSI_TEST_BIG_MESSAGE_SIZE + : TSI_TEST_SMALL_MESSAGE_SIZE; + config->server_message = + use_default_server_message + ? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE) + : generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE); + /* Set the value for client max_output_protected_frame_size. + If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(), + which then uses default protected frame size for it. */ + config->client_max_output_protected_frame_size = + use_default_client_max_output_protected_frame_size + ? 0 + : TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE; + /* Set the value for server max_output_protected_frame_size. + If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(), + which then uses default protected frame size for it. */ + config->server_max_output_protected_frame_size = + use_default_server_max_output_protected_frame_size + ? 0 + : TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE; + return config; +} + +void tsi_test_frame_protector_config_set_buffer_size( + tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size, + size_t message_buffer_allocated_size, size_t protected_buffer_size, + size_t client_max_output_protected_frame_size, + size_t server_max_output_protected_frame_size) { + GPR_ASSERT(config != NULL); + config->read_buffer_allocated_size = read_buffer_allocated_size; + config->message_buffer_allocated_size = message_buffer_allocated_size; + config->protected_buffer_size = protected_buffer_size; + config->client_max_output_protected_frame_size = + client_max_output_protected_frame_size; + config->server_max_output_protected_frame_size = + server_max_output_protected_frame_size; +} + +void tsi_test_frame_protector_config_destroy( + tsi_test_frame_protector_config *config) { + GPR_ASSERT(config != NULL); + gpr_free(config->client_message); + gpr_free(config->server_message); + gpr_free(config); +} + +void tsi_test_fixture_init(tsi_test_fixture *fixture) { + fixture->config = tsi_test_frame_protector_config_create( + true, true, true, true, true, true, true, true); + fixture->handshake_buffer_size = TSI_TEST_DEFAULT_BUFFER_SIZE; + fixture->client_channel = + static_cast(gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE)); + fixture->server_channel = + static_cast(gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE)); + fixture->bytes_written_to_client_channel = 0; + fixture->bytes_written_to_server_channel = 0; + fixture->bytes_read_from_client_channel = 0; + fixture->bytes_read_from_server_channel = 0; + fixture->test_unused_bytes = true; + fixture->has_client_finished_first = false; + gpr_mu_init(&fixture->mu); + gpr_cv_init(&fixture->cv); + fixture->notified = false; +} + +void tsi_test_fixture_destroy(tsi_test_fixture *fixture) { + GPR_ASSERT(fixture != NULL); + tsi_test_frame_protector_config_destroy(fixture->config); + tsi_handshaker_destroy(fixture->client_handshaker); + tsi_handshaker_destroy(fixture->server_handshaker); + tsi_handshaker_result_destroy(fixture->client_result); + tsi_handshaker_result_destroy(fixture->server_result); + gpr_free(fixture->client_channel); + gpr_free(fixture->server_channel); + GPR_ASSERT(fixture->vtable != NULL); + GPR_ASSERT(fixture->vtable->destruct != NULL); + fixture->vtable->destruct(fixture); + gpr_mu_destroy(&fixture->mu); + gpr_cv_destroy(&fixture->cv); + gpr_free(fixture); +} diff --git a/test/core/util/grpc_profiler.c b/test/core/util/grpc_profiler.c deleted file mode 100644 index 47b0270e29..0000000000 --- a/test/core/util/grpc_profiler.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/util/grpc_profiler.h" - -#if GRPC_HAVE_PERFTOOLS -#include - -void grpc_profiler_start(const char *filename) { ProfilerStart(filename); } - -void grpc_profiler_stop() { ProfilerStop(); } -#else -#include - -void grpc_profiler_start(const char *filename) { - static int printed_warning = 0; - if (!printed_warning) { - gpr_log(GPR_DEBUG, - "You do not have google-perftools installed, profiling is disabled " - "[for %s]", - filename); - gpr_log(GPR_DEBUG, - "To install on ubuntu: sudo apt-get install google-perftools " - "libgoogle-perftools-dev"); - printed_warning = 1; - } -} - -void grpc_profiler_stop(void) {} -#endif diff --git a/test/core/util/grpc_profiler.cc b/test/core/util/grpc_profiler.cc new file mode 100644 index 0000000000..47b0270e29 --- /dev/null +++ b/test/core/util/grpc_profiler.cc @@ -0,0 +1,45 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/util/grpc_profiler.h" + +#if GRPC_HAVE_PERFTOOLS +#include + +void grpc_profiler_start(const char *filename) { ProfilerStart(filename); } + +void grpc_profiler_stop() { ProfilerStop(); } +#else +#include + +void grpc_profiler_start(const char *filename) { + static int printed_warning = 0; + if (!printed_warning) { + gpr_log(GPR_DEBUG, + "You do not have google-perftools installed, profiling is disabled " + "[for %s]", + filename); + gpr_log(GPR_DEBUG, + "To install on ubuntu: sudo apt-get install google-perftools " + "libgoogle-perftools-dev"); + printed_warning = 1; + } +} + +void grpc_profiler_stop(void) {} +#endif diff --git a/test/core/util/memory_counters.c b/test/core/util/memory_counters.c deleted file mode 100644 index 9fb3ffe095..0000000000 --- a/test/core/util/memory_counters.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include -#include - -#include "test/core/util/memory_counters.h" - -static struct grpc_memory_counters g_memory_counters; -static gpr_allocation_functions g_old_allocs; - -static void *guard_malloc(size_t size); -static void *guard_realloc(void *vptr, size_t size); -static void guard_free(void *vptr); - -#ifdef GPR_LOW_LEVEL_COUNTERS -/* hide these from the microbenchmark atomic stats */ -#define NO_BARRIER_FETCH_ADD(x, sz) \ - __atomic_fetch_add((x), (sz), __ATOMIC_RELAXED) -#define NO_BARRIER_LOAD(x) __atomic_load_n((x), __ATOMIC_RELAXED) -#else -#define NO_BARRIER_FETCH_ADD(x, sz) gpr_atm_no_barrier_fetch_add(x, sz) -#define NO_BARRIER_LOAD(x) gpr_atm_no_barrier_load(x) -#endif - -static void *guard_malloc(size_t size) { - size_t *ptr; - if (!size) return NULL; - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, (gpr_atm)1); - ptr = (size_t *)g_old_allocs.malloc_fn(size + sizeof(size)); - *ptr++ = size; - return ptr; -} - -static void *guard_realloc(void *vptr, size_t size) { - size_t *ptr = (size_t *)vptr; - if (vptr == NULL) { - return guard_malloc(size); - } - if (size == 0) { - guard_free(vptr); - return NULL; - } - --ptr; - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1); - ptr = (size_t *)g_old_allocs.realloc_fn(ptr, size + sizeof(size)); - *ptr++ = size; - return ptr; -} - -static void guard_free(void *vptr) { - size_t *ptr = (size_t *)vptr; - if (!vptr) return; - --ptr; - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr); - NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, -(gpr_atm)1); - g_old_allocs.free_fn(ptr); -} - -struct gpr_allocation_functions g_guard_allocs = {guard_malloc, NULL, - guard_realloc, guard_free}; - -void grpc_memory_counters_init() { - memset(&g_memory_counters, 0, sizeof(g_memory_counters)); - g_old_allocs = gpr_get_allocation_functions(); - gpr_set_allocation_functions(g_guard_allocs); -} - -void grpc_memory_counters_destroy() { - gpr_set_allocation_functions(g_old_allocs); -} - -struct grpc_memory_counters grpc_memory_counters_snapshot() { - struct grpc_memory_counters counters; - counters.total_size_relative = - NO_BARRIER_LOAD(&g_memory_counters.total_size_relative); - counters.total_size_absolute = - NO_BARRIER_LOAD(&g_memory_counters.total_size_absolute); - counters.total_allocs_relative = - NO_BARRIER_LOAD(&g_memory_counters.total_allocs_relative); - counters.total_allocs_absolute = - NO_BARRIER_LOAD(&g_memory_counters.total_allocs_absolute); - return counters; -} diff --git a/test/core/util/memory_counters.cc b/test/core/util/memory_counters.cc new file mode 100644 index 0000000000..9fb3ffe095 --- /dev/null +++ b/test/core/util/memory_counters.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include + +#include "test/core/util/memory_counters.h" + +static struct grpc_memory_counters g_memory_counters; +static gpr_allocation_functions g_old_allocs; + +static void *guard_malloc(size_t size); +static void *guard_realloc(void *vptr, size_t size); +static void guard_free(void *vptr); + +#ifdef GPR_LOW_LEVEL_COUNTERS +/* hide these from the microbenchmark atomic stats */ +#define NO_BARRIER_FETCH_ADD(x, sz) \ + __atomic_fetch_add((x), (sz), __ATOMIC_RELAXED) +#define NO_BARRIER_LOAD(x) __atomic_load_n((x), __ATOMIC_RELAXED) +#else +#define NO_BARRIER_FETCH_ADD(x, sz) gpr_atm_no_barrier_fetch_add(x, sz) +#define NO_BARRIER_LOAD(x) gpr_atm_no_barrier_load(x) +#endif + +static void *guard_malloc(size_t size) { + size_t *ptr; + if (!size) return NULL; + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, (gpr_atm)1); + ptr = (size_t *)g_old_allocs.malloc_fn(size + sizeof(size)); + *ptr++ = size; + return ptr; +} + +static void *guard_realloc(void *vptr, size_t size) { + size_t *ptr = (size_t *)vptr; + if (vptr == NULL) { + return guard_malloc(size); + } + if (size == 0) { + guard_free(vptr); + return NULL; + } + --ptr; + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1); + ptr = (size_t *)g_old_allocs.realloc_fn(ptr, size + sizeof(size)); + *ptr++ = size; + return ptr; +} + +static void guard_free(void *vptr) { + size_t *ptr = (size_t *)vptr; + if (!vptr) return; + --ptr; + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr); + NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, -(gpr_atm)1); + g_old_allocs.free_fn(ptr); +} + +struct gpr_allocation_functions g_guard_allocs = {guard_malloc, NULL, + guard_realloc, guard_free}; + +void grpc_memory_counters_init() { + memset(&g_memory_counters, 0, sizeof(g_memory_counters)); + g_old_allocs = gpr_get_allocation_functions(); + gpr_set_allocation_functions(g_guard_allocs); +} + +void grpc_memory_counters_destroy() { + gpr_set_allocation_functions(g_old_allocs); +} + +struct grpc_memory_counters grpc_memory_counters_snapshot() { + struct grpc_memory_counters counters; + counters.total_size_relative = + NO_BARRIER_LOAD(&g_memory_counters.total_size_relative); + counters.total_size_absolute = + NO_BARRIER_LOAD(&g_memory_counters.total_size_absolute); + counters.total_allocs_relative = + NO_BARRIER_LOAD(&g_memory_counters.total_allocs_relative); + counters.total_allocs_absolute = + NO_BARRIER_LOAD(&g_memory_counters.total_allocs_absolute); + return counters; +} diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c deleted file mode 100644 index bd386b2148..0000000000 --- a/test/core/util/mock_endpoint.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" - -#include "test/core/util/mock_endpoint.h" - -#include - -#include -#include -#include "src/core/lib/iomgr/sockaddr.h" - -typedef struct grpc_mock_endpoint { - grpc_endpoint base; - gpr_mu mu; - void (*on_write)(grpc_slice slice); - grpc_slice_buffer read_buffer; - grpc_slice_buffer *on_read_out; - grpc_closure *on_read; - grpc_resource_user *resource_user; -} grpc_mock_endpoint; - -static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - gpr_mu_lock(&m->mu); - if (m->read_buffer.count > 0) { - grpc_slice_buffer_swap(&m->read_buffer, slices); - GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); - } else { - m->on_read = cb; - m->on_read_out = slices; - } - gpr_mu_unlock(&m->mu); -} - -static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - for (size_t i = 0; i < slices->count; i++) { - m->on_write(slices->slices[i]); - } - GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); -} - -static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset) {} - -static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pollset) {} - -static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_error *why) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - gpr_mu_lock(&m->mu); - if (m->on_read) { - GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Endpoint Shutdown", &why, 1)); - m->on_read = NULL; - } - gpr_mu_unlock(&m->mu); - grpc_resource_user_shutdown(exec_ctx, m->resource_user); - GRPC_ERROR_UNREF(why); -} - -static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - grpc_slice_buffer_destroy(&m->read_buffer); - grpc_resource_user_unref(exec_ctx, m->resource_user); - gpr_free(m); -} - -static char *me_get_peer(grpc_endpoint *ep) { - return gpr_strdup("fake:mock_endpoint"); -} - -static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - return m->resource_user; -} - -static int me_get_fd(grpc_endpoint *ep) { return -1; } - -static const grpc_endpoint_vtable vtable = { - me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, - me_shutdown, me_destroy, me_get_resource_user, me_get_peer, - me_get_fd, -}; - -grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice), - grpc_resource_quota *resource_quota) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)gpr_malloc(sizeof(*m)); - m->base.vtable = &vtable; - char *name; - gpr_asprintf(&name, "mock_endpoint_%" PRIxPTR, (intptr_t)m); - m->resource_user = grpc_resource_user_create(resource_quota, name); - gpr_free(name); - grpc_slice_buffer_init(&m->read_buffer); - gpr_mu_init(&m->mu); - m->on_write = on_write; - m->on_read = NULL; - return &m->base; -} - -void grpc_mock_endpoint_put_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice slice) { - grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; - gpr_mu_lock(&m->mu); - if (m->on_read != NULL) { - grpc_slice_buffer_add(m->on_read_out, slice); - GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, GRPC_ERROR_NONE); - m->on_read = NULL; - } else { - grpc_slice_buffer_add(&m->read_buffer, slice); - } - gpr_mu_unlock(&m->mu); -} diff --git a/test/core/util/mock_endpoint.cc b/test/core/util/mock_endpoint.cc new file mode 100644 index 0000000000..bd386b2148 --- /dev/null +++ b/test/core/util/mock_endpoint.cc @@ -0,0 +1,138 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + +#include "test/core/util/mock_endpoint.h" + +#include + +#include +#include +#include "src/core/lib/iomgr/sockaddr.h" + +typedef struct grpc_mock_endpoint { + grpc_endpoint base; + gpr_mu mu; + void (*on_write)(grpc_slice slice); + grpc_slice_buffer read_buffer; + grpc_slice_buffer *on_read_out; + grpc_closure *on_read; + grpc_resource_user *resource_user; +} grpc_mock_endpoint; + +static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + gpr_mu_lock(&m->mu); + if (m->read_buffer.count > 0) { + grpc_slice_buffer_swap(&m->read_buffer, slices); + GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); + } else { + m->on_read = cb; + m->on_read_out = slices; + } + gpr_mu_unlock(&m->mu); +} + +static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + for (size_t i = 0; i < slices->count; i++) { + m->on_write(slices->slices[i]); + } + GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); +} + +static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset *pollset) {} + +static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset_set *pollset) {} + +static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_error *why) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + gpr_mu_lock(&m->mu); + if (m->on_read) { + GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Endpoint Shutdown", &why, 1)); + m->on_read = NULL; + } + gpr_mu_unlock(&m->mu); + grpc_resource_user_shutdown(exec_ctx, m->resource_user); + GRPC_ERROR_UNREF(why); +} + +static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + grpc_slice_buffer_destroy(&m->read_buffer); + grpc_resource_user_unref(exec_ctx, m->resource_user); + gpr_free(m); +} + +static char *me_get_peer(grpc_endpoint *ep) { + return gpr_strdup("fake:mock_endpoint"); +} + +static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + return m->resource_user; +} + +static int me_get_fd(grpc_endpoint *ep) { return -1; } + +static const grpc_endpoint_vtable vtable = { + me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, + me_shutdown, me_destroy, me_get_resource_user, me_get_peer, + me_get_fd, +}; + +grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice), + grpc_resource_quota *resource_quota) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)gpr_malloc(sizeof(*m)); + m->base.vtable = &vtable; + char *name; + gpr_asprintf(&name, "mock_endpoint_%" PRIxPTR, (intptr_t)m); + m->resource_user = grpc_resource_user_create(resource_quota, name); + gpr_free(name); + grpc_slice_buffer_init(&m->read_buffer); + gpr_mu_init(&m->mu); + m->on_write = on_write; + m->on_read = NULL; + return &m->base; +} + +void grpc_mock_endpoint_put_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice slice) { + grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep; + gpr_mu_lock(&m->mu); + if (m->on_read != NULL) { + grpc_slice_buffer_add(m->on_read_out, slice); + GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, GRPC_ERROR_NONE); + m->on_read = NULL; + } else { + grpc_slice_buffer_add(&m->read_buffer, slice); + } + gpr_mu_unlock(&m->mu); +} diff --git a/test/core/util/one_corpus_entry_fuzzer.c b/test/core/util/one_corpus_entry_fuzzer.c deleted file mode 100644 index 42467390f2..0000000000 --- a/test/core/util/one_corpus_entry_fuzzer.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include "src/core/lib/iomgr/load_file.h" - -extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); - -extern bool squelch; -extern bool leak_check; - -int main(int argc, char **argv) { - grpc_slice buffer; - squelch = false; - leak_check = false; - GPR_ASSERT( - GRPC_LOG_IF_ERROR("load_file", grpc_load_file(argv[1], 0, &buffer))); - LLVMFuzzerTestOneInput(GRPC_SLICE_START_PTR(buffer), - GRPC_SLICE_LENGTH(buffer)); - grpc_slice_unref(buffer); - return 0; -} diff --git a/test/core/util/one_corpus_entry_fuzzer.cc b/test/core/util/one_corpus_entry_fuzzer.cc new file mode 100644 index 0000000000..42467390f2 --- /dev/null +++ b/test/core/util/one_corpus_entry_fuzzer.cc @@ -0,0 +1,39 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include "src/core/lib/iomgr/load_file.h" + +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +extern bool squelch; +extern bool leak_check; + +int main(int argc, char **argv) { + grpc_slice buffer; + squelch = false; + leak_check = false; + GPR_ASSERT( + GRPC_LOG_IF_ERROR("load_file", grpc_load_file(argv[1], 0, &buffer))); + LLVMFuzzerTestOneInput(GRPC_SLICE_START_PTR(buffer), + GRPC_SLICE_LENGTH(buffer)); + grpc_slice_unref(buffer); + return 0; +} diff --git a/test/core/util/parse_hexstring.c b/test/core/util/parse_hexstring.c deleted file mode 100644 index 346b871b67..0000000000 --- a/test/core/util/parse_hexstring.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/util/parse_hexstring.h" -#include - -grpc_slice parse_hexstring(const char *hexstring) { - size_t nibbles = 0; - const char *p = 0; - uint8_t *out; - uint8_t temp; - grpc_slice slice; - - for (p = hexstring; *p; p++) { - nibbles += (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f'); - } - - GPR_ASSERT((nibbles & 1) == 0); - - slice = grpc_slice_malloc(nibbles / 2); - out = GRPC_SLICE_START_PTR(slice); - - nibbles = 0; - temp = 0; - for (p = hexstring; *p; p++) { - if (*p >= '0' && *p <= '9') { - temp = (uint8_t)(temp << 4) | (uint8_t)(*p - '0'); - nibbles++; - } else if (*p >= 'a' && *p <= 'f') { - temp = (uint8_t)(temp << 4) | (uint8_t)(*p - 'a' + 10); - nibbles++; - } - if (nibbles == 2) { - *out++ = temp; - nibbles = 0; - } - } - - return slice; -} diff --git a/test/core/util/parse_hexstring.cc b/test/core/util/parse_hexstring.cc new file mode 100644 index 0000000000..346b871b67 --- /dev/null +++ b/test/core/util/parse_hexstring.cc @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/util/parse_hexstring.h" +#include + +grpc_slice parse_hexstring(const char *hexstring) { + size_t nibbles = 0; + const char *p = 0; + uint8_t *out; + uint8_t temp; + grpc_slice slice; + + for (p = hexstring; *p; p++) { + nibbles += (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f'); + } + + GPR_ASSERT((nibbles & 1) == 0); + + slice = grpc_slice_malloc(nibbles / 2); + out = GRPC_SLICE_START_PTR(slice); + + nibbles = 0; + temp = 0; + for (p = hexstring; *p; p++) { + if (*p >= '0' && *p <= '9') { + temp = (uint8_t)(temp << 4) | (uint8_t)(*p - '0'); + nibbles++; + } else if (*p >= 'a' && *p <= 'f') { + temp = (uint8_t)(temp << 4) | (uint8_t)(*p - 'a' + 10); + nibbles++; + } + if (nibbles == 2) { + *out++ = temp; + nibbles = 0; + } + } + + return slice; +} diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c deleted file mode 100644 index 38a47584d5..0000000000 --- a/test/core/util/passthru_endpoint.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr.h" - -#include "test/core/util/passthru_endpoint.h" - -#include -#include - -#include -#include -#include "src/core/lib/iomgr/sockaddr.h" - -#include "src/core/lib/slice/slice_internal.h" - -typedef struct passthru_endpoint passthru_endpoint; - -typedef struct { - grpc_endpoint base; - passthru_endpoint *parent; - grpc_slice_buffer read_buffer; - grpc_slice_buffer *on_read_out; - grpc_closure *on_read; - grpc_resource_user *resource_user; -} half; - -struct passthru_endpoint { - gpr_mu mu; - int halves; - grpc_passthru_endpoint_stats *stats; - grpc_passthru_endpoint_stats - dummy_stats; // used if constructor stats == NULL - bool shutdown; - half client; - half server; -}; - -static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - half *m = (half *)ep; - gpr_mu_lock(&m->parent->mu); - if (m->parent->shutdown) { - GRPC_CLOSURE_SCHED( - exec_ctx, cb, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already shutdown")); - } else if (m->read_buffer.count > 0) { - grpc_slice_buffer_swap(&m->read_buffer, slices); - GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); - } else { - m->on_read = cb; - m->on_read_out = slices; - } - gpr_mu_unlock(&m->parent->mu); -} - -static half *other_half(half *h) { - if (h == &h->parent->client) return &h->parent->server; - return &h->parent->client; -} - -static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - half *m = other_half((half *)ep); - gpr_mu_lock(&m->parent->mu); - grpc_error *error = GRPC_ERROR_NONE; - m->parent->stats->num_writes++; - if (m->parent->shutdown) { - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown"); - } else if (m->on_read != NULL) { - for (size_t i = 0; i < slices->count; i++) { - grpc_slice_buffer_add(m->on_read_out, grpc_slice_copy(slices->slices[i])); - } - GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, GRPC_ERROR_NONE); - m->on_read = NULL; - } else { - for (size_t i = 0; i < slices->count; i++) { - grpc_slice_buffer_add(&m->read_buffer, - grpc_slice_copy(slices->slices[i])); - } - } - gpr_mu_unlock(&m->parent->mu); - GRPC_CLOSURE_SCHED(exec_ctx, cb, error); -} - -static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset) {} - -static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pollset) {} - -static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_error *why) { - half *m = (half *)ep; - gpr_mu_lock(&m->parent->mu); - m->parent->shutdown = true; - if (m->on_read) { - GRPC_CLOSURE_SCHED( - exec_ctx, m->on_read, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1)); - m->on_read = NULL; - } - m = other_half(m); - if (m->on_read) { - GRPC_CLOSURE_SCHED( - exec_ctx, m->on_read, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1)); - m->on_read = NULL; - } - gpr_mu_unlock(&m->parent->mu); - grpc_resource_user_shutdown(exec_ctx, m->resource_user); - GRPC_ERROR_UNREF(why); -} - -static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - passthru_endpoint *p = ((half *)ep)->parent; - gpr_mu_lock(&p->mu); - if (0 == --p->halves) { - gpr_mu_unlock(&p->mu); - gpr_mu_destroy(&p->mu); - grpc_slice_buffer_destroy_internal(exec_ctx, &p->client.read_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &p->server.read_buffer); - grpc_resource_user_unref(exec_ctx, p->client.resource_user); - grpc_resource_user_unref(exec_ctx, p->server.resource_user); - gpr_free(p); - } else { - gpr_mu_unlock(&p->mu); - } -} - -static char *me_get_peer(grpc_endpoint *ep) { - passthru_endpoint *p = ((half *)ep)->parent; - return ((half *)ep) == &p->client ? gpr_strdup("fake:mock_client_endpoint") - : gpr_strdup("fake:mock_server_endpoint"); -} - -static int me_get_fd(grpc_endpoint *ep) { return -1; } - -static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { - half *m = (half *)ep; - return m->resource_user; -} - -static const grpc_endpoint_vtable vtable = { - me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, - me_shutdown, me_destroy, me_get_resource_user, me_get_peer, - me_get_fd, -}; - -static void half_init(half *m, passthru_endpoint *parent, - grpc_resource_quota *resource_quota, - const char *half_name) { - m->base.vtable = &vtable; - m->parent = parent; - grpc_slice_buffer_init(&m->read_buffer); - m->on_read = NULL; - char *name; - gpr_asprintf(&name, "passthru_endpoint_%s_%" PRIxPTR, half_name, - (intptr_t)parent); - m->resource_user = grpc_resource_user_create(resource_quota, name); - gpr_free(name); -} - -void grpc_passthru_endpoint_create(grpc_endpoint **client, - grpc_endpoint **server, - grpc_resource_quota *resource_quota, - grpc_passthru_endpoint_stats *stats) { - passthru_endpoint *m = (passthru_endpoint *)gpr_malloc(sizeof(*m)); - m->halves = 2; - m->shutdown = 0; - m->stats = stats == NULL ? &m->dummy_stats : stats; - memset(m->stats, 0, sizeof(*m->stats)); - half_init(&m->client, m, resource_quota, "client"); - half_init(&m->server, m, resource_quota, "server"); - gpr_mu_init(&m->mu); - *client = &m->client.base; - *server = &m->server.base; -} diff --git a/test/core/util/passthru_endpoint.cc b/test/core/util/passthru_endpoint.cc new file mode 100644 index 0000000000..38a47584d5 --- /dev/null +++ b/test/core/util/passthru_endpoint.cc @@ -0,0 +1,196 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when + using that endpoint. Because of various transitive includes in uv.h, + including windows.h on Windows, uv.h must be included before other system + headers. Therefore, sockaddr.h must always be included first */ +#include "src/core/lib/iomgr/sockaddr.h" + +#include "test/core/util/passthru_endpoint.h" + +#include +#include + +#include +#include +#include "src/core/lib/iomgr/sockaddr.h" + +#include "src/core/lib/slice/slice_internal.h" + +typedef struct passthru_endpoint passthru_endpoint; + +typedef struct { + grpc_endpoint base; + passthru_endpoint *parent; + grpc_slice_buffer read_buffer; + grpc_slice_buffer *on_read_out; + grpc_closure *on_read; + grpc_resource_user *resource_user; +} half; + +struct passthru_endpoint { + gpr_mu mu; + int halves; + grpc_passthru_endpoint_stats *stats; + grpc_passthru_endpoint_stats + dummy_stats; // used if constructor stats == NULL + bool shutdown; + half client; + half server; +}; + +static void me_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + half *m = (half *)ep; + gpr_mu_lock(&m->parent->mu); + if (m->parent->shutdown) { + GRPC_CLOSURE_SCHED( + exec_ctx, cb, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already shutdown")); + } else if (m->read_buffer.count > 0) { + grpc_slice_buffer_swap(&m->read_buffer, slices); + GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE); + } else { + m->on_read = cb; + m->on_read_out = slices; + } + gpr_mu_unlock(&m->parent->mu); +} + +static half *other_half(half *h) { + if (h == &h->parent->client) return &h->parent->server; + return &h->parent->client; +} + +static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + half *m = other_half((half *)ep); + gpr_mu_lock(&m->parent->mu); + grpc_error *error = GRPC_ERROR_NONE; + m->parent->stats->num_writes++; + if (m->parent->shutdown) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown"); + } else if (m->on_read != NULL) { + for (size_t i = 0; i < slices->count; i++) { + grpc_slice_buffer_add(m->on_read_out, grpc_slice_copy(slices->slices[i])); + } + GRPC_CLOSURE_SCHED(exec_ctx, m->on_read, GRPC_ERROR_NONE); + m->on_read = NULL; + } else { + for (size_t i = 0; i < slices->count; i++) { + grpc_slice_buffer_add(&m->read_buffer, + grpc_slice_copy(slices->slices[i])); + } + } + gpr_mu_unlock(&m->parent->mu); + GRPC_CLOSURE_SCHED(exec_ctx, cb, error); +} + +static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset *pollset) {} + +static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset_set *pollset) {} + +static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_error *why) { + half *m = (half *)ep; + gpr_mu_lock(&m->parent->mu); + m->parent->shutdown = true; + if (m->on_read) { + GRPC_CLOSURE_SCHED( + exec_ctx, m->on_read, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1)); + m->on_read = NULL; + } + m = other_half(m); + if (m->on_read) { + GRPC_CLOSURE_SCHED( + exec_ctx, m->on_read, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Shutdown", &why, 1)); + m->on_read = NULL; + } + gpr_mu_unlock(&m->parent->mu); + grpc_resource_user_shutdown(exec_ctx, m->resource_user); + GRPC_ERROR_UNREF(why); +} + +static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { + passthru_endpoint *p = ((half *)ep)->parent; + gpr_mu_lock(&p->mu); + if (0 == --p->halves) { + gpr_mu_unlock(&p->mu); + gpr_mu_destroy(&p->mu); + grpc_slice_buffer_destroy_internal(exec_ctx, &p->client.read_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &p->server.read_buffer); + grpc_resource_user_unref(exec_ctx, p->client.resource_user); + grpc_resource_user_unref(exec_ctx, p->server.resource_user); + gpr_free(p); + } else { + gpr_mu_unlock(&p->mu); + } +} + +static char *me_get_peer(grpc_endpoint *ep) { + passthru_endpoint *p = ((half *)ep)->parent; + return ((half *)ep) == &p->client ? gpr_strdup("fake:mock_client_endpoint") + : gpr_strdup("fake:mock_server_endpoint"); +} + +static int me_get_fd(grpc_endpoint *ep) { return -1; } + +static grpc_resource_user *me_get_resource_user(grpc_endpoint *ep) { + half *m = (half *)ep; + return m->resource_user; +} + +static const grpc_endpoint_vtable vtable = { + me_read, me_write, me_add_to_pollset, me_add_to_pollset_set, + me_shutdown, me_destroy, me_get_resource_user, me_get_peer, + me_get_fd, +}; + +static void half_init(half *m, passthru_endpoint *parent, + grpc_resource_quota *resource_quota, + const char *half_name) { + m->base.vtable = &vtable; + m->parent = parent; + grpc_slice_buffer_init(&m->read_buffer); + m->on_read = NULL; + char *name; + gpr_asprintf(&name, "passthru_endpoint_%s_%" PRIxPTR, half_name, + (intptr_t)parent); + m->resource_user = grpc_resource_user_create(resource_quota, name); + gpr_free(name); +} + +void grpc_passthru_endpoint_create(grpc_endpoint **client, + grpc_endpoint **server, + grpc_resource_quota *resource_quota, + grpc_passthru_endpoint_stats *stats) { + passthru_endpoint *m = (passthru_endpoint *)gpr_malloc(sizeof(*m)); + m->halves = 2; + m->shutdown = 0; + m->stats = stats == NULL ? &m->dummy_stats : stats; + memset(m->stats, 0, sizeof(*m->stats)); + half_init(&m->client, m, resource_quota, "client"); + half_init(&m->server, m, resource_quota, "server"); + gpr_mu_init(&m->mu); + *client = &m->client.base; + *server = &m->server.base; +} diff --git a/test/core/util/port.c b/test/core/util/port.c deleted file mode 100644 index 61f2e5018f..0000000000 --- a/test/core/util/port.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" -#include "test/core/util/test_config.h" -#if defined(GRPC_TEST_PICK_PORT) - -#include "test/core/util/port.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "test/core/util/port_server_client.h" - -static int *chosen_ports = NULL; -static size_t num_chosen_ports = 0; - -static int free_chosen_port(int port) { - size_t i; - int found = 0; - size_t found_at = 0; - /* Find the port and erase it from the list, then tell the server it can be - freed. */ - for (i = 0; i < num_chosen_ports; i++) { - if (chosen_ports[i] == port) { - GPR_ASSERT(found == 0); - found = 1; - found_at = i; - } - } - if (found) { - chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1]; - num_chosen_ports--; - grpc_free_port_using_server(port); - } - return found; -} - -static void free_chosen_ports(void) { - size_t i; - grpc_init(); - for (i = 0; i < num_chosen_ports; i++) { - grpc_free_port_using_server(chosen_ports[i]); - } - grpc_shutdown(); - gpr_free(chosen_ports); -} - -static void chose_port(int port) { - if (chosen_ports == NULL) { - atexit(free_chosen_ports); - } - num_chosen_ports++; - chosen_ports = - (int *)gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports); - chosen_ports[num_chosen_ports - 1] = port; -} - -static int grpc_pick_unused_port_impl(void) { - int port = grpc_pick_port_using_server(); - if (port != 0) { - chose_port(port); - } - - return port; -} - -static int grpc_pick_unused_port_or_die_impl(void) { - int port = grpc_pick_unused_port(); - if (port == 0) { - fprintf(stderr, - "gRPC tests require a helper port server to allocate ports used \n" - "during the test.\n\n" - "This server is not currently running.\n\n" - "To start it, run tools/run_tests/start_port_server.py\n\n"); - exit(1); - } - return port; -} - -static void grpc_recycle_unused_port_impl(int port) { - GPR_ASSERT(free_chosen_port(port)); -} - -static grpc_pick_port_functions g_pick_port_functions = { - grpc_pick_unused_port_impl, grpc_pick_unused_port_or_die_impl, - grpc_recycle_unused_port_impl}; - -int grpc_pick_unused_port(void) { - return g_pick_port_functions.pick_unused_port_fn(); -} - -int grpc_pick_unused_port_or_die(void) { - return g_pick_port_functions.pick_unused_port_or_die_fn(); -} - -void grpc_recycle_unused_port(int port) { - g_pick_port_functions.recycle_unused_port_fn(port); -} - -void grpc_set_pick_port_functions(grpc_pick_port_functions functions) { - GPR_ASSERT(functions.pick_unused_port_fn != NULL); - GPR_ASSERT(functions.pick_unused_port_or_die_fn != NULL); - GPR_ASSERT(functions.recycle_unused_port_fn != NULL); - g_pick_port_functions = functions; -} - -#endif /* GRPC_TEST_PICK_PORT */ diff --git a/test/core/util/port.cc b/test/core/util/port.cc new file mode 100644 index 0000000000..61f2e5018f --- /dev/null +++ b/test/core/util/port.cc @@ -0,0 +1,132 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" +#include "test/core/util/test_config.h" +#if defined(GRPC_TEST_PICK_PORT) + +#include "test/core/util/port.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "test/core/util/port_server_client.h" + +static int *chosen_ports = NULL; +static size_t num_chosen_ports = 0; + +static int free_chosen_port(int port) { + size_t i; + int found = 0; + size_t found_at = 0; + /* Find the port and erase it from the list, then tell the server it can be + freed. */ + for (i = 0; i < num_chosen_ports; i++) { + if (chosen_ports[i] == port) { + GPR_ASSERT(found == 0); + found = 1; + found_at = i; + } + } + if (found) { + chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1]; + num_chosen_ports--; + grpc_free_port_using_server(port); + } + return found; +} + +static void free_chosen_ports(void) { + size_t i; + grpc_init(); + for (i = 0; i < num_chosen_ports; i++) { + grpc_free_port_using_server(chosen_ports[i]); + } + grpc_shutdown(); + gpr_free(chosen_ports); +} + +static void chose_port(int port) { + if (chosen_ports == NULL) { + atexit(free_chosen_ports); + } + num_chosen_ports++; + chosen_ports = + (int *)gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports); + chosen_ports[num_chosen_ports - 1] = port; +} + +static int grpc_pick_unused_port_impl(void) { + int port = grpc_pick_port_using_server(); + if (port != 0) { + chose_port(port); + } + + return port; +} + +static int grpc_pick_unused_port_or_die_impl(void) { + int port = grpc_pick_unused_port(); + if (port == 0) { + fprintf(stderr, + "gRPC tests require a helper port server to allocate ports used \n" + "during the test.\n\n" + "This server is not currently running.\n\n" + "To start it, run tools/run_tests/start_port_server.py\n\n"); + exit(1); + } + return port; +} + +static void grpc_recycle_unused_port_impl(int port) { + GPR_ASSERT(free_chosen_port(port)); +} + +static grpc_pick_port_functions g_pick_port_functions = { + grpc_pick_unused_port_impl, grpc_pick_unused_port_or_die_impl, + grpc_recycle_unused_port_impl}; + +int grpc_pick_unused_port(void) { + return g_pick_port_functions.pick_unused_port_fn(); +} + +int grpc_pick_unused_port_or_die(void) { + return g_pick_port_functions.pick_unused_port_or_die_fn(); +} + +void grpc_recycle_unused_port(int port) { + g_pick_port_functions.recycle_unused_port_fn(port); +} + +void grpc_set_pick_port_functions(grpc_pick_port_functions functions) { + GPR_ASSERT(functions.pick_unused_port_fn != NULL); + GPR_ASSERT(functions.pick_unused_port_or_die_fn != NULL); + GPR_ASSERT(functions.recycle_unused_port_fn != NULL); + g_pick_port_functions = functions; +} + +#endif /* GRPC_TEST_PICK_PORT */ diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c deleted file mode 100644 index 7b94ac4ada..0000000000 --- a/test/core/util/port_server_client.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "test/core/util/test_config.h" - -#ifdef GRPC_TEST_PICK_PORT -#include "test/core/util/port_server_client.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/http/httpcli.h" - -typedef struct freereq { - gpr_mu *mu; - grpc_polling_entity pops; - int done; -} freereq; - -static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p, - grpc_error *error) { - grpc_pollset *pollset = grpc_polling_entity_pollset((grpc_polling_entity *)p); - grpc_pollset_destroy(exec_ctx, pollset); - gpr_free(pollset); -} - -static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - freereq *pr = (freereq *)arg; - gpr_mu_lock(pr->mu); - pr->done = 1; - GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), - NULL)); - gpr_mu_unlock(pr->mu); -} - -void grpc_free_port_using_server(int port) { - grpc_httpcli_context context; - grpc_httpcli_request req; - grpc_httpcli_response rsp; - freereq pr; - char *path; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure *shutdown_closure; - - grpc_init(); - - memset(&pr, 0, sizeof(pr)); - memset(&req, 0, sizeof(req)); - memset(&rsp, 0, sizeof(rsp)); - - grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &pr.mu); - pr.pops = grpc_polling_entity_create_from_pollset(pollset); - shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops, - grpc_schedule_on_exec_ctx); - - req.host = GRPC_PORT_SERVER_ADDRESS; - gpr_asprintf(&path, "/drop/%d", port); - req.http.path = path; - - grpc_httpcli_context_init(&context); - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("port_server_client/free"); - grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req, - grpc_exec_ctx_now(&exec_ctx) + 30 * GPR_MS_PER_SEC, - GRPC_CLOSURE_CREATE(freed_port_from_server, &pr, - grpc_schedule_on_exec_ctx), - &rsp); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(pr.mu); - while (!pr.done) { - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), - &worker, - grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC))) { - pr.done = 1; - } - } - gpr_mu_unlock(pr.mu); - - grpc_httpcli_context_destroy(&exec_ctx, &context); - grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), - shutdown_closure); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(path); - grpc_http_response_destroy(&rsp); - - grpc_shutdown(); -} - -typedef struct portreq { - gpr_mu *mu; - grpc_polling_entity pops; - int port; - int retries; - char *server; - grpc_httpcli_context *ctx; - grpc_httpcli_response response; -} portreq; - -static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - size_t i; - int port = 0; - portreq *pr = (portreq *)arg; - int failed = 0; - grpc_httpcli_response *response = &pr->response; - - if (error != GRPC_ERROR_NONE) { - failed = 1; - const char *msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg); - - } else if (response->status != 200) { - failed = 1; - gpr_log(GPR_DEBUG, "failed port pick from server: status=%d", - response->status); - } - - if (failed) { - grpc_httpcli_request req; - memset(&req, 0, sizeof(req)); - if (pr->retries >= 5) { - gpr_mu_lock(pr->mu); - pr->port = 0; - GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), - NULL)); - gpr_mu_unlock(pr->mu); - return; - } - GPR_ASSERT(pr->retries < 10); - gpr_sleep_until(gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_millis( - (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)), - GPR_TIMESPAN))); - pr->retries++; - req.host = pr->server; - req.http.path = "/get"; - grpc_http_response_destroy(&pr->response); - memset(&pr->response, 0, sizeof(pr->response)); - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("port_server_client/pick_retry"); - grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req, - grpc_exec_ctx_now(exec_ctx) + 30 * GPR_MS_PER_SEC, - GRPC_CLOSURE_CREATE(got_port_from_server, pr, - grpc_schedule_on_exec_ctx), - &pr->response); - grpc_resource_quota_unref_internal(exec_ctx, resource_quota); - return; - } - GPR_ASSERT(response); - GPR_ASSERT(response->status == 200); - for (i = 0; i < response->body_length; i++) { - GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); - port = port * 10 + response->body[i] - '0'; - } - GPR_ASSERT(port > 1024); - gpr_mu_lock(pr->mu); - pr->port = port; - GRPC_LOG_IF_ERROR( - "pollset_kick", - grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), - NULL)); - gpr_mu_unlock(pr->mu); -} - -int grpc_pick_port_using_server(void) { - grpc_httpcli_context context; - grpc_httpcli_request req; - portreq pr; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure *shutdown_closure; - - grpc_init(); - - memset(&pr, 0, sizeof(pr)); - memset(&req, 0, sizeof(req)); - grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(pollset, &pr.mu); - pr.pops = grpc_polling_entity_create_from_pollset(pollset); - shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops, - grpc_schedule_on_exec_ctx); - pr.port = -1; - pr.server = GRPC_PORT_SERVER_ADDRESS; - pr.ctx = &context; - - req.host = GRPC_PORT_SERVER_ADDRESS; - req.http.path = "/get"; - - grpc_httpcli_context_init(&context); - grpc_resource_quota *resource_quota = - grpc_resource_quota_create("port_server_client/pick"); - grpc_httpcli_get( - &exec_ctx, &context, &pr.pops, resource_quota, &req, - grpc_exec_ctx_now(&exec_ctx) + 30 * GPR_MS_PER_SEC, - GRPC_CLOSURE_CREATE(got_port_from_server, &pr, grpc_schedule_on_exec_ctx), - &pr.response); - grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(pr.mu); - while (pr.port == -1) { - grpc_pollset_worker *worker = NULL; - if (!GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), - &worker, - grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC))) { - pr.port = 0; - } - } - gpr_mu_unlock(pr.mu); - - grpc_http_response_destroy(&pr.response); - grpc_httpcli_context_destroy(&exec_ctx, &context); - grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), - shutdown_closure); - grpc_exec_ctx_finish(&exec_ctx); - grpc_shutdown(); - - return pr.port; -} - -#endif // GRPC_TEST_PICK_PORT diff --git a/test/core/util/port_server_client.cc b/test/core/util/port_server_client.cc new file mode 100644 index 0000000000..2c7301d058 --- /dev/null +++ b/test/core/util/port_server_client.cc @@ -0,0 +1,255 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "test/core/util/test_config.h" + +#ifdef GRPC_TEST_PICK_PORT +#include "test/core/util/port_server_client.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/http/httpcli.h" + +typedef struct freereq { + gpr_mu *mu; + grpc_polling_entity pops; + int done; +} freereq; + +static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset *pollset = grpc_polling_entity_pollset((grpc_polling_entity *)p); + grpc_pollset_destroy(exec_ctx, pollset); + gpr_free(pollset); +} + +static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + freereq *pr = (freereq *)arg; + gpr_mu_lock(pr->mu); + pr->done = 1; + GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), + NULL)); + gpr_mu_unlock(pr->mu); +} + +void grpc_free_port_using_server(int port) { + grpc_httpcli_context context; + grpc_httpcli_request req; + grpc_httpcli_response rsp; + freereq pr; + char *path; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_closure *shutdown_closure; + + grpc_init(); + + memset(&pr, 0, sizeof(pr)); + memset(&req, 0, sizeof(req)); + memset(&rsp, 0, sizeof(rsp)); + + grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(pollset, &pr.mu); + pr.pops = grpc_polling_entity_create_from_pollset(pollset); + shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops, + grpc_schedule_on_exec_ctx); + + req.host = const_cast(GRPC_PORT_SERVER_ADDRESS); + gpr_asprintf(&path, "/drop/%d", port); + req.http.path = path; + + grpc_httpcli_context_init(&context); + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("port_server_client/free"); + grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req, + grpc_exec_ctx_now(&exec_ctx) + 30 * GPR_MS_PER_SEC, + GRPC_CLOSURE_CREATE(freed_port_from_server, &pr, + grpc_schedule_on_exec_ctx), + &rsp); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(pr.mu); + while (!pr.done) { + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), + &worker, + grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC))) { + pr.done = 1; + } + } + gpr_mu_unlock(pr.mu); + + grpc_httpcli_context_destroy(&exec_ctx, &context); + grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), + shutdown_closure); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(path); + grpc_http_response_destroy(&rsp); + + grpc_shutdown(); +} + +typedef struct portreq { + gpr_mu *mu; + grpc_polling_entity pops; + int port; + int retries; + char *server; + grpc_httpcli_context *ctx; + grpc_httpcli_response response; +} portreq; + +static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + size_t i; + int port = 0; + portreq *pr = (portreq *)arg; + int failed = 0; + grpc_httpcli_response *response = &pr->response; + + if (error != GRPC_ERROR_NONE) { + failed = 1; + const char *msg = grpc_error_string(error); + gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg); + + } else if (response->status != 200) { + failed = 1; + gpr_log(GPR_DEBUG, "failed port pick from server: status=%d", + response->status); + } + + if (failed) { + grpc_httpcli_request req; + memset(&req, 0, sizeof(req)); + if (pr->retries >= 5) { + gpr_mu_lock(pr->mu); + pr->port = 0; + GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), + NULL)); + gpr_mu_unlock(pr->mu); + return; + } + GPR_ASSERT(pr->retries < 10); + gpr_sleep_until(gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis( + (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)), + GPR_TIMESPAN))); + pr->retries++; + req.host = pr->server; + req.http.path = const_cast("/get"); + grpc_http_response_destroy(&pr->response); + memset(&pr->response, 0, sizeof(pr->response)); + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("port_server_client/pick_retry"); + grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req, + grpc_exec_ctx_now(exec_ctx) + 30 * GPR_MS_PER_SEC, + GRPC_CLOSURE_CREATE(got_port_from_server, pr, + grpc_schedule_on_exec_ctx), + &pr->response); + grpc_resource_quota_unref_internal(exec_ctx, resource_quota); + return; + } + GPR_ASSERT(response); + GPR_ASSERT(response->status == 200); + for (i = 0; i < response->body_length; i++) { + GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); + port = port * 10 + response->body[i] - '0'; + } + GPR_ASSERT(port > 1024); + gpr_mu_lock(pr->mu); + pr->port = port; + GRPC_LOG_IF_ERROR( + "pollset_kick", + grpc_pollset_kick(exec_ctx, grpc_polling_entity_pollset(&pr->pops), + NULL)); + gpr_mu_unlock(pr->mu); +} + +int grpc_pick_port_using_server(void) { + grpc_httpcli_context context; + grpc_httpcli_request req; + portreq pr; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_closure *shutdown_closure; + + grpc_init(); + + memset(&pr, 0, sizeof(pr)); + memset(&req, 0, sizeof(req)); + grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); + grpc_pollset_init(pollset, &pr.mu); + pr.pops = grpc_polling_entity_create_from_pollset(pollset); + shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops, + grpc_schedule_on_exec_ctx); + pr.port = -1; + pr.server = const_cast(GRPC_PORT_SERVER_ADDRESS); + pr.ctx = &context; + + req.host = const_cast(GRPC_PORT_SERVER_ADDRESS); + req.http.path = const_cast("/get"); + + grpc_httpcli_context_init(&context); + grpc_resource_quota *resource_quota = + grpc_resource_quota_create("port_server_client/pick"); + grpc_httpcli_get( + &exec_ctx, &context, &pr.pops, resource_quota, &req, + grpc_exec_ctx_now(&exec_ctx) + 30 * GPR_MS_PER_SEC, + GRPC_CLOSURE_CREATE(got_port_from_server, &pr, grpc_schedule_on_exec_ctx), + &pr.response); + grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(pr.mu); + while (pr.port == -1) { + grpc_pollset_worker *worker = NULL; + if (!GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), + &worker, + grpc_exec_ctx_now(&exec_ctx) + GPR_MS_PER_SEC))) { + pr.port = 0; + } + } + gpr_mu_unlock(pr.mu); + + grpc_http_response_destroy(&pr.response); + grpc_httpcli_context_destroy(&exec_ctx, &context); + grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), + shutdown_closure); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + return pr.port; +} + +#endif // GRPC_TEST_PICK_PORT diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c deleted file mode 100644 index 9c56e02e8e..0000000000 --- a/test/core/util/reconnect_server.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/util/reconnect_server.h" - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/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; - int i = 1; - double expected_backoff = 1000.0, backoff; - timestamp_list *head = server->head; - gpr_log(GPR_INFO, "reconnect server: new connection"); - for (head = server->head; head && head->next; head = head->next, i++) { - diff = gpr_time_sub(head->next->timestamp, head->timestamp); - backoff = gpr_time_to_millis(diff); - gpr_log(GPR_INFO, - "retry %2d:backoff %6.2fs,expected backoff %6.2fs, jitter %4.2f%%", - i, backoff / 1000.0, expected_backoff / 1000.0, - (backoff - expected_backoff) * 100.0 / expected_backoff); - expected_backoff *= 1.6; - int max_reconnect_backoff_ms = 120 * 1000; - if (server->max_reconnect_backoff_ms > 0) { - max_reconnect_backoff_ms = server->max_reconnect_backoff_ms; - } - if (expected_backoff > max_reconnect_backoff_ms) { - expected_backoff = max_reconnect_backoff_ms; - } - } -} - -static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, - grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - gpr_free(acceptor); - char *peer; - char *last_colon; - reconnect_server *server = (reconnect_server *)arg; - gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); - timestamp_list *new_tail; - peer = grpc_endpoint_get_peer(tcp); - grpc_endpoint_shutdown(exec_ctx, tcp, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); - grpc_endpoint_destroy(exec_ctx, tcp); - if (peer) { - last_colon = strrchr(peer, ':'); - if (server->peer == NULL) { - server->peer = peer; - } else { - if (last_colon == NULL) { - gpr_log(GPR_ERROR, "peer does not contain a ':'"); - } else if (strncmp(server->peer, peer, (size_t)(last_colon - peer)) != - 0) { - gpr_log(GPR_ERROR, "mismatched peer! %s vs %s", server->peer, peer); - } - gpr_free(peer); - } - } - new_tail = gpr_malloc(sizeof(timestamp_list)); - new_tail->timestamp = now; - new_tail->next = NULL; - if (server->tail == NULL) { - server->head = new_tail; - server->tail = new_tail; - } else { - server->tail->next = new_tail; - server->tail = new_tail; - } - pretty_print_backoffs(server); -} - -void reconnect_server_init(reconnect_server *server) { - test_tcp_server_init(&server->tcp_server, on_connect, server); - server->head = NULL; - server->tail = NULL; - server->peer = NULL; - server->max_reconnect_backoff_ms = 0; -} - -void reconnect_server_start(reconnect_server *server, int port) { - test_tcp_server_start(&server->tcp_server, port); -} - -void reconnect_server_poll(reconnect_server *server, int seconds) { - test_tcp_server_poll(&server->tcp_server, seconds); -} - -void reconnect_server_clear_timestamps(reconnect_server *server) { - timestamp_list *new_head = server->head; - while (server->head) { - new_head = server->head->next; - gpr_free(server->head); - server->head = new_head; - } - server->tail = NULL; - gpr_free(server->peer); - server->peer = NULL; -} - -void reconnect_server_destroy(reconnect_server *server) { - reconnect_server_clear_timestamps(server); - test_tcp_server_destroy(&server->tcp_server); -} diff --git a/test/core/util/reconnect_server.cc b/test/core/util/reconnect_server.cc new file mode 100644 index 0000000000..883c02e51c --- /dev/null +++ b/test/core/util/reconnect_server.cc @@ -0,0 +1,129 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/util/reconnect_server.h" + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/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; + int i = 1; + double expected_backoff = 1000.0, backoff; + timestamp_list *head = server->head; + gpr_log(GPR_INFO, "reconnect server: new connection"); + for (head = server->head; head && head->next; head = head->next, i++) { + diff = gpr_time_sub(head->next->timestamp, head->timestamp); + backoff = gpr_time_to_millis(diff); + gpr_log(GPR_INFO, + "retry %2d:backoff %6.2fs,expected backoff %6.2fs, jitter %4.2f%%", + i, backoff / 1000.0, expected_backoff / 1000.0, + (backoff - expected_backoff) * 100.0 / expected_backoff); + expected_backoff *= 1.6; + int max_reconnect_backoff_ms = 120 * 1000; + if (server->max_reconnect_backoff_ms > 0) { + max_reconnect_backoff_ms = server->max_reconnect_backoff_ms; + } + if (expected_backoff > max_reconnect_backoff_ms) { + expected_backoff = max_reconnect_backoff_ms; + } + } +} + +static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, + grpc_pollset *accepting_pollset, + grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); + char *peer; + char *last_colon; + reconnect_server *server = (reconnect_server *)arg; + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + timestamp_list *new_tail; + peer = grpc_endpoint_get_peer(tcp); + grpc_endpoint_shutdown(exec_ctx, tcp, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected")); + grpc_endpoint_destroy(exec_ctx, tcp); + if (peer) { + last_colon = strrchr(peer, ':'); + if (server->peer == NULL) { + server->peer = peer; + } else { + if (last_colon == NULL) { + gpr_log(GPR_ERROR, "peer does not contain a ':'"); + } else if (strncmp(server->peer, peer, (size_t)(last_colon - peer)) != + 0) { + gpr_log(GPR_ERROR, "mismatched peer! %s vs %s", server->peer, peer); + } + gpr_free(peer); + } + } + new_tail = static_cast(gpr_malloc(sizeof(timestamp_list))); + new_tail->timestamp = now; + new_tail->next = NULL; + if (server->tail == NULL) { + server->head = new_tail; + server->tail = new_tail; + } else { + server->tail->next = new_tail; + server->tail = new_tail; + } + pretty_print_backoffs(server); +} + +void reconnect_server_init(reconnect_server *server) { + test_tcp_server_init(&server->tcp_server, on_connect, server); + server->head = NULL; + server->tail = NULL; + server->peer = NULL; + server->max_reconnect_backoff_ms = 0; +} + +void reconnect_server_start(reconnect_server *server, int port) { + test_tcp_server_start(&server->tcp_server, port); +} + +void reconnect_server_poll(reconnect_server *server, int seconds) { + test_tcp_server_poll(&server->tcp_server, seconds); +} + +void reconnect_server_clear_timestamps(reconnect_server *server) { + timestamp_list *new_head = server->head; + while (server->head) { + new_head = server->head->next; + gpr_free(server->head); + server->head = new_head; + } + server->tail = NULL; + gpr_free(server->peer); + server->peer = NULL; +} + +void reconnect_server_destroy(reconnect_server *server) { + reconnect_server_clear_timestamps(server); + test_tcp_server_destroy(&server->tcp_server); +} diff --git a/test/core/util/slice_splitter.c b/test/core/util/slice_splitter.c deleted file mode 100644 index 6fcef9acce..0000000000 --- a/test/core/util/slice_splitter.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/util/slice_splitter.h" - -#include - -#include -#include - -const char *grpc_slice_split_mode_name(grpc_slice_split_mode mode) { - switch (mode) { - case GRPC_SLICE_SPLIT_IDENTITY: - return "identity"; - case GRPC_SLICE_SPLIT_MERGE_ALL: - return "merge_all"; - case GRPC_SLICE_SPLIT_ONE_BYTE: - return "one_byte"; - } - return "error"; -} - -void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices, - size_t src_slice_count, grpc_slice **dst_slices, - size_t *dst_slice_count) { - size_t i, j; - size_t length; - - switch (mode) { - case GRPC_SLICE_SPLIT_IDENTITY: - *dst_slice_count = src_slice_count; - *dst_slices = - (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * src_slice_count); - for (i = 0; i < src_slice_count; i++) { - (*dst_slices)[i] = src_slices[i]; - grpc_slice_ref((*dst_slices)[i]); - } - break; - case GRPC_SLICE_SPLIT_MERGE_ALL: - *dst_slice_count = 1; - length = 0; - for (i = 0; i < src_slice_count; i++) { - length += GRPC_SLICE_LENGTH(src_slices[i]); - } - *dst_slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice)); - **dst_slices = grpc_slice_malloc(length); - length = 0; - for (i = 0; i < src_slice_count; i++) { - memcpy(GRPC_SLICE_START_PTR(**dst_slices) + length, - GRPC_SLICE_START_PTR(src_slices[i]), - GRPC_SLICE_LENGTH(src_slices[i])); - length += GRPC_SLICE_LENGTH(src_slices[i]); - } - break; - case GRPC_SLICE_SPLIT_ONE_BYTE: - length = 0; - for (i = 0; i < src_slice_count; i++) { - length += GRPC_SLICE_LENGTH(src_slices[i]); - } - *dst_slice_count = length; - *dst_slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * length); - length = 0; - for (i = 0; i < src_slice_count; i++) { - for (j = 0; j < GRPC_SLICE_LENGTH(src_slices[i]); j++) { - (*dst_slices)[length] = grpc_slice_sub(src_slices[i], j, j + 1); - length++; - } - } - break; - } -} - -void grpc_split_slices_to_buffer(grpc_slice_split_mode mode, - grpc_slice *src_slices, size_t src_slice_count, - grpc_slice_buffer *dst) { - grpc_slice *slices; - size_t nslices; - size_t i; - grpc_split_slices(mode, src_slices, src_slice_count, &slices, &nslices); - for (i = 0; i < nslices; i++) { - /* add indexed to avoid re-merging split slices */ - grpc_slice_buffer_add_indexed(dst, slices[i]); - } - gpr_free(slices); -} - -void grpc_split_slice_buffer(grpc_slice_split_mode mode, grpc_slice_buffer *src, - grpc_slice_buffer *dst) { - grpc_split_slices_to_buffer(mode, src->slices, src->count, dst); -} - -grpc_slice grpc_slice_merge(grpc_slice *slices, size_t nslices) { - uint8_t *out = NULL; - size_t length = 0; - size_t capacity = 0; - size_t i; - - for (i = 0; i < nslices; i++) { - if (GRPC_SLICE_LENGTH(slices[i]) + length > capacity) { - capacity = GPR_MAX(capacity * 2, GRPC_SLICE_LENGTH(slices[i]) + length); - out = (uint8_t *)gpr_realloc(out, capacity); - } - memcpy(out + length, GRPC_SLICE_START_PTR(slices[i]), - GRPC_SLICE_LENGTH(slices[i])); - length += GRPC_SLICE_LENGTH(slices[i]); - } - - return grpc_slice_new(out, length, gpr_free); -} diff --git a/test/core/util/slice_splitter.cc b/test/core/util/slice_splitter.cc new file mode 100644 index 0000000000..6fcef9acce --- /dev/null +++ b/test/core/util/slice_splitter.cc @@ -0,0 +1,124 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/util/slice_splitter.h" + +#include + +#include +#include + +const char *grpc_slice_split_mode_name(grpc_slice_split_mode mode) { + switch (mode) { + case GRPC_SLICE_SPLIT_IDENTITY: + return "identity"; + case GRPC_SLICE_SPLIT_MERGE_ALL: + return "merge_all"; + case GRPC_SLICE_SPLIT_ONE_BYTE: + return "one_byte"; + } + return "error"; +} + +void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices, + size_t src_slice_count, grpc_slice **dst_slices, + size_t *dst_slice_count) { + size_t i, j; + size_t length; + + switch (mode) { + case GRPC_SLICE_SPLIT_IDENTITY: + *dst_slice_count = src_slice_count; + *dst_slices = + (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * src_slice_count); + for (i = 0; i < src_slice_count; i++) { + (*dst_slices)[i] = src_slices[i]; + grpc_slice_ref((*dst_slices)[i]); + } + break; + case GRPC_SLICE_SPLIT_MERGE_ALL: + *dst_slice_count = 1; + length = 0; + for (i = 0; i < src_slice_count; i++) { + length += GRPC_SLICE_LENGTH(src_slices[i]); + } + *dst_slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice)); + **dst_slices = grpc_slice_malloc(length); + length = 0; + for (i = 0; i < src_slice_count; i++) { + memcpy(GRPC_SLICE_START_PTR(**dst_slices) + length, + GRPC_SLICE_START_PTR(src_slices[i]), + GRPC_SLICE_LENGTH(src_slices[i])); + length += GRPC_SLICE_LENGTH(src_slices[i]); + } + break; + case GRPC_SLICE_SPLIT_ONE_BYTE: + length = 0; + for (i = 0; i < src_slice_count; i++) { + length += GRPC_SLICE_LENGTH(src_slices[i]); + } + *dst_slice_count = length; + *dst_slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * length); + length = 0; + for (i = 0; i < src_slice_count; i++) { + for (j = 0; j < GRPC_SLICE_LENGTH(src_slices[i]); j++) { + (*dst_slices)[length] = grpc_slice_sub(src_slices[i], j, j + 1); + length++; + } + } + break; + } +} + +void grpc_split_slices_to_buffer(grpc_slice_split_mode mode, + grpc_slice *src_slices, size_t src_slice_count, + grpc_slice_buffer *dst) { + grpc_slice *slices; + size_t nslices; + size_t i; + grpc_split_slices(mode, src_slices, src_slice_count, &slices, &nslices); + for (i = 0; i < nslices; i++) { + /* add indexed to avoid re-merging split slices */ + grpc_slice_buffer_add_indexed(dst, slices[i]); + } + gpr_free(slices); +} + +void grpc_split_slice_buffer(grpc_slice_split_mode mode, grpc_slice_buffer *src, + grpc_slice_buffer *dst) { + grpc_split_slices_to_buffer(mode, src->slices, src->count, dst); +} + +grpc_slice grpc_slice_merge(grpc_slice *slices, size_t nslices) { + uint8_t *out = NULL; + size_t length = 0; + size_t capacity = 0; + size_t i; + + for (i = 0; i < nslices; i++) { + if (GRPC_SLICE_LENGTH(slices[i]) + length > capacity) { + capacity = GPR_MAX(capacity * 2, GRPC_SLICE_LENGTH(slices[i]) + length); + out = (uint8_t *)gpr_realloc(out, capacity); + } + memcpy(out + length, GRPC_SLICE_START_PTR(slices[i]), + GRPC_SLICE_LENGTH(slices[i])); + length += GRPC_SLICE_LENGTH(slices[i]); + } + + return grpc_slice_new(out, length, gpr_free); +} diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c deleted file mode 100644 index 536045e1c3..0000000000 --- a/test/core/util/test_config.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/util/test_config.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" - -int64_t g_fixture_slowdown_factor = 1; -int64_t g_poller_slowdown_factor = 1; - -#if GPR_GETPID_IN_UNISTD_H -#include -static unsigned seed(void) { return (unsigned)getpid(); } -#endif - -#if GPR_GETPID_IN_PROCESS_H -#include -static unsigned seed(void) { return (unsigned)_getpid(); } -#endif - -#if GPR_WINDOWS_CRASH_HANDLER -#include - -#include - -// disable warning 4091 - dbghelp.h is broken for msvc2015 -#pragma warning(disable : 4091) -#define DBGHELP_TRANSLATE_TCHAR -#include - -#ifdef _MSC_VER -#pragma comment(lib, "dbghelp.lib") -#endif - -static void print_current_stack() { - typedef USHORT(WINAPI * CaptureStackBackTraceType)( - __in ULONG, __in ULONG, __out PVOID *, __out_opt PULONG); - CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress( - LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace")); - - if (func == NULL) return; // WOE 29.SEP.2010 - -// Quote from Microsoft Documentation: -// ## Windows Server 2003 and Windows XP: -// ## The sum of the FramesToSkip and FramesToCapture parameters must be less -// than 63. -#define MAX_CALLERS 62 - - void *callers_stack[MAX_CALLERS]; - unsigned short frames; - SYMBOL_INFOW *symbol; - HANDLE process; - process = GetCurrentProcess(); - SymInitialize(process, NULL, TRUE); - frames = (func)(0, MAX_CALLERS, callers_stack, NULL); - symbol = - (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof(SYMBOL_INFOW); - - const unsigned short MAX_CALLERS_SHOWN = 32; - frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN; - for (unsigned int i = 0; i < frames; i++) { - SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol); - fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X\n", i, - (DWORD64)callers_stack[i], symbol->Name, (DWORD64)symbol->Address); - fflush(stderr); - } - - free(symbol); -} - -static void print_stack_from_context(CONTEXT c) { - STACKFRAME s; // in/out stackframe - memset(&s, 0, sizeof(s)); - DWORD imageType; -#ifdef _M_IX86 - // normally, call ImageNtHeader() and use machine info from PE header - imageType = IMAGE_FILE_MACHINE_I386; - s.AddrPC.Offset = c.Eip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Ebp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Esp; - s.AddrStack.Mode = AddrModeFlat; -#elif _M_X64 - imageType = IMAGE_FILE_MACHINE_AMD64; - s.AddrPC.Offset = c.Rip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Rsp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Rsp; - s.AddrStack.Mode = AddrModeFlat; -#elif _M_IA64 - imageType = IMAGE_FILE_MACHINE_IA64; - s.AddrPC.Offset = c.StIIP; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.IntSp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrBStore.Offset = c.RsBSP; - s.AddrBStore.Mode = AddrModeFlat; - s.AddrStack.Offset = c.IntSp; - s.AddrStack.Mode = AddrModeFlat; -#else -#error "Platform not supported!" -#endif - - HANDLE process = GetCurrentProcess(); - HANDLE thread = GetCurrentThread(); - - SYMBOL_INFOW *symbol = - (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof(SYMBOL_INFOW); - - while (StackWalk(imageType, process, thread, &s, &c, 0, - SymFunctionTableAccess, SymGetModuleBase, 0)) { - BOOL has_symbol = - SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol); - fwprintf( - stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset), - has_symbol ? symbol->Name : L"<>", (DWORD64)symbol->Address); - fflush(stderr); - } - - free(symbol); -} - -static LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) { - fprintf(stderr, "Exception handler called, dumping information\n"); - bool try_to_print_stack = true; - PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord; - while (exrec) { - DWORD code = exrec->ExceptionCode; - DWORD flgs = exrec->ExceptionFlags; - PVOID addr = exrec->ExceptionAddress; - if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false; - fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr); - exrec = exrec->ExceptionRecord; - } - if (try_to_print_stack) { - print_stack_from_context(*ex_info->ContextRecord); - } - if (IsDebuggerPresent()) { - __debugbreak(); - } else { - _exit(1); - } - return EXCEPTION_EXECUTE_HANDLER; -} - -static void abort_handler(int sig) { - fprintf(stderr, "Abort handler called.\n"); - print_current_stack(NULL); - if (IsDebuggerPresent()) { - __debugbreak(); - } else { - _exit(1); - } -} - -static void install_crash_handler() { - if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) { - fprintf(stderr, "SymInitialize failed: %d\n", GetLastError()); - } - SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler); - _set_abort_behavior(0, _WRITE_ABORT_MSG); - _set_abort_behavior(0, _CALL_REPORTFAULT); - signal(SIGABRT, abort_handler); -} -#elif GPR_POSIX_CRASH_HANDLER -#include -#include -#include -#include -#include - -#define SIGNAL_NAMES_LENGTH 32 - -static const char *const signal_names[] = { - NULL, "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", - "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV", - "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD", - "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", - "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", - "SIGPWR", "SIGSYS"}; - -static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)]; - -#define MAX_FRAMES 32 - -/* signal safe output */ -static void output_string(const char *string) { - size_t len = strlen(string); - ssize_t r; - - do { - r = write(STDERR_FILENO, string, len); - } while (r == -1 && errno == EINTR); -} - -static void output_num(long num) { - char buf[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(num, buf); - output_string(buf); -} - -static void crash_handler(int signum, siginfo_t *info, void *data) { - void *addrlist[MAX_FRAMES + 1]; - int addrlen; - - output_string("\n\n\n*******************************\nCaught signal "); - if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) { - output_string(signal_names[signum]); - } else { - output_num(signum); - } - output_string("\n"); - - addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist)); - - if (addrlen == 0) { - output_string(" no backtrace\n"); - } else { - backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO); - } - - /* try to get a core dump for SIGTERM */ - if (signum == SIGTERM) signum = SIGQUIT; - raise(signum); -} - -static void install_crash_handler() { - stack_t ss; - struct sigaction sa; - - memset(&ss, 0, sizeof(ss)); - memset(&sa, 0, sizeof(sa)); - ss.ss_size = sizeof(g_alt_stack); - ss.ss_sp = g_alt_stack; - GPR_ASSERT(sigaltstack(&ss, NULL) == 0); - sa.sa_flags = (int)(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND); - sa.sa_sigaction = crash_handler; - GPR_ASSERT(sigaction(SIGILL, &sa, NULL) == 0); - 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() {} -#endif - -bool BuiltUnderValgrind() { -#ifdef RUNNING_ON_VALGRIND - return true; -#else - return false; -#endif -} - -bool BuiltUnderTsan() { -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) - return true; -#else - return false; -#endif -#else -#ifdef THREAD_SANITIZER - return true; -#else - return false; -#endif -#endif -} - -bool BuiltUnderAsan() { -#if defined(__has_feature) -#if __has_feature(address_sanitizer) - return true; -#else - return false; -#endif -#else -#ifdef ADDRESS_SANITIZER - return true; -#else - return false; -#endif -#endif -} - -bool BuiltUnderMsan() { -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) - return true; -#else - return false; -#endif -#else -#ifdef MEMORY_SANITIZER - return true; -#else - return false; -#endif -#endif -} - -bool BuiltUnderUbsan() { -#ifdef GRPC_UBSAN - return true; -#else - return false; -#endif -} - -int64_t grpc_test_sanitizer_slowdown_factor() { - int64_t sanitizer_multiplier = 1; - if (BuiltUnderValgrind()) { - sanitizer_multiplier = 20; - } else if (BuiltUnderTsan()) { - sanitizer_multiplier = 5; - } else if (BuiltUnderAsan()) { - sanitizer_multiplier = 3; - } else if (BuiltUnderMsan()) { - sanitizer_multiplier = 4; - } else if (BuiltUnderUbsan()) { - sanitizer_multiplier = 5; - } - return sanitizer_multiplier; -} - -int64_t grpc_test_slowdown_factor() { - return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor * - g_poller_slowdown_factor; -} - -gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) { - return gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis(grpc_test_slowdown_factor() * (int64_t)1e3 * time_s, - GPR_TIMESPAN)); -} - -gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) { - return gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_micros(grpc_test_slowdown_factor() * (int64_t)1e3 * time_ms, - GPR_TIMESPAN)); -} - -void grpc_test_init(int argc, char **argv) { - install_crash_handler(); - { /* poll-cv poll strategy runs much more slowly than anything else */ - char *s = gpr_getenv("GRPC_POLL_STRATEGY"); - if (s != NULL && 0 == strcmp(s, "poll-cv")) { - g_poller_slowdown_factor = 5; - } - gpr_free(s); - } - gpr_log(GPR_DEBUG, - "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64 - ", poller=%" PRId64 ", total=%" PRId64, - grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor, - g_poller_slowdown_factor, grpc_test_slowdown_factor()); - /* seed rng with pid, so we don't end up with the same random numbers as a - concurrently running test binary */ - srand(seed()); -} diff --git a/test/core/util/test_config.cc b/test/core/util/test_config.cc new file mode 100644 index 0000000000..536045e1c3 --- /dev/null +++ b/test/core/util/test_config.cc @@ -0,0 +1,396 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test/core/util/test_config.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" + +int64_t g_fixture_slowdown_factor = 1; +int64_t g_poller_slowdown_factor = 1; + +#if GPR_GETPID_IN_UNISTD_H +#include +static unsigned seed(void) { return (unsigned)getpid(); } +#endif + +#if GPR_GETPID_IN_PROCESS_H +#include +static unsigned seed(void) { return (unsigned)_getpid(); } +#endif + +#if GPR_WINDOWS_CRASH_HANDLER +#include + +#include + +// disable warning 4091 - dbghelp.h is broken for msvc2015 +#pragma warning(disable : 4091) +#define DBGHELP_TRANSLATE_TCHAR +#include + +#ifdef _MSC_VER +#pragma comment(lib, "dbghelp.lib") +#endif + +static void print_current_stack() { + typedef USHORT(WINAPI * CaptureStackBackTraceType)( + __in ULONG, __in ULONG, __out PVOID *, __out_opt PULONG); + CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress( + LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace")); + + if (func == NULL) return; // WOE 29.SEP.2010 + +// Quote from Microsoft Documentation: +// ## Windows Server 2003 and Windows XP: +// ## The sum of the FramesToSkip and FramesToCapture parameters must be less +// than 63. +#define MAX_CALLERS 62 + + void *callers_stack[MAX_CALLERS]; + unsigned short frames; + SYMBOL_INFOW *symbol; + HANDLE process; + process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + frames = (func)(0, MAX_CALLERS, callers_stack, NULL); + symbol = + (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFOW); + + const unsigned short MAX_CALLERS_SHOWN = 32; + frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN; + for (unsigned int i = 0; i < frames; i++) { + SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol); + fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X\n", i, + (DWORD64)callers_stack[i], symbol->Name, (DWORD64)symbol->Address); + fflush(stderr); + } + + free(symbol); +} + +static void print_stack_from_context(CONTEXT c) { + STACKFRAME s; // in/out stackframe + memset(&s, 0, sizeof(s)); + DWORD imageType; +#ifdef _M_IX86 + // normally, call ImageNtHeader() and use machine info from PE header + imageType = IMAGE_FILE_MACHINE_I386; + s.AddrPC.Offset = c.Eip; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.Ebp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrStack.Offset = c.Esp; + s.AddrStack.Mode = AddrModeFlat; +#elif _M_X64 + imageType = IMAGE_FILE_MACHINE_AMD64; + s.AddrPC.Offset = c.Rip; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.Rsp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrStack.Offset = c.Rsp; + s.AddrStack.Mode = AddrModeFlat; +#elif _M_IA64 + imageType = IMAGE_FILE_MACHINE_IA64; + s.AddrPC.Offset = c.StIIP; + s.AddrPC.Mode = AddrModeFlat; + s.AddrFrame.Offset = c.IntSp; + s.AddrFrame.Mode = AddrModeFlat; + s.AddrBStore.Offset = c.RsBSP; + s.AddrBStore.Mode = AddrModeFlat; + s.AddrStack.Offset = c.IntSp; + s.AddrStack.Mode = AddrModeFlat; +#else +#error "Platform not supported!" +#endif + + HANDLE process = GetCurrentProcess(); + HANDLE thread = GetCurrentThread(); + + SYMBOL_INFOW *symbol = + (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFOW); + + while (StackWalk(imageType, process, thread, &s, &c, 0, + SymFunctionTableAccess, SymGetModuleBase, 0)) { + BOOL has_symbol = + SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol); + fwprintf( + stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset), + has_symbol ? symbol->Name : L"<>", (DWORD64)symbol->Address); + fflush(stderr); + } + + free(symbol); +} + +static LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) { + fprintf(stderr, "Exception handler called, dumping information\n"); + bool try_to_print_stack = true; + PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord; + while (exrec) { + DWORD code = exrec->ExceptionCode; + DWORD flgs = exrec->ExceptionFlags; + PVOID addr = exrec->ExceptionAddress; + if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false; + fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr); + exrec = exrec->ExceptionRecord; + } + if (try_to_print_stack) { + print_stack_from_context(*ex_info->ContextRecord); + } + if (IsDebuggerPresent()) { + __debugbreak(); + } else { + _exit(1); + } + return EXCEPTION_EXECUTE_HANDLER; +} + +static void abort_handler(int sig) { + fprintf(stderr, "Abort handler called.\n"); + print_current_stack(NULL); + if (IsDebuggerPresent()) { + __debugbreak(); + } else { + _exit(1); + } +} + +static void install_crash_handler() { + if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) { + fprintf(stderr, "SymInitialize failed: %d\n", GetLastError()); + } + SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler); + _set_abort_behavior(0, _WRITE_ABORT_MSG); + _set_abort_behavior(0, _CALL_REPORTFAULT); + signal(SIGABRT, abort_handler); +} +#elif GPR_POSIX_CRASH_HANDLER +#include +#include +#include +#include +#include + +#define SIGNAL_NAMES_LENGTH 32 + +static const char *const signal_names[] = { + NULL, "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", + "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV", + "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD", + "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", + "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", + "SIGPWR", "SIGSYS"}; + +static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)]; + +#define MAX_FRAMES 32 + +/* signal safe output */ +static void output_string(const char *string) { + size_t len = strlen(string); + ssize_t r; + + do { + r = write(STDERR_FILENO, string, len); + } while (r == -1 && errno == EINTR); +} + +static void output_num(long num) { + char buf[GPR_LTOA_MIN_BUFSIZE]; + gpr_ltoa(num, buf); + output_string(buf); +} + +static void crash_handler(int signum, siginfo_t *info, void *data) { + void *addrlist[MAX_FRAMES + 1]; + int addrlen; + + output_string("\n\n\n*******************************\nCaught signal "); + if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) { + output_string(signal_names[signum]); + } else { + output_num(signum); + } + output_string("\n"); + + addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist)); + + if (addrlen == 0) { + output_string(" no backtrace\n"); + } else { + backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO); + } + + /* try to get a core dump for SIGTERM */ + if (signum == SIGTERM) signum = SIGQUIT; + raise(signum); +} + +static void install_crash_handler() { + stack_t ss; + struct sigaction sa; + + memset(&ss, 0, sizeof(ss)); + memset(&sa, 0, sizeof(sa)); + ss.ss_size = sizeof(g_alt_stack); + ss.ss_sp = g_alt_stack; + GPR_ASSERT(sigaltstack(&ss, NULL) == 0); + sa.sa_flags = (int)(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND); + sa.sa_sigaction = crash_handler; + GPR_ASSERT(sigaction(SIGILL, &sa, NULL) == 0); + 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() {} +#endif + +bool BuiltUnderValgrind() { +#ifdef RUNNING_ON_VALGRIND + return true; +#else + return false; +#endif +} + +bool BuiltUnderTsan() { +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) + return true; +#else + return false; +#endif +#else +#ifdef THREAD_SANITIZER + return true; +#else + return false; +#endif +#endif +} + +bool BuiltUnderAsan() { +#if defined(__has_feature) +#if __has_feature(address_sanitizer) + return true; +#else + return false; +#endif +#else +#ifdef ADDRESS_SANITIZER + return true; +#else + return false; +#endif +#endif +} + +bool BuiltUnderMsan() { +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + return true; +#else + return false; +#endif +#else +#ifdef MEMORY_SANITIZER + return true; +#else + return false; +#endif +#endif +} + +bool BuiltUnderUbsan() { +#ifdef GRPC_UBSAN + return true; +#else + return false; +#endif +} + +int64_t grpc_test_sanitizer_slowdown_factor() { + int64_t sanitizer_multiplier = 1; + if (BuiltUnderValgrind()) { + sanitizer_multiplier = 20; + } else if (BuiltUnderTsan()) { + sanitizer_multiplier = 5; + } else if (BuiltUnderAsan()) { + sanitizer_multiplier = 3; + } else if (BuiltUnderMsan()) { + sanitizer_multiplier = 4; + } else if (BuiltUnderUbsan()) { + sanitizer_multiplier = 5; + } + return sanitizer_multiplier; +} + +int64_t grpc_test_slowdown_factor() { + return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor * + g_poller_slowdown_factor; +} + +gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) { + return gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(grpc_test_slowdown_factor() * (int64_t)1e3 * time_s, + GPR_TIMESPAN)); +} + +gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) { + return gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_micros(grpc_test_slowdown_factor() * (int64_t)1e3 * time_ms, + GPR_TIMESPAN)); +} + +void grpc_test_init(int argc, char **argv) { + install_crash_handler(); + { /* poll-cv poll strategy runs much more slowly than anything else */ + char *s = gpr_getenv("GRPC_POLL_STRATEGY"); + if (s != NULL && 0 == strcmp(s, "poll-cv")) { + g_poller_slowdown_factor = 5; + } + gpr_free(s); + } + gpr_log(GPR_DEBUG, + "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64 + ", poller=%" PRId64 ", total=%" PRId64, + grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor, + g_poller_slowdown_factor, grpc_test_slowdown_factor()); + /* seed rng with pid, so we don't end up with the same random numbers as a + concurrently running test binary */ + srand(seed()); +} diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c deleted file mode 100644 index 611ecb330c..0000000000 --- a/test/core/util/test_tcp_server.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/sockaddr.h" - -#include "test/core/util/test_tcp_server.h" - -#include -#include -#include -#include -#include -#include -#include -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_server.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data, - grpc_error *error) { - test_tcp_server *server = data; - server->shutdown = 1; -} - -void test_tcp_server_init(test_tcp_server *server, - grpc_tcp_server_cb on_connect, void *user_data) { - grpc_init(); - server->tcp_server = NULL; - GRPC_CLOSURE_INIT(&server->shutdown_complete, on_server_destroyed, server, - grpc_schedule_on_exec_ctx); - server->shutdown = 0; - server->pollset = gpr_zalloc(grpc_pollset_size()); - grpc_pollset_init(server->pollset, &server->mu); - server->on_connect = on_connect; - server->cb_data = user_data; -} - -void test_tcp_server_start(test_tcp_server *server, int port) { - grpc_resolved_address resolved_addr; - struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; - int port_added; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - addr->sin_family = AF_INET; - addr->sin_port = htons((uint16_t)port); - memset(&addr->sin_addr, 0, sizeof(addr->sin_addr)); - - grpc_error *error = grpc_tcp_server_create( - &exec_ctx, &server->shutdown_complete, NULL, &server->tcp_server); - GPR_ASSERT(error == GRPC_ERROR_NONE); - error = - grpc_tcp_server_add_port(server->tcp_server, &resolved_addr, &port_added); - GPR_ASSERT(error == GRPC_ERROR_NONE); - GPR_ASSERT(port_added == port); - - grpc_tcp_server_start(&exec_ctx, server->tcp_server, &server->pollset, 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 = NULL; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_millis deadline = grpc_timespec_to_millis_round_up( - grpc_timeout_seconds_to_deadline(seconds)); - gpr_mu_lock(server->mu); - GRPC_LOG_IF_ERROR( - "pollset_work", - grpc_pollset_work(&exec_ctx, server->pollset, &worker, deadline)); - gpr_mu_unlock(server->mu); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} -static void finish_pollset(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_pollset_destroy(exec_ctx, arg); -} - -void test_tcp_server_destroy(test_tcp_server *server) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - gpr_timespec shutdown_deadline; - grpc_closure do_nothing_cb; - grpc_tcp_server_unref(&exec_ctx, server->tcp_server); - GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, - grpc_schedule_on_exec_ctx); - 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, - GRPC_CLOSURE_CREATE(finish_pollset, server->pollset, - grpc_schedule_on_exec_ctx)); - grpc_exec_ctx_finish(&exec_ctx); - gpr_free(server->pollset); - grpc_shutdown(); -} diff --git a/test/core/util/test_tcp_server.cc b/test/core/util/test_tcp_server.cc new file mode 100644 index 0000000000..e2d1562aca --- /dev/null +++ b/test/core/util/test_tcp_server.cc @@ -0,0 +1,119 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/sockaddr.h" + +#include "test/core/util/test_tcp_server.h" + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/tcp_server.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data, + grpc_error *error) { + test_tcp_server *server = static_cast(data); + server->shutdown = 1; +} + +void test_tcp_server_init(test_tcp_server *server, + grpc_tcp_server_cb on_connect, void *user_data) { + grpc_init(); + server->tcp_server = NULL; + GRPC_CLOSURE_INIT(&server->shutdown_complete, on_server_destroyed, server, + grpc_schedule_on_exec_ctx); + server->shutdown = 0; + server->pollset = + static_cast(gpr_zalloc(grpc_pollset_size())); + grpc_pollset_init(server->pollset, &server->mu); + server->on_connect = on_connect; + server->cb_data = user_data; +} + +void test_tcp_server_start(test_tcp_server *server, int port) { + grpc_resolved_address resolved_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; + int port_added; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + addr->sin_family = AF_INET; + addr->sin_port = htons((uint16_t)port); + memset(&addr->sin_addr, 0, sizeof(addr->sin_addr)); + + grpc_error *error = grpc_tcp_server_create( + &exec_ctx, &server->shutdown_complete, NULL, &server->tcp_server); + GPR_ASSERT(error == GRPC_ERROR_NONE); + error = + grpc_tcp_server_add_port(server->tcp_server, &resolved_addr, &port_added); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(port_added == port); + + grpc_tcp_server_start(&exec_ctx, server->tcp_server, &server->pollset, 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 = NULL; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_millis deadline = grpc_timespec_to_millis_round_up( + grpc_timeout_seconds_to_deadline(seconds)); + gpr_mu_lock(server->mu); + GRPC_LOG_IF_ERROR( + "pollset_work", + grpc_pollset_work(&exec_ctx, server->pollset, &worker, deadline)); + gpr_mu_unlock(server->mu); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} +static void finish_pollset(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, static_cast(arg)); +} + +void test_tcp_server_destroy(test_tcp_server *server) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_timespec shutdown_deadline; + grpc_closure do_nothing_cb; + grpc_tcp_server_unref(&exec_ctx, server->tcp_server); + GRPC_CLOSURE_INIT(&do_nothing_cb, do_nothing, NULL, + grpc_schedule_on_exec_ctx); + 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, + GRPC_CLOSURE_CREATE(finish_pollset, server->pollset, + grpc_schedule_on_exec_ctx)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(server->pollset); + grpc_shutdown(); +} diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c deleted file mode 100644 index fc066f9d80..0000000000 --- a/test/core/util/trickle_endpoint.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/sockaddr.h" - -#include "test/core/util/passthru_endpoint.h" - -#include -#include - -#include -#include -#include -#include -#include "src/core/lib/slice/slice_internal.h" - -#define WRITE_BUFFER_SIZE (2 * 1024 * 1024) - -typedef struct { - grpc_endpoint base; - double bytes_per_second; - grpc_endpoint *wrapped; - gpr_timespec last_write; - - gpr_mu mu; - grpc_slice_buffer write_buffer; - grpc_slice_buffer writing_buffer; - grpc_error *error; - bool writing; - grpc_closure *write_cb; -} trickle_endpoint; - -static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - trickle_endpoint *te = (trickle_endpoint *)ep; - grpc_endpoint_read(exec_ctx, te->wrapped, slices, cb); -} - -static void maybe_call_write_cb_locked(grpc_exec_ctx *exec_ctx, - trickle_endpoint *te) { - if (te->write_cb != NULL && (te->error != GRPC_ERROR_NONE || - te->write_buffer.length <= WRITE_BUFFER_SIZE)) { - GRPC_CLOSURE_SCHED(exec_ctx, te->write_cb, GRPC_ERROR_REF(te->error)); - te->write_cb = NULL; - } -} - -static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_slice_buffer *slices, grpc_closure *cb) { - trickle_endpoint *te = (trickle_endpoint *)ep; - gpr_mu_lock(&te->mu); - GPR_ASSERT(te->write_cb == NULL); - if (te->write_buffer.length == 0) { - te->last_write = gpr_now(GPR_CLOCK_MONOTONIC); - } - for (size_t i = 0; i < slices->count; i++) { - grpc_slice_buffer_add(&te->write_buffer, - grpc_slice_copy(slices->slices[i])); - } - te->write_cb = cb; - maybe_call_write_cb_locked(exec_ctx, te); - gpr_mu_unlock(&te->mu); -} - -static void te_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset *pollset) { - trickle_endpoint *te = (trickle_endpoint *)ep; - grpc_endpoint_add_to_pollset(exec_ctx, te->wrapped, pollset); -} - -static void te_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_pollset_set *pollset_set) { - trickle_endpoint *te = (trickle_endpoint *)ep; - grpc_endpoint_add_to_pollset_set(exec_ctx, te->wrapped, pollset_set); -} - -static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, - grpc_error *why) { - trickle_endpoint *te = (trickle_endpoint *)ep; - gpr_mu_lock(&te->mu); - if (te->error == GRPC_ERROR_NONE) { - te->error = GRPC_ERROR_REF(why); - } - maybe_call_write_cb_locked(exec_ctx, te); - gpr_mu_unlock(&te->mu); - grpc_endpoint_shutdown(exec_ctx, te->wrapped, why); -} - -static void te_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - grpc_endpoint_destroy(exec_ctx, te->wrapped); - gpr_mu_destroy(&te->mu); - grpc_slice_buffer_destroy_internal(exec_ctx, &te->write_buffer); - grpc_slice_buffer_destroy_internal(exec_ctx, &te->writing_buffer); - GRPC_ERROR_UNREF(te->error); - gpr_free(te); -} - -static grpc_resource_user *te_get_resource_user(grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - return grpc_endpoint_get_resource_user(te->wrapped); -} - -static char *te_get_peer(grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - return grpc_endpoint_get_peer(te->wrapped); -} - -static int te_get_fd(grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - return grpc_endpoint_get_fd(te->wrapped); -} - -static void te_finish_write(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - trickle_endpoint *te = (trickle_endpoint *)arg; - gpr_mu_lock(&te->mu); - te->writing = false; - grpc_slice_buffer_reset_and_unref(&te->writing_buffer); - gpr_mu_unlock(&te->mu); -} - -static const grpc_endpoint_vtable vtable = { - te_read, te_write, te_add_to_pollset, te_add_to_pollset_set, - te_shutdown, te_destroy, te_get_resource_user, te_get_peer, - te_get_fd}; - -grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, - double bytes_per_second) { - trickle_endpoint *te = (trickle_endpoint *)gpr_malloc(sizeof(*te)); - te->base.vtable = &vtable; - te->wrapped = wrap; - te->bytes_per_second = bytes_per_second; - te->write_cb = NULL; - gpr_mu_init(&te->mu); - grpc_slice_buffer_init(&te->write_buffer); - grpc_slice_buffer_init(&te->writing_buffer); - te->error = GRPC_ERROR_NONE; - te->writing = false; - return &te->base; -} - -static double ts2dbl(gpr_timespec s) { - return (double)s.tv_sec + 1e-9 * (double)s.tv_nsec; -} - -size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, - grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - gpr_mu_lock(&te->mu); - if (!te->writing && te->write_buffer.length > 0) { - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - double elapsed = ts2dbl(gpr_time_sub(now, te->last_write)); - size_t bytes = (size_t)(te->bytes_per_second * elapsed); - // gpr_log(GPR_DEBUG, "%lf elapsed --> %" PRIdPTR " bytes", elapsed, bytes); - if (bytes > 0) { - grpc_slice_buffer_move_first(&te->write_buffer, - GPR_MIN(bytes, te->write_buffer.length), - &te->writing_buffer); - te->writing = true; - te->last_write = now; - grpc_endpoint_write( - exec_ctx, te->wrapped, &te->writing_buffer, - GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx)); - maybe_call_write_cb_locked(exec_ctx, te); - } - } - size_t backlog = te->write_buffer.length; - gpr_mu_unlock(&te->mu); - return backlog; -} - -size_t grpc_trickle_get_backlog(grpc_endpoint *ep) { - trickle_endpoint *te = (trickle_endpoint *)ep; - gpr_mu_lock(&te->mu); - size_t backlog = te->write_buffer.length; - gpr_mu_unlock(&te->mu); - return backlog; -} diff --git a/test/core/util/trickle_endpoint.cc b/test/core/util/trickle_endpoint.cc new file mode 100644 index 0000000000..fc066f9d80 --- /dev/null +++ b/test/core/util/trickle_endpoint.cc @@ -0,0 +1,194 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/sockaddr.h" + +#include "test/core/util/passthru_endpoint.h" + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/slice/slice_internal.h" + +#define WRITE_BUFFER_SIZE (2 * 1024 * 1024) + +typedef struct { + grpc_endpoint base; + double bytes_per_second; + grpc_endpoint *wrapped; + gpr_timespec last_write; + + gpr_mu mu; + grpc_slice_buffer write_buffer; + grpc_slice_buffer writing_buffer; + grpc_error *error; + bool writing; + grpc_closure *write_cb; +} trickle_endpoint; + +static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + trickle_endpoint *te = (trickle_endpoint *)ep; + grpc_endpoint_read(exec_ctx, te->wrapped, slices, cb); +} + +static void maybe_call_write_cb_locked(grpc_exec_ctx *exec_ctx, + trickle_endpoint *te) { + if (te->write_cb != NULL && (te->error != GRPC_ERROR_NONE || + te->write_buffer.length <= WRITE_BUFFER_SIZE)) { + GRPC_CLOSURE_SCHED(exec_ctx, te->write_cb, GRPC_ERROR_REF(te->error)); + te->write_cb = NULL; + } +} + +static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_slice_buffer *slices, grpc_closure *cb) { + trickle_endpoint *te = (trickle_endpoint *)ep; + gpr_mu_lock(&te->mu); + GPR_ASSERT(te->write_cb == NULL); + if (te->write_buffer.length == 0) { + te->last_write = gpr_now(GPR_CLOCK_MONOTONIC); + } + for (size_t i = 0; i < slices->count; i++) { + grpc_slice_buffer_add(&te->write_buffer, + grpc_slice_copy(slices->slices[i])); + } + te->write_cb = cb; + maybe_call_write_cb_locked(exec_ctx, te); + gpr_mu_unlock(&te->mu); +} + +static void te_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset *pollset) { + trickle_endpoint *te = (trickle_endpoint *)ep; + grpc_endpoint_add_to_pollset(exec_ctx, te->wrapped, pollset); +} + +static void te_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { + trickle_endpoint *te = (trickle_endpoint *)ep; + grpc_endpoint_add_to_pollset_set(exec_ctx, te->wrapped, pollset_set); +} + +static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_error *why) { + trickle_endpoint *te = (trickle_endpoint *)ep; + gpr_mu_lock(&te->mu); + if (te->error == GRPC_ERROR_NONE) { + te->error = GRPC_ERROR_REF(why); + } + maybe_call_write_cb_locked(exec_ctx, te); + gpr_mu_unlock(&te->mu); + grpc_endpoint_shutdown(exec_ctx, te->wrapped, why); +} + +static void te_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + grpc_endpoint_destroy(exec_ctx, te->wrapped); + gpr_mu_destroy(&te->mu); + grpc_slice_buffer_destroy_internal(exec_ctx, &te->write_buffer); + grpc_slice_buffer_destroy_internal(exec_ctx, &te->writing_buffer); + GRPC_ERROR_UNREF(te->error); + gpr_free(te); +} + +static grpc_resource_user *te_get_resource_user(grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + return grpc_endpoint_get_resource_user(te->wrapped); +} + +static char *te_get_peer(grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + return grpc_endpoint_get_peer(te->wrapped); +} + +static int te_get_fd(grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + return grpc_endpoint_get_fd(te->wrapped); +} + +static void te_finish_write(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + trickle_endpoint *te = (trickle_endpoint *)arg; + gpr_mu_lock(&te->mu); + te->writing = false; + grpc_slice_buffer_reset_and_unref(&te->writing_buffer); + gpr_mu_unlock(&te->mu); +} + +static const grpc_endpoint_vtable vtable = { + te_read, te_write, te_add_to_pollset, te_add_to_pollset_set, + te_shutdown, te_destroy, te_get_resource_user, te_get_peer, + te_get_fd}; + +grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, + double bytes_per_second) { + trickle_endpoint *te = (trickle_endpoint *)gpr_malloc(sizeof(*te)); + te->base.vtable = &vtable; + te->wrapped = wrap; + te->bytes_per_second = bytes_per_second; + te->write_cb = NULL; + gpr_mu_init(&te->mu); + grpc_slice_buffer_init(&te->write_buffer); + grpc_slice_buffer_init(&te->writing_buffer); + te->error = GRPC_ERROR_NONE; + te->writing = false; + return &te->base; +} + +static double ts2dbl(gpr_timespec s) { + return (double)s.tv_sec + 1e-9 * (double)s.tv_nsec; +} + +size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + gpr_mu_lock(&te->mu); + if (!te->writing && te->write_buffer.length > 0) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + double elapsed = ts2dbl(gpr_time_sub(now, te->last_write)); + size_t bytes = (size_t)(te->bytes_per_second * elapsed); + // gpr_log(GPR_DEBUG, "%lf elapsed --> %" PRIdPTR " bytes", elapsed, bytes); + if (bytes > 0) { + grpc_slice_buffer_move_first(&te->write_buffer, + GPR_MIN(bytes, te->write_buffer.length), + &te->writing_buffer); + te->writing = true; + te->last_write = now; + grpc_endpoint_write( + exec_ctx, te->wrapped, &te->writing_buffer, + GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx)); + maybe_call_write_cb_locked(exec_ctx, te); + } + } + size_t backlog = te->write_buffer.length; + gpr_mu_unlock(&te->mu); + return backlog; +} + +size_t grpc_trickle_get_backlog(grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + gpr_mu_lock(&te->mu); + size_t backlog = te->write_buffer.length; + gpr_mu_unlock(&te->mu); + return backlog; +} diff --git a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh index c471344157..5e26dd8387 100755 --- a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh +++ b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh @@ -29,7 +29,7 @@ for dir in $DIRS do for glob in $GLOB do - files="$files `find ${CLANG_FORMAT_ROOT}/$dir -name $glob -and -not -name *.generated.* -and -not -name *.pb.h -and -not -name *.pb.c -and -not -name *.pb.cc -and -not -name end2end_tests.c -and -not -name end2end_nosec_tests.c`" + files="$files `find ${CLANG_FORMAT_ROOT}/$dir -name $glob -and -not -name *.generated.* -and -not -name *.pb.h -and -not -name *.pb.c -and -not -name *.pb.cc -and -not -name end2end_tests.cc -and -not -name end2end_nosec_tests.cc`" done done diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7fa3d28834..31908d2770 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -13,7 +13,7 @@ "language": "c", "name": "alarm_test", "src": [ - "test/core/surface/alarm_test.c" + "test/core/surface/alarm_test.cc" ], "third_party": false, "type": "target" @@ -30,7 +30,7 @@ "language": "c", "name": "algorithm_test", "src": [ - "test/core/compression/algorithm_test.c" + "test/core/compression/algorithm_test.cc" ], "third_party": false, "type": "target" @@ -45,7 +45,7 @@ "language": "c", "name": "alloc_test", "src": [ - "test/core/support/alloc_test.c" + "test/core/support/alloc_test.cc" ], "third_party": false, "type": "target" @@ -62,7 +62,7 @@ "language": "c", "name": "alpn_test", "src": [ - "test/core/transport/chttp2/alpn_test.c" + "test/core/transport/chttp2/alpn_test.cc" ], "third_party": false, "type": "target" @@ -79,7 +79,7 @@ "language": "c", "name": "api_fuzzer", "src": [ - "test/core/end2end/fuzzers/api_fuzzer.c" + "test/core/end2end/fuzzers/api_fuzzer.cc" ], "third_party": false, "type": "target" @@ -94,7 +94,7 @@ "language": "c", "name": "arena_test", "src": [ - "test/core/support/arena_test.c" + "test/core/support/arena_test.cc" ], "third_party": false, "type": "target" @@ -111,7 +111,7 @@ "language": "c", "name": "backoff_test", "src": [ - "test/core/backoff/backoff_test.c" + "test/core/backoff/backoff_test.cc" ], "third_party": false, "type": "target" @@ -129,7 +129,7 @@ "language": "c", "name": "bad_server_response_test", "src": [ - "test/core/end2end/bad_server_response_test.c" + "test/core/end2end/bad_server_response_test.cc" ], "third_party": false, "type": "target" @@ -144,7 +144,7 @@ "language": "c", "name": "bin_decoder_test", "src": [ - "test/core/transport/chttp2/bin_decoder_test.c" + "test/core/transport/chttp2/bin_decoder_test.cc" ], "third_party": false, "type": "target" @@ -159,7 +159,7 @@ "language": "c", "name": "bin_encoder_test", "src": [ - "test/core/transport/chttp2/bin_encoder_test.c" + "test/core/transport/chttp2/bin_encoder_test.cc" ], "third_party": false, "type": "target" @@ -176,7 +176,7 @@ "language": "c", "name": "byte_stream_test", "src": [ - "test/core/transport/byte_stream_test.c" + "test/core/transport/byte_stream_test.cc" ], "third_party": false, "type": "target" @@ -193,7 +193,7 @@ "language": "c", "name": "census_context_test", "src": [ - "test/core/census/context_test.c" + "test/core/census/context_test.cc" ], "third_party": false, "type": "target" @@ -210,7 +210,7 @@ "language": "c", "name": "census_intrusive_hash_map_test", "src": [ - "test/core/census/intrusive_hash_map_test.c" + "test/core/census/intrusive_hash_map_test.cc" ], "third_party": false, "type": "target" @@ -227,7 +227,7 @@ "language": "c", "name": "census_resource_test", "src": [ - "test/core/census/resource_test.c" + "test/core/census/resource_test.cc" ], "third_party": false, "type": "target" @@ -244,7 +244,7 @@ "language": "c", "name": "census_trace_context_test", "src": [ - "test/core/census/trace_context_test.c" + "test/core/census/trace_context_test.cc" ], "third_party": false, "type": "target" @@ -261,7 +261,7 @@ "language": "c", "name": "channel_create_test", "src": [ - "test/core/surface/channel_create_test.c" + "test/core/surface/channel_create_test.cc" ], "third_party": false, "type": "target" @@ -276,7 +276,7 @@ "language": "c", "name": "check_epollexclusive", "src": [ - "test/build/check_epollexclusive.c" + "test/build/check_epollexclusive.cc" ], "third_party": false, "type": "target" @@ -293,7 +293,7 @@ "language": "c", "name": "chttp2_hpack_encoder_test", "src": [ - "test/core/transport/chttp2/hpack_encoder_test.c" + "test/core/transport/chttp2/hpack_encoder_test.cc" ], "third_party": false, "type": "target" @@ -310,7 +310,7 @@ "language": "c", "name": "chttp2_stream_map_test", "src": [ - "test/core/transport/chttp2/stream_map_test.c" + "test/core/transport/chttp2/stream_map_test.cc" ], "third_party": false, "type": "target" @@ -327,7 +327,7 @@ "language": "c", "name": "chttp2_varint_test", "src": [ - "test/core/transport/chttp2/varint_test.c" + "test/core/transport/chttp2/varint_test.cc" ], "third_party": false, "type": "target" @@ -344,7 +344,7 @@ "language": "c", "name": "client_fuzzer", "src": [ - "test/core/end2end/fuzzers/client_fuzzer.c" + "test/core/end2end/fuzzers/client_fuzzer.cc" ], "third_party": false, "type": "target" @@ -361,7 +361,7 @@ "language": "c", "name": "combiner_test", "src": [ - "test/core/iomgr/combiner_test.c" + "test/core/iomgr/combiner_test.cc" ], "third_party": false, "type": "target" @@ -378,7 +378,7 @@ "language": "c", "name": "compression_test", "src": [ - "test/core/compression/compression_test.c" + "test/core/compression/compression_test.cc" ], "third_party": false, "type": "target" @@ -395,7 +395,7 @@ "language": "c", "name": "concurrent_connectivity_test", "src": [ - "test/core/surface/concurrent_connectivity_test.c" + "test/core/surface/concurrent_connectivity_test.cc" ], "third_party": false, "type": "target" @@ -412,7 +412,7 @@ "language": "c", "name": "connection_refused_test", "src": [ - "test/core/end2end/connection_refused_test.c" + "test/core/end2end/connection_refused_test.cc" ], "third_party": false, "type": "target" @@ -429,7 +429,7 @@ "language": "c", "name": "dns_resolver_connectivity_test", "src": [ - "test/core/client_channel/resolvers/dns_resolver_connectivity_test.c" + "test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc" ], "third_party": false, "type": "target" @@ -446,7 +446,7 @@ "language": "c", "name": "dns_resolver_test", "src": [ - "test/core/client_channel/resolvers/dns_resolver_test.c" + "test/core/client_channel/resolvers/dns_resolver_test.cc" ], "third_party": false, "type": "target" @@ -463,7 +463,7 @@ "language": "c", "name": "dualstack_socket_test", "src": [ - "test/core/end2end/dualstack_socket_test.c" + "test/core/end2end/dualstack_socket_test.cc" ], "third_party": false, "type": "target" @@ -480,7 +480,7 @@ "language": "c", "name": "endpoint_pair_test", "src": [ - "test/core/iomgr/endpoint_pair_test.c" + "test/core/iomgr/endpoint_pair_test.cc" ], "third_party": false, "type": "target" @@ -497,7 +497,7 @@ "language": "c", "name": "error_test", "src": [ - "test/core/iomgr/error_test.c" + "test/core/iomgr/error_test.cc" ], "third_party": false, "type": "target" @@ -514,7 +514,7 @@ "language": "c", "name": "ev_epollsig_linux_test", "src": [ - "test/core/iomgr/ev_epollsig_linux_test.c" + "test/core/iomgr/ev_epollsig_linux_test.cc" ], "third_party": false, "type": "target" @@ -531,7 +531,7 @@ "language": "c", "name": "fake_resolver_test", "src": [ - "test/core/client_channel/resolvers/fake_resolver_test.c" + "test/core/client_channel/resolvers/fake_resolver_test.cc" ], "third_party": false, "type": "target" @@ -548,7 +548,7 @@ "language": "c", "name": "fake_transport_security_test", "src": [ - "test/core/tsi/fake_transport_security_test.c" + "test/core/tsi/fake_transport_security_test.cc" ], "third_party": false, "type": "target" @@ -565,7 +565,7 @@ "language": "c", "name": "fd_conservation_posix_test", "src": [ - "test/core/iomgr/fd_conservation_posix_test.c" + "test/core/iomgr/fd_conservation_posix_test.cc" ], "third_party": false, "type": "target" @@ -582,7 +582,7 @@ "language": "c", "name": "fd_posix_test", "src": [ - "test/core/iomgr/fd_posix_test.c" + "test/core/iomgr/fd_posix_test.cc" ], "third_party": false, "type": "target" @@ -599,7 +599,7 @@ "language": "c", "name": "fling_client", "src": [ - "test/core/fling/client.c" + "test/core/fling/client.cc" ], "third_party": false, "type": "target" @@ -616,7 +616,7 @@ "language": "c", "name": "fling_server", "src": [ - "test/core/fling/server.c" + "test/core/fling/server.cc" ], "third_party": false, "type": "target" @@ -633,7 +633,7 @@ "language": "c", "name": "fling_stream_test", "src": [ - "test/core/fling/fling_stream_test.c" + "test/core/fling/fling_stream_test.cc" ], "third_party": false, "type": "target" @@ -650,7 +650,7 @@ "language": "c", "name": "fling_test", "src": [ - "test/core/fling/fling_test.c" + "test/core/fling/fling_test.cc" ], "third_party": false, "type": "target" @@ -706,7 +706,7 @@ "language": "c", "name": "goaway_server_test", "src": [ - "test/core/end2end/goaway_server_test.c" + "test/core/end2end/goaway_server_test.cc" ], "third_party": false, "type": "target" @@ -721,7 +721,7 @@ "language": "c", "name": "gpr_avl_test", "src": [ - "test/core/support/avl_test.c" + "test/core/support/avl_test.cc" ], "third_party": false, "type": "target" @@ -736,7 +736,7 @@ "language": "c", "name": "gpr_cmdline_test", "src": [ - "test/core/support/cmdline_test.c" + "test/core/support/cmdline_test.cc" ], "third_party": false, "type": "target" @@ -751,7 +751,7 @@ "language": "c", "name": "gpr_cpu_test", "src": [ - "test/core/support/cpu_test.c" + "test/core/support/cpu_test.cc" ], "third_party": false, "type": "target" @@ -766,7 +766,7 @@ "language": "c", "name": "gpr_env_test", "src": [ - "test/core/support/env_test.c" + "test/core/support/env_test.cc" ], "third_party": false, "type": "target" @@ -781,7 +781,7 @@ "language": "c", "name": "gpr_histogram_test", "src": [ - "test/core/support/histogram_test.c" + "test/core/support/histogram_test.cc" ], "third_party": false, "type": "target" @@ -796,7 +796,7 @@ "language": "c", "name": "gpr_host_port_test", "src": [ - "test/core/support/host_port_test.c" + "test/core/support/host_port_test.cc" ], "third_party": false, "type": "target" @@ -811,7 +811,7 @@ "language": "c", "name": "gpr_log_test", "src": [ - "test/core/support/log_test.c" + "test/core/support/log_test.cc" ], "third_party": false, "type": "target" @@ -826,7 +826,7 @@ "language": "c", "name": "gpr_mpscq_test", "src": [ - "test/core/support/mpscq_test.c" + "test/core/support/mpscq_test.cc" ], "third_party": false, "type": "target" @@ -841,7 +841,7 @@ "language": "c", "name": "gpr_spinlock_test", "src": [ - "test/core/support/spinlock_test.c" + "test/core/support/spinlock_test.cc" ], "third_party": false, "type": "target" @@ -856,7 +856,7 @@ "language": "c", "name": "gpr_stack_lockfree_test", "src": [ - "test/core/support/stack_lockfree_test.c" + "test/core/support/stack_lockfree_test.cc" ], "third_party": false, "type": "target" @@ -871,7 +871,7 @@ "language": "c", "name": "gpr_string_test", "src": [ - "test/core/support/string_test.c" + "test/core/support/string_test.cc" ], "third_party": false, "type": "target" @@ -886,7 +886,7 @@ "language": "c", "name": "gpr_sync_test", "src": [ - "test/core/support/sync_test.c" + "test/core/support/sync_test.cc" ], "third_party": false, "type": "target" @@ -901,7 +901,7 @@ "language": "c", "name": "gpr_thd_test", "src": [ - "test/core/support/thd_test.c" + "test/core/support/thd_test.cc" ], "third_party": false, "type": "target" @@ -916,7 +916,7 @@ "language": "c", "name": "gpr_time_test", "src": [ - "test/core/support/time_test.c" + "test/core/support/time_test.cc" ], "third_party": false, "type": "target" @@ -931,7 +931,7 @@ "language": "c", "name": "gpr_tls_test", "src": [ - "test/core/support/tls_test.c" + "test/core/support/tls_test.cc" ], "third_party": false, "type": "target" @@ -946,7 +946,7 @@ "language": "c", "name": "gpr_useful_test", "src": [ - "test/core/support/useful_test.c" + "test/core/support/useful_test.cc" ], "third_party": false, "type": "target" @@ -963,7 +963,7 @@ "language": "c", "name": "grpc_auth_context_test", "src": [ - "test/core/security/auth_context_test.c" + "test/core/security/auth_context_test.cc" ], "third_party": false, "type": "target" @@ -980,7 +980,7 @@ "language": "c", "name": "grpc_b64_test", "src": [ - "test/core/slice/b64_test.c" + "test/core/slice/b64_test.cc" ], "third_party": false, "type": "target" @@ -997,7 +997,7 @@ "language": "c", "name": "grpc_byte_buffer_reader_test", "src": [ - "test/core/surface/byte_buffer_reader_test.c" + "test/core/surface/byte_buffer_reader_test.cc" ], "third_party": false, "type": "target" @@ -1014,7 +1014,7 @@ "language": "c", "name": "grpc_channel_args_test", "src": [ - "test/core/channel/channel_args_test.c" + "test/core/channel/channel_args_test.cc" ], "third_party": false, "type": "target" @@ -1031,7 +1031,7 @@ "language": "c", "name": "grpc_channel_stack_builder_test", "src": [ - "test/core/channel/channel_stack_builder_test.c" + "test/core/channel/channel_stack_builder_test.cc" ], "third_party": false, "type": "target" @@ -1048,7 +1048,7 @@ "language": "c", "name": "grpc_channel_stack_test", "src": [ - "test/core/channel/channel_stack_test.c" + "test/core/channel/channel_stack_test.cc" ], "third_party": false, "type": "target" @@ -1065,7 +1065,7 @@ "language": "c", "name": "grpc_completion_queue_test", "src": [ - "test/core/surface/completion_queue_test.c" + "test/core/surface/completion_queue_test.cc" ], "third_party": false, "type": "target" @@ -1082,7 +1082,7 @@ "language": "c", "name": "grpc_completion_queue_threading_test", "src": [ - "test/core/surface/completion_queue_threading_test.c" + "test/core/surface/completion_queue_threading_test.cc" ], "third_party": false, "type": "target" @@ -1097,7 +1097,7 @@ "language": "c", "name": "grpc_create_jwt", "src": [ - "test/core/security/create_jwt.c" + "test/core/security/create_jwt.cc" ], "third_party": false, "type": "target" @@ -1114,7 +1114,7 @@ "language": "c", "name": "grpc_credentials_test", "src": [ - "test/core/security/credentials_test.c" + "test/core/security/credentials_test.cc" ], "third_party": false, "type": "target" @@ -1131,7 +1131,7 @@ "language": "c", "name": "grpc_fetch_oauth2", "src": [ - "test/core/security/fetch_oauth2.c" + "test/core/security/fetch_oauth2.cc" ], "third_party": false, "type": "target" @@ -1148,7 +1148,7 @@ "language": "c", "name": "grpc_invalid_channel_args_test", "src": [ - "test/core/surface/invalid_channel_args_test.c" + "test/core/surface/invalid_channel_args_test.cc" ], "third_party": false, "type": "target" @@ -1165,7 +1165,7 @@ "language": "c", "name": "grpc_json_token_test", "src": [ - "test/core/security/json_token_test.c" + "test/core/security/json_token_test.cc" ], "third_party": false, "type": "target" @@ -1182,7 +1182,7 @@ "language": "c", "name": "grpc_jwt_verifier_test", "src": [ - "test/core/security/jwt_verifier_test.c" + "test/core/security/jwt_verifier_test.cc" ], "third_party": false, "type": "target" @@ -1197,7 +1197,7 @@ "language": "c", "name": "grpc_print_google_default_creds_token", "src": [ - "test/core/security/print_google_default_creds_token.c" + "test/core/security/print_google_default_creds_token.cc" ], "third_party": false, "type": "target" @@ -1214,7 +1214,7 @@ "language": "c", "name": "grpc_security_connector_test", "src": [ - "test/core/security/security_connector_test.c" + "test/core/security/security_connector_test.cc" ], "third_party": false, "type": "target" @@ -1229,7 +1229,7 @@ "language": "c", "name": "grpc_verify_jwt", "src": [ - "test/core/security/verify_jwt.c" + "test/core/security/verify_jwt.cc" ], "third_party": false, "type": "target" @@ -1246,7 +1246,7 @@ "language": "c", "name": "handshake_client", "src": [ - "test/core/handshake/client_ssl.c" + "test/core/handshake/client_ssl.cc" ], "third_party": false, "type": "target" @@ -1263,7 +1263,7 @@ "language": "c", "name": "handshake_server", "src": [ - "test/core/handshake/server_ssl.c" + "test/core/handshake/server_ssl.cc" ], "third_party": false, "type": "target" @@ -1280,7 +1280,7 @@ "language": "c", "name": "hpack_parser_fuzzer_test", "src": [ - "test/core/transport/chttp2/hpack_parser_fuzzer_test.c" + "test/core/transport/chttp2/hpack_parser_fuzzer_test.cc" ], "third_party": false, "type": "target" @@ -1297,7 +1297,7 @@ "language": "c", "name": "hpack_parser_test", "src": [ - "test/core/transport/chttp2/hpack_parser_test.c" + "test/core/transport/chttp2/hpack_parser_test.cc" ], "third_party": false, "type": "target" @@ -1314,7 +1314,7 @@ "language": "c", "name": "hpack_table_test", "src": [ - "test/core/transport/chttp2/hpack_table_test.c" + "test/core/transport/chttp2/hpack_table_test.cc" ], "third_party": false, "type": "target" @@ -1331,7 +1331,7 @@ "language": "c", "name": "http_parser_test", "src": [ - "test/core/http/parser_test.c" + "test/core/http/parser_test.cc" ], "third_party": false, "type": "target" @@ -1348,7 +1348,7 @@ "language": "c", "name": "http_request_fuzzer_test", "src": [ - "test/core/http/request_fuzzer.c" + "test/core/http/request_fuzzer.cc" ], "third_party": false, "type": "target" @@ -1365,7 +1365,7 @@ "language": "c", "name": "http_response_fuzzer_test", "src": [ - "test/core/http/response_fuzzer.c" + "test/core/http/response_fuzzer.cc" ], "third_party": false, "type": "target" @@ -1382,7 +1382,7 @@ "language": "c", "name": "httpcli_format_request_test", "src": [ - "test/core/http/format_request_test.c" + "test/core/http/format_request_test.cc" ], "third_party": false, "type": "target" @@ -1399,7 +1399,7 @@ "language": "c", "name": "httpcli_test", "src": [ - "test/core/http/httpcli_test.c" + "test/core/http/httpcli_test.cc" ], "third_party": false, "type": "target" @@ -1416,7 +1416,7 @@ "language": "c", "name": "httpscli_test", "src": [ - "test/core/http/httpscli_test.c" + "test/core/http/httpscli_test.cc" ], "third_party": false, "type": "target" @@ -1433,7 +1433,7 @@ "language": "c", "name": "init_test", "src": [ - "test/core/surface/init_test.c" + "test/core/surface/init_test.cc" ], "third_party": false, "type": "target" @@ -1450,7 +1450,7 @@ "language": "c", "name": "invalid_call_argument_test", "src": [ - "test/core/end2end/invalid_call_argument_test.c" + "test/core/end2end/invalid_call_argument_test.cc" ], "third_party": false, "type": "target" @@ -1467,7 +1467,7 @@ "language": "c", "name": "json_fuzzer_test", "src": [ - "test/core/json/fuzzer.c" + "test/core/json/fuzzer.cc" ], "third_party": false, "type": "target" @@ -1482,7 +1482,7 @@ "language": "c", "name": "json_rewrite", "src": [ - "test/core/json/json_rewrite.c" + "test/core/json/json_rewrite.cc" ], "third_party": false, "type": "target" @@ -1499,7 +1499,7 @@ "language": "c", "name": "json_rewrite_test", "src": [ - "test/core/json/json_rewrite_test.c" + "test/core/json/json_rewrite_test.cc" ], "third_party": false, "type": "target" @@ -1516,7 +1516,7 @@ "language": "c", "name": "json_stream_error_test", "src": [ - "test/core/json/json_stream_error_test.c" + "test/core/json/json_stream_error_test.cc" ], "third_party": false, "type": "target" @@ -1533,7 +1533,7 @@ "language": "c", "name": "json_test", "src": [ - "test/core/json/json_test.c" + "test/core/json/json_test.cc" ], "third_party": false, "type": "target" @@ -1550,7 +1550,7 @@ "language": "c", "name": "lame_client_test", "src": [ - "test/core/surface/lame_client_test.c" + "test/core/surface/lame_client_test.cc" ], "third_party": false, "type": "target" @@ -1567,7 +1567,7 @@ "language": "c", "name": "lb_policies_test", "src": [ - "test/core/client_channel/lb_policies_test.c" + "test/core/client_channel/lb_policies_test.cc" ], "third_party": false, "type": "target" @@ -1584,7 +1584,7 @@ "language": "c", "name": "load_file_test", "src": [ - "test/core/iomgr/load_file_test.c" + "test/core/iomgr/load_file_test.cc" ], "third_party": false, "type": "target" @@ -1601,7 +1601,7 @@ "language": "c", "name": "low_level_ping_pong_benchmark", "src": [ - "test/core/network_benchmarks/low_level_ping_pong.c" + "test/core/network_benchmarks/low_level_ping_pong.cc" ], "third_party": false, "type": "target" @@ -1618,7 +1618,7 @@ "language": "c", "name": "memory_profile_client", "src": [ - "test/core/memory_usage/client.c" + "test/core/memory_usage/client.cc" ], "third_party": false, "type": "target" @@ -1635,7 +1635,7 @@ "language": "c", "name": "memory_profile_server", "src": [ - "test/core/memory_usage/server.c" + "test/core/memory_usage/server.cc" ], "third_party": false, "type": "target" @@ -1652,7 +1652,7 @@ "language": "c", "name": "memory_profile_test", "src": [ - "test/core/memory_usage/memory_usage_test.c" + "test/core/memory_usage/memory_usage_test.cc" ], "third_party": false, "type": "target" @@ -1669,7 +1669,7 @@ "language": "c", "name": "message_compress_test", "src": [ - "test/core/compression/message_compress_test.c" + "test/core/compression/message_compress_test.cc" ], "third_party": false, "type": "target" @@ -1686,7 +1686,7 @@ "language": "c", "name": "minimal_stack_is_minimal_test", "src": [ - "test/core/channel/minimal_stack_is_minimal_test.c" + "test/core/channel/minimal_stack_is_minimal_test.cc" ], "third_party": false, "type": "target" @@ -1703,7 +1703,7 @@ "language": "c", "name": "mlog_test", "src": [ - "test/core/census/mlog_test.c" + "test/core/census/mlog_test.cc" ], "third_party": false, "type": "target" @@ -1720,7 +1720,7 @@ "language": "c", "name": "multiple_server_queues_test", "src": [ - "test/core/end2end/multiple_server_queues_test.c" + "test/core/end2end/multiple_server_queues_test.cc" ], "third_party": false, "type": "target" @@ -1735,7 +1735,7 @@ "language": "c", "name": "murmur_hash_test", "src": [ - "test/core/support/murmur_hash_test.c" + "test/core/support/murmur_hash_test.cc" ], "third_party": false, "type": "target" @@ -1752,7 +1752,7 @@ "language": "c", "name": "nanopb_fuzzer_response_test", "src": [ - "test/core/nanopb/fuzzer_response.c" + "test/core/nanopb/fuzzer_response.cc" ], "third_party": false, "type": "target" @@ -1769,7 +1769,7 @@ "language": "c", "name": "nanopb_fuzzer_serverlist_test", "src": [ - "test/core/nanopb/fuzzer_serverlist.c" + "test/core/nanopb/fuzzer_serverlist.cc" ], "third_party": false, "type": "target" @@ -1786,7 +1786,7 @@ "language": "c", "name": "no_server_test", "src": [ - "test/core/end2end/no_server_test.c" + "test/core/end2end/no_server_test.cc" ], "third_party": false, "type": "target" @@ -1803,7 +1803,7 @@ "language": "c", "name": "num_external_connectivity_watchers_test", "src": [ - "test/core/surface/num_external_connectivity_watchers_test.c" + "test/core/surface/num_external_connectivity_watchers_test.cc" ], "third_party": false, "type": "target" @@ -1820,7 +1820,7 @@ "language": "c", "name": "parse_address_test", "src": [ - "test/core/client_channel/parse_address_test.c" + "test/core/client_channel/parse_address_test.cc" ], "third_party": false, "type": "target" @@ -1837,7 +1837,7 @@ "language": "c", "name": "percent_decode_fuzzer", "src": [ - "test/core/slice/percent_decode_fuzzer.c" + "test/core/slice/percent_decode_fuzzer.cc" ], "third_party": false, "type": "target" @@ -1854,7 +1854,7 @@ "language": "c", "name": "percent_encode_fuzzer", "src": [ - "test/core/slice/percent_encode_fuzzer.c" + "test/core/slice/percent_encode_fuzzer.cc" ], "third_party": false, "type": "target" @@ -1871,7 +1871,7 @@ "language": "c", "name": "percent_encoding_test", "src": [ - "test/core/slice/percent_encoding_test.c" + "test/core/slice/percent_encoding_test.cc" ], "third_party": false, "type": "target" @@ -1888,7 +1888,7 @@ "language": "c", "name": "pollset_set_test", "src": [ - "test/core/iomgr/pollset_set_test.c" + "test/core/iomgr/pollset_set_test.cc" ], "third_party": false, "type": "target" @@ -1905,7 +1905,7 @@ "language": "c", "name": "resolve_address_posix_test", "src": [ - "test/core/iomgr/resolve_address_posix_test.c" + "test/core/iomgr/resolve_address_posix_test.cc" ], "third_party": false, "type": "target" @@ -1922,7 +1922,7 @@ "language": "c", "name": "resolve_address_test", "src": [ - "test/core/iomgr/resolve_address_test.c" + "test/core/iomgr/resolve_address_test.cc" ], "third_party": false, "type": "target" @@ -1939,7 +1939,7 @@ "language": "c", "name": "resource_quota_test", "src": [ - "test/core/iomgr/resource_quota_test.c" + "test/core/iomgr/resource_quota_test.cc" ], "third_party": false, "type": "target" @@ -1956,7 +1956,7 @@ "language": "c", "name": "secure_channel_create_test", "src": [ - "test/core/surface/secure_channel_create_test.c" + "test/core/surface/secure_channel_create_test.cc" ], "third_party": false, "type": "target" @@ -1973,7 +1973,7 @@ "language": "c", "name": "secure_endpoint_test", "src": [ - "test/core/security/secure_endpoint_test.c" + "test/core/security/secure_endpoint_test.cc" ], "third_party": false, "type": "target" @@ -1990,7 +1990,7 @@ "language": "c", "name": "sequential_connectivity_test", "src": [ - "test/core/surface/sequential_connectivity_test.c" + "test/core/surface/sequential_connectivity_test.cc" ], "third_party": false, "type": "target" @@ -2007,7 +2007,7 @@ "language": "c", "name": "server_chttp2_test", "src": [ - "test/core/surface/server_chttp2_test.c" + "test/core/surface/server_chttp2_test.cc" ], "third_party": false, "type": "target" @@ -2024,7 +2024,7 @@ "language": "c", "name": "server_fuzzer", "src": [ - "test/core/end2end/fuzzers/server_fuzzer.c" + "test/core/end2end/fuzzers/server_fuzzer.cc" ], "third_party": false, "type": "target" @@ -2041,7 +2041,7 @@ "language": "c", "name": "server_test", "src": [ - "test/core/surface/server_test.c" + "test/core/surface/server_test.cc" ], "third_party": false, "type": "target" @@ -2058,7 +2058,7 @@ "language": "c", "name": "slice_buffer_test", "src": [ - "test/core/slice/slice_buffer_test.c" + "test/core/slice/slice_buffer_test.cc" ], "third_party": false, "type": "target" @@ -2075,7 +2075,7 @@ "language": "c", "name": "slice_hash_table_test", "src": [ - "test/core/slice/slice_hash_table_test.c" + "test/core/slice/slice_hash_table_test.cc" ], "third_party": false, "type": "target" @@ -2092,7 +2092,7 @@ "language": "c", "name": "slice_string_helpers_test", "src": [ - "test/core/slice/slice_string_helpers_test.c" + "test/core/slice/slice_string_helpers_test.cc" ], "third_party": false, "type": "target" @@ -2109,7 +2109,7 @@ "language": "c", "name": "slice_test", "src": [ - "test/core/slice/slice_test.c" + "test/core/slice/slice_test.cc" ], "third_party": false, "type": "target" @@ -2126,7 +2126,7 @@ "language": "c", "name": "sockaddr_resolver_test", "src": [ - "test/core/client_channel/resolvers/sockaddr_resolver_test.c" + "test/core/client_channel/resolvers/sockaddr_resolver_test.cc" ], "third_party": false, "type": "target" @@ -2143,7 +2143,7 @@ "language": "c", "name": "sockaddr_utils_test", "src": [ - "test/core/iomgr/sockaddr_utils_test.c" + "test/core/iomgr/sockaddr_utils_test.cc" ], "third_party": false, "type": "target" @@ -2160,7 +2160,7 @@ "language": "c", "name": "socket_utils_test", "src": [ - "test/core/iomgr/socket_utils_test.c" + "test/core/iomgr/socket_utils_test.cc" ], "third_party": false, "type": "target" @@ -2177,7 +2177,7 @@ "language": "c", "name": "ssl_server_fuzzer", "src": [ - "test/core/security/ssl_server_fuzzer.c" + "test/core/security/ssl_server_fuzzer.cc" ], "third_party": false, "type": "target" @@ -2194,7 +2194,7 @@ "language": "c", "name": "ssl_transport_security_test", "src": [ - "test/core/tsi/ssl_transport_security_test.c" + "test/core/tsi/ssl_transport_security_test.cc" ], "third_party": false, "type": "target" @@ -2211,7 +2211,7 @@ "language": "c", "name": "status_conversion_test", "src": [ - "test/core/transport/status_conversion_test.c" + "test/core/transport/status_conversion_test.cc" ], "third_party": false, "type": "target" @@ -2228,7 +2228,7 @@ "language": "c", "name": "stream_compression_test", "src": [ - "test/core/compression/stream_compression_test.c" + "test/core/compression/stream_compression_test.cc" ], "third_party": false, "type": "target" @@ -2245,7 +2245,7 @@ "language": "c", "name": "stream_owned_slice_test", "src": [ - "test/core/transport/stream_owned_slice_test.c" + "test/core/transport/stream_owned_slice_test.cc" ], "third_party": false, "type": "target" @@ -2262,7 +2262,7 @@ "language": "c", "name": "tcp_client_posix_test", "src": [ - "test/core/iomgr/tcp_client_posix_test.c" + "test/core/iomgr/tcp_client_posix_test.cc" ], "third_party": false, "type": "target" @@ -2279,7 +2279,7 @@ "language": "c", "name": "tcp_client_uv_test", "src": [ - "test/core/iomgr/tcp_client_uv_test.c" + "test/core/iomgr/tcp_client_uv_test.cc" ], "third_party": false, "type": "target" @@ -2296,7 +2296,7 @@ "language": "c", "name": "tcp_posix_test", "src": [ - "test/core/iomgr/tcp_posix_test.c" + "test/core/iomgr/tcp_posix_test.cc" ], "third_party": false, "type": "target" @@ -2313,7 +2313,7 @@ "language": "c", "name": "tcp_server_posix_test", "src": [ - "test/core/iomgr/tcp_server_posix_test.c" + "test/core/iomgr/tcp_server_posix_test.cc" ], "third_party": false, "type": "target" @@ -2330,7 +2330,7 @@ "language": "c", "name": "tcp_server_uv_test", "src": [ - "test/core/iomgr/tcp_server_uv_test.c" + "test/core/iomgr/tcp_server_uv_test.cc" ], "third_party": false, "type": "target" @@ -2347,7 +2347,7 @@ "language": "c", "name": "time_averaged_stats_test", "src": [ - "test/core/iomgr/time_averaged_stats_test.c" + "test/core/iomgr/time_averaged_stats_test.cc" ], "third_party": false, "type": "target" @@ -2364,7 +2364,7 @@ "language": "c", "name": "timeout_encoding_test", "src": [ - "test/core/transport/timeout_encoding_test.c" + "test/core/transport/timeout_encoding_test.cc" ], "third_party": false, "type": "target" @@ -2381,7 +2381,7 @@ "language": "c", "name": "timer_heap_test", "src": [ - "test/core/iomgr/timer_heap_test.c" + "test/core/iomgr/timer_heap_test.cc" ], "third_party": false, "type": "target" @@ -2398,7 +2398,7 @@ "language": "c", "name": "timer_list_test", "src": [ - "test/core/iomgr/timer_list_test.c" + "test/core/iomgr/timer_list_test.cc" ], "third_party": false, "type": "target" @@ -2415,7 +2415,7 @@ "language": "c", "name": "transport_connectivity_state_test", "src": [ - "test/core/transport/connectivity_state_test.c" + "test/core/transport/connectivity_state_test.cc" ], "third_party": false, "type": "target" @@ -2432,7 +2432,7 @@ "language": "c", "name": "transport_metadata_test", "src": [ - "test/core/transport/metadata_test.c" + "test/core/transport/metadata_test.cc" ], "third_party": false, "type": "target" @@ -2449,7 +2449,7 @@ "language": "c", "name": "transport_security_test", "src": [ - "test/core/tsi/transport_security_test.c" + "test/core/tsi/transport_security_test.cc" ], "third_party": false, "type": "target" @@ -2466,7 +2466,7 @@ "language": "c", "name": "udp_server_test", "src": [ - "test/core/iomgr/udp_server_test.c" + "test/core/iomgr/udp_server_test.cc" ], "third_party": false, "type": "target" @@ -2483,7 +2483,7 @@ "language": "c", "name": "uri_fuzzer_test", "src": [ - "test/core/client_channel/uri_fuzzer_test.c" + "test/core/client_channel/uri_fuzzer_test.cc" ], "third_party": false, "type": "target" @@ -2500,7 +2500,7 @@ "language": "c", "name": "uri_parser_test", "src": [ - "test/core/client_channel/uri_parser_test.c" + "test/core/client_channel/uri_parser_test.cc" ], "third_party": false, "type": "target" @@ -2517,7 +2517,7 @@ "language": "c", "name": "wakeup_fd_cv_test", "src": [ - "test/core/iomgr/wakeup_fd_cv_test.c" + "test/core/iomgr/wakeup_fd_cv_test.cc" ], "third_party": false, "type": "target" @@ -4864,7 +4864,7 @@ "language": "c", "name": "badreq_bad_client_test", "src": [ - "test/core/bad_client/tests/badreq.c" + "test/core/bad_client/tests/badreq.cc" ], "third_party": false, "type": "target" @@ -4882,7 +4882,7 @@ "language": "c", "name": "connection_prefix_bad_client_test", "src": [ - "test/core/bad_client/tests/connection_prefix.c" + "test/core/bad_client/tests/connection_prefix.cc" ], "third_party": false, "type": "target" @@ -4900,7 +4900,7 @@ "language": "c", "name": "head_of_line_blocking_bad_client_test", "src": [ - "test/core/bad_client/tests/head_of_line_blocking.c" + "test/core/bad_client/tests/head_of_line_blocking.cc" ], "third_party": false, "type": "target" @@ -4918,7 +4918,7 @@ "language": "c", "name": "headers_bad_client_test", "src": [ - "test/core/bad_client/tests/headers.c" + "test/core/bad_client/tests/headers.cc" ], "third_party": false, "type": "target" @@ -4936,7 +4936,7 @@ "language": "c", "name": "initial_settings_frame_bad_client_test", "src": [ - "test/core/bad_client/tests/initial_settings_frame.c" + "test/core/bad_client/tests/initial_settings_frame.cc" ], "third_party": false, "type": "target" @@ -4954,7 +4954,7 @@ "language": "c", "name": "server_registered_method_bad_client_test", "src": [ - "test/core/bad_client/tests/server_registered_method.c" + "test/core/bad_client/tests/server_registered_method.cc" ], "third_party": false, "type": "target" @@ -4972,7 +4972,7 @@ "language": "c", "name": "simple_request_bad_client_test", "src": [ - "test/core/bad_client/tests/simple_request.c" + "test/core/bad_client/tests/simple_request.cc" ], "third_party": false, "type": "target" @@ -4990,7 +4990,7 @@ "language": "c", "name": "unknown_frame_bad_client_test", "src": [ - "test/core/bad_client/tests/unknown_frame.c" + "test/core/bad_client/tests/unknown_frame.cc" ], "third_party": false, "type": "target" @@ -5008,7 +5008,7 @@ "language": "c", "name": "window_overflow_bad_client_test", "src": [ - "test/core/bad_client/tests/window_overflow.c" + "test/core/bad_client/tests/window_overflow.cc" ], "third_party": false, "type": "target" @@ -5026,7 +5026,7 @@ "language": "c", "name": "bad_ssl_cert_server", "src": [ - "test/core/bad_ssl/servers/cert.c" + "test/core/bad_ssl/servers/cert.cc" ], "third_party": false, "type": "target" @@ -5043,7 +5043,7 @@ "language": "c", "name": "bad_ssl_cert_test", "src": [ - "test/core/bad_ssl/bad_ssl_test.c" + "test/core/bad_ssl/bad_ssl_test.cc" ], "third_party": false, "type": "target" @@ -5061,7 +5061,7 @@ "language": "c", "name": "h2_census_test", "src": [ - "test/core/end2end/fixtures/h2_census.c" + "test/core/end2end/fixtures/h2_census.cc" ], "third_party": false, "type": "target" @@ -5079,7 +5079,7 @@ "language": "c", "name": "h2_compress_test", "src": [ - "test/core/end2end/fixtures/h2_compress.c" + "test/core/end2end/fixtures/h2_compress.cc" ], "third_party": false, "type": "target" @@ -5097,7 +5097,7 @@ "language": "c", "name": "h2_fakesec_test", "src": [ - "test/core/end2end/fixtures/h2_fakesec.c" + "test/core/end2end/fixtures/h2_fakesec.cc" ], "third_party": false, "type": "target" @@ -5115,7 +5115,7 @@ "language": "c", "name": "h2_fd_test", "src": [ - "test/core/end2end/fixtures/h2_fd.c" + "test/core/end2end/fixtures/h2_fd.cc" ], "third_party": false, "type": "target" @@ -5133,7 +5133,7 @@ "language": "c", "name": "h2_full_test", "src": [ - "test/core/end2end/fixtures/h2_full.c" + "test/core/end2end/fixtures/h2_full.cc" ], "third_party": false, "type": "target" @@ -5151,7 +5151,7 @@ "language": "c", "name": "h2_full+pipe_test", "src": [ - "test/core/end2end/fixtures/h2_full+pipe.c" + "test/core/end2end/fixtures/h2_full+pipe.cc" ], "third_party": false, "type": "target" @@ -5169,7 +5169,7 @@ "language": "c", "name": "h2_full+trace_test", "src": [ - "test/core/end2end/fixtures/h2_full+trace.c" + "test/core/end2end/fixtures/h2_full+trace.cc" ], "third_party": false, "type": "target" @@ -5187,7 +5187,7 @@ "language": "c", "name": "h2_full+workarounds_test", "src": [ - "test/core/end2end/fixtures/h2_full+workarounds.c" + "test/core/end2end/fixtures/h2_full+workarounds.cc" ], "third_party": false, "type": "target" @@ -5205,7 +5205,7 @@ "language": "c", "name": "h2_http_proxy_test", "src": [ - "test/core/end2end/fixtures/h2_http_proxy.c" + "test/core/end2end/fixtures/h2_http_proxy.cc" ], "third_party": false, "type": "target" @@ -5223,7 +5223,7 @@ "language": "c", "name": "h2_load_reporting_test", "src": [ - "test/core/end2end/fixtures/h2_load_reporting.c" + "test/core/end2end/fixtures/h2_load_reporting.cc" ], "third_party": false, "type": "target" @@ -5241,7 +5241,7 @@ "language": "c", "name": "h2_oauth2_test", "src": [ - "test/core/end2end/fixtures/h2_oauth2.c" + "test/core/end2end/fixtures/h2_oauth2.cc" ], "third_party": false, "type": "target" @@ -5259,7 +5259,7 @@ "language": "c", "name": "h2_proxy_test", "src": [ - "test/core/end2end/fixtures/h2_proxy.c" + "test/core/end2end/fixtures/h2_proxy.cc" ], "third_party": false, "type": "target" @@ -5277,7 +5277,7 @@ "language": "c", "name": "h2_sockpair_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair.c" + "test/core/end2end/fixtures/h2_sockpair.cc" ], "third_party": false, "type": "target" @@ -5295,7 +5295,7 @@ "language": "c", "name": "h2_sockpair+trace_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair+trace.c" + "test/core/end2end/fixtures/h2_sockpair+trace.cc" ], "third_party": false, "type": "target" @@ -5313,7 +5313,7 @@ "language": "c", "name": "h2_sockpair_1byte_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair_1byte.c" + "test/core/end2end/fixtures/h2_sockpair_1byte.cc" ], "third_party": false, "type": "target" @@ -5331,7 +5331,7 @@ "language": "c", "name": "h2_ssl_test", "src": [ - "test/core/end2end/fixtures/h2_ssl.c" + "test/core/end2end/fixtures/h2_ssl.cc" ], "third_party": false, "type": "target" @@ -5349,7 +5349,7 @@ "language": "c", "name": "h2_ssl_proxy_test", "src": [ - "test/core/end2end/fixtures/h2_ssl_proxy.c" + "test/core/end2end/fixtures/h2_ssl_proxy.cc" ], "third_party": false, "type": "target" @@ -5367,7 +5367,7 @@ "language": "c", "name": "h2_uds_test", "src": [ - "test/core/end2end/fixtures/h2_uds.c" + "test/core/end2end/fixtures/h2_uds.cc" ], "third_party": false, "type": "target" @@ -5385,7 +5385,7 @@ "language": "c", "name": "inproc_test", "src": [ - "test/core/end2end/fixtures/inproc.c" + "test/core/end2end/fixtures/inproc.cc" ], "third_party": false, "type": "target" @@ -5403,7 +5403,7 @@ "language": "c", "name": "h2_census_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_census.c" + "test/core/end2end/fixtures/h2_census.cc" ], "third_party": false, "type": "target" @@ -5421,7 +5421,7 @@ "language": "c", "name": "h2_compress_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_compress.c" + "test/core/end2end/fixtures/h2_compress.cc" ], "third_party": false, "type": "target" @@ -5439,7 +5439,7 @@ "language": "c", "name": "h2_fd_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_fd.c" + "test/core/end2end/fixtures/h2_fd.cc" ], "third_party": false, "type": "target" @@ -5457,7 +5457,7 @@ "language": "c", "name": "h2_full_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_full.c" + "test/core/end2end/fixtures/h2_full.cc" ], "third_party": false, "type": "target" @@ -5475,7 +5475,7 @@ "language": "c", "name": "h2_full+pipe_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_full+pipe.c" + "test/core/end2end/fixtures/h2_full+pipe.cc" ], "third_party": false, "type": "target" @@ -5493,7 +5493,7 @@ "language": "c", "name": "h2_full+trace_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_full+trace.c" + "test/core/end2end/fixtures/h2_full+trace.cc" ], "third_party": false, "type": "target" @@ -5511,7 +5511,7 @@ "language": "c", "name": "h2_full+workarounds_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_full+workarounds.c" + "test/core/end2end/fixtures/h2_full+workarounds.cc" ], "third_party": false, "type": "target" @@ -5529,7 +5529,7 @@ "language": "c", "name": "h2_http_proxy_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_http_proxy.c" + "test/core/end2end/fixtures/h2_http_proxy.cc" ], "third_party": false, "type": "target" @@ -5547,7 +5547,7 @@ "language": "c", "name": "h2_load_reporting_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_load_reporting.c" + "test/core/end2end/fixtures/h2_load_reporting.cc" ], "third_party": false, "type": "target" @@ -5565,7 +5565,7 @@ "language": "c", "name": "h2_proxy_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_proxy.c" + "test/core/end2end/fixtures/h2_proxy.cc" ], "third_party": false, "type": "target" @@ -5583,7 +5583,7 @@ "language": "c", "name": "h2_sockpair_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair.c" + "test/core/end2end/fixtures/h2_sockpair.cc" ], "third_party": false, "type": "target" @@ -5601,7 +5601,7 @@ "language": "c", "name": "h2_sockpair+trace_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair+trace.c" + "test/core/end2end/fixtures/h2_sockpair+trace.cc" ], "third_party": false, "type": "target" @@ -5619,7 +5619,7 @@ "language": "c", "name": "h2_sockpair_1byte_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_sockpair_1byte.c" + "test/core/end2end/fixtures/h2_sockpair_1byte.cc" ], "third_party": false, "type": "target" @@ -5637,7 +5637,7 @@ "language": "c", "name": "h2_uds_nosec_test", "src": [ - "test/core/end2end/fixtures/h2_uds.c" + "test/core/end2end/fixtures/h2_uds.cc" ], "third_party": false, "type": "target" @@ -5655,7 +5655,7 @@ "language": "c", "name": "inproc_nosec_test", "src": [ - "test/core/end2end/fixtures/inproc.c" + "test/core/end2end/fixtures/inproc.cc" ], "third_party": false, "type": "target" @@ -5752,7 +5752,7 @@ "language": "c", "name": "api_fuzzer_one_entry", "src": [ - "test/core/end2end/fuzzers/api_fuzzer.c", + "test/core/end2end/fuzzers/api_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5770,7 +5770,7 @@ "language": "c", "name": "client_fuzzer_one_entry", "src": [ - "test/core/end2end/fuzzers/client_fuzzer.c", + "test/core/end2end/fuzzers/client_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5788,7 +5788,7 @@ "language": "c", "name": "hpack_parser_fuzzer_test_one_entry", "src": [ - "test/core/transport/chttp2/hpack_parser_fuzzer_test.c", + "test/core/transport/chttp2/hpack_parser_fuzzer_test.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5806,7 +5806,7 @@ "language": "c", "name": "http_request_fuzzer_test_one_entry", "src": [ - "test/core/http/request_fuzzer.c", + "test/core/http/request_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5824,7 +5824,7 @@ "language": "c", "name": "http_response_fuzzer_test_one_entry", "src": [ - "test/core/http/response_fuzzer.c", + "test/core/http/response_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5842,7 +5842,7 @@ "language": "c", "name": "json_fuzzer_test_one_entry", "src": [ - "test/core/json/fuzzer.c", + "test/core/json/fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5860,7 +5860,7 @@ "language": "c", "name": "nanopb_fuzzer_response_test_one_entry", "src": [ - "test/core/nanopb/fuzzer_response.c", + "test/core/nanopb/fuzzer_response.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5878,7 +5878,7 @@ "language": "c", "name": "nanopb_fuzzer_serverlist_test_one_entry", "src": [ - "test/core/nanopb/fuzzer_serverlist.c", + "test/core/nanopb/fuzzer_serverlist.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5896,7 +5896,7 @@ "language": "c", "name": "percent_decode_fuzzer_one_entry", "src": [ - "test/core/slice/percent_decode_fuzzer.c", + "test/core/slice/percent_decode_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5914,7 +5914,7 @@ "language": "c", "name": "percent_encode_fuzzer_one_entry", "src": [ - "test/core/slice/percent_encode_fuzzer.c", + "test/core/slice/percent_encode_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5932,7 +5932,7 @@ "language": "c", "name": "server_fuzzer_one_entry", "src": [ - "test/core/end2end/fuzzers/server_fuzzer.c", + "test/core/end2end/fuzzers/server_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5950,7 +5950,7 @@ "language": "c", "name": "ssl_server_fuzzer_one_entry", "src": [ - "test/core/security/ssl_server_fuzzer.c", + "test/core/security/ssl_server_fuzzer.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5968,7 +5968,7 @@ "language": "c", "name": "uri_fuzzer_test_one_entry", "src": [ - "test/core/client_channel/uri_fuzzer_test.c", + "test/core/client_channel/uri_fuzzer_test.cc", "test/core/util/one_corpus_entry_fuzzer.c" ], "third_party": false, @@ -5997,7 +5997,7 @@ "language": "c", "name": "gpr_test_util", "src": [ - "test/core/util/test_config.c", + "test/core/util/test_config.cc", "test/core/util/test_config.h" ], "third_party": false, @@ -6084,12 +6084,12 @@ "language": "c", "name": "grpc_test_util", "src": [ - "test/core/end2end/data/client_certs.c", - "test/core/end2end/data/server1_cert.c", - "test/core/end2end/data/server1_key.c", + "test/core/end2end/data/client_certs.cc", + "test/core/end2end/data/server1_cert.cc", + "test/core/end2end/data/server1_key.cc", "test/core/end2end/data/ssl_test_data.h", - "test/core/end2end/data/test_root_cert.c", - "test/core/security/oauth2_utils.c", + "test/core/end2end/data/test_root_cert.cc", + "test/core/security/oauth2_utils.cc", "test/core/security/oauth2_utils.h" ], "third_party": false, @@ -6158,7 +6158,7 @@ "language": "c", "name": "reconnect_server", "src": [ - "test/core/util/reconnect_server.c", + "test/core/util/reconnect_server.cc", "test/core/util/reconnect_server.h" ], "third_party": false, @@ -6178,7 +6178,7 @@ "language": "c", "name": "test_tcp_server", "src": [ - "test/core/util/test_tcp_server.c", + "test/core/util/test_tcp_server.cc", "test/core/util/test_tcp_server.h" ], "third_party": false, @@ -7535,7 +7535,7 @@ "language": "c", "name": "bad_client_test", "src": [ - "test/core/bad_client/bad_client.c", + "test/core/bad_client/bad_client.cc", "test/core/bad_client/bad_client.h" ], "third_party": false, @@ -7555,7 +7555,7 @@ "language": "c", "name": "bad_ssl_test_server", "src": [ - "test/core/bad_ssl/server_common.c", + "test/core/bad_ssl/server_common.cc", "test/core/bad_ssl/server_common.h" ], "third_party": false, @@ -7576,69 +7576,69 @@ "language": "c", "name": "end2end_tests", "src": [ - "test/core/end2end/end2end_test_utils.c", - "test/core/end2end/end2end_tests.c", + "test/core/end2end/end2end_test_utils.cc", + "test/core/end2end/end2end_tests.cc", "test/core/end2end/end2end_tests.h", - "test/core/end2end/tests/authority_not_supported.c", - "test/core/end2end/tests/bad_hostname.c", - "test/core/end2end/tests/bad_ping.c", - "test/core/end2end/tests/binary_metadata.c", - "test/core/end2end/tests/call_creds.c", - "test/core/end2end/tests/cancel_after_accept.c", - "test/core/end2end/tests/cancel_after_client_done.c", - "test/core/end2end/tests/cancel_after_invoke.c", - "test/core/end2end/tests/cancel_after_round_trip.c", - "test/core/end2end/tests/cancel_before_invoke.c", - "test/core/end2end/tests/cancel_in_a_vacuum.c", + "test/core/end2end/tests/authority_not_supported.cc", + "test/core/end2end/tests/bad_hostname.cc", + "test/core/end2end/tests/bad_ping.cc", + "test/core/end2end/tests/binary_metadata.cc", + "test/core/end2end/tests/call_creds.cc", + "test/core/end2end/tests/cancel_after_accept.cc", + "test/core/end2end/tests/cancel_after_client_done.cc", + "test/core/end2end/tests/cancel_after_invoke.cc", + "test/core/end2end/tests/cancel_after_round_trip.cc", + "test/core/end2end/tests/cancel_before_invoke.cc", + "test/core/end2end/tests/cancel_in_a_vacuum.cc", "test/core/end2end/tests/cancel_test_helpers.h", - "test/core/end2end/tests/cancel_with_status.c", - "test/core/end2end/tests/compressed_payload.c", - "test/core/end2end/tests/connectivity.c", - "test/core/end2end/tests/default_host.c", - "test/core/end2end/tests/disappearing_server.c", - "test/core/end2end/tests/empty_batch.c", - "test/core/end2end/tests/filter_call_init_fails.c", - "test/core/end2end/tests/filter_causes_close.c", - "test/core/end2end/tests/filter_latency.c", - "test/core/end2end/tests/graceful_server_shutdown.c", - "test/core/end2end/tests/high_initial_seqno.c", - "test/core/end2end/tests/hpack_size.c", - "test/core/end2end/tests/idempotent_request.c", - "test/core/end2end/tests/invoke_large_request.c", - "test/core/end2end/tests/keepalive_timeout.c", - "test/core/end2end/tests/large_metadata.c", - "test/core/end2end/tests/load_reporting_hook.c", - "test/core/end2end/tests/max_concurrent_streams.c", - "test/core/end2end/tests/max_connection_age.c", - "test/core/end2end/tests/max_connection_idle.c", - "test/core/end2end/tests/max_message_length.c", - "test/core/end2end/tests/negative_deadline.c", - "test/core/end2end/tests/network_status_change.c", - "test/core/end2end/tests/no_logging.c", - "test/core/end2end/tests/no_op.c", - "test/core/end2end/tests/payload.c", - "test/core/end2end/tests/ping.c", - "test/core/end2end/tests/ping_pong_streaming.c", - "test/core/end2end/tests/proxy_auth.c", - "test/core/end2end/tests/registered_call.c", - "test/core/end2end/tests/request_with_flags.c", - "test/core/end2end/tests/request_with_payload.c", - "test/core/end2end/tests/resource_quota_server.c", - "test/core/end2end/tests/server_finishes_request.c", - "test/core/end2end/tests/shutdown_finishes_calls.c", - "test/core/end2end/tests/shutdown_finishes_tags.c", - "test/core/end2end/tests/simple_cacheable_request.c", - "test/core/end2end/tests/simple_delayed_request.c", - "test/core/end2end/tests/simple_metadata.c", - "test/core/end2end/tests/simple_request.c", - "test/core/end2end/tests/stream_compression_compressed_payload.c", - "test/core/end2end/tests/stream_compression_payload.c", - "test/core/end2end/tests/stream_compression_ping_pong_streaming.c", - "test/core/end2end/tests/streaming_error_response.c", - "test/core/end2end/tests/trailing_metadata.c", - "test/core/end2end/tests/workaround_cronet_compression.c", - "test/core/end2end/tests/write_buffering.c", - "test/core/end2end/tests/write_buffering_at_end.c" + "test/core/end2end/tests/cancel_with_status.cc", + "test/core/end2end/tests/compressed_payload.cc", + "test/core/end2end/tests/connectivity.cc", + "test/core/end2end/tests/default_host.cc", + "test/core/end2end/tests/disappearing_server.cc", + "test/core/end2end/tests/empty_batch.cc", + "test/core/end2end/tests/filter_call_init_fails.cc", + "test/core/end2end/tests/filter_causes_close.cc", + "test/core/end2end/tests/filter_latency.cc", + "test/core/end2end/tests/graceful_server_shutdown.cc", + "test/core/end2end/tests/high_initial_seqno.cc", + "test/core/end2end/tests/hpack_size.cc", + "test/core/end2end/tests/idempotent_request.cc", + "test/core/end2end/tests/invoke_large_request.cc", + "test/core/end2end/tests/keepalive_timeout.cc", + "test/core/end2end/tests/large_metadata.cc", + "test/core/end2end/tests/load_reporting_hook.cc", + "test/core/end2end/tests/max_concurrent_streams.cc", + "test/core/end2end/tests/max_connection_age.cc", + "test/core/end2end/tests/max_connection_idle.cc", + "test/core/end2end/tests/max_message_length.cc", + "test/core/end2end/tests/negative_deadline.cc", + "test/core/end2end/tests/network_status_change.cc", + "test/core/end2end/tests/no_logging.cc", + "test/core/end2end/tests/no_op.cc", + "test/core/end2end/tests/payload.cc", + "test/core/end2end/tests/ping.cc", + "test/core/end2end/tests/ping_pong_streaming.cc", + "test/core/end2end/tests/proxy_auth.cc", + "test/core/end2end/tests/registered_call.cc", + "test/core/end2end/tests/request_with_flags.cc", + "test/core/end2end/tests/request_with_payload.cc", + "test/core/end2end/tests/resource_quota_server.cc", + "test/core/end2end/tests/server_finishes_request.cc", + "test/core/end2end/tests/shutdown_finishes_calls.cc", + "test/core/end2end/tests/shutdown_finishes_tags.cc", + "test/core/end2end/tests/simple_cacheable_request.cc", + "test/core/end2end/tests/simple_delayed_request.cc", + "test/core/end2end/tests/simple_metadata.cc", + "test/core/end2end/tests/simple_request.cc", + "test/core/end2end/tests/stream_compression_compressed_payload.cc", + "test/core/end2end/tests/stream_compression_payload.cc", + "test/core/end2end/tests/stream_compression_ping_pong_streaming.cc", + "test/core/end2end/tests/streaming_error_response.cc", + "test/core/end2end/tests/trailing_metadata.cc", + "test/core/end2end/tests/workaround_cronet_compression.cc", + "test/core/end2end/tests/write_buffering.cc", + "test/core/end2end/tests/write_buffering_at_end.cc" ], "third_party": false, "type": "lib" @@ -7658,68 +7658,68 @@ "language": "c", "name": "end2end_nosec_tests", "src": [ - "test/core/end2end/end2end_nosec_tests.c", - "test/core/end2end/end2end_test_utils.c", + "test/core/end2end/end2end_nosec_tests.cc", + "test/core/end2end/end2end_test_utils.cc", "test/core/end2end/end2end_tests.h", - "test/core/end2end/tests/authority_not_supported.c", - "test/core/end2end/tests/bad_hostname.c", - "test/core/end2end/tests/bad_ping.c", - "test/core/end2end/tests/binary_metadata.c", - "test/core/end2end/tests/cancel_after_accept.c", - "test/core/end2end/tests/cancel_after_client_done.c", - "test/core/end2end/tests/cancel_after_invoke.c", - "test/core/end2end/tests/cancel_after_round_trip.c", - "test/core/end2end/tests/cancel_before_invoke.c", - "test/core/end2end/tests/cancel_in_a_vacuum.c", + "test/core/end2end/tests/authority_not_supported.cc", + "test/core/end2end/tests/bad_hostname.cc", + "test/core/end2end/tests/bad_ping.cc", + "test/core/end2end/tests/binary_metadata.cc", + "test/core/end2end/tests/cancel_after_accept.cc", + "test/core/end2end/tests/cancel_after_client_done.cc", + "test/core/end2end/tests/cancel_after_invoke.cc", + "test/core/end2end/tests/cancel_after_round_trip.cc", + "test/core/end2end/tests/cancel_before_invoke.cc", + "test/core/end2end/tests/cancel_in_a_vacuum.cc", "test/core/end2end/tests/cancel_test_helpers.h", - "test/core/end2end/tests/cancel_with_status.c", - "test/core/end2end/tests/compressed_payload.c", - "test/core/end2end/tests/connectivity.c", - "test/core/end2end/tests/default_host.c", - "test/core/end2end/tests/disappearing_server.c", - "test/core/end2end/tests/empty_batch.c", - "test/core/end2end/tests/filter_call_init_fails.c", - "test/core/end2end/tests/filter_causes_close.c", - "test/core/end2end/tests/filter_latency.c", - "test/core/end2end/tests/graceful_server_shutdown.c", - "test/core/end2end/tests/high_initial_seqno.c", - "test/core/end2end/tests/hpack_size.c", - "test/core/end2end/tests/idempotent_request.c", - "test/core/end2end/tests/invoke_large_request.c", - "test/core/end2end/tests/keepalive_timeout.c", - "test/core/end2end/tests/large_metadata.c", - "test/core/end2end/tests/load_reporting_hook.c", - "test/core/end2end/tests/max_concurrent_streams.c", - "test/core/end2end/tests/max_connection_age.c", - "test/core/end2end/tests/max_connection_idle.c", - "test/core/end2end/tests/max_message_length.c", - "test/core/end2end/tests/negative_deadline.c", - "test/core/end2end/tests/network_status_change.c", - "test/core/end2end/tests/no_logging.c", - "test/core/end2end/tests/no_op.c", - "test/core/end2end/tests/payload.c", - "test/core/end2end/tests/ping.c", - "test/core/end2end/tests/ping_pong_streaming.c", - "test/core/end2end/tests/proxy_auth.c", - "test/core/end2end/tests/registered_call.c", - "test/core/end2end/tests/request_with_flags.c", - "test/core/end2end/tests/request_with_payload.c", - "test/core/end2end/tests/resource_quota_server.c", - "test/core/end2end/tests/server_finishes_request.c", - "test/core/end2end/tests/shutdown_finishes_calls.c", - "test/core/end2end/tests/shutdown_finishes_tags.c", - "test/core/end2end/tests/simple_cacheable_request.c", - "test/core/end2end/tests/simple_delayed_request.c", - "test/core/end2end/tests/simple_metadata.c", - "test/core/end2end/tests/simple_request.c", - "test/core/end2end/tests/stream_compression_compressed_payload.c", - "test/core/end2end/tests/stream_compression_payload.c", - "test/core/end2end/tests/stream_compression_ping_pong_streaming.c", - "test/core/end2end/tests/streaming_error_response.c", - "test/core/end2end/tests/trailing_metadata.c", - "test/core/end2end/tests/workaround_cronet_compression.c", - "test/core/end2end/tests/write_buffering.c", - "test/core/end2end/tests/write_buffering_at_end.c" + "test/core/end2end/tests/cancel_with_status.cc", + "test/core/end2end/tests/compressed_payload.cc", + "test/core/end2end/tests/connectivity.cc", + "test/core/end2end/tests/default_host.cc", + "test/core/end2end/tests/disappearing_server.cc", + "test/core/end2end/tests/empty_batch.cc", + "test/core/end2end/tests/filter_call_init_fails.cc", + "test/core/end2end/tests/filter_causes_close.cc", + "test/core/end2end/tests/filter_latency.cc", + "test/core/end2end/tests/graceful_server_shutdown.cc", + "test/core/end2end/tests/high_initial_seqno.cc", + "test/core/end2end/tests/hpack_size.cc", + "test/core/end2end/tests/idempotent_request.cc", + "test/core/end2end/tests/invoke_large_request.cc", + "test/core/end2end/tests/keepalive_timeout.cc", + "test/core/end2end/tests/large_metadata.cc", + "test/core/end2end/tests/load_reporting_hook.cc", + "test/core/end2end/tests/max_concurrent_streams.cc", + "test/core/end2end/tests/max_connection_age.cc", + "test/core/end2end/tests/max_connection_idle.cc", + "test/core/end2end/tests/max_message_length.cc", + "test/core/end2end/tests/negative_deadline.cc", + "test/core/end2end/tests/network_status_change.cc", + "test/core/end2end/tests/no_logging.cc", + "test/core/end2end/tests/no_op.cc", + "test/core/end2end/tests/payload.cc", + "test/core/end2end/tests/ping.cc", + "test/core/end2end/tests/ping_pong_streaming.cc", + "test/core/end2end/tests/proxy_auth.cc", + "test/core/end2end/tests/registered_call.cc", + "test/core/end2end/tests/request_with_flags.cc", + "test/core/end2end/tests/request_with_payload.cc", + "test/core/end2end/tests/resource_quota_server.cc", + "test/core/end2end/tests/server_finishes_request.cc", + "test/core/end2end/tests/shutdown_finishes_calls.cc", + "test/core/end2end/tests/shutdown_finishes_tags.cc", + "test/core/end2end/tests/simple_cacheable_request.cc", + "test/core/end2end/tests/simple_delayed_request.cc", + "test/core/end2end/tests/simple_metadata.cc", + "test/core/end2end/tests/simple_request.cc", + "test/core/end2end/tests/stream_compression_compressed_payload.cc", + "test/core/end2end/tests/stream_compression_payload.cc", + "test/core/end2end/tests/stream_compression_ping_pong_streaming.cc", + "test/core/end2end/tests/streaming_error_response.cc", + "test/core/end2end/tests/trailing_metadata.cc", + "test/core/end2end/tests/workaround_cronet_compression.cc", + "test/core/end2end/tests/write_buffering.cc", + "test/core/end2end/tests/write_buffering_at_end.cc" ], "third_party": false, "type": "lib" @@ -8957,33 +8957,33 @@ "src": [ "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc", "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h", - "test/core/end2end/cq_verifier.c", + "test/core/end2end/cq_verifier.cc", "test/core/end2end/cq_verifier.h", - "test/core/end2end/fixtures/http_proxy_fixture.c", + "test/core/end2end/fixtures/http_proxy_fixture.cc", "test/core/end2end/fixtures/http_proxy_fixture.h", - "test/core/end2end/fixtures/proxy.c", + "test/core/end2end/fixtures/proxy.cc", "test/core/end2end/fixtures/proxy.h", - "test/core/iomgr/endpoint_tests.c", + "test/core/iomgr/endpoint_tests.cc", "test/core/iomgr/endpoint_tests.h", "test/core/util/debugger_macros.cc", "test/core/util/debugger_macros.h", - "test/core/util/grpc_profiler.c", + "test/core/util/grpc_profiler.cc", "test/core/util/grpc_profiler.h", - "test/core/util/memory_counters.c", + "test/core/util/memory_counters.cc", "test/core/util/memory_counters.h", - "test/core/util/mock_endpoint.c", + "test/core/util/mock_endpoint.cc", "test/core/util/mock_endpoint.h", - "test/core/util/parse_hexstring.c", + "test/core/util/parse_hexstring.cc", "test/core/util/parse_hexstring.h", - "test/core/util/passthru_endpoint.c", + "test/core/util/passthru_endpoint.cc", "test/core/util/passthru_endpoint.h", - "test/core/util/port.c", + "test/core/util/port.cc", "test/core/util/port.h", - "test/core/util/port_server_client.c", + "test/core/util/port_server_client.cc", "test/core/util/port_server_client.h", - "test/core/util/slice_splitter.c", + "test/core/util/slice_splitter.cc", "test/core/util/slice_splitter.h", - "test/core/util/trickle_endpoint.c", + "test/core/util/trickle_endpoint.cc", "test/core/util/trickle_endpoint.h" ], "third_party": false, @@ -9349,7 +9349,7 @@ "language": "c", "name": "transport_security_test_lib", "src": [ - "test/core/tsi/transport_security_test_lib.c", + "test/core/tsi/transport_security_test_lib.cc", "test/core/tsi/transport_security_test_lib.h" ], "third_party": false, -- cgit v1.2.3 From e098d2eb5bfa58376a60b49989cb66c59b420755 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 1 Nov 2017 15:34:46 -0700 Subject: Finish conversion --- src/core/lib/iomgr/ev_epoll1_linux.cc | 30 +++++++++++++++--------------- src/core/lib/iomgr/ev_epollsig_linux.cc | 28 ++++++++++++++-------------- src/core/lib/iomgr/lockfree_event.h | 1 + 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 6126e2771c..9fc560c542 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/lockfree_event.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/string.h" static grpc_wakeup_fd global_wakeup_fd; @@ -111,8 +112,8 @@ static void epoll_set_shutdown() { struct grpc_fd { int fd; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd *freelist_next; @@ -264,8 +265,8 @@ static grpc_fd *fd_create(int fd, const char *name) { } new_fd->fd = fd; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -297,12 +298,11 @@ static int fd_wrapped_fd(grpc_fd *fd) { return fd->fd; } * shutdown() syscall on that fd) */ static void fd_shutdown_internal(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why, bool releasing_fd) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { if (!releasing_fd) { shutdown(fd->fd, SHUT_RDWR); } - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } @@ -318,7 +318,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *error = GRPC_ERROR_NONE; bool is_release_fd = (release_fd != NULL); - if (!grpc_lfev_is_shutdown(&fd->read_closure)) { + if (!fd->read_closure->IsShutdown()) { fd_shutdown_internal(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason), is_release_fd); @@ -335,8 +335,8 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_REF(error)); grpc_iomgr_unregister_object(&fd->iomgr_object); - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; @@ -351,28 +351,28 @@ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, } static bool fd_is_shutdown(grpc_fd *fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Use release store to match with acquire load in fd_get_read_notifier */ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); } static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } /******************************************************************************* diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc index 035bdc4cb5..46333569c3 100644 --- a/src/core/lib/iomgr/ev_epollsig_linux.cc +++ b/src/core/lib/iomgr/ev_epollsig_linux.cc @@ -50,6 +50,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) @@ -127,8 +128,8 @@ struct grpc_fd { valid */ bool orphaned; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd *freelist_next; grpc_closure *on_done_closure; @@ -764,8 +765,8 @@ static void unref_by(grpc_fd *fd, int n) { fd_freelist = fd; grpc_iomgr_unregister_object(&fd->iomgr_object); - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_unlock(&fd_freelist_mu); } else { @@ -830,8 +831,8 @@ static grpc_fd *fd_create(int fd, const char *name) { gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; new_fd->orphaned = false; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -922,27 +923,26 @@ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, } static bool fd_is_shutdown(grpc_fd *fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } /******************************************************************************* @@ -1106,7 +1106,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx *exec_ctx, static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -1118,7 +1118,7 @@ static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, } static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index d843c340a1..c985feef89 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -29,6 +29,7 @@ namespace grpc_core { class LockfreeEvent { public: + LockfreeEvent() = default; ~LockfreeEvent(); LockfreeEvent(const LockfreeEvent &) = delete; -- cgit v1.2.3 From c60659ad023d01f8d0f6ad0f87fefbd3740002d0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 1 Nov 2017 15:36:13 -0700 Subject: Review feedback --- src/core/lib/iomgr/lockfree_event.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index 549747b34b..d1273beee3 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -70,7 +70,7 @@ void LockfreeEvent::NotifyOn(grpc_exec_ctx *exec_ctx, grpc_closure *closure) { while (true) { gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_notify_on: %p curr=%p closure=%p", this, + gpr_log(GPR_ERROR, "LockfreeEvent::NotifyOn: %p curr=%p closure=%p", this, (void *)curr, closure); } switch (curr) { @@ -120,7 +120,8 @@ void LockfreeEvent::NotifyOn(grpc_exec_ctx *exec_ctx, grpc_closure *closure) { /* There is already a closure!. This indicates a bug in the code */ gpr_log(GPR_ERROR, - "notify_on called with a previous callback still pending"); + "LockfreeEvent::NotifyOn: notify_on called with a previous " + "callback still pending"); abort(); } } @@ -136,8 +137,8 @@ bool LockfreeEvent::SetShutdown(grpc_exec_ctx *exec_ctx, while (true) { gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", &state_, - (void *)curr, grpc_error_string(shutdown_err)); + gpr_log(GPR_ERROR, "LockfreeEvent::SetShutdown: %p curr=%p err=%s", + &state_, (void *)curr, grpc_error_string(shutdown_err)); } switch (curr) { case kClosureReady: @@ -185,7 +186,8 @@ void LockfreeEvent::SetReady(grpc_exec_ctx *exec_ctx) { gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_ready: %p curr=%p", &state_, (void *)curr); + gpr_log(GPR_ERROR, "LockfreeEvent::SetReady: %p curr=%p", &state_, + (void *)curr); } switch (curr) { -- cgit v1.2.3 From 62a4fd3523b322b4c32bf947b483ef7aebead63a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 4 Nov 2017 18:09:12 +0100 Subject: invalidate after wait in nonpolling poller --- src/core/lib/surface/completion_queue.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 5009f786e6..836314f90a 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -127,6 +127,7 @@ static grpc_error *non_polling_poller_work(grpc_exec_ctx *exec_ctx, while (!npp->shutdown && !w.kicked && !gpr_cv_wait(&w.cv, &npp->mu, deadline_ts)) ; + grpc_exec_ctx_invalidate_now(exec_ctx); if (&w == npp->root) { npp->root = w.next; if (&w == npp->root) { -- cgit v1.2.3 From 240256fd2497d7ce03f38db5c399466e1bb25d37 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 6 Nov 2017 16:32:29 -0800 Subject: Forward fix for PR #13235. Perform strcmp only when not NULL --- src/core/lib/security/transport/client_auth_filter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc index 8f7530ed27..11f5a13ccc 100644 --- a/src/core/lib/security/transport/client_auth_filter.cc +++ b/src/core/lib/security/transport/client_auth_filter.cc @@ -139,7 +139,7 @@ void grpc_auth_metadata_context_build( method_name = gpr_strdup(last_slash + 1); } char* host_and_port = grpc_slice_to_c_string(call_host); - if (strcmp(url_scheme, GRPC_SSL_URL_SCHEME) == 0) { + if (url_scheme != NULL && strcmp(url_scheme, GRPC_SSL_URL_SCHEME) == 0) { /* Remove the port if it is 443. */ char* port_delimiter = strrchr(host_and_port, ':'); if (port_delimiter != NULL && strcmp(port_delimiter + 1, "443") == 0) { -- cgit v1.2.3 From e1533572d517df2e660cf57556d296b59ab89cfc Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 7 Nov 2017 11:27:02 -0800 Subject: Add back mpscq request matcher --- include/grpc++/server_builder.h | 5 +- src/core/lib/support/mpscq.cc | 37 ++++++- src/core/lib/support/mpscq.h | 30 ++++- src/core/lib/surface/completion_queue.cc | 2 +- src/core/lib/surface/server.cc | 181 ++++++++++--------------------- 5 files changed, 130 insertions(+), 125 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 0888bef0d9..bf842baf6f 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -202,7 +202,10 @@ class ServerBuilder { struct SyncServerSettings { SyncServerSettings() - : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {} + : num_cqs(GPR_MAX(1, gpr_cpu_num_cores())), + min_pollers(1), + max_pollers(2), + cq_timeout_msec(10000) {} /// Number of server completion queues to create to listen to incoming RPCs. int num_cqs; diff --git a/src/core/lib/support/mpscq.cc b/src/core/lib/support/mpscq.cc index db25f24264..b270777d5c 100644 --- a/src/core/lib/support/mpscq.cc +++ b/src/core/lib/support/mpscq.cc @@ -31,11 +31,12 @@ void gpr_mpscq_destroy(gpr_mpscq* q) { GPR_ASSERT(q->tail == &q->stub); } -void gpr_mpscq_push(gpr_mpscq* q, gpr_mpscq_node* n) { +bool gpr_mpscq_push(gpr_mpscq* q, gpr_mpscq_node* n) { gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); gpr_mpscq_node* prev = (gpr_mpscq_node*)gpr_atm_full_xchg(&q->head, (gpr_atm)n); gpr_atm_rel_store(&prev->next, (gpr_atm)n); + return prev == &q->stub; } gpr_mpscq_node* gpr_mpscq_pop(gpr_mpscq* q) { @@ -77,3 +78,37 @@ gpr_mpscq_node* gpr_mpscq_pop_and_check_end(gpr_mpscq* q, bool* empty) { *empty = false; return NULL; } + +void gpr_locked_mpscq_init(gpr_locked_mpscq* q) { + gpr_mpscq_init(&q->queue); + gpr_mu_init(&q->mu); +} + +void gpr_locked_mpscq_destroy(gpr_locked_mpscq* q) { + gpr_mpscq_destroy(&q->queue); + gpr_mu_destroy(&q->mu); +} + +bool gpr_locked_mpscq_push(gpr_locked_mpscq* q, gpr_mpscq_node* n) { + return gpr_mpscq_push(&q->queue, n); +} + +gpr_mpscq_node* gpr_locked_mpscq_try_pop(gpr_locked_mpscq* q) { + if (gpr_mu_trylock(&q->mu)) { + gpr_mpscq_node* n = gpr_mpscq_pop(&q->queue); + gpr_mu_unlock(&q->mu); + return n; + } + return NULL; +} + +gpr_mpscq_node* gpr_locked_mpscq_pop(gpr_locked_mpscq* q) { + gpr_mu_lock(&q->mu); + bool empty = false; + gpr_mpscq_node* n; + do { + n = gpr_mpscq_pop_and_check_end(&q->queue, &empty); + } while (n == NULL && !empty); + gpr_mu_unlock(&q->mu); + return n; +} diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index 1cc9d89feb..fb22742050 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -20,6 +20,7 @@ #define GRPC_CORE_LIB_SUPPORT_MPSCQ_H #include +#include #include #include @@ -49,13 +50,40 @@ typedef struct gpr_mpscq { void gpr_mpscq_init(gpr_mpscq* q); void gpr_mpscq_destroy(gpr_mpscq* q); // Push a node -void gpr_mpscq_push(gpr_mpscq* q, gpr_mpscq_node* n); +// Thread safe - can be called from multiple threads concurrently +// Returns true if this was possibly the first node (may return true +// sporadically, will not return false sporadically) +bool gpr_mpscq_push(gpr_mpscq* q, gpr_mpscq_node* n); // Pop a node (returns NULL if no node is ready - which doesn't indicate that // the queue is empty!!) +// Thread compatible - can only be called from one thread at a time gpr_mpscq_node* gpr_mpscq_pop(gpr_mpscq* q); // Pop a node; sets *empty to true if the queue is empty, or false if it is not gpr_mpscq_node* gpr_mpscq_pop_and_check_end(gpr_mpscq* q, bool* empty); +// An mpscq with a lock: it's safe to pop from multiple threads, but doing +// only one thread will succeed concurrently +typedef struct gpr_locked_mpscq { + gpr_mpscq queue; + gpr_mu mu; +} gpr_locked_mpscq; + +void gpr_locked_mpscq_init(gpr_locked_mpscq* q); +void gpr_locked_mpscq_destroy(gpr_locked_mpscq* q); +// Push a node +// Thread safe - can be called from multiple threads concurrently +// Returns true if this was possibly the first node (may return true +// sporadically, will not return false sporadically) +bool gpr_locked_mpscq_push(gpr_locked_mpscq* q, gpr_mpscq_node* n); + +// Pop a node (returns NULL if no node is ready - which doesn't indicate that +// the queue is empty!!) +// Thread safe - can be called from multiple threads concurrently +gpr_mpscq_node* gpr_locked_mpscq_try_pop(gpr_locked_mpscq* q); + +// Pop a node. Returns NULL only if the queue was empty at some point after +// calling this function +gpr_mpscq_node* gpr_locked_mpscq_pop(gpr_locked_mpscq* q); #ifdef __cplusplus } #endif diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 14054e82e7..922df923ae 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -376,8 +376,8 @@ int grpc_completion_queue_thread_local_cache_flush(grpc_completion_queue* cq, (grpc_completion_queue*)gpr_tls_get(&g_cached_cq) == cq) { *tag = storage->tag; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - storage->done(&exec_ctx, storage->done_arg, storage); *ok = (storage->next & (uintptr_t)(1)) == 1; + storage->done(&exec_ctx, storage->done_arg, storage); ret = 1; cq_next_data* cqd = (cq_next_data*)DATA_FROM_CQ(cq); if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index eb7a4e2d30..da7ae17bef 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -33,7 +33,8 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/support/stack_lockfree.h" +#include "src/core/lib/support/mpscq.h" +#include "src/core/lib/support/spinlock.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" @@ -63,6 +64,7 @@ grpc_tracer_flag grpc_server_channel_trace = GRPC_TRACER_INITIALIZER(false, "server_channel"); typedef struct requested_call { + gpr_mpscq_node request_link; /* must be first */ requested_call_type type; size_t cq_idx; void* tag; @@ -128,10 +130,7 @@ typedef struct request_matcher request_matcher; struct call_data { grpc_call* call; - /** protects state */ - gpr_mu mu_state; - /** the current state of a call - see call_state */ - call_state state; + gpr_atm state; bool path_set; bool host_set; @@ -162,7 +161,7 @@ struct request_matcher { grpc_server* server; call_data* pending_head; call_data* pending_tail; - gpr_stack_lockfree** requests_per_cq; + gpr_locked_mpscq* requests_per_cq; }; struct registered_method { @@ -207,11 +206,6 @@ struct grpc_server { registered_method* registered_methods; /** one request matcher for unregistered methods */ request_matcher unregistered_request_matcher; - /** free list of available requested_calls_per_cq indices */ - gpr_stack_lockfree** request_freelist_per_cq; - /** requested call backing data */ - requested_call** requested_calls_per_cq; - int max_requested_calls_per_cq; gpr_atm shutdown_flag; uint8_t shutdown_published; @@ -313,21 +307,20 @@ static void channel_broadcaster_shutdown(grpc_exec_ctx* exec_ctx, * request_matcher */ -static void request_matcher_init(request_matcher* rm, size_t entries, - grpc_server* server) { +static void request_matcher_init(request_matcher* rm, grpc_server* server) { memset(rm, 0, sizeof(*rm)); rm->server = server; - rm->requests_per_cq = (gpr_stack_lockfree**)gpr_malloc( + rm->requests_per_cq = (gpr_locked_mpscq*)gpr_malloc( sizeof(*rm->requests_per_cq) * server->cq_count); for (size_t i = 0; i < server->cq_count; i++) { - rm->requests_per_cq[i] = gpr_stack_lockfree_create(entries); + gpr_locked_mpscq_init(&rm->requests_per_cq[i]); } } static void request_matcher_destroy(request_matcher* rm) { for (size_t i = 0; i < rm->server->cq_count; i++) { - GPR_ASSERT(gpr_stack_lockfree_pop(rm->requests_per_cq[i]) == -1); - gpr_stack_lockfree_destroy(rm->requests_per_cq[i]); + GPR_ASSERT(gpr_locked_mpscq_pop(&rm->requests_per_cq[i]) == NULL); + gpr_locked_mpscq_destroy(&rm->requests_per_cq[i]); } gpr_free(rm->requests_per_cq); } @@ -342,9 +335,7 @@ static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx* exec_ctx, while (rm->pending_head) { call_data* calld = rm->pending_head; rm->pending_head = calld->pending_next; - gpr_mu_lock(&calld->mu_state); - calld->state = ZOMBIED; - gpr_mu_unlock(&calld->mu_state); + gpr_atm_no_barrier_store(&calld->state, ZOMBIED); GRPC_CLOSURE_INIT( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), @@ -357,13 +348,17 @@ static void request_matcher_kill_requests(grpc_exec_ctx* exec_ctx, grpc_server* server, request_matcher* rm, grpc_error* error) { - int request_id; + requested_call* rc; for (size_t i = 0; i < server->cq_count; i++) { - while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) != - -1) { - fail_call(exec_ctx, server, i, - &server->requested_calls_per_cq[i][request_id], - GRPC_ERROR_REF(error)); + /* Here we know: + 1. no requests are being added (since the server is shut down) + 2. no other threads are pulling (since the shut down process is single + threaded) + So, we can ignore the queue lock and just pop, with the guarantee that a + NULL returned here truly means that the queue is empty */ + while ((rc = (requested_call*)gpr_mpscq_pop( + &rm->requests_per_cq[i].queue)) != NULL) { + fail_call(exec_ctx, server, i, rc, GRPC_ERROR_REF(error)); } } GRPC_ERROR_UNREF(error); @@ -398,13 +393,7 @@ static void server_delete(grpc_exec_ctx* exec_ctx, grpc_server* server) { } for (i = 0; i < server->cq_count; i++) { GRPC_CQ_INTERNAL_UNREF(exec_ctx, server->cqs[i], "server"); - if (server->started) { - gpr_stack_lockfree_destroy(server->request_freelist_per_cq[i]); - gpr_free(server->requested_calls_per_cq[i]); - } } - gpr_free(server->request_freelist_per_cq); - gpr_free(server->requested_calls_per_cq); gpr_free(server->cqs); gpr_free(server->pollsets); gpr_free(server->shutdown_tags); @@ -462,21 +451,7 @@ static void destroy_channel(grpc_exec_ctx* exec_ctx, channel_data* chand, static void done_request_event(grpc_exec_ctx* exec_ctx, void* req, grpc_cq_completion* c) { - requested_call* rc = (requested_call*)req; - grpc_server* server = rc->server; - - if (rc >= server->requested_calls_per_cq[rc->cq_idx] && - rc < server->requested_calls_per_cq[rc->cq_idx] + - server->max_requested_calls_per_cq) { - GPR_ASSERT(rc - server->requested_calls_per_cq[rc->cq_idx] <= INT_MAX); - gpr_stack_lockfree_push( - server->request_freelist_per_cq[rc->cq_idx], - (int)(rc - server->requested_calls_per_cq[rc->cq_idx])); - } else { - gpr_free(req); - } - - server_unref(exec_ctx, server); + gpr_free(req); } static void publish_call(grpc_exec_ctx* exec_ctx, grpc_server* server, @@ -508,10 +483,6 @@ static void publish_call(grpc_exec_ctx* exec_ctx, grpc_server* server, GPR_UNREACHABLE_CODE(return ); } - grpc_call_element* elem = - grpc_call_stack_element(grpc_call_get_call_stack(call), 0); - channel_data* chand = (channel_data*)elem->channel_data; - server_ref(chand->server); grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, GRPC_ERROR_NONE, done_request_event, rc, &rc->completion); } @@ -525,9 +496,7 @@ static void publish_new_rpc(grpc_exec_ctx* exec_ctx, void* arg, grpc_server* server = rm->server; if (error != GRPC_ERROR_NONE || gpr_atm_acq_load(&server->shutdown_flag)) { - gpr_mu_lock(&calld->mu_state); - calld->state = ZOMBIED; - gpr_mu_unlock(&calld->mu_state); + gpr_atm_no_barrier_store(&calld->state, ZOMBIED); GRPC_CLOSURE_INIT( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), @@ -539,16 +508,14 @@ static void publish_new_rpc(grpc_exec_ctx* exec_ctx, void* arg, for (size_t i = 0; i < server->cq_count; i++) { size_t cq_idx = (chand->cq_idx + i) % server->cq_count; - int request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]); - if (request_id == -1) { + requested_call* rc = + (requested_call*)gpr_locked_mpscq_try_pop(&rm->requests_per_cq[cq_idx]); + if (rc == NULL) { continue; } else { GRPC_STATS_INC_SERVER_CQS_CHECKED(exec_ctx, i); - gpr_mu_lock(&calld->mu_state); - calld->state = ACTIVATED; - gpr_mu_unlock(&calld->mu_state); - publish_call(exec_ctx, server, calld, cq_idx, - &server->requested_calls_per_cq[cq_idx][request_id]); + gpr_atm_no_barrier_store(&calld->state, ACTIVATED); + publish_call(exec_ctx, server, calld, cq_idx, rc); return; /* early out */ } } @@ -556,9 +523,27 @@ static void publish_new_rpc(grpc_exec_ctx* exec_ctx, void* arg, /* no cq to take the request found: queue it on the slow list */ GRPC_STATS_INC_SERVER_SLOWPATH_REQUESTS_QUEUED(exec_ctx); gpr_mu_lock(&server->mu_call); - gpr_mu_lock(&calld->mu_state); - calld->state = PENDING; - gpr_mu_unlock(&calld->mu_state); + + // We need to ensure that all the queues are empty. We do this under + // the server mu_call lock to ensure that if something is added to + // an empty request queue, it will block until the call is actually + // added to the pending list. + for (size_t i = 0; i < server->cq_count; i++) { + size_t cq_idx = (chand->cq_idx + i) % server->cq_count; + requested_call* rc = + (requested_call*)gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]); + if (rc == NULL) { + continue; + } else { + gpr_mu_unlock(&server->mu_call); + GRPC_STATS_INC_SERVER_CQS_CHECKED(exec_ctx, i + server->cq_count); + gpr_atm_no_barrier_store(&calld->state, ACTIVATED); + publish_call(exec_ctx, server, calld, cq_idx, rc); + return; /* early out */ + } + } + + gpr_atm_no_barrier_store(&calld->state, PENDING); if (rm->pending_head == NULL) { rm->pending_tail = rm->pending_head = calld; } else { @@ -576,9 +561,7 @@ static void finish_start_new_rpc( call_data* calld = (call_data*)elem->call_data; if (gpr_atm_acq_load(&server->shutdown_flag)) { - gpr_mu_lock(&calld->mu_state); - calld->state = ZOMBIED; - gpr_mu_unlock(&calld->mu_state); + gpr_atm_no_barrier_store(&calld->state, ZOMBIED); GRPC_CLOSURE_INIT(&calld->kill_zombie_closure, kill_zombie, elem, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); @@ -807,21 +790,14 @@ static void got_initial_metadata(grpc_exec_ctx* exec_ctx, void* ptr, if (error == GRPC_ERROR_NONE) { start_new_rpc(exec_ctx, elem); } else { - gpr_mu_lock(&calld->mu_state); - if (calld->state == NOT_STARTED) { - calld->state = ZOMBIED; - gpr_mu_unlock(&calld->mu_state); + if (gpr_atm_full_cas(&calld->state, NOT_STARTED, ZOMBIED)) { GRPC_CLOSURE_INIT(&calld->kill_zombie_closure, kill_zombie, elem, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); - } else if (calld->state == PENDING) { - calld->state = ZOMBIED; - gpr_mu_unlock(&calld->mu_state); + } else if (gpr_atm_full_cas(&calld->state, PENDING, ZOMBIED)) { /* zombied call will be destroyed when it's removed from the pending queue... later */ - } else { - gpr_mu_unlock(&calld->mu_state); } } } @@ -885,7 +861,6 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, memset(calld, 0, sizeof(call_data)); calld->deadline = GRPC_MILLIS_INF_FUTURE; calld->call = grpc_call_from_top_element(elem); - gpr_mu_init(&calld->mu_state); GRPC_CLOSURE_INIT(&calld->server_on_recv_initial_metadata, server_on_recv_initial_metadata, elem, @@ -912,8 +887,6 @@ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_metadata_array_destroy(&calld->initial_metadata); grpc_byte_buffer_destroy(calld->payload); - gpr_mu_destroy(&calld->mu_state); - server_unref(exec_ctx, chand->server); } @@ -1020,8 +993,6 @@ grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { server->root_channel_data.next = server->root_channel_data.prev = &server->root_channel_data; - /* TODO(ctiller): expose a channel_arg for this */ - server->max_requested_calls_per_cq = 32768; server->channel_args = grpc_channel_args_copy(args); return server; @@ -1095,29 +1066,15 @@ void grpc_server_start(grpc_server* server) { server->pollset_count = 0; server->pollsets = (grpc_pollset**)gpr_malloc(sizeof(grpc_pollset*) * server->cq_count); - server->request_freelist_per_cq = (gpr_stack_lockfree**)gpr_malloc( - sizeof(*server->request_freelist_per_cq) * server->cq_count); - server->requested_calls_per_cq = (requested_call**)gpr_malloc( - sizeof(*server->requested_calls_per_cq) * server->cq_count); for (i = 0; i < server->cq_count; i++) { if (grpc_cq_can_listen(server->cqs[i])) { server->pollsets[server->pollset_count++] = grpc_cq_pollset(server->cqs[i]); } - server->request_freelist_per_cq[i] = - gpr_stack_lockfree_create((size_t)server->max_requested_calls_per_cq); - for (int j = 0; j < server->max_requested_calls_per_cq; j++) { - gpr_stack_lockfree_push(server->request_freelist_per_cq[i], j); - } - server->requested_calls_per_cq[i] = - (requested_call*)gpr_malloc((size_t)server->max_requested_calls_per_cq * - sizeof(*server->requested_calls_per_cq[i])); } - request_matcher_init(&server->unregistered_request_matcher, - (size_t)server->max_requested_calls_per_cq, server); + request_matcher_init(&server->unregistered_request_matcher, server); for (registered_method* rm = server->registered_methods; rm; rm = rm->next) { - request_matcher_init(&rm->matcher, - (size_t)server->max_requested_calls_per_cq, server); + request_matcher_init(&rm->matcher, server); } server_ref(server); @@ -1373,21 +1330,11 @@ static grpc_call_error queue_call_request(grpc_exec_ctx* exec_ctx, requested_call* rc) { call_data* calld = NULL; request_matcher* rm = NULL; - int request_id; if (gpr_atm_acq_load(&server->shutdown_flag)) { fail_call(exec_ctx, server, cq_idx, rc, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown")); return GRPC_CALL_OK; } - request_id = gpr_stack_lockfree_pop(server->request_freelist_per_cq[cq_idx]); - if (request_id == -1) { - /* out of request ids: just fail this one */ - fail_call(exec_ctx, server, cq_idx, rc, - grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Out of request ids"), - GRPC_ERROR_INT_LIMIT, server->max_requested_calls_per_cq)); - return GRPC_CALL_OK; - } switch (rc->type) { case BATCH_CALL: rm = &server->unregistered_request_matcher; @@ -1396,20 +1343,17 @@ static grpc_call_error queue_call_request(grpc_exec_ctx* exec_ctx, rm = &rc->data.registered.method->matcher; break; } - server->requested_calls_per_cq[cq_idx][request_id] = *rc; - gpr_free(rc); - if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) { + if (gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link)) { /* this was the first queued request: we need to lock and start matching calls */ gpr_mu_lock(&server->mu_call); while ((calld = rm->pending_head) != NULL) { - request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]); - if (request_id == -1) break; + rc = (requested_call*)gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]); + if (rc == NULL) break; rm->pending_head = calld->pending_next; gpr_mu_unlock(&server->mu_call); - gpr_mu_lock(&calld->mu_state); - if (calld->state == ZOMBIED) { - gpr_mu_unlock(&calld->mu_state); + if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) { + // Zombied Call GRPC_CLOSURE_INIT( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), @@ -1417,11 +1361,7 @@ static grpc_call_error queue_call_request(grpc_exec_ctx* exec_ctx, GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); } else { - GPR_ASSERT(calld->state == PENDING); - calld->state = ACTIVATED; - gpr_mu_unlock(&calld->mu_state); - publish_call(exec_ctx, server, calld, cq_idx, - &server->requested_calls_per_cq[cq_idx][request_id]); + publish_call(exec_ctx, server, calld, cq_idx, rc); } gpr_mu_lock(&server->mu_call); } @@ -1540,7 +1480,6 @@ static void fail_call(grpc_exec_ctx* exec_ctx, grpc_server* server, rc->initial_metadata->count = 0; GPR_ASSERT(error != GRPC_ERROR_NONE); - server_ref(server); grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, error, done_request_event, rc, &rc->completion); } -- cgit v1.2.3 From 332c7e402ab5324d4d8c26aa58780cddc98c63dc Mon Sep 17 00:00:00 2001 From: "David G. Quintas" Date: Wed, 8 Nov 2017 11:01:59 -0800 Subject: Revert "Class-ify lockfree event" --- src/core/lib/iomgr/ev_epoll1_linux.cc | 30 ++++----- src/core/lib/iomgr/ev_epollex_linux.cc | 28 ++++---- src/core/lib/iomgr/ev_epollsig_linux.cc | 28 ++++---- src/core/lib/iomgr/lockfree_event.cc | 115 +++++++++++++++++--------------- src/core/lib/iomgr/lockfree_event.h | 44 ++++++------ 5 files changed, 125 insertions(+), 120 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 9e3643fa28..504c659874 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -46,7 +46,6 @@ #include "src/core/lib/iomgr/lockfree_event.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/string.h" static grpc_wakeup_fd global_wakeup_fd; @@ -112,8 +111,8 @@ static void epoll_set_shutdown() { struct grpc_fd { int fd; - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; + gpr_atm read_closure; + gpr_atm write_closure; struct grpc_fd* freelist_next; @@ -265,8 +264,8 @@ static grpc_fd* fd_create(int fd, const char* name) { } new_fd->fd = fd; - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -298,11 +297,12 @@ static int fd_wrapped_fd(grpc_fd* fd) { return fd->fd; } * shutdown() syscall on that fd) */ static void fd_shutdown_internal(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why, bool releasing_fd) { - if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { if (!releasing_fd) { shutdown(fd->fd, SHUT_RDWR); } - fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } @@ -318,7 +318,7 @@ static void fd_orphan(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* error = GRPC_ERROR_NONE; bool is_release_fd = (release_fd != NULL); - if (!fd->read_closure->IsShutdown()) { + if (!grpc_lfev_is_shutdown(&fd->read_closure)) { fd_shutdown_internal(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason), is_release_fd); @@ -335,8 +335,8 @@ static void fd_orphan(grpc_exec_ctx* exec_ctx, grpc_fd* fd, GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_REF(error)); grpc_iomgr_unregister_object(&fd->iomgr_object); - fd->read_closure.Destroy(); - fd->write_closure.Destroy(); + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; @@ -351,28 +351,28 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return grpc_lfev_is_shutdown(&fd->read_closure); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); } static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); /* Use release store to match with acquire load in fd_get_read_notifier */ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - fd->write_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); } /******************************************************************************* diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 26ed1f6747..aafdd690c7 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -48,7 +48,6 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/spinlock.h" // debug aid: create workers on the heap (allows asan to spot @@ -154,8 +153,8 @@ struct grpc_fd { gpr_mu pollable_mu; pollable* pollable_obj; - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; + gpr_atm read_closure; + gpr_atm write_closure; struct grpc_fd* freelist_next; grpc_closure* on_done_closure; @@ -287,8 +286,8 @@ static void fd_destroy(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { fd->freelist_next = fd_freelist; fd_freelist = fd; - fd->read_closure.Destroy(); - fd->write_closure.Destroy(); + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); gpr_mu_unlock(&fd_freelist_mu); } @@ -348,8 +347,8 @@ static grpc_fd* fd_create(int fd, const char* name) { new_fd->pollable_obj = NULL; gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -412,26 +411,27 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return grpc_lfev_is_shutdown(&fd->read_closure); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); } /******************************************************************************* @@ -702,7 +702,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx* exec_ctx, static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -714,7 +714,7 @@ static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - fd->write_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); } static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) { diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc index 9a127806fa..d5f3122abc 100644 --- a/src/core/lib/iomgr/ev_epollsig_linux.cc +++ b/src/core/lib/iomgr/ev_epollsig_linux.cc @@ -50,7 +50,6 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/manual_constructor.h" #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker*)1) @@ -128,8 +127,8 @@ struct grpc_fd { valid */ bool orphaned; - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; + gpr_atm read_closure; + gpr_atm write_closure; struct grpc_fd* freelist_next; grpc_closure* on_done_closure; @@ -767,8 +766,8 @@ static void unref_by(grpc_fd* fd, int n) { fd_freelist = fd; grpc_iomgr_unregister_object(&fd->iomgr_object); - fd->read_closure.Destroy(); - fd->write_closure.Destroy(); + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); gpr_mu_unlock(&fd_freelist_mu); } else { @@ -833,8 +832,8 @@ static grpc_fd* fd_create(int fd, const char* name) { gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; new_fd->orphaned = false; - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -925,26 +924,27 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return grpc_lfev_is_shutdown(&fd->read_closure); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(exec_ctx, closure); + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); } /******************************************************************************* @@ -1108,7 +1108,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx* exec_ctx, static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - fd->read_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -1120,7 +1120,7 @@ static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - fd->write_closure->SetReady(exec_ctx); + grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); } static void pollset_release_polling_island(grpc_exec_ctx* exec_ctx, diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index 98e19f89df..443a8375b2 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -26,79 +26,92 @@ extern grpc_tracer_flag grpc_polling_trace; /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: - kClosureReady : The fd has an I/O event of interest but there is no + CLOSURE_READY : The fd has an I/O event of interest but there is no closure yet to execute - kClosureNotReady : The fd has no I/O event of interest + CLOSURE_NOT_READY : The fd has no I/O event of interest closure ptr : The closure to be executed when the fd has an I/O event of interest - shutdown_error | kShutdownBit : - 'shutdown_error' field ORed with kShutdownBit. + shutdown_error | FD_SHUTDOWN_BIT : + 'shutdown_error' field ORed with FD_SHUTDOWN_BIT. This indicates that the fd is shutdown. Since all memory allocations are word-aligned, the lower two bits of the shutdown_error pointer are always 0. So - it is safe to OR these with kShutdownBit + it is safe to OR these with FD_SHUTDOWN_BIT Valid state transitions: - <-----3------ kClosureNotReady -----1-------> kClosureReady + <-----3------ CLOSURE_NOT_READY ----1----> CLOSURE_READY | | ^ | ^ | | | | | | | | | | +--------------4----------+ 6 +---------2---------------+ | | | | | v | - +-----5-------> [shutdown_error | kShutdownBit] <-------7---------+ + +-----5-------> [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+ - For 1, 4 : See SetReady() function - For 2, 3 : See NotifyOn() function - For 5,6,7: See SetShutdown() function */ + For 1, 4 : See grpc_lfev_set_ready() function + For 2, 3 : See grpc_lfev_notify_on() function + For 5,6,7: See grpc_lfev_set_shutdown() function */ -namespace grpc_core { +#define CLOSURE_NOT_READY ((gpr_atm)0) +#define CLOSURE_READY ((gpr_atm)2) -LockfreeEvent::~LockfreeEvent() { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); - if (curr & kShutdownBit) { - GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit)); +#define FD_SHUTDOWN_BIT ((gpr_atm)1) + +void grpc_lfev_init(gpr_atm* state) { + gpr_atm_no_barrier_store(state, CLOSURE_NOT_READY); +} + +void grpc_lfev_destroy(gpr_atm* state) { + gpr_atm curr = gpr_atm_no_barrier_load(state); + if (curr & FD_SHUTDOWN_BIT) { + GRPC_ERROR_UNREF((grpc_error*)(curr & ~FD_SHUTDOWN_BIT)); } else { - GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); + GPR_ASSERT(curr == CLOSURE_NOT_READY || curr == CLOSURE_READY); } } -void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { +bool grpc_lfev_is_shutdown(gpr_atm* state) { + gpr_atm curr = gpr_atm_no_barrier_load(state); + return (curr & FD_SHUTDOWN_BIT) != 0; +} + +void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, + grpc_closure* closure, const char* variable) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); + gpr_atm curr = gpr_atm_no_barrier_load(state); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "LockfreeEvent::NotifyOn: %p curr=%p closure=%p", this, - (void*)curr, closure); + gpr_log(GPR_ERROR, "lfev_notify_on[%s]: %p curr=%p closure=%p", variable, + state, (void*)curr, closure); } switch (curr) { - case kClosureNotReady: { - /* kClosureNotReady -> . + case CLOSURE_NOT_READY: { + /* CLOSURE_NOT_READY -> . We're guaranteed by API that there's an acquire barrier before here, so there's no need to double-dip and this can be a release-only. The release itself pairs with the acquire half of a set_ready full barrier. */ - if (gpr_atm_rel_cas(&state_, kClosureNotReady, (gpr_atm)closure)) { + if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) { return; /* Successful. Return */ } break; /* retry */ } - case kClosureReady: { - /* Change the state to kClosureNotReady. Schedule the closure if + case CLOSURE_READY: { + /* Change the state to CLOSURE_NOT_READY. Schedule the closure if successful. If not, the state most likely transitioned to shutdown. We should retry. This can be a no-barrier cas since the state is being transitioned to - kClosureNotReady; set_ready and set_shutdown do not schedule any + CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any closure when transitioning out of CLOSURE_NO_READY state (i.e there is no other code that needs to 'happen-after' this) */ - if (gpr_atm_no_barrier_cas(&state_, kClosureReady, kClosureNotReady)) { + if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) { GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_NONE); return; /* Successful. Return */ } @@ -110,8 +123,8 @@ void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { /* 'curr' is either a closure or the fd is shutdown(in which case 'curr' contains a pointer to the shutdown-error). If the fd is shutdown, schedule the closure with the shutdown error */ - if ((curr & kShutdownBit) > 0) { - grpc_error* shutdown_err = (grpc_error*)(curr & ~kShutdownBit); + if ((curr & FD_SHUTDOWN_BIT) > 0) { + grpc_error* shutdown_err = (grpc_error*)(curr & ~FD_SHUTDOWN_BIT); GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -120,8 +133,7 @@ void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { /* There is already a closure!. This indicates a bug in the code */ gpr_log(GPR_ERROR, - "LockfreeEvent::NotifyOn: notify_on called with a previous " - "callback still pending"); + "notify_on called with a previous callback still pending"); abort(); } } @@ -130,22 +142,22 @@ void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { GPR_UNREACHABLE_CODE(return ); } -bool LockfreeEvent::SetShutdown(grpc_exec_ctx* exec_ctx, - grpc_error* shutdown_err) { - gpr_atm new_state = (gpr_atm)shutdown_err | kShutdownBit; +bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, + grpc_error* shutdown_err) { + gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT; while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); + gpr_atm curr = gpr_atm_no_barrier_load(state); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "LockfreeEvent::SetShutdown: %p curr=%p err=%s", - &state_, (void*)curr, grpc_error_string(shutdown_err)); + gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", state, + (void*)curr, grpc_error_string(shutdown_err)); } switch (curr) { - case kClosureReady: - case kClosureNotReady: + case CLOSURE_READY: + case CLOSURE_NOT_READY: /* Need a full barrier here so that the initial load in notify_on doesn't need a barrier */ - if (gpr_atm_full_cas(&state_, curr, new_state)) { + if (gpr_atm_full_cas(state, curr, new_state)) { return true; /* early out */ } break; /* retry */ @@ -154,7 +166,7 @@ bool LockfreeEvent::SetShutdown(grpc_exec_ctx* exec_ctx, /* 'curr' is either a closure or the fd is already shutdown */ /* If fd is already shutdown, we are done */ - if ((curr & kShutdownBit) > 0) { + if ((curr & FD_SHUTDOWN_BIT) > 0) { GRPC_ERROR_UNREF(shutdown_err); return false; } @@ -164,7 +176,7 @@ bool LockfreeEvent::SetShutdown(grpc_exec_ctx* exec_ctx, Needs an acquire to pair with setting the closure (and get a happens-after on that edge), and a release to pair with anything loading the shutdown state. */ - if (gpr_atm_full_cas(&state_, curr, new_state)) { + if (gpr_atm_full_cas(state, curr, new_state)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure*)curr, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -181,25 +193,26 @@ bool LockfreeEvent::SetShutdown(grpc_exec_ctx* exec_ctx, GPR_UNREACHABLE_CODE(return false); } -void LockfreeEvent::SetReady(grpc_exec_ctx* exec_ctx) { +void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, + const char* variable) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); + gpr_atm curr = gpr_atm_no_barrier_load(state); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "LockfreeEvent::SetReady: %p curr=%p", &state_, + gpr_log(GPR_ERROR, "lfev_set_ready[%s]: %p curr=%p", variable, state, (void*)curr); } switch (curr) { - case kClosureReady: { + case CLOSURE_READY: { /* Already ready. We are done here */ return; } - case kClosureNotReady: { + case CLOSURE_NOT_READY: { /* No barrier required as we're transitioning to a state that does not involve a closure */ - if (gpr_atm_no_barrier_cas(&state_, kClosureNotReady, kClosureReady)) { + if (gpr_atm_no_barrier_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) { return; /* early out */ } break; /* retry */ @@ -207,14 +220,14 @@ void LockfreeEvent::SetReady(grpc_exec_ctx* exec_ctx) { default: { /* 'curr' is either a closure or the fd is shutdown */ - if ((curr & kShutdownBit) > 0) { + if ((curr & FD_SHUTDOWN_BIT) > 0) { /* The fd is shutdown. Do nothing */ return; } /* Full cas: acquire pairs with this cas' release in the event of a spurious set_ready; release pairs with this or the acquire in notify_on (or set_shutdown) */ - else if (gpr_atm_full_cas(&state_, curr, kClosureNotReady)) { + else if (gpr_atm_full_cas(state, curr, CLOSURE_NOT_READY)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure*)curr, GRPC_ERROR_NONE); return; } @@ -226,5 +239,3 @@ void LockfreeEvent::SetReady(grpc_exec_ctx* exec_ctx) { } } } - -} // namespace grpc_core diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index 47d0089c01..75526d6b9f 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -25,30 +25,24 @@ #include "src/core/lib/iomgr/exec_ctx.h" -namespace grpc_core { - -class LockfreeEvent { - public: - LockfreeEvent() = default; - ~LockfreeEvent(); - - LockfreeEvent(const LockfreeEvent&) = delete; - LockfreeEvent& operator=(const LockfreeEvent&) = delete; - - bool IsShutdown() const { - return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0; - } - - void NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure); - bool SetShutdown(grpc_exec_ctx* exec_ctx, grpc_error* error); - void SetReady(grpc_exec_ctx* exec_ctx); - - private: - enum State { kClosureNotReady = 0, kClosureReady = 2, kShutdownBit = 1 }; - - gpr_atm state_ = kClosureNotReady; -}; - -} // namespace grpc_core +#ifdef __cplusplus +extern "C" { +#endif + +void grpc_lfev_init(gpr_atm* state); +void grpc_lfev_destroy(gpr_atm* state); +bool grpc_lfev_is_shutdown(gpr_atm* state); + +void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, + grpc_closure* closure, const char* variable); +/* Returns true on first successful shutdown */ +bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, + grpc_error* shutdown_err); +void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, + const char* variable); + +#ifdef __cplusplus +} +#endif #endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */ -- cgit v1.2.3 From fbf61bbc1abe671d9e5b1a8177a6be2abf9d5e23 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 8 Nov 2017 11:50:14 -0800 Subject: Revert "Revert "Class-ify lockfree event"" --- src/core/lib/iomgr/ev_epoll1_linux.cc | 30 ++++----- src/core/lib/iomgr/ev_epollex_linux.cc | 28 ++++---- src/core/lib/iomgr/ev_epollsig_linux.cc | 28 ++++---- src/core/lib/iomgr/lockfree_event.cc | 115 +++++++++++++++----------------- src/core/lib/iomgr/lockfree_event.h | 44 ++++++------ 5 files changed, 120 insertions(+), 125 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 504c659874..9e3643fa28 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/lockfree_event.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/string.h" static grpc_wakeup_fd global_wakeup_fd; @@ -111,8 +112,8 @@ static void epoll_set_shutdown() { struct grpc_fd { int fd; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd* freelist_next; @@ -264,8 +265,8 @@ static grpc_fd* fd_create(int fd, const char* name) { } new_fd->fd = fd; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -297,12 +298,11 @@ static int fd_wrapped_fd(grpc_fd* fd) { return fd->fd; } * shutdown() syscall on that fd) */ static void fd_shutdown_internal(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why, bool releasing_fd) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { if (!releasing_fd) { shutdown(fd->fd, SHUT_RDWR); } - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } @@ -318,7 +318,7 @@ static void fd_orphan(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* error = GRPC_ERROR_NONE; bool is_release_fd = (release_fd != NULL); - if (!grpc_lfev_is_shutdown(&fd->read_closure)) { + if (!fd->read_closure->IsShutdown()) { fd_shutdown_internal(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason), is_release_fd); @@ -335,8 +335,8 @@ static void fd_orphan(grpc_exec_ctx* exec_ctx, grpc_fd* fd, GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_REF(error)); grpc_iomgr_unregister_object(&fd->iomgr_object); - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; @@ -351,28 +351,28 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Use release store to match with acquire load in fd_get_read_notifier */ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } /******************************************************************************* diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index aafdd690c7..26ed1f6747 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -48,6 +48,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #include "src/core/lib/support/spinlock.h" // debug aid: create workers on the heap (allows asan to spot @@ -153,8 +154,8 @@ struct grpc_fd { gpr_mu pollable_mu; pollable* pollable_obj; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd* freelist_next; grpc_closure* on_done_closure; @@ -286,8 +287,8 @@ static void fd_destroy(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { fd->freelist_next = fd_freelist; fd_freelist = fd; - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_unlock(&fd_freelist_mu); } @@ -347,8 +348,8 @@ static grpc_fd* fd_create(int fd, const char* name) { new_fd->pollable_obj = NULL; gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -411,27 +412,26 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } /******************************************************************************* @@ -702,7 +702,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx* exec_ctx, static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -714,7 +714,7 @@ static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) { diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc index d5f3122abc..9a127806fa 100644 --- a/src/core/lib/iomgr/ev_epollsig_linux.cc +++ b/src/core/lib/iomgr/ev_epollsig_linux.cc @@ -50,6 +50,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/manual_constructor.h" #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker*)1) @@ -127,8 +128,8 @@ struct grpc_fd { valid */ bool orphaned; - gpr_atm read_closure; - gpr_atm write_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; struct grpc_fd* freelist_next; grpc_closure* on_done_closure; @@ -766,8 +767,8 @@ static void unref_by(grpc_fd* fd, int n) { fd_freelist = fd; grpc_iomgr_unregister_object(&fd->iomgr_object); - grpc_lfev_destroy(&fd->read_closure); - grpc_lfev_destroy(&fd->write_closure); + fd->read_closure.Destroy(); + fd->write_closure.Destroy(); gpr_mu_unlock(&fd_freelist_mu); } else { @@ -832,8 +833,8 @@ static grpc_fd* fd_create(int fd, const char* name) { gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; new_fd->orphaned = false; - grpc_lfev_init(&new_fd->read_closure); - grpc_lfev_init(&new_fd->write_closure); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; @@ -924,27 +925,26 @@ static grpc_pollset* fd_get_read_notifier_pollset(grpc_exec_ctx* exec_ctx, } static bool fd_is_shutdown(grpc_fd* fd) { - return grpc_lfev_is_shutdown(&fd->read_closure); + return fd->read_closure->IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_error* why) { - if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, - GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); - grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(exec_ctx, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure, "read"); + fd->read_closure->NotifyOn(exec_ctx, closure); } static void fd_notify_on_write(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_closure* closure) { - grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure, "write"); + fd->write_closure->NotifyOn(exec_ctx, closure); } /******************************************************************************* @@ -1108,7 +1108,7 @@ static int poll_deadline_to_millis_timeout(grpc_exec_ctx* exec_ctx, static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, grpc_pollset* notifier) { - grpc_lfev_set_ready(exec_ctx, &fd->read_closure, "read"); + fd->read_closure->SetReady(exec_ctx); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll @@ -1120,7 +1120,7 @@ static void fd_become_readable(grpc_exec_ctx* exec_ctx, grpc_fd* fd, } static void fd_become_writable(grpc_exec_ctx* exec_ctx, grpc_fd* fd) { - grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write"); + fd->write_closure->SetReady(exec_ctx); } static void pollset_release_polling_island(grpc_exec_ctx* exec_ctx, diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index 443a8375b2..98e19f89df 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -26,92 +26,79 @@ extern grpc_tracer_flag grpc_polling_trace; /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: - CLOSURE_READY : The fd has an I/O event of interest but there is no + kClosureReady : The fd has an I/O event of interest but there is no closure yet to execute - CLOSURE_NOT_READY : The fd has no I/O event of interest + kClosureNotReady : The fd has no I/O event of interest closure ptr : The closure to be executed when the fd has an I/O event of interest - shutdown_error | FD_SHUTDOWN_BIT : - 'shutdown_error' field ORed with FD_SHUTDOWN_BIT. + shutdown_error | kShutdownBit : + 'shutdown_error' field ORed with kShutdownBit. This indicates that the fd is shutdown. Since all memory allocations are word-aligned, the lower two bits of the shutdown_error pointer are always 0. So - it is safe to OR these with FD_SHUTDOWN_BIT + it is safe to OR these with kShutdownBit Valid state transitions: - <-----3------ CLOSURE_NOT_READY ----1----> CLOSURE_READY + <-----3------ kClosureNotReady -----1-------> kClosureReady | | ^ | ^ | | | | | | | | | | +--------------4----------+ 6 +---------2---------------+ | | | | | v | - +-----5-------> [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+ + +-----5-------> [shutdown_error | kShutdownBit] <-------7---------+ - For 1, 4 : See grpc_lfev_set_ready() function - For 2, 3 : See grpc_lfev_notify_on() function - For 5,6,7: See grpc_lfev_set_shutdown() function */ + For 1, 4 : See SetReady() function + For 2, 3 : See NotifyOn() function + For 5,6,7: See SetShutdown() function */ -#define CLOSURE_NOT_READY ((gpr_atm)0) -#define CLOSURE_READY ((gpr_atm)2) +namespace grpc_core { -#define FD_SHUTDOWN_BIT ((gpr_atm)1) - -void grpc_lfev_init(gpr_atm* state) { - gpr_atm_no_barrier_store(state, CLOSURE_NOT_READY); -} - -void grpc_lfev_destroy(gpr_atm* state) { - gpr_atm curr = gpr_atm_no_barrier_load(state); - if (curr & FD_SHUTDOWN_BIT) { - GRPC_ERROR_UNREF((grpc_error*)(curr & ~FD_SHUTDOWN_BIT)); +LockfreeEvent::~LockfreeEvent() { + gpr_atm curr = gpr_atm_no_barrier_load(&state_); + if (curr & kShutdownBit) { + GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit)); } else { - GPR_ASSERT(curr == CLOSURE_NOT_READY || curr == CLOSURE_READY); + GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); } } -bool grpc_lfev_is_shutdown(gpr_atm* state) { - gpr_atm curr = gpr_atm_no_barrier_load(state); - return (curr & FD_SHUTDOWN_BIT) != 0; -} - -void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, - grpc_closure* closure, const char* variable) { +void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_notify_on[%s]: %p curr=%p closure=%p", variable, - state, (void*)curr, closure); + gpr_log(GPR_ERROR, "LockfreeEvent::NotifyOn: %p curr=%p closure=%p", this, + (void*)curr, closure); } switch (curr) { - case CLOSURE_NOT_READY: { - /* CLOSURE_NOT_READY -> . + case kClosureNotReady: { + /* kClosureNotReady -> . We're guaranteed by API that there's an acquire barrier before here, so there's no need to double-dip and this can be a release-only. The release itself pairs with the acquire half of a set_ready full barrier. */ - if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) { + if (gpr_atm_rel_cas(&state_, kClosureNotReady, (gpr_atm)closure)) { return; /* Successful. Return */ } break; /* retry */ } - case CLOSURE_READY: { - /* Change the state to CLOSURE_NOT_READY. Schedule the closure if + case kClosureReady: { + /* Change the state to kClosureNotReady. Schedule the closure if successful. If not, the state most likely transitioned to shutdown. We should retry. This can be a no-barrier cas since the state is being transitioned to - CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any + kClosureNotReady; set_ready and set_shutdown do not schedule any closure when transitioning out of CLOSURE_NO_READY state (i.e there is no other code that needs to 'happen-after' this) */ - if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) { + if (gpr_atm_no_barrier_cas(&state_, kClosureReady, kClosureNotReady)) { GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_NONE); return; /* Successful. Return */ } @@ -123,8 +110,8 @@ void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, /* 'curr' is either a closure or the fd is shutdown(in which case 'curr' contains a pointer to the shutdown-error). If the fd is shutdown, schedule the closure with the shutdown error */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { - grpc_error* shutdown_err = (grpc_error*)(curr & ~FD_SHUTDOWN_BIT); + if ((curr & kShutdownBit) > 0) { + grpc_error* shutdown_err = (grpc_error*)(curr & ~kShutdownBit); GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -133,7 +120,8 @@ void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, /* There is already a closure!. This indicates a bug in the code */ gpr_log(GPR_ERROR, - "notify_on called with a previous callback still pending"); + "LockfreeEvent::NotifyOn: notify_on called with a previous " + "callback still pending"); abort(); } } @@ -142,22 +130,22 @@ void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, GPR_UNREACHABLE_CODE(return ); } -bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, - grpc_error* shutdown_err) { - gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT; +bool LockfreeEvent::SetShutdown(grpc_exec_ctx* exec_ctx, + grpc_error* shutdown_err) { + gpr_atm new_state = (gpr_atm)shutdown_err | kShutdownBit; while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_shutdown: %p curr=%p err=%s", state, - (void*)curr, grpc_error_string(shutdown_err)); + gpr_log(GPR_ERROR, "LockfreeEvent::SetShutdown: %p curr=%p err=%s", + &state_, (void*)curr, grpc_error_string(shutdown_err)); } switch (curr) { - case CLOSURE_READY: - case CLOSURE_NOT_READY: + case kClosureReady: + case kClosureNotReady: /* Need a full barrier here so that the initial load in notify_on doesn't need a barrier */ - if (gpr_atm_full_cas(state, curr, new_state)) { + if (gpr_atm_full_cas(&state_, curr, new_state)) { return true; /* early out */ } break; /* retry */ @@ -166,7 +154,7 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, /* 'curr' is either a closure or the fd is already shutdown */ /* If fd is already shutdown, we are done */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { + if ((curr & kShutdownBit) > 0) { GRPC_ERROR_UNREF(shutdown_err); return false; } @@ -176,7 +164,7 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, Needs an acquire to pair with setting the closure (and get a happens-after on that edge), and a release to pair with anything loading the shutdown state. */ - if (gpr_atm_full_cas(state, curr, new_state)) { + if (gpr_atm_full_cas(&state_, curr, new_state)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure*)curr, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -193,26 +181,25 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, GPR_UNREACHABLE_CODE(return false); } -void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, - const char* variable) { +void LockfreeEvent::SetReady(grpc_exec_ctx* exec_ctx) { while (true) { - gpr_atm curr = gpr_atm_no_barrier_load(state); + gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (GRPC_TRACER_ON(grpc_polling_trace)) { - gpr_log(GPR_ERROR, "lfev_set_ready[%s]: %p curr=%p", variable, state, + gpr_log(GPR_ERROR, "LockfreeEvent::SetReady: %p curr=%p", &state_, (void*)curr); } switch (curr) { - case CLOSURE_READY: { + case kClosureReady: { /* Already ready. We are done here */ return; } - case CLOSURE_NOT_READY: { + case kClosureNotReady: { /* No barrier required as we're transitioning to a state that does not involve a closure */ - if (gpr_atm_no_barrier_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) { + if (gpr_atm_no_barrier_cas(&state_, kClosureNotReady, kClosureReady)) { return; /* early out */ } break; /* retry */ @@ -220,14 +207,14 @@ void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, default: { /* 'curr' is either a closure or the fd is shutdown */ - if ((curr & FD_SHUTDOWN_BIT) > 0) { + if ((curr & kShutdownBit) > 0) { /* The fd is shutdown. Do nothing */ return; } /* Full cas: acquire pairs with this cas' release in the event of a spurious set_ready; release pairs with this or the acquire in notify_on (or set_shutdown) */ - else if (gpr_atm_full_cas(state, curr, CLOSURE_NOT_READY)) { + else if (gpr_atm_full_cas(&state_, curr, kClosureNotReady)) { GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure*)curr, GRPC_ERROR_NONE); return; } @@ -239,3 +226,5 @@ void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, } } } + +} // namespace grpc_core diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index 75526d6b9f..47d0089c01 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -25,24 +25,30 @@ #include "src/core/lib/iomgr/exec_ctx.h" -#ifdef __cplusplus -extern "C" { -#endif - -void grpc_lfev_init(gpr_atm* state); -void grpc_lfev_destroy(gpr_atm* state); -bool grpc_lfev_is_shutdown(gpr_atm* state); - -void grpc_lfev_notify_on(grpc_exec_ctx* exec_ctx, gpr_atm* state, - grpc_closure* closure, const char* variable); -/* Returns true on first successful shutdown */ -bool grpc_lfev_set_shutdown(grpc_exec_ctx* exec_ctx, gpr_atm* state, - grpc_error* shutdown_err); -void grpc_lfev_set_ready(grpc_exec_ctx* exec_ctx, gpr_atm* state, - const char* variable); - -#ifdef __cplusplus -} -#endif +namespace grpc_core { + +class LockfreeEvent { + public: + LockfreeEvent() = default; + ~LockfreeEvent(); + + LockfreeEvent(const LockfreeEvent&) = delete; + LockfreeEvent& operator=(const LockfreeEvent&) = delete; + + bool IsShutdown() const { + return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0; + } + + void NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure); + bool SetShutdown(grpc_exec_ctx* exec_ctx, grpc_error* error); + void SetReady(grpc_exec_ctx* exec_ctx); + + private: + enum State { kClosureNotReady = 0, kClosureReady = 2, kShutdownBit = 1 }; + + gpr_atm state_ = kClosureNotReady; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */ -- cgit v1.2.3 From 15626bb5274d4f0a65d9328af536b46f3a15e18b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 8 Nov 2017 12:03:22 -0800 Subject: Fix data race --- src/core/lib/iomgr/lockfree_event.cc | 4 ++++ src/core/lib/iomgr/lockfree_event.h | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index 98e19f89df..af1bee4694 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -57,6 +57,10 @@ extern grpc_tracer_flag grpc_polling_trace; namespace grpc_core { +LockfreeEvent::LockfreeEvent() { + gpr_atm_no_barrier_store(&state_, kClosureNotReady); +} + LockfreeEvent::~LockfreeEvent() { gpr_atm curr = gpr_atm_no_barrier_load(&state_); if (curr & kShutdownBit) { diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index 47d0089c01..c667dcd3bc 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -29,7 +29,7 @@ namespace grpc_core { class LockfreeEvent { public: - LockfreeEvent() = default; + LockfreeEvent(); ~LockfreeEvent(); LockfreeEvent(const LockfreeEvent&) = delete; @@ -46,7 +46,7 @@ class LockfreeEvent { private: enum State { kClosureNotReady = 0, kClosureReady = 2, kShutdownBit = 1 }; - gpr_atm state_ = kClosureNotReady; + gpr_atm state_; }; } // namespace grpc_core -- cgit v1.2.3 From 1ef989cd50cdfb172e99c552a67e3ed5f350e5cc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 8 Nov 2017 12:08:33 -0800 Subject: Fixes, commentary --- src/core/lib/iomgr/lockfree_event.cc | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index af1bee4694..40e2ed6219 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -58,16 +58,29 @@ extern grpc_tracer_flag grpc_polling_trace; namespace grpc_core { LockfreeEvent::LockfreeEvent() { + /* Perform an atomic store to start the state machine. + + Note carefully that LockfreeEvent *MAY* be used whilst in a destroyed + state, while a file descriptor is on a freelist. In such a state it may + be SetReady'd, and so we need to perform an atomic operation here to + ensure no races */ gpr_atm_no_barrier_store(&state_, kClosureNotReady); } LockfreeEvent::~LockfreeEvent() { - gpr_atm curr = gpr_atm_no_barrier_load(&state_); - if (curr & kShutdownBit) { - GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit)); - } else { - GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); - } + gpr_atm curr; + do { + curr = gpr_atm_no_barrier_load(&state_); + if (curr & kShutdownBit) { + GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit)); + } else { + GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); + } + /* we CAS in a shutdown, no error value here. If this event is interacted + with post-deletion (see the note in the constructor) we want the bit + pattern to prevent error retention in a deleted object */ + } while (!gpr_atm_no_barrier_cas(&state_, curr, + kShutdownBit /* shutdown, no error */)); } void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) { -- cgit v1.2.3