aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/core/bad_client/BUILD9
-rw-r--r--test/core/bad_client/bad_client.c8
-rw-r--r--test/core/bad_ssl/BUILD9
-rw-r--r--test/core/census/BUILD11
-rw-r--r--test/core/channel/BUILD23
-rw-r--r--test/core/channel/channel_stack_builder_test.c146
-rw-r--r--test/core/channel/channel_stack_test.c5
-rw-r--r--test/core/channel/minimal_stack_is_minimal_test.c14
-rw-r--r--test/core/client_channel/BUILD11
-rw-r--r--test/core/client_channel/resolvers/BUILD11
-rw-r--r--test/core/compression/BUILD11
-rw-r--r--test/core/debug/stats_test.cc123
-rw-r--r--test/core/end2end/BUILD9
-rw-r--r--test/core/end2end/bad_server_response_test.c6
-rw-r--r--test/core/end2end/end2end_nosec_tests.c24
-rw-r--r--test/core/end2end/end2end_tests.c24
-rw-r--r--test/core/end2end/fixtures/h2_load_reporting.c2
-rw-r--r--test/core/end2end/fixtures/proxy.c36
-rw-r--r--test/core/end2end/fuzzers/BUILD11
-rw-r--r--test/core/end2end/fuzzers/hpack.dictionary10
-rwxr-xr-xtest/core/end2end/gen_build_yaml.py4
-rwxr-xr-xtest/core/end2end/generate_tests.bzl3
-rw-r--r--test/core/end2end/tests/cancel_after_accept.c9
-rw-r--r--test/core/end2end/tests/cancel_after_client_done.c6
-rw-r--r--test/core/end2end/tests/cancel_after_round_trip.c20
-rw-r--r--test/core/end2end/tests/cancel_before_invoke.c6
-rw-r--r--test/core/end2end/tests/cancel_in_a_vacuum.c6
-rw-r--r--test/core/end2end/tests/cancel_with_status.c6
-rw-r--r--test/core/end2end/tests/connectivity.c2
-rw-r--r--test/core/end2end/tests/filter_call_init_fails.c1
-rw-r--r--test/core/end2end/tests/filter_causes_close.c9
-rw-r--r--test/core/end2end/tests/filter_latency.c4
-rw-r--r--test/core/end2end/tests/load_reporting_hook.c4
-rw-r--r--test/core/end2end/tests/payload.c2
-rw-r--r--test/core/end2end/tests/resource_quota_server.c34
-rw-r--r--test/core/end2end/tests/shutdown_finishes_tags.c2
-rw-r--r--test/core/end2end/tests/simple_request.c22
-rw-r--r--test/core/end2end/tests/stream_compression_compressed_payload.c652
-rw-r--r--test/core/end2end/tests/stream_compression_payload.c305
-rw-r--r--test/core/end2end/tests/stream_compression_ping_pong_streaming.c291
-rw-r--r--test/core/end2end/tests/streaming_error_response.c25
-rw-r--r--test/core/fling/BUILD11
-rw-r--r--test/core/handshake/BUILD11
-rw-r--r--test/core/http/BUILD11
-rw-r--r--test/core/iomgr/BUILD10
-rw-r--r--test/core/iomgr/endpoint_tests.c8
-rw-r--r--test/core/iomgr/ev_epollsig_linux_test.c6
-rw-r--r--test/core/iomgr/fd_conservation_posix_test.c5
-rw-r--r--test/core/iomgr/fd_posix_test.c6
-rw-r--r--test/core/iomgr/resolve_address_posix_test.c7
-rw-r--r--test/core/iomgr/resolve_address_test.c6
-rw-r--r--test/core/iomgr/tcp_posix_test.c12
-rw-r--r--test/core/json/BUILD11
-rw-r--r--test/core/nanopb/BUILD11
-rw-r--r--test/core/network_benchmarks/BUILD13
-rw-r--r--test/core/security/BUILD9
-rw-r--r--test/core/security/secure_endpoint_test.c62
-rw-r--r--test/core/slice/BUILD11
-rw-r--r--test/core/support/BUILD9
-rw-r--r--test/core/support/string_test.c16
-rw-r--r--test/core/surface/BUILD9
-rw-r--r--test/core/surface/alarm_test.c25
-rw-r--r--test/core/surface/public_headers_must_be_c89.c2
-rw-r--r--test/core/transport/BUILD9
-rw-r--r--test/core/transport/chttp2/BUILD9
-rw-r--r--test/core/tsi/BUILD57
-rw-r--r--test/core/tsi/fake_transport_security_test.c148
-rw-r--r--test/core/tsi/ssl_transport_security_test.c558
-rw-r--r--test/core/tsi/transport_security_test_lib.c550
-rw-r--r--test/core/tsi/transport_security_test_lib.h165
-rw-r--r--test/core/util/BUILD10
-rw-r--r--test/core/util/memory_counters.c8
-rw-r--r--test/core/util/mock_endpoint.c2
-rw-r--r--test/core/util/passthru_endpoint.c2
-rw-r--r--test/core/util/port.c3
-rw-r--r--test/core/util/port_server_client.c10
-rw-r--r--test/core/util/slice_splitter.c9
-rw-r--r--test/core/util/trickle_endpoint.c4
-rw-r--r--test/cpp/codegen/BUILD9
-rw-r--r--test/cpp/common/BUILD9
-rw-r--r--test/cpp/common/alarm_cpp_test.cc60
-rw-r--r--test/cpp/end2end/BUILD12
-rw-r--r--test/cpp/end2end/async_end2end_test.cc138
-rw-r--r--test/cpp/end2end/client_lb_end2end_test.cc166
-rw-r--r--test/cpp/end2end/end2end_test.cc42
-rw-r--r--test/cpp/end2end/grpclb_end2end_test.cc310
-rw-r--r--test/cpp/interop/BUILD9
-rw-r--r--test/cpp/microbenchmarks/BUILD64
-rw-r--r--test/cpp/microbenchmarks/bm_call_create.cc40
-rw-r--r--test/cpp/microbenchmarks/bm_chttp2_transport.cc170
-rw-r--r--test/cpp/microbenchmarks/bm_cq_multiple_threads.cc2
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc367
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc147
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_trickle.cc8
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc87
-rw-r--r--test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h396
-rw-r--r--test/cpp/microbenchmarks/fullstack_streaming_pump.h170
-rw-r--r--test/cpp/microbenchmarks/fullstack_unary_ping_pong.h116
-rw-r--r--test/cpp/microbenchmarks/helpers.cc14
-rw-r--r--test/cpp/microbenchmarks/helpers.h3
-rw-r--r--test/cpp/qps/BUILD10
-rw-r--r--test/cpp/qps/client.h34
-rw-r--r--test/cpp/qps/client_async.cc16
-rw-r--r--test/cpp/qps/interarrival.h12
-rw-r--r--test/cpp/qps/report.cc28
-rw-r--r--test/cpp/qps/report.h3
-rw-r--r--test/cpp/qps/server.h6
-rw-r--r--test/cpp/qps/server_async.cc1
-rw-r--r--test/cpp/server/BUILD4
-rw-r--r--test/cpp/util/BUILD10
110 files changed, 4728 insertions, 1466 deletions
diff --git a/test/core/bad_client/BUILD b/test/core/bad_client/BUILD
index 8cc9dfa77a..99593dc5f3 100644
--- a/test/core/bad_client/BUILD
+++ b/test/core/bad_client/BUILD
@@ -12,14 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/bad_client")
licenses(["notice"]) # Apache v2
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index c3964ca84b..383d1240cb 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -45,18 +45,18 @@ typedef struct {
} thd_args;
static void thd_func(void *arg) {
- thd_args *a = 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 = arg;
+ 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 = ts;
+ 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));
@@ -64,7 +64,7 @@ static void server_setup_transport(void *ts, grpc_transport *transport) {
}
static void read_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
- gpr_event *read_done = arg;
+ gpr_event *read_done = (gpr_event *)arg;
gpr_event_set(read_done, (void *)1);
}
diff --git a/test/core/bad_ssl/BUILD b/test/core/bad_ssl/BUILD
index e13d43258a..0ea1520213 100644
--- a/test/core/bad_ssl/BUILD
+++ b/test/core/bad_ssl/BUILD
@@ -12,14 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/bad_ssl")
licenses(["notice"]) # Apache v2
diff --git a/test/core/census/BUILD b/test/core/census/BUILD
index 988d9a813a..24fd2807d0 100644
--- a/test/core/census/BUILD
+++ b/test/core/census/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/census")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "context_test",
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index 18dd112eb7..5ac77c449b 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/channel")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "channel_args_test",
@@ -46,3 +41,15 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
+
+grpc_cc_test(
+ name = "channel_stack_builder_test",
+ srcs = ["channel_stack_builder_test.c"],
+ language = "C",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
diff --git a/test/core/channel/channel_stack_builder_test.c b/test/core/channel/channel_stack_builder_test.c
new file mode 100644
index 0000000000..682efd1438
--- /dev/null
+++ b/test/core/channel/channel_stack_builder_test.c
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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 <limits.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#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_test.c b/test/core/channel/channel_stack_test.c
index 0c4bae6ded..7c3614b4a2 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -67,10 +67,6 @@ static void channel_func(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
++*(int *)(elem->channel_data);
}
-static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
- return gpr_strdup("peer");
-}
-
static void free_channel(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_channel_stack_destroy(exec_ctx, arg);
@@ -93,7 +89,6 @@ static void test_create_channel_stack(void) {
sizeof(int),
channel_init_func,
channel_destroy_func,
- get_peer,
grpc_channel_next_get_info,
"some_test_filter"};
const grpc_channel_filter *filters = &filter;
diff --git a/test/core/channel/minimal_stack_is_minimal_test.c b/test/core/channel/minimal_stack_is_minimal_test.c
index c99b54c6ac..b4528346f7 100644
--- a/test/core/channel/minimal_stack_is_minimal_test.c
+++ b/test/core/channel/minimal_stack_is_minimal_test.c
@@ -89,14 +89,14 @@ int main(int argc, char **argv) {
"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", "compress", "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", "compress", "connected", NULL);
- errors +=
- CHECK_STACK("chttp2", NULL, GRPC_SERVER_CHANNEL, "server", "message_size",
- "deadline", "http-server", "compress", "connected", NULL);
+ "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);
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index 7fc5b977a9..c4a93238f2 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/client_channel")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/client_channel/resolvers/BUILD b/test/core/client_channel/resolvers/BUILD
index 8af4a2d5f0..0907e06623 100644
--- a/test/core/client_channel/resolvers/BUILD
+++ b/test/core/client_channel/resolvers/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/client_channel_resolvers")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "dns_resolver_connectivity_test",
diff --git a/test/core/compression/BUILD b/test/core/compression/BUILD
index e4432b3b9d..1ab6e35f0d 100644
--- a/test/core/compression/BUILD
+++ b/test/core/compression/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/compression")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "algorithm_test",
diff --git a/test/core/debug/stats_test.cc b/test/core/debug/stats_test.cc
new file mode 100644
index 0000000000..c85ab3598a
--- /dev/null
+++ b/test/core/debug/stats_test.cc
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+extern "C" {
+#include "src/core/lib/debug/stats.h"
+}
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace testing {
+
+class Snapshot {
+ public:
+ Snapshot() { grpc_stats_collect(&begin_); }
+
+ grpc_stats_data delta() {
+ grpc_stats_data now;
+ grpc_stats_collect(&now);
+ grpc_stats_data delta;
+ grpc_stats_diff(&now, &begin_, &delta);
+ return delta;
+ }
+
+ private:
+ grpc_stats_data begin_;
+};
+
+TEST(StatsTest, IncCounters) {
+ for (int i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+ Snapshot snapshot;
+
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ GRPC_STATS_INC_COUNTER(&exec_ctx, (grpc_stats_counters)i);
+ grpc_exec_ctx_finish(&exec_ctx);
+
+ EXPECT_EQ(snapshot.delta().counters[i], 1);
+ }
+}
+
+TEST(StatsTest, IncSpecificCounter) {
+ Snapshot snapshot;
+
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ GRPC_STATS_INC_SYSCALL_POLL(&exec_ctx);
+ grpc_exec_ctx_finish(&exec_ctx);
+
+ EXPECT_EQ(snapshot.delta().counters[GRPC_STATS_COUNTER_SYSCALL_POLL], 1);
+}
+
+static int FindExpectedBucket(int i, int j) {
+ if (j < 0) {
+ return 0;
+ }
+ if (j >= grpc_stats_histo_bucket_boundaries[i][grpc_stats_histo_buckets[i]]) {
+ return grpc_stats_histo_buckets[i] - 1;
+ }
+ return std::upper_bound(grpc_stats_histo_bucket_boundaries[i],
+ grpc_stats_histo_bucket_boundaries[i] +
+ grpc_stats_histo_buckets[i],
+ j) -
+ grpc_stats_histo_bucket_boundaries[i] - 1;
+}
+
+TEST(StatsTest, IncHistogram) {
+ for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
+ std::vector<int> test_values;
+ for (int j = -1000;
+ j <
+ grpc_stats_histo_bucket_boundaries[i]
+ [grpc_stats_histo_buckets[i] - 1] +
+ 1000;
+ j++) {
+ test_values.push_back(j);
+ }
+ std::random_shuffle(test_values.begin(), test_values.end());
+ if (test_values.size() > 10000) {
+ test_values.resize(10000);
+ }
+ for (auto j : test_values) {
+ Snapshot snapshot;
+
+ int expected_bucket = FindExpectedBucket(i, j);
+
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_stats_inc_histogram[i](&exec_ctx, j);
+ grpc_exec_ctx_finish(&exec_ctx);
+
+ auto delta = snapshot.delta();
+
+ EXPECT_EQ(delta.histograms[grpc_stats_histo_start[i] + expected_bucket],
+ 1);
+ }
+ }
+}
+
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ grpc_init();
+ int ret = RUN_ALL_TESTS();
+ grpc_shutdown();
+ return ret;
+}
diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD
index 9e788bf7e5..49bfc43646 100644
--- a/test/core/end2end/BUILD
+++ b/test/core/end2end/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/end2end")
load(":generate_tests.bzl", "grpc_end2end_tests")
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index 5f89058c45..eeabc769d3 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -136,7 +136,7 @@ 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 = arg;
+ 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);
@@ -237,7 +237,7 @@ typedef struct {
} poll_args;
static void actually_poll_server(void *arg) {
- poll_args *pa = 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;
@@ -259,7 +259,7 @@ static void poll_server_until_read_done(test_tcp_server *server,
gpr_atm_rel_store(&state.done_atm, 0);
state.write_done = 0;
gpr_thd_id id;
- poll_args *pa = gpr_malloc(sizeof(*pa));
+ 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);
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index 6a061a4e2d..3236feea56 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -130,6 +130,12 @@ 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);
@@ -195,6 +201,9 @@ void grpc_end2end_tests_pre_init(void) {
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();
@@ -259,6 +268,9 @@ void grpc_end2end_tests(int argc, char **argv,
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);
@@ -468,6 +480,18 @@ void grpc_end2end_tests(int argc, char **argv,
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;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index 3fc7c3fb6c..ca9443b642 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -132,6 +132,12 @@ 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);
@@ -198,6 +204,9 @@ void grpc_end2end_tests_pre_init(void) {
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();
@@ -263,6 +272,9 @@ void grpc_end2end_tests(int argc, char **argv,
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);
@@ -476,6 +488,18 @@ void grpc_end2end_tests(int argc, char **argv,
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;
diff --git a/test/core/end2end/fixtures/h2_load_reporting.c b/test/core/end2end/fixtures/h2_load_reporting.c
index 385e2cbf70..8a05bb722a 100644
--- a/test/core/end2end/fixtures/h2_load_reporting.c
+++ b/test/core/end2end/fixtures/h2_load_reporting.c
@@ -28,7 +28,7 @@
#include <grpc/support/useful.h>
#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/load_reporting.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"
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index d457aeefe8..9ad862728f 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -80,7 +80,7 @@ grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def,
int proxy_port = grpc_pick_unused_port_or_die();
int server_port = grpc_pick_unused_port_or_die();
- grpc_end2end_proxy *proxy = gpr_malloc(sizeof(*proxy));
+ 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);
@@ -106,14 +106,14 @@ grpc_end2end_proxy *grpc_end2end_proxy_create(const grpc_end2end_proxy_def *def,
}
static closure *new_closure(void (*func)(void *arg, int success), void *arg) {
- closure *cl = gpr_malloc(sizeof(*cl));
+ 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 = arg;
+ grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg;
proxy->shutdown = 1;
grpc_completion_queue_shutdown(proxy->cq);
}
@@ -146,12 +146,12 @@ static void unrefpc(proxy_call *pc, const char *reason) {
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 = arg;
+ 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 = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -172,14 +172,14 @@ static void on_p2s_recv_initial_metadata(void *arg, int success) {
}
static void on_p2s_sent_initial_metadata(void *arg, int success) {
- proxy_call *pc = arg;
+ 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 = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -199,12 +199,12 @@ static void on_p2s_sent_message(void *arg, int success) {
}
static void on_p2s_sent_close(void *arg, int success) {
- proxy_call *pc = arg;
+ 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 = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -235,7 +235,7 @@ static void on_c2p_recv_msg(void *arg, int success) {
static void on_p2s_recv_msg(void *arg, int success);
static void on_c2p_sent_message(void *arg, int success) {
- proxy_call *pc = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -255,7 +255,7 @@ static void on_c2p_sent_message(void *arg, int success) {
}
static void on_p2s_recv_msg(void *arg, int success) {
- proxy_call *pc = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -275,12 +275,12 @@ static void on_p2s_recv_msg(void *arg, int success) {
}
static void on_c2p_sent_status(void *arg, int success) {
- proxy_call *pc = arg;
+ proxy_call *pc = (proxy_call *)arg;
unrefpc(pc, "on_c2p_sent_status");
}
static void on_p2s_status(void *arg, int success) {
- proxy_call *pc = arg;
+ proxy_call *pc = (proxy_call *)arg;
grpc_op op;
grpc_call_error err;
@@ -305,18 +305,18 @@ static void on_p2s_status(void *arg, int success) {
}
static void on_c2p_closed(void *arg, int success) {
- proxy_call *pc = arg;
+ proxy_call *pc = (proxy_call *)arg;
unrefpc(pc, "on_c2p_closed");
}
static void on_new_call(void *arg, int success) {
- grpc_end2end_proxy *proxy = arg;
+ 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 = gpr_malloc(sizeof(*pc));
+ 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,
@@ -404,7 +404,7 @@ static void request_call(grpc_end2end_proxy *proxy) {
}
static void thread_main(void *arg) {
- grpc_end2end_proxy *proxy = arg;
+ grpc_end2end_proxy *proxy = (grpc_end2end_proxy *)arg;
closure *cl;
for (;;) {
grpc_event ev = grpc_completion_queue_next(
@@ -416,7 +416,7 @@ static void thread_main(void *arg) {
case GRPC_QUEUE_SHUTDOWN:
return;
case GRPC_OP_COMPLETE:
- cl = ev.tag;
+ cl = (closure *)ev.tag;
cl->func(cl->arg, ev.success);
gpr_free(cl);
break;
diff --git a/test/core/end2end/fuzzers/BUILD b/test/core/end2end/fuzzers/BUILD
index bf3a62ad37..4ed9a70578 100644
--- a/test/core/end2end/fuzzers/BUILD
+++ b/test/core/end2end/fuzzers/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/end2end/fuzzers")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
index 2bb9de34c5..7c77512aa9 100644
--- a/test/core/end2end/fuzzers/hpack.dictionary
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -14,7 +14,10 @@
"\x0Dgrpc-tags-bin"
"\x0Egrpc-trace-bin"
"\x0Ccontent-type"
+"\x10content-encoding"
+"\x0Faccept-encoding"
"\x1Egrpc-internal-encoding-request"
+"%grpc-internal-stream-encoding-request"
"\x0Auser-agent"
"\x04host"
"\x08lb-token"
@@ -49,7 +52,6 @@
"\x03400"
"\x03500"
"\x0Eaccept-charset"
-"\x0Faccept-encoding"
"\x0Dgzip, deflate"
"\x0Faccept-language"
"\x0Daccept-ranges"
@@ -60,7 +62,6 @@
"\x0Dauthorization"
"\x0Dcache-control"
"\x13content-disposition"
-"\x10content-encoding"
"\x10content-language"
"\x0Econtent-length"
"\x10content-location"
@@ -134,6 +135,8 @@
"\x00\x0Dauthorization\x00"
"\x00\x0Dcache-control\x00"
"\x00\x13content-disposition\x00"
+"\x00\x10content-encoding\x08identity"
+"\x00\x10content-encoding\x04gzip"
"\x00\x10content-encoding\x00"
"\x00\x10content-language\x00"
"\x00\x0Econtent-length\x00"
@@ -179,3 +182,6 @@
"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
+"\x00\x0Faccept-encoding\x08identity"
+"\x00\x0Faccept-encoding\x04gzip"
+"\x00\x0Faccept-encoding\x0Didentity,gzip"
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 18bae63a8a..33fd97f3bd 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -137,6 +137,10 @@ END2END_TESTS = {
'shutdown_finishes_calls': default_test_options._replace(cpu_cost=LOWCPU),
'shutdown_finishes_tags': default_test_options._replace(cpu_cost=LOWCPU),
'simple_cacheable_request': default_test_options._replace(cpu_cost=LOWCPU),
+ 'stream_compression_compressed_payload': default_test_options._replace(proxyable=False,
+ exclude_inproc=True),
+ 'stream_compression_payload': default_test_options._replace(exclude_inproc=True),
+ 'stream_compression_ping_pong_streaming': default_test_options._replace(exclude_inproc=True),
'simple_delayed_request': connectivity_test_options,
'simple_metadata': default_test_options,
'simple_request': default_test_options,
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 6d1917c0ff..9bbba26108 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -138,6 +138,9 @@ END2END_TESTS = {
'simple_metadata': test_options(),
'simple_request': test_options(),
'streaming_error_response': test_options(),
+ 'stream_compression_compressed_payload': test_options(proxyable=False, exclude_inproc=True),
+ 'stream_compression_payload': test_options(exclude_inproc=True),
+ 'stream_compression_ping_pong_streaming': test_options(exclude_inproc=True),
'trailing_metadata': test_options(),
'authority_not_supported': test_options(),
'filter_latency': test_options(),
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index a360c6f0d2..c3ac0c3201 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -39,10 +39,13 @@ 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", test_name, config.name);
+ 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);
@@ -135,8 +138,8 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
args = grpc_channel_args_copy_and_add(args, &arg, 1);
}
- grpc_end2end_test_fixture f =
- begin_test(config, "cancel_after_accept", args, NULL);
+ 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
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index 502005b6af..0e2a751d83 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -33,10 +33,12 @@ 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", test_name, config.name);
+ 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);
@@ -93,7 +95,7 @@ static void test_cancel_after_accept_and_writes_closed(
grpc_call *c;
grpc_call *s;
grpc_end2end_test_fixture f = begin_test(
- config, "test_cancel_after_accept_and_writes_closed", NULL, NULL);
+ 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;
diff --git a/test/core/end2end/tests/cancel_after_round_trip.c b/test/core/end2end/tests/cancel_after_round_trip.c
index 0fc8b95ef7..bc41bd3a6d 100644
--- a/test/core/end2end/tests/cancel_after_round_trip.c
+++ b/test/core/end2end/tests/cancel_after_round_trip.c
@@ -39,10 +39,13 @@ 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", test_name, config.name);
+ 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);
@@ -114,7 +117,9 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
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_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;
@@ -135,8 +140,8 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
args = grpc_channel_args_copy_and_add(args, &arg, 1);
}
- grpc_end2end_test_fixture f =
- begin_test(config, "cancel_after_round_trip", args, NULL);
+ 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
@@ -199,7 +204,7 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
- op->data.send_message.send_message = response_payload;
+ op->data.send_message.send_message = response_payload1;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -242,7 +247,7 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
- op->data.send_message.send_message = response_payload;
+ op->data.send_message.send_message = response_payload2;
op->flags = 0;
op->reserved = NULL;
op++;
@@ -262,7 +267,8 @@ static void test_cancel_after_round_trip(grpc_end2end_test_config config,
grpc_call_details_destroy(&call_details);
grpc_byte_buffer_destroy(request_payload);
- grpc_byte_buffer_destroy(response_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);
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index 423194b63e..397e8b8ba6 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -32,10 +32,12 @@ 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", test_name, config.name);
+ 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);
@@ -91,7 +93,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
grpc_op *op;
grpc_call *c;
grpc_end2end_test_fixture f =
- begin_test(config, "cancel_before_invoke", NULL, NULL);
+ 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;
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index f64cbdf929..cd9551bef9 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -33,10 +33,12 @@ 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", test_name, config.name);
+ 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);
@@ -90,7 +92,7 @@ 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", NULL, NULL);
+ 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();
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index fd26fd122e..ab8c4f4187 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -35,10 +35,12 @@ 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", test_name, config.name);
+ 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);
@@ -165,7 +167,7 @@ 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);
+ 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);
diff --git a/test/core/end2end/tests/connectivity.c b/test/core/end2end/tests/connectivity.c
index a5af46e09e..610243ee3a 100644
--- a/test/core/end2end/tests/connectivity.c
+++ b/test/core/end2end/tests/connectivity.c
@@ -34,7 +34,7 @@ typedef struct {
} child_events;
static void child_thread(void *arg) {
- child_events *ce = arg;
+ child_events *ce = (child_events *)arg;
grpc_event ev;
gpr_event_set(&ce->started, (void *)1);
gpr_log(GPR_DEBUG, "verifying");
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index b6be375a51..09e9dbcd7b 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -430,7 +430,6 @@ static const grpc_channel_filter test_filter = {
0,
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"filter_call_init_fails"};
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index aff39dd89d..ee7aeb3f33 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -195,9 +195,9 @@ 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 = arg;
- call_data *calld = elem->call_data;
- GRPC_CLOSURE_SCHED(
+ 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),
@@ -208,7 +208,7 @@ static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg,
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 = elem->call_data;
+ 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;
@@ -247,7 +247,6 @@ static const grpc_channel_filter test_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"filter_causes_close"};
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index 5dbbc4d18d..c24934f05d 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -290,7 +290,6 @@ static const grpc_channel_filter test_client_filter = {
0,
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"client_filter_latency"};
@@ -304,7 +303,6 @@ static const grpc_channel_filter test_server_filter = {
0,
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"server_filter_latency"};
@@ -314,7 +312,7 @@ static const grpc_channel_filter test_server_filter = {
static bool maybe_add_filter(grpc_exec_ctx *exec_ctx,
grpc_channel_stack_builder *builder, void *arg) {
- grpc_channel_filter *filter = 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
diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c
index 3584d47887..7b503790db 100644
--- a/test/core/end2end/tests/load_reporting_hook.c
+++ b/test/core/end2end/tests/load_reporting_hook.c
@@ -26,8 +26,8 @@
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
-#include "src/core/ext/filters/load_reporting/load_reporting.h"
-#include "src/core/ext/filters/load_reporting/load_reporting_filter.h"
+#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"
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index 19fb4d9769..d98eed68e0 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -91,7 +91,7 @@ static grpc_slice generate_random_slice() {
static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
char *output;
const size_t output_size = 1024 * 1024;
- output = gpr_malloc(output_size);
+ output = (char *)gpr_malloc(output_size);
for (i = 0; i < output_size - 1; ++i) {
output[i] = chars[rand() % (int)(sizeof(chars) - 1)];
}
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index 010e20c4c2..0316920762 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -91,7 +91,7 @@ static grpc_slice generate_random_slice() {
static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
char *output;
const size_t output_size = 1024 * 1024;
- output = gpr_malloc(output_size);
+ output = (char *)gpr_malloc(output_size);
for (i = 0; i < output_size - 1; ++i) {
output[i] = chars[rand() % (int)(sizeof(chars) - 1)];
}
@@ -111,10 +111,10 @@ void resource_quota_server(grpc_end2end_test_config config) {
grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024);
#define NUM_CALLS 100
-#define CLIENT_BASE_TAG 1000
-#define SERVER_START_BASE_TAG 2000
-#define SERVER_RECV_BASE_TAG 3000
-#define SERVER_END_BASE_TAG 4000
+#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;
@@ -131,8 +131,10 @@ void resource_quota_server(grpc_end2end_test_config config) {
* will be verified on completion. */
grpc_slice request_payload_slice = generate_random_slice();
- grpc_call **client_calls = malloc(sizeof(grpc_call *) * NUM_CALLS);
- grpc_call **server_calls = malloc(sizeof(grpc_call *) * NUM_CALLS);
+ 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 =
malloc(sizeof(grpc_metadata_array) * NUM_CALLS);
grpc_metadata_array *trailing_metadata_recv =
@@ -141,11 +143,14 @@ void resource_quota_server(grpc_end2end_test_config config) {
malloc(sizeof(grpc_metadata_array) * NUM_CALLS);
grpc_call_details *call_details =
malloc(sizeof(grpc_call_details) * NUM_CALLS);
- grpc_status_code *status = malloc(sizeof(grpc_status_code) * NUM_CALLS);
- grpc_slice *details = malloc(sizeof(grpc_slice) * 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 =
+ malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
grpc_byte_buffer **request_payload_recv =
malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
- int *was_cancelled = malloc(sizeof(int) * 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;
@@ -156,9 +161,6 @@ void resource_quota_server(grpc_end2end_test_config config) {
int deadline_exceeded = 0;
int unavailable = 0;
- grpc_byte_buffer *request_payload =
- grpc_raw_byte_buffer_create(&request_payload_slice, 1);
-
grpc_op ops[6];
grpc_op *op;
@@ -167,6 +169,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
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;
}
@@ -195,7 +198,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
- op->data.send_message.send_message = request_payload;
+ op->data.send_message.send_message = request_payload[i];
op->flags = 0;
op->reserved = NULL;
op++;
@@ -261,6 +264,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
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) {
@@ -351,7 +355,6 @@ void resource_quota_server(grpc_end2end_test_config config) {
NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client,
deadline_exceeded, unavailable);
- grpc_byte_buffer_destroy(request_payload);
grpc_slice_unref(request_payload_slice);
grpc_resource_quota_unref(resource_quota);
@@ -366,6 +369,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
free(call_details);
free(status);
free(details);
+ free(request_payload);
free(request_payload_recv);
free(was_cancelled);
}
diff --git a/test/core/end2end/tests/shutdown_finishes_tags.c b/test/core/end2end/tests/shutdown_finishes_tags.c
index f9b8e4c955..7914cc95ba 100644
--- a/test/core/end2end/tests/shutdown_finishes_tags.c
+++ b/test/core/end2end/tests/shutdown_finishes_tags.c
@@ -78,7 +78,7 @@ static void test_early_server_shutdown_finishes_tags(
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 = (void *)1;
+ grpc_call *s = (grpc_call *)(uintptr_t)1;
grpc_call_details call_details;
grpc_metadata_array request_metadata_recv;
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 7a81133dfa..82ab0a1cfe 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -27,6 +27,7 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/debug/stats.h"
#include "src/core/lib/support/string.h"
#include "test/core/end2end/cq_verifier.h"
@@ -102,6 +103,10 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_slice details;
int was_cancelled = 2;
char *peer;
+ grpc_stats_data before;
+ grpc_stats_data after;
+
+ grpc_stats_collect(&before);
gpr_timespec deadline = five_seconds_from_now();
c = grpc_channel_create_call(
@@ -208,6 +213,23 @@ static void simple_request_body(grpc_end2end_test_config config,
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);
}
static void test_invoke_simple_request(grpc_end2end_test_config config) {
diff --git a/test/core/end2end/tests/stream_compression_compressed_payload.c b/test/core/end2end/tests/stream_compression_compressed_payload.c
new file mode 100644
index 0000000000..11e7999a1c
--- /dev/null
+++ b/test/core/end2end/tests/stream_compression_compressed_payload.c
@@ -0,0 +1,652 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/byte_buffer_reader.h>
+#include <grpc/compression.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/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);
+
+ 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);
+
+ 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);
+
+ 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_EXPECT_COMPLETION(cqv, tag(1), true);
+ cq_verify(cqv);
+
+ /* call was cancelled (closed) ... */
+ GPR_ASSERT(was_cancelled != 0);
+ /* with a certain error */
+ GPR_ASSERT(status == expected_error);
+
+ 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
new file mode 100644
index 0000000000..e47d2aa93c
--- /dev/null
+++ b/test/core/end2end/tests/stream_compression_payload.c
@@ -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 <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/compression.h>
+#include <grpc/compression.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#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
new file mode 100644
index 0000000000..4c1a34cc64
--- /dev/null
+++ b/test/core/end2end/tests/stream_compression_ping_pong_streaming.c
@@ -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 <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/compression.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#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
index fd8fa7ff6c..9d562b9090 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -185,6 +185,19 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
cq_verify(cqv);
+ 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;
@@ -199,21 +212,9 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
- 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(104), 1);
if (request_status_early) {
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
- } else {
- CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
}
cq_verify(cqv);
diff --git a/test/core/fling/BUILD b/test/core/fling/BUILD
index b0d34e9eb0..27b2b5bec6 100644
--- a/test/core/fling/BUILD
+++ b/test/core/fling/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/fling")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index c93ddc8c21..8e462cfc5b 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/handshake")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "client_ssl",
diff --git a/test/core/http/BUILD b/test/core/http/BUILD
index 28313082c6..fffdac5e08 100644
--- a/test/core/http/BUILD
+++ b/test/core/http/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/http")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index 3e6fd37ec6..7620d1de21 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -12,19 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
-package(
- default_visibility = ["//visibility:public"], # Useful for third party devs to test their io manager implementation.
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/iomgr", visibility = "public") # Useful for third party devs to test their io manager implementation.
grpc_cc_library(
name = "endpoint_tests",
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index 11b45e8e08..895cc0e158 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -77,7 +77,7 @@ 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 = gpr_malloc(sizeof(grpc_slice) * nslices);
+ grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices);
size_t num_bytes_left = num_bytes;
size_t i;
size_t j;
@@ -117,7 +117,8 @@ struct read_and_write_test_state {
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 = data;
+ 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);
@@ -135,7 +136,8 @@ static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx,
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 = data;
+ struct read_and_write_test_state *state =
+ (struct read_and_write_test_state *)data;
grpc_slice *slices = NULL;
size_t nslices;
diff --git a/test/core/iomgr/ev_epollsig_linux_test.c b/test/core/iomgr/ev_epollsig_linux_test.c
index c702065d4d..cca07bf002 100644
--- a/test/core/iomgr/ev_epollsig_linux_test.c
+++ b/test/core/iomgr/ev_epollsig_linux_test.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <unistd.h>
+#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/thd.h>
@@ -308,9 +309,8 @@ static void test_threading(void) {
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;
- grpc_iomgr_init(&exec_ctx);
- grpc_iomgr_start(&exec_ctx);
poll_strategy = grpc_get_poll_strategy_name();
if (poll_strategy != NULL && strcmp(poll_strategy, "epollsig") == 0) {
@@ -323,8 +323,8 @@ int main(int argc, char **argv) {
poll_strategy);
}
- grpc_iomgr_shutdown(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
+ grpc_shutdown();
return 0;
}
#else /* defined(GRPC_LINUX_EPOLL) */
diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c
index 3c61173ecd..d29b1e8e41 100644
--- a/test/core/iomgr/fd_conservation_posix_test.c
+++ b/test/core/iomgr/fd_conservation_posix_test.c
@@ -30,9 +30,8 @@ int main(int argc, char **argv) {
grpc_endpoint_pair p;
grpc_test_init(argc, argv);
+ grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_iomgr_init(&exec_ctx);
- grpc_iomgr_start(&exec_ctx);
/* set max # of file descriptors to a low value, and
verify we can create and destroy many more than this number
@@ -51,7 +50,7 @@ int main(int argc, char **argv) {
grpc_resource_quota_unref(resource_quota);
- grpc_iomgr_shutdown(&exec_ctx);
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
index 85d5d9c07f..5791d17af6 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -35,6 +35,7 @@
#include <sys/time.h>
#include <unistd.h>
+#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
@@ -530,8 +531,7 @@ int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_test_init(argc, argv);
- grpc_iomgr_init(&exec_ctx);
- grpc_iomgr_start(&exec_ctx);
+ grpc_init();
g_pollset = gpr_zalloc(grpc_pollset_size());
grpc_pollset_init(g_pollset, &g_mu);
test_grpc_fd();
@@ -541,8 +541,8 @@ int main(int argc, char **argv) {
grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
grpc_exec_ctx_flush(&exec_ctx);
gpr_free(g_pollset);
- grpc_iomgr_shutdown(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
+ grpc_shutdown();
return 0;
}
diff --git a/test/core/iomgr/resolve_address_posix_test.c b/test/core/iomgr/resolve_address_posix_test.c
index 9cc09ed5d3..e4be99f03c 100644
--- a/test/core/iomgr/resolve_address_posix_test.c
+++ b/test/core/iomgr/resolve_address_posix_test.c
@@ -21,12 +21,14 @@
#include <string.h>
#include <sys/un.h>
+#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
+
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "test/core/util/test_config.h"
@@ -159,13 +161,12 @@ static void test_unix_socket_path_name_too_long(void) {
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
+ grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_iomgr_init(&exec_ctx);
- grpc_iomgr_start(&exec_ctx);
test_unix_socket();
test_unix_socket_path_name_too_long();
grpc_executor_shutdown(&exec_ctx);
- grpc_iomgr_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
index cb156ee61e..7f5c4073d8 100644
--- a/test/core/iomgr/resolve_address_test.c
+++ b/test/core/iomgr/resolve_address_test.c
@@ -17,6 +17,7 @@
*/
#include "src/core/lib/iomgr/resolve_address.h"
+#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
@@ -250,9 +251,8 @@ static void test_unparseable_hostports(void) {
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
+ grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_iomgr_init(&exec_ctx);
- grpc_iomgr_start(&exec_ctx);
test_localhost();
test_default_port();
test_non_numeric_default_port();
@@ -262,7 +262,7 @@ int main(int argc, char **argv) {
test_invalid_ip_addresses();
test_unparseable_hostports();
grpc_executor_shutdown(&exec_ctx);
- grpc_iomgr_shutdown(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
+ grpc_shutdown();
return 0;
}
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index c45068e7ec..cdaa2ce2af 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -89,7 +89,7 @@ static ssize_t fill_socket(int fd) {
static size_t fill_socket_partial(int fd, size_t bytes) {
ssize_t write_bytes;
size_t total_bytes = 0;
- unsigned char *buf = gpr_malloc(bytes);
+ unsigned char *buf = (unsigned char *)gpr_malloc(bytes);
unsigned i;
for (i = 0; i < bytes; ++i) {
buf[i] = (uint8_t)(i % 256);
@@ -267,7 +267,7 @@ struct write_socket_state {
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 = gpr_malloc(sizeof(grpc_slice) * nslices);
+ grpc_slice *slices = (grpc_slice *)gpr_malloc(sizeof(grpc_slice) * nslices);
size_t num_bytes_left = num_bytes;
unsigned i, j;
unsigned char *buf;
@@ -301,7 +301,7 @@ static void write_done(grpc_exec_ctx *exec_ctx,
}
void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) {
- unsigned char *buf = gpr_malloc(read_size);
+ unsigned char *buf = (unsigned char *)gpr_malloc(read_size);
ssize_t bytes_read;
size_t bytes_left = num_bytes;
int flags;
@@ -404,7 +404,7 @@ static void write_test(size_t num_bytes, size_t slice_size) {
}
void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *errors) {
- int *done = arg;
+ int *done = (int *)arg;
*done = 1;
GPR_ASSERT(
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
@@ -548,7 +548,7 @@ static grpc_endpoint_test_config configs[] = {
static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
grpc_error *error) {
- grpc_pollset_destroy(exec_ctx, p);
+ grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p);
}
int main(int argc, char **argv) {
@@ -556,7 +556,7 @@ int main(int argc, char **argv) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_test_init(argc, argv);
grpc_init();
- g_pollset = gpr_zalloc(grpc_pollset_size());
+ 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();
diff --git a/test/core/json/BUILD b/test/core/json/BUILD
index 36b0897d80..3ff7918677 100644
--- a/test/core/json/BUILD
+++ b/test/core/json/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/json")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/nanopb/BUILD b/test/core/nanopb/BUILD
index bdb468867d..f332207e2d 100644
--- a/test/core/nanopb/BUILD
+++ b/test/core/nanopb/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/nanopb")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD
index cee23ecd51..0e15393030 100644
--- a/test/core/network_benchmarks/BUILD
+++ b/test/core/network_benchmarks/BUILD
@@ -12,17 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
-
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
+grpc_package(name = "test/core/network_benchmarks",
+ features = ["-layering_check", "-parse_headers" ]
)
+licenses(["notice"]) # Apache v2
+
grpc_cc_binary(
name = "low_level_ping_pong",
srcs = ["low_level_ping_pong.c"],
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index 241ffc0591..dc41759922 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/security")
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index 7ecd947e1f..839a05fa9b 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -36,12 +36,19 @@ 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) {
+ 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;
@@ -54,15 +61,16 @@ static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
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, tcp.client, NULL, 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 = gpr_malloc(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++) {
@@ -96,31 +104,47 @@ static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
} 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, tcp.client,
- &encrypted_leftover, 1);
+ 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, tcp.server, NULL, 0);
+ 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);
+ 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");
- grpc_endpoint_test_fixture f;
+ return secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1,
+ false);
+}
- f = secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1);
- return f;
+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) {}
@@ -128,8 +152,14 @@ 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,
@@ -172,7 +202,7 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) {
static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
grpc_error *error) {
- grpc_pollset_destroy(exec_ctx, p);
+ grpc_pollset_destroy(exec_ctx, (grpc_pollset *)p);
}
int main(int argc, char **argv) {
@@ -181,10 +211,12 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
- g_pollset = gpr_zalloc(grpc_pollset_size());
+ 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);
- test_leftover(configs[1], 1);
+ 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);
diff --git a/test/core/slice/BUILD b/test/core/slice/BUILD
index 9f2225adfb..f86a3a6082 100644
--- a/test/core/slice/BUILD
+++ b/test/core/slice/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-licenses(["notice"]) # Apache v2
+grpc_package(name = "test/core/slice")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+licenses(["notice"]) # Apache v2
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 7e142c1e3f..096576e13c 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/support")
grpc_cc_test(
name = "alloc_test",
diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c
index a3c33c3fa4..bee2139477 100644
--- a/test/core/support/string_test.c
+++ b/test/core/support/string_test.c
@@ -279,6 +279,21 @@ static void test_memrchr(void) {
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();
@@ -292,5 +307,6 @@ int main(int argc, char **argv) {
test_leftpad();
test_stricmp();
test_memrchr();
+ test_is_true();
return 0;
}
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index 2923927412..17db7737f7 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/surface")
grpc_cc_test(
name = "alarm_test",
diff --git a/test/core/surface/alarm_test.c b/test/core/surface/alarm_test.c
index 6971d92074..4fd7cb93c6 100644
--- a/test/core/surface/alarm_test.c
+++ b/test/core/surface/alarm_test.c
@@ -48,45 +48,50 @@ static void test_alarm(void) {
/* regular expiry */
grpc_event ev;
void *tag = create_test_tag();
- grpc_alarm *alarm =
- grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(1), 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);
+ grpc_alarm_destroy(alarm, NULL);
}
{
/* cancellation */
grpc_event ev;
void *tag = create_test_tag();
- grpc_alarm *alarm =
- grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(2), 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);
+ 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);
+ grpc_alarm_destroy(alarm, NULL);
}
{
/* alarm_destroy before cq_next */
grpc_event ev;
void *tag = create_test_tag();
- grpc_alarm *alarm =
- grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(2), 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);
+ 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);
}
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 3b1c53390b..0d7f68c0ad 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -36,6 +36,7 @@
#include <grpc/impl/codegen/slice.h>
#include <grpc/impl/codegen/status.h>
#include <grpc/impl/codegen/sync.h>
+#include <grpc/impl/codegen/sync_custom.h>
#include <grpc/impl/codegen/sync_generic.h>
#include <grpc/load_reporting.h>
#include <grpc/slice.h>
@@ -53,6 +54,7 @@
#include <grpc/support/string_util.h>
#include <grpc/support/subprocess.h>
#include <grpc/support/sync.h>
+#include <grpc/support/sync_custom.h>
#include <grpc/support/sync_generic.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index 040c0c35c2..12e36132c8 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/transport")
grpc_cc_test(
name = "bdp_estimator_test",
diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD
index e3989f7059..6081940243 100644
--- a/test/core/transport/chttp2/BUILD
+++ b/test/core/transport/chttp2/BUILD
@@ -12,16 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/transport/chttp2")
load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
diff --git a/test/core/tsi/BUILD b/test/core/tsi/BUILD
index 3bbc50b27e..0c5509dda6 100644
--- a/test/core/tsi/BUILD
+++ b/test/core/tsi/BUILD
@@ -12,14 +12,59 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- features = [
- "-layering_check",
- "-parse_headers",
+grpc_package(name = "test/core/tsi")
+
+grpc_cc_library(
+ name = "transport_security_test_lib",
+ srcs = ["transport_security_test_lib.c"],
+ hdrs = ["transport_security_test_lib.h"],
+ deps = [
+ "//:grpc",
+ "//:tsi",
+ ],
+)
+
+grpc_cc_test(
+ name = "fake_transport_security_test",
+ srcs = ["fake_transport_security_test.c"],
+ language = "C",
+ deps = [
+ ":transport_security_test_lib",
+ "//:grpc",
+ "//:gpr",
+ "//:tsi",
+ "//test/core/util:gpr_test_util",
+ ],
+)
+
+
+grpc_cc_test(
+ name = "ssl_transport_security_test",
+ srcs = ["ssl_transport_security_test.c"],
+ data = [
+ "//src/core/tsi/test_creds:badclient.key",
+ "//src/core/tsi/test_creds:badclient.pem",
+ "//src/core/tsi/test_creds:badserver.key",
+ "//src/core/tsi/test_creds:badserver.pem",
+ "//src/core/tsi/test_creds:ca.pem",
+ "//src/core/tsi/test_creds:client.key",
+ "//src/core/tsi/test_creds:client.pem",
+ "//src/core/tsi/test_creds:server0.key",
+ "//src/core/tsi/test_creds:server0.pem",
+ "//src/core/tsi/test_creds:server1.key",
+ "//src/core/tsi/test_creds:server1.pem",
+ ],
+ language = "C",
+ deps = [
+ ":transport_security_test_lib",
+ "//:grpc",
+ "//:gpr",
+ "//:tsi",
+ "//test/core/util:gpr_test_util",
],
)
@@ -28,8 +73,8 @@ grpc_cc_test(
srcs = ["transport_security_test.c"],
language = "C",
deps = [
- "//:gpr",
"//:grpc",
+ "//:gpr",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
diff --git a/test/core/tsi/fake_transport_security_test.c b/test/core/tsi/fake_transport_security_test.c
new file mode 100644
index 0000000000..11be8802b7
--- /dev/null
+++ b/test/core/tsi/fake_transport_security_test.c
@@ -0,0 +1,148 @@
+/*
+ *
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+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/ssl_transport_security_test.c b/test/core/tsi/ssl_transport_security_test.c
new file mode 100644
index 0000000000..364dfa1b73
--- /dev/null
+++ b/test/core/tsi/ssl_transport_security_test.c
@@ -0,0 +1,558 @@
+/*
+ *
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#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_adapter.h"
+#include "test/core/tsi/transport_security_test_lib.h"
+#include "test/core/util/test_config.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#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);
+ /* Destroy others. */
+ tsi_ssl_server_handshaker_factory_destroy(
+ ssl_fixture->server_handshaker_factory);
+ tsi_ssl_client_handshaker_factory_destroy(
+ 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);
+ }
+ }
+ }
+ }
+ }
+}
+
+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();
+ grpc_shutdown();
+ return 0;
+}
diff --git a/test/core/tsi/transport_security_test_lib.c b/test/core/tsi/transport_security_test_lib.c
new file mode 100644
index 0000000000..7d66e110f2
--- /dev/null
+++ b/test/core/tsi/transport_security_test_lib.c
@@ -0,0 +1,550 @@
+/*
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include "src/core/lib/security/transport/tsi_error.h"
+#include "test/core/tsi/transport_security_test_lib.h"
+
+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);
+ return error;
+ }
+ if (result != TSI_OK) {
+ 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);
+ }
+ 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);
+ }
+}
+
+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;
+}
+
+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_free(fixture);
+}
diff --git a/test/core/tsi/transport_security_test_lib.h b/test/core/tsi/transport_security_test_lib.h
new file mode 100644
index 0000000000..8ae2024ee4
--- /dev/null
+++ b/test/core/tsi/transport_security_test_lib.h
@@ -0,0 +1,165 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
+#define GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
+
+#include "src/core/tsi/transport_security_interface.h"
+
+#define TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE 32
+#define TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE 128
+#define TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE 41
+#define TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE 37
+#define TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE 42
+#define TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE 39
+#define TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE 43
+#define TSI_TEST_DEFAULT_BUFFER_SIZE 4096
+#define TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE 16384
+#define TSI_TEST_DEFAULT_CHANNEL_SIZE 32768
+#define TSI_TEST_BIG_MESSAGE_SIZE 17000
+#define TSI_TEST_SMALL_MESSAGE_SIZE 10
+#define TSI_TEST_NUM_OF_ARGUMENTS 8
+#define TSI_TEST_NUM_OF_COMBINATIONS 256
+#define TSI_TEST_UNUSED_BYTES "HELLO GOOGLE"
+
+/* --- tsi_test_fixture object ---
+ The tests for specific TSI implementations should create their own
+ custom "subclass" of this fixture, which wraps all information
+ that will be used to test correctness of TSI handshakes and frame
+ protect/unprotect operations with respect to TSI implementations. */
+typedef struct tsi_test_fixture tsi_test_fixture;
+
+/* --- tsi_test_frame_protector_config object ---
+
+ This object is used to configure different parameters of TSI frame protector
+ APIs. */
+typedef struct tsi_test_frame_protector_config tsi_test_frame_protector_config;
+
+/* V-table for tsi_test_fixture operations that are implemented differently in
+ different TSI implementations. */
+typedef struct tsi_test_fixture_vtable {
+ void (*setup_handshakers)(tsi_test_fixture *fixture);
+ void (*check_handshaker_peers)(tsi_test_fixture *fixture);
+ void (*destruct)(tsi_test_fixture *fixture);
+} tranport_security_test_vtable;
+
+struct tsi_test_fixture {
+ const struct tsi_test_fixture_vtable *vtable;
+ /* client/server TSI handshaker used to perform TSI handshakes, and will get
+ instantiated during the call to setup_handshakers. */
+ tsi_handshaker *client_handshaker;
+ tsi_handshaker *server_handshaker;
+ /* client/server TSI handshaker results used to store the result of TSI
+ handshake. If the handshake fails, the result will store NULL upon
+ finishing the handshake. */
+ tsi_handshaker_result *client_result;
+ tsi_handshaker_result *server_result;
+ /* size of buffer used to store data received from the peer. */
+ size_t handshake_buffer_size;
+ /* simulated channels between client and server. If the server (client)
+ wants to send data to the client (server), he will write data to
+ client_channel (server_channel), which will be read by client (server). */
+ uint8_t *client_channel;
+ uint8_t *server_channel;
+ /* size of data written to the client/server channel. */
+ size_t bytes_written_to_client_channel;
+ size_t bytes_written_to_server_channel;
+ /* size of data read from the client/server channel */
+ size_t bytes_read_from_client_channel;
+ size_t bytes_read_from_server_channel;
+ /* tsi_test_frame_protector_config instance */
+ tsi_test_frame_protector_config *config;
+ /* a flag indicating if client has finished TSI handshake first (i.e., before
+ server).
+ The flag should be referred if and only if TSI handshake finishes
+ successfully. */
+ bool has_client_finished_first;
+ /* a flag indicating whether to test tsi_handshaker_result_get_unused_bytes()
+ for TSI implementation. This field is true by default, and false
+ for SSL TSI implementation due to grpc issue #12164
+ (https://github.com/grpc/grpc/issues/12164).
+ */
+ bool test_unused_bytes;
+};
+
+struct tsi_test_frame_protector_config {
+ /* size of buffer used to store protected frames to be unprotected. */
+ size_t read_buffer_allocated_size;
+ /* size of buffer used to store bytes resulted from unprotect operations. */
+ size_t message_buffer_allocated_size;
+ /* size of buffer used to store frames resulted from protect operations. */
+ size_t protected_buffer_size;
+ /* size of client/server maximum frame size. */
+ size_t client_max_output_protected_frame_size;
+ size_t server_max_output_protected_frame_size;
+ /* pointer that points to client/server message to be protected. */
+ uint8_t *client_message;
+ uint8_t *server_message;
+ /* size of client/server message. */
+ size_t client_message_size;
+ size_t server_message_size;
+};
+
+/* This method creates a tsi_test_frame_protector_config instance. Each
+ parameter of this function is a boolean value indicating whether to set the
+ corresponding parameter with a default value or not. If it's false, it will
+ be set with a specific value which is usually much smaller than the default.
+ Both values are defined with #define directive. */
+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);
+
+/* This method sets different buffer and frame sizes of a
+ tsi_test_frame_protector_config instance with user provided values. */
+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);
+
+/* This method destroys a tsi_test_frame_protector_config instance. */
+void tsi_test_frame_protector_config_destroy(
+ tsi_test_frame_protector_config *config);
+
+/* This method initializes members of tsi_test_fixture instance.
+ Note that the struct instance should be allocated before making
+ this call. */
+void tsi_test_fixture_init(tsi_test_fixture *fixture);
+
+/* This method destroys a tsi_test_fixture instance. Note that the
+ fixture intance must be dynamically allocated and will be freed by
+ this function. */
+void tsi_test_fixture_destroy(tsi_test_fixture *fixture);
+
+/* This method performs a full TSI handshake between a client and a server.
+ Note that the test library will implement the new TSI handshaker API to
+ perform handshakes. */
+void tsi_test_do_handshake(tsi_test_fixture *fixture);
+
+/* This method performs a round trip test between the client and the server.
+ That is, the client sends a protected message to a server who receives the
+ message, and unprotects it. The same operation is triggered again with
+ the client and server switching its role. */
+void tsi_test_do_round_trip(tsi_test_fixture *fixture);
+
+#endif // GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index 1268c2cd10..10eefe159a 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -12,17 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
licenses(["notice"]) # Apache v2
-package(
- default_visibility = ["//visibility:public"],
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/core/util", visibility = "public")
grpc_cc_library(
name = "gpr_test_util",
diff --git a/test/core/util/memory_counters.c b/test/core/util/memory_counters.c
index b898057034..9fb3ffe095 100644
--- a/test/core/util/memory_counters.c
+++ b/test/core/util/memory_counters.c
@@ -48,13 +48,13 @@ static void *guard_malloc(size_t 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 = g_old_allocs.malloc_fn(size + sizeof(size));
+ 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 = vptr;
+ size_t *ptr = (size_t *)vptr;
if (vptr == NULL) {
return guard_malloc(size);
}
@@ -67,13 +67,13 @@ static void *guard_realloc(void *vptr, size_t 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 = g_old_allocs.realloc_fn(ptr, size + sizeof(size));
+ 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 = vptr;
+ size_t *ptr = (size_t *)vptr;
if (!vptr) return;
--ptr;
NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr);
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
index 40cf0a2652..bd386b2148 100644
--- a/test/core/util/mock_endpoint.c
+++ b/test/core/util/mock_endpoint.c
@@ -110,7 +110,7 @@ static const grpc_endpoint_vtable vtable = {
grpc_endpoint *grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice),
grpc_resource_quota *resource_quota) {
- grpc_mock_endpoint *m = gpr_malloc(sizeof(*m));
+ 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);
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index eef1f163f0..38a47584d5 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -183,7 +183,7 @@ void grpc_passthru_endpoint_create(grpc_endpoint **client,
grpc_endpoint **server,
grpc_resource_quota *resource_quota,
grpc_passthru_endpoint_stats *stats) {
- passthru_endpoint *m = gpr_malloc(sizeof(*m));
+ passthru_endpoint *m = (passthru_endpoint *)gpr_malloc(sizeof(*m));
m->halves = 2;
m->shutdown = 0;
m->stats = stats == NULL ? &m->dummy_stats : stats;
diff --git a/test/core/util/port.c b/test/core/util/port.c
index b1fc722858..61f2e5018f 100644
--- a/test/core/util/port.c
+++ b/test/core/util/port.c
@@ -75,7 +75,8 @@ static void chose_port(int port) {
atexit(free_chosen_ports);
}
num_chosen_ports++;
- chosen_ports = gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports);
+ chosen_ports =
+ (int *)gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports);
chosen_ports[num_chosen_ports - 1] = port;
}
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index d5739effb3..851c50941e 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -42,14 +42,14 @@ typedef struct freereq {
static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p,
grpc_error *error) {
- grpc_pollset *pollset = grpc_polling_entity_pollset(p);
+ 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 = arg;
+ freereq *pr = (freereq *)arg;
gpr_mu_lock(pr->mu);
pr->done = 1;
GRPC_LOG_IF_ERROR(
@@ -73,7 +73,7 @@ void grpc_free_port_using_server(int port) {
memset(&req, 0, sizeof(req));
memset(&rsp, 0, sizeof(rsp));
- grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
+ 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,
@@ -130,7 +130,7 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
size_t i;
int port = 0;
- portreq *pr = arg;
+ portreq *pr = (portreq *)arg;
int failed = 0;
grpc_httpcli_response *response = &pr->response;
@@ -204,7 +204,7 @@ int grpc_pick_port_using_server(void) {
memset(&pr, 0, sizeof(pr));
memset(&req, 0, sizeof(req));
- grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
+ 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,
diff --git a/test/core/util/slice_splitter.c b/test/core/util/slice_splitter.c
index f6d892f166..6fcef9acce 100644
--- a/test/core/util/slice_splitter.c
+++ b/test/core/util/slice_splitter.c
@@ -44,7 +44,8 @@ void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices,
switch (mode) {
case GRPC_SLICE_SPLIT_IDENTITY:
*dst_slice_count = src_slice_count;
- *dst_slices = gpr_malloc(sizeof(grpc_slice) * 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]);
@@ -56,7 +57,7 @@ void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices,
for (i = 0; i < src_slice_count; i++) {
length += GRPC_SLICE_LENGTH(src_slices[i]);
}
- *dst_slices = gpr_malloc(sizeof(grpc_slice));
+ *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++) {
@@ -72,7 +73,7 @@ void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices,
length += GRPC_SLICE_LENGTH(src_slices[i]);
}
*dst_slice_count = length;
- *dst_slices = gpr_malloc(sizeof(grpc_slice) * 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++) {
@@ -112,7 +113,7 @@ grpc_slice grpc_slice_merge(grpc_slice *slices, size_t nslices) {
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 = gpr_realloc(out, capacity);
+ out = (uint8_t *)gpr_realloc(out, capacity);
}
memcpy(out + length, GRPC_SLICE_START_PTR(slices[i]),
GRPC_SLICE_LENGTH(slices[i]));
diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c
index 4f3c30dcf6..fc066f9d80 100644
--- a/test/core/util/trickle_endpoint.c
+++ b/test/core/util/trickle_endpoint.c
@@ -128,7 +128,7 @@ static int te_get_fd(grpc_endpoint *ep) {
static void te_finish_write(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
- trickle_endpoint *te = arg;
+ trickle_endpoint *te = (trickle_endpoint *)arg;
gpr_mu_lock(&te->mu);
te->writing = false;
grpc_slice_buffer_reset_and_unref(&te->writing_buffer);
@@ -142,7 +142,7 @@ static const grpc_endpoint_vtable vtable = {
grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap,
double bytes_per_second) {
- trickle_endpoint *te = gpr_malloc(sizeof(*te));
+ trickle_endpoint *te = (trickle_endpoint *)gpr_malloc(sizeof(*te));
te->base.vtable = &vtable;
te->wrapped = wrap;
te->bytes_per_second = bytes_per_second;
diff --git a/test/cpp/codegen/BUILD b/test/cpp/codegen/BUILD
index 4780800645..8de46be816 100644
--- a/test/cpp/codegen/BUILD
+++ b/test/cpp/codegen/BUILD
@@ -14,14 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/codegen")
grpc_cc_test(
name = "codegen_test_full",
diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD
index be9c279f13..e2b6365b13 100644
--- a/test/cpp/common/BUILD
+++ b/test/cpp/common/BUILD
@@ -14,14 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/common")
grpc_cc_test(
name = "alarm_cpp_test",
diff --git a/test/cpp/common/alarm_cpp_test.cc b/test/cpp/common/alarm_cpp_test.cc
index ce4168843c..212972d25d 100644
--- a/test/cpp/common/alarm_cpp_test.cc
+++ b/test/cpp/common/alarm_cpp_test.cc
@@ -18,6 +18,8 @@
#include <grpc++/alarm.h>
#include <grpc++/completion_queue.h>
+#include <thread>
+
#include <gtest/gtest.h>
#include "test/core/util/test_config.h"
@@ -28,6 +30,46 @@ namespace {
TEST(AlarmTest, RegularExpiry) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
+ Alarm alarm;
+ alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
+
+ void* output_tag;
+ bool ok;
+ const CompletionQueue::NextStatus status = cq.AsyncNext(
+ (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+
+ EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
+ EXPECT_TRUE(ok);
+ EXPECT_EQ(junk, output_tag);
+}
+
+TEST(AlarmTest, MultithreadedRegularExpiry) {
+ CompletionQueue cq;
+ void* junk = reinterpret_cast<void*>(1618033);
+ void* output_tag;
+ bool ok;
+ CompletionQueue::NextStatus status;
+ Alarm alarm;
+
+ std::thread t1([&alarm, &cq, &junk] {
+ alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
+ });
+
+ std::thread t2([&cq, &ok, &output_tag, &status] {
+ status = cq.AsyncNext((void**)&output_tag, &ok,
+ grpc_timeout_seconds_to_deadline(2));
+ });
+
+ t1.join();
+ t2.join();
+ EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
+ EXPECT_TRUE(ok);
+ EXPECT_EQ(junk, output_tag);
+}
+
+TEST(AlarmTest, DeprecatedRegularExpiry) {
+ CompletionQueue cq;
+ void* junk = reinterpret_cast<void*>(1618033);
Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(1), junk);
void* output_tag;
@@ -43,7 +85,8 @@ TEST(AlarmTest, RegularExpiry) {
TEST(AlarmTest, MoveConstructor) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
- Alarm first(&cq, grpc_timeout_seconds_to_deadline(1), junk);
+ Alarm first;
+ first.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
Alarm second(std::move(first));
void* output_tag;
bool ok;
@@ -57,7 +100,8 @@ TEST(AlarmTest, MoveConstructor) {
TEST(AlarmTest, MoveAssignment) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
- Alarm first(&cq, grpc_timeout_seconds_to_deadline(1), junk);
+ Alarm first;
+ first.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
Alarm second(std::move(first));
first = std::move(second);
@@ -76,7 +120,8 @@ TEST(AlarmTest, RegularExpiryChrono) {
void* junk = reinterpret_cast<void*>(1618033);
std::chrono::system_clock::time_point one_sec_deadline =
std::chrono::system_clock::now() + std::chrono::seconds(1);
- Alarm alarm(&cq, one_sec_deadline, junk);
+ Alarm alarm;
+ alarm.Set(&cq, one_sec_deadline, junk);
void* output_tag;
bool ok;
@@ -91,7 +136,8 @@ TEST(AlarmTest, RegularExpiryChrono) {
TEST(AlarmTest, ZeroExpiry) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
- Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(0), junk);
+ Alarm alarm;
+ alarm.Set(&cq, grpc_timeout_seconds_to_deadline(0), junk);
void* output_tag;
bool ok;
@@ -106,7 +152,8 @@ TEST(AlarmTest, ZeroExpiry) {
TEST(AlarmTest, NegativeExpiry) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
- Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(-1), junk);
+ Alarm alarm;
+ alarm.Set(&cq, grpc_timeout_seconds_to_deadline(-1), junk);
void* output_tag;
bool ok;
@@ -121,7 +168,8 @@ TEST(AlarmTest, NegativeExpiry) {
TEST(AlarmTest, Cancellation) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
- Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(2), junk);
+ Alarm alarm;
+ alarm.Set(&cq, grpc_timeout_seconds_to_deadline(2), junk);
alarm.Cancel();
void* output_tag;
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index 27c5492c17..b29a13d4fb 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -14,15 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
-package(
- default_visibility=["//visibility:public"], # Allows external users to implement end2end tests.
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/end2end", visibility = "public") # Allows external users to implement end2end tests.
grpc_cc_library(
name = "test_service_impl",
@@ -199,6 +193,7 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
external_deps = [
+ "gmock",
"gtest",
],
)
@@ -241,6 +236,7 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
external_deps = [
+ "gmock",
"gtest",
],
)
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 7cb7b262de..41090d161a 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -260,11 +260,31 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
server_address_ << "localhost:" << port_;
// Setup server
+ BuildAndStartServer();
+
+ gpr_tls_set(&g_is_async_end2end_test, 1);
+ }
+
+ void TearDown() override {
+ gpr_tls_set(&g_is_async_end2end_test, 0);
+ server_->Shutdown();
+ void* ignored_tag;
+ bool ignored_ok;
+ cq_->Shutdown();
+ while (cq_->Next(&ignored_tag, &ignored_ok))
+ ;
+ stub_.reset();
+ poll_overrider_.reset();
+ grpc_recycle_unused_port(port_);
+ }
+
+ void BuildAndStartServer() {
ServerBuilder builder;
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
GetParam().credentials_type);
builder.AddListeningPort(server_address_.str(), server_creds);
- builder.RegisterService(&service_);
+ service_.reset(new grpc::testing::EchoTestService::AsyncService());
+ builder.RegisterService(service_.get());
if (GetParam().health_check_service) {
builder.RegisterService(&health_check_);
}
@@ -276,20 +296,6 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
new ServerBuilderSyncPluginDisabler());
builder.SetOption(move(sync_plugin_disabler));
server_ = builder.BuildAndStart();
-
- gpr_tls_set(&g_is_async_end2end_test, 1);
- }
-
- void TearDown() override {
- server_->Shutdown();
- void* ignored_tag;
- bool ignored_ok;
- cq_->Shutdown();
- while (cq_->Next(&ignored_tag, &ignored_ok))
- ;
- poll_overrider_.reset();
- gpr_tls_set(&g_is_async_end2end_test, 0);
- grpc_recycle_unused_port(port_);
}
void ResetStub() {
@@ -319,8 +325,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer,
+ cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@@ -341,7 +347,7 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
std::unique_ptr<ServerCompletionQueue> cq_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<Server> server_;
- grpc::testing::EchoTestService::AsyncService service_;
+ std::unique_ptr<grpc::testing::EchoTestService::AsyncService> service_;
HealthCheck health_check_;
std::ostringstream server_address_;
int port_;
@@ -359,6 +365,26 @@ TEST_P(AsyncEnd2endTest, SequentialRpcs) {
SendRpc(10);
}
+TEST_P(AsyncEnd2endTest, ReconnectChannel) {
+ if (GetParam().inproc) {
+ return;
+ }
+ ResetStub();
+ SendRpc(1);
+ server_->Shutdown();
+ void* ignored_tag;
+ bool ignored_ok;
+ cq_->Shutdown();
+ while (cq_->Next(&ignored_tag, &ignored_ok))
+ ;
+ BuildAndStartServer();
+ // It needs more than kConnectivityCheckIntervalMsec time to reconnect the
+ // channel.
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(1600, GPR_TIMESPAN)));
+ SendRpc(1);
+}
+
// We do not need to protect notify because the use is synchronized.
void ServerWait(Server* server, int* notify) {
server->Wait();
@@ -370,6 +396,7 @@ TEST_P(AsyncEnd2endTest, WaitAndShutdownTest) {
ResetStub();
SendRpc(1);
EXPECT_EQ(0, notify);
+ gpr_tls_set(&g_is_async_end2end_test, 0);
server_->Shutdown();
wait_thread.join();
EXPECT_EQ(1, notify);
@@ -378,8 +405,9 @@ TEST_P(AsyncEnd2endTest, WaitAndShutdownTest) {
TEST_P(AsyncEnd2endTest, ShutdownThenWait) {
ResetStub();
SendRpc(1);
- server_->Shutdown();
+ std::thread t([this]() { server_->Shutdown(); });
server_->Wait();
+ t.join();
}
// Test a simple RPC using the async version of Next
@@ -407,8 +435,8 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) {
Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now);
Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now);
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(2, true)
@@ -444,8 +472,8 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreaming) {
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream(
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1)));
- service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
Verifier(GetParam().disable_blocking)
.Expect(2, true)
@@ -506,8 +534,8 @@ TEST_P(AsyncEnd2endTest, SimpleClientStreamingWithCoalescingApi) {
std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream(
stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1)));
- service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
cli_stream->Write(send_request, tag(3));
@@ -579,8 +607,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreaming) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
- service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
- cq_.get(), cq_.get(), tag(2));
+ service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
+ cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@@ -635,8 +663,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWAF) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
- service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
- cq_.get(), cq_.get(), tag(2));
+ service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
+ cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@@ -687,8 +715,8 @@ TEST_P(AsyncEnd2endTest, SimpleServerStreamingWithCoalescingApiWL) {
std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
- service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
- cq_.get(), cq_.get(), tag(2));
+ service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
+ cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@@ -741,8 +769,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreaming) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
- service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
Verifier(GetParam().disable_blocking)
.Expect(1, true)
@@ -801,8 +829,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWAF) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
- service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
cli_stream->WriteLast(send_request, WriteOptions(), tag(3));
@@ -869,8 +897,8 @@ TEST_P(AsyncEnd2endTest, SimpleBidiStreamingWithCoalescingApiWL) {
std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
- service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
cli_stream->WriteLast(send_request, WriteOptions(), tag(3));
@@ -946,8 +974,8 @@ TEST_P(AsyncEnd2endTest, ClientInitialMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
auto client_initial_metadata = srv_ctx.client_metadata();
@@ -991,8 +1019,8 @@ TEST_P(AsyncEnd2endTest, ServerInitialMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
srv_ctx.AddInitialMetadata(meta1.first, meta1.second);
@@ -1041,8 +1069,8 @@ TEST_P(AsyncEnd2endTest, ServerTrailingMetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
response_writer.SendInitialMetadata(tag(3));
@@ -1104,8 +1132,8 @@ TEST_P(AsyncEnd2endTest, MetadataRpc) {
std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
auto client_initial_metadata = srv_ctx.client_metadata();
@@ -1168,8 +1196,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckCancellation) {
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
srv_ctx.AsyncNotifyWhenDone(tag(5));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@@ -1203,8 +1231,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) {
stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
srv_ctx.AsyncNotifyWhenDone(tag(5));
- service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
- cq_.get(), tag(2));
+ service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
+ cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@@ -1295,8 +1323,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of 'RequestStream' calls
// and receive the 'RequestStream' call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
- service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
// Client sends 3 messages (tags 3, 4 and 5)
@@ -1426,8 +1454,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of 'ResponseStream' calls and
// receive the call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
- service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
- cq_.get(), cq_.get(), tag(2));
+ service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
+ cq_.get(), cq_.get(), tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
EXPECT_EQ(send_request.message(), recv_request.message());
@@ -1562,8 +1590,8 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
// On the server, request to be notified of the 'BidiStream' call and
// receive the call just made by the client
srv_ctx.AsyncNotifyWhenDone(tag(11));
- service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
- tag(2));
+ service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
+ tag(2));
Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
// Client sends the first and the only message
diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc
index e1160ecdc6..c236f76e89 100644
--- a/test/cpp/end2end/client_lb_end2end_test.cc
+++ b/test/cpp/end2end/client_lb_end2end_test.cc
@@ -85,7 +85,8 @@ class MyTestServiceImpl : public TestServiceImpl {
class ClientLbEnd2endTest : public ::testing::Test {
protected:
- ClientLbEnd2endTest() : server_host_("localhost") {}
+ ClientLbEnd2endTest()
+ : server_host_("localhost"), kRequestMessage_("Live long and prosper.") {}
void SetUp() override {
response_generator_ = grpc_fake_resolver_response_generator_create();
@@ -139,6 +140,7 @@ class ClientLbEnd2endTest : public ::testing::Test {
} // else, default to pick first
args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
response_generator_);
+ args.SetInt("grpc.testing.fixed_reconnect_backoff_ms", 2000);
std::ostringstream uri;
uri << "fake:///";
for (size_t i = 0; i < servers_.size() - 1; ++i) {
@@ -150,18 +152,27 @@ class ClientLbEnd2endTest : public ::testing::Test {
stub_ = grpc::testing::EchoTestService::NewStub(channel_);
}
- void SendRpc(bool expect_ok = true) {
+ Status SendRpc(EchoResponse* response = nullptr) {
+ const bool local_response = (response == nullptr);
+ if (local_response) response = new EchoResponse;
EchoRequest request;
- EchoResponse response;
- request.set_message("Live long and prosper.");
+ request.set_message(kRequestMessage_);
ClientContext context;
- Status status = stub_->Echo(&context, request, &response);
- if (expect_ok) {
- EXPECT_TRUE(status.ok());
- EXPECT_EQ(response.message(), request.message());
- } else {
- EXPECT_FALSE(status.ok());
- }
+ Status status = stub_->Echo(&context, request, response);
+ if (local_response) delete response;
+ return status;
+ }
+
+ void CheckRpcSendOk() {
+ EchoResponse response;
+ const Status status = SendRpc(&response);
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(response.message(), kRequestMessage_);
+ }
+
+ void CheckRpcSendFailure() {
+ const Status status = SendRpc();
+ EXPECT_FALSE(status.ok());
}
struct ServerData {
@@ -169,16 +180,18 @@ class ClientLbEnd2endTest : public ::testing::Test {
std::unique_ptr<Server> server_;
MyTestServiceImpl service_;
std::unique_ptr<std::thread> thread_;
+ bool server_ready_ = false;
explicit ServerData(const grpc::string& server_host, int port = 0) {
port_ = port > 0 ? port : grpc_pick_unused_port_or_die();
gpr_log(GPR_INFO, "starting server on port %d", port_);
std::mutex mu;
+ std::unique_lock<std::mutex> lock(mu);
std::condition_variable cond;
thread_.reset(new std::thread(
std::bind(&ServerData::Start, this, server_host, &mu, &cond)));
- std::unique_lock<std::mutex> lock(mu);
- cond.wait(lock);
+ cond.wait(lock, [this] { return server_ready_; });
+ server_ready_ = false;
gpr_log(GPR_INFO, "server startup complete");
}
@@ -192,6 +205,7 @@ class ClientLbEnd2endTest : public ::testing::Test {
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
std::lock_guard<std::mutex> lock(*mu);
+ server_ready_ = true;
cond->notify_one();
}
@@ -207,16 +221,42 @@ class ClientLbEnd2endTest : public ::testing::Test {
void WaitForServer(size_t server_idx) {
do {
- SendRpc();
+ CheckRpcSendOk();
} while (servers_[server_idx]->service_.request_count() == 0);
ResetCounters();
}
+ bool SeenAllServers() {
+ for (const auto& server : servers_) {
+ if (server->service_.request_count() == 0) return false;
+ }
+ return true;
+ }
+
+ // Updates \a connection_order by appending to it the index of the newly
+ // connected server. Must be called after every single RPC.
+ void UpdateConnectionOrder(
+ const std::vector<std::unique_ptr<ServerData>>& servers,
+ std::vector<int>* connection_order) {
+ for (size_t i = 0; i < servers.size(); ++i) {
+ if (servers[i]->service_.request_count() == 1) {
+ // Was the server index known? If not, update connection_order.
+ const auto it =
+ std::find(connection_order->begin(), connection_order->end(), i);
+ if (it == connection_order->end()) {
+ connection_order->push_back(i);
+ return;
+ }
+ }
+ }
+ }
+
const grpc::string server_host_;
std::shared_ptr<Channel> channel_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::vector<std::unique_ptr<ServerData>> servers_;
grpc_fake_resolver_response_generator* response_generator_;
+ const grpc::string kRequestMessage_;
};
TEST_F(ClientLbEnd2endTest, PickFirst) {
@@ -230,7 +270,7 @@ TEST_F(ClientLbEnd2endTest, PickFirst) {
}
SetNextResolution(ports);
for (size_t i = 0; i < servers_.size(); ++i) {
- SendRpc();
+ CheckRpcSendOk();
}
// All requests should have gone to a single server.
bool found = false;
@@ -258,7 +298,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdates) {
ports.emplace_back(servers_[0]->port_);
SetNextResolution(ports);
gpr_log(GPR_INFO, "****** SET [0] *******");
- SendRpc();
+ CheckRpcSendOk();
EXPECT_EQ(servers_[0]->service_.request_count(), 1);
// An empty update will result in the channel going into TRANSIENT_FAILURE.
@@ -304,7 +344,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdateSuperset) {
ports.emplace_back(servers_[0]->port_);
SetNextResolution(ports);
gpr_log(GPR_INFO, "****** SET [0] *******");
- SendRpc();
+ CheckRpcSendOk();
EXPECT_EQ(servers_[0]->service_.request_count(), 1);
servers_[0]->service_.ResetCounters();
@@ -314,7 +354,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdateSuperset) {
ports.emplace_back(servers_[0]->port_);
SetNextResolution(ports);
gpr_log(GPR_INFO, "****** SET superset *******");
- SendRpc();
+ CheckRpcSendOk();
// We stick to the previously connected server.
WaitForServer(0);
EXPECT_EQ(0, servers_[1]->service_.request_count());
@@ -338,7 +378,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstManyUpdates) {
for (size_t i = 0; i < 1000; ++i) {
std::random_shuffle(ports.begin(), ports.end());
SetNextResolution(ports);
- if (i % 10 == 0) SendRpc();
+ if (i % 10 == 0) CheckRpcSendOk();
}
}
// Check LB policy name for the channel.
@@ -355,13 +395,23 @@ TEST_F(ClientLbEnd2endTest, RoundRobin) {
ports.emplace_back(server->port_);
}
SetNextResolution(ports);
+ // Wait until all backends are ready.
+ do {
+ CheckRpcSendOk();
+ } while (!SeenAllServers());
+ ResetCounters();
+ // "Sync" to the end of the list. Next sequence of picks will start at the
+ // first server (index 0).
+ WaitForServer(servers_.size() - 1);
+ std::vector<int> connection_order;
for (size_t i = 0; i < servers_.size(); ++i) {
- SendRpc();
- }
- // One request should have gone to each server.
- for (size_t i = 0; i < servers_.size(); ++i) {
- EXPECT_EQ(1, servers_[i]->service_.request_count());
+ CheckRpcSendOk();
+ UpdateConnectionOrder(servers_, &connection_order);
}
+ // Backends should be iterated over in the order in which the addresses were
+ // given.
+ const auto expected = std::vector<int>{0, 1, 2};
+ EXPECT_EQ(expected, connection_order);
// Check LB policy name for the channel.
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
}
@@ -378,7 +428,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
SetNextResolution(ports);
WaitForServer(0);
// Send RPCs. They should all go servers_[0]
- for (size_t i = 0; i < 10; ++i) SendRpc();
+ for (size_t i = 0; i < 10; ++i) CheckRpcSendOk();
EXPECT_EQ(10, servers_[0]->service_.request_count());
EXPECT_EQ(0, servers_[1]->service_.request_count());
EXPECT_EQ(0, servers_[2]->service_.request_count());
@@ -394,7 +444,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
EXPECT_EQ(0, servers_[1]->service_.request_count());
WaitForServer(1);
- for (size_t i = 0; i < 10; ++i) SendRpc();
+ for (size_t i = 0; i < 10; ++i) CheckRpcSendOk();
EXPECT_EQ(0, servers_[0]->service_.request_count());
EXPECT_EQ(10, servers_[1]->service_.request_count());
EXPECT_EQ(0, servers_[2]->service_.request_count());
@@ -406,7 +456,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
SetNextResolution(ports);
WaitForServer(2);
- for (size_t i = 0; i < 10; ++i) SendRpc();
+ for (size_t i = 0; i < 10; ++i) CheckRpcSendOk();
EXPECT_EQ(0, servers_[0]->service_.request_count());
EXPECT_EQ(0, servers_[1]->service_.request_count());
EXPECT_EQ(10, servers_[2]->service_.request_count());
@@ -423,7 +473,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
WaitForServer(2);
// Send three RPCs, one per server.
- for (size_t i = 0; i < 3; ++i) SendRpc();
+ for (size_t i = 0; i < 3; ++i) CheckRpcSendOk();
EXPECT_EQ(1, servers_[0]->service_.request_count());
EXPECT_EQ(1, servers_[1]->service_.request_count());
EXPECT_EQ(1, servers_[2]->service_.request_count());
@@ -450,6 +500,37 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
}
+TEST_F(ClientLbEnd2endTest, RoundRobinUpdateInError) {
+ const int kNumServers = 3;
+ StartServers(kNumServers);
+ ResetStub("round_robin");
+ std::vector<int> ports;
+
+ // Start with a single server.
+ ports.emplace_back(servers_[0]->port_);
+ SetNextResolution(ports);
+ WaitForServer(0);
+ // Send RPCs. They should all go to servers_[0]
+ for (size_t i = 0; i < 10; ++i) SendRpc();
+ EXPECT_EQ(10, servers_[0]->service_.request_count());
+ EXPECT_EQ(0, servers_[1]->service_.request_count());
+ EXPECT_EQ(0, servers_[2]->service_.request_count());
+ servers_[0]->service_.ResetCounters();
+
+ // Shutdown one of the servers to be sent in the update.
+ servers_[1]->Shutdown(false);
+ ports.emplace_back(servers_[1]->port_);
+ ports.emplace_back(servers_[2]->port_);
+ SetNextResolution(ports);
+ WaitForServer(0);
+ WaitForServer(2);
+
+ // Send three RPCs, one per server.
+ for (size_t i = 0; i < kNumServers; ++i) SendRpc();
+ // The server in shutdown shouldn't receive any.
+ EXPECT_EQ(0, servers_[1]->service_.request_count());
+}
+
TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) {
// Start servers and send one RPC per server.
const int kNumServers = 3;
@@ -462,7 +543,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) {
for (size_t i = 0; i < 1000; ++i) {
std::random_shuffle(ports.begin(), ports.end());
SetNextResolution(ports);
- if (i % 10 == 0) SendRpc();
+ if (i % 10 == 0) CheckRpcSendOk();
}
// Check LB policy name for the channel.
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
@@ -473,37 +554,30 @@ TEST_F(ClientLbEnd2endTest, RoundRobinConcurrentUpdates) {
// update provisions of RR.
}
-TEST_F(ClientLbEnd2endTest, RoundRobinReconnect) {
+TEST_F(ClientLbEnd2endTest, RoundRobinReresolve) {
// Start servers and send one RPC per server.
- const int kNumServers = 1;
+ const int kNumServers = 3;
std::vector<int> ports;
- ports.push_back(grpc_pick_unused_port_or_die());
+ for (int i = 0; i < kNumServers; ++i) {
+ ports.push_back(grpc_pick_unused_port_or_die());
+ }
StartServers(kNumServers, ports);
ResetStub("round_robin");
SetNextResolution(ports);
- // Send one RPC per backend and make sure they are used in order.
- // Note: This relies on the fact that the subchannels are reported in
- // state READY in the order in which the addresses are specified,
- // which is only true because the backends are all local.
- for (size_t i = 0; i < servers_.size(); ++i) {
- SendRpc();
- EXPECT_EQ(1, servers_[i]->service_.request_count()) << "for backend #" << i;
+ // Send a number of RPCs, which succeed.
+ for (size_t i = 0; i < 100; ++i) {
+ CheckRpcSendOk();
}
- // Check LB policy name for the channel.
- EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
-
// Kill all servers
for (size_t i = 0; i < servers_.size(); ++i) {
servers_[i]->Shutdown(false);
}
// Client request should fail.
- SendRpc(false);
-
+ CheckRpcSendFailure();
// Bring servers back up on the same port (we aren't recreating the channel).
StartServers(kNumServers, ports);
-
// Client request should succeed.
- SendRpc();
+ CheckRpcSendOk();
}
} // namespace
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 8bada48a2b..e54cd03ca2 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -238,6 +238,18 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
int port = grpc_pick_unused_port_or_die();
server_address_ << "127.0.0.1:" << port;
// Setup server
+ BuildAndStartServer(processor);
+ }
+
+ void RestartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) {
+ if (is_server_started_) {
+ server_->Shutdown();
+ BuildAndStartServer(processor);
+ }
+ }
+
+ void BuildAndStartServer(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) {
ServerBuilder builder;
ConfigureServerBuilder(&builder);
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
@@ -685,6 +697,20 @@ TEST_P(End2endTest, MultipleRpcs) {
}
}
+TEST_P(End2endTest, ReconnectChannel) {
+ if (GetParam().inproc) {
+ return;
+ }
+ ResetStub();
+ SendRpc(stub_.get(), 1, false);
+ RestartServer(std::shared_ptr<AuthMetadataProcessor>());
+ // It needs more than kConnectivityCheckIntervalMsec time to reconnect the
+ // channel.
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(1600, GPR_TIMESPAN)));
+ SendRpc(stub_.get(), 1, false);
+}
+
TEST_P(End2endTest, RequestStreamOneRequest) {
ResetStub();
EchoRequest request;
@@ -731,6 +757,22 @@ TEST_P(End2endTest, RequestStreamTwoRequests) {
EXPECT_TRUE(s.ok());
}
+TEST_P(End2endTest, RequestStreamTwoRequestsWithWriteThrough) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+
+ auto stream = stub_->RequestStream(&context, &response);
+ request.set_message("hello");
+ EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through()));
+ EXPECT_TRUE(stream->Write(request, WriteOptions().set_write_through()));
+ stream->WritesDone();
+ Status s = stream->Finish();
+ EXPECT_EQ(response.message(), "hellohello");
+ EXPECT_TRUE(s.ok());
+}
+
TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) {
ResetStub();
EchoRequest request;
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index b5cff664f6..570a3d1067 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -332,7 +332,8 @@ class GrpclbEnd2endTest : public ::testing::Test {
num_backends_(num_backends),
num_balancers_(num_balancers),
client_load_reporting_interval_seconds_(
- client_load_reporting_interval_seconds) {}
+ client_load_reporting_interval_seconds),
+ kRequestMessage_("Live long and prosper.") {}
void SetUp() override {
response_generator_ = grpc_fake_resolver_response_generator_create();
@@ -378,6 +379,10 @@ class GrpclbEnd2endTest : public ::testing::Test {
stub_ = grpc::testing::EchoTestService::NewStub(channel_);
}
+ void ResetBackendCounters() {
+ for (const auto& backend : backends_) backend->ResetCounters();
+ }
+
ClientStats WaitForLoadReports() {
ClientStats client_stats;
for (const auto& balancer : balancers_) {
@@ -386,6 +391,27 @@ class GrpclbEnd2endTest : public ::testing::Test {
return client_stats;
}
+ bool SeenAllBackends() {
+ for (const auto& backend : backends_) {
+ if (backend->request_count() == 0) return false;
+ }
+ return true;
+ }
+
+ void WaitForAllBackends() {
+ while (!SeenAllBackends()) {
+ CheckRpcSendOk();
+ }
+ ResetBackendCounters();
+ }
+
+ void WaitForBackend(size_t backend_idx) {
+ do {
+ CheckRpcSendOk();
+ } while (backends_[backend_idx]->request_count() == 0);
+ ResetBackendCounters();
+ }
+
struct AddressData {
int port;
bool is_balancer;
@@ -429,20 +455,31 @@ class GrpclbEnd2endTest : public ::testing::Test {
balancers_.at(i)->add_response(response, delay_ms);
}
- std::vector<std::pair<Status, EchoResponse>> SendRpc(const string& message,
- int num_rpcs,
- int timeout_ms = 1000) {
- std::vector<std::pair<Status, EchoResponse>> results;
+ Status SendRpc(EchoResponse* response = nullptr, int timeout_ms = 1000) {
+ const bool local_response = (response == nullptr);
+ if (local_response) response = new EchoResponse;
EchoRequest request;
- EchoResponse response;
- request.set_message(message);
- for (int i = 0; i < num_rpcs; i++) {
- ClientContext context;
- context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms));
- Status status = stub_->Echo(&context, request, &response);
- results.push_back(std::make_pair(status, response));
+ request.set_message(kRequestMessage_);
+ ClientContext context;
+ context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms));
+ Status status = stub_->Echo(&context, request, response);
+ if (local_response) delete response;
+ return status;
+ }
+
+ void CheckRpcSendOk(const size_t times = 1) {
+ for (size_t i = 0; i < times; ++i) {
+ EchoResponse response;
+ const Status status = SendRpc(&response);
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kRequestMessage_);
}
- return results;
+ }
+
+ void CheckRpcSendFailure() {
+ const Status status = SendRpc();
+ EXPECT_FALSE(status.ok());
}
template <typename T>
@@ -499,14 +536,12 @@ class GrpclbEnd2endTest : public ::testing::Test {
const int client_load_reporting_interval_seconds_;
std::shared_ptr<Channel> channel_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
-
std::vector<std::unique_ptr<BackendServiceImpl>> backends_;
std::vector<std::unique_ptr<BalancerServiceImpl>> balancers_;
-
std::vector<ServerThread<BackendService>> backend_servers_;
std::vector<ServerThread<BalancerService>> balancer_servers_;
-
grpc_fake_resolver_response_generator* response_generator_;
+ const grpc::string kRequestMessage_;
};
class SingleBalancerTest : public GrpclbEnd2endTest {
@@ -521,17 +556,12 @@ TEST_F(SingleBalancerTest, Vanilla) {
0);
// Make sure that trying to connect works without a call.
channel_->GetState(true /* try_to_connect */);
- // Send 100 RPCs per server.
- const auto& statuses_and_responses =
- SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
-
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
+
+ // We need to wait for all backends to come online.
+ WaitForAllBackends();
+
+ // Send kNumRpcsPerAddress RPCs per server.
+ CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
// Each backend should have gotten 100 requests.
for (size_t i = 0; i < backends_.size(); ++i) {
@@ -561,8 +591,7 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
const auto t0 = system_clock::now();
// Client will block: LB will initially send empty serverlist.
- const auto& statuses_and_responses =
- SendRpc(kMessage_, num_backends_, kCallDeadlineMs);
+ CheckRpcSendOk(num_backends_);
const auto ellapsed_ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
system_clock::now() - t0);
@@ -576,13 +605,6 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
for (size_t i = 0; i < backends_.size(); ++i) {
EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
}
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
balancers_[0]->NotifyDoneWithServerlists();
// The balancer got a single request.
EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
@@ -593,70 +615,6 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
}
-TEST_F(SingleBalancerTest, RepeatedServerlist) {
- constexpr int kServerlistDelayMs = 100;
-
- // Send a serverlist right away.
- ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
- 0);
- // ... and the same one a bit later.
- ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
- kServerlistDelayMs);
-
- // Send num_backends/2 requests.
- auto statuses_and_responses = SendRpc(kMessage_, num_backends_ / 2);
- // only the first half of the backends will receive them.
- for (size_t i = 0; i < backends_.size(); ++i) {
- if (i < backends_.size() / 2)
- EXPECT_EQ(1U, backend_servers_[i].service_->request_count())
- << "for backend #" << i;
- else
- EXPECT_EQ(0U, backend_servers_[i].service_->request_count())
- << "for backend #" << i;
- }
- EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
-
- // Wait for the (duplicated) serverlist update.
- gpr_sleep_until(gpr_time_add(
- gpr_now(GPR_CLOCK_REALTIME),
- gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN)));
-
- // Verify the LB has sent two responses.
- EXPECT_EQ(2U, balancer_servers_[0].service_->response_count());
-
- // Some more calls to complete the total number of backends.
- statuses_and_responses = SendRpc(
- kMessage_,
- num_backends_ / 2 + (num_backends_ & 0x1) /* extra one if num_bes odd */);
- // Because a duplicated serverlist should have no effect, all backends must
- // have been hit once now.
- for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
- }
- EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
- balancers_[0]->NotifyDoneWithServerlists();
- // The balancer got a single request.
- EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
- // Check LB policy name for the channel.
- EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
-}
-
TEST_F(SingleBalancerTest, BackendsRestart) {
const size_t kNumRpcsPerAddress = 100;
ScheduleResponseForBalancer(
@@ -664,21 +622,8 @@ TEST_F(SingleBalancerTest, BackendsRestart) {
0);
// Make sure that trying to connect works without a call.
channel_->GetState(true /* try_to_connect */);
- // Send 100 RPCs per server.
- auto statuses_and_responses =
- SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
- // Each backend should have gotten 100 requests.
- for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(kNumRpcsPerAddress,
- backend_servers_[i].service_->request_count());
- }
+ // Send kNumRpcsPerAddress RPCs per server.
+ CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
balancers_[0]->NotifyDoneWithServerlists();
// The balancer got a single request.
EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
@@ -687,11 +632,7 @@ TEST_F(SingleBalancerTest, BackendsRestart) {
for (size_t i = 0; i < backends_.size(); ++i) {
if (backends_[i]->Shutdown()) backend_servers_[i].Shutdown();
}
- statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- EXPECT_FALSE(status.ok());
- }
+ CheckRpcSendFailure();
for (size_t i = 0; i < num_backends_; ++i) {
backends_.emplace_back(new BackendServiceImpl());
backend_servers_.emplace_back(ServerThread<BackendService>(
@@ -703,11 +644,7 @@ TEST_F(SingleBalancerTest, BackendsRestart) {
// TODO(dgq): implement the "backend restart" component as well. We need extra
// machinery to either update the LB responses "on the fly" or instruct
// backends which ports to restart on.
- statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- EXPECT_FALSE(status.ok());
- }
+ CheckRpcSendFailure();
// Check LB policy name for the channel.
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
}
@@ -727,13 +664,9 @@ TEST_F(UpdatesTest, UpdateBalancers) {
// Start servers and send 10 RPCs per server.
gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
- auto statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should have gone to the first backend.
EXPECT_EQ(10U, backend_servers_[0].service_->request_count());
@@ -758,22 +691,12 @@ TEST_F(UpdatesTest, UpdateBalancers) {
// Wait until update has been processed, as signaled by the second backend
// receiving a request.
EXPECT_EQ(0U, backend_servers_[1].service_->request_count());
- do {
- auto statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
- } while (backend_servers_[1].service_->request_count() == 0);
+ WaitForBackend(1);
backend_servers_[1].service_->ResetCounters();
gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
- statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should have gone to the second backend.
EXPECT_EQ(10U, backend_servers_[1].service_->request_count());
@@ -804,13 +727,9 @@ TEST_F(UpdatesTest, UpdateBalancersRepeated) {
// Start servers and send 10 RPCs per server.
gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
- auto statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should have gone to the first backend.
EXPECT_EQ(10U, backend_servers_[0].service_->request_count());
@@ -837,11 +756,7 @@ TEST_F(UpdatesTest, UpdateBalancersRepeated) {
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN));
// Send 10 seconds worth of RPCs
do {
- statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
+ CheckRpcSendOk();
} while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
// grpclb continued using the original LB call to the first balancer, which
// doesn't assign the second backend.
@@ -860,11 +775,7 @@ TEST_F(UpdatesTest, UpdateBalancersRepeated) {
gpr_time_from_millis(10000, GPR_TIMESPAN));
// Send 10 seconds worth of RPCs
do {
- statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
+ CheckRpcSendOk();
} while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0);
// grpclb continued using the original LB call to the first balancer, which
// doesn't assign the second backend.
@@ -886,12 +797,8 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) {
// Start servers and send 10 RPCs per server.
gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH ==========");
- auto statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should have gone to the first backend.
EXPECT_EQ(10U, backend_servers_[0].service_->request_count());
@@ -903,12 +810,8 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) {
// This is serviced by the existing RR policy
gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH ==========");
- statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should again have gone to the first backend.
EXPECT_EQ(20U, backend_servers_[0].service_->request_count());
EXPECT_EQ(0U, backend_servers_[1].service_->request_count());
@@ -935,23 +838,13 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) {
// receiving a request. In the meantime, the client continues to be serviced
// (by the first backend) without interruption.
EXPECT_EQ(0U, backend_servers_[1].service_->request_count());
- do {
- auto statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
- } while (backend_servers_[1].service_->request_count() == 0);
+ WaitForBackend(1);
// This is serviced by the existing RR policy
backend_servers_[1].service_->ResetCounters();
gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH ==========");
- statuses_and_responses = SendRpc(kMessage_, 10);
+ CheckRpcSendOk(10);
gpr_log(GPR_INFO, "========= DONE WITH THIRD BATCH ==========");
- for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
- }
// All 10 requests should have gone to the second backend.
EXPECT_EQ(10U, backend_servers_[1].service_->request_count());
@@ -974,14 +867,11 @@ TEST_F(SingleBalancerTest, Drop) {
0, BalancerServiceImpl::BuildResponseForBackends(
GetBackendPorts(), {{"rate_limiting", 1}, {"load_balancing", 2}}),
0);
- // Send 100 RPCs for each server and drop address.
- const auto& statuses_and_responses =
- SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
-
+ // Send kNumRpcsPerAddress RPCs for each server and drop address.
size_t num_drops = 0;
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
+ for (size_t i = 0; i < kNumRpcsPerAddress * (num_backends_ + 3); ++i) {
+ EchoResponse response;
+ const Status status = SendRpc(&response);
if (!status.ok() &&
status.error_message() == "Call dropped by load balancing policy") {
++num_drops;
@@ -1010,12 +900,9 @@ TEST_F(SingleBalancerTest, DropAllFirst) {
0, BalancerServiceImpl::BuildResponseForBackends(
{}, {{"rate_limiting", 1}, {"load_balancing", 1}}),
0);
- const auto& statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- EXPECT_FALSE(status.ok());
- EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy");
- }
+ const Status status = SendRpc();
+ EXPECT_FALSE(status.ok());
+ EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy");
}
TEST_F(SingleBalancerTest, DropAll) {
@@ -1028,21 +915,13 @@ TEST_F(SingleBalancerTest, DropAll) {
1000);
// First call succeeds.
- auto statuses_and_responses = SendRpc(kMessage_, 1);
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
+ CheckRpcSendOk();
// But eventually, the update with only dropped servers is processed and calls
// fail.
+ Status status;
do {
- statuses_and_responses = SendRpc(kMessage_, 1);
- ASSERT_EQ(statuses_and_responses.size(), 1UL);
- } while (statuses_and_responses[0].first.ok());
- const Status& status = statuses_and_responses[0].first;
+ status = SendRpc();
+ } while (status.ok());
EXPECT_FALSE(status.ok());
EXPECT_EQ(status.error_message(), "Call dropped by load balancing policy");
}
@@ -1057,18 +936,8 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
ScheduleResponseForBalancer(
0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}),
0);
- // Send 100 RPCs per server.
- const auto& statuses_and_responses =
- SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
-
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
- EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
- << " message=" << status.error_message();
- EXPECT_EQ(response.message(), kMessage_);
- }
-
+ // Send kNumRpcsPerAddress RPCs per server.
+ CheckRpcSendOk(kNumRpcsPerAddress * num_backends_);
// Each backend should have gotten 100 requests.
for (size_t i = 0; i < backends_.size(); ++i) {
EXPECT_EQ(kNumRpcsPerAddress,
@@ -1096,14 +965,11 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) {
0, BalancerServiceImpl::BuildResponseForBackends(
GetBackendPorts(), {{"rate_limiting", 2}, {"load_balancing", 1}}),
0);
- // Send 100 RPCs for each server and drop address.
- const auto& statuses_and_responses =
- SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
size_t num_drops = 0;
- for (const auto& status_and_response : statuses_and_responses) {
- const Status& status = status_and_response.first;
- const EchoResponse& response = status_and_response.second;
+ for (size_t i = 0; i < kNumRpcsPerAddress * (num_backends_ + 3); ++i) {
+ EchoResponse response;
+ const Status status = SendRpc(&response);
if (!status.ok() &&
status.error_message() == "Call dropped by load balancing policy") {
++num_drops;
diff --git a/test/cpp/interop/BUILD b/test/cpp/interop/BUILD
index 9123bd929e..4f21551ff4 100644
--- a/test/cpp/interop/BUILD
+++ b/test/cpp/interop/BUILD
@@ -14,14 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/interop")
grpc_cc_library(
name = "server_helper_lib",
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 442da38426..985a335f1b 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -14,14 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/microbenchmarks")
grpc_cc_test(
name = "noop-benchmark",
@@ -33,75 +28,94 @@ grpc_cc_test(
grpc_cc_library(
name = "helpers",
+ testonly = 1,
srcs = ["helpers.cc"],
hdrs = [
"fullstack_context_mutators.h",
"fullstack_fixtures.h",
"helpers.h",
],
+ external_deps = [
+ "benchmark",
+ ],
deps = [
"//:grpc++_unsecure",
"//src/proto/grpc/testing:echo_proto",
"//test/core/util:grpc_test_util_unsecure",
],
- external_deps = [
- "benchmark",
- ],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_closure",
+ testonly = 1,
srcs = ["bm_closure.cc"],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_cq",
+ testonly = 1,
srcs = ["bm_cq.cc"],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_cq_multiple_threads",
+ testonly = 1,
srcs = ["bm_cq_multiple_threads.cc"],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_error",
+ testonly = 1,
srcs = ["bm_error.cc"],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_fullstack_streaming_ping_pong",
- srcs = ["bm_fullstack_streaming_ping_pong.cc"],
+ testonly = 1,
+ srcs = [
+ "bm_fullstack_streaming_ping_pong.cc",
+ "fullstack_streaming_ping_pong.h",
+ ],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_fullstack_streaming_pump",
- srcs = ["bm_fullstack_streaming_pump.cc"],
+ testonly = 1,
+ srcs = [
+ "bm_fullstack_streaming_pump.cc",
+ "fullstack_streaming_pump.h",
+ ],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_fullstack_trickle",
+ testonly = 1,
srcs = ["bm_fullstack_trickle.cc"],
- deps = [":helpers"],
- external_deps = [
- "gflags",
+ deps = [
+ ":helpers",
+ "//test/cpp/util:test_config",
],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_fullstack_unary_ping_pong",
- srcs = ["bm_fullstack_unary_ping_pong.cc"],
+ testonly = 1,
+ srcs = [
+ "bm_fullstack_unary_ping_pong.cc",
+ "fullstack_unary_ping_pong.h",
+ ],
deps = [":helpers"],
)
-grpc_cc_test(
+grpc_cc_binary(
name = "bm_metadata",
+ testonly = 1,
srcs = ["bm_metadata.cc"],
deps = [":helpers"],
)
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 508f7f94d6..cadc9b2a11 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -35,10 +35,11 @@ extern "C" {
#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/filters/load_reporting/load_reporting_filter.h"
+#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h"
#include "src/core/ext/filters/message_size/message_size_filter.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport_impl.h"
@@ -396,10 +397,6 @@ grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
-char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
- return gpr_strdup("peer");
-}
-
void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info) {}
@@ -412,7 +409,6 @@ static const grpc_channel_filter dummy_filter = {StartTransportStreamOp,
0,
InitChannelElem,
DestroyChannelElem,
- GetPeer,
GetChannelInfo,
"dummy_filter"};
@@ -459,11 +455,6 @@ void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
/* implementation of grpc_transport_destroy */
void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
-/* implementation of grpc_transport_get_peer */
-char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
- return gpr_strdup("transport_peer");
-}
-
/* implementation of grpc_transport_get_endpoint */
grpc_endpoint *GetEndpoint(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
return nullptr;
@@ -473,7 +464,7 @@ static const grpc_transport_vtable dummy_transport_vtable = {
0, "dummy_http2", InitStream,
SetPollset, SetPollsetSet, PerformStreamOp,
PerformOp, DestroyStream, Destroy,
- GetPeer, GetEndpoint};
+ GetEndpoint};
static grpc_transport dummy_transport = {&dummy_transport_vtable};
@@ -629,7 +620,7 @@ BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, SendEmptyMetadata);
typedef Fixture<&grpc_message_size_filter, CHECKS_NOT_LAST> MessageSizeFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, SendEmptyMetadata);
-typedef Fixture<&grpc_load_reporting_filter, CHECKS_NOT_LAST>
+typedef Fixture<&grpc_server_load_reporting_filter, CHECKS_NOT_LAST>
LoadReportingFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
@@ -639,18 +630,22 @@ BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
namespace isolated_call_filter {
+typedef struct { grpc_call_combiner *call_combiner; } call_data;
+
static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op_batch *op) {
+ call_data *calld = static_cast<call_data *>(elem->call_data);
if (op->recv_initial_metadata) {
- GRPC_CLOSURE_SCHED(
- exec_ctx,
+ GRPC_CALL_COMBINER_START(
+ exec_ctx, calld->call_combiner,
op->payload->recv_initial_metadata.recv_initial_metadata_ready,
- GRPC_ERROR_NONE);
+ GRPC_ERROR_NONE, "recv_initial_metadata");
}
if (op->recv_message) {
- GRPC_CLOSURE_SCHED(exec_ctx, op->payload->recv_message.recv_message_ready,
- GRPC_ERROR_NONE);
+ GRPC_CALL_COMBINER_START(exec_ctx, calld->call_combiner,
+ op->payload->recv_message.recv_message_ready,
+ GRPC_ERROR_NONE, "recv_message");
}
GRPC_CLOSURE_SCHED(exec_ctx, op->on_complete, GRPC_ERROR_NONE);
}
@@ -667,6 +662,8 @@ static void StartTransportOp(grpc_exec_ctx *exec_ctx,
static grpc_error *InitCallElem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
+ call_data *calld = static_cast<call_data *>(elem->call_data);
+ calld->call_combiner = args->call_combiner;
return GRPC_ERROR_NONE;
}
@@ -687,24 +684,19 @@ grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
-char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
- return gpr_strdup("peer");
-}
-
void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info) {}
static const grpc_channel_filter isolated_call_filter = {
StartTransportStreamOp,
StartTransportOp,
- 0,
+ sizeof(call_data),
InitCallElem,
SetPollsetOrPollsetSet,
DestroyCallElem,
0,
InitChannelElem,
DestroyChannelElem,
- GetPeer,
GetChannelInfo,
"isolated_call_filter"};
} // namespace isolated_call_filter
diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
index cb113c5254..070034fe33 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
@@ -29,6 +29,7 @@
extern "C" {
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/resource_quota.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -154,23 +155,59 @@ class Fixture {
grpc_transport *t_;
};
-static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+class Closure : public grpc_closure {
+ public:
+ virtual ~Closure() {}
+};
+
+template <class F>
+std::unique_ptr<Closure> MakeClosure(
+ F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
+ struct C : public Closure {
+ C(const F &f, grpc_closure_scheduler *sched) : f_(f) {
+ GRPC_CLOSURE_INIT(this, Execute, this, sched);
+ }
+ F f_;
+ static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ static_cast<C *>(arg)->f_(exec_ctx, error);
+ }
+ };
+ return std::unique_ptr<Closure>(new C(f, sched));
+}
+
+template <class F>
+grpc_closure *MakeOnceClosure(
+ F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
+ struct C : public grpc_closure {
+ C(const F &f) : f_(f) {}
+ F f_;
+ static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ static_cast<C *>(arg)->f_(exec_ctx, error);
+ delete static_cast<C *>(arg);
+ }
+ };
+ auto *c = new C{f};
+ return GRPC_CLOSURE_INIT(c, C::Execute, c, sched);
+}
class Stream {
public:
Stream(Fixture *f) : f_(f) {
- GRPC_STREAM_REF_INIT(&refcount_, 1, DoNothing, nullptr, "test_stream");
stream_size_ = grpc_transport_stream_size(f->transport());
stream_ = gpr_malloc(stream_size_);
arena_ = gpr_arena_create(4096);
}
~Stream() {
+ gpr_event_wait(&done_, gpr_inf_future(GPR_CLOCK_REALTIME));
gpr_free(stream_);
gpr_arena_destroy(arena_);
}
void Init(benchmark::State &state) {
+ GRPC_STREAM_REF_INIT(&refcount_, 1, &Stream::FinishDestroy, this,
+ "test_stream");
+ gpr_event_init(&done_);
memset(stream_, 0, stream_size_);
if ((state.iterations() & 0xffff) == 0) {
gpr_arena_destroy(arena_);
@@ -181,13 +218,17 @@ class Stream {
NULL, arena_);
}
- void DestroyThen(grpc_closure *closure) {
- grpc_transport_destroy_stream(f_->exec_ctx(), f_->transport(),
- static_cast<grpc_stream *>(stream_), closure);
+ void DestroyThen(grpc_exec_ctx *exec_ctx, grpc_closure *closure) {
+ destroy_closure_ = closure;
+#ifndef NDEBUG
+ grpc_stream_unref(exec_ctx, &refcount_, "DestroyThen");
+#else
+ grpc_stream_unref(exec_ctx, &refcount_);
+#endif
}
- void Op(grpc_transport_stream_op_batch *op) {
- grpc_transport_perform_stream_op(f_->exec_ctx(), f_->transport(),
+ void Op(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op) {
+ grpc_transport_perform_stream_op(exec_ctx, f_->transport(),
static_cast<grpc_stream *>(stream_), op);
}
@@ -196,48 +237,24 @@ class Stream {
}
private:
+ static void FinishDestroy(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ auto stream = static_cast<Stream *>(arg);
+ grpc_transport_destroy_stream(exec_ctx, stream->f_->transport(),
+ static_cast<grpc_stream *>(stream->stream_),
+ stream->destroy_closure_);
+ gpr_event_set(&stream->done_, (void *)1);
+ }
+
Fixture *f_;
grpc_stream_refcount refcount_;
gpr_arena *arena_;
size_t stream_size_;
void *stream_;
+ grpc_closure *destroy_closure_ = nullptr;
+ gpr_event done_;
};
-class Closure : public grpc_closure {
- public:
- virtual ~Closure() {}
-};
-
-template <class F>
-std::unique_ptr<Closure> MakeClosure(
- F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
- struct C : public Closure {
- C(const F &f, grpc_closure_scheduler *sched) : f_(f) {
- GRPC_CLOSURE_INIT(this, Execute, this, sched);
- }
- F f_;
- static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
- static_cast<C *>(arg)->f_(exec_ctx, error);
- }
- };
- return std::unique_ptr<Closure>(new C(f, sched));
-}
-
-template <class F>
-grpc_closure *MakeOnceClosure(
- F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
- struct C : public grpc_closure {
- C(const F &f) : f_(f) {}
- F f_;
- static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
- static_cast<C *>(arg)->f_(exec_ctx, error);
- delete static_cast<C *>(arg);
- }
- };
- auto *c = new C{f};
- return GRPC_CLOSURE_INIT(c, C::Execute, c, sched);
-}
-
////////////////////////////////////////////////////////////////////////////////
// Benchmarks
//
@@ -246,11 +263,18 @@ static void BM_StreamCreateDestroy(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
+ grpc_transport_stream_op_batch op;
+ grpc_transport_stream_op_batch_payload op_payload;
+ memset(&op, 0, sizeof(op));
+ op.cancel_stream = true;
+ op.payload = &op_payload;
+ op_payload.cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
std::unique_ptr<Closure> next =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
s.Init(state);
- s.DestroyThen(next.get());
+ s.Op(exec_ctx, &op);
+ s.DestroyThen(exec_ctx, next.get());
});
GRPC_CLOSURE_RUN(f.exec_ctx(), next.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
@@ -286,6 +310,7 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) {
Stream s(&f);
grpc_transport_stream_op_batch op;
grpc_transport_stream_op_batch_payload op_payload;
+ memset(&op_payload, 0, sizeof(op_payload));
std::unique_ptr<Closure> start;
std::unique_ptr<Closure> done;
@@ -313,14 +338,14 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) {
op.on_complete = done.get();
op.send_initial_metadata = true;
op.payload->send_initial_metadata.send_initial_metadata = &b;
- s.Op(&op);
+ s.Op(exec_ctx, &op);
});
done = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
reset_op();
op.cancel_stream = true;
op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
- s.Op(&op);
- s.DestroyThen(start.get());
+ s.Op(exec_ctx, &op);
+ s.DestroyThen(exec_ctx, start.get());
});
GRPC_CLOSURE_SCHED(f.exec_ctx(), start.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
@@ -337,6 +362,7 @@ static void BM_TransportEmptyOp(benchmark::State &state) {
s.Init(state);
grpc_transport_stream_op_batch op;
grpc_transport_stream_op_batch_payload op_payload;
+ memset(&op_payload, 0, sizeof(op_payload));
auto reset_op = [&]() {
memset(&op, 0, sizeof(op));
op.payload = &op_payload;
@@ -346,24 +372,31 @@ static void BM_TransportEmptyOp(benchmark::State &state) {
if (!state.KeepRunning()) return;
reset_op();
op.on_complete = c.get();
- s.Op(&op);
+ s.Op(exec_ctx, &op);
});
GRPC_CLOSURE_SCHED(f.exec_ctx(), c.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
- s.DestroyThen(
- MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ reset_op();
+ op.cancel_stream = true;
+ op_payload.cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
+ s.Op(f.exec_ctx(), &op);
+ s.DestroyThen(f.exec_ctx(), MakeOnceClosure([](grpc_exec_ctx *exec_ctx,
+ grpc_error *error) {}));
f.FlushExecCtx();
track_counters.Finish(state);
}
BENCHMARK(BM_TransportEmptyOp);
+std::vector<std::unique_ptr<gpr_event>> done_events;
+
static void BM_TransportStreamSend(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
- Stream s(&f);
- s.Init(state);
+ auto s = std::unique_ptr<Stream>(new Stream(&f));
+ s->Init(state);
grpc_transport_stream_op_batch op;
grpc_transport_stream_op_batch_payload op_payload;
+ memset(&op_payload, 0, sizeof(op_payload));
auto reset_op = [&]() {
memset(&op, 0, sizeof(op));
op.payload = &op_payload;
@@ -387,11 +420,17 @@ static void BM_TransportStreamSend(benchmark::State &state) {
grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
}
+ gpr_event *bm_done = new gpr_event;
+ gpr_event_init(bm_done);
+
std::unique_ptr<Closure> c =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
- if (!state.KeepRunning()) return;
+ if (!state.KeepRunning()) {
+ gpr_event_set(bm_done, (void *)1);
+ return;
+ }
// force outgoing window to be yuge
- s.chttp2_stream()->flow_control.remote_window_delta =
+ s->chttp2_stream()->flow_control.remote_window_delta =
1024 * 1024 * 1024;
f.chttp2_transport()->flow_control.remote_window = 1024 * 1024 * 1024;
grpc_slice_buffer_stream_init(&send_stream, &send_buffer, 0);
@@ -399,23 +438,27 @@ static void BM_TransportStreamSend(benchmark::State &state) {
op.on_complete = c.get();
op.send_message = true;
op.payload->send_message.send_message = &send_stream.base;
- s.Op(&op);
+ s->Op(exec_ctx, &op);
});
reset_op();
op.send_initial_metadata = true;
op.payload->send_initial_metadata.send_initial_metadata = &b;
op.on_complete = c.get();
- s.Op(&op);
+ s->Op(f.exec_ctx(), &op);
f.FlushExecCtx();
+ gpr_event_wait(bm_done, gpr_inf_future(GPR_CLOCK_REALTIME));
+ done_events.emplace_back(bm_done);
+
reset_op();
op.cancel_stream = true;
op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
- s.Op(&op);
- s.DestroyThen(
- MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ s->Op(f.exec_ctx(), &op);
+ s->DestroyThen(f.exec_ctx(), MakeOnceClosure([](grpc_exec_ctx *exec_ctx,
+ grpc_error *error) {}));
f.FlushExecCtx();
+ s.reset();
track_counters.Finish(state);
grpc_metadata_batch_destroy(f.exec_ctx(), &b);
grpc_slice_buffer_destroy(&send_buffer);
@@ -485,6 +528,7 @@ static void BM_TransportStreamRecv(benchmark::State &state) {
Stream s(&f);
s.Init(state);
grpc_transport_stream_op_batch_payload op_payload;
+ memset(&op_payload, 0, sizeof(op_payload));
grpc_transport_stream_op_batch op;
grpc_byte_stream *recv_stream;
grpc_slice incoming_data = CreateIncomingDataSlice(state.range(0), 16384);
@@ -531,7 +575,7 @@ static void BM_TransportStreamRecv(benchmark::State &state) {
op.recv_message = true;
op.payload->recv_message.recv_message = &recv_stream;
op.payload->recv_message.recv_message_ready = drain_start.get();
- s.Op(&op);
+ s.Op(exec_ctx, &op);
f.PushInput(grpc_slice_ref(incoming_data));
});
@@ -574,7 +618,7 @@ static void BM_TransportStreamRecv(benchmark::State &state) {
op.payload->recv_initial_metadata.recv_initial_metadata_ready =
do_nothing.get();
op.on_complete = c.get();
- s.Op(&op);
+ s.Op(f.exec_ctx(), &op);
f.PushInput(SLICE_FROM_BUFFER(
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
// Generated using:
@@ -592,9 +636,9 @@ static void BM_TransportStreamRecv(benchmark::State &state) {
reset_op();
op.cancel_stream = true;
op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
- s.Op(&op);
- s.DestroyThen(
- MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
+ s.Op(f.exec_ctx(), &op);
+ s.DestroyThen(f.exec_ctx(), MakeOnceClosure([](grpc_exec_ctx *exec_ctx,
+ grpc_error *error) {}));
f.FlushExecCtx();
track_counters.Finish(state);
grpc_metadata_batch_destroy(f.exec_ctx(), &b);
diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
index f109fe6251..9d71d3990d 100644
--- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
+++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
@@ -38,6 +38,8 @@ struct grpc_pollset {
namespace grpc {
namespace testing {
+auto& force_library_initialization = Library::get();
+
static void* g_tag = (void*)(intptr_t)10; // Some random number
static grpc_completion_queue* g_cq;
static grpc_event_engine_vtable g_vtable;
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
index 0712a40018..655e032faf 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
@@ -18,13 +18,7 @@
/* Benchmark gRPC end2end in various configurations */
-#include <benchmark/benchmark.h>
-#include <sstream>
-#include "src/core/lib/profiling/timers.h"
-#include "src/cpp/client/create_channel_internal.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
-#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h"
namespace grpc {
namespace testing {
@@ -33,365 +27,6 @@ namespace testing {
auto& force_library_initialization = Library::get();
/*******************************************************************************
- * BENCHMARKING KERNELS
- */
-
-static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
-
-// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
-// messages in each call) in a loop on a single channel
-//
-// First parmeter (i.e state.range(0)): Message size (in bytes) to use
-// Second parameter (i.e state.range(1)): Number of ping pong messages.
-// Note: One ping-pong means two messages (one from client to server and
-// the other from server to client):
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_StreamingPingPong(benchmark::State& state) {
- const int msg_size = state.range(0);
- const int max_ping_pongs = state.range(1);
-
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- EchoRequest send_request;
- EchoRequest recv_request;
-
- if (msg_size > 0) {
- send_request.set_message(std::string(msg_size, 'a'));
- send_response.set_message(std::string(msg_size, 'b'));
- }
-
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
-
- while (state.KeepRunning()) {
- ServerContext svr_ctx;
- ServerContextMutator svr_ctx_mut(&svr_ctx);
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
-
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
-
- // Establish async stream between client side and server side
- void* t;
- bool ok;
- int need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- // Send 'max_ping_pongs' number of ping pong messages
- int ping_pong_cnt = 0;
- while (ping_pong_cnt < max_ping_pongs) {
- request_rw->Write(send_request, tag(0)); // Start client send
- response_rw.Read(&recv_request, tag(1)); // Start server recv
- request_rw->Read(&recv_response, tag(2)); // Start client recv
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
-
- // If server recv is complete, start the server send operation
- if (i == 1) {
- response_rw.Write(send_response, tag(3));
- }
-
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- ping_pong_cnt++;
- }
-
- request_rw->WritesDone(tag(0));
- response_rw.Finish(Status::OK, tag(1));
-
- Status recv_status;
- request_rw->Finish(&recv_status, tag(2));
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- GPR_ASSERT(recv_status.ok());
- }
- }
-
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
-}
-
-// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
-// First parmeter (i.e state.range(0)): Message size (in bytes) to use
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_StreamingPingPongMsgs(benchmark::State& state) {
- const int msg_size = state.range(0);
-
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- EchoRequest send_request;
- EchoRequest recv_request;
-
- if (msg_size > 0) {
- send_request.set_message(std::string(msg_size, 'a'));
- send_response.set_message(std::string(msg_size, 'b'));
- }
-
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
-
- ServerContext svr_ctx;
- ServerContextMutator svr_ctx_mut(&svr_ctx);
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
-
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
-
- // Establish async stream between client side and server side
- void* t;
- bool ok;
- int need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- request_rw->Write(send_request, tag(0)); // Start client send
- response_rw.Read(&recv_request, tag(1)); // Start server recv
- request_rw->Read(&recv_response, tag(2)); // Start client recv
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
-
- // If server recv is complete, start the server send operation
- if (i == 1) {
- response_rw.Write(send_response, tag(3));
- }
-
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
-
- request_rw->WritesDone(tag(0));
- response_rw.Finish(Status::OK, tag(1));
- Status recv_status;
- request_rw->Finish(&recv_status, tag(2));
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- GPR_ASSERT(recv_status.ok());
- }
-
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(msg_size * state.iterations() * 2);
-}
-
-// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
-// messages in each call) in a loop on a single channel. Different from
-// BM_StreamingPingPong we are using stream coalescing api, e.g. WriteLast,
-// WriteAndFinish, set_initial_metadata_corked. These apis aim at saving
-// sendmsg syscalls for streaming by coalescing 1. initial metadata with first
-// message; 2. final streaming message with trailing metadata.
-//
-// First parmeter (i.e state.range(0)): Message size (in bytes) to use
-// Second parameter (i.e state.range(1)): Number of ping pong messages.
-// Note: One ping-pong means two messages (one from client to server and
-// the other from server to client):
-// Third parameter (i.e state.range(2)): Switch between using WriteAndFinish
-// API and WriteLast API for server.
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_StreamingPingPongWithCoalescingApi(benchmark::State& state) {
- const int msg_size = state.range(0);
- const int max_ping_pongs = state.range(1);
- // This options is used to test out server API: WriteLast and WriteAndFinish
- // respectively, since we can not use both of them on server side at the same
- // time. Value 1 means we are testing out the WriteAndFinish API, and
- // otherwise we are testing out the WriteLast API.
- const int write_and_finish = state.range(2);
-
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- EchoRequest send_request;
- EchoRequest recv_request;
-
- if (msg_size > 0) {
- send_request.set_message(std::string(msg_size, 'a'));
- send_response.set_message(std::string(msg_size, 'b'));
- }
-
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
-
- while (state.KeepRunning()) {
- ServerContext svr_ctx;
- ServerContextMutator svr_ctx_mut(&svr_ctx);
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
-
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- cli_ctx.set_initial_metadata_corked(true);
- // tag:1 here will never comes up, since we are not performing any op due
- // to initial metadata coalescing.
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
-
- void* t;
- bool ok;
- int need_tags;
-
- // Send 'max_ping_pongs' number of ping pong messages
- int ping_pong_cnt = 0;
- while (ping_pong_cnt < max_ping_pongs) {
- if (ping_pong_cnt == max_ping_pongs - 1) {
- request_rw->WriteLast(send_request, WriteOptions(), tag(2));
- } else {
- request_rw->Write(send_request, tag(2)); // Start client send
- }
-
- need_tags = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
-
- if (ping_pong_cnt == 0) {
- // wait for the server call structure (call_hook, etc.) to be
- // initialized (async stream between client side and server side
- // established). It is necessary when client init metadata is
- // coalesced
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- while ((int)(intptr_t)t != 0) {
- // In some cases tag:2 comes before tag:0 (write tag comes out
- // first), this while loop is to make sure get tag:0.
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- }
- }
-
- response_rw.Read(&recv_request, tag(3)); // Start server recv
- request_rw->Read(&recv_response, tag(4)); // Start client recv
-
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
-
- // If server recv is complete, start the server send operation
- if (i == 3) {
- if (ping_pong_cnt == max_ping_pongs - 1) {
- if (write_and_finish == 1) {
- response_rw.WriteAndFinish(send_response, WriteOptions(),
- Status::OK, tag(5));
- } else {
- response_rw.WriteLast(send_response, WriteOptions(), tag(5));
- // WriteLast buffers the write, so neither server write op nor
- // client read op will finish inside the while loop.
- need_tags &= ~(1 << 4);
- need_tags &= ~(1 << 5);
- }
- } else {
- response_rw.Write(send_response, tag(5));
- }
- }
-
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- ping_pong_cnt++;
- }
-
- if (max_ping_pongs == 0) {
- need_tags = (1 << 6) | (1 << 7) | (1 << 8);
- } else {
- if (write_and_finish == 1) {
- need_tags = (1 << 8);
- } else {
- // server's buffered write and the client's read of the buffered write
- // tags should come up.
- need_tags = (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8);
- }
- }
-
- // No message write or initial metadata write happened yet.
- if (max_ping_pongs == 0) {
- request_rw->WritesDone(tag(6));
- // wait for server call data structure(call_hook, etc.) to be
- // initialized, since initial metadata is corked.
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- while ((int)(intptr_t)t != 0) {
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- }
- response_rw.Finish(Status::OK, tag(7));
- } else {
- if (write_and_finish != 1) {
- response_rw.Finish(Status::OK, tag(7));
- }
- }
-
- Status recv_status;
- request_rw->Finish(&recv_status, tag(8));
-
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- GPR_ASSERT(recv_status.ok());
- }
- }
-
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
-}
-
-/*******************************************************************************
* CONFIGURATIONS
*/
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
index 6fbf9da0ad..c7ceacd320 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
@@ -18,157 +18,18 @@
/* Benchmark gRPC end2end in various configurations */
-#include <benchmark/benchmark.h>
-#include <sstream>
-#include "src/core/lib/profiling/timers.h"
-#include "src/cpp/client/create_channel_internal.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
-#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "test/cpp/microbenchmarks/fullstack_streaming_pump.h"
namespace grpc {
namespace testing {
-// force library initialization
-auto& force_library_initialization = Library::get();
-
-/*******************************************************************************
- * BENCHMARKING KERNELS
- */
-
-static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
-
-template <class Fixture>
-static void BM_PumpStreamClientToServer(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoRequest send_request;
- EchoRequest recv_request;
- if (state.range(0) > 0) {
- send_request.set_message(std::string(state.range(0), 'a'));
- }
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- response_rw.Read(&recv_request, tag(0));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- request_rw->Write(send_request, tag(1));
- while (true) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- response_rw.Read(&recv_request, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
- }
- }
- }
- request_rw->WritesDone(tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- response_rw.Finish(Status::OK, tag(0));
- Status final_status;
- request_rw->Finish(&final_status, tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- GPR_ASSERT(final_status.ok());
- }
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
-}
-
-template <class Fixture>
-static void BM_PumpStreamServerToClient(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_response.set_message(std::string(state.range(0), 'a'));
- }
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- request_rw->Read(&recv_response, tag(0));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- response_rw.Write(send_response, tag(1));
- while (true) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- request_rw->Read(&recv_response, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
- }
- }
- }
- response_rw.Finish(Status::OK, tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
-}
-
/*******************************************************************************
* CONFIGURATIONS
*/
+// force library initialization
+auto& force_library_initialization = Library::get();
+
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP)
->Range(0, 128 * 1024 * 1024);
BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index 5c44b9751f..59fb29dd60 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -26,6 +26,7 @@
#include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "test/cpp/util/test_config.h"
extern "C" {
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
@@ -104,7 +105,7 @@ class TrickledCHTTP2 : public EndpointPairFixture {
(double)state.iterations());
}
- void Log(int64_t iteration) {
+ void Log(int64_t iteration) GPR_ATTRIBUTE_NO_TSAN {
auto now = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), start_);
grpc_chttp2_transport* client =
reinterpret_cast<grpc_chttp2_transport*>(client_transport_);
@@ -192,7 +193,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
return p;
}
- void UpdateStats(grpc_chttp2_transport* t, Stats* s, size_t backlog) {
+ void UpdateStats(grpc_chttp2_transport* t, Stats* s,
+ size_t backlog) GPR_ATTRIBUTE_NO_TSAN {
if (backlog == 0) {
if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != NULL) {
s->streams_stalled_due_to_stream_flow_control++;
@@ -420,6 +422,6 @@ BENCHMARK(BM_PumpUnbalancedUnary_Trickle)->Apply(UnaryTrickleArgs);
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
- ::google::ParseCommandLineFlags(&argc, &argv, false);
+ ::grpc::testing::InitTest(&argc, &argv, false);
::benchmark::RunSpecifiedBenchmarks();
}
diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
index 9af751245f..fa41d114c0 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
@@ -18,13 +18,7 @@
/* Benchmark gRPC end2end in various configurations */
-#include <benchmark/benchmark.h>
-#include <sstream>
-#include "src/core/lib/profiling/timers.h"
-#include "src/cpp/client/create_channel_internal.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
-#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "test/cpp/microbenchmarks/fullstack_unary_ping_pong.h"
namespace grpc {
namespace testing {
@@ -33,85 +27,6 @@ namespace testing {
auto& force_library_initialization = Library::get();
/*******************************************************************************
- * BENCHMARKING KERNELS
- */
-
-static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
-
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_UnaryPingPong(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- EchoRequest send_request;
- EchoResponse send_response;
- EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_request.set_message(std::string(state.range(0), 'a'));
- }
- if (state.range(1) > 0) {
- send_response.set_message(std::string(state.range(1), 'a'));
- }
- Status recv_status;
- struct ServerEnv {
- ServerContext ctx;
- EchoRequest recv_request;
- grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
- ServerEnv() : response_writer(&ctx) {}
- };
- uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
- ServerEnv* server_env[2] = {
- reinterpret_cast<ServerEnv*>(server_env_buffer),
- reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
- new (server_env[0]) ServerEnv;
- new (server_env[1]) ServerEnv;
- service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
- &server_env[0]->response_writer, fixture->cq(),
- fixture->cq(), tag(0));
- service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
- &server_env[1]->response_writer, fixture->cq(),
- fixture->cq(), tag(1));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- recv_response.Clear();
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
- stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
- void* t;
- bool ok;
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- GPR_ASSERT(t == tag(0) || t == tag(1));
- intptr_t slot = reinterpret_cast<intptr_t>(t);
- ServerEnv* senv = server_env[slot];
- ServerContextMutator svr_ctx_mut(&senv->ctx);
- senv->response_writer.Finish(send_response, Status::OK, tag(3));
- response_reader->Finish(&recv_response, &recv_status, tag(4));
- for (int i = (1 << 3) | (1 << 4); i != 0;) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int tagnum = (int)reinterpret_cast<intptr_t>(t);
- GPR_ASSERT(i & (1 << tagnum));
- i -= 1 << tagnum;
- }
- GPR_ASSERT(recv_status.ok());
-
- senv->~ServerEnv();
- senv = new (senv) ServerEnv();
- service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
- fixture->cq(), fixture->cq(), tag(slot));
- }
- fixture->Finish(state);
- fixture.reset();
- server_env[0]->~ServerEnv();
- server_env[1]->~ServerEnv();
- state.SetBytesProcessed(state.range(0) * state.iterations() +
- state.range(1) * state.iterations());
-}
-
-/*******************************************************************************
* CONFIGURATIONS
*/
diff --git a/test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h b/test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h
new file mode 100644
index 0000000000..ff1f966753
--- /dev/null
+++ b/test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h
@@ -0,0 +1,396 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_STREAMING_PING_PONG_H
+#define TEST_CPP_MICROBENCHMARKS_FULLSTACK_STREAMING_PING_PONG_H
+
+#include <benchmark/benchmark.h>
+#include <sstream>
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+
+namespace grpc {
+namespace testing {
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
+// messages in each call) in a loop on a single channel
+//
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+// Second parameter (i.e state.range(1)): Number of ping pong messages.
+// Note: One ping-pong means two messages (one from client to server and
+// the other from server to client):
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPong(benchmark::State& state) {
+ const int msg_size = state.range(0);
+ const int max_ping_pongs = state.range(1);
+
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
+ }
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
+ while (state.KeepRunning()) {
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ // Establish async stream between client side and server side
+ void* t;
+ bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ // Send 'max_ping_pongs' number of ping pong messages
+ int ping_pong_cnt = 0;
+ while (ping_pong_cnt < max_ping_pongs) {
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ ping_pong_cnt++;
+ }
+
+ request_rw->WritesDone(tag(0));
+ response_rw.Finish(Status::OK, tag(1));
+
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
+ }
+ }
+
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
+}
+
+// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPongMsgs(benchmark::State& state) {
+ const int msg_size = state.range(0);
+
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
+ }
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ // Establish async stream between client side and server side
+ void* t;
+ bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+
+ request_rw->WritesDone(tag(0));
+ response_rw.Finish(Status::OK, tag(1));
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
+ }
+
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(msg_size * state.iterations() * 2);
+}
+
+// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
+// messages in each call) in a loop on a single channel. Different from
+// BM_StreamingPingPong we are using stream coalescing api, e.g. WriteLast,
+// WriteAndFinish, set_initial_metadata_corked. These apis aim at saving
+// sendmsg syscalls for streaming by coalescing 1. initial metadata with first
+// message; 2. final streaming message with trailing metadata.
+//
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+// Second parameter (i.e state.range(1)): Number of ping pong messages.
+// Note: One ping-pong means two messages (one from client to server and
+// the other from server to client):
+// Third parameter (i.e state.range(2)): Switch between using WriteAndFinish
+// API and WriteLast API for server.
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPongWithCoalescingApi(benchmark::State& state) {
+ const int msg_size = state.range(0);
+ const int max_ping_pongs = state.range(1);
+ // This options is used to test out server API: WriteLast and WriteAndFinish
+ // respectively, since we can not use both of them on server side at the same
+ // time. Value 1 means we are testing out the WriteAndFinish API, and
+ // otherwise we are testing out the WriteLast API.
+ const int write_and_finish = state.range(2);
+
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
+ }
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
+ while (state.KeepRunning()) {
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ cli_ctx.set_initial_metadata_corked(true);
+ // tag:1 here will never comes up, since we are not performing any op due
+ // to initial metadata coalescing.
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ void* t;
+ bool ok;
+ int need_tags;
+
+ // Send 'max_ping_pongs' number of ping pong messages
+ int ping_pong_cnt = 0;
+ while (ping_pong_cnt < max_ping_pongs) {
+ if (ping_pong_cnt == max_ping_pongs - 1) {
+ request_rw->WriteLast(send_request, WriteOptions(), tag(2));
+ } else {
+ request_rw->Write(send_request, tag(2)); // Start client send
+ }
+
+ need_tags = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
+
+ if (ping_pong_cnt == 0) {
+ // wait for the server call structure (call_hook, etc.) to be
+ // initialized (async stream between client side and server side
+ // established). It is necessary when client init metadata is
+ // coalesced
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ while ((int)(intptr_t)t != 0) {
+ // In some cases tag:2 comes before tag:0 (write tag comes out
+ // first), this while loop is to make sure get tag:0.
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ }
+ }
+
+ response_rw.Read(&recv_request, tag(3)); // Start server recv
+ request_rw->Read(&recv_response, tag(4)); // Start client recv
+
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 3) {
+ if (ping_pong_cnt == max_ping_pongs - 1) {
+ if (write_and_finish == 1) {
+ response_rw.WriteAndFinish(send_response, WriteOptions(),
+ Status::OK, tag(5));
+ } else {
+ response_rw.WriteLast(send_response, WriteOptions(), tag(5));
+ // WriteLast buffers the write, so neither server write op nor
+ // client read op will finish inside the while loop.
+ need_tags &= ~(1 << 4);
+ need_tags &= ~(1 << 5);
+ }
+ } else {
+ response_rw.Write(send_response, tag(5));
+ }
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ ping_pong_cnt++;
+ }
+
+ if (max_ping_pongs == 0) {
+ need_tags = (1 << 6) | (1 << 7) | (1 << 8);
+ } else {
+ if (write_and_finish == 1) {
+ need_tags = (1 << 8);
+ } else {
+ // server's buffered write and the client's read of the buffered write
+ // tags should come up.
+ need_tags = (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8);
+ }
+ }
+
+ // No message write or initial metadata write happened yet.
+ if (max_ping_pongs == 0) {
+ request_rw->WritesDone(tag(6));
+ // wait for server call data structure(call_hook, etc.) to be
+ // initialized, since initial metadata is corked.
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ while ((int)(intptr_t)t != 0) {
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ }
+ response_rw.Finish(Status::OK, tag(7));
+ } else {
+ if (write_and_finish != 1) {
+ response_rw.Finish(Status::OK, tag(7));
+ }
+ }
+
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(8));
+
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
+ }
+ }
+
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
+}
+} // namespace testing
+} // namespace grpc
+
+#endif // TEST_CPP_MICROBENCHMARKS_FULLSTACK_STREAMING_PING_PONG_H
diff --git a/test/cpp/microbenchmarks/fullstack_streaming_pump.h b/test/cpp/microbenchmarks/fullstack_streaming_pump.h
new file mode 100644
index 0000000000..f9db212b02
--- /dev/null
+++ b/test/cpp/microbenchmarks/fullstack_streaming_pump.h
@@ -0,0 +1,170 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_STREAMING_PUMP_H
+#define TEST_CPP_MICROBENCHMARKS_FULLSTACK_STREAMING_PUMP_H
+
+#include <benchmark/benchmark.h>
+#include <sstream>
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+
+namespace grpc {
+namespace testing {
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+template <class Fixture>
+static void BM_PumpStreamClientToServer(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoRequest send_request;
+ EchoRequest recv_request;
+ if (state.range(0) > 0) {
+ send_request.set_message(std::string(state.range(0), 'a'));
+ }
+ Status recv_status;
+ ServerContext svr_ctx;
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ ClientContext cli_ctx;
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+ int need_tags = (1 << 0) | (1 << 1);
+ void* t;
+ bool ok;
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ response_rw.Read(&recv_request, tag(0));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ request_rw->Write(send_request, tag(1));
+ while (true) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ if (t == tag(0)) {
+ response_rw.Read(&recv_request, tag(0));
+ } else if (t == tag(1)) {
+ break;
+ } else {
+ GPR_ASSERT(false);
+ }
+ }
+ }
+ request_rw->WritesDone(tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ response_rw.Finish(Status::OK, tag(0));
+ Status final_status;
+ request_rw->Finish(&final_status, tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ GPR_ASSERT(final_status.ok());
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+template <class Fixture>
+static void BM_PumpStreamServerToClient(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ if (state.range(0) > 0) {
+ send_response.set_message(std::string(state.range(0), 'a'));
+ }
+ Status recv_status;
+ ServerContext svr_ctx;
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ ClientContext cli_ctx;
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+ int need_tags = (1 << 0) | (1 << 1);
+ void* t;
+ bool ok;
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ request_rw->Read(&recv_response, tag(0));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ response_rw.Write(send_response, tag(1));
+ while (true) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ if (t == tag(0)) {
+ request_rw->Read(&recv_response, tag(0));
+ } else if (t == tag(1)) {
+ break;
+ } else {
+ GPR_ASSERT(false);
+ }
+ }
+ }
+ response_rw.Finish(Status::OK, tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+} // namespace testing
+} // namespace grpc
+
+#endif // TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
diff --git a/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h b/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
new file mode 100644
index 0000000000..76d278b2a0
--- /dev/null
+++ b/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_UNARY_PING_PONG_H
+#define TEST_CPP_MICROBENCHMARKS_FULLSTACK_UNARY_PING_PONG_H
+
+#include <benchmark/benchmark.h>
+#include <sstream>
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+
+namespace grpc {
+namespace testing {
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_UnaryPingPong(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ EchoRequest send_request;
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ if (state.range(0) > 0) {
+ send_request.set_message(std::string(state.range(0), 'a'));
+ }
+ if (state.range(1) > 0) {
+ send_response.set_message(std::string(state.range(1), 'a'));
+ }
+ Status recv_status;
+ struct ServerEnv {
+ ServerContext ctx;
+ EchoRequest recv_request;
+ grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
+ ServerEnv() : response_writer(&ctx) {}
+ };
+ uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
+ ServerEnv* server_env[2] = {
+ reinterpret_cast<ServerEnv*>(server_env_buffer),
+ reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
+ new (server_env[0]) ServerEnv;
+ new (server_env[1]) ServerEnv;
+ service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
+ &server_env[0]->response_writer, fixture->cq(),
+ fixture->cq(), tag(0));
+ service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
+ &server_env[1]->response_writer, fixture->cq(),
+ fixture->cq(), tag(1));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ recv_response.Clear();
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
+ stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
+ void* t;
+ bool ok;
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ GPR_ASSERT(t == tag(0) || t == tag(1));
+ intptr_t slot = reinterpret_cast<intptr_t>(t);
+ ServerEnv* senv = server_env[slot];
+ ServerContextMutator svr_ctx_mut(&senv->ctx);
+ senv->response_writer.Finish(send_response, Status::OK, tag(3));
+ response_reader->Finish(&recv_response, &recv_status, tag(4));
+ for (int i = (1 << 3) | (1 << 4); i != 0;) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int tagnum = (int)reinterpret_cast<intptr_t>(t);
+ GPR_ASSERT(i & (1 << tagnum));
+ i -= 1 << tagnum;
+ }
+ GPR_ASSERT(recv_status.ok());
+
+ senv->~ServerEnv();
+ senv = new (senv) ServerEnv();
+ service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
+ fixture->cq(), fixture->cq(), tag(slot));
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ server_env[0]->~ServerEnv();
+ server_env[1]->~ServerEnv();
+ state.SetBytesProcessed(state.range(0) * state.iterations() +
+ state.range(1) * state.iterations());
+}
+} // namespace testing
+} // namespace grpc
+
+#endif // TEST_CPP_MICROBENCHMARKS_FULLSTACK_UNARY_PING_PONG_H
diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc
index 0c10d6c4ce..b0caa48cd0 100644
--- a/test/cpp/microbenchmarks/helpers.cc
+++ b/test/cpp/microbenchmarks/helpers.cc
@@ -29,6 +29,20 @@ void TrackCounters::Finish(benchmark::State &state) {
}
void TrackCounters::AddToLabel(std::ostream &out, benchmark::State &state) {
+ grpc_stats_data stats_end;
+ grpc_stats_collect(&stats_end);
+ grpc_stats_data stats;
+ grpc_stats_diff(&stats_end, &stats_begin_, &stats);
+ for (int i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+ out << " " << grpc_stats_counter_name[i]
+ << "/iter:" << ((double)stats.counters[i] / (double)state.iterations());
+ }
+ for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
+ out << " " << grpc_stats_histogram_name[i] << "-median:"
+ << grpc_stats_histo_percentile(&stats, (grpc_stats_histograms)i, 50.0)
+ << " " << grpc_stats_histogram_name[i] << "-99p:"
+ << grpc_stats_histo_percentile(&stats, (grpc_stats_histograms)i, 99.0);
+ }
#ifdef GPR_LOW_LEVEL_COUNTERS
grpc_memory_counters counters_at_end = grpc_memory_counters_snapshot();
out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
diff --git a/test/cpp/microbenchmarks/helpers.h b/test/cpp/microbenchmarks/helpers.h
index c81d95a4ea..07dd611709 100644
--- a/test/cpp/microbenchmarks/helpers.h
+++ b/test/cpp/microbenchmarks/helpers.h
@@ -23,6 +23,7 @@
extern "C" {
#include <grpc/support/port_platform.h>
+#include "src/core/lib/debug/stats.h"
#include "test/core/util/memory_counters.h"
}
@@ -62,10 +63,12 @@ extern "C" gpr_atm gpr_now_call_count;
class TrackCounters {
public:
+ TrackCounters() { grpc_stats_collect(&stats_begin_); }
virtual void Finish(benchmark::State& state);
virtual void AddToLabel(std::ostream& out, benchmark::State& state);
private:
+ grpc_stats_data stats_begin_;
#ifdef GPR_LOW_LEVEL_COUNTERS
const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
const size_t atm_cas_at_start_ =
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index b3348b76fa..3352269517 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -14,14 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
-package(
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/qps")
grpc_cc_library(
name = "parse_json",
@@ -51,6 +46,7 @@ grpc_cc_library(
":usage_timer",
"//:grpc",
"//:grpc++",
+ "//:grpc++_core_stats",
"//src/proto/grpc/testing:control_proto",
"//src/proto/grpc/testing:payloads_proto",
"//src/proto/grpc/testing:services_proto",
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 6c4d92e859..7fbaf63492 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -31,10 +31,10 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
-#include "src/core/lib/surface/completion_queue.h"
#include "src/proto/grpc/testing/payloads.pb.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/cpp/util/core_stats.h"
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/interarrival.h"
#include "test/cpp/qps/usage_timer.h"
@@ -173,6 +173,9 @@ class Client {
timer_result = timer_->Mark();
}
+ grpc_stats_data core_stats;
+ grpc_stats_collect(&core_stats);
+
ClientStats stats;
latencies.FillProto(stats.mutable_latencies());
for (StatusHistogram::const_iterator it = statuses.begin();
@@ -185,6 +188,7 @@ class Client {
stats.set_time_system(timer_result.system);
stats.set_time_user(timer_result.user);
stats.set_cq_poll_count(poll_count);
+ CoreStatsToProto(core_stats, stats.mutable_core_stats());
return stats;
}
@@ -370,12 +374,11 @@ class ClientImpl : public Client {
ClientImpl(const ClientConfig& config,
std::function<std::unique_ptr<StubType>(std::shared_ptr<Channel>)>
create_stub)
- : cores_(gpr_cpu_num_cores()),
- channels_(config.client_channels()),
- create_stub_(create_stub) {
+ : cores_(gpr_cpu_num_cores()), create_stub_(create_stub) {
for (int i = 0; i < config.client_channels(); i++) {
- channels_[i].init(config.server_targets(i % config.server_targets_size()),
- config, create_stub_, i);
+ channels_.emplace_back(
+ config.server_targets(i % config.server_targets_size()), config,
+ create_stub_, i);
}
ClientRequestCreator<RequestType> create_req(&request_,
@@ -389,20 +392,11 @@ class ClientImpl : public Client {
class ClientChannelInfo {
public:
- ClientChannelInfo() {}
- ClientChannelInfo(const ClientChannelInfo& i) {
- // The copy constructor is to satisfy old compilers
- // that need it for using std::vector . It is only ever
- // used for empty entries
- GPR_ASSERT(!i.channel_ && !i.stub_);
- }
- void init(const grpc::string& target, const ClientConfig& config,
- std::function<std::unique_ptr<StubType>(std::shared_ptr<Channel>)>
- create_stub,
- int shard) {
- // We have to use a 2-phase init like this with a default
- // constructor followed by an initializer function to make
- // old compilers happy with using this in std::vector
+ ClientChannelInfo(
+ const grpc::string& target, const ClientConfig& config,
+ std::function<std::unique_ptr<StubType>(std::shared_ptr<Channel>)>
+ create_stub,
+ int shard) {
ChannelArguments args;
args.SetInt("shard_to_ensure_no_subchannel_merges", shard);
set_channel_args(config, &args);
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 265f174cc5..912c871482 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -34,6 +34,7 @@
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
+#include "src/core/lib/surface/completion_queue.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/cpp/qps/client.h"
#include "test/cpp/qps/usage_timer.h"
@@ -140,7 +141,8 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext {
if (!next_issue_) { // ready to issue
RunNextState(true, nullptr);
} else { // wait for the issue time
- alarm_.reset(new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this)));
+ alarm_.reset(new Alarm);
+ alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this));
}
}
};
@@ -359,8 +361,8 @@ class ClientRpcContextStreamingPingPongImpl : public ClientRpcContext {
break; // loop around, don't return
case State::WAIT:
next_state_ = State::READY_TO_WRITE;
- alarm_.reset(
- new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this)));
+ alarm_.reset(new Alarm);
+ alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this));
return true;
case State::READY_TO_WRITE:
if (!ok) {
@@ -517,8 +519,8 @@ class ClientRpcContextStreamingFromClientImpl : public ClientRpcContext {
}
break; // loop around, don't return
case State::WAIT:
- alarm_.reset(
- new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this)));
+ alarm_.reset(new Alarm);
+ alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this));
next_state_ = State::READY_TO_WRITE;
return true;
case State::READY_TO_WRITE:
@@ -759,8 +761,8 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext {
break; // loop around, don't return
case State::WAIT:
next_state_ = State::READY_TO_WRITE;
- alarm_.reset(
- new Alarm(cq_, next_issue_(), ClientRpcContext::tag(this)));
+ alarm_.reset(new Alarm);
+ alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this));
return true;
case State::READY_TO_WRITE:
if (!ok) {
diff --git a/test/cpp/qps/interarrival.h b/test/cpp/qps/interarrival.h
index c6e417985a..1fa310c209 100644
--- a/test/cpp/qps/interarrival.h
+++ b/test/cpp/qps/interarrival.h
@@ -21,7 +21,7 @@
#include <chrono>
#include <cmath>
-#include <cstdlib>
+#include <random>
#include <vector>
#include <grpc++/support/config.h>
@@ -75,13 +75,13 @@ class InterarrivalTimer {
public:
InterarrivalTimer() {}
void init(const RandomDistInterface& r, int threads, int entries = 1000000) {
+ std::random_device devrand;
+ std::mt19937_64 generator(devrand());
+ std::uniform_real_distribution<double> rando(0, 1);
for (int i = 0; i < entries; i++) {
- // rand is the only choice that is portable across POSIX and Windows
- // and that supports new and old compilers
- const double uniform_0_1 =
- static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
random_table_.push_back(
- static_cast<int64_t>(1e9 * r.transform(uniform_0_1)));
+ static_cast<int64_t>(1e9 * r.transform(rando(generator))));
+ ;
}
// Now set up the thread positions
for (int i = 0; i < threads; i++) {
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index a45b10bcb8..3c99bda144 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -26,6 +26,7 @@
#include "test/cpp/qps/stats.h"
#include <grpc++/client_context.h>
+#include "src/cpp/util/core_stats.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
namespace grpc {
@@ -85,6 +86,33 @@ void GprLogReporter::ReportQPS(const ScenarioResult& result) {
gpr_log(GPR_INFO, "successful requests/second: %.1f",
result.summary().successful_requests_per_second());
}
+ for (int i = 0; i < result.client_stats_size(); i++) {
+ if (result.client_stats(i).has_core_stats()) {
+ ReportCoreStats("CLIENT", i, result.client_stats(i).core_stats());
+ }
+ }
+ for (int i = 0; i < result.server_stats_size(); i++) {
+ if (result.server_stats(i).has_core_stats()) {
+ ReportCoreStats("SERVER", i, result.server_stats(i).core_stats());
+ }
+ }
+}
+
+void GprLogReporter::ReportCoreStats(const char* name, int idx,
+ const grpc::core::Stats& stats) {
+ grpc_stats_data data;
+ ProtoToCoreStats(stats, &data);
+ for (int i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+ gpr_log(GPR_DEBUG, "%s[%d].%s = %" PRIdPTR, name, idx,
+ grpc_stats_counter_name[i], data.counters[i]);
+ }
+ for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
+ gpr_log(GPR_DEBUG, "%s[%d].%s = %lf/%lf/%lf (50/95/99%%-ile)", name, idx,
+ grpc_stats_histogram_name[i],
+ grpc_stats_histo_percentile(&data, (grpc_stats_histograms)i, 50),
+ grpc_stats_histo_percentile(&data, (grpc_stats_histograms)i, 95),
+ grpc_stats_histo_percentile(&data, (grpc_stats_histograms)i, 99));
+ }
}
void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) {
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 321be2a97f..1d7b2b54e7 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -104,6 +104,9 @@ class GprLogReporter : public Reporter {
void ReportCpuUsage(const ScenarioResult& result) override;
void ReportPollCount(const ScenarioResult& result) override;
void ReportQueriesPerCpuSec(const ScenarioResult& result) override;
+
+ void ReportCoreStats(const char* name, int idx,
+ const grpc::core::Stats& stats);
};
/** Dumps the report to a JSON file. */
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index df27a4368e..16d101d5e6 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -26,7 +26,7 @@
#include <grpc/support/log.h>
#include <vector>
-#include "src/core/lib/surface/completion_queue.h"
+#include "src/cpp/util/core_stats.h"
#include "src/proto/grpc/testing/control.pb.h"
#include "src/proto/grpc/testing/messages.pb.h"
#include "test/core/end2end/data/ssl_test_data.h"
@@ -64,6 +64,9 @@ class Server {
timer_result = timer_->Mark();
}
+ grpc_stats_data core_stats;
+ grpc_stats_collect(&core_stats);
+
ServerStats stats;
stats.set_time_elapsed(timer_result.wall);
stats.set_time_system(timer_result.system);
@@ -71,6 +74,7 @@ class Server {
stats.set_total_cpu_time(timer_result.total_cpu_time);
stats.set_idle_cpu_time(timer_result.idle_cpu_time);
stats.set_cq_poll_count(poll_count);
+ CoreStatsToProto(core_stats, stats.mutable_core_stats());
return stats;
}
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 8b00bcfeaf..4a82f98199 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -35,6 +35,7 @@
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
+#include "src/core/lib/surface/completion_queue.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/core/util/test_config.h"
#include "test/cpp/qps/server.h"
diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD
index 3f63be2aa3..7538845803 100644
--- a/test/cpp/server/BUILD
+++ b/test/cpp/server/BUILD
@@ -14,7 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+
+grpc_package(name = "test/cpp/server")
grpc_cc_test(
name = "server_builder_test",
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index fbdec05698..2559c18c32 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -14,15 +14,9 @@
licenses(["notice"]) # Apache v2
-load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_binary", "grpc_cc_test")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_binary", "grpc_cc_test", "grpc_package")
-package(
- default_visibility = ["//visibility:public"],
- features = [
- "-layering_check",
- "-parse_headers",
- ],
-)
+grpc_package(name = "test/cpp/util", visibility = "public")
grpc_cc_library(
name = "test_config",