Merge remote-tracking branch 'upstream/master' into security_handshaker2

pull/8913/head
Mark D. Roth 8 years ago
commit 86a893d52e
  1. 1
      build.yaml
  2. 130
      src/core/ext/client_channel/subchannel.c
  3. 8
      src/core/lib/iomgr/socket_windows.c
  4. 1
      src/core/lib/iomgr/socket_windows.h
  5. 26
      src/core/lib/iomgr/tcp_client_windows.c
  6. 86
      src/core/lib/iomgr/tcp_server_windows.c
  7. 3
      src/core/lib/support/subprocess_posix.c
  8. 13
      src/core/lib/transport/connectivity_state.c
  9. 5
      src/core/lib/transport/connectivity_state.h
  10. 3
      src/csharp/Grpc.Core.Tests/SanityTest.cs
  11. 14
      src/csharp/Grpc.Dotnet.sln
  12. 24
      src/csharp/Grpc.Examples/Math.cs
  13. 2
      src/csharp/Grpc.Examples/MathGrpc.cs
  14. 22
      src/csharp/Grpc.HealthCheck/Health.cs
  15. 2
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  16. 2
      src/csharp/Grpc.Reflection.Tests/.gitignore
  17. 94
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj
  18. 8
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.project.json
  19. 18
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.xproj
  20. 59
      src/csharp/Grpc.Reflection.Tests/NUnitMain.cs
  21. 44
      src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs
  22. 154
      src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs
  23. 63
      src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs
  24. 7
      src/csharp/Grpc.Reflection.Tests/packages.config
  25. 65
      src/csharp/Grpc.Reflection.Tests/project.json
  26. 2
      src/csharp/Grpc.Reflection/.gitignore
  27. 84
      src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
  28. 28
      src/csharp/Grpc.Reflection/Grpc.Reflection.nuspec
  29. 8
      src/csharp/Grpc.Reflection/Grpc.Reflection.project.json
  30. 18
      src/csharp/Grpc.Reflection/Grpc.Reflection.xproj
  31. 44
      src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs
  32. 1556
      src/csharp/Grpc.Reflection/Reflection.cs
  33. 132
      src/csharp/Grpc.Reflection/ReflectionGrpc.cs
  34. 173
      src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs
  35. 10
      src/csharp/Grpc.Reflection/Settings.StyleCop
  36. 160
      src/csharp/Grpc.Reflection/SymbolRegistry.cs
  37. 5
      src/csharp/Grpc.Reflection/packages.config
  38. 40
      src/csharp/Grpc.Reflection/project.json
  39. 16
      src/csharp/Grpc.sln
  40. 11
      src/csharp/generate_proto_csharp.sh
  41. 4
      src/csharp/tests.json
  42. 26
      templates/src/csharp/Grpc.Reflection.Tests/project.json.template
  43. 42
      templates/src/csharp/Grpc.Reflection/project.json.template
  44. 19
      test/cpp/end2end/async_end2end_test.cc
  45. 20
      test/cpp/end2end/end2end_test.cc
  46. 59
      test/cpp/grpclb/grpclb_test.cc
  47. 1
      test/cpp/interop/client.cc
  48. 10
      test/cpp/interop/client_helper.cc
  49. 1
      test/cpp/interop/interop_server.cc
  50. 18
      test/cpp/interop/server_helper.cc
  51. 1
      test/cpp/interop/stress_test.cc
  52. 65
      test/cpp/qps/json_run_localhost.cc
  53. 64
      test/cpp/util/create_test_channel.cc
  54. 4
      test/cpp/util/create_test_channel.h
  55. 52
      test/cpp/util/test_credentials_provider.cc
  56. 50
      test/cpp/util/test_credentials_provider.h
  57. 2
      tools/README.md
  58. 6
      tools/internal_ci/README.md
  59. 34
      tools/internal_ci/linux/grpc_master.cfg
  60. 45
      tools/internal_ci/linux/run_tests.sh
  61. 5
      tools/jenkins/README.md
  62. 1
      tools/run_tests/sources_and_headers.json
  63. 3
      vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj

@ -1243,7 +1243,6 @@ libs:
src:
- test/cpp/interop/server_helper.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc

@ -133,6 +133,8 @@ struct grpc_subchannel {
gpr_backoff backoff_state;
/** do we have an active alarm? */
bool have_alarm;
/** have we started the backoff loop */
bool backoff_begun;
/** our alarm */
grpc_timer alarm;
};
@ -370,7 +372,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
return grpc_subchannel_index_register(exec_ctx, key, c);
}
static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
static void continue_connect_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;
@ -386,12 +389,6 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
&c->connected);
}
static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
c->next_attempt =
gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
}
grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
grpc_error **error) {
grpc_connectivity_state state;
@ -418,6 +415,73 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
follow_up->cb(exec_ctx, follow_up->cb_arg, error);
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = false;
if (c->disconnected) {
error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
} else {
GRPC_ERROR_REF(error);
}
if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect_locked(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
GRPC_ERROR_UNREF(error);
}
static void maybe_start_connecting_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
if (c->disconnected) {
/* Don't try to connect if we're already disconnected */
return;
}
if (c->connecting) {
/* Already connecting: don't restart */
return;
}
if (GET_CONNECTED_SUBCHANNEL(c, no_barrier) != NULL) {
/* Already connected: don't restart */
return;
}
if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) {
/* Nobody is interested in connecting: so don't just yet */
return;
}
c->connecting = true;
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
if (!c->backoff_begun) {
c->backoff_begun = true;
c->next_attempt = gpr_backoff_begin(&c->backoff_state, now);
continue_connect_locked(exec_ctx, c);
} else {
GPR_ASSERT(!c->have_alarm);
c->have_alarm = true;
gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
0) {
gpr_log(GPR_INFO, "Retry immediately");
} else {
gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
time_til_next.tv_sec, time_til_next.tv_nsec);
}
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
}
}
void grpc_subchannel_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
@ -449,13 +513,9 @@ void grpc_subchannel_notify_on_state_change(
w->next = &c->root_external_state_watcher;
w->prev = w->next->prev;
w->next->prev = w->prev->next = w;
if (grpc_connectivity_state_notify_on_state_change(
exec_ctx, &c->state_tracker, state, &w->closure)) {
c->connecting = true;
/* released by connection */
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
start_connect(exec_ctx, c);
}
grpc_connectivity_state_notify_on_state_change(exec_ctx, &c->state_tracker,
state, &w->closure);
maybe_start_connecting_locked(exec_ctx, c);
gpr_mu_unlock(&c->mu);
}
}
@ -575,7 +635,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
Re-evaluate if we really need this. */
gpr_atm_full_barrier();
GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
c->connecting = false;
/* setup subchannel watching connected subchannel for changes; subchannel
ref for connecting is donated to the state watcher */
@ -590,28 +649,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE, "connected");
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = false;
if (c->disconnected) {
error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
} else {
GRPC_ERROR_REF(error);
}
if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
GRPC_ERROR_UNREF(error);
}
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_subchannel *c = arg;
@ -619,35 +656,28 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
gpr_mu_lock(&c->mu);
c->connecting = false;
if (c->connecting_result.transport != NULL) {
publish_transport_locked(exec_ctx, c);
} else if (c->disconnected) {
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
GPR_ASSERT(!c->have_alarm);
c->have_alarm = true;
grpc_connectivity_state_set(
exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
"connect_failed");
gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
const char *errmsg = grpc_error_string(error);
gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
0) {
gpr_log(GPR_INFO, "Retry immediately");
} else {
gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
time_til_next.tv_sec, time_til_next.tv_nsec);
}
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
grpc_error_free_string(errmsg);
maybe_start_connecting_locked(exec_ctx, c);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connected");
grpc_channel_args_destroy(delete_channel_args);
}

@ -76,6 +76,14 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
LPFN_DISCONNECTEX DisconnectEx;
DWORD ioctl_num_bytes;
gpr_mu_lock(&winsocket->state_mu);
if (winsocket->shutdown_called) {
gpr_mu_unlock(&winsocket->state_mu);
return;
}
winsocket->shutdown_called = true;
gpr_mu_unlock(&winsocket->state_mu);
status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx),
&ioctl_num_bytes, NULL, NULL);

@ -87,6 +87,7 @@ typedef struct grpc_winsocket {
grpc_winsocket_callback_info read_info;
gpr_mu state_mu;
bool shutdown_called;
/* You can't add the same socket twice to the same IO Completion Port.
This prevents that. */

@ -107,18 +107,22 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
gpr_mu_lock(&ac->mu);
if (error == GRPC_ERROR_NONE && socket != NULL) {
DWORD transfered_bytes = 0;
DWORD flags;
BOOL wsa_success =
WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
&transfered_bytes, FALSE, &flags);
GPR_ASSERT(transfered_bytes == 0);
if (!wsa_success) {
error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
if (error == GRPC_ERROR_NONE) {
if (socket != NULL) {
DWORD transfered_bytes = 0;
DWORD flags;
BOOL wsa_success =
WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
&transfered_bytes, FALSE, &flags);
GPR_ASSERT(transfered_bytes == 0);
if (!wsa_success) {
error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
} else {
*ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name);
socket = NULL;
}
} else {
*ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name);
socket = NULL;
error = GRPC_ERROR_CREATE("socket is null");
}
}

@ -73,6 +73,7 @@ struct grpc_tcp_listener {
/* The cached AcceptEx for that port. */
LPFN_ACCEPTEX AcceptEx;
int shutting_down;
int outstanding_calls;
/* closure for socket notification of accept being ready */
grpc_closure on_accept;
/* linked list */
@ -140,10 +141,9 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE;
}
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
if (s->shutdown_complete != NULL) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
}
static void destroy_server(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_tcp_server *s = arg;
/* Now that the accepts have been aborted, we can destroy the sockets.
The IOCP won't get notified on these, so we can flag them as already
@ -159,6 +159,16 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
gpr_free(s);
}
static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_server *s) {
if (s->shutdown_complete != NULL) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
}
grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(destroy_server, s),
GRPC_ERROR_NONE, NULL);
}
grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
gpr_ref_non_zero(&s->refs);
return s;
@ -180,17 +190,14 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
/* First, shutdown all fd's. This will queue abortion calls for all
of the pending accepts due to the normal operation mechanism. */
if (s->active_ports == 0) {
immediately_done = 1;
}
for (sp = s->head; sp; sp = sp->next) {
sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket);
finish_shutdown_locked(exec_ctx, s);
} else {
for (sp = s->head; sp; sp = sp->next) {
sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket);
}
}
gpr_mu_unlock(&s->mu);
if (immediately_done) {
finish_shutdown(exec_ctx, s);
}
}
void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
@ -251,31 +258,30 @@ failure:
return error;
}
static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *sp) {
static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *sp) {
int notify = 0;
sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports) {
notify = 1;
}
gpr_mu_unlock(&sp->server->mu);
if (notify) {
finish_shutdown(exec_ctx, sp->server);
finish_shutdown_locked(exec_ctx, sp->server);
}
}
/* In order to do an async accept, we need to create a socket first which
will be the one assigned to the new incoming connection. */
static grpc_error *start_accept(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *port) {
static grpc_error *start_accept_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *port) {
SOCKET sock = INVALID_SOCKET;
BOOL success;
DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
DWORD bytes_received = 0;
grpc_error *error = GRPC_ERROR_NONE;
if (port->shutting_down) {
return GRPC_ERROR_NONE;
}
sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
WSA_FLAG_OVERLAPPED);
if (sock == INVALID_SOCKET) {
@ -305,20 +311,11 @@ static grpc_error *start_accept(grpc_exec_ctx *exec_ctx,
immediately process an accept that happened in the meantime. */
port->new_socket = sock;
grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
port->outstanding_calls++;
return error;
failure:
GPR_ASSERT(error != GRPC_ERROR_NONE);
if (port->shutting_down) {
/* We are abandoning the listener port, take that into account to prevent
occasional hangs on shutdown. The hang happens when sp->shutting_down
change is not seen by on_accept and we proceed to trying new accept,
but we fail there because the listening port has been closed in the
meantime. */
decrement_active_ports_and_notify(exec_ctx, port);
GRPC_ERROR_UNREF(error);
return GRPC_ERROR_NONE;
}
if (sock != INVALID_SOCKET) closesocket(sock);
return error;
}
@ -338,6 +335,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
BOOL wsa_success;
int err;
gpr_mu_lock(&sp->server->mu);
peer_name.len = sizeof(struct sockaddr_storage);
/* The general mechanism for shutting down is to queue abortion calls. While
@ -347,6 +346,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
const char *msg = grpc_error_string(error);
gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
grpc_error_free_string(msg);
gpr_mu_unlock(&sp->server->mu);
return;
}
@ -356,17 +356,12 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
&transfered_bytes, FALSE, &flags);
if (!wsa_success) {
if (sp->shutting_down) {
/* During the shutdown case, we ARE expecting an error. So that's well,
and we can wake up the shutdown thread. */
decrement_active_ports_and_notify(exec_ctx, sp);
return;
} else {
if (!sp->shutting_down) {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
gpr_free(utf8_message);
closesocket(sock);
}
closesocket(sock);
} else {
if (!sp->shutting_down) {
peer_name_string = NULL;
@ -408,7 +403,12 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
the former socked we created has now either been destroy or assigned
to the new connection. We need to create a new one for the next
connection. */
GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp)));
GPR_ASSERT(
GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
if (0 == --sp->outstanding_calls) {
decrement_active_ports_and_notify_locked(exec_ctx, sp);
}
gpr_mu_unlock(&sp->server->mu);
}
static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
@ -456,6 +456,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
sp->server = s;
sp->socket = grpc_winsocket_create(sock, "listener");
sp->shutting_down = 0;
sp->outstanding_calls = 0;
sp->AcceptEx = AcceptEx;
sp->new_socket = INVALID_SOCKET;
sp->port = port;
@ -553,7 +554,8 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
s->on_accept_cb = on_accept_cb;
s->on_accept_cb_arg = on_accept_cb_arg;
for (sp = s->head; sp; sp = sp->next) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp)));
GPR_ASSERT(
GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
s->active_ports++;
}
gpr_mu_unlock(&s->mu);

@ -98,7 +98,8 @@ retry:
if (errno == EINTR) {
goto retry;
}
gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno));
gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid,
strerror(errno));
return -1;
}
p->joined = true;

@ -100,7 +100,12 @@ grpc_connectivity_state grpc_connectivity_state_check(
return tracker->current_state;
}
int grpc_connectivity_state_notify_on_state_change(
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker *connectivity_state) {
return connectivity_state->watchers != NULL;
}
bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify) {
if (grpc_connectivity_state_trace) {
@ -119,7 +124,7 @@ int grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
tracker->watchers = w->next;
gpr_free(w);
return 0;
return false;
}
while (w != NULL) {
grpc_connectivity_state_watcher *rm_candidate = w->next;
@ -127,11 +132,11 @@ int grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
w->next = w->next->next;
gpr_free(rm_candidate);
return 0;
return false;
}
w = w->next;
}
return 0;
return false;
} else {
if (tracker->current_state != *current) {
*current = tracker->current_state;

@ -75,13 +75,16 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
grpc_error *associated_error,
const char *reason);
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker *tracker);
grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state_tracker *tracker, grpc_error **current_error);
/** Return 1 if the channel should start connecting, 0 otherwise.
If current==NULL cancel notify if it is already queued (success==0 in that
case) */
int grpc_connectivity_state_notify_on_state_change(
bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify);

@ -115,7 +115,8 @@ namespace Grpc.Core.Tests
var otherAssemblies = new[] {
"Grpc.Examples.Tests",
"Grpc.HealthCheck.Tests",
"Grpc.IntegrationTesting"
"Grpc.IntegrationTesting",
"Grpc.Reflection.Tests",
};
foreach (var assemblyName in otherAssemblies)
{

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Core", "Grpc.Core\Grpc.Core.xproj", "{DC9908B6-F291-4FC8-A46D-2EA2551790EC}"
EndProject
@ -31,6 +31,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.Ser
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.xproj", "{0EBC910B-8867-4D3E-8686-91F34183D839}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.xproj", "{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.xproj", "{FE90181D-A4B3-4A5C-8490-F07561E18E3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -93,6 +97,14 @@ Global
{0EBC910B-8867-4D3E-8686-91F34183D839}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.Build.0 = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.Build.0 = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto
// source: math/math.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Math {
/// <summary>Holder for reflection information generated from math.proto</summary>
/// <summary>Holder for reflection information generated from math/math.proto</summary>
public static partial class MathReflection {
#region Descriptor
/// <summary>File descriptor for math.proto</summary>
/// <summary>File descriptor for math/math.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
@ -22,15 +22,15 @@ namespace Math {
static MathReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB",
"KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB",
"IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB",
"IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50",
"GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu",
"RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E",
"aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51",
"bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv",
"Mw=="));
"Cg9tYXRoL21hdGgucHJvdG8SBG1hdGgiLAoHRGl2QXJncxIQCghkaXZpZGVu",
"ZBgBIAEoAxIPCgdkaXZpc29yGAIgASgDIi8KCERpdlJlcGx5EhAKCHF1b3Rp",
"ZW50GAEgASgDEhEKCXJlbWFpbmRlchgCIAEoAyIYCgdGaWJBcmdzEg0KBWxp",
"bWl0GAEgASgDIhIKA051bRILCgNudW0YASABKAMiGQoIRmliUmVwbHkSDQoF",
"Y291bnQYASABKAMypAEKBE1hdGgSJgoDRGl2Eg0ubWF0aC5EaXZBcmdzGg4u",
"bWF0aC5EaXZSZXBseSIAEi4KB0Rpdk1hbnkSDS5tYXRoLkRpdkFyZ3MaDi5t",
"YXRoLkRpdlJlcGx5IgAoATABEiMKA0ZpYhINLm1hdGguRmliQXJncxoJLm1h",
"dGguTnVtIgAwARIfCgNTdW0SCS5tYXRoLk51bRoJLm1hdGguTnVtIgAoAWIG",
"cHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto
// source: math/math.proto
// Original file comments:
// Copyright 2015, Google Inc.
// All rights reserved.

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: health.proto
// source: grpc/health/v1/health.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Health.V1 {
/// <summary>Holder for reflection information generated from health.proto</summary>
/// <summary>Holder for reflection information generated from grpc/health/v1/health.proto</summary>
public static partial class HealthReflection {
#region Descriptor
/// <summary>File descriptor for health.proto</summary>
/// <summary>File descriptor for grpc/health/v1/health.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
@ -22,14 +22,14 @@ namespace Grpc.Health.V1 {
static HealthReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CgxoZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYxIiUKEkhlYWx0aENoZWNr",
"UmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNIZWFsdGhDaGVja1Jlc3Bv",
"bnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVhbHRoLnYxLkhlYWx0aENo",
"ZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsK",
"B1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9UX1NFUlZJTkcQAjJaCgZI",
"ZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jl",
"cXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jlc3BvbnNlQhGq",
"Ag5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
"ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx",
"IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNI",
"ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh",
"bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1T",
"ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
"X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52",
"MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD",
"aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: health.proto
// source: grpc/health/v1/health.proto
// Original file comments:
// Copyright 2015, Google Inc.
// All rights reserved.

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B88F91D6-436D-4C78-8B99-47800FA8DE03}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Grpc.Reflection.Tests</RootNamespace>
<AssemblyName>Grpc.Reflection.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="SymbolRegistryTest.cs" />
<Compile Include="ReflectionClientServerTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="NUnitMain.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.Reflection\Grpc.Reflection.csproj">
<Project>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</Project>
<Name>Grpc.Reflection</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Reflection.Tests.project.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,8 @@
{
"frameworks": {
"net45": { }
},
"runtimes": {
"win": { }
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>fe90181d-a4b3-4a5c-8490-f07561e18e3b</ProjectGuid>
<RootNamespace>Grpc.Reflection.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

@ -0,0 +1,59 @@
#region Copyright notice and license
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Reflection;
using Grpc.Core;
using Grpc.Core.Logging;
using NUnit.Common;
using NUnitLite;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Provides entry point for NUnitLite
/// </summary>
public class NUnitMain
{
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
#endif
}
}
}

@ -0,0 +1,44 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Reflection.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -0,0 +1,154 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Reflection;
using Grpc.Reflection.V1Alpha;
using NUnit.Framework;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Reflection client talks to reflection server.
/// </summary>
public class ReflectionClientServerTest
{
const string Host = "localhost";
Server server;
Channel channel;
ServerReflection.ServerReflectionClient client;
ReflectionServiceImpl serviceImpl;
[TestFixtureSetUp]
public void Init()
{
serviceImpl = new ReflectionServiceImpl(ServerReflection.Descriptor);
server = new Server
{
Services = { ServerReflection.BindService(serviceImpl) },
Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = new ServerReflection.ServerReflectionClient(channel);
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public async Task FileByFilename_NotFound()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileByFilename = "somepackage/nonexistent.proto"
});
Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode);
}
[Test]
public async Task FileByFilename()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileByFilename = "grpc/reflection/v1alpha/reflection.proto"
});
Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count);
Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]);
}
[Test]
public async Task FileContainingSymbol()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingSymbol = "grpc.reflection.v1alpha.ServerReflection"
});
Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count);
Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]);
}
[Test]
public async Task FileContainingSymbol_NotFound()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingSymbol = "somepackage.Nonexistent"
});
Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode);
}
[Test]
public async Task ListServices()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
ListServices = ""
});
Assert.AreEqual(1, response.ListServicesResponse.Service.Count);
Assert.AreEqual(ServerReflection.Descriptor.FullName, response.ListServicesResponse.Service[0].Name);
}
[Test]
public async Task FileContainingExtension()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingExtension = new ExtensionRequest()
});
Assert.AreEqual((int)StatusCode.Unimplemented, response.ErrorResponse.ErrorCode);
}
private async Task<ServerReflectionResponse> SingleRequestAsync(ServerReflectionRequest request)
{
var call = client.ServerReflectionInfo();
await call.RequestStream.WriteAsync(request);
Assert.IsTrue(await call.ResponseStream.MoveNext());
var response = call.ResponseStream.Current;
await call.RequestStream.CompleteAsync();
Assert.IsFalse(await call.ResponseStream.MoveNext());
return response;
}
}
}

@ -0,0 +1,63 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using Grpc.Reflection;
using Grpc.Reflection.V1Alpha;
using NUnit.Framework;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Tests for ReflectionServiceImpl
/// </summary>
public class SymbolRegistryTest
{
SymbolRegistry registry = SymbolRegistry.FromFiles(new[] { ReflectionReflection.Descriptor, Google.Protobuf.WellKnownTypes.Duration.Descriptor.File });
[Test]
public void FileByName()
{
Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileByName("google/protobuf/duration.proto"));
Assert.IsNull(registry.FileByName("somepackage/nonexistent.proto"));
}
[Test]
public void FileContainingSymbol()
{
Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileContainingSymbol("google.protobuf.Duration"));
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo")); // method
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection")); // service
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflectionRequest")); // message
Assert.IsNull(registry.FileContainingSymbol("somepackage.Nonexistent"));
}
}
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -0,0 +1,65 @@
{
"buildOptions": {
"emitEntryPoint": true
},
"configurations": {
"Debug": {
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
},
"copyToOutput": {
"mappings": {
"grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
"grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
},
"Release": {
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
},
"copyToOutput": {
"mappings": {
"grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
"grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
}
},
"dependencies": {
"Grpc.Reflection": {
"target": "project"
},
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
"frameworks": {
"net45": { },
"netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
}
}

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Grpc.Reflection</RootNamespace>
<AssemblyName>Grpc.Reflection</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<DocumentationFile>bin\$(Configuration)\Grpc.Reflection.Xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="SymbolRegistry.cs" />
<Compile Include="ReflectionServiceImpl.cs" />
<Compile Include="Reflection.cs" />
<Compile Include="ReflectionGrpc.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Reflection.nuspec" />
<None Include="Grpc.Reflection.project.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>Grpc.Reflection</id>
<title>gRPC C# Reflection</title>
<summary>Implementation of gRPC reflection service</summary>
<description>Provides information about services running on a gRPC C# server.</description>
<version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<copyright>Copyright 2016, Google Inc.</copyright>
<tags>gRPC reflection</tags>
<dependencies>
<dependency id="Google.Protobuf" version="$ProtobufVersion$" />
<dependency id="Grpc.Core" version="$version$" />
<dependency id="System.Interactive.Async" version="3.1.1" />
</dependencies>
</metadata>
<files>
<file src="bin/ReleaseSigned/Grpc.Reflection.dll" target="lib/net45" />
<file src="bin/ReleaseSigned/Grpc.Reflection.pdb" target="lib/net45" />
<file src="bin/ReleaseSigned/Grpc.Reflection.xml" target="lib/net45" />
<file src="**\*.cs" target="src" />
</files>
</package>

@ -0,0 +1,8 @@
{
"frameworks": {
"net45": { }
},
"runtimes": {
"win": { }
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2b372155-80ba-4cf9-82d6-4b938e8ec3a0</ProjectGuid>
<RootNamespace>Grpc.Reflection</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

@ -0,0 +1,44 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Reflection")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,132 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: grpc/reflection/v1alpha/reflection.proto
// Original file comments:
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Service exported by server reflection
//
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Reflection.V1Alpha {
public static partial class ServerReflection
{
static readonly string __ServiceName = "grpc.reflection.v1alpha.ServerReflection";
static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> __Marshaller_ServerReflectionRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Marshaller_ServerReflectionResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser.ParseFrom);
static readonly Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Method_ServerReflectionInfo = new Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse>(
MethodType.DuplexStreaming,
__ServiceName,
"ServerReflectionInfo",
__Marshaller_ServerReflectionRequest,
__Marshaller_ServerReflectionResponse);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.Services[0]; }
}
/// <summary>Base class for server-side implementations of ServerReflection</summary>
public abstract partial class ServerReflectionBase
{
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(IAsyncStreamReader<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> requestStream, IServerStreamWriter<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for ServerReflection</summary>
public partial class ServerReflectionClient : ClientBase<ServerReflectionClient>
{
/// <summary>Creates a new client for ServerReflection</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public ServerReflectionClient(Channel channel) : base(channel)
{
}
/// <summary>Creates a new client for ServerReflection that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public ServerReflectionClient(CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected ServerReflectionClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected ServerReflectionClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return ServerReflectionInfo(new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override ServerReflectionClient NewInstance(ClientBaseConfiguration configuration)
{
return new ServerReflectionClient(configuration);
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
public static ServerServiceDefinition BindService(ServerReflectionBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build();
}
}
}
#endregion

@ -0,0 +1,173 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Reflection.V1Alpha;
using Google.Protobuf.Reflection;
namespace Grpc.Reflection
{
/// <summary>
/// Implementation of server reflection service.
/// </summary>
public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase
{
readonly List<string> services;
readonly SymbolRegistry symbolRegistry;
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(IEnumerable<string> services, SymbolRegistry symbolRegistry)
{
this.services = new List<string>(services);
this.symbolRegistry = symbolRegistry;
}
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(IEnumerable<ServiceDescriptor> serviceDescriptors)
{
this.services = new List<string>(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName));
this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File));
}
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable<ServiceDescriptor>) serviceDescriptors)
{
}
public override async Task ServerReflectionInfo(IAsyncStreamReader<ServerReflectionRequest> requestStream, IServerStreamWriter<ServerReflectionResponse> responseStream, ServerCallContext context)
{
while (await requestStream.MoveNext())
{
var response = ProcessRequest(requestStream.Current);
await responseStream.WriteAsync(response);
}
}
ServerReflectionResponse ProcessRequest(ServerReflectionRequest request)
{
switch (request.MessageRequestCase)
{
case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename:
return FileByFilename(request.FileByFilename);
case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol:
return FileContainingSymbol(request.FileContainingSymbol);
case ServerReflectionRequest.MessageRequestOneofCase.ListServices:
return ListServices();
case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType:
case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension:
default:
return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service.");
}
}
ServerReflectionResponse FileByFilename(string filename)
{
FileDescriptor file = symbolRegistry.FileByName(filename);
if (file == null)
{
return CreateErrorResponse(StatusCode.NotFound, "File not found.");
}
var transitiveDependencies = new HashSet<FileDescriptor>();
CollectTransitiveDependencies(file, transitiveDependencies);
return new ServerReflectionResponse
{
FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
};
}
ServerReflectionResponse FileContainingSymbol(string symbol)
{
FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol);
if (file == null)
{
return CreateErrorResponse(StatusCode.NotFound, "Symbol not found.");
}
var transitiveDependencies = new HashSet<FileDescriptor>();
CollectTransitiveDependencies(file, transitiveDependencies);
return new ServerReflectionResponse
{
FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
};
}
ServerReflectionResponse ListServices()
{
var serviceResponses = new ListServiceResponse();
foreach (string serviceName in services)
{
serviceResponses.Service.Add(new ServiceResponse { Name = serviceName });
}
return new ServerReflectionResponse
{
ListServicesResponse = serviceResponses
};
}
ServerReflectionResponse CreateErrorResponse(StatusCode status, string message)
{
return new ServerReflectionResponse
{
ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message }
};
}
void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet<FileDescriptor> pool)
{
pool.Add(descriptor);
foreach (var dependency in descriptor.Dependencies)
{
if (pool.Add(dependency))
{
// descriptors cannot have circular dependencies
CollectTransitiveDependencies(dependency, pool);
}
}
}
}
}

@ -0,0 +1,10 @@
<StyleCopSettings Version="105">
<SourceFileList>
<SourceFile>Health.cs</SourceFile>
<Settings>
<GlobalSettings>
<BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
</GlobalSettings>
</Settings>
</SourceFileList>
</StyleCopSettings>

@ -0,0 +1,160 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System.Collections.Generic;
using Grpc.Core.Utils;
using Google.Protobuf.Reflection;
namespace Grpc.Reflection
{
/// <summary>Registry of protobuf symbols</summary>
public class SymbolRegistry
{
private readonly Dictionary<string, FileDescriptor> filesByName;
private readonly Dictionary<string, FileDescriptor> filesBySymbol;
private SymbolRegistry(Dictionary<string, FileDescriptor> filesByName, Dictionary<string, FileDescriptor> filesBySymbol)
{
this.filesByName = new Dictionary<string, FileDescriptor>(filesByName);
this.filesBySymbol = new Dictionary<string, FileDescriptor>(filesBySymbol);
}
/// <summary>
/// Creates a symbol registry from the specified set of file descriptors.
/// </summary>
/// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
/// <returns>A symbol registry for the given files.</returns>
public static SymbolRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors)
{
GrpcPreconditions.CheckNotNull(fileDescriptors);
var builder = new Builder();
foreach (var file in fileDescriptors)
{
builder.AddFile(file);
}
return builder.Build();
}
/// <summary>
/// Gets file descriptor for given file name (including package path). Returns <c>null</c> if not found.
/// </summary>
public FileDescriptor FileByName(string filename)
{
FileDescriptor file;
filesByName.TryGetValue(filename, out file);
return file;
}
/// <summary>
/// Gets file descriptor that contains definition of given symbol full name (including package path). Returns <c>null</c> if not found.
/// </summary>
public FileDescriptor FileContainingSymbol(string symbol)
{
FileDescriptor file;
filesBySymbol.TryGetValue(symbol, out file);
return file;
}
/// <summary>
/// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls.
/// </summary>
private class Builder
{
private readonly Dictionary<string, FileDescriptor> filesByName;
private readonly Dictionary<string, FileDescriptor> filesBySymbol;
internal Builder()
{
filesByName = new Dictionary<string, FileDescriptor>();
filesBySymbol = new Dictionary<string, FileDescriptor>();
}
internal void AddFile(FileDescriptor fileDescriptor)
{
if (filesByName.ContainsKey(fileDescriptor.Name))
{
return;
}
filesByName.Add(fileDescriptor.Name, fileDescriptor);
foreach (var dependency in fileDescriptor.Dependencies)
{
AddFile(dependency);
}
foreach (var enumeration in fileDescriptor.EnumTypes)
{
AddEnum(enumeration);
}
foreach (var message in fileDescriptor.MessageTypes)
{
AddMessage(message);
}
foreach (var service in fileDescriptor.Services)
{
AddService(service);
}
}
private void AddEnum(EnumDescriptor enumDescriptor)
{
filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File;
}
private void AddMessage(MessageDescriptor messageDescriptor)
{
foreach (var nestedEnum in messageDescriptor.EnumTypes)
{
AddEnum(nestedEnum);
}
foreach (var nestedType in messageDescriptor.NestedTypes)
{
AddMessage(nestedType);
}
filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File;
}
private void AddService(ServiceDescriptor serviceDescriptor)
{
foreach (var method in serviceDescriptor.Methods)
{
filesBySymbol[method.FullName] = method.File;
}
filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File;
}
internal SymbolRegistry Build()
{
return new SymbolRegistry(filesByName, filesBySymbol);
}
}
}
}

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -0,0 +1,40 @@
{
"version": "1.1.0-dev",
"title": "gRPC C# Reflection",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2016, Google Inc.",
"packOptions": {
"summary": "Implementation of gRPC reflection service",
"description": "Provides information about services running on a gRPC C# server.",
"owners": [ "grpc-packages" ],
"licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
"projectUrl": "https://github.com/grpc/grpc",
"requireLicenseAcceptance": false,
"tags": [ "gRPC reflection" ]
},
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
}
},
"dependencies": {
"Grpc.Core": "1.1.0-dev",
"Google.Protobuf": "3.0.0"
},
"frameworks": {
"net45": {
"frameworkAssemblies": {
"System.Runtime": "",
"System.IO": ""
}
},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}

@ -36,6 +36,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Qps
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.csproj", "{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{B88F91D6-436D-4C78-8B99-47800FA8DE03}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -55,6 +59,12 @@ Global
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.Build.0 = Release|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -103,6 +113,12 @@ Global
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.Build.0 = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU

@ -36,13 +36,20 @@ PROTOC=bins/opt/protobuf/protoc
PLUGIN=protoc-gen-grpc=bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=src/csharp/Grpc.Examples
HEALTHCHECK_DIR=src/csharp/Grpc.HealthCheck
REFLECTION_DIR=src/csharp/Grpc.Reflection
TESTING_DIR=src/csharp/Grpc.IntegrationTesting
$PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
-I src/proto/math src/proto/math/math.proto
-I src/proto src/proto/math/math.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
-I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
-I src/proto src/proto/grpc/health/v1/health.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR \
-I src/proto src/proto/grpc/reflection/v1alpha/reflection.proto
# TODO(jtattermusch): following .proto files are a bit broken and import paths
# don't match the package names. Setting -I to the correct value src/proto
# breaks the code generation.
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto

@ -48,5 +48,9 @@
"Grpc.IntegrationTesting.MetadataCredentialsTest",
"Grpc.IntegrationTesting.RunnerClientServerTest",
"Grpc.IntegrationTesting.SslCredentialsTest"
],
"Grpc.Reflection.Tests": [
"Grpc.Reflection.Tests.ReflectionClientServerTest",
"Grpc.Reflection.Tests.SymbolRegistryTest"
]
}

@ -0,0 +1,26 @@
%YAML 1.2
--- |
{
<%include file="../build_options.include" args="executable=True"/>
"dependencies": {
"Grpc.Reflection": {
"target": "project"
},
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
"frameworks": {
"net45": { },
"netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
}
}

@ -0,0 +1,42 @@
%YAML 1.2
--- |
{
"version": "${settings.csharp_version}",
"title": "gRPC C# Reflection",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2016, Google Inc.",
"packOptions": {
"summary": "Implementation of gRPC reflection service",
"description": "Provides information about services running on a gRPC C# server.",
"owners": [ "grpc-packages" ],
"licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
"projectUrl": "https://github.com/grpc/grpc",
"requireLicenseAcceptance": false,
"tags": [ "gRPC reflection" ]
},
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
}
},
"dependencies": {
"Grpc.Core": "${settings.csharp_version}",
"Google.Protobuf": "3.0.0"
},
"frameworks": {
"net45": {
"frameworkAssemblies": {
"System.Runtime": "",
"System.IO": ""
}
},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}

@ -254,8 +254,7 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
// Setup server
ServerBuilder builder;
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
GetParam().credentials_type);
auto server_creds = GetServerCredentials(GetParam().credentials_type);
builder.AddListeningPort(server_address_.str(), server_creds);
builder.RegisterService(&service_);
cq_ = builder.AddCompletionQueue();
@ -284,8 +283,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
void ResetStub() {
ChannelArguments args;
auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
GetParam().credentials_type, &args);
auto channel_creds =
GetChannelCredentials(GetParam().credentials_type, &args);
std::shared_ptr<Channel> channel =
CreateCustomChannel(server_address_.str(), channel_creds, args);
stub_ = grpc::testing::EchoTestService::NewStub(channel);
@ -893,8 +892,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) {
TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
ChannelArguments args;
auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
GetParam().credentials_type, &args);
auto channel_creds =
GetChannelCredentials(GetParam().credentials_type, &args);
std::shared_ptr<Channel> channel =
CreateCustomChannel(server_address_.str(), channel_creds, args);
std::unique_ptr<grpc::testing::UnimplementedEchoService::Stub> stub;
@ -1405,15 +1404,11 @@ std::vector<TestScenario> CreateTestScenarios(bool test_disable_blocking,
std::vector<grpc::string> credentials_types;
std::vector<grpc::string> messages;
if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType,
nullptr) != nullptr) {
credentials_types.push_back(kInsecureCredentialsType);
}
auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList();
credentials_types.push_back(kInsecureCredentialsType);
auto sec_list = GetSecureCredentialsTypeList();
for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) {
credentials_types.push_back(*sec);
}
GPR_ASSERT(!credentials_types.empty());
messages.push_back("Hello");
for (int sz = 1; sz < test_big_limit; sz *= 2) {

@ -242,8 +242,7 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
// Setup server
ServerBuilder builder;
ConfigureServerBuilder(&builder);
auto server_creds = GetCredentialsProvider()->GetServerCredentials(
GetParam().credentials_type);
auto server_creds = GetServerCredentials(GetParam().credentials_type);
if (GetParam().credentials_type != kInsecureCredentialsType) {
server_creds->SetAuthMetadataProcessor(processor);
}
@ -271,8 +270,8 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
}
EXPECT_TRUE(is_server_started_);
ChannelArguments args;
auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
GetParam().credentials_type, &args);
auto channel_creds =
GetChannelCredentials(GetParam().credentials_type, &args);
if (!user_agent_prefix_.empty()) {
args.SetUserAgentPrefix(user_agent_prefix_);
}
@ -1521,18 +1520,11 @@ std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
std::vector<TestScenario> scenarios;
std::vector<grpc::string> credentials_types;
if (test_secure) {
credentials_types =
GetCredentialsProvider()->GetSecureCredentialsTypeList();
credentials_types = GetSecureCredentialsTypeList();
}
if (test_insecure) {
// Only add insecure credentials type when it is registered with the
// provider. User may create providers that do not have insecure.
if (GetCredentialsProvider()->GetChannelCredentials(
kInsecureCredentialsType, nullptr) != nullptr) {
credentials_types.push_back(kInsecureCredentialsType);
}
credentials_types.push_back(kInsecureCredentialsType);
}
GPR_ASSERT(!credentials_types.empty());
for (auto it = credentials_types.begin(); it != credentials_types.end();
++it) {
scenarios.emplace_back(false, *it);
@ -1549,7 +1541,7 @@ INSTANTIATE_TEST_CASE_P(End2end, End2endTest,
INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest,
::testing::ValuesIn(CreateTestScenarios(false, true,
true)));
false)));
INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true, true,

@ -523,9 +523,8 @@ static void perform_request(client_fixture *cf) {
CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "Client after sending msg %d / 4", i + 1);
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, PAYLOAD));
GPR_ASSERT(grpc_channel_check_connectivity_state(
cf->client, 0 /* try to connect */) == GRPC_CHANNEL_READY);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
@ -546,16 +545,17 @@ static void perform_request(client_fixture *cf) {
cq_verify(cqv);
peer = grpc_call_get_peer(c);
gpr_log(GPR_INFO, "Client DONE WITH SERVER %s ", peer);
gpr_free(peer);
grpc_call_destroy(c);
cq_verify_empty_timeout(cqv, 1);
cq_verify_empty_timeout(cqv, 1 /* seconds */);
cq_verifier_destroy(cqv);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
gpr_free(details);
gpr_log(GPR_INFO, "Client call (peer %s) DESTROYED.", peer);
gpr_free(peer);
}
static void setup_client(const char *server_hostport, client_fixture *cf) {
@ -699,39 +699,42 @@ static test_fixture test_update(int lb_server_update_delay_ms) {
TEST(GrpclbTest, Updates) {
grpc::test_fixture tf_result;
// Clients take a bit over one second to complete a call (the last part of the
// Clients take at least one second to complete a call (the last part of the
// call sleeps for 1 second while verifying the client's completion queue is
// empty). Therefore:
// empty), more if the system is under load. Therefore:
//
// If the LB server waits 800ms before sending an update, it will arrive
// before the first client request is done, skipping the second server from
// batch 1 altogether: the 2nd client request will go to the 1st server of
// batch 2 (ie, the third one out of the four total servers).
// before the first client request finishes, skipping the second server from
// batch 1. All subsequent picks will come from the second half of the
// backends, those coming in the LB update.
tf_result = grpc::test_update(800);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 2);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
tf_result.lb_backends[3].num_calls_serviced >
0);
int num_serviced_calls = 0;
for (int i = 0; i < 4; i++) {
num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced;
}
GPR_ASSERT(num_serviced_calls == 4);
// If the LB server waits 1500ms, the update arrives after having picked the
// 2nd server from batch 1 but before the next pick for the first server of
// batch 2. All server are used.
tf_result = grpc::test_update(1500);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1);
// If the LB server waits > 2000ms, the update arrives after the first two
// request are done and the third pick is performed, which returns, in RR
// fashion, the 1st server of the 1st update. Therefore, the second server of
// batch 1 is hit at least one, whereas the first server of batch 2 is never
// hit.
// If the LB server waits 2500ms, the update arrives after two calls and three
// picks. The third pick will be the 1st server of the 1st update (RR policy
// going around). The fourth and final pick will come from the second LB
// update. In any case, the total number of serviced calls must again be equal
// to four across all the backends.
tf_result = grpc::test_update(2500);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced >= 1);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced > 0);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced > 0);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 0);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
tf_result.lb_backends[3].num_calls_serviced >
0);
num_serviced_calls = 0;
for (int i = 0; i < 4; i++) {
num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced;
}
GPR_ASSERT(num_serviced_calls == 4);
}
TEST(GrpclbTest, InvalidAddressInServerlist) {}

@ -49,7 +49,6 @@
#include "test/cpp/util/test_config.h"
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
DEFINE_int32(server_port, 0, "Server port.");
DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");

@ -50,10 +50,8 @@
#include "src/cpp/client/secure_credentials.h"
#include "test/core/security/oauth2_utils.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/test_credentials_provider.h"
DECLARE_bool(use_tls);
DECLARE_string(custom_credentials_type);
DECLARE_bool(use_test_ca);
DECLARE_int32(server_port);
DECLARE_string(server_host);
@ -116,12 +114,8 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
creds = AccessTokenCredentials(raw_token);
GPR_ASSERT(creds);
}
if (FLAGS_custom_credentials_type.empty()) {
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_use_tls, !FLAGS_use_test_ca, creds);
} else {
return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
}
return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls,
!FLAGS_use_test_ca, creds);
}
} // namespace testing

@ -56,7 +56,6 @@
#include "test/cpp/util/test_config.h"
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
DEFINE_int32(port, 0, "Server port.");
DEFINE_int32(max_send_message_size, -1, "The maximum send message size.");

@ -39,23 +39,23 @@
#include <grpc++/security/server_credentials.h>
#include "src/core/lib/surface/call_test_only.h"
#include "test/cpp/util/test_credentials_provider.h"
#include "test/core/end2end/data/ssl_test_data.h"
DECLARE_bool(use_tls);
DECLARE_string(custom_credentials_type);
namespace grpc {
namespace testing {
std::shared_ptr<ServerCredentials> CreateInteropServerCredentials() {
if (!FLAGS_custom_credentials_type.empty()) {
return GetCredentialsProvider()->GetServerCredentials(
FLAGS_custom_credentials_type);
} else if (FLAGS_use_tls) {
return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType);
if (FLAGS_use_tls) {
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);
return SslServerCredentials(ssl_opts);
} else {
return GetCredentialsProvider()->GetServerCredentials(
kInsecureCredentialsType);
return InsecureServerCredentials();
}
}

@ -147,7 +147,6 @@ DEFINE_bool(do_not_abort_on_transient_failures, true,
// Options from client.cc (for compatibility with interop test).
// TODO(sreek): Consolidate overlapping options
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
DEFINE_int32(server_port, 0, "Server port.");
DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");

@ -31,7 +31,11 @@
*
*/
#include <signal.h>
#include <string.h>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
@ -43,6 +47,11 @@
using grpc::SubProcess;
constexpr auto kNumWorkers = 2;
static SubProcess* g_driver;
static SubProcess* g_workers[kNumWorkers];
template <class T>
std::string as_string(const T& val) {
std::ostringstream out;
@ -50,6 +59,24 @@ std::string as_string(const T& val) {
return out.str();
}
static void sighandler(int sig) {
const int errno_saved = errno;
if (g_driver != NULL) g_driver->Interrupt();
for (int i = 0; i < kNumWorkers; ++i) {
if (g_workers[i]) g_workers[i]->Interrupt();
}
errno = errno_saved;
}
static void register_sighandler() {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sighandler;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
}
static void LogStatus(int status, const char* label) {
if (WIFEXITED(status)) {
gpr_log(GPR_INFO, "%s: subprocess exited with status %d", label,
@ -63,8 +90,7 @@ static void LogStatus(int status, const char* label) {
}
int main(int argc, char** argv) {
typedef std::unique_ptr<SubProcess> SubProcessPtr;
std::vector<SubProcessPtr> jobs;
register_sighandler();
std::string my_bin = argv[0];
std::string bin_dir = my_bin.substr(0, my_bin.rfind('/'));
@ -72,11 +98,11 @@ int main(int argc, char** argv) {
std::ostringstream env;
bool first = true;
for (int i = 0; i < 2; i++) {
auto port = grpc_pick_unused_port_or_die();
for (int i = 0; i < kNumWorkers; i++) {
const auto port = grpc_pick_unused_port_or_die();
std::vector<std::string> args = {bin_dir + "/qps_worker", "-driver_port",
as_string(port)};
jobs.emplace_back(new SubProcess(args));
g_workers[i] = new SubProcess(args);
if (!first) env << ",";
env << "localhost:" << port;
first = false;
@ -87,18 +113,27 @@ int main(int argc, char** argv) {
for (int i = 1; i < argc; i++) {
args.push_back(argv[i]);
}
int status = SubProcess(args).Join();
if (status != 0) {
LogStatus(status, "driver");
}
for (auto it = jobs.begin(); it != jobs.end(); ++it) {
(*it)->Interrupt();
g_driver = new SubProcess(args);
const int driver_join_status = g_driver->Join();
if (driver_join_status != 0) {
LogStatus(driver_join_status, "driver");
}
for (auto it = jobs.begin(); it != jobs.end(); ++it) {
status = (*it)->Join();
if (status != 0) {
LogStatus(status, "worker");
for (int i = 0; i < kNumWorkers; ++i) {
if (g_workers[i]) g_workers[i]->Interrupt();
}
for (int i = 0; i < kNumWorkers; ++i) {
if (g_workers[i]) {
const int worker_status = g_workers[i]->Join();
if (worker_status != 0) {
LogStatus(worker_status, "worker");
}
}
}
delete g_driver;
g_driver = NULL;
for (int i = 0; i < kNumWorkers; ++i) delete g_workers[i];
GPR_ASSERT(driver_join_status == 0);
}

@ -35,37 +35,11 @@
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include <grpc/support/log.h>
#include "test/cpp/util/test_credentials_provider.h"
#include "test/core/end2end/data/ssl_test_data.h"
namespace grpc {
namespace {
const char kProdTlsCredentialsType[] = "prod_ssl";
class SslCredentialProvider : public testing::CredentialTypeProvider {
public:
std::shared_ptr<ChannelCredentials> GetChannelCredentials(
grpc::ChannelArguments* args) override {
return SslCredentials(SslCredentialsOptions());
}
std::shared_ptr<ServerCredentials> GetServerCredentials() override {
return nullptr;
}
};
gpr_once g_once_init_add_prod_ssl_provider = GPR_ONCE_INIT;
// Register ssl with non-test roots type to the credentials provider.
void AddProdSslType() {
testing::GetCredentialsProvider()->AddSecureType(
kProdTlsCredentialsType, std::unique_ptr<testing::CredentialTypeProvider>(
new SslCredentialProvider));
}
} // namespace
// When ssl is enabled, if server is empty, override_hostname is used to
// create channel. Otherwise, connect to server and override hostname if
// override_hostname is provided.
@ -87,22 +61,16 @@ std::shared_ptr<Channel> CreateTestChannel(
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args) {
ChannelArguments channel_args(args);
std::shared_ptr<ChannelCredentials> channel_creds;
if (enable_ssl) {
if (use_prod_roots) {
gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType);
channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
kProdTlsCredentialsType, &channel_args);
if (!server.empty() && !override_hostname.empty()) {
channel_args.SetSslTargetNameOverride(override_hostname);
}
} else {
// override_hostname is discarded as the provider handles it.
channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials(
testing::kTlsCredentialsType, &channel_args);
}
GPR_ASSERT(channel_creds != nullptr);
const char* roots_certs = use_prod_roots ? "" : test_root_cert;
SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
std::shared_ptr<ChannelCredentials> channel_creds =
SslCredentials(ssl_opts);
if (!server.empty() && !override_hostname.empty()) {
channel_args.SetSslTargetNameOverride(override_hostname);
}
const grpc::string& connect_to =
server.empty() ? override_hostname : server;
if (creds.get()) {
@ -135,18 +103,4 @@ std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false);
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds) {
ChannelArguments channel_args;
std::shared_ptr<ChannelCredentials> channel_creds =
testing::GetCredentialsProvider()->GetChannelCredentials(credential_type,
&channel_args);
GPR_ASSERT(channel_creds != nullptr);
if (creds.get()) {
channel_creds = CompositeChannelCredentials(channel_creds, creds);
}
return CreateCustomChannel(server, channel_creds, channel_args);
}
} // namespace grpc

@ -59,10 +59,6 @@ std::shared_ptr<Channel> CreateTestChannel(
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds);
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H

@ -43,9 +43,25 @@
#include "test/core/end2end/data/ssl_test_data.h"
namespace grpc {
namespace testing {
namespace {
using grpc::testing::CredentialTypeProvider;
// Provide test credentials. Thread-safe.
class CredentialsProvider {
public:
virtual ~CredentialsProvider() {}
virtual void AddSecureType(
const grpc::string& type,
std::unique_ptr<CredentialTypeProvider> type_provider) = 0;
virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
const grpc::string& type, ChannelArguments* args) = 0;
virtual std::shared_ptr<ServerCredentials> GetServerCredentials(
const grpc::string& type) = 0;
virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0;
};
class DefaultCredentialsProvider : public CredentialsProvider {
public:
~DefaultCredentialsProvider() override {}
@ -129,21 +145,37 @@ class DefaultCredentialsProvider : public CredentialsProvider {
added_secure_type_providers_;
};
gpr_once g_once_init_provider = GPR_ONCE_INIT;
CredentialsProvider* g_provider = nullptr;
} // namespace
void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; }
CredentialsProvider* GetCredentialsProvider() {
if (g_provider == nullptr) {
g_provider = new DefaultCredentialsProvider;
}
CredentialsProvider* GetProvider() {
gpr_once_init(&g_once_init_provider, &CreateDefaultProvider);
return g_provider;
}
void SetCredentialsProvider(CredentialsProvider* provider) {
// For now, forbids overriding provider.
GPR_ASSERT(g_provider == nullptr);
g_provider = provider;
} // namespace
namespace testing {
void AddSecureType(const grpc::string& type,
std::unique_ptr<CredentialTypeProvider> type_provider) {
GetProvider()->AddSecureType(type, std::move(type_provider));
}
std::shared_ptr<ChannelCredentials> GetChannelCredentials(
const grpc::string& type, ChannelArguments* args) {
return GetProvider()->GetChannelCredentials(type, args);
}
std::shared_ptr<ServerCredentials> GetServerCredentials(
const grpc::string& type) {
return GetProvider()->GetServerCredentials(type);
}
std::vector<grpc::string> GetSecureCredentialsTypeList() {
return GetProvider()->GetSecureCredentialsTypeList();
}
} // namespace testing

@ -59,39 +59,23 @@ class CredentialTypeProvider {
virtual std::shared_ptr<ServerCredentials> GetServerCredentials() = 0;
};
// Provide test credentials. Thread-safe.
class CredentialsProvider {
public:
virtual ~CredentialsProvider() {}
// Add a secure type in addition to the defaults. The default provider has
// (kInsecureCredentialsType, kTlsCredentialsType).
virtual void AddSecureType(
const grpc::string& type,
std::unique_ptr<CredentialTypeProvider> type_provider) = 0;
// Provide channel credentials according to the given type. Alter the channel
// arguments if needed. Return nullptr if type is not registered.
virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
const grpc::string& type, ChannelArguments* args) = 0;
// Provide server credentials according to the given type.
// Return nullptr if type is not registered.
virtual std::shared_ptr<ServerCredentials> GetServerCredentials(
const grpc::string& type) = 0;
// Provide a list of secure credentials type.
virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0;
};
// Get the current provider. Create a default one if not set.
// Not thread-safe.
CredentialsProvider* GetCredentialsProvider();
// Set the global provider. Takes ownership. The previous set provider will be
// destroyed.
// Not thread-safe.
void SetCredentialsProvider(CredentialsProvider* provider);
// Add a secure type in addition to the defaults above
// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the
// functions below.
void AddSecureType(const grpc::string& type,
std::unique_ptr<CredentialTypeProvider> type_provider);
// Provide channel credentials according to the given type. Alter the channel
// arguments if needed.
std::shared_ptr<ChannelCredentials> GetChannelCredentials(
const grpc::string& type, ChannelArguments* args);
// Provide server credentials according to the given type.
std::shared_ptr<ServerCredentials> GetServerCredentials(
const grpc::string& type);
// Provide a list of secure credentials type.
std::vector<grpc::string> GetSecureCredentialsTypeList();
} // namespace testing
} // namespace grpc

@ -11,6 +11,8 @@ gce: Scripts to help setup testing infrastructure on GCE.
gcp: Helper scripts for interacting with various services on GCP (like Google
container engine, BigQuery etc)
internal_ci: Support for running tests on an internal CI platform.
jenkins: Support for running tests on Jenkins.
run_tests: Scripts to run gRPC tests in parallel.

@ -0,0 +1,6 @@
#Internal continuous integration
gRPC's externally facing testing is managed by Jenkins CI (see `tools/jenkins`
directory). Nevertheless, some of the tests are better suited for being run
on internal infrastructure and using an internal CI system. Configuration for
such tests is under this directory.

@ -0,0 +1,34 @@
#!/bin/bash
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Config file for the internal CI (in protobuf text format)
# Location of the continuous shell script in repository.
build_file: "grpc/tools/internal_ci/linux/run_tests.sh"

@ -0,0 +1,45 @@
#!/bin/bash
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -ex
# change to grpc repo root
cd $(dirname $0)/../../..
# TODO(jtattermusch): get rid of the system inspection eventually
nproc || true
lsb_release -dc || true
gcc --version || true
clang --version || true
docker --version || true
git submodule update --init
tools/run_tests/run_tests.py -l c --build_only

@ -1 +1,6 @@
# Jenkins CI scripts
Scripts invoked by Jenkins (our CI platform) to run gRPC test suites.
We run a comprehensive set of tests (unit, integration, interop,
performance, portability..) on each pull request and also periodically on
`master` and release branches.

@ -5447,7 +5447,6 @@
"gpr",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_test_util"
],
"headers": [

@ -154,9 +154,6 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
<Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>

Loading…
Cancel
Save