aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core
diff options
context:
space:
mode:
authorGravatar Sree Kuchibhotla <sreek@google.com>2018-05-08 10:24:30 -0700
committerGravatar Sree Kuchibhotla <sreek@google.com>2018-05-08 10:24:30 -0700
commit6d5c2c250d4f96af7cc413ce245dc131a9cf4cf9 (patch)
tree29c94b81a45c1182d41f6dce8dc8e2391614b933 /test/core
parentdc01cb64c25abc14f6d0ab24db1afd019a37d7ee (diff)
parent978b9b179e631348cf8b62bf64af7fc65e322fc4 (diff)
Merge branch 'master' into fix-time
Diffstat (limited to 'test/core')
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc115
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_test.cc7
-rw-r--r--test/core/end2end/end2end_nosec_tests.cc8
-rw-r--r--test/core/end2end/end2end_tests.cc8
-rwxr-xr-xtest/core/end2end/gen_build_yaml.py3
-rwxr-xr-xtest/core/end2end/generate_tests.bzl2
-rw-r--r--test/core/end2end/tests/bad_ping.cc5
-rw-r--r--test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc266
-rw-r--r--test/core/gprpp/ref_counted_ptr_test.cc2
-rw-r--r--test/core/handshake/readahead_handshaker_server_ssl.cc2
-rw-r--r--test/core/security/credentials_test.cc10
-rw-r--r--test/core/security/security_connector_test.cc51
-rw-r--r--test/core/tsi/alts/fake_handshaker/BUILD57
-rw-r--r--test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc268
-rw-r--r--test/core/tsi/alts/fake_handshaker/handshaker.proto224
-rw-r--r--test/core/tsi/alts/fake_handshaker/transport_security_common.proto40
-rw-r--r--test/core/tsi/ssl_session_cache_test.cc1
-rw-r--r--test/core/tsi/ssl_transport_security_test.cc22
18 files changed, 1011 insertions, 80 deletions
diff --git a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
index 4fd7aedc6c..521fc3107e 100644
--- a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
+++ b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
@@ -145,7 +145,6 @@ struct OnResolutionCallbackArg {
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver;
grpc_channel_args* result = nullptr;
grpc_millis delay_before_second_resolution = 0;
- bool using_cares = false;
};
// Counter for the number of times a resolution notification callback has been
@@ -155,81 +154,100 @@ static int g_on_resolution_invocations_count;
// Set to true by the last callback in the resolution chain.
bool g_all_callbacks_invoked;
-void on_third_resolution(void* arg, grpc_error* error) {
+void on_fourth_resolution(void* arg, grpc_error* error) {
OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
+ grpc_channel_args_destroy(cb_arg->result);
GPR_ASSERT(error == GRPC_ERROR_NONE);
++g_on_resolution_invocations_count;
- grpc_channel_args_destroy(cb_arg->result);
gpr_log(GPR_INFO,
- "3rd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
+ "4th: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
g_on_resolution_invocations_count, g_resolution_count);
// In this case we expect to have incurred in another system-level resolution
- // because on_second_resolution slept for longer than the min resolution
+ // because on_third_resolution slept for longer than the min resolution
// period.
- GPR_ASSERT(g_on_resolution_invocations_count == 3);
- GPR_ASSERT(g_resolution_count == 2);
+ GPR_ASSERT(g_on_resolution_invocations_count == 4);
+ GPR_ASSERT(g_resolution_count == 3);
cb_arg->resolver.reset();
- if (cb_arg->using_cares) {
- gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
- gpr_mu_lock(g_iomgr_args.mu);
- GRPC_LOG_IF_ERROR("pollset_kick",
- grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
- gpr_mu_unlock(g_iomgr_args.mu);
- }
+ gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
+ gpr_mu_lock(g_iomgr_args.mu);
+ GRPC_LOG_IF_ERROR("pollset_kick",
+ grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+ gpr_mu_unlock(g_iomgr_args.mu);
grpc_core::Delete(cb_arg);
g_all_callbacks_invoked = true;
}
-void on_second_resolution(void* arg, grpc_error* error) {
+void on_third_resolution(void* arg, grpc_error* error) {
OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
- ++g_on_resolution_invocations_count;
grpc_channel_args_destroy(cb_arg->result);
+ GPR_ASSERT(error == GRPC_ERROR_NONE);
+ ++g_on_resolution_invocations_count;
+ gpr_log(GPR_INFO,
+ "3rd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
+ g_on_resolution_invocations_count, g_resolution_count);
+ // The timer set because of the previous re-resolution request fires, so a new
+ // system-level resolution happened.
+ GPR_ASSERT(g_on_resolution_invocations_count == 3);
+ GPR_ASSERT(g_resolution_count == 2);
+ grpc_core::ExecCtx::Get()->TestOnlySetNow(
+ cb_arg->delay_before_second_resolution * 2);
+ cb_arg->resolver->NextLocked(
+ &cb_arg->result,
+ GRPC_CLOSURE_CREATE(on_fourth_resolution, arg,
+ grpc_combiner_scheduler(g_combiner)));
+ cb_arg->resolver->RequestReresolutionLocked();
+ gpr_mu_lock(g_iomgr_args.mu);
+ GRPC_LOG_IF_ERROR("pollset_kick",
+ grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+ gpr_mu_unlock(g_iomgr_args.mu);
+}
+void on_second_resolution(void* arg, grpc_error* error) {
+ OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
+ grpc_channel_args_destroy(cb_arg->result);
+ GPR_ASSERT(error == GRPC_ERROR_NONE);
+ ++g_on_resolution_invocations_count;
gpr_log(GPR_INFO,
"2nd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
g_on_resolution_invocations_count, g_resolution_count);
// The resolution request for which this function is the callback happened
// before the min resolution period. Therefore, no new system-level
- // resolutions happened, as indicated by g_resolution_count.
+ // resolutions happened, as indicated by g_resolution_count. But a resolution
+ // timer was set to fire when the cooldown finishes.
GPR_ASSERT(g_on_resolution_invocations_count == 2);
GPR_ASSERT(g_resolution_count == 1);
- grpc_core::ExecCtx::Get()->TestOnlySetNow(
- cb_arg->delay_before_second_resolution * 2);
+ // Register a new callback to capture the timer firing.
cb_arg->resolver->NextLocked(
&cb_arg->result,
GRPC_CLOSURE_CREATE(on_third_resolution, arg,
grpc_combiner_scheduler(g_combiner)));
- cb_arg->resolver->RequestReresolutionLocked();
- if (cb_arg->using_cares) {
- gpr_mu_lock(g_iomgr_args.mu);
- GRPC_LOG_IF_ERROR("pollset_kick",
- grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
- gpr_mu_unlock(g_iomgr_args.mu);
- }
+ gpr_mu_lock(g_iomgr_args.mu);
+ GRPC_LOG_IF_ERROR("pollset_kick",
+ grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+ gpr_mu_unlock(g_iomgr_args.mu);
}
void on_first_resolution(void* arg, grpc_error* error) {
OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
- ++g_on_resolution_invocations_count;
grpc_channel_args_destroy(cb_arg->result);
- cb_arg->resolver->NextLocked(
- &cb_arg->result,
- GRPC_CLOSURE_CREATE(on_second_resolution, arg,
- grpc_combiner_scheduler(g_combiner)));
- cb_arg->resolver->RequestReresolutionLocked();
+ GPR_ASSERT(error == GRPC_ERROR_NONE);
+ ++g_on_resolution_invocations_count;
gpr_log(GPR_INFO,
"1st: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
g_on_resolution_invocations_count, g_resolution_count);
- // Theres one initial system-level resolution and one invocation of a
+ // There's one initial system-level resolution and one invocation of a
// notification callback (the current function).
GPR_ASSERT(g_on_resolution_invocations_count == 1);
GPR_ASSERT(g_resolution_count == 1);
- if (cb_arg->using_cares) {
- gpr_mu_lock(g_iomgr_args.mu);
- GRPC_LOG_IF_ERROR("pollset_kick",
- grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
- gpr_mu_unlock(g_iomgr_args.mu);
- }
+ cb_arg->resolver->NextLocked(
+ &cb_arg->result,
+ GRPC_CLOSURE_CREATE(on_second_resolution, arg,
+ grpc_combiner_scheduler(g_combiner)));
+ cb_arg->resolver->RequestReresolutionLocked();
+ gpr_mu_lock(g_iomgr_args.mu);
+ GRPC_LOG_IF_ERROR("pollset_kick",
+ grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+ gpr_mu_unlock(g_iomgr_args.mu);
}
static void start_test_under_combiner(void* arg, grpc_error* error) {
@@ -269,22 +287,19 @@ static void start_test_under_combiner(void* arg, grpc_error* error) {
grpc_uri_destroy(uri);
}
-static void test_cooldown(bool using_cares) {
+static void test_cooldown() {
grpc_core::ExecCtx exec_ctx;
- if (using_cares) iomgr_args_init(&g_iomgr_args);
+ iomgr_args_init(&g_iomgr_args);
OnResolutionCallbackArg* res_cb_arg =
grpc_core::New<OnResolutionCallbackArg>();
res_cb_arg->uri_str = "dns:127.0.0.1";
- res_cb_arg->using_cares = using_cares;
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(start_test_under_combiner, res_cb_arg,
grpc_combiner_scheduler(g_combiner)),
GRPC_ERROR_NONE);
- if (using_cares) {
- grpc_core::ExecCtx::Get()->Flush();
- poll_pollset_until_request_done(&g_iomgr_args);
- iomgr_args_finish(&g_iomgr_args);
- }
+ grpc_core::ExecCtx::Get()->Flush();
+ poll_pollset_until_request_done(&g_iomgr_args);
+ iomgr_args_finish(&g_iomgr_args);
}
int main(int argc, char** argv) {
@@ -293,16 +308,12 @@ int main(int argc, char** argv) {
g_combiner = grpc_combiner_create();
- bool using_cares = false;
-#if GRPC_ARES == 1
- using_cares = true;
-#endif
g_default_dns_lookup_ares = grpc_dns_lookup_ares;
grpc_dns_lookup_ares = test_dns_lookup_ares;
default_resolve_address = grpc_resolve_address_impl;
grpc_set_resolver_impl(&test_resolver);
- test_cooldown(using_cares);
+ test_cooldown();
{
grpc_core::ExecCtx exec_ctx;
diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc
index e3fba2838c..103b2916c4 100644
--- a/test/core/client_channel/resolvers/dns_resolver_test.cc
+++ b/test/core/client_channel/resolvers/dns_resolver_test.cc
@@ -70,11 +70,12 @@ int main(int argc, char** argv) {
test_succeeds(dns, "dns:10.2.1.1");
test_succeeds(dns, "dns:10.2.1.1:1234");
- test_succeeds(dns, "ipv4:www.google.com");
+ test_succeeds(dns, "dns:www.google.com");
+ test_succeeds(dns, "dns:///www.google.com");
if (grpc_resolve_address == grpc_resolve_address_ares) {
- test_succeeds(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
+ test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888");
} else {
- test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
+ test_fails(dns, "dns://8.8.8.8/8.8.8.8:8888");
}
{
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc
index 297408cd92..59eb643a93 100644
--- a/test/core/end2end/end2end_nosec_tests.cc
+++ b/test/core/end2end/end2end_nosec_tests.cc
@@ -132,6 +132,8 @@ extern void retry_exceeds_buffer_size_in_subsequent_batch(grpc_end2end_test_conf
extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void);
extern void retry_non_retriable_status(grpc_end2end_test_config config);
extern void retry_non_retriable_status_pre_init(void);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(void);
extern void retry_recv_initial_metadata(grpc_end2end_test_config config);
extern void retry_recv_initial_metadata_pre_init(void);
extern void retry_recv_message(grpc_end2end_test_config config);
@@ -236,6 +238,7 @@ void grpc_end2end_tests_pre_init(void) {
retry_exceeds_buffer_size_in_initial_batch_pre_init();
retry_exceeds_buffer_size_in_subsequent_batch_pre_init();
retry_non_retriable_status_pre_init();
+ retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init();
retry_recv_initial_metadata_pre_init();
retry_recv_message_pre_init();
retry_server_pushback_delay_pre_init();
@@ -320,6 +323,7 @@ void grpc_end2end_tests(int argc, char **argv,
retry_exceeds_buffer_size_in_initial_batch(config);
retry_exceeds_buffer_size_in_subsequent_batch(config);
retry_non_retriable_status(config);
+ retry_non_retriable_status_before_recv_trailing_metadata_started(config);
retry_recv_initial_metadata(config);
retry_recv_message(config);
retry_server_pushback_delay(config);
@@ -552,6 +556,10 @@ void grpc_end2end_tests(int argc, char **argv,
retry_non_retriable_status(config);
continue;
}
+ if (0 == strcmp("retry_non_retriable_status_before_recv_trailing_metadata_started", argv[i])) {
+ retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+ continue;
+ }
if (0 == strcmp("retry_recv_initial_metadata", argv[i])) {
retry_recv_initial_metadata(config);
continue;
diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc
index 9b3f655254..9f164b4ead 100644
--- a/test/core/end2end/end2end_tests.cc
+++ b/test/core/end2end/end2end_tests.cc
@@ -134,6 +134,8 @@ extern void retry_exceeds_buffer_size_in_subsequent_batch(grpc_end2end_test_conf
extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void);
extern void retry_non_retriable_status(grpc_end2end_test_config config);
extern void retry_non_retriable_status_pre_init(void);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(void);
extern void retry_recv_initial_metadata(grpc_end2end_test_config config);
extern void retry_recv_initial_metadata_pre_init(void);
extern void retry_recv_message(grpc_end2end_test_config config);
@@ -239,6 +241,7 @@ void grpc_end2end_tests_pre_init(void) {
retry_exceeds_buffer_size_in_initial_batch_pre_init();
retry_exceeds_buffer_size_in_subsequent_batch_pre_init();
retry_non_retriable_status_pre_init();
+ retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init();
retry_recv_initial_metadata_pre_init();
retry_recv_message_pre_init();
retry_server_pushback_delay_pre_init();
@@ -324,6 +327,7 @@ void grpc_end2end_tests(int argc, char **argv,
retry_exceeds_buffer_size_in_initial_batch(config);
retry_exceeds_buffer_size_in_subsequent_batch(config);
retry_non_retriable_status(config);
+ retry_non_retriable_status_before_recv_trailing_metadata_started(config);
retry_recv_initial_metadata(config);
retry_recv_message(config);
retry_server_pushback_delay(config);
@@ -560,6 +564,10 @@ void grpc_end2end_tests(int argc, char **argv,
retry_non_retriable_status(config);
continue;
}
+ if (0 == strcmp("retry_non_retriable_status_before_recv_trailing_metadata_started", argv[i])) {
+ retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+ continue;
+ }
if (0 == strcmp("retry_recv_initial_metadata", argv[i])) {
retry_recv_initial_metadata(config);
continue;
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index c7b0362574..c355fc24b5 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -170,6 +170,9 @@ END2END_TESTS = {
proxyable=False),
'retry_non_retriable_status': default_test_options._replace(
cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
+ 'retry_non_retriable_status_before_recv_trailing_metadata_started':
+ default_test_options._replace(
+ cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
'retry_recv_initial_metadata': default_test_options._replace(
cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
'retry_recv_message': default_test_options._replace(
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 37fd1837f4..11fc576165 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -158,6 +158,8 @@ END2END_TESTS = {
needs_client_channel=True, proxyable=False),
'retry_non_retriable_status': test_options(needs_client_channel=True,
proxyable=False),
+ 'retry_non_retriable_status_before_recv_trailing_metadata_started':
+ test_options(needs_client_channel=True, proxyable=False),
'retry_recv_initial_metadata': test_options(needs_client_channel=True,
proxyable=False),
'retry_recv_message': test_options(needs_client_channel=True,
diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc
index 22481d1be7..98d893f64d 100644
--- a/test/core/end2end/tests/bad_ping.cc
+++ b/test/core/end2end/tests/bad_ping.cc
@@ -355,6 +355,11 @@ static void test_pings_without_data(grpc_end2end_test_config config) {
grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1);
+
+ // Also expect the previously blocked pings to complete with an error
+ CQ_EXPECT_COMPLETION(cqv, tag(200 + MAX_PING_STRIKES + 1), 0);
+ CQ_EXPECT_COMPLETION(cqv, tag(200 + MAX_PING_STRIKES + 2), 0);
+
cq_verify(cqv);
grpc_call_unref(s);
diff --git a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
new file mode 100644
index 0000000000..eb016a3de9
--- /dev/null
+++ b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
@@ -0,0 +1,266 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/end2end/tests/cancel_test_helpers.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+ const char* test_name,
+ 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(), nullptr);
+ } 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),
+ nullptr)
+ .type == GRPC_OP_COMPLETE);
+ grpc_server_destroy(f->server);
+ f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+ if (!f->client) return;
+ grpc_channel_destroy(f->client);
+ f->client = nullptr;
+}
+
+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);
+}
+
+// Tests that we don't retry for non-retryable status codes, even if
+// status is received before the recv_trailing_metadata op is started.
+// - 1 retry allowed for ABORTED status
+// - first attempt gets INVALID_ARGUMENT, so no retry is done
+static void
+test_retry_non_retriable_status_before_recv_trailing_metadata_started(
+ grpc_end2end_test_config config) {
+ grpc_call* c;
+ grpc_call* s;
+ grpc_op ops[6];
+ grpc_op* op;
+ grpc_metadata_array initial_metadata_recv;
+ grpc_metadata_array trailing_metadata_recv;
+ grpc_metadata_array request_metadata_recv;
+ grpc_call_details call_details;
+ grpc_slice request_payload_slice = grpc_slice_from_static_string("foo");
+ grpc_slice response_payload_slice = grpc_slice_from_static_string("bar");
+ grpc_byte_buffer* request_payload =
+ grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+ grpc_byte_buffer* response_payload =
+ grpc_raw_byte_buffer_create(&response_payload_slice, 1);
+ grpc_byte_buffer* request_payload_recv = nullptr;
+ grpc_byte_buffer* response_payload_recv = nullptr;
+ grpc_status_code status;
+ grpc_call_error error;
+ grpc_slice details;
+ int was_cancelled = 2;
+ char* peer;
+
+ grpc_arg arg;
+ arg.type = GRPC_ARG_STRING;
+ arg.key = const_cast<char*>(GRPC_ARG_SERVICE_CONFIG);
+ arg.value.string = const_cast<char*>(
+ "{\n"
+ " \"methodConfig\": [ {\n"
+ " \"name\": [\n"
+ " { \"service\": \"service\", \"method\": \"method\" }\n"
+ " ],\n"
+ " \"retryPolicy\": {\n"
+ " \"maxAttempts\": 2,\n"
+ " \"initialBackoff\": \"1s\",\n"
+ " \"maxBackoff\": \"120s\",\n"
+ " \"backoffMultiplier\": 1.6,\n"
+ " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
+ " }\n"
+ " } ]\n"
+ "}");
+ grpc_channel_args client_args = {1, &arg};
+ grpc_end2end_test_fixture f =
+ begin_test(config, "retry_non_retriable_status", &client_args, nullptr);
+
+ cq_verifier* cqv = cq_verifier_create(f.cq);
+
+ gpr_timespec deadline = five_seconds_from_now();
+ c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/service/method"),
+ nullptr, deadline, nullptr);
+ GPR_ASSERT(c);
+
+ peer = grpc_call_get_peer(c);
+ GPR_ASSERT(peer != nullptr);
+ gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
+ gpr_free(peer);
+
+ grpc_metadata_array_init(&initial_metadata_recv);
+ grpc_metadata_array_init(&trailing_metadata_recv);
+ grpc_metadata_array_init(&request_metadata_recv);
+ grpc_call_details_init(&call_details);
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op++;
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->data.send_message.send_message = request_payload;
+ op++;
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message.recv_message = &response_payload_recv;
+ op++;
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op++;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+ op++;
+ error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), nullptr);
+ 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);
+
+ peer = grpc_call_get_peer(s);
+ GPR_ASSERT(peer != nullptr);
+ gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+ gpr_free(peer);
+ peer = grpc_call_get_peer(c);
+ GPR_ASSERT(peer != nullptr);
+ gpr_log(GPR_DEBUG, "client_peer=%s", peer);
+ gpr_free(peer);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op++;
+ 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_INVALID_ARGUMENT;
+ op->data.send_status_from_server.status_details = &status_details;
+ op++;
+ op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+ op->data.recv_close_on_server.cancelled = &was_cancelled;
+ op++;
+ error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), nullptr);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ CQ_EXPECT_COMPLETION(cqv, tag(102), true);
+ CQ_EXPECT_COMPLETION(cqv, tag(1), true);
+ cq_verify(cqv);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+ op->data.recv_status_on_client.status = &status;
+ op->data.recv_status_on_client.status_details = &details;
+ op++;
+ error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), nullptr);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ CQ_EXPECT_COMPLETION(cqv, tag(2), true);
+ cq_verify(cqv);
+
+ GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
+ GPR_ASSERT(0 == call_details.flags);
+ GPR_ASSERT(was_cancelled == 1);
+
+ grpc_slice_unref(details);
+ grpc_metadata_array_destroy(&initial_metadata_recv);
+ grpc_metadata_array_destroy(&trailing_metadata_recv);
+ grpc_metadata_array_destroy(&request_metadata_recv);
+ grpc_call_details_destroy(&call_details);
+ grpc_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_call_unref(c);
+ grpc_call_unref(s);
+
+ cq_verifier_destroy(cqv);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+void retry_non_retriable_status_before_recv_trailing_metadata_started(
+ grpc_end2end_test_config config) {
+ GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL);
+ test_retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+}
+
+void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init() {
+}
diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc
index 2e398a7722..c810345166 100644
--- a/test/core/gprpp/ref_counted_ptr_test.cc
+++ b/test/core/gprpp/ref_counted_ptr_test.cc
@@ -88,7 +88,7 @@ TEST(RefCountedPtr, CopyAssignmentWhenEmpty) {
TEST(RefCountedPtr, CopyAssignmentToSelf) {
RefCountedPtr<Foo> foo(New<Foo>());
- foo = foo;
+ foo = *&foo; // The "*&" avoids warnings from LLVM -Wself-assign.
}
TEST(RefCountedPtr, EnclosedScope) {
diff --git a/test/core/handshake/readahead_handshaker_server_ssl.cc b/test/core/handshake/readahead_handshaker_server_ssl.cc
index 9788320e0d..97e9c20ee4 100644
--- a/test/core/handshake/readahead_handshaker_server_ssl.cc
+++ b/test/core/handshake/readahead_handshaker_server_ssl.cc
@@ -64,7 +64,7 @@ static void readahead_handshaker_do_handshake(
const grpc_handshaker_vtable readahead_handshaker_vtable = {
readahead_handshaker_destroy, readahead_handshaker_shutdown,
- readahead_handshaker_do_handshake};
+ readahead_handshaker_do_handshake, "read_ahead"};
static grpc_handshaker* readahead_handshaker_create() {
grpc_handshaker* h =
diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc
index ce92e21d73..2b90939ab8 100644
--- a/test/core/security/credentials_test.cc
+++ b/test/core/security/credentials_test.cc
@@ -867,6 +867,7 @@ static void set_google_default_creds_env_var_with_file_contents(
static void test_google_default_creds_auth_key(void) {
grpc_core::ExecCtx exec_ctx;
grpc_service_account_jwt_access_credentials* jwt;
+ grpc_google_default_channel_credentials* default_creds;
grpc_composite_channel_credentials* creds;
char* json_key = test_json_key_str();
grpc_flush_cached_google_default_credentials();
@@ -875,7 +876,9 @@ static void test_google_default_creds_auth_key(void) {
gpr_free(json_key);
creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create());
- GPR_ASSERT(creds != nullptr);
+ default_creds = reinterpret_cast<grpc_google_default_channel_credentials*>(
+ creds->inner_creds);
+ GPR_ASSERT(default_creds->ssl_creds != nullptr);
jwt = reinterpret_cast<grpc_service_account_jwt_access_credentials*>(
creds->call_creds);
GPR_ASSERT(
@@ -889,13 +892,16 @@ static void test_google_default_creds_auth_key(void) {
static void test_google_default_creds_refresh_token(void) {
grpc_core::ExecCtx exec_ctx;
grpc_google_refresh_token_credentials* refresh;
+ grpc_google_default_channel_credentials* default_creds;
grpc_composite_channel_credentials* creds;
grpc_flush_cached_google_default_credentials();
set_google_default_creds_env_var_with_file_contents(
"refresh_token_google_default_creds", test_refresh_token_str);
creds = reinterpret_cast<grpc_composite_channel_credentials*>(
grpc_google_default_credentials_create());
- GPR_ASSERT(creds != nullptr);
+ default_creds = reinterpret_cast<grpc_google_default_channel_credentials*>(
+ creds->inner_creds);
+ GPR_ASSERT(default_creds->ssl_creds != nullptr);
refresh = reinterpret_cast<grpc_google_refresh_token_credentials*>(
creds->call_creds);
GPR_ASSERT(strcmp(refresh->refresh_token.client_id,
diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc
index f03f4ccdbd..e4c3ace6b4 100644
--- a/test/core/security/security_connector_test.cc
+++ b/test/core/security/security_connector_test.cc
@@ -87,15 +87,15 @@ static void test_unauthenticated_ssl_peer(void) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
- ctx = tsi_ssl_peer_to_auth_context(&peer);
+ ctx = grpc_ssl_peer_to_auth_context(&peer);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx));
GPR_ASSERT(check_transport_security_type(ctx));
- rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+ rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
- tsi_shallow_peer_destruct(&rpeer);
+ grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
@@ -187,7 +187,7 @@ static void test_cn_only_ssl_peer_to_auth_context(void) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
&peer.properties[2]) == TSI_OK);
- ctx = tsi_ssl_peer_to_auth_context(&peer);
+ ctx = grpc_ssl_peer_to_auth_context(&peer);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
@@ -195,10 +195,10 @@ static void test_cn_only_ssl_peer_to_auth_context(void) {
GPR_ASSERT(check_x509_cn(ctx, expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
- rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+ rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
- tsi_shallow_peer_destruct(&rpeer);
+ grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
@@ -223,7 +223,7 @@ static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
&peer.properties[3]) == TSI_OK);
- ctx = tsi_ssl_peer_to_auth_context(&peer);
+ ctx = grpc_ssl_peer_to_auth_context(&peer);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
GPR_ASSERT(
@@ -232,10 +232,10 @@ static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
GPR_ASSERT(check_x509_cn(ctx, expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
- rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+ rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
- tsi_shallow_peer_destruct(&rpeer);
+ grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
@@ -264,7 +264,7 @@ static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
expected_sans[i], &peer.properties[3 + i]) == TSI_OK);
}
- ctx = tsi_ssl_peer_to_auth_context(&peer);
+ ctx = grpc_ssl_peer_to_auth_context(&peer);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
@@ -273,10 +273,10 @@ static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
GPR_ASSERT(check_x509_cn(ctx, expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
- rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+ rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
- tsi_shallow_peer_destruct(&rpeer);
+ grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
@@ -310,7 +310,7 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
expected_sans[i], &peer.properties[5 + i]) == TSI_OK);
}
- ctx = tsi_ssl_peer_to_auth_context(&peer);
+ ctx = grpc_ssl_peer_to_auth_context(&peer);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
@@ -319,10 +319,10 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
GPR_ASSERT(check_x509_cn(ctx, expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
- rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+ rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
- tsi_shallow_peer_destruct(&rpeer);
+ grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
@@ -340,6 +340,26 @@ static grpc_ssl_roots_override_result override_roots_permanent_failure(
return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
}
+static void test_ipv6_address_san(void) {
+ const char* addresses[] = {
+ "2001:db8::1", "fe80::abcd:ef65:4321%em0", "fd11:feed:beef:0:cafe::4",
+ "128.10.0.1:8888", "[2001:db8::1]:8080", "[2001:db8::1%em1]:8080",
+ };
+ const char* san_ips[] = {
+ "2001:db8::1", "fe80::abcd:ef65:4321", "fd11:feed:beef:0:cafe::4",
+ "128.10.0.1", "2001:db8::1", "2001:db8::1",
+ };
+ tsi_peer peer;
+ GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(addresses); i++) {
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, san_ips[i],
+ &peer.properties[0]) == TSI_OK);
+ GPR_ASSERT(grpc_ssl_host_matches_name(&peer, addresses[i]));
+ tsi_peer_property_destruct(&peer.properties[0]);
+ }
+ tsi_peer_destruct(&peer);
+}
namespace grpc_core {
namespace {
@@ -416,6 +436,7 @@ int main(int argc, char** argv) {
test_cn_and_one_san_ssl_peer_to_auth_context();
test_cn_and_multiple_sans_ssl_peer_to_auth_context();
test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
+ test_ipv6_address_san();
test_default_ssl_roots();
grpc_shutdown();
diff --git a/test/core/tsi/alts/fake_handshaker/BUILD b/test/core/tsi/alts/fake_handshaker/BUILD
new file mode 100644
index 0000000000..a09a046d27
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/BUILD
@@ -0,0 +1,57 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+licenses(["notice"]) # Apache v2
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+
+grpc_package(name = "test/core/tsi/alts/fake_handshaker", visibility = "public")
+
+grpc_proto_library(
+ name = "transport_security_common_proto",
+ srcs = ["transport_security_common.proto"],
+ has_services = False,
+)
+
+grpc_proto_library(
+ name = "handshaker_proto",
+ srcs = ["handshaker.proto"],
+ has_services = True,
+ deps = [
+ "transport_security_common_proto",
+ ],
+)
+
+grpc_cc_library(
+ name = "fake_handshaker_lib",
+ testonly = True,
+ srcs = ["fake_handshaker_server.cc"],
+ language = "C++",
+ deps = [
+ "handshaker_proto",
+ "transport_security_common_proto",
+ "//:grpc++",
+ "//test/cpp/util:test_config",
+ ],
+)
+
+grpc_cc_binary(
+ name = "fake_handshaker_server",
+ testonly = True,
+ srcs = ["fake_handshaker_server.cc"],
+ language = "C++",
+ deps = [
+ "fake_handshaker_lib",
+ ],
+)
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
new file mode 100644
index 0000000000..f6a4791b49
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/server_context.h>
+
+#include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
+#include "test/cpp/util/test_config.h"
+
+DEFINE_int32(handshaker_port, 55056,
+ "TCP port on which the fake handshaker server listens to.");
+
+// Fake handshake messages.
+constexpr char kClientInitFrame[] = "ClientInit";
+constexpr char kServerFrame[] = "ServerInitAndFinished";
+constexpr char kClientFinishFrame[] = "ClientFinished";
+// Error messages.
+constexpr char kInvalidFrameError[] = "Invalid input frame.";
+constexpr char kWrongStateError[] = "Wrong handshake state.";
+
+namespace grpc {
+namespace gcp {
+
+// FakeHandshakeService implements a fake handshaker service using a fake key
+// exchange protocol. The fake key exchange protocol is a 3-message protocol:
+// - Client first sends ClientInit message to Server.
+// - Server then sends ServerInitAndFinished message back to Client.
+// - Client finally sends ClientFinished message to Server.
+// This fake handshaker service is intended for ALTS integration testing without
+// relying on real ALTS handshaker service inside GCE.
+// It is thread-safe.
+class FakeHandshakerService : public HandshakerService::Service {
+ public:
+ Status DoHandshake(
+ ServerContext* server_context,
+ ServerReaderWriter<HandshakerResp, HandshakerReq>* stream) override {
+ Status status;
+ HandshakerContext context;
+ HandshakerReq request;
+ HandshakerResp response;
+ gpr_log(GPR_DEBUG, "Start a new handshake.");
+ while (stream->Read(&request)) {
+ status = ProcessRequest(&context, request, &response);
+ if (!status.ok()) return WriteErrorResponse(stream, status);
+ stream->Write(response);
+ if (context.state == COMPLETED) return Status::OK;
+ request.Clear();
+ }
+ return Status::OK;
+ }
+
+ private:
+ // HandshakeState is used by fake handshaker server to keep track of client's
+ // handshake status. In the beginning of a handshake, the state is INITIAL.
+ // If start_client or start_server request is called, the state becomes at
+ // least STARTED. When the handshaker server produces the first fame, the
+ // state becomes SENT. After the handshaker server processes the final frame
+ // from the peer, the state becomes COMPLETED.
+ enum HandshakeState { INITIAL, STARTED, SENT, COMPLETED };
+
+ struct HandshakerContext {
+ bool is_client = true;
+ HandshakeState state = INITIAL;
+ };
+
+ Status ProcessRequest(HandshakerContext* context,
+ const HandshakerReq& request,
+ HandshakerResp* response) {
+ GPR_ASSERT(context != nullptr && response != nullptr);
+ response->Clear();
+ if (request.has_client_start()) {
+ gpr_log(GPR_DEBUG, "Process client start request.");
+ return ProcessClientStart(context, request.client_start(), response);
+ } else if (request.has_server_start()) {
+ gpr_log(GPR_DEBUG, "Process server start request.");
+ return ProcessServerStart(context, request.server_start(), response);
+ } else if (request.has_next()) {
+ gpr_log(GPR_DEBUG, "Process next request.");
+ return ProcessNext(context, request.next(), response);
+ }
+ return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
+ }
+
+ Status ProcessClientStart(HandshakerContext* context,
+ const StartClientHandshakeReq& request,
+ HandshakerResp* response) {
+ GPR_ASSERT(context != nullptr && response != nullptr);
+ // Checks request.
+ if (context->state != INITIAL) {
+ return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+ }
+ if (request.application_protocols_size() == 0) {
+ return Status(StatusCode::INVALID_ARGUMENT,
+ "At least one application protocol needed.");
+ }
+ if (request.record_protocols_size() == 0) {
+ return Status(StatusCode::INVALID_ARGUMENT,
+ "At least one record protocol needed.");
+ }
+ // Sets response.
+ response->set_out_frames(kClientInitFrame);
+ response->set_bytes_consumed(0);
+ response->mutable_status()->set_code(StatusCode::OK);
+ // Updates handshaker context.
+ context->is_client = true;
+ context->state = SENT;
+ return Status::OK;
+ }
+
+ Status ProcessServerStart(HandshakerContext* context,
+ const StartServerHandshakeReq& request,
+ HandshakerResp* response) {
+ GPR_ASSERT(context != nullptr && response != nullptr);
+ // Checks request.
+ if (context->state != INITIAL) {
+ return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+ }
+ if (request.application_protocols_size() == 0) {
+ return Status(StatusCode::INVALID_ARGUMENT,
+ "At least one application protocol needed.");
+ }
+ if (request.handshake_parameters().empty()) {
+ return Status(StatusCode::INVALID_ARGUMENT,
+ "At least one set of handshake parameters needed.");
+ }
+ // Sets response.
+ if (request.in_bytes().empty()) {
+ // start_server request does not have in_bytes.
+ response->set_bytes_consumed(0);
+ context->state = STARTED;
+ } else {
+ // start_server request has in_bytes.
+ if (request.in_bytes() == kClientInitFrame) {
+ response->set_out_frames(kServerFrame);
+ response->set_bytes_consumed(strlen(kClientInitFrame));
+ context->state = SENT;
+ } else {
+ return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+ }
+ }
+ response->mutable_status()->set_code(StatusCode::OK);
+ context->is_client = false;
+ return Status::OK;
+ }
+
+ Status ProcessNext(HandshakerContext* context,
+ const NextHandshakeMessageReq& request,
+ HandshakerResp* response) {
+ GPR_ASSERT(context != nullptr && response != nullptr);
+ if (context->is_client) {
+ // Processes next request on client side.
+ if (context->state != SENT) {
+ return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+ }
+ if (request.in_bytes() != kServerFrame) {
+ return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+ }
+ response->set_out_frames(kClientFinishFrame);
+ response->set_bytes_consumed(strlen(kServerFrame));
+ context->state = COMPLETED;
+ } else {
+ // Processes next request on server side.
+ HandshakeState current_state = context->state;
+ if (current_state == STARTED) {
+ if (request.in_bytes() != kClientInitFrame) {
+ return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+ }
+ response->set_out_frames(kServerFrame);
+ response->set_bytes_consumed(strlen(kClientInitFrame));
+ context->state = SENT;
+ } else if (current_state == SENT) {
+ // Client finish frame may be sent along with the first payload from the
+ // client, handshaker only consumes the client finish frame.
+ if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
+ kClientFinishFrame) {
+ return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+ }
+ response->set_bytes_consumed(strlen(kClientFinishFrame));
+ context->state = COMPLETED;
+ } else {
+ return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+ }
+ }
+ // At this point, processing next request succeeded.
+ response->mutable_status()->set_code(StatusCode::OK);
+ if (context->state == COMPLETED) {
+ *response->mutable_result() = GetHandshakerResult();
+ }
+ return Status::OK;
+ }
+
+ Status WriteErrorResponse(
+ ServerReaderWriter<HandshakerResp, HandshakerReq>* stream,
+ const Status& status) {
+ GPR_ASSERT(!status.ok());
+ HandshakerResp response;
+ response.mutable_status()->set_code(status.error_code());
+ response.mutable_status()->set_details(status.error_message());
+ stream->Write(response);
+ return status;
+ }
+
+ HandshakerResult GetHandshakerResult() {
+ HandshakerResult result;
+ result.set_application_protocol("grpc");
+ result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
+ result.mutable_peer_identity()->set_service_account("peer_identity");
+ result.mutable_local_identity()->set_service_account("local_identity");
+ string key(1024, '\0');
+ result.set_key_data(key);
+ result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
+ result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
+ result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
+ result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
+ return result;
+ }
+};
+
+} // namespace gcp
+} // namespace grpc
+
+void RunServer() {
+ GPR_ASSERT(FLAGS_handshaker_port != 0);
+ std::ostringstream server_address;
+ server_address << "[::1]:" << FLAGS_handshaker_port;
+ grpc::gcp::FakeHandshakerService service;
+ grpc::ServerBuilder builder;
+ builder.AddListeningPort(server_address.str(),
+ grpc::InsecureServerCredentials());
+ builder.RegisterService(&service);
+ std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+ gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
+ server_address.str().c_str());
+ server->Wait();
+}
+
+int main(int argc, char** argv) {
+ grpc::testing::InitTest(&argc, &argv, true);
+ RunServer();
+ return 0;
+}
diff --git a/test/core/tsi/alts/fake_handshaker/handshaker.proto b/test/core/tsi/alts/fake_handshaker/handshaker.proto
new file mode 100644
index 0000000000..8af9abfbf5
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/handshaker.proto
@@ -0,0 +1,224 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+import "test/core/tsi/alts/fake_handshaker/transport_security_common.proto";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+enum HandshakeProtocol {
+ // Default value.
+ HANDSHAKE_PROTOCOL_UNSPECIFIED = 0;
+
+ // TLS handshake protocol.
+ TLS = 1;
+
+ // Application Layer Transport Security handshake protocol.
+ ALTS = 2;
+}
+
+enum NetworkProtocol {
+ NETWORK_PROTOCOL_UNSPECIFIED = 0;
+ TCP = 1;
+ UDP = 2;
+}
+
+message Endpoint {
+ // IP address. It should contain an IPv4 or IPv6 string literal, e.g.
+ // "192.168.0.1" or "2001:db8::1".
+ string ip_address = 1;
+
+ // Port number.
+ int32 port = 2;
+
+ // Network protocol (e.g., TCP, UDP) associated with this endpoint.
+ NetworkProtocol protocol = 3;
+}
+
+message Identity {
+ oneof identity_oneof {
+ // Service account of a connection endpoint.
+ string service_account = 1;
+
+ // Hostname of a connection endpoint.
+ string hostname = 2;
+ }
+}
+
+message StartClientHandshakeReq {
+ // Handshake security protocol requested by the client.
+ HandshakeProtocol handshake_security_protocol = 1;
+
+ // The application protocols supported by the client, e.g., "h2" (for http2),
+ // "grpc".
+ repeated string application_protocols = 2;
+
+ // The record protocols supported by the client, e.g.,
+ // "ALTSRP_GCM_AES128".
+ repeated string record_protocols = 3;
+
+ // (Optional) Describes which server identities are acceptable by the client.
+ // If target identities are provided and none of them matches the peer
+ // identity of the server, handshake will fail.
+ repeated Identity target_identities = 4;
+
+ // (Optional) Application may specify a local identity. Otherwise, the
+ // handshaker chooses a default local identity.
+ Identity local_identity = 5;
+
+ // (Optional) Local endpoint information of the connection to the server,
+ // such as local IP address, port number, and network protocol.
+ Endpoint local_endpoint = 6;
+
+ // (Optional) Endpoint information of the remote server, such as IP address,
+ // port number, and network protocol.
+ Endpoint remote_endpoint = 7;
+
+ // (Optional) If target name is provided, a secure naming check is performed
+ // to verify that the peer authenticated identity is indeed authorized to run
+ // the target name.
+ string target_name = 8;
+
+ // (Optional) RPC protocol versions supported by the client.
+ RpcProtocolVersions rpc_versions = 9;
+}
+
+message ServerHandshakeParameters {
+ // The record protocols supported by the server, e.g.,
+ // "ALTSRP_GCM_AES128".
+ repeated string record_protocols = 1;
+
+ // (Optional) A list of local identities supported by the server, if
+ // specified. Otherwise, the handshaker chooses a default local identity.
+ repeated Identity local_identities = 2;
+}
+
+message StartServerHandshakeReq {
+ // The application protocols supported by the server, e.g., "h2" (for http2),
+ // "grpc".
+ repeated string application_protocols = 1;
+
+ // Handshake parameters (record protocols and local identities supported by
+ // the server) mapped by the handshake protocol. Each handshake security
+ // protocol (e.g., TLS or ALTS) has its own set of record protocols and local
+ // identities. Since protobuf does not support enum as key to the map, the key
+ // to handshake_parameters is the integer value of HandshakeProtocol enum.
+ map<int32, ServerHandshakeParameters> handshake_parameters = 2;
+
+ // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+ // that the peer's out_frames are split into multiple HandshakReq messages.
+ bytes in_bytes = 3;
+
+ // (Optional) Local endpoint information of the connection to the client,
+ // such as local IP address, port number, and network protocol.
+ Endpoint local_endpoint = 4;
+
+ // (Optional) Endpoint information of the remote client, such as IP address,
+ // port number, and network protocol.
+ Endpoint remote_endpoint = 5;
+
+ // (Optional) RPC protocol versions supported by the server.
+ RpcProtocolVersions rpc_versions = 6;
+}
+
+message NextHandshakeMessageReq {
+ // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+ // that the peer's out_frames are split into multiple NextHandshakerMessageReq
+ // messages.
+ bytes in_bytes = 1;
+}
+
+message HandshakerReq {
+ oneof req_oneof {
+ // The start client handshake request message.
+ StartClientHandshakeReq client_start = 1;
+
+ // The start server handshake request message.
+ StartServerHandshakeReq server_start = 2;
+
+ // The next handshake request message.
+ NextHandshakeMessageReq next = 3;
+ }
+}
+
+message HandshakerResult {
+ // The application protocol negotiated for this connection.
+ string application_protocol = 1;
+
+ // The record protocol negotiated for this connection.
+ string record_protocol = 2;
+
+ // Cryptographic key data. The key data may be more than the key length
+ // required for the record protocol, thus the client of the handshaker
+ // service needs to truncate the key data into the right key length.
+ bytes key_data = 3;
+
+ // The authenticated identity of the peer.
+ Identity peer_identity = 4;
+
+ // The local identity used in the handshake.
+ Identity local_identity = 5;
+
+ // Indicate whether the handshaker service client should keep the channel
+ // between the handshaker service open, e.g., in order to handle
+ // post-handshake messages in the future.
+ bool keep_channel_open = 6;
+
+ // The RPC protocol versions supported by the peer.
+ RpcProtocolVersions peer_rpc_versions = 7;
+}
+
+message HandshakerStatus {
+ // The status code. This could be the gRPC status code.
+ uint32 code = 1;
+
+ // The status details.
+ string details = 2;
+}
+
+message HandshakerResp {
+ // Frames to be given to the peer for the NextHandshakeMessageReq. May be
+ // empty if no out_frames have to be sent to the peer or if in_bytes in the
+ // HandshakerReq are incomplete. All the non-empty out frames must be sent to
+ // the peer even if the handshaker status is not OK as these frames may
+ // contain the alert frames.
+ bytes out_frames = 1;
+
+ // Number of bytes in the in_bytes consumed by the handshaker. It is possible
+ // that part of in_bytes in HandshakerReq was unrelated to the handshake
+ // process.
+ uint32 bytes_consumed = 2;
+
+ // This is set iff the handshake was successful. out_frames may still be set
+ // to frames that needs to be forwarded to the peer.
+ HandshakerResult result = 3;
+
+ // Status of the handshaker.
+ HandshakerStatus status = 4;
+}
+
+service HandshakerService {
+ // Handshaker service accepts a stream of handshaker request, returning a
+ // stream of handshaker response. Client is expected to send exactly one
+ // message with either client_start or server_start followed by one or more
+ // messages with next. Each time client sends a request, the handshaker
+ // service expects to respond. Client does not have to wait for service's
+ // response before sending next request.
+ rpc DoHandshake(stream HandshakerReq)
+ returns (stream HandshakerResp) {
+ }
+}
diff --git a/test/core/tsi/alts/fake_handshaker/transport_security_common.proto b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
new file mode 100644
index 0000000000..d0f861e644
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
@@ -0,0 +1,40 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+// The security level of the created channel. The list is sorted in increasing
+// level of security. This order must always be maintained.
+enum SecurityLevel {
+ SECURITY_NONE = 0;
+ INTEGRITY_ONLY = 1;
+ INTEGRITY_AND_PRIVACY = 2;
+}
+
+// Max and min supported RPC protocol versions.
+message RpcProtocolVersions {
+ // RPC version contains a major version and a minor version.
+ message Version {
+ uint32 major = 1;
+ uint32 minor = 2;
+ }
+ // Maximum supported RPC version.
+ Version max_rpc_version = 1;
+ // Minimum supported RPC version.
+ Version min_rpc_version = 2;
+}
diff --git a/test/core/tsi/ssl_session_cache_test.cc b/test/core/tsi/ssl_session_cache_test.cc
index 72df0e545c..c86cefb3ff 100644
--- a/test/core/tsi/ssl_session_cache_test.cc
+++ b/test/core/tsi/ssl_session_cache_test.cc
@@ -88,7 +88,6 @@ TEST(SslSessionCacheTest, InitialState) {
// Verify session initial state.
{
tsi::SslSessionPtr tmp_sess = tracker.NewSession(1);
- EXPECT_EQ(tmp_sess->references, 1);
EXPECT_TRUE(tracker.IsAlive(1));
EXPECT_EQ(tracker.AliveCount(), 1);
}
diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc
index 88f1abc18c..cf1ac82413 100644
--- a/test/core/tsi/ssl_transport_security_test.cc
+++ b/test/core/tsi/ssl_transport_security_test.cc
@@ -34,6 +34,10 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+extern "C" {
+#include <openssl/crypto.h>
+}
+
#define SSL_TSI_TEST_ALPN1 "foo"
#define SSL_TSI_TEST_ALPN2 "toto"
#define SSL_TSI_TEST_ALPN3 "baz"
@@ -42,6 +46,14 @@
#define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1
#define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/"
+// OpenSSL 1.1 uses AES256 for encryption session ticket by default so specify
+// different STEK size.
+#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_IS_BORINGSSL)
+const size_t kSessionTicketEncryptionKeySize = 80;
+#else
+const size_t kSessionTicketEncryptionKeySize = 48;
+#endif
+
typedef enum AlpnMode {
NO_ALPN,
ALPN_CLIENT_NO_SERVER,
@@ -624,7 +636,7 @@ void ssl_tsi_test_do_round_trip_odd_buffer_size() {
void ssl_tsi_test_do_handshake_session_cache() {
tsi_ssl_session_cache* session_cache = tsi_ssl_session_cache_create_lru(16);
- char session_ticket_key[48];
+ char session_ticket_key[kSessionTicketEncryptionKeySize];
auto do_handshake = [&session_ticket_key,
&session_cache](bool session_reused) {
tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
@@ -633,22 +645,22 @@ void ssl_tsi_test_do_handshake_session_cache() {
ssl_fixture->server_name_indication =
const_cast<char*>("waterzooi.test.google.be");
ssl_fixture->session_ticket_key = session_ticket_key;
- ssl_fixture->session_ticket_key_size = 48;
+ ssl_fixture->session_ticket_key_size = sizeof(session_ticket_key);
tsi_ssl_session_cache_ref(session_cache);
ssl_fixture->session_cache = session_cache;
ssl_fixture->session_reused = session_reused;
tsi_test_do_round_trip(&ssl_fixture->base);
tsi_test_fixture_destroy(fixture);
};
- memset(session_ticket_key, 'a', 48);
+ memset(session_ticket_key, 'a', sizeof(session_ticket_key));
do_handshake(false);
do_handshake(true);
do_handshake(true);
// Changing session_ticket_key on server invalidates ticket.
- memset(session_ticket_key, 'b', 48);
+ memset(session_ticket_key, 'b', sizeof(session_ticket_key));
do_handshake(false);
do_handshake(true);
- memset(session_ticket_key, 'c', 48);
+ memset(session_ticket_key, 'c', sizeof(session_ticket_key));
do_handshake(false);
do_handshake(true);
tsi_ssl_session_cache_unref(session_cache);