aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorGravatar Yash Tibrewal <yashkt@google.com>2018-08-13 10:53:06 -0700
committerGravatar Yash Tibrewal <yashkt@google.com>2018-08-13 10:53:06 -0700
commit556775d7c78125e051c6571d4c528de214024c23 (patch)
tree77d3e0effdb58b01e9e257a8dcd03a024acedf31 /test
parent0ec6973b743e8e1f463bdcc8691e1869097c92f0 (diff)
parentba7ca9742eb7484009b75c268dba7e56b8feaebb (diff)
Merge master
Diffstat (limited to 'test')
-rw-r--r--test/core/channel/channel_trace_test.cc24
-rw-r--r--test/core/channel/channelz_registry_test.cc74
-rw-r--r--test/core/channel/channelz_test.cc100
-rw-r--r--test/core/channel/minimal_stack_is_minimal_test.cc16
-rw-r--r--test/core/end2end/tests/channelz.cc16
-rw-r--r--test/core/end2end/tests/filter_call_init_fails.cc15
-rw-r--r--test/core/end2end/tests/filter_causes_close.cc5
-rw-r--r--test/core/end2end/tests/filter_latency.cc19
-rw-r--r--test/core/end2end/tests/filter_status_code.cc19
-rw-r--r--test/core/gprpp/inlined_vector_test.cc192
-rw-r--r--test/core/gprpp/ref_counted_ptr_test.cc63
-rw-r--r--test/core/iomgr/BUILD13
-rw-r--r--test/core/iomgr/grpc_ipv6_loopback_available_test.cc48
-rw-r--r--test/core/security/BUILD25
-rw-r--r--test/core/security/check_gcp_environment_linux_test.cc1
-rw-r--r--test/core/security/etc/BUILD22
-rw-r--r--test/core/security/etc/README2
-rw-r--r--test/core/security/etc/bundle.pem63
-rw-r--r--test/core/security/etc/test_roots/cert1.pem21
-rw-r--r--test/core/security/etc/test_roots/cert2.pem21
-rw-r--r--test/core/security/etc/test_roots/cert3.pem21
-rw-r--r--test/core/security/linux_system_roots_test.cc104
-rw-r--r--test/core/security/security_connector_test.cc12
-rw-r--r--test/core/surface/public_headers_must_be_c89.c3
-rw-r--r--test/cpp/common/channel_filter_test.cc3
-rw-r--r--test/cpp/end2end/BUILD21
-rw-r--r--test/cpp/end2end/async_end2end_test.cc23
-rw-r--r--test/cpp/end2end/channelz_service_test.cc352
-rw-r--r--test/cpp/end2end/client_lb_end2end_test.cc70
-rw-r--r--test/cpp/end2end/filter_end2end_test.cc3
-rw-r--r--test/cpp/interop/client.cc16
-rw-r--r--test/cpp/interop/client_helper.cc20
-rw-r--r--test/cpp/interop/interop_client.cc64
-rw-r--r--test/cpp/interop/interop_client.h20
-rw-r--r--test/cpp/interop/stress_interop_client.cc6
-rw-r--r--test/cpp/interop/stress_interop_client.h4
-rw-r--r--test/cpp/interop/stress_test.cc11
-rw-r--r--test/cpp/naming/address_sorting_test.cc160
-rw-r--r--test/cpp/naming/cancel_ares_query_test.cc55
-rwxr-xr-xtest/cpp/naming/gen_build_yaml.py6
-rw-r--r--test/cpp/naming/manual_run_resolver_component_test.py36
-rw-r--r--test/cpp/naming/resolver_component_test.cc72
-rwxr-xr-xtest/cpp/naming/resolver_component_tests_runner.py31
-rw-r--r--test/cpp/naming/resolver_test_record_groups.yaml8
-rw-r--r--test/cpp/qps/BUILD6
-rw-r--r--test/cpp/qps/benchmark_config.cc15
-rw-r--r--test/cpp/qps/client.h24
-rw-r--r--test/cpp/qps/qps_server_builder.cc45
-rw-r--r--test/cpp/qps/qps_server_builder.h46
-rw-r--r--test/cpp/qps/qps_worker.cc9
-rw-r--r--test/cpp/qps/server_async.cc15
-rw-r--r--test/cpp/qps/server_sync.cc13
-rw-r--r--test/cpp/server/load_reporter/load_reporter_test.cc4
-rw-r--r--test/cpp/util/BUILD1
-rw-r--r--test/cpp/util/channel_trace_proto_helper.cc19
-rw-r--r--test/cpp/util/channel_trace_proto_helper.h6
-rw-r--r--test/cpp/util/cli_credentials.cc110
-rw-r--r--test/cpp/util/cli_credentials.h16
-rw-r--r--test/cpp/util/grpc_tool.cc17
-rw-r--r--test/cpp/util/grpc_tool_test.cc55
-rw-r--r--test/distrib/cpp/run_distrib_test_cmake.bat2
-rwxr-xr-xtest/distrib/cpp/run_distrib_test_routeguide.sh2
62 files changed, 1970 insertions, 315 deletions
diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc
index bbddee3f14..f224457a55 100644
--- a/test/core/channel/channel_trace_test.cc
+++ b/test/core/channel/channel_trace_test.cc
@@ -34,8 +34,6 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/channel_trace_proto_helper.h"
-// remove me
-#include <grpc/support/string_util.h>
#include <stdlib.h>
#include <string.h>
@@ -88,7 +86,7 @@ void AddSimpleTrace(ChannelTrace* tracer) {
void ValidateChannelTrace(ChannelTrace* tracer,
size_t expected_num_event_logged, size_t max_nodes) {
if (!max_nodes) return;
- grpc_json* json = tracer->RenderJSON();
+ grpc_json* json = tracer->RenderJson();
EXPECT_NE(json, nullptr);
char* json_str = grpc_json_dump_to_string(json, 0);
grpc_json_destroy(json);
@@ -157,7 +155,7 @@ TEST_P(ChannelTracerTest, ComplexTest) {
AddSimpleTrace(&tracer);
ChannelFixture channel1(GetParam());
RefCountedPtr<ChannelNode> sc1 =
- MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam(), true);
tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
@@ -175,7 +173,7 @@ TEST_P(ChannelTracerTest, ComplexTest) {
ValidateChannelTrace(&tracer, 5, GetParam());
ChannelFixture channel2(GetParam());
RefCountedPtr<ChannelNode> sc2 =
- MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam(), true);
tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("LB channel two created"), sc2);
@@ -189,8 +187,8 @@ TEST_P(ChannelTracerTest, ComplexTest) {
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
- sc1.reset(nullptr);
- sc2.reset(nullptr);
+ sc1.reset();
+ sc2.reset();
}
// Test a case in which the parent channel has subchannels and the subchannels
@@ -204,7 +202,7 @@ TEST_P(ChannelTracerTest, TestNesting) {
ValidateChannelTrace(&tracer, 2, GetParam());
ChannelFixture channel1(GetParam());
RefCountedPtr<ChannelNode> sc1 =
- MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam(), true);
tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
@@ -212,7 +210,7 @@ TEST_P(ChannelTracerTest, TestNesting) {
AddSimpleTrace(sc1->trace());
ChannelFixture channel2(GetParam());
RefCountedPtr<ChannelNode> conn1 =
- MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam(), true);
// nesting one level deeper.
sc1->trace()->AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
@@ -225,7 +223,7 @@ TEST_P(ChannelTracerTest, TestNesting) {
ValidateChannelTrace(conn1->trace(), 1, GetParam());
ChannelFixture channel3(GetParam());
RefCountedPtr<ChannelNode> sc2 =
- MakeRefCounted<ChannelNode>(channel3.channel(), GetParam());
+ MakeRefCounted<ChannelNode>(channel3.channel(), GetParam(), true);
tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel two created"), sc2);
@@ -236,9 +234,9 @@ TEST_P(ChannelTracerTest, TestNesting) {
grpc_slice_from_static_string("subchannel one inactive"), sc1);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 8, GetParam());
- sc1.reset(nullptr);
- sc2.reset(nullptr);
- conn1.reset(nullptr);
+ sc1.reset();
+ sc2.reset();
+ conn1.reset();
}
INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc
index 24e50933d7..581e867584 100644
--- a/test/core/channel/channelz_registry_test.cc
+++ b/test/core/channel/channelz_registry_test.cc
@@ -19,17 +19,20 @@
#include <stdlib.h>
#include <string.h>
+#include <grpc/grpc.h>
#include <gtest/gtest.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/json/json.h"
+#include "src/core/lib/surface/channel.h"
#include "test/core/util/test_config.h"
@@ -37,27 +40,26 @@
#include <string.h>
namespace grpc_core {
+namespace channelz {
namespace testing {
-// Tests basic ChannelTrace functionality like construction, adding trace, and
-// lookups by uuid.
TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) {
- int object_to_register;
- intptr_t uuid = ChannelzRegistry::Register(&object_to_register);
+ ChannelNode* channelz_channel = nullptr;
+ intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if "
"reserved according to "
"https://github.com/grpc/proposal/blob/master/"
"A14-channelz.md";
- ChannelzRegistry::Unregister(uuid);
+ ChannelzRegistry::UnregisterChannelNode(uuid);
}
TEST(ChannelzRegistryTest, UuidsAreIncreasing) {
- int object_to_register;
+ ChannelNode* channelz_channel = nullptr;
std::vector<intptr_t> uuids;
uuids.reserve(10);
for (int i = 0; i < 10; ++i) {
// reregister the same object. It's ok since we are just testing uuids
- uuids.push_back(ChannelzRegistry::Register(&object_to_register));
+ uuids.push_back(ChannelzRegistry::RegisterChannelNode(channelz_channel));
}
for (size_t i = 1; i < uuids.size(); ++i) {
EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing";
@@ -65,60 +67,36 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) {
}
TEST(ChannelzRegistryTest, RegisterGetTest) {
- int object_to_register = 42;
- intptr_t uuid = ChannelzRegistry::Register(&object_to_register);
- int* retrieved = ChannelzRegistry::Get<int>(uuid);
- EXPECT_EQ(&object_to_register, retrieved);
-}
-
-TEST(ChannelzRegistryTest, MultipleTypeTest) {
- int int_to_register = 42;
- intptr_t int_uuid = ChannelzRegistry::Register(&int_to_register);
- std::string str_to_register = "hello world";
- intptr_t str_uuid = ChannelzRegistry::Register(&str_to_register);
- int* retrieved_int = ChannelzRegistry::Get<int>(int_uuid);
- std::string* retrieved_str = ChannelzRegistry::Get<std::string>(str_uuid);
- EXPECT_EQ(&int_to_register, retrieved_int);
- EXPECT_EQ(&str_to_register, retrieved_str);
+ // we hackily jam an intptr_t into this pointer to check for equality later
+ ChannelNode* channelz_channel = (ChannelNode*)42;
+ intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
+ ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ EXPECT_EQ(channelz_channel, retrieved);
}
TEST(ChannelzRegistryTest, RegisterManyItems) {
- int object_to_register = 42;
+ // we hackily jam an intptr_t into this pointer to check for equality later
+ ChannelNode* channelz_channel = (ChannelNode*)42;
for (int i = 0; i < 100; i++) {
- intptr_t uuid = ChannelzRegistry::Register(&object_to_register);
- int* retrieved = ChannelzRegistry::Get<int>(uuid);
- EXPECT_EQ(&object_to_register, retrieved);
+ intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
+ ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ EXPECT_EQ(channelz_channel, retrieved);
}
}
-namespace {
-class Foo {
- public:
- int bar;
-};
-} // namespace
-
-TEST(ChannelzRegistryTest, CustomObjectTest) {
- Foo* foo = New<Foo>();
- foo->bar = 1024;
- intptr_t uuid = ChannelzRegistry::Register(foo);
- Foo* retrieved = ChannelzRegistry::Get<Foo>(uuid);
- EXPECT_EQ(foo, retrieved);
- Delete(foo);
-}
-
TEST(ChannelzRegistryTest, NullIfNotPresentTest) {
- int object_to_register = 42;
- intptr_t uuid = ChannelzRegistry::Register(&object_to_register);
+ // we hackily jam an intptr_t into this pointer to check for equality later
+ ChannelNode* channelz_channel = (ChannelNode*)42;
+ intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
// try to pull out a uuid that does not exist.
- int* nonexistant = ChannelzRegistry::Get<int>(uuid + 1);
+ ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1);
EXPECT_EQ(nonexistant, nullptr);
- int* retrieved = ChannelzRegistry::Get<int>(uuid);
- EXPECT_EQ(object_to_register, *retrieved);
- EXPECT_EQ(&object_to_register, retrieved);
+ ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ EXPECT_EQ(channelz_channel, retrieved);
}
} // namespace testing
+} // namespace channelz
} // namespace grpc_core
int main(int argc, char** argv) {
diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc
index 058eea914c..ad5f86d934 100644
--- a/test/core/channel/channelz_test.cc
+++ b/test/core/channel/channelz_test.cc
@@ -67,17 +67,50 @@ grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
return nullptr;
}
+void ValidateJsonArraySize(grpc_json* json, const char* key,
+ size_t expected_size) {
+ grpc_json* arr = GetJsonChild(json, key);
+ if (expected_size == 0) {
+ ASSERT_EQ(arr, nullptr);
+ return;
+ }
+ ASSERT_NE(arr, nullptr);
+ ASSERT_EQ(arr->type, GRPC_JSON_ARRAY);
+ size_t count = 0;
+ for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
+ ++count;
+ }
+ EXPECT_EQ(count, expected_size);
+}
+
+void ValidateGetTopChannels(size_t expected_channels) {
+ char* json_str = ChannelzRegistry::GetTopChannels(0);
+ grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ // This check will naturally have to change when we support pagination.
+ // tracked: https://github.com/grpc/grpc/issues/16019.
+ ValidateJsonArraySize(parsed_json, "channel", expected_channels);
+ grpc_json* end = GetJsonChild(parsed_json, "end");
+ ASSERT_NE(end, nullptr);
+ EXPECT_EQ(end->type, GRPC_JSON_TRUE);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+ // also check that the core API formats this correctly
+ char* core_api_json_str = grpc_channelz_get_top_channels(0);
+ grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
+ core_api_json_str);
+ gpr_free(core_api_json_str);
+}
+
class ChannelFixture {
public:
- ChannelFixture(int max_trace_nodes) {
+ ChannelFixture(int max_trace_nodes = 0) {
grpc_arg client_a[2];
- client_a[0].type = GRPC_ARG_INTEGER;
- client_a[0].key =
- const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
- client_a[0].value.integer = max_trace_nodes;
- client_a[1].type = GRPC_ARG_INTEGER;
- client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
- client_a[1].value.integer = true;
+ client_a[0] = grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE),
+ max_trace_nodes);
+ client_a[1] = grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true);
grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
channel_ =
grpc_insecure_channel_create("fake_target", &client_args, nullptr);
@@ -99,6 +132,10 @@ struct validate_channel_data_args {
void ValidateChildInteger(grpc_json* json, int64_t expect, const char* key) {
grpc_json* gotten_json = GetJsonChild(json, key);
+ if (expect == 0) {
+ ASSERT_EQ(gotten_json, nullptr);
+ return;
+ }
ASSERT_NE(gotten_json, nullptr);
int64_t gotten_number = (int64_t)strtol(gotten_json->value, nullptr, 0);
EXPECT_EQ(gotten_number, expect);
@@ -115,10 +152,15 @@ void ValidateCounters(char* json_str, validate_channel_data_args args) {
}
void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
- char* json_str = channel->RenderJSON();
+ char* json_str = channel->RenderJsonString();
grpc::testing::ValidateChannelProtoJsonTranslation(json_str);
ValidateCounters(json_str, args);
gpr_free(json_str);
+ // also check that the core API formats this the correct way
+ char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid());
+ grpc::testing::ValidateGetChannelResponseProtoJsonTranslation(
+ core_api_json_str);
+ gpr_free(core_api_json_str);
}
grpc_millis GetLastCallStartedMillis(ChannelNode* channel) {
@@ -141,9 +183,7 @@ TEST_P(ChannelzChannelTest, BasicChannel) {
ChannelFixture channel(GetParam());
ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(channel.channel());
- char* json_str = channelz_channel->RenderJSON();
- ValidateCounters(json_str, {0, 0, 0});
- gpr_free(json_str);
+ ValidateChannel(channelz_channel, {0, 0, 0});
}
TEST(ChannelzChannelTest, ChannelzDisabled) {
@@ -199,6 +239,42 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
EXPECT_NE(millis1, millis4);
}
+TEST(ChannelzGetTopChannelsTest, BasicTest) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel;
+ ValidateGetTopChannels(1);
+}
+
+TEST(ChannelzGetTopChannelsTest, NoChannelsTest) {
+ grpc_core::ExecCtx exec_ctx;
+ ValidateGetTopChannels(0);
+}
+
+TEST(ChannelzGetTopChannelsTest, ManyChannelsTest) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channels[10];
+ (void)channels; // suppress unused variable error
+ ValidateGetTopChannels(10);
+}
+
+TEST(ChannelzGetTopChannelsTest, InternalChannelTest) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channels[10];
+ (void)channels; // suppress unused variable error
+ // create an internal channel
+ grpc_arg client_a[2];
+ client_a[0] = grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), true);
+ client_a[1] = grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true);
+ grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+ grpc_channel* internal_channel =
+ grpc_insecure_channel_create("fake_target", &client_args, nullptr);
+ // The internal channel should not be returned from the request
+ ValidateGetTopChannels(10);
+ grpc_channel_destroy(internal_channel);
+}
+
INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
::testing::Values(0, 1, 2, 6, 10, 15));
diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc
index e5953acedc..5b651ed39b 100644
--- a/test/core/channel/minimal_stack_is_minimal_test.cc
+++ b/test/core/channel/minimal_stack_is_minimal_test.cc
@@ -85,21 +85,21 @@ int main(int argc, char** argv) {
// tests with a default stack
errors +=
- CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "authority",
- "message_size", "deadline", "connected", NULL);
+ CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "deadline",
+ "authority", "message_size", "connected", NULL);
errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
"message_size", "connected", NULL);
errors += CHECK_STACK("unknown", nullptr, GRPC_SERVER_CHANNEL, "server",
- "message_size", "deadline", "connected", NULL);
+ "deadline", "message_size", "connected", NULL);
errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_DIRECT_CHANNEL,
- "authority", "message_size", "deadline", "http-client",
- "message_compress", "connected", NULL);
+ "deadline", "authority", "message_size",
+ "message_compress", "http-client", "connected", NULL);
errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
- "message_size", "http-client", "message_compress",
+ "message_size", "message_compress", "http-client",
"connected", NULL);
errors += CHECK_STACK("chttp2", nullptr, GRPC_SERVER_CHANNEL, "server",
- "message_size", "deadline", "http-server",
- "message_compress", "connected", NULL);
+ "deadline", "message_size", "message_compress",
+ "http-server", "connected", NULL);
errors += CHECK_STACK(nullptr, nullptr, GRPC_CLIENT_CHANNEL, "client-channel",
NULL);
diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc
index eb052119ca..533703a2be 100644
--- a/test/core/end2end/tests/channelz.cc
+++ b/test/core/end2end/tests/channelz.cc
@@ -209,27 +209,27 @@ static void test_channelz(grpc_end2end_test_config config) {
grpc_channel_get_channelz_node(f.client);
GPR_ASSERT(channelz_channel != nullptr);
- char* json = channelz_channel->RenderJSON();
+ char* json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
- GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"0\""));
- GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
- GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"0\""));
+ // nothing is present yet
+ GPR_ASSERT(nullptr == strstr(json, "\"callsStarted\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"callsFailed\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"callsSucceeded\""));
gpr_free(json);
// one successful request
run_one_request(config, f, true);
- json = channelz_channel->RenderJSON();
+ json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\""));
- GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
gpr_free(json);
// one failed request
run_one_request(config, f, false);
- json = channelz_channel->RenderJSON();
+ json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
gpr_log(GPR_INFO, "%s", json);
GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
@@ -264,7 +264,7 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) {
grpc_channel_get_channelz_node(f.client);
GPR_ASSERT(channelz_channel != nullptr);
- char* json = channelz_channel->RenderJSON();
+ char* json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
gpr_log(GPR_INFO, "%s", json);
GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
diff --git a/test/core/end2end/tests/filter_call_init_fails.cc b/test/core/end2end/tests/filter_call_init_fails.cc
index ab96879fe4..07e1421446 100644
--- a/test/core/end2end/tests/filter_call_init_fails.cc
+++ b/test/core/end2end/tests/filter_call_init_fails.cc
@@ -438,7 +438,6 @@ static bool maybe_add_server_channel_filter(grpc_channel_stack_builder* builder,
// must be the last one. So we add it right before the last one.
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_last(builder);
- GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
const bool retval = grpc_channel_stack_builder_add_filter_before(
it, &test_filter, nullptr, nullptr);
grpc_channel_stack_builder_iterator_destroy(it);
@@ -457,7 +456,6 @@ static bool maybe_add_client_channel_filter(grpc_channel_stack_builder* builder,
// must be the last one. So we add it right before the last one.
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_last(builder);
- GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
const bool retval = grpc_channel_stack_builder_add_filter_before(
it, &test_filter, nullptr, nullptr);
grpc_channel_stack_builder_iterator_destroy(it);
@@ -476,7 +474,6 @@ static bool maybe_add_client_subchannel_filter(
// must be the last one. So we add it right before the last one.
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_last(builder);
- GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
const bool retval = grpc_channel_stack_builder_add_filter_before(
it, &test_filter, nullptr, nullptr);
grpc_channel_stack_builder_iterator_destroy(it);
@@ -487,13 +484,17 @@ static bool maybe_add_client_subchannel_filter(
}
static void init_plugin(void) {
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
+ grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
maybe_add_server_channel_filter, nullptr);
- grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
+ grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
maybe_add_client_channel_filter, nullptr);
- grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+ grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
maybe_add_client_subchannel_filter, nullptr);
- grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+ grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
maybe_add_client_channel_filter, nullptr);
}
diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc
index a7f4268803..891c1b8c1f 100644
--- a/test/core/end2end/tests/filter_causes_close.cc
+++ b/test/core/end2end/tests/filter_causes_close.cc
@@ -261,8 +261,9 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
}
static void init_plugin(void) {
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter,
- nullptr);
+ grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ maybe_add_filter, nullptr);
}
static void destroy_plugin(void) {}
diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc
index a89db7b094..02a4d07927 100644
--- a/test/core/end2end/tests/filter_latency.cc
+++ b/test/core/end2end/tests/filter_latency.cc
@@ -314,7 +314,6 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
// must be the last one. So we add it right before the last one.
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_last(builder);
- GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
const bool retval = grpc_channel_stack_builder_add_filter_before(
it, filter, nullptr, nullptr);
grpc_channel_stack_builder_iterator_destroy(it);
@@ -326,15 +325,15 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
static void init_plugin(void) {
gpr_mu_init(&g_mu);
- grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_client_filter);
- grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_client_filter);
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_server_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter,
+ (void*)&test_client_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ maybe_add_filter, (void*)&test_client_filter);
+ grpc_channel_init_register_stage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter,
+ (void*)&test_server_filter);
}
static void destroy_plugin(void) { gpr_mu_destroy(&g_mu); }
diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc
index ba3cbfa6d1..6ed1de15c6 100644
--- a/test/core/end2end/tests/filter_status_code.cc
+++ b/test/core/end2end/tests/filter_status_code.cc
@@ -333,7 +333,6 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) {
// So we add it right before the last one.
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_last(builder);
- GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
const bool retval = grpc_channel_stack_builder_add_filter_before(
it, filter, nullptr, nullptr);
grpc_channel_stack_builder_iterator_destroy(it);
@@ -350,15 +349,15 @@ static void init_plugin(void) {
g_client_code_recv = false;
g_server_code_recv = false;
- grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_client_filter);
- grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_client_filter);
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
- maybe_add_filter,
- (void*)&test_server_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter,
+ (void*)&test_client_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ maybe_add_filter, (void*)&test_client_filter);
+ grpc_channel_init_register_stage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter,
+ (void*)&test_server_filter);
}
static void destroy_plugin(void) {
diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc
index 41f4338f8a..e9d1eb2c76 100644
--- a/test/core/gprpp/inlined_vector_test.cc
+++ b/test/core/gprpp/inlined_vector_test.cc
@@ -17,20 +17,32 @@
*/
#include "src/core/lib/gprpp/inlined_vector.h"
+#include <grpc/support/log.h>
#include <gtest/gtest.h>
#include "src/core/lib/gprpp/memory.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
namespace testing {
+namespace {
+
+template <typename Vector>
+static void FillVector(Vector* v, int len, int start = 0) {
+ for (int i = 0; i < len; i++) {
+ v->push_back(i + start);
+ EXPECT_EQ(i + 1UL, v->size());
+ }
+ EXPECT_EQ(static_cast<size_t>(len), v->size());
+ EXPECT_LE(static_cast<size_t>(len), v->capacity());
+}
+
+} // namespace
TEST(InlinedVectorTest, CreateAndIterate) {
const int kNumElements = 9;
InlinedVector<int, 2> v;
EXPECT_TRUE(v.empty());
- for (int i = 0; i < kNumElements; ++i) {
- v.push_back(i);
- }
+ FillVector(&v, kNumElements);
EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
EXPECT_FALSE(v.empty());
for (int i = 0; i < kNumElements; ++i) {
@@ -42,9 +54,7 @@ TEST(InlinedVectorTest, CreateAndIterate) {
TEST(InlinedVectorTest, ValuesAreInlined) {
const int kNumElements = 5;
InlinedVector<int, 10> v;
- for (int i = 0; i < kNumElements; ++i) {
- v.push_back(i);
- }
+ FillVector(&v, kNumElements);
EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
for (int i = 0; i < kNumElements; ++i) {
EXPECT_EQ(i, v[i]);
@@ -71,19 +81,13 @@ TEST(InlinedVectorTest, ClearAndRepopulate) {
const int kNumElements = 10;
InlinedVector<int, 5> v;
EXPECT_EQ(0UL, v.size());
- for (int i = 0; i < kNumElements; ++i) {
- v.push_back(i);
- EXPECT_EQ(i + 1UL, v.size());
- }
+ FillVector(&v, kNumElements);
for (int i = 0; i < kNumElements; ++i) {
EXPECT_EQ(i, v[i]);
}
v.clear();
EXPECT_EQ(0UL, v.size());
- for (int i = 0; i < kNumElements; ++i) {
- v.push_back(kNumElements + i);
- EXPECT_EQ(i + 1UL, v.size());
- }
+ FillVector(&v, kNumElements, kNumElements);
for (int i = 0; i < kNumElements; ++i) {
EXPECT_EQ(kNumElements + i, v[i]);
}
@@ -93,10 +97,7 @@ TEST(InlinedVectorTest, ConstIndexOperator) {
constexpr int kNumElements = 10;
InlinedVector<int, 5> v;
EXPECT_EQ(0UL, v.size());
- for (int i = 0; i < kNumElements; ++i) {
- v.push_back(i);
- EXPECT_EQ(i + 1UL, v.size());
- }
+ FillVector(&v, kNumElements);
// The following lambda function is exceptionally allowed to use an anonymous
// capture due to the erroneous behavior of the MSVC compiler, that refuses to
// capture the kNumElements constexpr, something allowed by the standard.
@@ -108,6 +109,161 @@ TEST(InlinedVectorTest, ConstIndexOperator) {
const_func(v);
}
+// the following constants and typedefs are used for copy/move
+// construction/assignment
+const size_t kInlinedLength = 8;
+typedef InlinedVector<int, kInlinedLength> IntVec8;
+const size_t kInlinedFillSize = kInlinedLength - 1;
+const size_t kAllocatedFillSize = kInlinedLength + 1;
+
+TEST(InlinedVectorTest, CopyConstructerInlined) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 copy_constructed(original);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_constructed[i]);
+ }
+}
+
+TEST(InlinedVectorTest, CopyConstructerAllocated) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 copy_constructed(original);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_constructed[i]);
+ }
+}
+
+TEST(InlinedVectorTest, CopyAssignementInlinedInlined) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 copy_assigned;
+ FillVector(&copy_assigned, kInlinedFillSize, 99);
+ copy_assigned = original;
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_assigned[i]);
+ }
+}
+
+TEST(InlinedVectorTest, CopyAssignementInlinedAllocated) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 copy_assigned;
+ FillVector(&copy_assigned, kAllocatedFillSize, 99);
+ copy_assigned = original;
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_assigned[i]);
+ }
+}
+
+TEST(InlinedVectorTest, CopyAssignementAllocatedInlined) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 copy_assigned;
+ FillVector(&copy_assigned, kInlinedFillSize, 99);
+ copy_assigned = original;
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_assigned[i]);
+ }
+}
+
+TEST(InlinedVectorTest, CopyAssignementAllocatedAllocated) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 copy_assigned;
+ FillVector(&copy_assigned, kAllocatedFillSize, 99);
+ copy_assigned = original;
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], copy_assigned[i]);
+ }
+}
+
+TEST(InlinedVectorTest, MoveConstructorInlined) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ IntVec8 move_constructed(std::move(tmp));
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_constructed[i]);
+ }
+ // original data was inlined so it should have been copied, not moved.
+ EXPECT_NE(move_constructed.data(), old_data);
+}
+
+TEST(InlinedVectorTest, MoveConstructorAllocated) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ IntVec8 move_constructed(std::move(tmp));
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_constructed[i]);
+ }
+ // original data was allocated, so it should been moved, not copied
+ EXPECT_EQ(move_constructed.data(), old_data);
+}
+
+TEST(InlinedVectorTest, MoveAssignmentInlinedInlined) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 move_assigned;
+ FillVector(&move_assigned, kInlinedFillSize, 99); // Add dummy elements
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ move_assigned = std::move(tmp);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_assigned[i]);
+ }
+ // original data was inlined so it should have been copied, not moved.
+ EXPECT_NE(move_assigned.data(), old_data);
+}
+
+TEST(InlinedVectorTest, MoveAssignmentInlinedAllocated) {
+ IntVec8 original;
+ FillVector(&original, kInlinedFillSize);
+ IntVec8 move_assigned;
+ FillVector(&move_assigned, kAllocatedFillSize, 99); // Add dummy elements
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ move_assigned = std::move(tmp);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_assigned[i]);
+ }
+ // original data was inlined so it should have been copied, not moved.
+ EXPECT_NE(move_assigned.data(), old_data);
+}
+
+TEST(InlinedVectorTest, MoveAssignmentAllocatedInlined) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 move_assigned;
+ FillVector(&move_assigned, kInlinedFillSize, 99); // Add dummy elements
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ move_assigned = std::move(tmp);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_assigned[i]);
+ }
+ // original data was allocated so it should have been moved, not copied.
+ EXPECT_EQ(move_assigned.data(), old_data);
+}
+
+TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) {
+ IntVec8 original;
+ FillVector(&original, kAllocatedFillSize);
+ IntVec8 move_assigned;
+ FillVector(&move_assigned, kAllocatedFillSize, 99); // Add dummy elements
+ IntVec8 tmp(original);
+ auto* old_data = tmp.data();
+ move_assigned = std::move(tmp);
+ for (size_t i = 0; i < original.size(); ++i) {
+ EXPECT_EQ(original[i], move_assigned[i]);
+ }
+ // original data was allocated so it should have been moved, not copied.
+ EXPECT_EQ(move_assigned.data(), old_data);
+}
+
} // namespace testing
} // namespace grpc_core
diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc
index aa30b72282..463b5e8966 100644
--- a/test/core/gprpp/ref_counted_ptr_test.cc
+++ b/test/core/gprpp/ref_counted_ptr_test.cc
@@ -127,7 +127,7 @@ TEST(RefCountedPtr, ResetFromNonNullToNull) {
TEST(RefCountedPtr, ResetFromNullToNull) {
RefCountedPtr<Foo> foo;
EXPECT_EQ(nullptr, foo.get());
- foo.reset(nullptr);
+ foo.reset();
EXPECT_EQ(nullptr, foo.get());
}
@@ -175,6 +175,67 @@ TEST(RefCountedPtr, RefCountedWithTracing) {
foo->Unref(DEBUG_LOCATION, "foo");
}
+class BaseClass : public RefCounted<BaseClass> {
+ public:
+ BaseClass() {}
+};
+
+class Subclass : public BaseClass {
+ public:
+ Subclass() {}
+};
+
+TEST(RefCountedPtr, ConstructFromSubclass) {
+ RefCountedPtr<BaseClass> p(New<Subclass>());
+}
+
+TEST(RefCountedPtr, CopyAssignFromSubclass) {
+ RefCountedPtr<BaseClass> b;
+ EXPECT_EQ(nullptr, b.get());
+ RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
+ b = s;
+ EXPECT_NE(nullptr, b.get());
+}
+
+TEST(RefCountedPtr, MoveAssignFromSubclass) {
+ RefCountedPtr<BaseClass> b;
+ EXPECT_EQ(nullptr, b.get());
+ RefCountedPtr<Subclass> s = MakeRefCounted<Subclass>();
+ b = std::move(s);
+ EXPECT_NE(nullptr, b.get());
+}
+
+TEST(RefCountedPtr, ResetFromSubclass) {
+ RefCountedPtr<BaseClass> b;
+ EXPECT_EQ(nullptr, b.get());
+ b.reset(New<Subclass>());
+ EXPECT_NE(nullptr, b.get());
+}
+
+TEST(RefCountedPtr, EqualityWithSubclass) {
+ Subclass* s = New<Subclass>();
+ RefCountedPtr<BaseClass> b(s);
+ EXPECT_EQ(b, s);
+}
+
+void FunctionTakingBaseClass(RefCountedPtr<BaseClass> p) {
+ p.reset(); // To appease clang-tidy.
+}
+
+TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) {
+ RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
+ FunctionTakingBaseClass(p);
+}
+
+void FunctionTakingSubclass(RefCountedPtr<Subclass> p) {
+ p.reset(); // To appease clang-tidy.
+}
+
+TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) {
+ RefCountedPtr<Subclass> p = MakeRefCounted<Subclass>();
+ FunctionTakingSubclass(p);
+}
+
} // namespace
} // namespace testing
} // namespace grpc_core
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index a3d2ba2fc0..675d9e6278 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -125,6 +125,19 @@ grpc_cc_test(
)
grpc_cc_test(
+ name = "grpc_ipv6_loopback_available_test",
+ srcs = ["grpc_ipv6_loopback_available_test.cc"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
+
+grpc_cc_test(
name = "load_file_test",
srcs = ["load_file_test.cc"],
language = "C++",
diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc
new file mode 100644
index 0000000000..329aa9a851
--- /dev/null
+++ b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/lib/iomgr/port.h"
+
+// grpc_ipv6_loopback_available isn't currently available on UV.
+#ifndef GRPC_UV
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include "test/core/util/test_config.h"
+
+#ifdef GPR_WINDOWS
+#include "src/core/lib/iomgr/socket_windows.h"
+#else
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#endif
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ grpc_init();
+ // This test assumes that the ipv6 loopback is available
+ // in all environments in which grpc tests run in.
+ GPR_ASSERT(grpc_ipv6_loopback_available());
+ grpc_shutdown();
+ return 0;
+}
+
+#else
+
+int main(int argc, char** argv) { return 0; }
+
+#endif /* GRPC_UV */
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index 12aa84d93b..b7de955cdb 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -129,6 +129,27 @@ grpc_cc_test(
)
grpc_cc_test(
+ name = "linux_system_roots_test",
+ srcs = ["linux_system_roots_test.cc"],
+ data = [
+ "//test/core/security/etc:bundle.pem",
+ "//test/core/security/etc:test_roots/cert1.pem",
+ "//test/core/security/etc:test_roots/cert2.pem",
+ "//test/core/security/etc:test_roots/cert3.pem",
+ ],
+ language = "C++",
+ external_deps = [
+ "gtest",
+ ],
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
+grpc_cc_test(
name = "ssl_credentials_test",
srcs = ["ssl_credentials_test.cc"],
language = "C++",
@@ -219,9 +240,9 @@ grpc_cc_test(
deps = [
"//:gpr",
"//:grpc",
- "//:grpc_base_c",
+ "//:grpc_base_c",
"//:grpc_secure",
- "//:tsi",
+ "//:tsi",
"//:tsi_interface",
"//test/core/util:gpr_test_util",
],
diff --git a/test/core/security/check_gcp_environment_linux_test.cc b/test/core/security/check_gcp_environment_linux_test.cc
index 3acd5b6ae4..b01471abd3 100644
--- a/test/core/security/check_gcp_environment_linux_test.cc
+++ b/test/core/security/check_gcp_environment_linux_test.cc
@@ -69,6 +69,7 @@ static void test_gcp_environment_check_failure() {
GPR_ASSERT(!check_bios_data_linux_test("Amazon"));
GPR_ASSERT(!check_bios_data_linux_test("Google-Chrome\t\t"));
GPR_ASSERT(!check_bios_data_linux_test("Amazon"));
+ GPR_ASSERT(!check_bios_data_linux_test("\n"));
}
int main(int argc, char** argv) {
diff --git a/test/core/security/etc/BUILD b/test/core/security/etc/BUILD
new file mode 100644
index 0000000000..2c6ab64a3b
--- /dev/null
+++ b/test/core/security/etc/BUILD
@@ -0,0 +1,22 @@
+# 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
+
+exports_files([
+ "bundle.pem",
+ "test_roots/cert1.pem",
+ "test_roots/cert2.pem",
+ "test_roots/cert3.pem",
+])
diff --git a/test/core/security/etc/README b/test/core/security/etc/README
new file mode 100644
index 0000000000..6ba4382586
--- /dev/null
+++ b/test/core/security/etc/README
@@ -0,0 +1,2 @@
+These files are manual copies of a pem cert from the /etc/ssl/certs/ directory.
+They serve only as dummy certificate test files.
diff --git a/test/core/security/etc/bundle.pem b/test/core/security/etc/bundle.pem
new file mode 100644
index 0000000000..07d7672f83
--- /dev/null
+++ b/test/core/security/etc/bundle.pem
@@ -0,0 +1,63 @@
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/test/core/security/etc/test_roots/cert1.pem b/test/core/security/etc/test_roots/cert1.pem
new file mode 100644
index 0000000000..988cc68aac
--- /dev/null
+++ b/test/core/security/etc/test_roots/cert1.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/test/core/security/etc/test_roots/cert2.pem b/test/core/security/etc/test_roots/cert2.pem
new file mode 100644
index 0000000000..988cc68aac
--- /dev/null
+++ b/test/core/security/etc/test_roots/cert2.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/test/core/security/etc/test_roots/cert3.pem b/test/core/security/etc/test_roots/cert3.pem
new file mode 100644
index 0000000000..988cc68aac
--- /dev/null
+++ b/test/core/security/etc/test_roots/cert3.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/test/core/security/linux_system_roots_test.cc b/test/core/security/linux_system_roots_test.cc
new file mode 100644
index 0000000000..fce9c8dcc5
--- /dev/null
+++ b/test/core/security/linux_system_roots_test.cc
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+#include <stdio.h>
+
+#ifdef GPR_LINUX
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/tmpfile.h"
+#include "src/core/lib/iomgr/load_file.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/security_connector/load_system_roots.h"
+#include "src/core/lib/security/security_connector/load_system_roots_linux.h"
+#include "src/core/lib/security/security_connector/security_connector.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/tsi/ssl_transport_security.h"
+#include "src/core/tsi/transport_security.h"
+#include "test/core/util/test_config.h"
+
+#include "gtest/gtest.h"
+
+#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR
+#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS"
+#endif
+
+namespace grpc {
+namespace {
+
+TEST(AbsoluteFilePathTest, ConcatenatesCorrectly) {
+ const char* directory = "nonexistent/test/directory";
+ const char* filename = "doesnotexist.txt";
+ char result_path[MAXPATHLEN];
+ grpc_core::GetAbsoluteFilePath(directory, filename, result_path);
+ EXPECT_STREQ(result_path, "nonexistent/test/directory/doesnotexist.txt");
+}
+
+TEST(CreateRootCertsBundleTest, ReturnsEmpty) {
+ // Test that CreateRootCertsBundle returns an empty slice for null or
+ // nonexistent cert directories.
+ grpc_slice result_slice = grpc_core::CreateRootCertsBundle(nullptr);
+ EXPECT_TRUE(GRPC_SLICE_IS_EMPTY(result_slice));
+ grpc_slice_unref(result_slice);
+ result_slice = grpc_core::CreateRootCertsBundle("does/not/exist");
+ EXPECT_TRUE(GRPC_SLICE_IS_EMPTY(result_slice));
+ grpc_slice_unref(result_slice);
+}
+
+TEST(CreateRootCertsBundleTest, BundlesCorrectly) {
+ gpr_setenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR, "true");
+ // Test that CreateRootCertsBundle returns a correct slice.
+ grpc_slice roots_bundle = grpc_empty_slice();
+ GRPC_LOG_IF_ERROR(
+ "load_file",
+ grpc_load_file("test/core/security/etc/bundle.pem", 1, &roots_bundle));
+ // result_slice should have the same content as roots_bundle.
+ grpc_slice result_slice =
+ grpc_core::CreateRootCertsBundle("test/core/security/etc/test_roots");
+ char* result_str = grpc_slice_to_c_string(result_slice);
+ char* bundle_str = grpc_slice_to_c_string(roots_bundle);
+ EXPECT_STREQ(result_str, bundle_str);
+ // Clean up.
+ unsetenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR);
+ gpr_free(result_str);
+ gpr_free(bundle_str);
+ grpc_slice_unref(roots_bundle);
+ grpc_slice_unref(result_slice);
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#else
+int main() {
+ printf("*** WARNING: this test is only supported on Linux systems ***\n");
+ return 0;
+}
+#endif // GPR_LINUX
diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc
index e4c3ace6b4..82d77eef8b 100644
--- a/test/core/security/security_connector_test.cc
+++ b/test/core/security/security_connector_test.cc
@@ -363,7 +363,7 @@ static void test_ipv6_address_san(void) {
namespace grpc_core {
namespace {
-class TestDefafaultSllRootStore : public DefaultSslRootStore {
+class TestDefaultSslRootStore : public DefaultSslRootStore {
public:
static grpc_slice ComputePemRootCertsForTesting() {
return ComputePemRootCerts();
@@ -389,7 +389,7 @@ static void test_default_ssl_roots(void) {
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
grpc_set_ssl_roots_override_callback(override_roots_success);
grpc_slice roots =
- grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
+ grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
char* roots_contents = grpc_slice_to_c_string(roots);
grpc_slice_unref(roots);
GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
@@ -398,7 +398,7 @@ static void test_default_ssl_roots(void) {
/* Now let's set the env var: We should get the contents pointed value
instead. */
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path);
- roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
+ roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
roots_contents = grpc_slice_to_c_string(roots);
grpc_slice_unref(roots);
GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
@@ -407,7 +407,7 @@ static void test_default_ssl_roots(void) {
/* Now reset the env var. We should fall back to the value overridden using
the api. */
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
- roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
+ roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
roots_contents = grpc_slice_to_c_string(roots);
grpc_slice_unref(roots);
GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
@@ -416,10 +416,10 @@ static void test_default_ssl_roots(void) {
/* Now setup a permanent failure for the overridden roots and we should get
an empty slice. */
grpc_set_ssl_roots_override_callback(override_roots_permanent_failure);
- roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
+ roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots));
const tsi_ssl_root_certs_store* root_store =
- grpc_core::TestDefafaultSllRootStore::GetRootStore();
+ grpc_core::TestDefaultSslRootStore::GetRootStore();
GPR_ASSERT(root_store == nullptr);
/* Cleanup. */
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 9a79b468dd..7b3e875cf0 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -104,6 +104,7 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_census_call_get_context);
printf("%lx", (unsigned long) grpc_channel_get_target);
printf("%lx", (unsigned long) grpc_channel_get_info);
+ printf("%lx", (unsigned long) grpc_channel_reset_connect_backoff);
printf("%lx", (unsigned long) grpc_insecure_channel_create);
printf("%lx", (unsigned long) grpc_lame_client_channel_create);
printf("%lx", (unsigned long) grpc_channel_destroy);
@@ -131,6 +132,8 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_resource_quota_unref);
printf("%lx", (unsigned long) grpc_resource_quota_resize);
printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable);
+ printf("%lx", (unsigned long) grpc_channelz_get_top_channels);
+ printf("%lx", (unsigned long) grpc_channelz_get_channel);
printf("%lx", (unsigned long) grpc_auth_property_iterator_next);
printf("%lx", (unsigned long) grpc_auth_context_property_iterator);
printf("%lx", (unsigned long) grpc_auth_context_peer_identity);
diff --git a/test/cpp/common/channel_filter_test.cc b/test/cpp/common/channel_filter_test.cc
index 7bdd53f9e7..9b603ca5b4 100644
--- a/test/cpp/common/channel_filter_test.cc
+++ b/test/cpp/common/channel_filter_test.cc
@@ -50,7 +50,8 @@ class MyCallData : public CallData {
// C-core, we don't accidentally break the C++ filter API.
TEST(ChannelFilterTest, RegisterChannelFilter) {
grpc::RegisterChannelFilter<MyChannelData, MyCallData>(
- "myfilter", GRPC_CLIENT_CHANNEL, INT_MAX, nullptr);
+ "myfilter", GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW, true,
+ nullptr);
}
// TODO(roth): When we have time, add tests for all methods of the
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index 95bb7ed229..75dec56a60 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -120,6 +120,27 @@ grpc_cc_library(
)
grpc_cc_test(
+ name = "channelz_service_test",
+ srcs = ["channelz_service_test.cc"],
+ external_deps = [
+ "gtest",
+ ],
+ deps = [
+ ":test_service_impl",
+ "//:gpr",
+ "//:grpc",
+ "//:grpc++",
+ "//:grpcpp_channelz",
+ "//src/proto/grpc/channelz:channelz_proto",
+ "//src/proto/grpc/testing:echo_messages_proto",
+ "//src/proto/grpc/testing:echo_proto",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ "//test/cpp/util:test_util",
+ ],
+)
+
+grpc_cc_test(
name = "server_early_return_test",
srcs = ["server_early_return_test.cc"],
external_deps = [
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 3d31c9d810..c9246f0806 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -1709,7 +1709,7 @@ TEST_P(AsyncEnd2endServerTryCancelTest, ServerBidiStreamingTryCancelAfter) {
}
std::vector<TestScenario> CreateTestScenarios(bool test_secure,
- int test_big_limit) {
+ bool test_message_size_limit) {
std::vector<TestScenario> scenarios;
std::vector<grpc::string> credentials_types;
std::vector<grpc::string> messages;
@@ -1731,13 +1731,18 @@ std::vector<TestScenario> CreateTestScenarios(bool test_secure,
GPR_ASSERT(!credentials_types.empty());
messages.push_back("Hello");
- for (int sz = 1; sz <= test_big_limit; sz *= 32) {
- grpc::string big_msg;
- for (int i = 0; i < sz * 1024; i++) {
- char c = 'a' + (i % 26);
- big_msg += c;
+ if (test_message_size_limit) {
+ for (size_t k = 1; k < GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH / 1024;
+ k *= 32) {
+ grpc::string big_msg;
+ for (size_t i = 0; i < k * 1024; ++i) {
+ char c = 'a' + (i % 26);
+ big_msg += c;
+ }
+ messages.push_back(big_msg);
}
- messages.push_back(big_msg);
+ messages.push_back(
+ grpc::string(GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH - 10, 'a'));
}
// TODO (sreek) Renable tests with health check service after the issue
@@ -1758,10 +1763,10 @@ std::vector<TestScenario> CreateTestScenarios(bool test_secure,
}
INSTANTIATE_TEST_CASE_P(AsyncEnd2end, AsyncEnd2endTest,
- ::testing::ValuesIn(CreateTestScenarios(true, 1024)));
+ ::testing::ValuesIn(CreateTestScenarios(true, true)));
INSTANTIATE_TEST_CASE_P(AsyncEnd2endServerTryCancel,
AsyncEnd2endServerTryCancelTest,
- ::testing::ValuesIn(CreateTestScenarios(false, 0)));
+ ::testing::ValuesIn(CreateTestScenarios(false, false)));
} // namespace
} // namespace testing
diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc
new file mode 100644
index 0000000000..933e4a1ff6
--- /dev/null
+++ b/test/cpp/end2end/channelz_service_test.cc
@@ -0,0 +1,352 @@
+/*
+ *
+ * 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 <grpc/support/port_platform.h>
+
+#include <grpc/grpc.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/server_context.h>
+
+#include <grpcpp/ext/channelz_service_plugin.h>
+#include "src/proto/grpc/channelz/channelz.grpc.pb.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/test_service_impl.h"
+
+#include <gtest/gtest.h>
+
+using grpc::channelz::v1::GetChannelRequest;
+using grpc::channelz::v1::GetChannelResponse;
+using grpc::channelz::v1::GetTopChannelsRequest;
+using grpc::channelz::v1::GetTopChannelsResponse;
+
+namespace grpc {
+namespace testing {
+namespace {
+
+// Proxy service supports N backends. Sends RPC to backend dictated by
+// request->backend_channel_idx().
+class Proxy : public ::grpc::testing::EchoTestService::Service {
+ public:
+ Proxy() {}
+
+ void AddChannelToBackend(const std::shared_ptr<Channel>& channel) {
+ stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel));
+ }
+
+ Status Echo(ServerContext* server_context, const EchoRequest* request,
+ EchoResponse* response) override {
+ std::unique_ptr<ClientContext> client_context =
+ ClientContext::FromServerContext(*server_context);
+ size_t idx = request->param().backend_channel_idx();
+ GPR_ASSERT(idx < stubs_.size());
+ return stubs_[idx]->Echo(client_context.get(), *request, response);
+ }
+
+ private:
+ std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_;
+};
+
+} // namespace
+
+class ChannelzServerTest : public ::testing::Test {
+ public:
+ ChannelzServerTest() {}
+
+ void SetUp() override {
+ // ensure channel server is brought up on all severs we build.
+ ::grpc::channelz::experimental::InitChannelzService();
+
+ // We set up a proxy server with channelz enabled.
+ proxy_port_ = grpc_pick_unused_port_or_die();
+ ServerBuilder proxy_builder;
+ grpc::string proxy_server_address = "localhost:" + to_string(proxy_port_);
+ proxy_builder.AddListeningPort(proxy_server_address,
+ InsecureServerCredentials());
+ // forces channelz and channel tracing to be enabled.
+ proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1);
+ proxy_builder.AddChannelArgument(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE,
+ 10);
+ proxy_builder.RegisterService(&proxy_service_);
+ proxy_server_ = proxy_builder.BuildAndStart();
+ }
+
+ // Sets the proxy up to have an arbitrary number of backends.
+ void ConfigureProxy(size_t num_backends) {
+ backends_.resize(num_backends);
+ for (size_t i = 0; i < num_backends; ++i) {
+ // create a new backend.
+ backends_[i].port = grpc_pick_unused_port_or_die();
+ ServerBuilder backend_builder;
+ grpc::string backend_server_address =
+ "localhost:" + to_string(backends_[i].port);
+ backend_builder.AddListeningPort(backend_server_address,
+ InsecureServerCredentials());
+ backends_[i].service.reset(new TestServiceImpl);
+ // ensure that the backend itself has channelz disabled.
+ backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0);
+ backend_builder.RegisterService(backends_[i].service.get());
+ backends_[i].server = backend_builder.BuildAndStart();
+ // set up a channel to the backend. We ensure that this channel has
+ // channelz enabled since these channels (proxy outbound to backends)
+ // are the ones that our test will actually be validating.
+ ChannelArguments args;
+ args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1);
+ args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE, 10);
+ std::shared_ptr<Channel> channel_to_backend = CreateCustomChannel(
+ backend_server_address, InsecureChannelCredentials(), args);
+ proxy_service_.AddChannelToBackend(channel_to_backend);
+ }
+ }
+
+ void ResetStubs() {
+ string target = "dns:localhost:" + to_string(proxy_port_);
+ ChannelArguments args;
+ // disable channelz. We only want to focus on proxy to backend outbound.
+ args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0);
+ std::shared_ptr<Channel> channel =
+ CreateCustomChannel(target, InsecureChannelCredentials(), args);
+ channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel);
+ echo_stub_ = grpc::testing::EchoTestService::NewStub(channel);
+ }
+
+ void SendSuccessfulEcho(int channel_idx) {
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello channelz");
+ request.mutable_param()->set_backend_channel_idx(channel_idx);
+ ClientContext context;
+ Status s = echo_stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+ }
+
+ void SendFailedEcho(int channel_idx) {
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello channelz");
+ request.mutable_param()->set_backend_channel_idx(channel_idx);
+ auto* error = request.mutable_param()->mutable_expected_error();
+ error->set_code(13); // INTERNAL
+ error->set_error_message("error");
+ ClientContext context;
+ Status s = echo_stub_->Echo(&context, request, &response);
+ EXPECT_FALSE(s.ok());
+ }
+
+ static string to_string(const int number) {
+ std::stringstream strs;
+ strs << number;
+ return strs.str();
+ }
+
+ protected:
+ // package of data needed for each backend server.
+ struct BackendData {
+ std::unique_ptr<Server> server;
+ int port;
+ std::unique_ptr<TestServiceImpl> service;
+ };
+
+ std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_;
+
+ // proxy server to ping with channelz requests.
+ std::unique_ptr<Server> proxy_server_;
+ int proxy_port_;
+ Proxy proxy_service_;
+
+ // backends. All implement the echo service.
+ std::vector<BackendData> backends_;
+};
+
+TEST_F(ChannelzServerTest, BasicTest) {
+ ResetStubs();
+ ConfigureProxy(1);
+ GetTopChannelsRequest request;
+ GetTopChannelsResponse response;
+ request.set_start_channel_id(0);
+ ClientContext context;
+ Status s = channelz_stub_->GetTopChannels(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel_size(), 1);
+}
+
+TEST_F(ChannelzServerTest, HighStartId) {
+ ResetStubs();
+ ConfigureProxy(1);
+ GetTopChannelsRequest request;
+ GetTopChannelsResponse response;
+ request.set_start_channel_id(10000);
+ ClientContext context;
+ Status s = channelz_stub_->GetTopChannels(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel_size(), 0);
+}
+
+TEST_F(ChannelzServerTest, SuccessfulRequestTest) {
+ ResetStubs();
+ ConfigureProxy(1);
+ SendSuccessfulEcho(0);
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(1);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(), 1);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), 1);
+ EXPECT_EQ(response.channel().data().calls_failed(), 0);
+}
+
+TEST_F(ChannelzServerTest, FailedRequestTest) {
+ ResetStubs();
+ ConfigureProxy(1);
+ SendFailedEcho(0);
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(1);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(), 1);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
+ EXPECT_EQ(response.channel().data().calls_failed(), 1);
+}
+
+TEST_F(ChannelzServerTest, ManyRequestsTest) {
+ ResetStubs();
+ ConfigureProxy(1);
+ // send some RPCs
+ const int kNumSuccess = 10;
+ const int kNumFailed = 11;
+ for (int i = 0; i < kNumSuccess; ++i) {
+ SendSuccessfulEcho(0);
+ }
+ for (int i = 0; i < kNumFailed; ++i) {
+ SendFailedEcho(0);
+ }
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(1);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(),
+ kNumSuccess + kNumFailed);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
+ EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
+}
+
+TEST_F(ChannelzServerTest, ManyChannels) {
+ ResetStubs();
+ const int kNumChannels = 4;
+ ConfigureProxy(kNumChannels);
+ GetTopChannelsRequest request;
+ GetTopChannelsResponse response;
+ request.set_start_channel_id(0);
+ ClientContext context;
+ Status s = channelz_stub_->GetTopChannels(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel_size(), kNumChannels);
+}
+
+TEST_F(ChannelzServerTest, ManyRequestsManyChannels) {
+ ResetStubs();
+ const int kNumChannels = 4;
+ ConfigureProxy(kNumChannels);
+ const int kNumSuccess = 10;
+ const int kNumFailed = 11;
+ for (int i = 0; i < kNumSuccess; ++i) {
+ SendSuccessfulEcho(0);
+ SendSuccessfulEcho(2);
+ }
+ for (int i = 0; i < kNumFailed; ++i) {
+ SendFailedEcho(1);
+ SendFailedEcho(2);
+ }
+
+ // the first channel saw only successes
+ {
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(1);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
+ EXPECT_EQ(response.channel().data().calls_failed(), 0);
+ }
+
+ // the second channel saw only failures
+ {
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(2);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(), kNumFailed);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
+ EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
+ }
+
+ // the third channel saw both
+ {
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(3);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(),
+ kNumSuccess + kNumFailed);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
+ EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
+ }
+
+ // the fourth channel saw nothing
+ {
+ GetChannelRequest request;
+ GetChannelResponse response;
+ request.set_channel_id(4);
+ ClientContext context;
+ Status s = channelz_stub_->GetChannel(&context, request, &response);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.channel().data().calls_started(), 0);
+ EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
+ EXPECT_EQ(response.channel().data().calls_failed(), 0);
+ }
+}
+
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc
index 8896fc6cae..7fe0da8aae 100644
--- a/test/cpp/end2end/client_lb_end2end_test.cc
+++ b/test/cpp/end2end/client_lb_end2end_test.cc
@@ -279,9 +279,14 @@ class ClientLbEnd2endTest : public ::testing::Test {
void WaitForServer(
const std::unique_ptr<grpc::testing::EchoTestService::Stub>& stub,
- size_t server_idx, const grpc_core::DebugLocation& location) {
+ size_t server_idx, const grpc_core::DebugLocation& location,
+ bool ignore_failure = false) {
do {
- CheckRpcSendOk(stub, location);
+ if (ignore_failure) {
+ SendRpc(stub);
+ } else {
+ CheckRpcSendOk(stub, location);
+ }
} while (servers_[server_idx]->service_.request_count() == 0);
ResetCounters();
}
@@ -403,6 +408,36 @@ TEST_F(ClientLbEnd2endTest, PickFirstBackOffMinReconnect) {
gpr_atm_rel_store(&g_connection_delay_ms, 0);
}
+TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) {
+ ChannelArguments args;
+ constexpr int kInitialBackOffMs = 1000;
+ args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs);
+ const std::vector<int> ports = {grpc_pick_unused_port_or_die()};
+ auto channel = BuildChannel("pick_first", args);
+ auto stub = BuildStub(channel);
+ SetNextResolution(ports);
+ // The channel won't become connected (there's no server).
+ EXPECT_FALSE(
+ channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10)));
+ // Bring up a server on the chosen port.
+ StartServers(1, ports);
+ const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC);
+ // Wait for connect, but not long enough. This proves that we're
+ // being throttled by initial backoff.
+ EXPECT_FALSE(
+ channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10)));
+ // Reset connection backoff.
+ experimental::ChannelResetConnectionBackoff(channel.get());
+ // Wait for connect. Should happen ~immediately.
+ EXPECT_TRUE(
+ channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10)));
+ const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC);
+ const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0));
+ gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms);
+ // We should have waited less than kInitialBackOffMs.
+ EXPECT_LT(waited_ms, kInitialBackOffMs);
+}
+
TEST_F(ClientLbEnd2endTest, PickFirstUpdates) {
// Start servers and send one RPC per server.
const int kNumServers = 3;
@@ -507,6 +542,37 @@ TEST_F(ClientLbEnd2endTest, PickFirstManyUpdates) {
EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName());
}
+TEST_F(ClientLbEnd2endTest, PickFirstReresolutionNoSelected) {
+ // Prepare the ports for up servers and down servers.
+ const int kNumServers = 3;
+ const int kNumAliveServers = 1;
+ StartServers(kNumAliveServers);
+ std::vector<int> alive_ports, dead_ports;
+ for (size_t i = 0; i < kNumServers; ++i) {
+ if (i < kNumAliveServers) {
+ alive_ports.emplace_back(servers_[i]->port_);
+ } else {
+ dead_ports.emplace_back(grpc_pick_unused_port_or_die());
+ }
+ }
+ auto channel = BuildChannel("pick_first");
+ auto stub = BuildStub(channel);
+ // The initial resolution only contains dead ports. There won't be any
+ // selected subchannel. Re-resolution will return the same result.
+ SetNextResolution(dead_ports);
+ gpr_log(GPR_INFO, "****** INITIAL RESOLUTION SET *******");
+ for (size_t i = 0; i < 10; ++i) CheckRpcSendFailure(stub);
+ // Set a re-resolution result that contains reachable ports, so that the
+ // pick_first LB policy can recover soon.
+ SetNextResolutionUponError(alive_ports);
+ gpr_log(GPR_INFO, "****** RE-RESOLUTION SET *******");
+ WaitForServer(stub, 0, DEBUG_LOCATION, true /* ignore_failure */);
+ CheckRpcSendOk(stub, DEBUG_LOCATION);
+ EXPECT_EQ(servers_[0]->service_.request_count(), 1);
+ // Check LB policy name for the channel.
+ EXPECT_EQ("pick_first", channel->GetLoadBalancingPolicyName());
+}
+
TEST_F(ClientLbEnd2endTest, RoundRobin) {
// Start servers and send one RPC per server.
const int kNumServers = 3;
diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc
index 88f8f380c3..a8022823b1 100644
--- a/test/cpp/end2end/filter_end2end_test.cc
+++ b/test/cpp/end2end/filter_end2end_test.cc
@@ -323,7 +323,8 @@ TEST_F(FilterEnd2endTest, SimpleBidiStreaming) {
void RegisterFilter() {
grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>(
- "test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+ "test-filter", GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW, true,
+ nullptr);
}
} // namespace
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 3eb155ef95..7bcf23c0eb 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -46,6 +46,7 @@ DEFINE_string(
"all : all test cases;\n"
"cancel_after_begin : cancel stream after starting it;\n"
"cancel_after_first_response: cancel on first response;\n"
+ "channel_soak: sends 'soak_iterations' rpcs, rebuilds channel each time;\n"
"client_compressed_streaming : compressed request streaming with "
"client_compressed_unary : single compressed request;\n"
"client_streaming : request streaming with single response;\n"
@@ -60,6 +61,7 @@ DEFINE_string(
"per_rpc_creds: raw oauth2 access token on a single rpc;\n"
"ping_pong : full-duplex streaming;\n"
"response streaming;\n"
+ "rpc_soak: 'sends soak_iterations' large_unary rpcs;\n"
"server_compressed_streaming : single request with compressed "
"server_compressed_unary : single compressed response;\n"
"server_streaming : single request with response streaming;\n"
@@ -83,6 +85,10 @@ DEFINE_bool(do_not_abort_on_transient_failures, false,
"test is retried in case of transient failures (and currently the "
"interop tests are not retried even if this flag is set to true)");
+DEFINE_int32(soak_iterations, 1000,
+ "number of iterations to use for the two soak tests; rpc_soak and "
+ "channel_soak");
+
using grpc::testing::CreateChannelForTestCase;
using grpc::testing::GetServiceAccountJsonKey;
using grpc::testing::UpdateActions;
@@ -91,8 +97,9 @@ int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
gpr_log(GPR_INFO, "Testing these cases: %s", FLAGS_test_case.c_str());
int ret = 0;
- grpc::testing::InteropClient client(CreateChannelForTestCase(FLAGS_test_case),
- true,
+ grpc::testing::ChannelCreationFunc channel_creation_func =
+ std::bind(&CreateChannelForTestCase, FLAGS_test_case);
+ grpc::testing::InteropClient client(channel_creation_func, true,
FLAGS_do_not_abort_on_transient_failures);
std::unordered_map<grpc::string, std::function<bool()>> actions;
@@ -151,6 +158,11 @@ int main(int argc, char** argv) {
std::bind(&grpc::testing::InteropClient::DoUnimplementedService, &client);
actions["cacheable_unary"] =
std::bind(&grpc::testing::InteropClient::DoCacheableUnary, &client);
+ actions["channel_soak"] =
+ std::bind(&grpc::testing::InteropClient::DoChannelSoakTest, &client,
+ FLAGS_soak_iterations);
+ actions["rpc_soak"] = std::bind(&grpc::testing::InteropClient::DoRpcSoakTest,
+ &client, FLAGS_soak_iterations);
UpdateActions(&actions);
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 29b5a1ed6c..fb7b7bb7d0 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -88,20 +88,20 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
std::shared_ptr<CallCredentials> creds;
if (test_case == "compute_engine_creds") {
- GPR_ASSERT(FLAGS_use_tls);
- creds = GoogleComputeEngineCredentials();
- GPR_ASSERT(creds);
+ creds = FLAGS_custom_credentials_type == "google_default_credentials"
+ ? nullptr
+ : GoogleComputeEngineCredentials();
} else if (test_case == "jwt_token_creds") {
- GPR_ASSERT(FLAGS_use_tls);
grpc::string json_key = GetServiceAccountJsonKey();
std::chrono::seconds token_lifetime = std::chrono::hours(1);
- creds =
- ServiceAccountJWTAccessCredentials(json_key, token_lifetime.count());
- GPR_ASSERT(creds);
+ creds = FLAGS_custom_credentials_type == "google_default_credentials"
+ ? nullptr
+ : ServiceAccountJWTAccessCredentials(json_key,
+ token_lifetime.count());
} else if (test_case == "oauth2_auth_token") {
- grpc::string raw_token = GetOauth2AccessToken();
- creds = AccessTokenCredentials(raw_token);
- GPR_ASSERT(creds);
+ creds = FLAGS_custom_credentials_type == "google_default_credentials"
+ ? nullptr
+ : AccessTokenCredentials(GetOauth2AccessToken());
}
if (FLAGS_custom_credentials_type.empty()) {
transport_security security_type =
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index fce99a1697..b7ce90803b 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -74,13 +74,15 @@ void UnaryCompressionChecks(const InteropClientContextInspector& inspector,
}
} // namespace
-InteropClient::ServiceStub::ServiceStub(const std::shared_ptr<Channel>& channel,
- bool new_stub_every_call)
- : channel_(channel), new_stub_every_call_(new_stub_every_call) {
+InteropClient::ServiceStub::ServiceStub(
+ ChannelCreationFunc channel_creation_func, bool new_stub_every_call)
+ : channel_creation_func_(channel_creation_func),
+ channel_(channel_creation_func_()),
+ new_stub_every_call_(new_stub_every_call) {
// If new_stub_every_call is false, then this is our chance to initialize
// stub_. (see Get())
if (!new_stub_every_call) {
- stub_ = TestService::NewStub(channel);
+ stub_ = TestService::NewStub(channel_);
}
}
@@ -100,27 +102,17 @@ InteropClient::ServiceStub::GetUnimplementedServiceStub() {
return unimplemented_service_stub_.get();
}
-void InteropClient::ServiceStub::Reset(
- const std::shared_ptr<Channel>& channel) {
- channel_ = channel;
-
- // Update stub_ as well. Note: If new_stub_every_call_ is true, we can reset
- // the stub_ since the next call to Get() will create a new stub
- if (new_stub_every_call_) {
- stub_.reset();
- } else {
- stub_ = TestService::NewStub(channel);
+void InteropClient::ServiceStub::ResetChannel() {
+ channel_ = channel_creation_func_();
+ if (!new_stub_every_call_) {
+ stub_ = TestService::NewStub(channel_);
}
}
-void InteropClient::Reset(const std::shared_ptr<Channel>& channel) {
- serviceStub_.Reset(std::move(channel));
-}
-
-InteropClient::InteropClient(const std::shared_ptr<Channel>& channel,
+InteropClient::InteropClient(ChannelCreationFunc channel_creation_func,
bool new_stub_every_test_case,
bool do_not_abort_on_transient_failures)
- : serviceStub_(std::move(channel), new_stub_every_test_case),
+ : serviceStub_(channel_creation_func, new_stub_every_test_case),
do_not_abort_on_transient_failures_(do_not_abort_on_transient_failures) {}
bool InteropClient::AssertStatusOk(const Status& s,
@@ -1028,6 +1020,38 @@ bool InteropClient::DoCustomMetadata() {
return true;
}
+bool InteropClient::DoRpcSoakTest(int32_t soak_iterations) {
+ gpr_log(GPR_DEBUG, "Sending %d RPCs...", soak_iterations);
+ GPR_ASSERT(soak_iterations > 0);
+ SimpleRequest request;
+ SimpleResponse response;
+ for (int i = 0; i < soak_iterations; ++i) {
+ if (!PerformLargeUnary(&request, &response)) {
+ gpr_log(GPR_ERROR, "rpc_soak test failed on iteration %d", i);
+ return false;
+ }
+ }
+ gpr_log(GPR_DEBUG, "rpc_soak test done.");
+ return true;
+}
+
+bool InteropClient::DoChannelSoakTest(int32_t soak_iterations) {
+ gpr_log(GPR_DEBUG, "Sending %d RPCs, tearing down the channel each time...",
+ soak_iterations);
+ GPR_ASSERT(soak_iterations > 0);
+ SimpleRequest request;
+ SimpleResponse response;
+ for (int i = 0; i < soak_iterations; ++i) {
+ serviceStub_.ResetChannel();
+ if (!PerformLargeUnary(&request, &response)) {
+ gpr_log(GPR_ERROR, "channel_soak test failed on iteration %d", i);
+ return false;
+ }
+ }
+ gpr_log(GPR_DEBUG, "channel_soak test done.");
+ return true;
+}
+
bool InteropClient::DoUnimplementedService() {
gpr_log(GPR_DEBUG, "Sending a request for an unimplemented service...");
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 480eb3f4b6..e5be44d1d4 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -34,13 +34,15 @@ typedef std::function<void(const InteropClientContextInspector&,
const SimpleRequest*, const SimpleResponse*)>
CheckerFn;
+typedef std::function<std::shared_ptr<Channel>(void)> ChannelCreationFunc;
+
class InteropClient {
public:
/// If new_stub_every_test_case is true, a new TestService::Stub object is
/// created for every test case
/// If do_not_abort_on_transient_failures is true, abort() is not called in
/// case of transient failures (like connection failures)
- explicit InteropClient(const std::shared_ptr<Channel>& channel,
+ explicit InteropClient(ChannelCreationFunc channel_creation_func,
bool new_stub_every_test_case,
bool do_not_abort_on_transient_failures);
~InteropClient() {}
@@ -67,6 +69,14 @@ class InteropClient {
bool DoUnimplementedMethod();
bool DoUnimplementedService();
bool DoCacheableUnary();
+
+ // The following interop test are not yet part of the interop spec, and are
+ // not implemented cross-language. They are considered experimental for now,
+ // but at some point in the future, might be codified and implemented in all
+ // languages
+ bool DoChannelSoakTest(int32_t soak_iterations);
+ bool DoRpcSoakTest(int32_t soak_iterations);
+
// Auth tests.
// username is a string containing the user email
bool DoJwtTokenCreds(const grpc::string& username);
@@ -83,15 +93,17 @@ class InteropClient {
public:
// If new_stub_every_call = true, pointer to a new instance of
// TestServce::Stub is returned by Get() everytime it is called
- ServiceStub(const std::shared_ptr<Channel>& channel,
+ ServiceStub(ChannelCreationFunc channel_creation_func,
bool new_stub_every_call);
TestService::Stub* Get();
UnimplementedService::Stub* GetUnimplementedServiceStub();
- void Reset(const std::shared_ptr<Channel>& channel);
+ // forces channel to be recreated.
+ void ResetChannel();
private:
+ ChannelCreationFunc channel_creation_func_;
std::unique_ptr<TestService::Stub> stub_;
std::unique_ptr<UnimplementedService::Stub> unimplemented_service_stub_;
std::shared_ptr<Channel> channel_;
@@ -109,8 +121,8 @@ class InteropClient {
bool AssertStatusCode(const Status& s, StatusCode expected_code,
const grpc::string& optional_debug_string);
bool TransientFailureOrAbort();
- ServiceStub serviceStub_;
+ ServiceStub serviceStub_;
/// If true, abort() is not called for transient failures
bool do_not_abort_on_transient_failures_;
};
diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc
index 9d373c3cd9..7dc1956f78 100644
--- a/test/cpp/interop/stress_interop_client.cc
+++ b/test/cpp/interop/stress_interop_client.cc
@@ -68,13 +68,13 @@ TestCaseType WeightedRandomTestSelector::GetNextTest() const {
StressTestInteropClient::StressTestInteropClient(
int test_id, const grpc::string& server_address,
- const std::shared_ptr<Channel>& channel,
+ ChannelCreationFunc channel_creation_func,
const WeightedRandomTestSelector& test_selector, long test_duration_secs,
long sleep_duration_ms, bool do_not_abort_on_transient_failures)
: test_id_(test_id),
server_address_(server_address),
- channel_(channel),
- interop_client_(new InteropClient(channel, false,
+ channel_creation_func_(channel_creation_func),
+ interop_client_(new InteropClient(channel_creation_func_, false,
do_not_abort_on_transient_failures)),
test_selector_(test_selector),
test_duration_secs_(test_duration_secs),
diff --git a/test/cpp/interop/stress_interop_client.h b/test/cpp/interop/stress_interop_client.h
index e4fa7d0973..58680d8093 100644
--- a/test/cpp/interop/stress_interop_client.h
+++ b/test/cpp/interop/stress_interop_client.h
@@ -91,7 +91,7 @@ class WeightedRandomTestSelector {
class StressTestInteropClient {
public:
StressTestInteropClient(int test_id, const grpc::string& server_address,
- const std::shared_ptr<Channel>& channel,
+ ChannelCreationFunc channel_creation_func,
const WeightedRandomTestSelector& test_selector,
long test_duration_secs, long sleep_duration_ms,
bool do_not_abort_on_transient_failures);
@@ -105,7 +105,7 @@ class StressTestInteropClient {
int test_id_;
const grpc::string& server_address_;
- std::shared_ptr<Channel> channel_;
+ ChannelCreationFunc channel_creation_func_;
std::unique_ptr<InteropClient> interop_client_;
const WeightedRandomTestSelector& test_selector_;
long test_duration_secs_;
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 023e0c8f0b..ebbd14beba 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -283,15 +283,20 @@ int main(int argc, char** argv) {
channel_idx++) {
gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
channel_idx);
- std::shared_ptr<grpc::Channel> channel = grpc::CreateTestChannel(
+ grpc::testing::ChannelCreationFunc channel_creation_func = std::bind(
+ static_cast<std::shared_ptr<grpc::Channel> (*)(
+ const grpc::string&, const grpc::string&,
+ grpc::testing::transport_security, bool)>(
+ grpc::CreateTestChannel),
*it, FLAGS_server_host_override, security_type, !FLAGS_use_test_ca);
// Create stub(s) for each channel
for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
stub_idx++) {
clients.emplace_back(new StressTestInteropClient(
- ++thread_idx, *it, channel, test_selector, FLAGS_test_duration_secs,
- FLAGS_sleep_duration_ms, FLAGS_do_not_abort_on_transient_failures));
+ ++thread_idx, *it, channel_creation_func, test_selector,
+ FLAGS_test_duration_secs, FLAGS_sleep_duration_ms,
+ FLAGS_do_not_abort_on_transient_failures));
bool is_already_created = false;
// QpsGauge name
diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc
index a92e9e3b3e..04c300876c 100644
--- a/test/cpp/naming/address_sorting_test.cc
+++ b/test/cpp/naming/address_sorting_test.cc
@@ -24,10 +24,8 @@
#include <grpc/support/time.h>
#include <string.h>
-#include <arpa/inet.h>
#include <gflags/gflags.h>
#include <gmock/gmock.h>
-#include <sys/socket.h>
#include <sys/types.h>
#include <vector>
@@ -51,6 +49,11 @@
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
+#ifndef GPR_WINDOWS
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#endif
+
namespace {
struct TestAddress {
@@ -190,10 +193,18 @@ void VerifyLbAddrOutputs(grpc_lb_addresses* lb_addrs,
grpc_lb_addresses_destroy(lb_addrs);
}
-} // namespace
+/* We need to run each test case inside of its own
+ * isolated grpc_init/grpc_shutdown pair, so that
+ * the "address sorting source addr factory" can be
+ * restored to its default for each test case. */
+class AddressSortingTest : public ::testing::Test {
+ protected:
+ void SetUp() override { grpc_init(); }
+ void TearDown() override { grpc_shutdown(); }
+};
/* Tests for rule 1 */
-TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) {
+TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -212,7 +223,7 @@ TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) {
});
}
-TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) {
+TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) {
bool ipv4_supported = true;
bool ipv6_supported = false;
OverrideAddressSortingSourceAddrFactory(
@@ -231,7 +242,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) {
});
}
-TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) {
+TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) {
bool ipv4_supported = false;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -253,7 +264,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) {
/* Tests for rule 2 */
-TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) {
+TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -277,7 +288,7 @@ TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) {
/* Tests for rule 5 */
-TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) {
+TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -300,7 +311,7 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) {
/* Flip the input on the test above to reorder the sort function's
* comparator's inputs. */
-TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
+TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -323,8 +334,8 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
/* Tests for rule 6 */
-TEST(AddressSortingTest,
- TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) {
+TEST_F(AddressSortingTest,
+ TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -348,8 +359,8 @@ TEST(AddressSortingTest,
});
}
-TEST(AddressSortingTest,
- TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) {
+TEST_F(AddressSortingTest,
+ TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) {
bool ipv4_supported = true;
bool ipv6_supported = true;
// Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X.
@@ -377,8 +388,8 @@ TEST(AddressSortingTest,
});
}
-TEST(AddressSortingTest,
- TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) {
+TEST_F(AddressSortingTest,
+ TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -403,8 +414,8 @@ TEST(AddressSortingTest,
});
}
-TEST(AddressSortingTest,
- TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) {
+TEST_F(AddressSortingTest,
+ TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -426,7 +437,7 @@ TEST(AddressSortingTest,
});
}
-TEST(
+TEST_F(
AddressSortingTest,
TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) {
bool ipv4_supported = true;
@@ -448,8 +459,8 @@ TEST(
});
}
-TEST(AddressSortingTest,
- TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) {
+TEST_F(AddressSortingTest,
+ TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -469,19 +480,22 @@ TEST(AddressSortingTest,
});
}
-TEST(
+TEST_F(
AddressSortingTest,
TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) {
bool ipv4_supported = true;
bool ipv6_supported = true;
+ // Use embedded ipv4 addresses with leading 1's instead of zero's to be
+ // compatible with inet_ntop implementations that can display such
+ // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows.
OverrideAddressSortingSourceAddrFactory(
ipv4_supported, ipv6_supported,
{
- {"[::ffff:0.0.0.2]:443", {"[::ffff:0.0.0.3]:0", AF_INET6}},
+ {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}},
{"[1234::2]:443", {"[1234::3]:0", AF_INET6}},
});
grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({
- {"[::ffff:0.0.0.2]:443", AF_INET6},
+ {"[::ffff:1.1.1.2]:443", AF_INET6},
{"[1234::2]:443", AF_INET6},
});
grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs);
@@ -489,13 +503,13 @@ TEST(
// ::ffff:0:2 should match the v4-mapped
// precedence entry and be deprioritized.
"[1234::2]:443",
- "[::ffff:0.0.0.2]:443",
+ "[::ffff:1.1.1.2]:443",
});
}
/* Tests for rule 8 */
-TEST(AddressSortingTest, TestPrefersSmallerScope) {
+TEST_F(AddressSortingTest, TestPrefersSmallerScope) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -520,7 +534,7 @@ TEST(AddressSortingTest, TestPrefersSmallerScope) {
/* Tests for rule 9 */
-TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) {
+TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -543,8 +557,8 @@ TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) {
});
}
-TEST(AddressSortingTest,
- TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) {
+TEST_F(AddressSortingTest,
+ TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -564,7 +578,7 @@ TEST(AddressSortingTest,
});
}
-TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) {
+TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -584,7 +598,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) {
});
}
-TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) {
+TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -604,7 +618,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) {
});
}
-TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) {
+TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -628,7 +642,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) {
/* Tests for rule 10 */
-TEST(AddressSortingTest, TestStableSort) {
+TEST_F(AddressSortingTest, TestStableSort) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -648,7 +662,7 @@ TEST(AddressSortingTest, TestStableSort) {
});
}
-TEST(AddressSortingTest, TestStableSortFiveElements) {
+TEST_F(AddressSortingTest, TestStableSortFiveElements) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(
@@ -677,7 +691,7 @@ TEST(AddressSortingTest, TestStableSortFiveElements) {
});
}
-TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) {
+TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
@@ -698,7 +712,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) {
});
}
-TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) {
+TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) {
bool ipv4_supported = true;
bool ipv6_supported = true;
OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
@@ -713,7 +727,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) {
});
}
-TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) {
+TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) {
bool ipv4_supported = true;
bool ipv6_supported = true;
// Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X.
@@ -744,6 +758,78 @@ TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) {
});
}
+/* TestPrefersIpv6Loopback tests the actual "address probing" code
+ * for the current platform, without any mocks.
+ * This test relies on the assumption that the ipv6 loopback address is
+ * available in the hosts/containers that grpc C/C++ tests run on
+ * (whether ipv4 loopback is available or not, an available ipv6
+ * loopback should be preferred). */
+TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) {
+ grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({
+ {"[::1]:443", AF_INET6},
+ {"127.0.0.1:443", AF_INET},
+ });
+ grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs);
+ VerifyLbAddrOutputs(lb_addrs, {
+ "[::1]:443",
+ "127.0.0.1:443",
+ });
+}
+
+/* Flip the order of the inputs above and expect the same output order
+ * (try to rule out influence of arbitrary qsort ordering) */
+TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) {
+ grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({
+ {"127.0.0.1:443", AF_INET},
+ {"[::1]:443", AF_INET6},
+ });
+ grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs);
+ VerifyLbAddrOutputs(lb_addrs, {
+ "[::1]:443",
+ "127.0.0.1:443",
+ });
+}
+
+/* Try to rule out false positives in the above two tests in which
+ * the sorter might think that neither ipv6 or ipv4 loopback is
+ * available, but ipv6 loopback is still preferred only due
+ * to precedance table lookups. */
+TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) {
+ sockaddr_in6 ipv6_loopback;
+ memset(&ipv6_loopback, 0, sizeof(ipv6_loopback));
+ ipv6_loopback.sin6_family = AF_INET6;
+ ((char*)&ipv6_loopback.sin6_addr)[15] = 1;
+ ipv6_loopback.sin6_port = htons(443);
+ // Set up the source and destination parameters of
+ // address_sorting_get_source_addr
+ address_sorting_address sort_input_dest;
+ memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback));
+ sort_input_dest.len = sizeof(ipv6_loopback);
+ address_sorting_address source_for_sort_input_dest;
+ memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest));
+ // address_sorting_get_source_addr returns true if a source address was found
+ // for the destination address, otherwise false.
+ EXPECT_TRUE(address_sorting_get_source_addr_for_testing(
+ &sort_input_dest, &source_for_sort_input_dest));
+ // Now also check that the source address was filled in correctly.
+ EXPECT_GT(source_for_sort_input_dest.len, 0u);
+ sockaddr_in6* source_addr_output =
+ (sockaddr_in6*)source_for_sort_input_dest.addr;
+ EXPECT_EQ(source_addr_output->sin6_family, AF_INET6);
+ char* buf = static_cast<char*>(gpr_zalloc(100));
+ EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100),
+ nullptr)
+ << "inet_ntop failed. Errno: " + std::to_string(errno);
+ std::string source_addr_str(buf);
+ gpr_free(buf);
+ // This test
+ // assumes that the source address for any loopback destination is also the
+ // loopback address.
+ EXPECT_EQ(source_addr_str, "::1");
+}
+
+} // namespace
+
int main(int argc, char** argv) {
char* resolver = gpr_getenv("GRPC_DNS_RESOLVER");
if (resolver == nullptr || strlen(resolver) == 0) {
@@ -754,9 +840,7 @@ int main(int argc, char** argv) {
gpr_free(resolver);
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
- grpc_init();
auto result = RUN_ALL_TESTS();
- grpc_shutdown();
// Test sequential and nested inits and shutdowns.
grpc_init();
grpc_init();
diff --git a/test/cpp/naming/cancel_ares_query_test.cc b/test/cpp/naming/cancel_ares_query_test.cc
index 0d59bf6fb6..dec7c171dc 100644
--- a/test/cpp/naming/cancel_ares_query_test.cc
+++ b/test/cpp/naming/cancel_ares_query_test.cc
@@ -45,11 +45,14 @@
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
-// TODO: pull in different headers when enabling this
-// test on windows. Also set BAD_SOCKET_RETURN_VAL
-// to INVALID_SOCKET on windows.
+#ifdef GPR_WINDOWS
+#include "src/core/lib/iomgr/sockaddr_windows.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#define BAD_SOCKET_RETURN_VAL INVALID_SOCKET
+#else
#include "src/core/lib/iomgr/sockaddr_posix.h"
#define BAD_SOCKET_RETURN_VAL -1
+#endif
namespace {
@@ -91,7 +94,13 @@ class FakeNonResponsiveDNSServer {
abort();
}
}
- ~FakeNonResponsiveDNSServer() { close(socket_); }
+ ~FakeNonResponsiveDNSServer() {
+#ifdef GPR_WINDOWS
+ closesocket(socket_);
+#else
+ close(socket_);
+#endif
+ }
private:
int socket_;
@@ -193,6 +202,38 @@ TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
TestCancelActiveDNSQuery(&args);
}
+#ifdef GPR_WINDOWS
+
+void MaybePollArbitraryPollsetTwice() {
+ grpc_pollset* pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size());
+ gpr_mu* mu;
+ grpc_pollset_init(pollset, &mu);
+ grpc_pollset_worker* worker = nullptr;
+ // Make a zero timeout poll
+ gpr_mu_lock(mu);
+ GRPC_LOG_IF_ERROR(
+ "pollset_work",
+ grpc_pollset_work(pollset, &worker, grpc_core::ExecCtx::Get()->Now()));
+ gpr_mu_unlock(mu);
+ grpc_core::ExecCtx::Get()->Flush();
+ // Make a second zero-timeout poll (in case the first one
+ // short-circuited by picking up a previous "kick")
+ gpr_mu_lock(mu);
+ GRPC_LOG_IF_ERROR(
+ "pollset_work",
+ grpc_pollset_work(pollset, &worker, grpc_core::ExecCtx::Get()->Now()));
+ gpr_mu_unlock(mu);
+ grpc_core::ExecCtx::Get()->Flush();
+ grpc_pollset_destroy(pollset);
+ gpr_free(pollset);
+}
+
+#else
+
+void MaybePollArbitraryPollsetTwice() {}
+
+#endif
+
TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
grpc_core::ExecCtx exec_ctx;
ArgsStruct args;
@@ -209,6 +250,12 @@ TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
// this test. This test only cares about what happens to fd's that c-ares
// opens.
TestCancelActiveDNSQuery(&args);
+ // This test relies on the assumption that cancelling a c-ares query
+ // will flush out all callbacks on the current exec ctx, which is true
+ // on posix platforms but not on Windows, because fd shutdown on Windows
+ // requires a trip through the polling loop to schedule the callback.
+ // So we need to do extra polling work on Windows to free things up.
+ MaybePollArbitraryPollsetTwice();
EXPECT_EQ(grpc_iomgr_count_objects_for_testing(), 0u);
grpc_pollset_set_destroy(fake_other_pollset_set);
}
diff --git a/test/cpp/naming/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py
index baa6512f62..1c9d0676b8 100755
--- a/test/cpp/naming/gen_build_yaml.py
+++ b/test/cpp/naming/gen_build_yaml.py
@@ -68,7 +68,7 @@ def main():
'gtest': False,
'run': False,
'src': ['test/cpp/naming/resolver_component_test.cc'],
- 'platforms': ['linux', 'posix', 'mac'],
+ 'platforms': ['linux', 'posix', 'mac', 'windows'],
'deps': [
'grpc++_test_util' + unsecure_build_config_suffix,
'grpc_test_util' + unsecure_build_config_suffix,
@@ -110,7 +110,7 @@ def main():
'gtest': True,
'run': True,
'src': ['test/cpp/naming/address_sorting_test.cc'],
- 'platforms': ['linux', 'posix', 'mac'],
+ 'platforms': ['linux', 'posix', 'mac', 'windows'],
'deps': [
'grpc++_test_util' + unsecure_build_config_suffix,
'grpc_test_util' + unsecure_build_config_suffix,
@@ -129,7 +129,7 @@ def main():
'gtest': True,
'run': True,
'src': ['test/cpp/naming/cancel_ares_query_test.cc'],
- 'platforms': ['linux', 'posix', 'mac'],
+ 'platforms': ['linux', 'posix', 'mac', 'windows'],
'deps': [
'grpc++_test_util',
'grpc_test_util',
diff --git a/test/cpp/naming/manual_run_resolver_component_test.py b/test/cpp/naming/manual_run_resolver_component_test.py
new file mode 100644
index 0000000000..fb2157741a
--- /dev/null
+++ b/test/cpp/naming/manual_run_resolver_component_test.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# Copyright 2015 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import subprocess
+import sys
+
+# The c-ares test suite doesn't get ran regularly on Windows, but
+# this script provides a way to run a lot of the tests manually.
+_MSBUILD_CONFIG = os.environ['CONFIG']
+os.chdir(os.path.join('..', '..', os.getcwd()))
+# This port is arbitrary, but it needs to be available.
+_DNS_SERVER_PORT = 15353
+
+subprocess.call([
+ sys.executable,
+ 'test\\cpp\\naming\\resolver_component_tests_runner.py',
+ '--test_bin_path', 'cmake\\build\\%s\\resolver_component_test.exe' % _MSBUILD_CONFIG,
+ '--dns_server_bin_path', 'test\\cpp\\naming\\utils\\dns_server.py',
+ '--records_config_path', 'test\\cpp\\naming\\resolver_test_record_groups.yaml',
+ '--dns_server_port', str(_DNS_SERVER_PORT),
+ '--dns_resolver_bin_path', 'test\\cpp\\naming\\utils\\dns_resolver.py',
+ '--tcp_connect_bin_path', 'test\\cpp\\naming\\utils\\tcp_connect.py',
+])
diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc
index 6ac548120c..3dc6e7178c 100644
--- a/test/cpp/naming/resolver_component_test.cc
+++ b/test/cpp/naming/resolver_component_test.cc
@@ -16,6 +16,8 @@
*
*/
+#include <grpc/support/port_platform.h>
+
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -55,8 +57,15 @@
// TODO: pull in different headers when enabling this
// test on windows. Also set BAD_SOCKET_RETURN_VAL
// to INVALID_SOCKET on windows.
+#ifdef GPR_WINDOWS
+#include "src/core/lib/iomgr/sockaddr_windows.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_windows.h"
+#define BAD_SOCKET_RETURN_VAL INVALID_SOCKET
+#else
#include "src/core/lib/iomgr/sockaddr_posix.h"
#define BAD_SOCKET_RETURN_VAL -1
+#endif
using grpc::SubProcess;
using std::vector;
@@ -241,6 +250,62 @@ void CheckLBPolicyResultLocked(grpc_channel_args* channel_args,
}
}
+#ifdef GPR_WINDOWS
+void OpenAndCloseSocketsStressLoop(int dummy_port, gpr_event* done_ev) {
+ sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(dummy_port);
+ ((char*)&addr.sin6_addr)[15] = 1;
+ for (;;) {
+ if (gpr_event_get(done_ev)) {
+ return;
+ }
+ std::vector<int> sockets;
+ for (size_t i = 0; i < 50; i++) {
+ SOCKET s = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, nullptr, 0,
+ WSA_FLAG_OVERLAPPED);
+ ASSERT_TRUE(s != BAD_SOCKET_RETURN_VAL)
+ << "Failed to create TCP ipv6 socket";
+ gpr_log(GPR_DEBUG, "Opened socket: %d", s);
+ char val = 1;
+ ASSERT_TRUE(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) !=
+ SOCKET_ERROR)
+ << "Failed to set socketopt reuseaddr. WSA error: " +
+ std::to_string(WSAGetLastError());
+ ASSERT_TRUE(grpc_tcp_set_non_block(s) == GRPC_ERROR_NONE)
+ << "Failed to set socket non-blocking";
+ ASSERT_TRUE(bind(s, (const sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR)
+ << "Failed to bind socket " + std::to_string(s) +
+ " to [::1]:" + std::to_string(dummy_port) +
+ ". WSA error: " + std::to_string(WSAGetLastError());
+ ASSERT_TRUE(listen(s, 1) != SOCKET_ERROR)
+ << "Failed to listen on socket " + std::to_string(s) +
+ ". WSA error: " + std::to_string(WSAGetLastError());
+ sockets.push_back(s);
+ }
+ // Do a non-blocking accept followed by a close on all of those sockets.
+ // Do this in a separate loop to try to induce a time window to hit races.
+ for (size_t i = 0; i < sockets.size(); i++) {
+ gpr_log(GPR_DEBUG, "non-blocking accept then close on %d", sockets[i]);
+ ASSERT_TRUE(accept(sockets[i], nullptr, nullptr) == INVALID_SOCKET)
+ << "Accept on dummy socket unexpectedly accepted actual connection.";
+ ASSERT_TRUE(WSAGetLastError() == WSAEWOULDBLOCK)
+ << "OpenAndCloseSocketsStressLoop accept on socket " +
+ std::to_string(sockets[i]) +
+ " failed in "
+ "an unexpected way. "
+ "WSA error: " +
+ std::to_string(WSAGetLastError()) +
+ ". Socket use-after-close bugs are likely.";
+ ASSERT_TRUE(closesocket(sockets[i]) != SOCKET_ERROR)
+ << "Failed to close socket: " + std::to_string(sockets[i]) +
+ ". WSA error: " + std::to_string(WSAGetLastError());
+ }
+ }
+ return;
+}
+#else
void OpenAndCloseSocketsStressLoop(int dummy_port, gpr_event* done_ev) {
// The goal of this loop is to catch socket
// "use after close" bugs within the c-ares resolver by acting
@@ -311,6 +376,7 @@ void OpenAndCloseSocketsStressLoop(int dummy_port, gpr_event* done_ev) {
}
}
}
+#endif
void CheckResolverResultLocked(void* argsp, grpc_error* err) {
EXPECT_EQ(err, GRPC_ERROR_NONE);
@@ -372,9 +438,9 @@ void RunResolvesRelevantRecordsTest(void (*OnDoneLocked)(void* arg,
args.expected_lb_policy = FLAGS_expected_lb_policy;
// maybe build the address with an authority
char* whole_uri = nullptr;
- GPR_ASSERT(asprintf(&whole_uri, "dns://%s/%s",
- FLAGS_local_dns_server_address.c_str(),
- FLAGS_target_name.c_str()));
+ GPR_ASSERT(gpr_asprintf(&whole_uri, "dns://%s/%s",
+ FLAGS_local_dns_server_address.c_str(),
+ FLAGS_target_name.c_str()));
// create resolver and resolve
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
grpc_core::ResolverRegistry::CreateResolver(whole_uri, nullptr,
diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py
index 69386ebeb0..1873eec35b 100755
--- a/test/cpp/naming/resolver_component_tests_runner.py
+++ b/test/cpp/naming/resolver_component_tests_runner.py
@@ -22,6 +22,7 @@ import tempfile
import os
import time
import signal
+import platform
argp = argparse.ArgumentParser(description='Run c-ares resolver tests')
@@ -43,6 +44,11 @@ args = argp.parse_args()
def test_runner_log(msg):
sys.stderr.write('\n%s: %s\n' % (__file__, msg))
+def python_args(arg_list):
+ if platform.system() == 'Windows':
+ return [sys.executable] + arg_list
+ return arg_list
+
cur_resolver = os.environ.get('GRPC_DNS_RESOLVER')
if cur_resolver and cur_resolver != 'ares':
test_runner_log(('WARNING: cur resolver set to %s. This set of tests '
@@ -50,26 +56,27 @@ if cur_resolver and cur_resolver != 'ares':
test_runner_log('Exit 1 without running tests.')
sys.exit(1)
os.environ.update({'GRPC_DNS_RESOLVER': 'ares'})
+os.environ.update({'GRPC_TRACE': 'cares_resolver'})
def wait_until_dns_server_is_up(args,
dns_server_subprocess,
dns_server_subprocess_output):
for i in range(0, 30):
test_runner_log('Health check: attempt to connect to DNS server over TCP.')
- tcp_connect_subprocess = subprocess.Popen([
+ tcp_connect_subprocess = subprocess.Popen(python_args([
args.tcp_connect_bin_path,
'--server_host', '127.0.0.1',
'--server_port', str(args.dns_server_port),
- '--timeout', str(1)])
+ '--timeout', str(1)]))
tcp_connect_subprocess.communicate()
if tcp_connect_subprocess.returncode == 0:
test_runner_log(('Health check: attempt to make an A-record '
'query to DNS server.'))
- dns_resolver_subprocess = subprocess.Popen([
+ dns_resolver_subprocess = subprocess.Popen(python_args([
args.dns_resolver_bin_path,
'--qname', 'health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp',
'--server_host', '127.0.0.1',
- '--server_port', str(args.dns_server_port)],
+ '--server_port', str(args.dns_server_port)]),
stdout=subprocess.PIPE)
dns_resolver_stdout, _ = dns_resolver_subprocess.communicate()
if dns_resolver_subprocess.returncode == 0:
@@ -91,10 +98,10 @@ def wait_until_dns_server_is_up(args,
dns_server_subprocess_output = tempfile.mktemp()
with open(dns_server_subprocess_output, 'w') as l:
- dns_server_subprocess = subprocess.Popen([
+ dns_server_subprocess = subprocess.Popen(python_args([
args.dns_server_bin_path,
'--port', str(args.dns_server_port),
- '--records_config_path', args.records_config_path],
+ '--records_config_path', args.records_config_path]),
stdin=subprocess.PIPE,
stdout=l,
stderr=l)
@@ -112,6 +119,18 @@ wait_until_dns_server_is_up(args,
dns_server_subprocess_output)
num_test_failures = 0
+test_runner_log('Run test with target: %s' % 'no-srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+ args.test_bin_path,
+ '--target_name', 'no-srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.',
+ '--expected_addrs', '5.5.5.5:443,False',
+ '--expected_chosen_service_config', '',
+ '--expected_lb_policy', '',
+ '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+ num_test_failures += 1
+
test_runner_log('Run test with target: %s' % 'srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.')
current_test_subprocess = subprocess.Popen([
args.test_bin_path,
diff --git a/test/cpp/naming/resolver_test_record_groups.yaml b/test/cpp/naming/resolver_test_record_groups.yaml
index 6c4f89d09b..3c51a00c7b 100644
--- a/test/cpp/naming/resolver_test_record_groups.yaml
+++ b/test/cpp/naming/resolver_test_record_groups.yaml
@@ -1,6 +1,14 @@
resolver_tests_common_zone_name: resolver-tests-version-4.grpctestingexp.
resolver_component_tests:
- expected_addrs:
+ - {address: '5.5.5.5:443', is_balancer: false}
+ expected_chosen_service_config: null
+ expected_lb_policy: null
+ record_to_resolve: no-srv-ipv4-single-target
+ records:
+ no-srv-ipv4-single-target:
+ - {TTL: '2100', data: 5.5.5.5, type: A}
+- expected_addrs:
- {address: '1.2.3.4:1234', is_balancer: true}
expected_chosen_service_config: null
expected_lb_policy: null
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index e7d093c71a..b958c75fc7 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -34,11 +34,13 @@ grpc_cc_library(
"qps_worker.cc",
"server_async.cc",
"server_sync.cc",
+ "qps_server_builder.cc",
],
hdrs = [
"client.h",
"qps_worker.h",
"server.h",
+ "qps_server_builder.h",
],
deps = [
":histogram",
@@ -55,6 +57,10 @@ grpc_cc_library(
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
"//test/cpp/util:test_util",
+ "//test/cpp/util:test_config",
+ ],
+ external_deps = [
+ "gflags",
],
)
diff --git a/test/cpp/qps/benchmark_config.cc b/test/cpp/qps/benchmark_config.cc
index a4fd9de820..5fd0f00038 100644
--- a/test/cpp/qps/benchmark_config.cc
+++ b/test/cpp/qps/benchmark_config.cc
@@ -22,6 +22,8 @@
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
+#include "test/cpp/util/test_credentials_provider.h"
+
DEFINE_bool(enable_log_reporter, true,
"Enable reporting of benchmark results through GprLog");
@@ -44,6 +46,10 @@ DEFINE_string(rpc_reporter_server_address, "",
DEFINE_bool(enable_rpc_reporter, false, "Enable use of RPC reporter");
+DEFINE_string(
+ rpc_reporter_credential_type, grpc::testing::kInsecureCredentialsType,
+ "Credential type for communication to the QPS benchmark report server");
+
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
@@ -65,11 +71,14 @@ static std::shared_ptr<Reporter> InitBenchmarkReporters() {
new JsonReporter("JsonReporter", FLAGS_scenario_result_file)));
}
if (FLAGS_enable_rpc_reporter) {
+ ChannelArguments channel_args;
+ std::shared_ptr<ChannelCredentials> channel_creds =
+ testing::GetCredentialsProvider()->GetChannelCredentials(
+ FLAGS_rpc_reporter_credential_type, &channel_args);
GPR_ASSERT(!FLAGS_rpc_reporter_server_address.empty());
composite_reporter->add(std::unique_ptr<Reporter>(new RpcReporter(
- "RpcReporter",
- grpc::CreateChannel(FLAGS_rpc_reporter_server_address,
- grpc::InsecureChannelCredentials()))));
+ "RpcReporter", grpc::CreateChannel(FLAGS_rpc_reporter_server_address,
+ channel_creds))));
}
return std::shared_ptr<Reporter>(composite_reporter);
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 9d58ea8882..9d7469c9b5 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -19,6 +19,8 @@
#ifndef TEST_QPS_CLIENT_H
#define TEST_QPS_CLIENT_H
+#include <stdlib.h>
+
#include <condition_variable>
#include <mutex>
#include <unordered_map>
@@ -34,6 +36,7 @@
#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
#include "src/proto/grpc/testing/payloads.pb.h"
+#include "src/core/lib/gpr/env.h"
#include "src/cpp/util/core_stats.h"
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/interarrival.h"
@@ -441,9 +444,24 @@ class ClientImpl : public Client {
std::unique_ptr<std::thread> WaitForReady() {
return std::unique_ptr<std::thread>(new std::thread([this]() {
if (!is_inproc_) {
- GPR_ASSERT(channel_->WaitForConnected(
- gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
- gpr_time_from_seconds(10, GPR_TIMESPAN))));
+ int connect_deadline = 10;
+ /* Allow optionally overriding connect_deadline in order
+ * to deal with benchmark environments in which the server
+ * can take a long time to become ready. */
+ char* channel_connect_timeout_str =
+ gpr_getenv("QPS_WORKER_CHANNEL_CONNECT_TIMEOUT");
+ if (channel_connect_timeout_str != nullptr &&
+ strcmp(channel_connect_timeout_str, "") != 0) {
+ connect_deadline = atoi(channel_connect_timeout_str);
+ }
+ gpr_log(GPR_INFO,
+ "Waiting for up to %d seconds for the channel %p to connect",
+ connect_deadline, channel_.get());
+ gpr_free(channel_connect_timeout_str);
+ GPR_ASSERT(channel_->WaitForConnected(gpr_time_add(
+ gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_seconds(connect_deadline, GPR_TIMESPAN))));
+ gpr_log(GPR_INFO, "Channel %p connected!", channel_.get());
}
}));
}
diff --git a/test/cpp/qps/qps_server_builder.cc b/test/cpp/qps/qps_server_builder.cc
new file mode 100644
index 0000000000..5fbc682b75
--- /dev/null
+++ b/test/cpp/qps/qps_server_builder.cc
@@ -0,0 +1,45 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qps_server_builder.h"
+
+using grpc::ServerBuilder;
+
+namespace grpc {
+namespace testing {
+
+namespace {
+std::unique_ptr<ServerBuilder> DefaultCreateQpsServerBuilder() {
+ return std::unique_ptr<ServerBuilder>(new ServerBuilder());
+}
+
+std::function<std::unique_ptr<ServerBuilder>()> g_create_qps_server_builder =
+ DefaultCreateQpsServerBuilder;
+} // namespace
+
+std::unique_ptr<ServerBuilder> CreateQpsServerBuilder() {
+ return g_create_qps_server_builder();
+}
+
+void SetCreateQpsServerBuilderFunc(
+ std::function<std::unique_ptr<ServerBuilder>()> create_qps_server_builder) {
+ g_create_qps_server_builder = std::move(create_qps_server_builder);
+}
+
+} // namespace testing
+} // namespace grpc
diff --git a/test/cpp/qps/qps_server_builder.h b/test/cpp/qps/qps_server_builder.h
new file mode 100644
index 0000000000..98f9fa72e9
--- /dev/null
+++ b/test/cpp/qps/qps_server_builder.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_QPS_SERVER_BUILDER_H
+#define GRPC_QPS_SERVER_BUILDER_H
+
+#include <functional>
+#include <memory>
+
+#include <grpcpp/server_builder.h>
+
+namespace grpc {
+namespace testing {
+
+// CreateQpsServerBuilder creates a new ServerBuilder.
+// This uses the "create ServerBuilder" func that was set
+// in SetCreateQpsServerBuilderFunc if one has been set,
+// otherwise, this defaults to creating a new ServerBuilder
+// with only its default constructor.
+std::unique_ptr<ServerBuilder> CreateQpsServerBuilder();
+
+// SetCreateQpsServerBuilderFunc sets a function to use to create new
+// ServerBuilders in "CreateQpsServerBuilder". It can be used to modify options
+// that the server is built with.
+void SetCreateQpsServerBuilderFunc(
+ std::function<std::unique_ptr<ServerBuilder>()>);
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPC_QPS_SERVER_BUILDER_H
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index d3f0380474..7ddf3c1cf3 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -39,6 +39,7 @@
#include "test/core/util/grpc_profiler.h"
#include "test/core/util/histogram.h"
#include "test/cpp/qps/client.h"
+#include "test/cpp/qps/qps_server_builder.h"
#include "test/cpp/qps/server.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/test_credentials_provider.h"
@@ -272,18 +273,18 @@ QpsWorker::QpsWorker(int driver_port, int server_port,
impl_.reset(new WorkerServiceImpl(server_port, this));
gpr_atm_rel_store(&done_, static_cast<gpr_atm>(0));
- ServerBuilder builder;
+ std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
if (driver_port >= 0) {
char* server_address = nullptr;
gpr_join_host_port(&server_address, "::", driver_port);
- builder.AddListeningPort(
+ builder->AddListeningPort(
server_address,
GetCredentialsProvider()->GetServerCredentials(credential_type));
gpr_free(server_address);
}
- builder.RegisterService(impl_.get());
+ builder->RegisterService(impl_.get());
- server_ = builder.BuildAndStart();
+ server_ = builder->BuildAndStart();
}
QpsWorker::~QpsWorker() {}
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 1dfef6cfc1..5cd975cf74 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -38,6 +38,7 @@
#include "src/core/lib/surface/completion_queue.h"
#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
#include "test/core/util/test_config.h"
+#include "test/cpp/qps/qps_server_builder.h"
#include "test/cpp/qps/server.h"
namespace grpc {
@@ -74,19 +75,19 @@ class AsyncQpsServerTest final : public grpc::testing::Server {
ResponseType*)>
process_rpc)
: Server(config) {
- ServerBuilder builder;
+ std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
auto port_num = port();
// Negative port number means inproc server, so no listen port needed
if (port_num >= 0) {
char* server_address = nullptr;
gpr_join_host_port(&server_address, "::", port_num);
- builder.AddListeningPort(server_address,
- Server::CreateServerCredentials(config));
+ builder->AddListeningPort(server_address,
+ Server::CreateServerCredentials(config));
gpr_free(server_address);
}
- register_service(&builder, &async_service_);
+ register_service(builder.get(), &async_service_);
int num_threads = config.async_server_threads();
if (num_threads <= 0) { // dynamic sizing
@@ -97,15 +98,15 @@ class AsyncQpsServerTest final : public grpc::testing::Server {
int tpc = std::max(1, config.threads_per_cq()); // 1 if unspecified
int num_cqs = (num_threads + tpc - 1) / tpc; // ceiling operator
for (int i = 0; i < num_cqs; i++) {
- srv_cqs_.emplace_back(builder.AddCompletionQueue());
+ srv_cqs_.emplace_back(builder->AddCompletionQueue());
}
for (int i = 0; i < num_threads; i++) {
cq_.emplace_back(i % srv_cqs_.size());
}
- ApplyConfigToBuilder(config, &builder);
+ ApplyConfigToBuilder(config, builder.get());
- server_ = builder.BuildAndStart();
+ server_ = builder->BuildAndStart();
auto process_rpc_bound =
std::bind(process_rpc, config.payload_config(), std::placeholders::_1,
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index b8facf9b56..2e63f5ec86 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -27,6 +27,7 @@
#include "src/core/lib/gpr/host_port.h"
#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
+#include "test/cpp/qps/qps_server_builder.h"
#include "test/cpp/qps/server.h"
#include "test/cpp/qps/usage_timer.h"
@@ -154,23 +155,23 @@ class BenchmarkServiceImpl final : public BenchmarkService::Service {
class SynchronousServer final : public grpc::testing::Server {
public:
explicit SynchronousServer(const ServerConfig& config) : Server(config) {
- ServerBuilder builder;
+ std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
auto port_num = port();
// Negative port number means inproc server, so no listen port needed
if (port_num >= 0) {
char* server_address = nullptr;
gpr_join_host_port(&server_address, "::", port_num);
- builder.AddListeningPort(server_address,
- Server::CreateServerCredentials(config));
+ builder->AddListeningPort(server_address,
+ Server::CreateServerCredentials(config));
gpr_free(server_address);
}
- ApplyConfigToBuilder(config, &builder);
+ ApplyConfigToBuilder(config, builder.get());
- builder.RegisterService(&service_);
+ builder->RegisterService(&service_);
- impl_ = builder.BuildAndStart();
+ impl_ = builder->BuildAndStart();
}
std::shared_ptr<Channel> InProcessChannel(
diff --git a/test/cpp/server/load_reporter/load_reporter_test.cc b/test/cpp/server/load_reporter/load_reporter_test.cc
index 719c3a67d9..0d56cdf431 100644
--- a/test/cpp/server/load_reporter/load_reporter_test.cc
+++ b/test/cpp/server/load_reporter/load_reporter_test.cc
@@ -172,9 +172,9 @@ class LbFeedbackTest : public LoadReporterTest {
// TODO(juanlishen): The error is big because we use sleep(). It should be
// much smaller when we use fake clock.
ASSERT_THAT(static_cast<double>(lb_feedback.calls_per_second()),
- DoubleNear(expected_qps, expected_qps / 50));
+ DoubleNear(expected_qps, expected_qps * 0.05));
ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
- DoubleNear(expected_eps, expected_eps / 50));
+ DoubleNear(expected_eps, expected_eps * 0.05));
gpr_log(GPR_INFO,
"Verified LB feedback matches the samples of index [%lu, %lu).",
start, start + count);
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index 9b42bb28b1..c3bfeb7615 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -177,6 +177,7 @@ grpc_cc_test(
"//:grpc++_reflection",
"//src/proto/grpc/testing:echo_messages_proto",
"//src/proto/grpc/testing:echo_proto",
+ "//test/core/end2end:ssl_test_data",
"//test/core/util:grpc_test_util",
],
)
diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc
index ee310784c2..b4704bfe6a 100644
--- a/test/cpp/util/channel_trace_proto_helper.cc
+++ b/test/cpp/util/channel_trace_proto_helper.cc
@@ -64,13 +64,22 @@ void VaidateProtoJsonTranslation(char* json_c_str) {
} // namespace
-void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) {
- VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(
- tracer_json_c_str);
+void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(json_c_str);
}
-void ValidateChannelProtoJsonTranslation(char* channel_json_c_str) {
- VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(channel_json_c_str);
+void ValidateChannelProtoJsonTranslation(char* json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(json_c_str);
+}
+
+void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::GetTopChannelsResponse>(
+ json_c_str);
+}
+
+void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::GetChannelResponse>(
+ json_c_str);
}
} // namespace testing
diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h
index d1a3603372..18e3d54b6b 100644
--- a/test/cpp/util/channel_trace_proto_helper.h
+++ b/test/cpp/util/channel_trace_proto_helper.h
@@ -22,8 +22,10 @@
namespace grpc {
namespace testing {
-void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str);
-void ValidateChannelProtoJsonTranslation(char* channel_json_c_str);
+void ValidateChannelTraceProtoJsonTranslation(char* json_c_str);
+void ValidateChannelProtoJsonTranslation(char* json_c_str);
+void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str);
+void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str);
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/util/cli_credentials.cc b/test/cpp/util/cli_credentials.cc
index aa4eafb756..acf4ef8ef1 100644
--- a/test/cpp/util/cli_credentials.cc
+++ b/test/cpp/util/cli_credentials.cc
@@ -20,45 +20,123 @@
#include <gflags/gflags.h>
-DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
-DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
+DEFINE_bool(
+ enable_ssl, false,
+ "Whether to use ssl/tls. Deprecated. Use --channel_creds_type=ssl.");
+DEFINE_bool(use_auth, false,
+ "Whether to create default google credentials. Deprecated. Use "
+ "--channel_creds_type=gdc.");
DEFINE_string(
access_token, "",
"The access token that will be sent to the server to authenticate RPCs.");
+DEFINE_string(
+ ssl_target, "",
+ "If not empty, treat the server host name as this for ssl/tls certificate "
+ "validation.");
+DEFINE_string(
+ channel_creds_type, "",
+ "The channel creds type: insecure, ssl, gdc (Google Default Credentials) "
+ "or alts.");
namespace grpc {
namespace testing {
-std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
+grpc::string CliCredentials::GetDefaultChannelCredsType() const {
+ // Compatibility logic for --enable_ssl.
+ if (FLAGS_enable_ssl) {
+ fprintf(stderr,
+ "warning: --enable_ssl is deprecated. Use "
+ "--channel_creds_type=ssl.\n");
+ return "ssl";
+ }
+ // Compatibility logic for --use_auth.
+ if (FLAGS_access_token.empty() && FLAGS_use_auth) {
+ fprintf(stderr,
+ "warning: --use_auth is deprecated. Use "
+ "--channel_creds_type=gdc.\n");
+ return "gdc";
+ }
+ return "insecure";
+}
+
+std::shared_ptr<grpc::ChannelCredentials>
+CliCredentials::GetChannelCredentials() const {
+ if (FLAGS_channel_creds_type.compare("insecure") == 0) {
+ return grpc::InsecureChannelCredentials();
+ } else if (FLAGS_channel_creds_type.compare("ssl") == 0) {
+ return grpc::SslCredentials(grpc::SslCredentialsOptions());
+ } else if (FLAGS_channel_creds_type.compare("gdc") == 0) {
+ return grpc::GoogleDefaultCredentials();
+ } else if (FLAGS_channel_creds_type.compare("alts") == 0) {
+ return grpc::experimental::AltsCredentials(
+ grpc::experimental::AltsCredentialsOptions());
+ }
+ fprintf(stderr,
+ "--channel_creds_type=%s invalid; must be insecure, ssl, gdc or "
+ "alts.\n",
+ FLAGS_channel_creds_type.c_str());
+ return std::shared_ptr<grpc::ChannelCredentials>();
+}
+
+std::shared_ptr<grpc::CallCredentials> CliCredentials::GetCallCredentials()
const {
if (!FLAGS_access_token.empty()) {
if (FLAGS_use_auth) {
fprintf(stderr,
"warning: use_auth is ignored when access_token is provided.");
}
-
- return grpc::CompositeChannelCredentials(
- grpc::SslCredentials(grpc::SslCredentialsOptions()),
- grpc::AccessTokenCredentials(FLAGS_access_token));
+ return grpc::AccessTokenCredentials(FLAGS_access_token);
}
+ return std::shared_ptr<grpc::CallCredentials>();
+}
- if (FLAGS_use_auth) {
- return grpc::GoogleDefaultCredentials();
+std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
+ const {
+ if (FLAGS_channel_creds_type.empty()) {
+ FLAGS_channel_creds_type = GetDefaultChannelCredsType();
+ } else if (FLAGS_enable_ssl && FLAGS_channel_creds_type.compare("ssl") != 0) {
+ fprintf(stderr,
+ "warning: ignoring --enable_ssl because "
+ "--channel_creds_type already set to %s.\n",
+ FLAGS_channel_creds_type.c_str());
+ } else if (FLAGS_use_auth && FLAGS_channel_creds_type.compare("gdc") != 0) {
+ fprintf(stderr,
+ "warning: ignoring --use_auth because "
+ "--channel_creds_type already set to %s.\n",
+ FLAGS_channel_creds_type.c_str());
}
-
- if (FLAGS_enable_ssl) {
- return grpc::SslCredentials(grpc::SslCredentialsOptions());
+ // Legacy transport upgrade logic for insecure requests.
+ if (!FLAGS_access_token.empty() &&
+ FLAGS_channel_creds_type.compare("insecure") == 0) {
+ fprintf(stderr,
+ "warning: --channel_creds_type=insecure upgraded to ssl because "
+ "an access token was provided.\n");
+ FLAGS_channel_creds_type = "ssl";
}
-
- return grpc::InsecureChannelCredentials();
+ std::shared_ptr<grpc::ChannelCredentials> channel_creds =
+ GetChannelCredentials();
+ // Composite any call-type credentials on top of the base channel.
+ std::shared_ptr<grpc::CallCredentials> call_creds = GetCallCredentials();
+ return (channel_creds == nullptr || call_creds == nullptr)
+ ? channel_creds
+ : grpc::CompositeChannelCredentials(channel_creds, call_creds);
}
const grpc::string CliCredentials::GetCredentialUsage() const {
- return " --enable_ssl ; Set whether to use tls\n"
+ return " --enable_ssl ; Set whether to use ssl (deprecated)\n"
" --use_auth ; Set whether to create default google"
" credentials\n"
" --access_token ; Set the access token in metadata,"
- " overrides --use_auth\n";
+ " overrides --use_auth\n"
+ " --ssl_target ; Set server host for ssl validation\n"
+ " --channel_creds_type ; Set to insecure, ssl, gdc, or alts\n";
}
+
+const grpc::string CliCredentials::GetSslTargetNameOverride() const {
+ bool use_ssl = FLAGS_channel_creds_type.compare("ssl") == 0 ||
+ FLAGS_channel_creds_type.compare("gdc") == 0;
+ return use_ssl ? FLAGS_ssl_target : "";
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/util/cli_credentials.h b/test/cpp/util/cli_credentials.h
index b1358e77d8..4636d3ca14 100644
--- a/test/cpp/util/cli_credentials.h
+++ b/test/cpp/util/cli_credentials.h
@@ -28,8 +28,22 @@ namespace testing {
class CliCredentials {
public:
virtual ~CliCredentials() {}
- virtual std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const;
+ std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const;
virtual const grpc::string GetCredentialUsage() const;
+ virtual const grpc::string GetSslTargetNameOverride() const;
+
+ protected:
+ // Returns the appropriate channel_creds_type value for the set of legacy
+ // flag arguments.
+ virtual grpc::string GetDefaultChannelCredsType() const;
+ // Returns the base transport channel credentials. Child classes can override
+ // to support additional channel_creds_types unknown to this base class.
+ virtual std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials()
+ const;
+ // Returns call credentials to composite onto the base transport channel
+ // credentials. Child classes can override to support additional
+ // authentication flags unknown to this base class.
+ virtual std::shared_ptr<grpc::CallCredentials> GetCallCredentials() const;
};
} // namespace testing
diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc
index 840ca07d2b..ccc60cca27 100644
--- a/test/cpp/util/grpc_tool.cc
+++ b/test/cpp/util/grpc_tool.cc
@@ -206,6 +206,15 @@ void ReadResponse(CliCall* call, const grpc::string& method_name,
}
}
+std::shared_ptr<grpc::Channel> CreateCliChannel(
+ const grpc::string& server_address, const CliCredentials& cred) {
+ grpc::ChannelArguments args;
+ if (!cred.GetSslTargetNameOverride().empty()) {
+ args.SetSslTargetNameOverride(cred.GetSslTargetNameOverride());
+ }
+ return grpc::CreateCustomChannel(server_address, cred.GetCredentials(), args);
+}
+
struct Command {
const char* command;
std::function<bool(GrpcTool*, int, const char**, const CliCredentials&,
@@ -324,7 +333,7 @@ bool GrpcTool::ListServices(int argc, const char** argv,
grpc::string server_address(argv[0]);
std::shared_ptr<grpc::Channel> channel =
- grpc::CreateChannel(server_address, cred.GetCredentials());
+ CreateCliChannel(server_address, cred);
grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
grpc::protobuf::DescriptorPool desc_pool(&desc_db);
@@ -422,7 +431,7 @@ bool GrpcTool::PrintType(int argc, const char** argv,
grpc::string server_address(argv[0]);
std::shared_ptr<grpc::Channel> channel =
- grpc::CreateChannel(server_address, cred.GetCredentials());
+ CreateCliChannel(server_address, cred);
grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
grpc::protobuf::DescriptorPool desc_pool(&desc_db);
@@ -469,7 +478,7 @@ bool GrpcTool::CallMethod(int argc, const char** argv,
bool print_mode = false;
std::shared_ptr<grpc::Channel> channel =
- grpc::CreateChannel(server_address, cred.GetCredentials());
+ CreateCliChannel(server_address, cred);
if (!FLAGS_binary_input || !FLAGS_binary_output) {
parser.reset(
@@ -820,7 +829,7 @@ bool GrpcTool::ParseMessage(int argc, const char** argv,
if (!FLAGS_binary_input || !FLAGS_binary_output) {
std::shared_ptr<grpc::Channel> channel =
- grpc::CreateChannel(server_address, cred.GetCredentials());
+ CreateCliChannel(server_address, cred);
parser.reset(
new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
FLAGS_proto_path, FLAGS_protofiles));
diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc
index 6574d1bb44..3aae090e81 100644
--- a/test/cpp/util/grpc_tool_test.cc
+++ b/test/cpp/util/grpc_tool_test.cc
@@ -35,6 +35,7 @@
#include "src/core/lib/gpr/env.h"
#include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "src/proto/grpc/testing/echo.pb.h"
+#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/cli_credentials.h"
@@ -80,6 +81,9 @@ using grpc::testing::EchoResponse;
" peer: \"peer\"\n" \
"}\n\n"
+DECLARE_string(channel_creds_type);
+DECLARE_string(ssl_target);
+
namespace grpc {
namespace testing {
@@ -97,10 +101,19 @@ const int kServerDefaultResponseStreamsToSend = 3;
class TestCliCredentials final : public grpc::testing::CliCredentials {
public:
- std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const override {
- return InsecureChannelCredentials();
+ TestCliCredentials(bool secure = false) : secure_(secure) {}
+ std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials()
+ const override {
+ if (!secure_) {
+ return InsecureChannelCredentials();
+ }
+ SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
+ return SslCredentials(grpc::SslCredentialsOptions(ssl_opts));
}
const grpc::string GetCredentialUsage() const override { return ""; }
+
+ private:
+ const bool secure_;
};
bool PrintStream(std::stringstream* ss, const grpc::string& output) {
@@ -206,13 +219,24 @@ class GrpcToolTest : public ::testing::Test {
// SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
// uses atexit() to free chosen ports, and it will spawn a new thread in
// resolve_address_posix.c:192 at exit time.
- const grpc::string SetUpServer() {
+ const grpc::string SetUpServer(bool secure = false) {
std::ostringstream server_address;
int port = grpc_pick_unused_port_or_die();
server_address << "localhost:" << port;
// Setup server
ServerBuilder builder;
- builder.AddListeningPort(server_address.str(), InsecureServerCredentials());
+ std::shared_ptr<grpc::ServerCredentials> creds;
+ if (secure) {
+ SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
+ test_server1_cert};
+ SslServerCredentialsOptions ssl_opts;
+ ssl_opts.pem_root_certs = "";
+ ssl_opts.pem_key_cert_pairs.push_back(pkcp);
+ creds = SslServerCredentials(ssl_opts);
+ } else {
+ creds = InsecureServerCredentials();
+ }
+ builder.AddListeningPort(server_address.str(), creds);
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
return server_address.str();
@@ -743,6 +767,29 @@ TEST_F(GrpcToolTest, CallCommandWithBadMetadata) {
gpr_free(test_srcdir);
}
+TEST_F(GrpcToolTest, ListCommand_OverrideSslHostName) {
+ const grpc::string server_address = SetUpServer(true);
+
+ // Test input "grpc_cli ls localhost:<port> --channel_creds_type=ssl
+ // --ssl_target=z.test.google.fr"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
+ FLAGS_l = false;
+ FLAGS_channel_creds_type = "ssl";
+ FLAGS_ssl_target = "z.test.google.fr";
+ EXPECT_TRUE(
+ 0 == GrpcToolMainLib(
+ ArraySize(argv), argv, TestCliCredentials(true),
+ std::bind(PrintStream, &output_stream, std::placeholders::_1)));
+ EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
+ "grpc.testing.EchoTestService\n"
+ "grpc.reflection.v1alpha.ServerReflection\n"));
+
+ FLAGS_channel_creds_type = "";
+ FLAGS_ssl_target = "";
+ ShutdownServer();
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/distrib/cpp/run_distrib_test_cmake.bat b/test/distrib/cpp/run_distrib_test_cmake.bat
index 8eb3b201b1..7658156be1 100644
--- a/test/distrib/cpp/run_distrib_test_cmake.bat
+++ b/test/distrib/cpp/run_distrib_test_cmake.bat
@@ -39,7 +39,7 @@ cd ../../..
cd third_party/protobuf/cmake
mkdir build
cd build
-cmake -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% -Dprotobuf_MSVC_STATIC_RUNTIME=OFF -Dprotobuf_BUILD_TESTS=OFF ..
+cmake -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% -DZLIB_ROOT=%INSTALL_DIR% -Dprotobuf_MSVC_STATIC_RUNTIME=OFF -Dprotobuf_BUILD_TESTS=OFF ..
cmake --build . --config Release --target install || goto :error
cd ../../../..
diff --git a/test/distrib/cpp/run_distrib_test_routeguide.sh b/test/distrib/cpp/run_distrib_test_routeguide.sh
index dc69ab8377..a81692d920 100755
--- a/test/distrib/cpp/run_distrib_test_routeguide.sh
+++ b/test/distrib/cpp/run_distrib_test_routeguide.sh
@@ -19,7 +19,7 @@ set -ex
cd "$(dirname "$0")/../../.."
cd third_party/protobuf && ./autogen.sh && \
-./configure && make -j4 && make check && make install && ldconfig
+./configure && make -j4 && make install && ldconfig
cd ../.. && make -j4 && make install