From f52e54235294cb71c09d880e8f78a6661b2803f2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 10 Dec 2018 12:45:00 -0800 Subject: Add pagination to serversockets --- src/core/lib/channel/channelz.cc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 0cb2890518..8d449ee672 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -204,16 +204,27 @@ ServerNode::ServerNode(grpc_server* server, size_t channel_tracer_max_nodes) ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { + const int kPaginationLimit = 100; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; ChildSocketsList socket_refs; grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); + int sockets_added = 0; + bool reached_pagination_limit = false; if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); for (size_t i = 0; i < socket_refs.size(); ++i) { + // check if we are over pagination limit to determine if we need to set + // the "end" element. If we don't go through this block, we know that + // when the loop terminates, we have <= to kPaginationLimit. + if (sockets_added == kPaginationLimit) { + reached_pagination_limit = true; + break; + } + sockets_added++; grpc_json* socket_ref_json = grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); @@ -223,11 +234,10 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { socket_refs[i]->remote(), GRPC_JSON_STRING, false); } } - // For now we do not have any pagination rules. In the future we could - // pick a constant for max_channels_sent for a GetServers request. - // Tracking: https://github.com/grpc/grpc/issues/16019. - json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, - GRPC_JSON_TRUE, false); + if (!reached_pagination_limit) { + json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, + GRPC_JSON_TRUE, false); + } char* json_str = grpc_json_dump_to_string(top_level_json, 0); grpc_json_destroy(top_level_json); return json_str; -- cgit v1.2.3 From 07fc27c20d694021669f2d77449da0666b6b1626 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 08:08:34 -0800 Subject: Update channelz proto --- src/proto/grpc/channelz/channelz.proto | 38 ++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/proto/grpc/channelz/channelz.proto b/src/proto/grpc/channelz/channelz.proto index 6202e5e817..9d73f37554 100644 --- a/src/proto/grpc/channelz/channelz.proto +++ b/src/proto/grpc/channelz/channelz.proto @@ -177,6 +177,7 @@ message SubchannelRef { // SocketRef is a reference to a Socket. message SocketRef { + // The globally unique id for this socket. Must be a positive number. int64 socket_id = 3; // An optional name associated with the socket. string name = 4; @@ -288,7 +289,8 @@ message SocketData { // include stream level or TCP level flow control info. google.protobuf.Int64Value remote_flow_control_window = 12; - // Socket options set on this socket. May be absent. + // Socket options set on this socket. May be absent if 'summary' is set + // on GetSocketRequest. repeated SocketOption option = 13; } @@ -439,12 +441,21 @@ service Channelz { message GetTopChannelsRequest { // start_channel_id indicates that only channels at or above this id should be // included in the results. + // To request the first page, this should be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. int64 start_channel_id = 1; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 2; } message GetTopChannelsResponse { // list of channels that the connection detail service knows about. Sorted in // ascending channel_id order. + // Must contain at least 1 result, otherwise 'end' must be true. repeated Channel channel = 1; // If set, indicates that the list of channels is the final list. Requesting // more channels can only return more if they are created after this RPC @@ -455,12 +466,21 @@ message GetTopChannelsResponse { message GetServersRequest { // start_server_id indicates that only servers at or above this id should be // included in the results. + // To request the first page, this must be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. int64 start_server_id = 1; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 2; } message GetServersResponse { // list of servers that the connection detail service knows about. Sorted in // ascending server_id order. + // Must contain at least 1 result, otherwise 'end' must be true. repeated Server server = 1; // If set, indicates that the list of servers is the final list. Requesting // more servers will only return more if they are created after this RPC @@ -483,12 +503,21 @@ message GetServerSocketsRequest { int64 server_id = 1; // start_socket_id indicates that only sockets at or above this id should be // included in the results. + // To request the first page, this must be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. int64 start_socket_id = 2; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 3; } message GetServerSocketsResponse { // list of socket refs that the connection detail service knows about. Sorted in // ascending socket_id order. + // Must contain at least 1 result, otherwise 'end' must be true. repeated SocketRef socket_ref = 1; // If set, indicates that the list of sockets is the final list. Requesting // more sockets will only return more if they are created after this RPC @@ -521,10 +550,15 @@ message GetSubchannelResponse { message GetSocketRequest { // socket_id is the identifier of the specific socket to get. int64 socket_id = 1; + + // If true, the response will contain only high level information + // that is inexpensive to obtain. Fields thay may be omitted are + // documented. + bool summary = 2; } message GetSocketResponse { // The Socket that corresponds to the requested socket_id. This field // should be set. Socket socket = 1; -} +} \ No newline at end of file -- cgit v1.2.3 From 7b1fc0faa23b2cc1807450498b8c69afb079c2d2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 08:22:51 -0800 Subject: Add max_results to ServerSockets --- include/grpc/grpc.h | 3 ++- src/core/lib/channel/channelz.cc | 10 ++++++---- src/core/lib/channel/channelz.h | 3 ++- src/core/lib/channel/channelz_registry.cc | 5 +++-- src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi | 8 +++++--- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi | 3 ++- src/python/grpcio_channelz/grpc_channelz/v1/channelz.py | 3 ++- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 2 +- test/core/end2end/tests/channelz.cc | 2 +- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index d3b74cabab..fec7f5269e 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -511,7 +511,8 @@ GRPCAPI char* grpc_channelz_get_server(intptr_t server_id); /* Gets all server sockets that exist in the server. */ GRPCAPI char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id); + intptr_t start_socket_id, + intptr_t max_results); /* Returns a single Channel, or else a NOT_FOUND code. The returned string is allocated and must be freed by the application. */ diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 8d449ee672..3fcfa2a412 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -203,8 +203,10 @@ ServerNode::ServerNode(grpc_server* server, size_t channel_tracer_max_nodes) ServerNode::~ServerNode() {} -char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { - const int kPaginationLimit = 100; +char* ServerNode::RenderServerSockets(intptr_t start_socket_id, + intptr_t max_results) { + // if user does not set max_results, we choose 500. + int pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; @@ -219,8 +221,8 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { for (size_t i = 0; i < socket_refs.size(); ++i) { // check if we are over pagination limit to determine if we need to set // the "end" element. If we don't go through this block, we know that - // when the loop terminates, we have <= to kPaginationLimit. - if (sockets_added == kPaginationLimit) { + // when the loop terminates, we have <= to pagination_limit. + if (sockets_added == pagination_limit) { reached_pagination_limit = true; break; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 96a4333083..e43792126f 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -210,7 +210,8 @@ class ServerNode : public BaseNode { grpc_json* RenderJson() override; - char* RenderServerSockets(intptr_t start_socket_id); + char* RenderServerSockets(intptr_t start_socket_id, + intptr_t pagination_limit); // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index bc23b90a66..7cca247d64 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -252,7 +252,8 @@ char* grpc_channelz_get_server(intptr_t server_id) { } char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id) { + intptr_t start_socket_id, + intptr_t max_results) { grpc_core::channelz::BaseNode* base_node = grpc_core::channelz::ChannelzRegistry::Get(server_id); if (base_node == nullptr || @@ -263,7 +264,7 @@ char* grpc_channelz_get_server_sockets(intptr_t server_id, // actually a server node grpc_core::channelz::ServerNode* server_node = static_cast(base_node); - return server_node->RenderServerSockets(start_socket_id); + return server_node->RenderServerSockets(start_socket_id, max_results); } char* grpc_channelz_get_channel(intptr_t channel_id) { diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi index 113f7976dd..36c8cd121c 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi @@ -36,15 +36,17 @@ def channelz_get_server(server_id): ' server_id==%s is valid' % server_id) return c_returned_str -def channelz_get_server_sockets(server_id, start_socket_id): +def channelz_get_server_sockets(server_id, start_socket_id, max_results): cdef char *c_returned_str = grpc_channelz_get_server_sockets( server_id, start_socket_id, + max_results, ) if c_returned_str == NULL: raise ValueError('Failed to get server sockets, please ensure your' \ - ' server_id==%s and start_socket_id==%s is valid' % - (server_id, start_socket_id)) + ' server_id==%s and start_socket_id==%s and' \ + ' max_results==%s is valid' % + (server_id, start_socket_id, max_results)) return c_returned_str def channelz_get_channel(channel_id): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 5bbc10af25..fc7a9ba439 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -389,7 +389,8 @@ cdef extern from "grpc/grpc.h": char* grpc_channelz_get_servers(intptr_t start_server_id) char* grpc_channelz_get_server(intptr_t server_id) char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id) + intptr_t start_socket_id, + intptr_t max_results) char* grpc_channelz_get_channel(intptr_t channel_id) char* grpc_channelz_get_subchannel(intptr_t subchannel_id) char* grpc_channelz_get_socket(intptr_t socket_id) diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py index 573b9d0d5a..00eca311dc 100644 --- a/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py +++ b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py @@ -66,7 +66,8 @@ class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer): try: return json_format.Parse( cygrpc.channelz_get_server_sockets(request.server_id, - request.start_socket_id), + request.start_socket_id, + request.max_results), _channelz_pb2.GetServerSocketsResponse(), ) except ValueError as e: diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 56d222c7ec..e61a35d09f 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -272,7 +272,7 @@ extern grpc_channelz_get_servers_type grpc_channelz_get_servers_import; typedef char*(*grpc_channelz_get_server_type)(intptr_t server_id); extern grpc_channelz_get_server_type grpc_channelz_get_server_import; #define grpc_channelz_get_server grpc_channelz_get_server_import -typedef char*(*grpc_channelz_get_server_sockets_type)(intptr_t server_id, intptr_t start_socket_id); +typedef char*(*grpc_channelz_get_server_sockets_type)(intptr_t server_id, intptr_t start_socket_id, intptr_t max_results); extern grpc_channelz_get_server_sockets_type grpc_channelz_get_server_sockets_import; #define grpc_channelz_get_server_sockets grpc_channelz_get_server_sockets_import typedef char*(*grpc_channelz_get_channel_type)(intptr_t channel_id); diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 49a0bc8011..169190eec0 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -259,7 +259,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); - json = channelz_server->RenderServerSockets(0); + json = channelz_server->RenderServerSockets(0, 100); GPR_ASSERT(nullptr != strstr(json, "\"end\":true")); gpr_free(json); -- cgit v1.2.3 From a6ed43b41fec1201c3d239ee2910aac65cba9d90 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 10:27:11 -0800 Subject: reviewer feedback --- src/core/lib/channel/channelz.cc | 20 ++++++-------------- src/proto/grpc/channelz/channelz.proto | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 3fcfa2a412..10d5e1b581 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -205,28 +205,20 @@ ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id, intptr_t max_results) { - // if user does not set max_results, we choose 500. - int pagination_limit = max_results == 0 ? 500 : max_results; + // if user does not set max_results, we choose 1000. + size_t pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; ChildSocketsList socket_refs; grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); - int sockets_added = 0; - bool reached_pagination_limit = false; + // declared early so it can be used outside of the loop. + size_t i = 0; if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); - for (size_t i = 0; i < socket_refs.size(); ++i) { - // check if we are over pagination limit to determine if we need to set - // the "end" element. If we don't go through this block, we know that - // when the loop terminates, we have <= to pagination_limit. - if (sockets_added == pagination_limit) { - reached_pagination_limit = true; - break; - } - sockets_added++; + for (i = 0; i < GPR_MIN(socket_refs.size(), pagination_limit); ++i) { grpc_json* socket_ref_json = grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); @@ -236,7 +228,7 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id, socket_refs[i]->remote(), GRPC_JSON_STRING, false); } } - if (!reached_pagination_limit) { + if (i == socket_refs.size()) { json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, GRPC_JSON_TRUE, false); } diff --git a/src/proto/grpc/channelz/channelz.proto b/src/proto/grpc/channelz/channelz.proto index 9d73f37554..20de23f7fa 100644 --- a/src/proto/grpc/channelz/channelz.proto +++ b/src/proto/grpc/channelz/channelz.proto @@ -561,4 +561,4 @@ message GetSocketResponse { // The Socket that corresponds to the requested socket_id. This field // should be set. Socket socket = 1; -} \ No newline at end of file +} -- cgit v1.2.3 From c7f7db65e0fdc058b4caa2b76baaa308465fda9e Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 11:28:12 -0800 Subject: Add test and fix bug --- src/core/lib/channel/channelz.cc | 7 ++- src/cpp/server/channelz/channelz_service.cc | 4 +- test/cpp/end2end/channelz_service_test.cc | 82 +++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 10d5e1b581..8a596ad460 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -205,7 +205,7 @@ ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id, intptr_t max_results) { - // if user does not set max_results, we choose 1000. + // if user does not set max_results, we choose 500. size_t pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -219,9 +219,8 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id, grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); for (i = 0; i < GPR_MIN(socket_refs.size(), pagination_limit); ++i) { - grpc_json* socket_ref_json = - grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, - GRPC_JSON_OBJECT, false); + grpc_json* socket_ref_json = grpc_json_create_child( + nullptr, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); json_iterator = grpc_json_add_number_string_child( socket_ref_json, nullptr, "socketId", socket_refs[i]->uuid()); grpc_json_create_child(json_iterator, socket_ref_json, "name", diff --git a/src/cpp/server/channelz/channelz_service.cc b/src/cpp/server/channelz/channelz_service.cc index 9ecb9de7e4..c44a9ac0de 100644 --- a/src/cpp/server/channelz/channelz_service.cc +++ b/src/cpp/server/channelz/channelz_service.cc @@ -79,8 +79,8 @@ Status ChannelzService::GetServer(ServerContext* unused, Status ChannelzService::GetServerSockets( ServerContext* unused, const channelz::v1::GetServerSocketsRequest* request, channelz::v1::GetServerSocketsResponse* response) { - char* json_str = grpc_channelz_get_server_sockets(request->server_id(), - request->start_socket_id()); + char* json_str = grpc_channelz_get_server_sockets( + request->server_id(), request->start_socket_id(), request->max_results()); if (json_str == nullptr) { return Status(StatusCode::INTERNAL, "grpc_channelz_get_server_sockets returned null"); diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index 29b59e4e5e..425334d972 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -54,6 +54,14 @@ using grpc::channelz::v1::GetSubchannelResponse; using grpc::channelz::v1::GetTopChannelsRequest; using grpc::channelz::v1::GetTopChannelsResponse; +// This code snippet can be used to print out any responses for +// visual debugging. +// +// +// string out_str; +// google::protobuf::TextFormat::PrintToString(resp, &out_str); +// std::cout << "resp: " << out_str << "\n"; + namespace grpc { namespace testing { namespace { @@ -164,6 +172,19 @@ class ChannelzServerTest : public ::testing::Test { echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); } + std::unique_ptr NewEchoStub() { + static int salt = 0; + 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); + // This ensures that gRPC will not do connection sharing. + args.SetInt("salt", salt++); + std::shared_ptr channel = + CreateCustomChannel(target, InsecureChannelCredentials(), args); + return grpc::testing::EchoTestService::NewStub(channel); + } + void SendSuccessfulEcho(int channel_idx) { EchoRequest request; EchoResponse response; @@ -651,6 +672,67 @@ TEST_F(ChannelzServerTest, GetServerSocketsTest) { EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); } +TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { + ResetStubs(); + ConfigureProxy(1); + std::vector> stubs; + const int kNumServerSocketsCreated = 20; + for (int i = 0; i < kNumServerSocketsCreated; ++i) { + stubs.push_back(NewEchoStub()); + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + request.mutable_param()->set_backend_channel_idx(0); + ClientContext context; + Status s = stubs.back()->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + } + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + // Make a request that gets all of the serversockets + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + // We add one to account the the channelz stub that will end up creating + // a serversocket. + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), + kNumServerSocketsCreated + 1); + EXPECT_TRUE(get_server_sockets_response.end()); + } + // Now we make a request that exercises pagination. + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + const int kMaxResults = 10; + get_server_sockets_request.set_max_results(kMaxResults); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults); + EXPECT_FALSE(get_server_sockets_response.end()); + } +} + TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { ResetStubs(); ConfigureProxy(1); -- cgit v1.2.3