aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
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/end2end/tests/channelz.cc16
-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/check_gcp_environment_linux_test.cc1
-rw-r--r--test/core/surface/public_headers_must_be_c89.c2
-rw-r--r--test/cpp/end2end/BUILD21
-rw-r--r--test/cpp/end2end/channelz_service_test.cc352
-rw-r--r--test/cpp/end2end/client_lb_end2end_test.cc40
-rw-r--r--test/cpp/interop/client.cc16
-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
-rwxr-xr-xtest/cpp/naming/gen_build_yaml.py2
-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.cc14
-rw-r--r--test/cpp/util/cli_credentials.h1
-rw-r--r--test/cpp/util/grpc_tool.cc17
-rw-r--r--test/cpp/util/grpc_tool_test.cc52
36 files changed, 1127 insertions, 197 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/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/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 fb0490a95f..002671a5fa 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/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/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 9a79b468dd..9f4ad2b4d7 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -131,6 +131,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/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/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..c5a73a2469 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();
}
@@ -507,6 +512,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/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/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/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py
index baa6512f62..5dad2ea7af 100755
--- a/test/cpp/naming/gen_build_yaml.py
+++ b/test/cpp/naming/gen_build_yaml.py
@@ -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,
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..d14dc18f16 100644
--- a/test/cpp/util/cli_credentials.cc
+++ b/test/cpp/util/cli_credentials.cc
@@ -25,6 +25,10 @@ DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
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.");
namespace grpc {
namespace testing {
@@ -58,7 +62,15 @@ const grpc::string CliCredentials::GetCredentialUsage() const {
" --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 tls validation\n";
+}
+
+const grpc::string CliCredentials::GetSslTargetNameOverride() const {
+ bool use_tls =
+ FLAGS_enable_ssl || (FLAGS_access_token.empty() && FLAGS_use_auth);
+ return use_tls ? 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..8d662356de 100644
--- a/test/cpp/util/cli_credentials.h
+++ b/test/cpp/util/cli_credentials.h
@@ -30,6 +30,7 @@ class CliCredentials {
virtual ~CliCredentials() {}
virtual std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const;
virtual const grpc::string GetCredentialUsage() const;
+ virtual const grpc::string GetSslTargetNameOverride() 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..7e7f44551e 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_bool(enable_ssl);
+DECLARE_string(ssl_target);
+
namespace grpc {
namespace testing {
@@ -97,10 +101,18 @@ const int kServerDefaultResponseStreamsToSend = 3;
class TestCliCredentials final : public grpc::testing::CliCredentials {
public:
+ TestCliCredentials(bool secure = false) : secure_(secure) {}
std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const override {
- return InsecureChannelCredentials();
+ 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 +218,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 +766,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> --enable_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_enable_ssl = true;
+ 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_enable_ssl = false;
+ FLAGS_ssl_target = "";
+ ShutdownServer();
+}
+
} // namespace testing
} // namespace grpc